From 2878fa95ab4e30046472a8c1f7576aa6a39f8ba5 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Wed, 22 Apr 2020 15:59:22 +0200 Subject: Add optional argument to Fl_Printer::begin_job() to inform caller when an error occurs. This solves an issue raised in fltk.general : Fl_Printer errors - how can I interpret them? https://www.fltk.org/newsgroups.php?s38419+gfltk.general+v38427 --- CHANGES.txt | 2 ++ FL/Fl_Paged_Device.H | 8 ++++--- FL/Fl_PostScript.H | 2 +- FL/Fl_Printer.H | 2 +- src/Fl_Paged_Device.cxx | 6 +++-- src/Fl_Printer.cxx | 16 ++----------- src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm | 13 ++++++++--- src/drivers/Posix/Fl_Posix_Printer_Driver.cxx | 29 ++++++++++++++++++------ src/drivers/PostScript/Fl_PostScript.cxx | 2 +- src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx | 30 +++++++++++++++++-------- test/device.cxx | 7 +++--- 11 files changed, 73 insertions(+), 44 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 2bff747dc..29048f478 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -119,6 +119,8 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2020 Other Improvements - (add new items here) + - Add optional argument to Fl_Printer::begin_job() to receive + a string describing the error when an error occurs. - Fix Windows-specific bug when the program tries to enlarge a maximized window, that would freeze the window (git issue #65). - Improve X11 16-bit coordinate clipping for text (STR 2798). This diff --git a/FL/Fl_Paged_Device.H b/FL/Fl_Paged_Device.H index db6fab3ce..154fb5d7a 100644 --- a/FL/Fl_Paged_Device.H +++ b/FL/Fl_Paged_Device.H @@ -103,10 +103,12 @@ public: static const page_format page_formats[NO_PAGE_FORMATS]; /** \brief The destructor */ virtual ~Fl_Paged_Device() {}; - virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); - /** Synonym of begin_job(int pagecount, int *frompage, int *topage). + virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL); + /** Synonym of begin_job(int pagecount, int *frompage, int *topage, char **perr_message). For API compatibility with FLTK 1.3.x */ - int start_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL) {return begin_job(pagecount, frompage, topage);} + int start_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL) { + return begin_job(pagecount, frompage, topage, perr_message); + } virtual int begin_page(void); /** Synonym of begin_page(). For API compatibility with FLTK 1.3.x */ diff --git a/FL/Fl_PostScript.H b/FL/Fl_PostScript.H index 470943268..6d26490dc 100644 --- a/FL/Fl_PostScript.H +++ b/FL/Fl_PostScript.H @@ -258,7 +258,7 @@ public: */ ~Fl_PostScript_File_Device(); /** Don't use with this class. */ - int begin_job(int pagecount, int* from, int* to); + int begin_job(int pagecount, int* from, int* to, char **perr_message); /** @brief Begins the session where all graphics requests will go to a local PostScript file. * diff --git a/FL/Fl_Printer.H b/FL/Fl_Printer.H index 977f75762..43b05c1be 100644 --- a/FL/Fl_Printer.H +++ b/FL/Fl_Printer.H @@ -93,7 +93,7 @@ private: public: /** The constructor */ Fl_Printer(void); - int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); + int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL); int begin_page(void); int printable_rect(int *w, int *h); void margins(int *left, int *top, int *right, int *bottom); diff --git a/src/Fl_Paged_Device.cxx b/src/Fl_Paged_Device.cxx index cc61f4cc0..3d96d797f 100644 --- a/src/Fl_Paged_Device.cxx +++ b/src/Fl_Paged_Device.cxx @@ -31,9 +31,11 @@ \param[in] pagecount the total number of pages of the job (or 0 if you don't know the number of pages) \param[out] frompage if non-null, *frompage is set to the first page the user wants printed \param[out] topage if non-null, *topage is set to the last page the user wants printed - \return 0 if OK, non-zero if any error + \param[out] perr_message if non-null and if the returned value is > 1, *perr_message is set to a string + describing the error. That string can be delete[]'d after use. + \return 0 if OK, 1 if user cancelled the job, > 1 if any error. */ -int Fl_Paged_Device::begin_job(int pagecount, int *frompage, int *topage) {return 1;} +int Fl_Paged_Device::begin_job(int pagecount, int *frompage, int *topage, char **perr_message) {return 1;} /** \brief Begins a new printed page diff --git a/src/Fl_Printer.cxx b/src/Fl_Printer.cxx index 390f1e6e1..3f8e50355 100644 --- a/src/Fl_Printer.cxx +++ b/src/Fl_Printer.cxx @@ -132,21 +132,9 @@ Fl_Printer::Fl_Printer(void) { driver(printer->driver()); } -/** - Begins a print job. - Opens a platform-specific dialog window allowing the user to set several options including - the desired printer and the page orientation. Optionally, the user can also select a range of pages to be - printed. This range is returned to the caller that is in charge of sending only these pages - for printing. - - \param[in] pagecount the total number of pages of the job (or 0 if you don't know the number of pages) - \param[out] frompage if non-null, *frompage is set to the first page the user wants printed - \param[out] topage if non-null, *topage is set to the last page the user wants printed - \return 0 if OK, non-zero if any error occurred or if the user cancelled the print request. - */ -int Fl_Printer::begin_job(int pagecount, int *frompage, int *topage) +int Fl_Printer::begin_job(int pagecount, int *frompage, int *topage, char **perr_message) { - return printer->begin_job(pagecount, frompage, topage); + return printer->begin_job(pagecount, frompage, topage, perr_message); } int Fl_Printer::begin_page(void) diff --git a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm index 4c6e794f3..4fa639d6a 100644 --- a/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm +++ b/src/drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm @@ -57,7 +57,7 @@ private: PMPageFormat pageFormat; PMPrintSettings printSettings; Fl_Cocoa_Printer_Driver(void); - int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); + int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL); int begin_page (void); int printable_rect(int *w, int *h); void margins(int *left, int *top, int *right, int *bottom); @@ -101,7 +101,7 @@ Fl_Cocoa_Printer_Driver::~Fl_Cocoa_Printer_Driver(void) { } @end -int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage) +int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message) //printing using a Quartz graphics context //returns 0 iff OK { @@ -194,7 +194,14 @@ int Fl_Cocoa_Printer_Driver::begin_job (int pagecount, int *frompage, int *topag #endif //__LP64__ } - if (status != noErr) return 1; + if (status != noErr) { + if (perr_message) { + NSError *nserr = [NSError errorWithDomain:NSCocoaErrorDomain code:status userInfo:nil]; + NSString *s = [nserr localizedDescription]; + if (s) *perr_message = strdup([s UTF8String]); + } + return 2; + } y_offset = x_offset = 0; return 0; } diff --git a/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx index 56849ad39..bf206070e 100644 --- a/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx +++ b/src/drivers/Posix/Fl_Posix_Printer_Driver.cxx @@ -28,7 +28,7 @@ /** Support for printing on the Unix/Linux platform */ class Fl_Posix_Printer_Driver : public Fl_PostScript_File_Device { - virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); + virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message=NULL); }; #if HAVE_DLSYM && HAVE_DLFCN_H @@ -57,7 +57,7 @@ public: GtkPrintJob *pjob; // data shared between begin_job() and end_job() char tmpfilename[50]; // name of temporary PostScript file containing to-be-printed data - virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); + virtual int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message=NULL); virtual void end_job(); static bool probe_for_GTK(); static void *ptr_gtk; // points to the GTK dynamic lib or NULL @@ -103,7 +103,7 @@ bool Fl_GTK_Printer_Driver::probe_for_GTK() { } -int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpage) { +int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpage, char **perr_message) { enum Fl_Paged_Device::Page_Format format = Fl_Paged_Device::A4; enum Fl_Paged_Device::Page_Layout layout = Fl_Paged_Device::PORTRAIT ; @@ -157,6 +157,12 @@ int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpag if (output) { Fl_PostScript_File_Device::begin_job(output, 0, format, layout); response_id = GTK_RESPONSE_OK; + } else { + response_id = GTK_RESPONSE_NONE + GTK_RESPONSE_OK + 1; + if (perr_message) { + *perr_message = new char[strlen(line)+50]; + sprintf(*perr_message, "Can't open output file %s", line); + } } } else if ( CALL_GTK(gtk_printer_accepts_ps)(gprinter) && //2.10 CALL_GTK(gtk_printer_is_active)(gprinter) ) { // 2.10 @@ -167,6 +173,12 @@ int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpag Fl_PostScript_File_Device::begin_job(output, 0, format, layout); pjob = CALL_GTK(gtk_print_job_new)("FLTK print job", gprinter, psettings, psetup); //2.10 response_id = GTK_RESPONSE_OK; + } else { + response_id = GTK_RESPONSE_NONE + GTK_RESPONSE_OK + 1; + if (perr_message) { + *perr_message = new char[strlen(tmpfilename)+50]; + sprintf(*perr_message, "Can't create temporary file %s", tmpfilename); + } } } CALL_GTK(g_object_unref)(psettings); @@ -183,7 +195,7 @@ int Fl_GTK_Printer_Driver::begin_job(int pagecount, int *firstpage, int *lastpag while (Fl::ready()) Fl::check(); Fl_Surface_Device::pop_current(); } - return (response_id == GTK_RESPONSE_OK ? 0 : 1); + return (response_id == GTK_RESPONSE_OK ? 0 : (response_id == GTK_RESPONSE_NONE ? 1 : 2)); } static void pJobCompleteFunc(Fl_GTK_Printer_Driver::GtkPrintJob *print_job, Fl_GTK_Printer_Driver::gboolean *user_data, const Fl_GTK_Printer_Driver::GError *error) { @@ -221,7 +233,7 @@ Fl_Paged_Device* Fl_Printer::newPrinterDriver(void) } /* Begins a print job. */ -int Fl_Posix_Printer_Driver::begin_job(int pages, int *firstpage, int *lastpage) { +int Fl_Posix_Printer_Driver::begin_job(int pages, int *firstpage, int *lastpage, char **perr_message) { enum Fl_Paged_Device::Page_Format format; enum Fl_Paged_Device::Page_Layout layout; @@ -309,8 +321,11 @@ int Fl_Posix_Printer_Driver::begin_job(int pages, int *firstpage, int *lastpage) Fl_PostScript_Graphics_Driver *ps = driver(); ps->output = popen(command, "w"); if (!ps->output) { - fl_alert("could not run command: %s\n",command); - return 1; + if (perr_message) { + *perr_message = new char[strlen(command) + 50]; + sprintf(*perr_message, "could not run command: %s", command); + } + return 2; } ps->close_command(pclose); this->set_current(); diff --git a/src/drivers/PostScript/Fl_PostScript.cxx b/src/drivers/PostScript/Fl_PostScript.cxx index 9994a515d..f182720b8 100644 --- a/src/drivers/PostScript/Fl_PostScript.cxx +++ b/src/drivers/PostScript/Fl_PostScript.cxx @@ -109,7 +109,7 @@ int Fl_PostScript_File_Device::begin_job (FILE *ps_output, int pagecount, return 0; } -int Fl_PostScript_File_Device::begin_job(int pagecount, int* from, int* to) +int Fl_PostScript_File_Device::begin_job(int pagecount, int* from, int* to, char **) { return 1; } diff --git a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx index ba33e1ebe..980533045 100644 --- a/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx +++ b/src/drivers/WinAPI/Fl_WinAPI_Printer_Driver.cxx @@ -38,7 +38,7 @@ private: int top_margin; void absolute_printable_rect(int *x, int *y, int *w, int *h); Fl_WinAPI_Printer_Driver(void); - int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL); + int begin_job(int pagecount = 0, int *frompage = NULL, int *topage = NULL, char **perr_message = NULL); int begin_page (void); int printable_rect(int *w, int *h); void margins(int *left, int *top, int *right, int *bottom); @@ -85,7 +85,7 @@ static void WIN_SetupPrinterDeviceContext(HDC prHDC) } -int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage) +int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topage, char **perr_message) // returns 0 iff OK { if (pagecount == 0) pagecount = 10000; @@ -116,14 +116,26 @@ int Fl_WinAPI_Printer_Driver::begin_job (int pagecount, int *frompage, int *topa prerr = StartDoc (hPr, &di); if (prerr < 1) { abortPrint = TRUE; - //fl_alert ("StartDoc error %d", prerr); - err = 1; + DWORD dw = GetLastError(); + err = (dw == ERROR_CANCELLED ? 1 : 2); + if (perr_message && err == 2) { + wchar_t *lpMsgBuf; + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR) &lpMsgBuf, + 0, NULL); + unsigned srclen = lstrlenW(lpMsgBuf) - 2; // ignore terminal ^M + unsigned l = fl_utf8fromwc(NULL, 0, lpMsgBuf, srclen); + char *tmp = new char[l+1]; + fl_utf8fromwc(tmp, l, lpMsgBuf, srclen); + LocalFree(lpMsgBuf); + *perr_message = new char[l + 50]; + sprintf(*perr_message, "begin_job() failed with error %d: %s", dw, tmp); + delete[] tmp; + } } - } else { - commdlgerr = CommDlgExtendedError (); - fl_alert ("Unable to create print context, error %lu", - (unsigned long) commdlgerr); - err = 1; } } else { err = 1; diff --git a/test/device.cxx b/test/device.cxx index 964e4da84..6ddda8761 100644 --- a/test/device.cxx +++ b/test/device.cxx @@ -612,21 +612,22 @@ void copy(Fl_Widget *, void *data) { if (strcmp(operation, "Fl_Printer") == 0 || strcmp(operation, "Fl_PostScript_File_Device") == 0) { Fl_Paged_Device *p; int err; + char *err_message = NULL; if (strcmp(operation, "Fl_Printer") == 0) { p = new Fl_Printer(); - err = p->start_job(1); + err = p->begin_job(1, NULL, NULL, &err_message); } else { p = new Fl_PostScript_File_Device(); err = ((Fl_PostScript_File_Device*)p)->start_job(1); } if (!err) { - p->start_page(); + p->begin_page(); if (target->as_window()) p->print_window(target->as_window()); else p->print_widget(target); p->end_page(); p->end_job(); - } + } else if (err > 1 && err_message) {fl_alert("%s", err_message); delete[] err_message;} delete p; } } -- cgit v1.2.3