Edit

IABSD.fr/xenocara/lib/libXaw/src/PrintShell.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2006-11-25 16:53:47
    Hash : 59f6d906
    Message : import from X.Org 7.2RC2

  • lib/libXaw/src/PrintShell.c
  • /* $Xorg: PrintShell.c,v 1.1 2003/07/11 19:46:06 gisburn Exp $ */
    /******************************************************************************
     ******************************************************************************
     **
     ** (c) Copyright 2003 Danny Backx <danny.backx@skynet.be>
     ** (c) Copyright 2003-2004 Roland Mainz <roland.mainz@nrubsig.org>
     ** 
     ** Permission is hereby granted, free of charge, to any person obtaining a copy
     ** of this software and associated documentation files (the "Software"), to deal
     ** in the Software without restriction, including without limitation the rights
     ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     ** copies of the Software, and to permit persons to whom the Software is
     ** furnished to do so, subject to the following conditions:
     **
     ** 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
     ** COPYRIGHT HOLDERS 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 names of the copyright holders shall
     ** not be used in advertising or otherwise to promote the sale, use or other
     ** dealings in this Software without prior written authorization from said
     ** copyright holders.
     **
     ******************************************************************************
     *****************************************************************************/
     
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    
    #include <X11/IntrinsicP.h>
    #include <X11/StringDefs.h>
    
    #include "Print.h"
    #include "PrintSP.h"
    
    /* Local prototypes */
    static void    class_initialize(void);
    static void    class_part_initialize(WidgetClass w_class);
    static void    initialize(Widget request, Widget new_w, ArgList args, Cardinal *num_args);
    static void    destroy(Widget w);
    static Boolean set_values(Widget current, Widget request, Widget new_w, ArgList args, Cardinal *num_args);
    static void    XawPrintNotify(Widget w, XtPointer client, XEvent *evp, Boolean *cont);
    static void    XawAttributesNotify(Widget w, XtPointer client, XEvent *evp, Boolean *cont);
    static void    XawUpdateLayout(Widget w);
    static void    XawUpdateResources(Widget w, XPContext pcontext);
    
    #define Offset(field) XtOffsetOf(XawPrintShellRec, print.field)
    
    #ifdef XAWDEBUG
    #define DEBUGOUT(x) XawDebug x ;
    
    static void
    XawDebug(const char *fn, Widget w, const char *fmt, ...)
    {
        va_list ap;
    
        if (w) {
            fprintf(stderr, "%s %s: ",
                    w->core.widget_class->core_class.class_name, XtName(w));
        } else {
            fprintf(stderr, "(null widget): ");
        }
    
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        va_end(ap);
    }
    #else
    #define DEBUGOUT(x)
    #endif /* XAWDEBUG */
    
    /* Resources for the PrintShell class */
    static XtResource resources[] =
    {
      {
        XawNstartJobCallback, XtCCallback, XtRCallback,
        sizeof(XtCallbackList), Offset(start_job_callback),
        XtRImmediate, (XtPointer)NULL
      },
      {
        XawNendJobCallback, XtCCallback, XtRCallback,
        sizeof(XtCallbackList), Offset(end_job_callback),
        XtRImmediate, (XtPointer)NULL
      },
      {
        XawNdocSetupCallback, XtCCallback, XtRCallback,
        sizeof(XtCallbackList), Offset(doc_setup_callback),
        XtRImmediate, (XtPointer)NULL
      },
      {
        XawNpageSetupCallback, XtCCallback, XtRCallback,
        sizeof(XtCallbackList), Offset(page_setup_callback),
        XtRImmediate, (XtPointer)NULL
      },
      {
        XawNlayoutMode, XawCLayoutMode, XtREnum,
        sizeof(XtEnum), Offset(layoutmode),
        XtRImmediate, (XtPointer)XawPrintLAYOUTMODE_PAGESIZE
      },
      {
        XawNminX, XawCMinX, XtRDimension,
        sizeof(Dimension), Offset(min_x),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNminY, XawCMinY, XtRDimension,
        sizeof(Dimension), Offset(min_y),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNmaxX, XawCMaxX, XtRDimension,
        sizeof(Dimension), Offset(max_x),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNmaxY, XawCMaxY, XtRDimension,
        sizeof(Dimension), Offset(max_y),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNcurrDocNumInJob, XawCCurrDocNumInJob, XtRInt,
        sizeof(unsigned int), Offset(curr_doc_num_in_job),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNcurrPageNumInDoc, XawCCurrPageNumInDoc, XtRInt,
        sizeof(unsigned int), Offset(curr_page_num_in_doc),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNcurrPageNumInJob, XawCCurrPageNumInJob, XtRInt,
        sizeof(unsigned int), Offset(curr_page_num_in_job),
        XtRImmediate, (XtPointer)NULL        /* dynamic */
      },
      {
        XawNdefaultPixmapResolution, XawCDefaultPixmapResolution, XtRShort,
        sizeof(unsigned short), Offset(default_pixmap_resolution),
        XtRImmediate, (XtPointer)0
      },
    };
    
    static XtActionsRec actions[] =
    {
        { NULL, NULL }
    };
    
    XawPrintShellClassRec xawPrintShellClassRec = {
        /* Core class part */
        {
        /* superclass            */ (WidgetClass) &applicationShellClassRec,
        /* class_name            */ "XawPrintShell",
        /* widget_size           */ sizeof(XawPrintShellRec),
        /* class_initialize      */ class_initialize,
        /* class_part_initialize */ class_part_initialize,
        /* class_inited          */ False,
        /* initialize            */ initialize,
        /* initialize_hook       */ NULL,
        /* realize               */ XtInheritRealize,
        /* actions               */ actions,
        /* num_actions           */ XtNumber(actions),
        /* resources             */ resources,
        /* num_resources         */ XtNumber(resources),
        /* xrm_class             */ NULLQUARK,
        /* compress_motion       */ False,
        /* compress_exposure     */ XtExposeCompressSeries,
        /* compress_enterleave   */ False,
        /* visible_interest      */ False,
        /* destroy               */ destroy,
        /* resize                */ XtInheritResize,
        /* expose                */ XtInheritExpose,
        /* set_values            */ set_values,
        /* set_values_hook       */ NULL,
        /* set_values_almost     */ XtInheritSetValuesAlmost,
        /* get_values_hook       */ NULL,
        /* accept_focus          */ NULL,
        /* version               */ XtVersion,
        /* callback offsets      */ NULL,
        /* tm_table              */ XtInheritTranslations,
        /* query_geometry        */ XtInheritQueryGeometry,
        /* display_accelerator   */ NULL,
        /* extension             */ NULL /* (XtPointer)&_XawPrintShellCoreClassExtRec */
        },
        /* Composite class part */
        {
        /* geometry manager */    XtInheritGeometryManager,
        /* change_managed   */    XtInheritChangeManaged,
        /* insert_child     */    XtInheritInsertChild,
        /* delete_child     */    XtInheritDeleteChild,
        /* extension        */    NULL,    
        },
        /* Shell class part */
        {
        /* extension        */    NULL,
        },
        /* WM Shell class part */
        {
        /* extension    */        NULL,
        },
        /* VendorShell class part */
        {
        /* extension    */        NULL,
        },
        /* TopLevelShell class part */
        {
        /* extension    */        NULL,
        },
        /* ApplicationShell class part */
        {
        /* extension    */        NULL,
        },
        {
            /* ?? */              NULL,
        },
    };
    
    WidgetClass xawPrintShellWidgetClass = (WidgetClass)&xawPrintShellClassRec;
    
    
    static void
    class_initialize(void)
    {
    }
    
    
    static void
    class_part_initialize(WidgetClass widget_class)
    {
    }
    
    /*
     * This is a static table to keep the link between widgets and XPContexts.
     * Yeah - this is probably not a very bright idea. Maybe it should also
     * contain the Display.
     */
    typedef struct {
        Widget    w;
        XPContext c;
    } WidgetContext;
    static WidgetContext *w_ctxt     = NULL;
    static int            wc_nfields = 0;
    
    static void
    XawStoreWidgetContext(Widget w, XPContext c)
    {
        wc_nfields++;
        w_ctxt = (WidgetContext *)XtRealloc((XtPointer)w_ctxt, sizeof(WidgetContext) * wc_nfields);
        w_ctxt[wc_nfields-1].w = w;
        w_ctxt[wc_nfields-1].c = c;
    }
    
    /* FIXME: This is not threadsafe... */
    static Widget
    XawPrintContextToWidget(XPContext c)
    {
        int i;
    
        for( i = 0 ; i < wc_nfields ; i++ ) {
            if( w_ctxt[i].c == c ) {
                return w_ctxt[i].w;
            }
        }
        return NULL;
    }
    
    /* FIXME: This is not threadsafe... */
    static XPContext
    XawPrintWidgetToContext(Widget w)
    {
        int i;
    
        for( i = 0 ; i < wc_nfields ; i++ ) {
            if (w_ctxt[i].w == w) {
                return w_ctxt[i].c;
            }
        }
        return (XPContext)None;
    }
    
    /* FIXME: This is not threadsafe... */
    static void
    XawPrintDeleteWidgetContext(Widget w)
    {
        int i;
    
        for( i = 0 ; i < wc_nfields ; i++ ) {
            if( w_ctxt[i].w == w ) {
                w_ctxt[i].w = NULL;
                w_ctxt[i].c = None;
            }
        }
    }
    
    static void
    SelectNotify(Widget w, int *e, XtPointer *s, int n, XtPointer client)
    {
        XPContext c = XpGetContext(XtDisplay(w));
    
        if (!c) {
            XtAppWarning(XtWidgetToApplicationContext(w),
                         "XawPrintShell: SelectNotify: no print context\n");
            return;
        }
    
        XpSelectInput(XtDisplay(w), c, XPPrintMask|XPAttributeMask);   
    }
    
    
    static Boolean
    DispatchEvent(XEvent *evp)
    {
        XPPrintEvent *e = (XPPrintEvent*)evp;
    
        Widget w = XawPrintContextToWidget(e->context);
    
        /* Make sure this event is really for this window... */
        if (XFilterEvent(evp, XtWindow(w)))
        {
            DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent *** filter XFilterEvent() matched.\n"));
            return True;
        }
    
        /* Only for debugging */   
    #ifdef XAWDEBUG
        {
            int error_base,
                event_base;
    
            if (!XpQueryExtension(XtDisplay(w), &event_base, &error_base)) {
                return False;
            }
    
            if (e->type == event_base + XPPrintNotify) {
                switch (e->detail) {
                case XPStartJobNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPStartJobNotify\n"));
                    break;
                case XPEndJobNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPEndJobNotify\n"));
                    break;
                case XPStartDocNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPStartDocNotify\n"));
                    break;
                case XPStartPageNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPStartPageNotify\n"));
                    break;
                case XPEndPageNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPEndPageNotify\n"));
                    break;
                case XPEndDocNotify:
                    DEBUGOUT((__FILE__, w, "XawPrintShell-DispatchEvent XPEndDocNotify\n"));
                    break;
                default:
                    DEBUGOUT((__FILE__, w, "XawPrintShell DispatchEvent\n"));
                }
            }
        }
    #endif /* XAWDEBUG */
    
        return XtDispatchEventToWidget(w, evp);
    }
    
    
    static void
    initialize(Widget request, Widget new_w, ArgList args, Cardinal *num_args)
    {
        int       error_base,
                  event_base;
        XPContext pcontext;
    
        DEBUGOUT((__FILE__, new_w, "XawPrintShell Initialize\n"));
    
        if (!XpQueryExtension(XtDisplay(new_w), &event_base, &error_base)) {
            DEBUGOUT((__FILE__, new_w, "XawPrintShell initialize: failed!!\n"));
            XtAppWarning(XtWidgetToApplicationContext(new_w),
                         "XawPrintShell: initialize: XpQueryExtension() failed. BAD.\n");
            return;
        }
    
        DEBUGOUT((__FILE__, new_w, "XawPrintShell Initialize event_base %d error_base %d\n",
                          event_base, error_base));
    
        pcontext = XpGetContext(XtDisplay(new_w));
    
        if( pcontext == None ) {
            XtAppWarning(XtWidgetToApplicationContext(new_w),
                         "XawPrintShell: initialize: No print content. BAD.\n");
            return;
        }
        
        /* Make sure that the Xt machinery is really using the right screen (assertion) */
        if( XpGetScreenOfContext(XtDisplay(new_w), pcontext) != XtScreen(new_w) ) {
            XtAppWarning(XtWidgetToApplicationContext(new_w),
                         "XawPrintShell: initialize: Widget's screen != print screen. BAD.\n");
            return;
        }
    
        XawStoreWidgetContext(new_w, pcontext);
    
        XtInsertEventTypeHandler(new_w,
                                 event_base + XPPrintNotify,
                                 (XtPointer)XPPrintMask,
                                 XawPrintNotify, NULL,
                                 XtListTail);
        XtInsertEventTypeHandler(new_w,
                                 event_base + XPAttributeNotify,
                                 (XtPointer)XPAttributeMask, 
                                 XawAttributesNotify, NULL,
                                 XtListTail);
    
        XtRegisterExtensionSelector(XtDisplay(new_w),
                                    event_base + XPPrintNotify,
                                    event_base + XPAttributeNotify,
                                    SelectNotify,
                                    NULL);
    
        XtSetEventDispatcher(XtDisplay(new_w),
                             event_base + XPPrintNotify,
                             DispatchEvent);
        XtSetEventDispatcher(XtDisplay(new_w),
                             event_base + XPAttributeNotify,
                             DispatchEvent);
    
        PS_LastPageInDoc(new_w) = False;
        PS_LastPageInJob(new_w) = False;
    
        XawUpdateResources(new_w, pcontext);
        XawUpdateLayout(new_w);
        
        DEBUGOUT((__FILE__, new_w, "XawPrintShell Initialize x %d y %d wid %d ht %d\n",
                 new_w->core.x,
                 new_w->core.y,
                 new_w->core.width,
                 new_w->core.height));
    }
    
    
    static void
    destroy(Widget w)
    {
        DEBUGOUT((__FILE__, w, "XawPrintShell Destroy\n"));
        XawPrintDeleteWidgetContext(w);
    }
    
    static Boolean
    set_values(Widget current, Widget request, Widget new_w,
               ArgList args, Cardinal *num_args)
    {
        DEBUGOUT((__FILE__, new_w, "XawPrintShell SetValues\n"));
        return True;
    }
    
    void XawPrintRedisplayWidget(Widget w) 
    {
        XExposeEvent xev;
        Region       region;
    
        xev.type       = Expose;
        xev.serial     = XLastKnownRequestProcessed(XtDisplay(w));
        xev.send_event = False;
        xev.display    = XtDisplay(w);
        xev.window     = XtWindowOfObject(w);
        xev.x          = 0;
        xev.y          = 0;
        xev.width      = w->core.width;
        xev.height     = w->core.height;
        xev.count      = 0;
    
        region = XCreateRegion();
        if (!region)
          return;
    
        XtAddExposureToRegion((XEvent*)&xev, region);    
    
        if (w->core.widget_class->core_class.expose)
            (*(w->core.widget_class->core_class.expose))(w, (XEvent *)&xev, region);
    
        XDestroyRegion(region);
    }
    
    /* Returns whether the widget passed in is a print shell or "print shell"-like
     * widget (e.g. print preview).
     * Note that this will return |True| for more classes than |XawPrintShell| in
     * the future (like for |XmPrintShell| etc.)
     */
    Boolean 
    XawIsPrintShell(Widget w)
    {
        return XtIsSubclass(w, xawPrintShellWidgetClass);
    }
    
    
    static void
    XawPrintNotify(Widget w, XtPointer client, XEvent *evp, Boolean *cont)
    {
        XPPrintEvent                *e = (XPPrintEvent *)evp;
        XawPrintShellCallbackStruct  cbs;
    
        switch (e->detail) {
        case XPStartPageNotify:
            DEBUGOUT((__FILE__, w, "XPStartPageNotify\n"));
    
            /* Re do not have to call |XawPrintRedisplayWidget(w)| here since
             * Xprint triggers an expose event anyway
             */
            
            DEBUGOUT((__FILE__, w, "XpEndPage\n"));
            XpEndPage(XtDisplay(w));
            break;
    
        case XPEndPageNotify:
            DEBUGOUT((__FILE__, w, "XPEndPageNotify\n"));
    
            if (PS_LastPageInDoc(w) || PS_LastPageInJob(w)) {
                DEBUGOUT((__FILE__, w, "XpEndDoc\n"));
                XpEndDoc(XtDisplay(w));
            }
            else {
                /* Increment page numbers... */
                PS_CurrPageNumInDoc(w) += 1;
                PS_CurrPageNumInJob(w) += 1;
    
                /* ... do the page setup callback ... */
                cbs.reason           = XawCR_PAGE_SETUP;
                cbs.event            = evp;
                cbs.detail           = NULL;
                cbs.context          = XawPrintWidgetToContext(w);
                cbs.last_page_in_doc = False;
                cbs.last_page_in_job = False;
    
                if (PS_PageSetupCallback(w))
                    XtCallCallbackList(w, PS_PageSetupCallback(w), &cbs);
    
                PS_LastPageInDoc(w) = cbs.last_page_in_doc;
                PS_LastPageInJob(w) = cbs.last_page_in_job;
    
                /* ... and start the new page */
                DEBUGOUT((__FILE__, w, "XpStartPage\n"));
                XpStartPage(XtDisplay(w), XtWindow(w));
            }
            break;
    
        case XPStartDocNotify:
            DEBUGOUT((__FILE__, w, "XPStartDocNotify\n"));
    
            cbs.reason           = XawCR_PAGE_SETUP;
            cbs.event            = evp;
            cbs.detail           = NULL;
            cbs.context          = XawPrintWidgetToContext(w);
            cbs.last_page_in_doc = False;
            cbs.last_page_in_job = False;
    
            if (PS_PageSetupCallback(w))
                XtCallCallbackList(w, PS_PageSetupCallback(w), &cbs);
    
            PS_LastPageInDoc(w) = cbs.last_page_in_doc;
            PS_LastPageInJob(w) = cbs.last_page_in_job;
    
            DEBUGOUT((__FILE__, w, "XpStartPage\n"));
            XpStartPage(XtDisplay(w), XtWindow(w));
            break;
    
        case XPEndDocNotify:
            DEBUGOUT((__FILE__, w, "XPEndDocNotify\n"));
            
            /* Start a new document (via XpStartDoc()) if we are not done with the job yet,
             * otherwise finish the job (via XpEndJob())
             */
            if (PS_LastPageInJob(w)) {
                DEBUGOUT((__FILE__, w, "XpEndJob\n"));
                XpEndJob(XtDisplay(w));
            }
            else {
                PS_CurrDocNumInJob(w) += 1;
                PS_CurrPageNumInDoc(w) = 1;
    
                cbs.reason           = XawCR_DOC_SETUP;
                cbs.event            = evp;
                cbs.detail           = NULL;
                cbs.context          = XawPrintWidgetToContext(w);
                cbs.last_page_in_doc = False;
                cbs.last_page_in_job = False;
    
                if (PS_DocSetupCallback(w))
                    XtCallCallbackList(w, PS_DocSetupCallback(w), &cbs);
    
                PS_LastPageInDoc(w)  = cbs.last_page_in_doc;
                PS_LastPageInJob(w)  = cbs.last_page_in_job;
    
                DEBUGOUT((__FILE__, w, "XpStartDoc\n"));
                XpStartDoc(XtDisplay(w), XPDocNormal);
            }
            break;
    
        case XPStartJobNotify:
            DEBUGOUT((__FILE__, w, "XPStartJobNotify\n"));
            PS_LastPageInJob(w)    = False;
            PS_LastPageInDoc(w)    = False;
            PS_CurrDocNumInJob(w)  = 1;
            PS_CurrPageNumInDoc(w) = 1;
            PS_CurrPageNumInJob(w) = 1;
    
            cbs.reason           = XawCR_START_JOB;
            cbs.event            = evp;
            cbs.detail           = NULL;
            cbs.context          = XawPrintWidgetToContext(w);
            cbs.last_page_in_doc = False;
            cbs.last_page_in_job = False;
    
            if (PS_StartJobCallback(w))
                XtCallCallbackList(w, PS_StartJobCallback(w), &cbs);
    
            PS_LastPageInDoc(w)  = cbs.last_page_in_doc;
            PS_LastPageInJob(w)  = cbs.last_page_in_job;
    
            /* Start a document (which will trigger the first page in
             * |XPStartDocNotify| above) */
            if (PS_LastPageInDoc(w) || PS_LastPageInJob(w)) {
                DEBUGOUT((__FILE__, w, "XpEndJob\n"));
                XpEndJob(XtDisplay(w));
            }
            else
            {
                cbs.reason           = XawCR_DOC_SETUP;
                cbs.event            = evp;
                cbs.detail           = NULL;
                cbs.context          = XawPrintWidgetToContext(w);
                cbs.last_page_in_doc = False;
                cbs.last_page_in_job = False;
    
                if (PS_DocSetupCallback(w))
                    XtCallCallbackList(w, PS_DocSetupCallback(w), &cbs);
    
                PS_LastPageInDoc(w)  = cbs.last_page_in_doc;
                PS_LastPageInJob(w)  = cbs.last_page_in_job;
    
                DEBUGOUT((__FILE__, w, "XpStartDoc\n"));
                XpStartDoc(XtDisplay(w), XPDocNormal);
            }
            break;
    
        case XPEndJobNotify:
            DEBUGOUT((__FILE__, w, "XPEndJobNotify\n"));
            cbs.reason           = XawCR_END_JOB;
            cbs.event            = evp;
            cbs.detail           = NULL;
            cbs.context          = None;
            cbs.last_page_in_doc = True;
            cbs.last_page_in_job = True;
    
            if (PS_EndJobCallback(w))
                XtCallCallbackList(w, PS_EndJobCallback(w), &cbs);
            break;
    
        default:
            DEBUGOUT((__FILE__, w, "XawPrintNotify(default)\n"));
            break;
        }
    }
    
    static void 
    XawUpdateResources(Widget w, XPContext pcontext)
    {
        XawPrintShellWidget print_shell = (XawPrintShellWidget)w;
        String              string_resolution;
        XRectangle          drawable_paper_area;
    
        string_resolution = XpGetOneAttribute(XtDisplay(w), pcontext, XPDocAttr, "default-printer-resolution");
        if (!string_resolution) {
          XtAppWarning(XtWidgetToApplicationContext(w),
                       "XawPrintShell: XawUpdateResources: Could not get 'default-printer-resolution' XPDocAttr\n");
        }
        print_shell->print.print_resolution = atol(string_resolution);
        XFree(string_resolution);
    
        if (print_shell->print.print_resolution == 0) {
          XtAppWarning(XtWidgetToApplicationContext(w),
                       "XawPrintShell: XawUpdateResources: Resolution '0' invalid\n");
        }
    
        /* Get the paper size... */
        XpGetPageDimensions(XtDisplay(w), pcontext,
                            &print_shell->print.page_width, &print_shell->print.page_height, 
                            &drawable_paper_area);
        /* ... and store it in the widget */
        print_shell->print.min_x = drawable_paper_area.x;
        print_shell->print.min_y = drawable_paper_area.y;
        print_shell->print.max_x = drawable_paper_area.x + drawable_paper_area.width;
        print_shell->print.max_y = drawable_paper_area.y + drawable_paper_area.height;
    }
    
    static void 
    XawUpdateLayout(Widget w)
    {
        XawPrintShellWidget  print_shell = (XawPrintShellWidget)w;
    
        switch( print_shell->print.layoutmode )
        {
          case XawPrintLAYOUTMODE_NONE:
              break;
          case XawPrintLAYOUTMODE_PAGESIZE:
              XtResizeWidget(w,
                             print_shell->print.page_width,
                             print_shell->print.page_height,
                             w->core.border_width);
              break;
          case XawPrintLAYOUTMODE_DRAWABLEAREA:
              XtConfigureWidget(w, 
                                print_shell->print.min_x,
                                print_shell->print.min_y, 
                                print_shell->print.max_x - print_shell->print.min_x, 
                                print_shell->print.max_y - print_shell->print.min_y,
                                w->core.border_width);
              break;
          default:
              XtAppWarning(XtWidgetToApplicationContext(w),
                           "XawPrintShell: XawUpdateResources: Invalid layout mode\n");
              break;
        }
    }
    
    
    /* Update widget attributes+properties when the we receive
     * "Xp attribute change"-events (e.g. paper (size/orientation/etc.)
     * changed etc.) */
    static void 
    XawAttributesNotify(Widget w,
                        XtPointer client,
                        XEvent *evp,
                        Boolean *cont)
    {
        XawPrintShellWidget  print_shell = (XawPrintShellWidget)w;
        XPAttributeEvent    *xpevp       = (XPAttributeEvent *)evp;
    
        XawUpdateResources(w, xpevp->context);
        XawUpdateLayout(w);
    }