bool AP_Win32App::_pasteFormatFromClipboard(PD_DocumentRange * pDocRange, const char * szFormat, const char * szType, bool bWide) { HANDLE hData; bool bSuccess = false; if (!(hData = m_pClipboard->getHandleInFormat(szFormat))) return bSuccess; // It's a bitmap if (g_ascii_strcasecmp(szFormat, AP_CLIPBOARD_BMP)==0) { HBITMAP hBitmap; PBITMAPINFO bi; HWND hWnd; HDC hdc; IE_ImpGraphic* pIEG = NULL; FG_Graphic* pFG = NULL; UT_Error errorCode; UT_ByteBuf byteBuf; IEGraphicFileType iegft = IEGFT_BMP; XAP_Frame* pFrame; AP_FrameData* pFrameData; FL_DocLayout* pDocLy; FV_View* pView; UT_ByteBuf* bBufBMP = new UT_ByteBuf; hBitmap = (HBITMAP)hData; hWnd = GetDesktopWindow(); hdc = GetDC(hWnd); // Create a BMP file from a BITMAP bi = CreateBitmapInfoStruct(hBitmap); CreateBMP(hWnd, *bBufBMP, bi, hBitmap,hdc); // Since we are providing the file type, there is not need to pass the bytebuff filled up errorCode = IE_ImpGraphic::constructImporter(*bBufBMP, iegft, &pIEG); if(errorCode != UT_OK) return false; errorCode = pIEG->importGraphic(bBufBMP, &pFG); if(errorCode != UT_OK || !pFG) { DELETEP(bBufBMP); DELETEP(pIEG); return false; } // sunk in importGraphic bBufBMP = NULL; // Insert graphic in the view pFrame = getLastFocussedFrame(); pFrameData = (AP_FrameData*) pFrame->getFrameData(); pDocLy = pFrameData->m_pDocLayout; pView = pDocLy->getView(); errorCode = pView->cmdInsertGraphic(pFG); DELETEP(pIEG); //DELETEP(pFG); bSuccess = true; } else { unsigned char * pData = static_cast<unsigned char *>(GlobalLock(hData)); UT_DEBUGMSG(("Paste: [fmt %s %s][hdata 0x%08lx][pData 0x%08lx]\n", szFormat, szType, hData, pData)); UT_uint32 iSize = GlobalSize(hData); UT_uint32 iStrLen = bWide ? wcslen(reinterpret_cast<const wchar_t *>(pData)) * 2 : strlen(reinterpret_cast<const char *>(pData)); UT_uint32 iLen = UT_MIN(iSize,iStrLen); IE_Imp * pImp = 0; IE_Imp::constructImporter(pDocRange->m_pDoc, IE_Imp::fileTypeForSuffix(szType), &pImp, 0); if (pImp) { const char * szEncoding = 0; if (bWide) szEncoding = XAP_EncodingManager::get_instance()->getUCS2LEName(); else ; // TODO Get code page using CF_LOCALE pImp->pasteFromBuffer(pDocRange,pData,iLen,szEncoding); delete pImp; } GlobalUnlock(hData); bSuccess = true; } return bSuccess; }
/*! paste from the system clipboard using the best-for-us format that is present. try to get the content in the order listed. \todo currently i have this set so that a ^v or Menu[Edit/Paste] will use the CLIPBOARD property and a MiddleMouseClick will use the PRIMARY property -- this seems to be the "X11 way" (sigh). consider having a preferences switch to allow ^v and Menu[Edit/Paste] to use the most recent property... this might be a nice way of unifying things -- or it might not -- this is probably an area for investigation or some usability testing. */ void AP_UnixApp::pasteFromClipboard(PD_DocumentRange * pDocRange, bool bUseClipboard, bool bHonorFormatting) { XAP_UnixClipboard::T_AllowGet tFrom = ((bUseClipboard) ? XAP_UnixClipboard::TAG_ClipboardOnly : XAP_UnixClipboard::TAG_PrimaryOnly); const char * szFormatFound = NULL; const unsigned char * pData = NULL; UT_uint32 iLen = 0; bool bFoundOne = false; bool bSuccess = false; if ( bHonorFormatting ) bFoundOne = m_pClipboard->getSupportedData(tFrom,reinterpret_cast<const void **>(&pData),&iLen,&szFormatFound); else bFoundOne = m_pClipboard->getTextData(tFrom,reinterpret_cast<const void **>(&pData),&iLen, &szFormatFound); #ifdef DUMP_CLIPBOARD_PASTE if (bFoundOne) { std::ofstream oss("/tmp/clips"); oss.write( (const char*)pData, iLen ); oss.close(); } #endif if (!bFoundOne) { UT_DEBUGMSG(("PasteFromClipboard: did not find anything to paste.\n")); return; } if (AP_UnixClipboard::isDynamicTag (szFormatFound)) { UT_DEBUGMSG(("Dynamic Format Found = %s \n",szFormatFound)); } if (AP_UnixClipboard::isRichTextTag(szFormatFound)) { IE_Imp_RTF * pImpRTF = new IE_Imp_RTF(pDocRange->m_pDoc); bSuccess = pImpRTF->pasteFromBuffer(pDocRange,pData,iLen); DELETEP(pImpRTF); } else if (AP_UnixClipboard::isHTMLTag (szFormatFound)) { IE_Imp_Text_Sniffer SniffBuf; const char * szRes = SniffBuf.recognizeContentsType(reinterpret_cast<const char *>(pData),iLen); if(szRes && strcmp(szRes,"none") != 0) { UT_uint32 iread,iwritten = 0; const char * szutf8= static_cast<const char *>(UT_convert(reinterpret_cast<const char *>(pData),iLen,szRes,"UTF-8",&iread,&iwritten)); IE_Imp_XHTML * pImpHTML = new IE_Imp_XHTML(pDocRange->m_pDoc); bSuccess = pImpHTML->pasteFromBuffer(pDocRange,reinterpret_cast<const unsigned char *>(szutf8),iwritten,"UTF-8"); g_free(const_cast<char *>(szutf8)); DELETEP(pImpHTML); } else { IE_Imp_XHTML * pImpHTML = new IE_Imp_XHTML(pDocRange->m_pDoc); bSuccess = pImpHTML->pasteFromBuffer(pDocRange,reinterpret_cast<const unsigned char *>(pData),iLen); DELETEP(pImpHTML); } } else if (AP_UnixClipboard::isDynamicTag (szFormatFound)) { UT_DEBUGMSG(("Format Found = %s \n",szFormatFound)); IE_Imp * pImp = NULL; IEFileType ieft = IE_Imp::fileTypeForMimetype(szFormatFound); UT_DEBUGMSG(("found file type %d\n",ieft)); IE_Imp::constructImporter(pDocRange->m_pDoc,ieft,&pImp); if(pImp == NULL) goto retry_text; bSuccess = pImp->pasteFromBuffer(pDocRange,pData,iLen); DELETEP(pImp); } else if (AP_UnixClipboard::isImageTag(szFormatFound)) { UT_DEBUGMSG(("Format Found = %s \n",szFormatFound)); if(strncmp(szFormatFound,"application",11) == 0) // embedded object { IE_Imp * pImp = NULL; IEGraphicFileType iegft = IE_Imp::fileTypeForMimetype(szFormatFound); IE_Imp::constructImporter(pDocRange->m_pDoc,iegft,&pImp); if(pImp == NULL) { goto retry_text; } /*bool b = */ pImp->pasteFromBuffer(pDocRange,pData,iLen); DELETEP(pImp); return; } FG_Graphic * pFG = NULL; IEGraphicFileType iegft = IEGFT_Unknown; UT_Error error = UT_OK; UT_ByteBuf bytes( iLen ); bytes.append (pData, iLen); error = IE_ImpGraphic::loadGraphic(bytes, iegft, &pFG); if(!pFG || error) { UT_DEBUGMSG(("DOM: could not import graphic (%d)\n", error)); goto retry_text; } // at this point, 'bytes' is owned by pFG FV_View * pView = static_cast<FV_View*>(getLastFocussedFrame ()->getCurrentView()); error = pView->cmdInsertGraphic(pFG); DELETEP(pFG); if (!error) bSuccess = true; } else // ( AP_UnixClipboard::isTextTag(szFormatFound) ) { IE_Imp_Text * pImpText = new IE_Imp_Text(pDocRange->m_pDoc,"UTF-8"); bSuccess = pImpText->pasteFromBuffer(pDocRange,pData,iLen); DELETEP(pImpText); } retry_text: // we failed to paste *anything.* try plaintext as a last-ditch effort if(!bSuccess && m_pClipboard->getTextData(tFrom,reinterpret_cast<const void **>(&pData),&iLen, &szFormatFound)) { UT_DEBUGMSG(("DOM: pasting text as an absolute fallback (bug 7666)\n")); IE_Imp_Text * pImpText = new IE_Imp_Text(pDocRange->m_pDoc,"UTF-8"); bSuccess = pImpText->pasteFromBuffer(pDocRange,pData,iLen); DELETEP(pImpText); } }
// // AbiPaint editImage // ------------------ // This is the function that we actually call to invoke the image editor. // // parameters are: // AV_View* v // EV_EditMethodCallData *d // static DECLARE_ABI_PLUGIN_METHOD(editImage) { UT_UNUSED(v); // Get the current view that the user is in. XAP_Frame *pFrame = XAP_App::getApp()->getLastFocussedFrame(); FV_View* pView = static_cast<FV_View*>(pFrame->getCurrentView()); // // get values from preference (initial plugin execution should have set sensible defaults) // UT_String imageApp; // holds MAXPATH\appName <space> MAXPATH\imagefilename bool bLeaveImageAsPNG; // read stuff from the preference value if (!prefsScheme->getValue(ABIPAINT_PREF_KEY_szProgramName, imageApp)) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); getDefaultApp(imageApp, bLeaveImageAsPNG); } // now that we have program name, try to get other flag (allows overriding default value) // Note: we allow overriding, otherwise if we don't adhere to user's setting // then the use BMP or not menu should be greyed to note it has no effect prefsScheme->getValueBool(ABIPAINT_PREF_KEY_bLeaveImageAsPNG, &bLeaveImageAsPNG); // // generate a temp file name... // char *szTempFileName = NULL; GError *err = NULL; gint fp = g_file_open_tmp ("XXXXXX", &szTempFileName, &err); if (err) { g_warning ("%s", err->message); g_error_free (err); err = NULL; return FALSE; } close(fp); UT_String szTmpPng = szTempFileName; szTmpPng += ".png"; UT_String szTmp = szTmpPng; // default: our temp file is the created png file PT_DocPosition pos = pView->saveSelectedImage((const char *)szTmpPng.c_str()); if(pos == 0) { remove(szTempFileName); g_free (szTempFileName); szTempFileName = NULL; pFrame->showMessageBox("You must select an Image before editing it", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); return false; } #ifdef ENABLE_BMP // // Convert png into bmp for best compatibility with Windows programs // NOTE: probably looses detail/information though!!! so if possible use PNG // if (!bLeaveImageAsPNG) { szTmp = szTempFileName; szTmp += ".bmp"; // our temp file is a bmp file if (convertPNG2BMP(szTmpPng.c_str(), szTmp.c_str())) { pFrame->showMessageBox("Unable to convert PNG image data to BMP for external program use!", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); remove(szTempFileName); g_free (szTempFileName); szTempFileName = NULL; remove(szTmpPng.c_str()); return false; } // remove(szTmpPng.c_str()); } #endif // remove the temp file (that lacks proper extension) remove(szTempFileName); g_free (szTempFileName); szTempFileName = NULL; // // Get the initial file status. // struct stat myFileStat; int ok = stat(szTmp.c_str(),&myFileStat); if(ok < 0) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); remove(szTmpPng.c_str()); remove(szTmp.c_str()); // should silently fail if exporting as PNG file return false; } time_t mod_time = myFileStat.st_mtime; // // Fire up the image editor... // ProcessInfo procInfo; if (!createChildProcess(imageApp.c_str(), szTmp.c_str(), &procInfo)) { UT_String msg = "Unable to run program: "; msg += imageApp + " " + szTmp; pFrame->showMessageBox(msg.c_str(), XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); // failed to spawn stuff, so do some cleanup and return failure remove(szTmpPng.c_str()); remove(szTmp.c_str()); // should silently fail if exporting as PNG file return false; } lockGUI(d); while (isProcessStillAlive(procInfo)) { UT_usleep(10000); // wait 10 milliseconds pFrame->nullUpdate(); ok = stat(szTmp.c_str(),&myFileStat); if(ok == 0) { if(myFileStat.st_mtime != mod_time) { // wait for changes to settle (program done writing changes) // we use both modified time & file size, but really we // could just use file size as mod time doesn't appear to change for small images mod_time = myFileStat.st_mtime; off_t size = myFileStat.st_size; UT_usleep(100000); // wait 100 milliseconds (so program may have time to write something) ok = stat(szTmp.c_str(),&myFileStat); while((mod_time != myFileStat.st_mtime) || !size || (size > 0 && size != myFileStat.st_size)) { mod_time = myFileStat.st_mtime; size = myFileStat.st_size; ok = stat(szTmp.c_str(),&myFileStat); UT_usleep(500000); // wait a while, let program write its data // just make sure the program is still running, otherwise we could get stuck in a loop if (!isProcessStillAlive(procInfo)) { pFrame->showMessageBox("External image editor appears to have been terminated unexpectedly.", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); //procInfo.hProcess = 0; goto Cleanup; } } mod_time = myFileStat.st_mtime; UT_usleep(100000); // wait a while just to make sure program is done with file // // OK replace the current image with this. // IEGraphicFileType iegft = IEGFT_Unknown; FG_Graphic* pFG; UT_Error errorCode; #ifdef ENABLE_BMP // // Convert bmp back to png (as we can not assume AbiWord has builtin BMP support [as its now an optional plugin]) // NOTE: probably looses detail/information though!!! so if possible use only PNG // if (!bLeaveImageAsPNG) { if (convertBMP2PNG(szTmp.c_str(), szTmpPng.c_str())) { pFrame->showMessageBox("Unable to convert BMP image data back to PNG for AbiWord to import!", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); goto Cleanup; } } #endif errorCode = IE_ImpGraphic::loadGraphic(szTmpPng.c_str(), iegft, &pFG); if(errorCode) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); pFrame->showMessageBox("Error making pFG. Could not put image back into Abiword", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); goto Cleanup; } unlockGUI(d); pView->cmdUnselectSelection(); pView->setPoint(pos); pView->extSelHorizontal(true, 1); // move point forward one errorCode = pView->cmdInsertGraphic(pFG); if (errorCode) { pFrame->showMessageBox("Could not put image back into Abiword", XAP_Dialog_MessageBox::b_O,XAP_Dialog_MessageBox::a_OK); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); DELETEP(pFG); goto Cleanup; } DELETEP(pFG); // // Reselect the image // pView->setPoint(pos); pView->extSelHorizontal(true, 1); // move point forward one lockGUI(d); } } } // // Normal exit, delete the tempfile and return success // remove(szTmpPng.c_str()); remove(szTmp.c_str()); // should silently fail if exporting as PNG file unlockGUI(d); return true; // // Something went wrong. // Cleanup: remove(szTmpPng.c_str()); remove(szTmp.c_str()); // should silently fail if exporting as PNG file unlockGUI(d); // // Kill the image editor. // endProcess(procInfo); return false; }