/*! this method goes with setSelectionStatus(). we are called by the clipboard (thru the callback chain) in response to another application stealing the X Selection. we need to notify the view so that it can clear the screen as is the custom on X -- only one selection at any time. we have to watch out here because when we call up to clear the selection, the view will notify the view-listeners of the change, which may cause setSelectionStatus() to get called and thus update the clipboard -- this could recurse a while.... */ void AP_UnixApp::clearSelection(void) { if (m_bSelectionInFlux) return; m_bSelectionInFlux = true; if (m_pViewSelection && m_pFrameSelection && m_bHasSelection) { FV_View *pView = static_cast<FV_View *>(m_pViewSelection); pView->cmdUnselectSelection(); m_bHasSelection = false; } m_bSelectionInFlux = false; }
// // 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; }