/*! * Method to handle expose events with a background repainter. Events that * Pass through here are rapidly delt with by either expanding an * already existing expose rectangle to cover the expose rectangle of * the current event or if there is no pending expose rectangle, because * the background repainter has cleared it, set a new expose rectangle. \param UT_Rect *rClip the rectangle of the expose event. */ void GR_Graphics::doRepaint( UT_Rect * rClip) { // // Look if we have a pending expose left over. // xxx_UT_DEBUGMSG(("SEVIOR: Starting doRepaint \n")); while(isSpawnedRedraw()) { UT_usleep(100); } // // Stop the repainter // setDontRedraw(true); // // Get a lock on the expose rectangle // while(isExposedAreaAccessed()) { UT_usleep(10); // 10 microseconds } setExposedAreaAccessed(true); if(isExposePending() || doMerge()) { // // If so merge in the current expose area // xxx_UT_DEBUGMSG(("Doing a union in expose handler\n")); unionPendingRect( rClip); setRecentRect(rClip); setDoMerge(false); } else { // // Otherwise Load the current expose area into the redraw area. // xxx_UT_DEBUGMSG(("Setting Exposed Area in expose handler \n")); setPendingRect(rClip->left,rClip->top,rClip->width,rClip->height); setRecentRect(rClip); } // // Release expose rectangle lock // setExposedAreaAccessed(false); // // Tell the repainter there is something to repaint. // setExposePending(true); // // Allow the repainter to paint // setDontRedraw(false); xxx_UT_DEBUGMSG(("SEVIOR: Finished doRepaint \n")); // // OK this event is handled. // }
AP_UnixLeftRuler::~AP_UnixLeftRuler(void) { GtkWidget * toplevel = static_cast<XAP_UnixFrameImpl *>(m_pFrame->getFrameImpl())->getTopLevelWindow(); if (toplevel && g_signal_handler_is_connected(G_OBJECT(toplevel), m_iBackgroundRedrawID)) { g_signal_handler_disconnect(G_OBJECT(toplevel),m_iBackgroundRedrawID); } while(m_pG && m_pG->isSpawnedRedraw()) { UT_usleep(100); } DELETEP(m_pG); }
/*! * Background abi repaint function. \param XAP_UnixFrame * p pointer to the Frame that initiated this background repainter. */ gint AP_UnixLeftRuler::_fe::abi_expose_repaint( gpointer p) { // // Grab our pointer so we can do useful stuff. // UT_Rect localCopy; AP_UnixLeftRuler * pR = static_cast<AP_UnixLeftRuler *>(p); GR_Graphics * pG = pR->getGraphics(); if(pG == NULL || pG->isDontRedraw()) { // // Come back later // return TRUE; } FV_View * pView = static_cast<FV_View *>(pR->m_pFrame->getCurrentView()); if(pView && pView->getPoint()==0) { // // Come back later // return TRUE; } pG->setSpawnedRedraw(true); if(pG->isExposePending()) { while(pG->isExposedAreaAccessed()) { UT_usleep(10); // 10 microseconds } pG->setExposedAreaAccessed(true); localCopy.set(pG->getPendingRect()->left,pG->getPendingRect()->top, pG->getPendingRect()->width,pG->getPendingRect()->height); // // Clear out this set of expose info // pG->setExposePending(false); pG->setExposedAreaAccessed(false); xxx_UT_DEBUGMSG(("Painting area on Left ruler: left=%d, top=%d, width=%d, height=%d\n", localCopy.left, localCopy.top, localCopy.width, localCopy.height)); xxx_UT_DEBUGMSG(("SEVIOR: Repaint now \n")); pR->draw(&localCopy); } // // OK we've finshed. Wait for the next signal // pG->setSpawnedRedraw(false); return TRUE; }
/*! This function actually handles signals. The most commonly recieved one is SIGSEGV, the segfault signal. We want to clean up, save the user's files to backup locations (currently <filename>.saved) and then call abort, so we still get a core dump that we can debug. \param sig_num the integer representing which signal we recieved */ void AP_UnixApp::catchSignals(int /*sig_num*/) { // Reset the signal handler // (not that it matters - this is mostly for race conditions) signal(SIGSEGV, signalWrapper); s_signal_count = s_signal_count + 1; if(s_signal_count > 1) { UT_DEBUGMSG(("Crash during filesave - no file saved\n")); fflush(stdout); abort(); } UT_DEBUGMSG(("Oh no - we just crashed!\n")); // // fixme: Enable this to help debug the bonobo component. After a crash the // the program hangs here and you can connect to it from gdb and backtrace to // the crash point #ifdef LOGFILE fprintf(logfile,"abicrashed \n"); fclose(logfile); #endif #if 0 while(1) { UT_usleep(10000); } #endif UT_sint32 i = 0; IEFileType abiType = IE_Imp::fileTypeForSuffix(".abw"); for(;i<m_vecFrames.getItemCount();i++) { AP_UnixFrame * curFrame = const_cast<AP_UnixFrame*>(static_cast<const AP_UnixFrame*>(m_vecFrames[i])); UT_continue_if_fail(curFrame); if (NULL == curFrame->getFilename()) curFrame->backup(".abw.saved",abiType); else curFrame->backup(".saved",abiType); } fflush(stdout); // Abort and dump core abort(); }
// // 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; }