diff options
Diffstat (limited to 'xpxmhelloworld/xpxmhelloworld.c')
-rw-r--r-- | xpxmhelloworld/xpxmhelloworld.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/xpxmhelloworld/xpxmhelloworld.c b/xpxmhelloworld/xpxmhelloworld.c new file mode 100644 index 0000000..608c385 --- /dev/null +++ b/xpxmhelloworld/xpxmhelloworld.c @@ -0,0 +1,449 @@ + +/* + * $Xorg: xpxmhelloworld.c,v 1.2 2003/10/19 00:3:26 gisburn Exp $ + * + * xpxmhelloworld - Xprint version of hello world using Motif widgets + * + * +Copyright 2002-2004 Roland Mainz <roland.mainz@nrubsig.org> + +All Rights Reserved. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * + * Author: Roland Mainz <roland.mainz@nrubsig.org> + */ + +/* + * Referencess: + * http://nscp.upenn.edu/aix4.3html/libs/motiftr/XmPrintShell.htm + * http://nscp.upenn.edu/aix4.3html/libs/motiftr/XmText.htm + * + */ + +#include <X11/IntrinsicP.h> +#include <X11/ShellP.h> +#include <X11/StringDefs.h> +#include <Xm/Xm.h> +#include <Xm/Text.h> +#include <Xm/Print.h> +#include <X11/XprintUtil/xprintutil.h> + +#include <stdlib.h> +#include <stdio.h> + +/* Turn a NULL pointer string into an empty string */ +#define NULLSTR(x) (((x)!=NULL)?(x):("")) + +#define Error(x) { printf x ; exit(EXIT_FAILURE); } +#define Log(x) { if(verbose) printf x; } + +/* Prototypes */ +static int do_hello_world( int argc, char *argv[], const char *printername, + const char *toFile, const char *sample_string ); + +/* Global vars */ +const char *ProgramName; /* program name (from argv[0]) */ +Bool verbose = False; /* verbose output what the program is doing */ +Bool doPrint = False; /* Do we print on a printer ? */ +Display *pdpy = NULL; /* (Paper) display */ +Screen *pscreen = NULL; /* (Paper) screen (DDX-specific!) */ +XPContext pcontext = None; /* Xprint context */ +void *printtofile_handle = NULL; /* XprintUtil "context" when printing to file */ +Drawable pdrawable = None; /* paper drawable */ + +static +void usage( void ) +{ + fprintf(stderr, "usage: %s [options] string\n", ProgramName); + fprintf(stderr, "-print\tPrint via Xprint instead of displaying on the Xserver\n"); + fprintf(stderr, "-printer printernname\tprinter to use\n"); + fprintf(stderr, "-printfile file\tprint to file instead of printer\n"); + fprintf(stderr, "-v\tverbose output\n"); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); +} + +int main( int argc, char *argv[] ) +{ + const char *printername = NULL; /* printer to query */ + const char *toFile = NULL; /* output file (instead of printer) */ + XPPrinterList plist; /* list of printers */ + int plist_count; /* number of entries in |plist|-array */ + int i; + int retval; + const char *sample_string; + + ProgramName = argv[0]; + + if( argc < 2 ) + { + usage(); + } + + for( i = 1 ; i < (argc-1) ; i++ ) + { + char *arg = argv[i]; + int len = strlen(arg); + + if (!strncmp("-print", arg, len)) + { + doPrint = True; + } + else if (!strncmp("-printer", arg, len)) + { + if (++i >= argc) + usage(); + printername = argv[i]; + doPrint = True; + } + else if (!strncmp("-printfile", arg, len)) + { + if (++i >= argc) + usage(); + toFile = argv[i]; + doPrint = True; + } + else if (!strncmp("-v", arg, len)) + { + verbose = True; + } + else + { + usage(); + } + } + + sample_string = argv[argc-1]; + + if( doPrint ) + { + plist = XpuGetPrinterList(printername, &plist_count); + + if (!plist) { + fprintf(stderr, "%s: no printers found for printer spec \"%s\".\n", + ProgramName, NULLSTR(printername)); + exit(EXIT_FAILURE); + } + + Log(("Using printer '%s'\n", plist[0].name)); + + retval = do_hello_world(argc, argv, plist[0].name, toFile, sample_string); + + XpuFreePrinterList(plist); + } + else + { + Log(("Displaying on framebuffer Xserver\n")); + + retval = do_hello_world(argc, argv, NULL, NULL, sample_string); + } + + return retval; +} + +/* xt_xp_openapplication() - mainly identical to XtOpenApplication() but + * takes a |Display *| and |Screen *| as arguments, too... */ +static +Widget xt_xp_openapplication(XtAppContext *app_context_return, + Display *dpy, + Screen *screen, + String application_name, + String application_class, + WidgetClass widget_class, + int *argc, + String *argv) +{ + Widget toplevel; + Cardinal n; + Arg args[2]; + + XtToolkitInitialize(); + *app_context_return = XtCreateApplicationContext(); + if( *app_context_return == NULL ) + return NULL; + + XtDisplayInitialize(*app_context_return, dpy, + application_name, application_class, + NULL, 0, + argc, argv); + + n = 0; + XtSetArg(args[n], XtNscreen, screen); n++; + toplevel = XtAppCreateShell(application_name, + application_class, + widget_class, + dpy, + args, n); + + return toplevel; +} + +typedef struct +{ + int num_pages; + int curr_page; + + Widget printshell_content; + int num_visible_rows; + XtAppContext appcontext; /* for XtAppSetExitFlag() */ +} MyPrintCallbackData; + + +static +void PrintOnePageCB(Widget pshell, XtPointer context, XtPointer call_data) +{ + MyPrintCallbackData *mpcd = (MyPrintCallbackData *)context; + XmPrintShellCallbackStruct *psp = (XmPrintShellCallbackStruct *)call_data; + + Log(("--> PrintOnePageCB, printing page %d of %d\n", mpcd->curr_page, mpcd->num_pages)); + + mpcd->curr_page++; + + /* Get ready for next page + * Scroll widget to display the next page (except for the first page :) + */ + if (!psp->last_page && mpcd->curr_page > 1) + { + /* XmText allows two solutions to scroll a page down + * - Either scroll num_rows_per_page down (this is XmText-specific) + * or + * - Call the "next-page" action procedure (this works for all widgets + * which support this action proc) + */ +#define USE_ACTION_TO_SCROLL_DOWN 1 +#ifdef USE_ACTION_TO_SCROLL_DOWN + Log(("Scrolling down one page ...\n")); + XtCallActionProc(mpcd->printshell_content, "next-page", NULL, NULL, 0); +#else + Log(("Scrolling down %d rows (=one page) ...\n", mpcd->num_visible_rows)); + XmTextScroll(mpcd->printshell_content, mpcd->num_visible_rows); +#endif /* USE_ACTION_TO_SCROLL_DOWN */ + } + + if (mpcd->curr_page == (int)mpcd->num_pages) + { + Log(("Printing last page.\n")); + psp->last_page = True; + } + + Log(("PrintOnePageCB: done\n")); +} + +static +void PrintStartJobCB(Widget pshell, XtPointer context, XtPointer call_data) +{ + XmPrintShellCallbackStruct *psp = (XmPrintShellCallbackStruct *)call_data; + + Log(("--> PrintStartJobCB\n")); +} + +static +void PrintEndJobCB(Widget pshell, XtPointer context, XtPointer call_data) +{ + MyPrintCallbackData *mpcd = (MyPrintCallbackData *)context; + XmPrintShellCallbackStruct *psp = (XmPrintShellCallbackStruct *)call_data; + + Log(("--> PrintEndJobCB\n")); + + /* We're done with printing, tell |XtAppMainLoop()| that it can exit */ + XtAppSetExitFlag(mpcd->appcontext); +} + +int do_hello_world( int argc, char *argv[], const char *printername, const char *toFile, const char *sample_string ) +{ + XtAppContext app; + Widget toplevel, + shell, + print_shell, + hello; + long dpi; + char fontname[256]; /* BUG: is this really big enougth ? */ + XFontStruct *textFont; + XmFontList textFontList; + Cardinal n; + Arg args[10]; + MyPrintCallbackData mpcd; + + if( doPrint ) + { + /* Get printer, either by "name" (foobar) or "name@display" (foobar@gaja:5) */ + if( XpuGetPrinter(printername, &pdpy, &pcontext) != 1 ) + Error(("XpuGetPrinter failure.\n")); + + /* Configure the print context (paper size, title etc.) + * We must do this before creating any Xt widgets - otherwise they will + * make wrong assuptions about fonts, resultions etc. ... + */ + XpuSetJobTitle(pdpy, pcontext, "Simple Xprint XmPrintShell widget demo"); + + /* Configuration done, set the context */ + XpSetContext(pdpy, pcontext); + + /* Get default printer resolution */ + if( XpuGetResolution(pdpy, pcontext, &dpi) != 1 ) + { + fprintf(stderr, "No default resolution for printer '%s'\n", printername); + XpuClosePrinterDisplay(pdpy, pcontext); + return(EXIT_FAILURE); + } + + pscreen = XpGetScreenOfContext(pdpy, pcontext); + } + else + { + pdpy = XOpenDisplay(NULL); + if( !pdpy ) + Error(("XOpenDisplay failure.\n")); + + dpi = 0; + + pscreen = XDefaultScreenOfDisplay(pdpy); + } + + toplevel = xt_xp_openapplication(&app, + pdpy, pscreen, + "xpxmprintshelldemo", "XpXmPrintShellDemo", + applicationShellWidgetClass, + &argc, argv); + + if( !toplevel ) + Error(("xt_xp_openapplication failure.\n")); + + if( doPrint ) + { + n = 0; + print_shell = XtCreatePopupShell("myprintshell", + xmPrintShellWidgetClass, + toplevel, args, n); + + /* we're mapping/unmapping at start/end page time */ + XtSetMappedWhenManaged(print_shell, False); + + shell = print_shell; + } + else + { + shell = toplevel; + } + + sprintf(fontname, "-adobe-courier-medium-r-normal--40-*-%ld-%ld-*-*-iso8859-1", dpi, dpi); + textFont = XLoadQueryFont(pdpy, fontname); + if( !textFont ) + { + sprintf(fontname, "-*-*-*-*-*-*-*-160-%ld-%ld-*-*-iso8859-1", dpi, dpi); + textFont = XLoadQueryFont(pdpy, fontname); + } + if( !textFont ) + Error(("XLoadQueryFont failure.\n")); + textFontList = XmFontListCreate(textFont, XmSTRING_DEFAULT_CHARSET); + + n = 0; + /* Make sure the cursor is off, current Xprt servers do not seem to like + * blinking cursors that much... ;-/ */ + XtSetArg(args[n], XmNcursorPositionVisible, False); n++; + XtSetArg(args[n], XmNvalue, sample_string); n++; + XtSetArg(args[n], XmNfontList, textFontList); n++; + XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; + + hello = XmCreateText(shell, "mytext", args, n); + if( !hello ) + Error(("XmCreateText failure.\n")); + + XtManageChild(hello); + XtRealizeWidget(toplevel); + XtRealizeWidget(shell); + + if( doPrint ) + { + int num_total_rows; + short num_visible_rows; + int num_pages; + + pdpy = XtDisplay(toplevel); + pdrawable = XtWindow(toplevel); + if( !pdpy || !pdrawable ) + Error(("No display.\n")); + + /* Make sure that the Xt machinery is really using the right screen (assertion) */ + if( XpGetScreenOfContext(XtDisplay(toplevel), pcontext) != XtScreen(toplevel) ) + Error(("Widget's screen != print screen. BAD.\n")); + + /* Get number of rows visible per page and the number of total rows + * in the whole text widget... */ + n = 0; + XtSetArg(args[n], XmNrows, &num_visible_rows); n++ ; + XtSetArg(args[n], XmNtotalLines, &num_total_rows); n++ ; + XtGetValues(hello, args, n); + + /* Take away one row to match the one-line overlapping used by the + * "next-page" action proc */ + num_visible_rows -= 1; + + /* Calculate the number of pages */ + num_pages = (num_total_rows+num_visible_rows-1) / num_visible_rows; + Log(("Printing %d pages (num_total_rows=%d, num_visible_rows=%d)...\n", + num_pages, num_total_rows, num_visible_rows)); + + /* Prepare our own context data for the print shell callbacks */ + mpcd.num_pages = num_pages; + mpcd.curr_page = 0; + mpcd.printshell_content = hello; + mpcd.num_visible_rows = num_visible_rows; + mpcd.appcontext = app; + + /* Setup the print shell callbacks... */ + XtAddCallback(print_shell, XmNpageSetupCallback, PrintOnePageCB, (XtPointer)&mpcd); + XtAddCallback(print_shell, XmNstartJobCallback, PrintStartJobCB, NULL); + XtAddCallback(print_shell, XmNendJobCallback, PrintEndJobCB, (XtPointer)&mpcd); + + /* ... and finally start the print job. */ + if( toFile ) + { + printtofile_handle = XpuStartJobToFile(pdpy, pcontext, toFile); + if( !printtofile_handle ) + { + perror("XpuStartJobToFile failure"); + Error(("XpuStartJobToFile failure.")); + } + } + else + { + XpuStartJobToSpooler(pdpy); + } + } + + XtAppMainLoop(app); + + if( doPrint ) + { + if( toFile ) + { + if( XpuWaitForPrintFileChild(printtofile_handle) != XPGetDocFinished ) + { + fprintf(stderr, "%s: Error while printing to file.\n", ProgramName); + } + } + + /* We have to use XpDestroyContext() and XtCloseDisplay() instead + * of XpuClosePrinterDisplay() to make libXt happy... */ + if( pcontext != None ) + XpDestroyContext(pdpy, pcontext); + XtCloseDisplay(pdpy); + } + + return EXIT_SUCCESS; +} + |