Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtpdm / PrinterBox.c
1 /* $XConsortium: PrinterBox.c /main/10 1996/11/20 12:59:48 cde-hp $ */
2 /*
3  * dtpdm/PrinterBox.c
4  */
5 /*
6  * (c) Copyright 1996 Digital Equipment Corporation.
7  * (c) Copyright 1996 Hewlett-Packard Company.
8  * (c) Copyright 1996 International Business Machines Corp.
9  * (c) Copyright 1996 Sun Microsystems, Inc.
10  * (c) Copyright 1996 Novell, Inc. 
11  * (c) Copyright 1996 FUJITSU LIMITED.
12  * (c) Copyright 1996 Hitachi.
13  */
14 #include <Xm/XmAll.h>
15 #include <Dt/DtNlUtils.h>
16
17 #include "PrinterBox.h"
18
19 #include "PdmMsgs.h"
20
21 #ifndef CDE_INSTALLATION_TOP
22 #define CDE_INSTALLATION_TOP "/usr/dt"
23 #endif
24
25 #define ICON_INSTALL_DIR CDE_INSTALLATION_TOP "/appconfig/icons/C/"
26
27 #ifndef MAX
28 # define MAX(a, b) ((a) > (b) ? (a) : (b))
29 #endif /* ! MAX */
30
31 /*
32  * PrinterBox-specific data - PdmSetupBox.subclass_data
33  */
34 typedef struct
35 {
36     /*
37      * child controls
38      */
39     struct _OrientCtl* orient_ctl;
40     struct _PlexCtl* plex_ctl;
41     struct _TrayCtl* tray_ctl;
42     struct _SizeCtl* size_ctl;
43     /*
44      * attribute values
45      */
46     const char* printer_model;
47     char* document_format;
48
49     PdmOidList* document_attrs_supported;
50
51     PdmOidList* orientations_supported;
52     PdmOid orientation;
53
54     PdmOidList* plexes_supported;
55     PdmOid plex;
56
57     PdmOid default_input_tray;
58     PdmOid default_medium;
59
60     PdmOidList* input_trays;
61     PdmOidList* tray_sizes;
62     PdmOidLinkedList* sizes_supported;
63
64 } PdmPrinterBoxData;
65
66 /*
67  * orientations control
68  */
69 typedef struct _OrientCtl
70 {
71     Widget widget;
72     Widget frame_label;
73     Widget option_menu;
74     Widget icon_label;
75
76     int selected_item;
77
78     const PdmOidList* orientations_supported;
79     PdmOidList* dummy_orientations_supported;
80
81     struct _PdmPixmapList* pixmap_list;
82     struct _PdmPixmapList* i_pixmap_list;
83     
84     struct _PlexCtl* plex_ctl;
85     
86 } OrientCtl;
87
88 /*
89  * plexes control
90  */
91 typedef struct _PlexCtl
92 {
93     Widget widget;
94     Widget frame_label;
95     Widget option_menu;
96     Widget icon_label;
97     
98     int selected_item;
99
100     const PdmOidList* plexes_supported;
101     PdmOidList* dummy_plexes_supported;
102
103     struct _PdmPixmapList** pixmap_list_ptr;
104     struct _PdmPixmapList* portrait_pixmap_list;
105     struct _PdmPixmapList* landscape_pixmap_list;
106
107     struct _PdmPixmapList** i_pixmap_list_ptr;
108     struct _PdmPixmapList* i_portrait_pixmap_list;
109     struct _PdmPixmapList* i_landscape_pixmap_list;
110
111 } PlexCtl;
112
113 /*
114  * input trays control
115  */
116 typedef struct _TrayCtl
117 {
118     Widget widget;
119     Widget frame_label;
120     Widget option_menu;
121
122     int selected_item;
123
124     const PdmOidList* input_trays;
125     const PdmOidList* tray_sizes;
126     
127     struct _SizeCtl* size_ctl;
128     
129 } TrayCtl;
130
131 /*
132  * page size control
133  */
134 typedef struct _SizeCtlSortRec
135 {
136     const char* str;
137     PdmOid oid;
138 } SizeCtlSortRec, *SizeCtlSortList;
139
140 typedef struct _SizeCtl
141 {
142     Widget widget;
143     Widget frame_label;
144     Widget list_box;
145     Widget radio_box;
146     Widget ready_radio;
147     Widget supported_radio;
148
149     PdmOidList* sizes_ready;
150     PdmOidList* sizes_supported; 
151
152     PdmOid selected_size;
153     enum {
154         SIZECTL_UNSUPPORTED,
155         SIZECTL_SIZES_READY,
156         SIZECTL_SIZES_SUPPORTED } selected_list;
157
158     Boolean single_size_mode;
159
160     XmStringTable sizes_ready_xmstr;
161     XmStringTable sizes_supported_xmstr;
162     
163 } SizeCtl;
164
165 /*
166  * list of pixmaps
167  */
168 typedef struct _PdmPixmapList
169 {
170     Pixmap* pixmap;
171     char** image_name;
172     int count;
173     Screen* screen;
174     Pixel foreground, background;
175     Pixmap stipple;
176 } PdmPixmapList;
177
178 /*
179  * PrinterBox-specific fallback resources
180  */
181 static String PdmPrinterBoxFallbackResources[] =
182 {
183     "*PrinterSetup*LoadedAllowed.button_0.labelString: Loaded in Printer",
184     "*PrinterSetup*LoadedAllowed.button_1.labelString: All Sizes",
185     "*PrinterSetup*OrientationLabel.labelString: Page Orientation",
186     "*PrinterSetup*PageSizeLabel.labelString: Page Size",
187     "*PrinterSetup*PlexLabel.labelString: Printed Sides",
188     "*PrinterSetup*DocumentFormatLabel.labelString: Format:",
189     "*PrinterSetup*PrinterModelLabel.labelString: Printer Model:",
190     "*PrinterSetup*TrayLabel.labelString: Tray",
191     "*PrinterSetup.locationId: PrinterSetup",
192     "*PrinterSetup*OrientCtlTop.PortraitIconFileName: "
193         ICON_INSTALL_DIR "portrait.pm",
194     "*PrinterSetup*OrientCtlTop.LandscapeIconFileName: "
195         ICON_INSTALL_DIR "landscap.pm",
196     "*PrinterSetup*OrientCtlTop.ReversePortraitIconFileName: "
197         ICON_INSTALL_DIR "rportrai.pm",
198     "*PrinterSetup*OrientCtlTop.ReverseLandscapeIconFileName: "
199         ICON_INSTALL_DIR "rlandsca.pm",
200     "*PrinterSetup*PlexCtlTop.SimplexPortraitIconFileName: "
201         ICON_INSTALL_DIR "psimplex.pm",
202     "*PrinterSetup*PlexCtlTop.SimplexLandscapeIconFileName: "
203         ICON_INSTALL_DIR "lsimplex.pm",
204     "*PrinterSetup*PlexCtlTop.DuplexPortraitIconFileName: "
205         ICON_INSTALL_DIR "pduplex.pm",
206     "*PrinterSetup*PlexCtlTop.DuplexLandscapeIconFileName: "
207         ICON_INSTALL_DIR "lduplex.pm",
208     "*PrinterSetup*PlexCtlTop.TumblePortraitIconFileName: "
209         ICON_INSTALL_DIR "ptumble.pm",
210     "*PrinterSetup*PlexCtlTop.TumbleLandscapeIconFileName: "
211         ICON_INSTALL_DIR "ltumble.pm",
212     "*PrinterTab.compoundString: Printer",
213     "*PrinterTab.labelString: Printer"
214 };
215
216 /*
217  * Printer Setup Box static function declarations
218  */
219 static void PdmPrinterBoxDelete(PdmSetupBox* me);
220 static void PdmPrinterBoxCreate(PdmSetupBox* me, Widget parent);
221 static PdmStatus PdmPrinterBoxVerifyAttr(PdmSetupBox* me, PdmXp* pdm_xp);
222 static void PdmPrinterBoxGetAttr(PdmSetupBox* me, PdmXp* pdm_xp);
223 static void PdmPrinterBoxSetAttr(PdmSetupBox* me, PdmXp* pdm_xp);
224 static Widget PdmPrinterBoxCreateWindow(PdmSetupBox* me, Widget parent);
225 static void PdmPrinterBoxResizeCB(Widget w,
226                                   XtPointer client_data,
227                                   XtPointer call_data);
228 /*
229  * Orientation Control methods
230  */
231 static OrientCtl* OrientCtlNew(PlexCtl* plex_ctl);
232 static void OrientCtlDelete(OrientCtl* me);
233 static void OrientCtlCreate(OrientCtl* me,
234                             Widget parent,
235                             PdmOid orientation,
236                             const PdmOidList* document_attrs_supported,
237                             const PdmOidList* orientations_supported);
238 static void OrientCtlCreateWindow(OrientCtl* me, Widget parent);
239 #define OrientCtlGetWidget(me) ((me)->widget)
240 static void OrientCtlCreatePulldown(OrientCtl* me);
241 static void OrientCtlDisable(OrientCtl* me);
242 static void OrientCtlUpdateIcon(OrientCtl* me);
243 static PdmOid OrientCtlGetOrientation(OrientCtl* me);
244 static void OrientCtlResizeCB(Widget w,
245                               XtPointer client_data, XtPointer call_data);
246 static void OrientCtlSetSelectedItem(OrientCtl* me, int selected_item);
247 static void OrientCtlSelectCB(Widget w, XtPointer client_d, XtPointer call_d);
248 static void OrientCtlInitPixmapList(OrientCtl* me);
249
250 /*
251  * Plex Control methods
252  */
253 static PlexCtl* PlexCtlNew();
254 static void PlexCtlDelete(PlexCtl* me);
255 static void PlexCtlCreate(PlexCtl* me,
256                           Widget parent,
257                           PdmOid plex,
258                           const PdmOidList* document_attrs_supported,
259                           const PdmOidList* plexes_supported);
260 static void PlexCtlCreateWindow(PlexCtl* me, Widget parent);
261 static void PlexCtlDisable(PlexCtl* me);
262 #define PlexCtlGetWidget(me) ((me)->widget)
263 static void PlexCtlCreatePulldown(PlexCtl* me);
264 static void PlexCtlUpdateIcon(PlexCtl* me);
265 static PdmOid PlexCtlGetPlex(PlexCtl* me);
266 static void PlexCtlResizeCB(Widget w,
267                             XtPointer client_data, XtPointer call_data);
268 static void PlexCtlSetSelectedItem(PlexCtl* me, int selected_item);
269 static void PlexCtlSelectCB(Widget w, XtPointer client_d, XtPointer call_d);
270 static void PlexCtlSetOrientation(PlexCtl* me, PdmOid orientation);
271 static void PlexCtlInitPixmapLists(PlexCtl* me);
272
273 /*
274  * Tray Control methods
275  */
276 static TrayCtl* TrayCtlNew(SizeCtl* size_ctl);
277 static void TrayCtlDelete(TrayCtl* me);
278 static void TrayCtlCreate(TrayCtl* me,
279                           Widget parent,
280                           PdmOid default_input_tray,
281                           PdmOid default_medium,
282                           const PdmOidList* document_attrs_supported,
283                           const PdmOidList* input_trays,
284                           const PdmOidList* tray_sizes);
285 static void TrayCtlCreateWindow(TrayCtl* me, Widget parent);
286 #define TrayCtlGetWidget(me) ((me)->widget)
287 static PdmOid TrayCtlGetTray(TrayCtl* me);
288 static void TrayCtlDisable(TrayCtl* me);
289 static void TrayCtlResizeCB(Widget w,
290                             XtPointer client_data, XtPointer call_data);
291 static void TrayCtlCreatePulldown(TrayCtl* me);
292 static void TrayCtlSetSelectedItem(TrayCtl* me, int selected_item);
293 static void TrayCtlSelectCB(Widget w, XtPointer client_d, XtPointer call_d);
294
295 /*
296  * Size Control methods
297  */
298 static SizeCtl* SizeCtlNew();
299 static void SizeCtlDelete(SizeCtl* me);
300 static int SizeCtlStrColl(void* e1, void* e2);
301 static void SizeCtlSetSizeLists(PdmOidList** oids,
302                                 XmStringTable* xmstrs,
303                                 PdmOidLinkedList* oids_ll);
304 static void SizeCtlCreate(SizeCtl* me,
305                           Widget parent,
306                           PdmOid default_medium,
307                           const PdmOidList* document_attrs_supported,
308                           const PdmOidList* tray_sizes,
309                           PdmOidLinkedList* sizes_supported);
310 static void SizeCtlCreateWindow(SizeCtl* me, Widget parent);
311 #define SizeCtlGetWidget(me) ((me)->widget)
312 static void SizeCtlUpdate(SizeCtl* me);
313 static PdmOid SizeCtlGetSize(SizeCtl* me);
314 static void SizeCtlResizeCB(Widget w,
315                             XtPointer client_data, XtPointer call_data);
316 static void SizeCtlSetSingleSizeMode(SizeCtl* me, PdmOid size);
317 static void SizeCtlSetMultiSizeMode(SizeCtl* me);
318 static void SizeCtlReadyChangedCB(Widget w,
319                                   XtPointer client_data, XtPointer call_data);
320 static void SizeCtlSupportedChangedCB(Widget w,
321                                       XtPointer client_data,
322                                       XtPointer call_data);
323 static void SizeCtlSelectCB(Widget w,
324                             XtPointer client_data,
325                             XtPointer call_data);
326 /*
327  * pixmap list functions
328  */
329 static PdmPixmapList* PdmPixmapListNew(int count, Widget w, Boolean stipple);
330 static void PdmPixmapListDelete(PdmPixmapList* me);
331 static Pixmap PdmPixmapListGetPixmap(PdmPixmapList* me, int i);
332 #define PdmPixmapListCount(me) ((me)->count)
333 static void PdmPixmapListSetImageName(PdmPixmapList* me,
334                                       const char* name,
335                                       int i);
336
337 /*
338  * option menu list creation function
339  */
340 static Widget
341 CreateOptionMenuPulldown(String pulldown_name,
342                          Widget option_menu,
343                          XtCallbackProc activate_proc,
344                          XtPointer user_data,
345                          XmString* item_list,
346                          int item_count,
347                          int initial_item);
348 /*
349  * XmString / oid utilities
350  */
351 static XmString* CreateXmStringsFromOidList(const PdmOidList* list);
352 static void FreeXmStringList(XmString* list, int count);
353
354 /*
355  * utility to help determine maximum icon size
356  */
357 static void
358 IconMaxDimension(Widget icon_label,
359                  PdmPixmapList* pixmap_list, int i,
360                  Dimension* max_width, Dimension* max_height);
361
362 /*
363  * utility to position list box initial selection
364  */
365 static void SetListBoxSelection(Widget list_box, int position);
366
367 /*
368  * utility to grab icon file names out of the Xrm resource database
369  */
370 static String GetIconFileName(Widget w, String resource_name);
371
372 /*
373  * ------------------------------------------------------------------------
374  * Name: PdmPrinterBoxNew
375  *
376  * Description:
377  *
378  *     Creates a new PdmPrinterBox (PdmSetupBox) instance structure.
379  *
380  * Return value:
381  *
382  *     The new PdmPrinterBox instance structure.
383  *
384  */
385 PdmSetupBox*
386 PdmPrinterBoxNew()
387 {
388     PdmSetupBox* me = (PdmSetupBox*)XtCalloc(1, sizeof(PdmSetupBox));
389     PdmPrinterBoxData* data;
390     
391     me->delete_proc = PdmPrinterBoxDelete;
392     me->create_proc = PdmPrinterBoxCreate;
393     me->verify_attr_proc = PdmPrinterBoxVerifyAttr;
394     me->get_attr_proc = PdmPrinterBoxGetAttr;
395     me->set_attr_proc = PdmPrinterBoxSetAttr;
396     me->fallback_resources = PdmPrinterBoxFallbackResources;
397     me->fallback_resources_count = XtNumber(PdmPrinterBoxFallbackResources);
398     me->tab_name = "PrinterTab";
399
400     me->subclass_data = (XtPointer)XtCalloc(1, sizeof(PdmPrinterBoxData));
401     data = (PdmPrinterBoxData*)me->subclass_data;
402     
403     data->plex_ctl = PlexCtlNew();
404     data->orient_ctl = OrientCtlNew(data->plex_ctl);
405
406     data->size_ctl = SizeCtlNew();
407     data->tray_ctl = TrayCtlNew(data->size_ctl);
408
409     return me;
410 }
411
412 /*
413  * ------------------------------------------------------------------------
414  * Name: PdmPrinterBoxDelete
415  *
416  * Description:
417  *
418  *     Frees the passed PdmPrinterBox (PdmSetupBox) instance structure.
419  *
420  * Return value:
421  *
422  *     None.
423  *
424  */
425 static void
426 PdmPrinterBoxDelete(PdmSetupBox* me)
427 {
428     if(me != (PdmSetupBox*)NULL)
429     {
430         PdmPrinterBoxData* data = (PdmPrinterBoxData*)me->subclass_data;
431
432         XtFree(data->document_format);
433         
434         PdmOidListDelete(data->document_attrs_supported);
435         PdmOidListDelete(data->orientations_supported);
436         PdmOidListDelete(data->plexes_supported);
437         PdmOidListDelete(data->input_trays);
438         PdmOidListDelete(data->tray_sizes);
439         PdmOidLinkedListDelete(data->sizes_supported);
440         
441         OrientCtlDelete(data->orient_ctl);
442         PlexCtlDelete(data->plex_ctl);
443         SizeCtlDelete(data->size_ctl);
444         TrayCtlDelete(data->tray_ctl);
445         
446         XtFree((char*)data);
447         XtFree((char*)me);
448     }
449 }
450
451 /*
452  * ------------------------------------------------------------------------
453  * Name: PdmPrinterBoxCreate
454  *
455  * Description:
456  *
457  *     Creates the PDM Printer options setup box.
458  *
459  * Return value:
460  *
461  *     The passed PdmPrinterBox (PdmSetupBox) instance structure.
462  *
463  */
464 static void
465 PdmPrinterBoxCreate(PdmSetupBox* me, Widget parent)
466 {
467     me->widget = PdmPrinterBoxCreateWindow(me, parent);
468     XtManageChild(me->widget);
469 }
470
471 /*
472  * ------------------------------------------------------------------------
473  * Name: PdmPrinterBoxVerifyAttr
474  *
475  * Description:
476  *
477  *     
478  *
479  * Return value:
480  *
481  *     PDM_SUCCESS if all of the Printer options selected are OK.
482  *
483  *     PDM_FAILURE if any of the Printer options are invalid.
484  *
485  */
486 static PdmStatus
487 PdmPrinterBoxVerifyAttr(PdmSetupBox* me, PdmXp* pdm_xp)
488 {
489     return PDM_SUCCESS;
490 }
491
492 /*
493  * ------------------------------------------------------------------------
494  * Name: PdmPrinterBoxGetAttr
495  *
496  * Description:
497  *
498  *     
499  *
500  * Return value:
501  *
502  *     None.
503  *
504  */
505 static void
506 PdmPrinterBoxGetAttr(PdmSetupBox* me, PdmXp* pdm_xp)
507 {
508     PdmPrinterBoxData* data = (PdmPrinterBoxData*)me->subclass_data;
509     const char* strval;
510     PdmOidMediumSS* medium_ss_supported;
511     PdmOidTrayMediumList* input_trays_medium;
512     /*
513      * printer model description
514      */
515     data->printer_model =
516         PdmXpGetStringValue(pdm_xp, XPPrinterAttr, pdmoid_att_printer_model);
517     /*
518      * document format
519      */
520     strval = PdmXpGetStringValue(pdm_xp, XPDocAttr,
521                                  pdmoid_att_document_format);
522     data->document_format = PdmOidDocumentFormatParse(strval);
523     if((char*)NULL == data->document_format)
524     {
525         /*
526          * document format not specified, try to obtain
527          * document-formats-supported, and obtain up the default from it
528          */
529         strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
530                                      pdmoid_att_document_formats_supported);
531         data->document_format = PdmOidDocumentFormatDefault(strval);
532     }
533     /*
534      * document attributes supported
535      */
536     strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
537                                  pdmoid_att_document_attributes_supported);
538     data->document_attrs_supported = PdmOidListNew(strval);
539     /*
540      * content orientation supported
541      */
542     strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
543                                  pdmoid_att_content_orientations_supported);
544     data->orientations_supported = PdmOidListNew(strval);
545     /*
546      * orientation
547      */
548     data->orientation =
549         PdmXpGetValue(pdm_xp, XPDocAttr, pdmoid_att_content_orientation);
550     /*
551      * plexes supported
552      */
553     strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
554                                  pdmoid_att_plexes_supported);
555     data->plexes_supported = PdmOidListNew(strval);
556     /*
557      * plex
558      */
559     data->plex = PdmXpGetValue(pdm_xp, XPDocAttr, pdmoid_att_plex);
560     /*
561      * default input tray, default medium
562      */
563     data->default_input_tray =
564         PdmXpGetValue(pdm_xp, XPDocAttr, pdmoid_att_default_input_tray);
565     data->default_medium =
566         PdmXpGetValue(pdm_xp, XPDocAttr, pdmoid_att_default_medium);
567     /*
568      * medium source sizes supported
569      */
570     strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
571                                  pdmoid_att_medium_source_sizes_supported);
572     medium_ss_supported = PdmOidMediumSSNew(strval);
573     /*
574      * input trays medium
575      */
576     strval = PdmXpGetStringValue(pdm_xp, XPPrinterAttr,
577                                  pdmoid_att_input_trays_medium);
578     input_trays_medium = PdmOidTrayMediumListNew(strval);
579     /*
580      * build input trays and page sizes ready lists
581      */
582     PdmOidMediumSSGetTraysSizes(medium_ss_supported, input_trays_medium,
583                                 &data->input_trays, &data->tray_sizes);
584     /*
585      * build list of supported page sizes
586      */
587     data->sizes_supported = PdmOidMediumSSGetAllSizes(medium_ss_supported);
588     /*
589      * clean up
590      */
591     PdmOidMediumSSDelete(medium_ss_supported);
592     PdmOidTrayMediumListDelete(input_trays_medium);
593 }
594
595 /*
596  * ------------------------------------------------------------------------
597  * Name: PdmPrinterBoxSetAttr
598  *
599  * Description:
600  *
601  *     
602  *
603  * Return value:
604  *
605  *     None.
606  *
607  */
608 static void
609 PdmPrinterBoxSetAttr(PdmSetupBox* me, PdmXp* pdm_xp)
610 {
611     PdmPrinterBoxData* data = (PdmPrinterBoxData*)me->subclass_data;
612     /*
613      * orientation
614      */
615     PdmXpSetValue(pdm_xp, XPDocAttr, pdmoid_att_content_orientation,
616                   OrientCtlGetOrientation(data->orient_ctl));
617     /*
618      * plex
619      */
620     PdmXpSetValue(pdm_xp, XPDocAttr, pdmoid_att_plex,
621                   PlexCtlGetPlex(data->plex_ctl));
622     /*
623      * page size
624      */
625     PdmXpSetValue(pdm_xp, XPDocAttr, pdmoid_att_default_medium,
626                   SizeCtlGetSize(data->size_ctl));
627     /*
628      * input tray
629      */
630     PdmXpSetValue(pdm_xp, XPDocAttr, pdmoid_att_default_input_tray,
631                   TrayCtlGetTray(data->tray_ctl));
632 }
633
634 /*
635  * ------------------------------------------------------------------------
636  * Name: PdmPrinterBoxCreateWindow
637  *
638  * Description:
639  *
640  *     Creates the PDM Printer options setup box window.
641  *
642  * Return value:
643  *
644  *     Widget ID of the new Printer setup box.
645  *
646  */
647 static Widget
648 PdmPrinterBoxCreateWindow(PdmSetupBox* me, Widget parent)
649 {
650     PdmPrinterBoxData* data = (PdmPrinterBoxData*)me->subclass_data;
651     Widget manager;
652     Widget row;
653     Widget w;
654     Widget draw_area;
655     XmString label;
656     /*
657      * create the manager for the Printer Setup Box
658      */
659     manager = XtVaCreateManagedWidget(
660                                       "PrinterSetup",
661                                       xmRowColumnWidgetClass,
662                                       parent,
663                                       NULL);
664     /*
665      * create the printer model row
666      */
667     if(data->printer_model != (const char*)NULL)
668     {
669         char* desc;
670         char* ptr;
671
672         row = XtVaCreateManagedWidget(
673                                       "PrinterModelRow",
674                                       xmRowColumnWidgetClass,
675                                       manager,
676                                       XmNorientation, XmHORIZONTAL,
677                                       NULL);
678         /*
679          * create the printer model label
680          */
681         w = XtVaCreateManagedWidget("PrinterModelLabel",
682                                     xmLabelGadgetClass,
683                                     row,
684                                     NULL);
685         /*
686          * create the printer model using just the 1st line
687          */
688         desc = XtNewString(data->printer_model);
689         ptr = Dt_strchr(desc, '\n');
690         if(ptr != NULL)
691             *ptr = '\0';
692         label = XmStringCreateLocalized(desc);
693         XtFree(desc);
694         w = XtVaCreateManagedWidget("PrinterModel",
695                                     xmLabelGadgetClass,
696                                     row,
697                                     XmNlabelString, label,
698                                     NULL);
699         XmStringFree(label);
700     }
701     /*
702      * create the document format row
703      */
704     if((char*)NULL != data->document_format)
705     {
706         /*
707          * create the document format row
708          */
709         row = XtVaCreateManagedWidget(
710                                       "DocumentFormatRow",
711                                       xmRowColumnWidgetClass,
712                                       manager,
713                                       XmNorientation, XmHORIZONTAL,
714                                       NULL);
715         /*
716          * create the document format label
717          */
718         w = XtVaCreateManagedWidget("DocumentFormatLabel",
719                                     xmLabelGadgetClass,
720                                     row,
721                                     NULL);
722         /*
723          * create the document format
724          */
725         label = XmStringCreateLocalized(data->document_format);
726         w = XtVaCreateManagedWidget("DocumentFormat",
727                                     xmLabelGadgetClass,
728                                     row,
729                                     XmNlabelString, label,
730                                     NULL);
731         XmStringFree(label);
732     }
733     /*
734      * orientation / plex / tray / sides
735      */
736     draw_area = XtVaCreateWidget("PrinterSetupControls",
737                                  xmDrawingAreaWidgetClass,
738                                  manager,
739                                  NULL);
740     XtAddCallback(draw_area, XmNresizeCallback,
741                   PdmPrinterBoxResizeCB, (XtPointer)me);
742     /*
743      * orientation control
744      */
745     OrientCtlCreate(data->orient_ctl,
746                     draw_area,
747                     data->orientation,
748                     data->document_attrs_supported,
749                     data->orientations_supported);
750     /*
751      * page size control
752      */
753     SizeCtlCreate(data->size_ctl,
754                   draw_area,
755                   data->default_medium,
756                   data->document_attrs_supported,
757                   data->tray_sizes,
758                   data->sizes_supported);
759     /*
760      * plex control
761      */
762     PlexCtlCreate(data->plex_ctl,
763                   draw_area,
764                   data->plex,
765                   data->document_attrs_supported,
766                   data->plexes_supported);
767     /*
768      * input tray control
769      */
770     TrayCtlCreate(data->tray_ctl,
771                   draw_area,
772                   data->default_input_tray,
773                   data->default_medium,
774                   data->document_attrs_supported,
775                   data->input_trays,
776                   data->tray_sizes);
777
778     XtManageChild(draw_area);
779     /*
780      * return the new Printer Setup Box
781      */
782     return manager;
783 }
784
785 /*
786  * ------------------------------------------------------------------------
787  * Name: PdmPrinterBoxResizeCB
788  *
789  * Description:
790  *
791  *     
792  *
793  * Return value:
794  *
795  *     None.
796  *
797  */
798 static void
799 PdmPrinterBoxResizeCB(Widget w,
800                       XtPointer client_data,
801                       XtPointer call_data)
802 {
803     PdmSetupBox* me = (PdmSetupBox*)client_data;
804     PdmPrinterBoxData* data = (PdmPrinterBoxData*)me->subclass_data;
805     typedef struct {
806         Position x, y;
807         Dimension width, height;
808     } PdmRect;
809     PdmRect rt, rs, ro, rp, c1, c2, r1, r2;
810     /*
811      * retrieve child dimensions
812      */
813     XtVaGetValues(TrayCtlGetWidget(data->tray_ctl),
814                   XmNx, &rt.x,
815                   XmNy, &rt.y,
816                   XmNwidth, &rt.width,
817                   XmNheight, &rt.height,
818                   NULL);
819     XtVaGetValues(SizeCtlGetWidget(data->size_ctl),
820                   XmNx, &rs.x,
821                   XmNy, &rs.y,
822                   XmNwidth, &rs.width,
823                   XmNheight, &rs.height,
824                   NULL);
825     XtVaGetValues(OrientCtlGetWidget(data->orient_ctl),
826                   XmNx, &ro.x,
827                   XmNy, &ro.y,
828                   XmNwidth, &ro.width,
829                   XmNheight, &ro.height,
830                   NULL);
831     XtVaGetValues(PlexCtlGetWidget(data->plex_ctl),
832                   XmNx, &rp.x,
833                   XmNy, &rp.y,
834                   XmNwidth, &rp.width,
835                   XmNheight, &rp.height,
836                   NULL);
837     /*
838      * calculate rows and columns dimensions
839      */
840     r1.x = r2.x = c1.x = 0;
841     r1.y = c1.y = c2.y = 0;
842     r1.height = MAX(ro.height, rp.height);
843     r2.height = MAX(rs.height, rt.height);
844     c1.width = MAX(ro.width, rs.width);
845     c2.width = MAX(rp.width, rt.width);
846     r2.y = r1.height + 5;
847     c2.x = c1.width + 3;
848     r1.width = r2.width = c2.x + c2.width;
849     c1.height = c2.height = r2.y + r2.height;
850     /*
851      * position the children
852      */
853     XtVaSetValues(OrientCtlGetWidget(data->orient_ctl),
854                   XmNx, c1.x,
855                   XmNy, r1.y,
856                   XmNwidth, c1.width,
857                   XmNheight, r1.height,
858                   NULL);
859     XtVaSetValues(PlexCtlGetWidget(data->plex_ctl),
860                   XmNx, c2.x,
861                   XmNy, r1.y,
862                   XmNwidth, c2.width,
863                   XmNheight, r1.height,
864                   NULL);
865     XtVaSetValues(SizeCtlGetWidget(data->size_ctl),
866                   XmNx, c1.x,
867                   XmNy, r2.y,
868                   XmNwidth, c1.width,
869                   XmNheight, r2.height,
870                   NULL);
871     XtVaSetValues(TrayCtlGetWidget(data->tray_ctl),
872                   XmNx, c2.x,
873                   XmNy, r2.y,
874                   XmNwidth, c2.width,
875                   XmNheight, r2.height,
876                   NULL);
877     /*
878      * resize the drawing area to accomodate the new layout
879      */
880     XtVaSetValues(w,
881                   XmNwidth, r1.width,
882                   XmNheight, c1.height,
883                   NULL);
884 }
885
886 /*
887  * ------------------------------------------------------------------------
888  * Name: OrientCtlNew
889  *
890  * Description:
891  *
892  *     
893  *
894  * Return value:
895  *
896  *     
897  *
898  */
899 static OrientCtl*
900 OrientCtlNew(PlexCtl* plex_ctl)
901 {
902     OrientCtl* me = (OrientCtl*)XtCalloc(1, sizeof(OrientCtl));
903     me->plex_ctl = plex_ctl;
904     return me;
905 }
906
907 /*
908  * ------------------------------------------------------------------------
909  * Name: OrientCtlDelete
910  *
911  * Description:
912  *
913  *     
914  *
915  * Return value:
916  *
917  *     
918  *
919  */
920 static void
921 OrientCtlDelete(OrientCtl* me)
922 {
923     PdmOidListDelete(me->dummy_orientations_supported);
924     PdmPixmapListDelete(me->pixmap_list);
925     PdmPixmapListDelete(me->i_pixmap_list);
926     
927     XtFree((char*)me);
928 }
929
930 /*
931  * ------------------------------------------------------------------------
932  * Name: OrientCtlCreate
933  *
934  * Description:
935  *
936  *     
937  *
938  * Return value:
939  *
940  *     
941  *
942  */
943 static void
944 OrientCtlCreate(OrientCtl* me,
945                 Widget parent,
946                 PdmOid orientation,
947                 const PdmOidList* document_attrs_supported,
948                 const PdmOidList* orientations_supported)
949 {
950     Boolean supported;
951     /*
952      * determine if setting the content orientation is supported
953      */
954     if(PdmOidListHasOid(document_attrs_supported,
955                         pdmoid_att_content_orientation)
956        &&
957        PdmOidListCount(orientations_supported) > 0)
958     {
959         supported = True;
960         me->orientations_supported = orientations_supported;
961     }
962     else
963     {
964         supported = False;
965         /*
966          * dummy up a list to be presented (insensitive)
967          */
968         me->dummy_orientations_supported = 
969           PdmOidListNew(PdmOidString(pdmoid_val_content_orientation_portrait));
970         me->orientations_supported = me->dummy_orientations_supported;
971         orientation = pdmoid_none;
972     }
973     /*
974      * set the initially selected list item
975      */
976     OrientCtlSetSelectedItem(me,
977                              PdmOidListGetIndex(me->orientations_supported,
978                                                 orientation));
979     /*
980      * create the orientations control window
981      */
982     OrientCtlCreateWindow(me, parent);
983     /*
984      * initialize the window components
985      */
986     OrientCtlCreatePulldown(me);
987     OrientCtlInitPixmapList(me);
988     OrientCtlUpdateIcon(me);
989     /*
990      * if content-orientation is not supported, disable the control
991      */
992     if(!supported)
993         OrientCtlDisable(me);
994 }
995
996 /*
997  * ------------------------------------------------------------------------
998  * Name: OrientCtlCreateWindow
999  *
1000  * Description:
1001  *
1002  *     
1003  *
1004  * Return value:
1005  *
1006  *     
1007  *
1008  */
1009 static void
1010 OrientCtlCreateWindow(OrientCtl* me,
1011                       Widget parent)
1012 {
1013     Widget control_manager;
1014     
1015     /*
1016      * orientation frame
1017      */
1018     me->widget = XtVaCreateManagedWidget("OrientCtlTop",
1019                                          xmFrameWidgetClass,
1020                                          parent,
1021                                          XmNshadowType, XmSHADOW_ETCHED_IN,
1022                                          NULL);
1023     /*
1024      * orientation label
1025      */
1026     me->frame_label =
1027         XtVaCreateManagedWidget("OrientationLabel",
1028                                 xmLabelWidgetClass,
1029                                 me->widget,
1030                                 XmNframeChildType, XmFRAME_TITLE_CHILD,
1031                                 NULL);
1032     /*
1033      * orientation controls manager
1034      */
1035     control_manager =
1036         XtVaCreateManagedWidget("OrientationControls",
1037                                 xmDrawingAreaWidgetClass,
1038                                 me->widget,
1039                                 XmNframeChildType, XmFRAME_WORKAREA_CHILD,
1040                                 NULL);
1041     XtAddCallback(control_manager, XmNresizeCallback, OrientCtlResizeCB, me);
1042     /*
1043      * orientations option menu
1044      */
1045     me->option_menu =
1046         XtVaCreateManagedWidget("OrientationOptionMenu",
1047                                 xmRowColumnWidgetClass,
1048                                 control_manager,
1049                                 XmNmarginHeight, 0,
1050                                 XmNrowColumnType, XmMENU_OPTION,
1051                                 NULL);
1052     /*
1053      * orientation icon
1054      */
1055     me->icon_label =
1056         XtVaCreateManagedWidget("OrientationIcon",
1057                                 xmLabelWidgetClass,
1058                                 control_manager,
1059                                 XmNlabelType, XmPIXMAP,
1060                                 XmNalignment, XmALIGNMENT_CENTER,
1061                                 NULL);
1062 }
1063
1064 /*
1065  * ------------------------------------------------------------------------
1066  * Name: OrientCtlDisable
1067  *
1068  * Description:
1069  *
1070  *     Disable the orientation controls.
1071  *
1072  * Return value:
1073  *
1074  *     None.
1075  *
1076  */
1077 static void
1078 OrientCtlDisable(OrientCtl* me)
1079 {
1080     XtSetSensitive(me->frame_label, False);
1081     XtSetSensitive(me->option_menu, False);
1082     XtSetSensitive(me->icon_label, False);
1083 }
1084
1085 /*
1086  * ------------------------------------------------------------------------
1087  * Name: OrientCtlResizeCB
1088  *
1089  * Description:
1090  *
1091  *     
1092  *
1093  * Return value:
1094  *
1095  *     None.
1096  *
1097  */
1098 static void
1099 OrientCtlResizeCB(Widget w, XtPointer client_data, XtPointer call_data)
1100 {
1101     OrientCtl* me = (OrientCtl*)client_data;
1102     Dimension height, width, margin_width, new_width;
1103     Position menu_x, menu_y, icon_x, icon_y;
1104     Dimension menu_h, menu_w, icon_h, icon_w;
1105     /*
1106      * get current layout info
1107      */
1108     XtVaGetValues(w, XmNheight, &height, XmNwidth, &width,
1109                   XmNmarginWidth, &margin_width,
1110                   NULL);
1111     XtVaGetValues(me->option_menu, XmNheight, &menu_h, XmNwidth, &menu_w,
1112                   NULL);
1113     XtVaGetValues(me->icon_label, XmNheight, &icon_h, XmNwidth, &icon_w,
1114                   NULL);
1115     /*
1116      * position controls side by side
1117      */
1118     menu_x = 0;
1119     icon_x = menu_x + menu_w;
1120     /*
1121      * center vertically
1122      */
1123     menu_y = (height - menu_h) / 2;
1124     icon_y = (height - icon_h) / 2;
1125     /*
1126      * set new positions
1127      */
1128     XtVaSetValues(me->option_menu, XmNx, menu_x, XmNy, menu_y, NULL);
1129     XtVaSetValues(me->icon_label, XmNx, icon_x, XmNy, icon_y, NULL);
1130     /*
1131      * update drawing area width
1132      */
1133     new_width = menu_x + menu_w + icon_w + margin_width;
1134     if(new_width > width)
1135         XtVaSetValues(w, XmNwidth, new_width, NULL);
1136 }
1137
1138 /*
1139  * ------------------------------------------------------------------------
1140  * Name: OrientCtlCreatePulldown
1141  *
1142  * Description:
1143  *
1144  *     
1145  *
1146  * Return value:
1147  *
1148  *     
1149  *
1150  */
1151 static void
1152 OrientCtlCreatePulldown(OrientCtl* me)
1153 {
1154     XmString* list;
1155     int count;
1156     /*
1157      * create a list of XmStrings for the content orientations
1158      */
1159     list = CreateXmStringsFromOidList(me->orientations_supported);
1160     /*
1161      * create the option menu pulldown
1162      */
1163     count = PdmOidListCount(me->orientations_supported);
1164     CreateOptionMenuPulldown("OrientationOptions",
1165                              me->option_menu,
1166                              OrientCtlSelectCB,
1167                              (XtPointer)me,
1168                              list, count,
1169                              me->selected_item);
1170     /*
1171      * clean up
1172      */
1173     FreeXmStringList(list, count);
1174 }
1175
1176 /*
1177  * ------------------------------------------------------------------------
1178  * Name: OrientCtlSelectCB
1179  *
1180  * Description:
1181  *
1182  *     
1183  *
1184  * Return value:
1185  *
1186  *     
1187  *
1188  */
1189 static void
1190 OrientCtlSelectCB(Widget w, XtPointer client_data, XtPointer call_data)
1191 {
1192     OrientCtl* me;
1193     int selected_item = (int)client_data;
1194
1195     XtVaGetValues(w, XmNuserData, &me, NULL);
1196     OrientCtlSetSelectedItem(me, selected_item);
1197     OrientCtlUpdateIcon(me);
1198 }
1199
1200 /*
1201  * ------------------------------------------------------------------------
1202  * Name: OrientCtlInitPixmapList
1203  *
1204  * Description:
1205  *
1206  *     
1207  *
1208  * Return value:
1209  *
1210  *     
1211  *
1212  */
1213 static void
1214 OrientCtlInitPixmapList(OrientCtl* me)
1215 {
1216     int i;
1217     const char* image_name;
1218     int count;
1219     Dimension max_width = 0;
1220     Dimension max_height = 0;
1221     
1222     /*
1223      * initialize the list of pixmaps based on the supported orientations
1224      */
1225     count = PdmOidListCount(me->orientations_supported);
1226     me->pixmap_list = PdmPixmapListNew(count, me->icon_label, False);
1227     me->i_pixmap_list = PdmPixmapListNew(count, me->icon_label, True);
1228     for(i = 0; i < count; i++)
1229     {
1230         switch(PdmOidListGetOid(me->orientations_supported, i))
1231         {
1232         case pdmoid_val_content_orientation_portrait:
1233             image_name = GetIconFileName(me->widget, "PortraitIconFileName");
1234             break;
1235         case pdmoid_val_content_orientation_landscape:
1236             image_name = GetIconFileName(me->widget, "LandscapeIconFileName");
1237             break;
1238         case pdmoid_val_content_orientation_reverse_portrait:
1239             image_name =
1240                 GetIconFileName(me->widget, "ReversePortraitIconFileName");
1241             break;
1242         case pdmoid_val_content_orientation_reverse_landscape:
1243             image_name =
1244                 GetIconFileName(me->widget, "ReverseLandscapeIconFileName");
1245             break;
1246         default:
1247             continue;
1248         }
1249         PdmPixmapListSetImageName(me->pixmap_list, image_name, i);
1250         PdmPixmapListSetImageName(me->i_pixmap_list, image_name, i);
1251         IconMaxDimension(me->icon_label,
1252                          me->pixmap_list, i,
1253                          &max_width, &max_height);
1254     }
1255     XtVaSetValues(me->icon_label,
1256                   XmNwidth, max_width,
1257                   XmNheight, max_height,
1258                   XmNrecomputeSize, False,
1259                   NULL);
1260 }
1261
1262 /*
1263  * ------------------------------------------------------------------------
1264  * Name: OrientCtlSetSelectedItem
1265  *
1266  * Description:
1267  *
1268  *     
1269  *
1270  * Return value:
1271  *
1272  *     
1273  *
1274  */
1275 static void
1276 OrientCtlSetSelectedItem(OrientCtl* me, int selected_item)
1277 {
1278     if(selected_item == -1)
1279         me->selected_item = 0;
1280     else
1281         me->selected_item = selected_item;
1282
1283     if(me->plex_ctl != (PlexCtl*)NULL)
1284         PlexCtlSetOrientation(me->plex_ctl, OrientCtlGetOrientation(me));
1285 }
1286
1287
1288 /*
1289  * ------------------------------------------------------------------------
1290  * Name: OrientCtlUpdateIcon
1291  *
1292  * Description:
1293  *
1294  *     
1295  *
1296  * Return value:
1297  *
1298  *     
1299  *
1300  */
1301 static void
1302 OrientCtlUpdateIcon(OrientCtl* me)
1303 {
1304     if(me->icon_label != (Widget)NULL)
1305         XtVaSetValues(me->icon_label,
1306                       XmNlabelPixmap,
1307                       PdmPixmapListGetPixmap(me->pixmap_list,
1308                                              me->selected_item),
1309                       XmNlabelInsensitivePixmap,
1310                       PdmPixmapListGetPixmap(me->i_pixmap_list,
1311                                              me->selected_item),
1312                       NULL);
1313 }
1314
1315 /*
1316  * ------------------------------------------------------------------------
1317  * Name: OrientCtlGetOrientation
1318  *
1319  * Description:
1320  *
1321  *     
1322  *
1323  * Return value:
1324  *
1325  *     
1326  *
1327  */
1328 static PdmOid
1329 OrientCtlGetOrientation(OrientCtl* me)
1330 {
1331     if(me->orientations_supported == me->dummy_orientations_supported)
1332         return pdmoid_none;
1333     else
1334         return PdmOidListGetOid(me->orientations_supported, me->selected_item);
1335 }
1336
1337
1338 /*
1339  * ------------------------------------------------------------------------
1340  * Name: PlexCtlNew
1341  *
1342  * Description:
1343  *
1344  *     
1345  *
1346  * Return value:
1347  *
1348  *     
1349  *
1350  */
1351 static PlexCtl*
1352 PlexCtlNew()
1353 {
1354     PlexCtl* me = (PlexCtl*)XtCalloc(1, sizeof(PlexCtl));
1355     me->pixmap_list_ptr = &me->portrait_pixmap_list;
1356     me->i_pixmap_list_ptr = &me->i_portrait_pixmap_list;
1357     return me;
1358 }
1359
1360 /*
1361  * ------------------------------------------------------------------------
1362  * Name: PlexCtlDelete
1363  *
1364  * Description:
1365  *
1366  *     
1367  *
1368  * Return value:
1369  *
1370  *     
1371  *
1372  */
1373 static void
1374 PlexCtlDelete(PlexCtl* me)
1375 {
1376     PdmOidListDelete(me->dummy_plexes_supported);
1377     PdmPixmapListDelete(me->portrait_pixmap_list);
1378     PdmPixmapListDelete(me->i_portrait_pixmap_list);
1379     PdmPixmapListDelete(me->landscape_pixmap_list);
1380     PdmPixmapListDelete(me->i_landscape_pixmap_list);
1381     
1382     XtFree((char*)me);
1383 }
1384
1385 /*
1386  * ------------------------------------------------------------------------
1387  * Name: PlexCtlCreate
1388  *
1389  * Description:
1390  *
1391  *     
1392  *
1393  * Return value:
1394  *
1395  *     
1396  *
1397  */
1398 static void
1399 PlexCtlCreate(PlexCtl* me,
1400               Widget parent,
1401               PdmOid plex,
1402               const PdmOidList* document_attrs_supported,
1403               const PdmOidList* plexes_supported)
1404 {
1405     Boolean supported;
1406     /*
1407      * determine if setting the content orientation is supported
1408      */
1409     if(PdmOidListHasOid(document_attrs_supported, pdmoid_att_plex)
1410        &&
1411        PdmOidListCount(plexes_supported) > 0)
1412     {
1413         supported = True;
1414         me->plexes_supported = plexes_supported;
1415     }
1416     else
1417     {
1418         supported = False;
1419         /*
1420          * dummy up a list to be presented (insensitive)
1421          */
1422         me->dummy_plexes_supported = 
1423           PdmOidListNew(PdmOidString(pdmoid_val_plex_simplex));
1424         me->plexes_supported = me->dummy_plexes_supported;
1425         plex = pdmoid_none;
1426     }
1427
1428     /*
1429      * set the initially selected list item
1430      */
1431     PlexCtlSetSelectedItem(me, PdmOidListGetIndex(me->plexes_supported, plex));
1432     /*
1433      * create the plexes control window
1434      */
1435     PlexCtlCreateWindow(me, parent);
1436     /*
1437      * initialize the window components
1438      */
1439     PlexCtlCreatePulldown(me);
1440     PlexCtlInitPixmapLists(me);
1441     PlexCtlUpdateIcon(me);
1442     /*
1443      * if plex is not supported, disable the control
1444      */
1445     if(!supported)
1446         PlexCtlDisable(me);
1447 }
1448
1449 /*
1450  * ------------------------------------------------------------------------
1451  * Name: PlexCtlCreateWindow
1452  *
1453  * Description:
1454  *
1455  *     
1456  *
1457  * Return value:
1458  *
1459  *     
1460  *
1461  */
1462 static void
1463 PlexCtlCreateWindow(PlexCtl* me,
1464                       Widget parent)
1465 {
1466     Widget control_manager;
1467     /*
1468      * plex frame
1469      */
1470     me->widget = XtVaCreateManagedWidget("PlexCtlTop",
1471                                          xmFrameWidgetClass,
1472                                          parent,
1473                                          XmNshadowType, XmSHADOW_ETCHED_IN,
1474                                          NULL);
1475     /*
1476      * plex label
1477      */
1478     me->frame_label =
1479         XtVaCreateManagedWidget("PlexLabel",
1480                                 xmLabelGadgetClass,
1481                                 me->widget,
1482                                 XmNframeChildType, XmFRAME_TITLE_CHILD,
1483                                 NULL);
1484     /*
1485      * plex controls manager
1486      */
1487     control_manager =
1488         XtVaCreateManagedWidget(
1489                                 "PlexControls",
1490                                 xmDrawingAreaWidgetClass,
1491                                 me->widget,
1492                                 XmNframeChildType, XmFRAME_WORKAREA_CHILD,
1493                                 NULL);
1494     XtAddCallback(control_manager, XmNresizeCallback, PlexCtlResizeCB, me);
1495     /*
1496      * plexes option menu
1497      */
1498     me->option_menu =
1499         XtVaCreateManagedWidget("PlexOptionMenu",
1500                                 xmRowColumnWidgetClass,
1501                                 control_manager,
1502                                 XmNrowColumnType, XmMENU_OPTION,
1503                                 XmNmarginHeight, 0,
1504                                 NULL);
1505     /*
1506      * plex icon
1507      */
1508     me->icon_label =
1509         XtVaCreateManagedWidget("PlexIcon",
1510                                 xmLabelWidgetClass,
1511                                 control_manager,
1512                                 XmNlabelType, XmPIXMAP,
1513                                 XmNalignment, XmALIGNMENT_CENTER,
1514                                 NULL);
1515 }
1516
1517 /*
1518  * ------------------------------------------------------------------------
1519  * Name: PlexCtlDisable
1520  *
1521  * Description:
1522  *
1523  *     Disable the plex controls.
1524  *
1525  * Return value:
1526  *
1527  *     None.
1528  *
1529  */
1530 static void
1531 PlexCtlDisable(PlexCtl* me)
1532 {
1533     XtSetSensitive(me->frame_label, False);
1534     XtSetSensitive(me->option_menu, False);
1535     XtSetSensitive(me->icon_label, False);
1536 }
1537
1538 /*
1539  * ------------------------------------------------------------------------
1540  * Name: PlexCtlResizeCB
1541  *
1542  * Description:
1543  *
1544  *     
1545  *
1546  * Return value:
1547  *
1548  *     None.
1549  *
1550  */
1551 static void
1552 PlexCtlResizeCB(Widget w, XtPointer client_data, XtPointer call_data)
1553 {
1554     PlexCtl* me = (PlexCtl*)client_data;
1555     Dimension height, width, margin_width, new_width;
1556     Position menu_x, menu_y, icon_x, icon_y;
1557     Dimension menu_h, menu_w, icon_h, icon_w;
1558     /*
1559      * get current layout info
1560      */
1561     XtVaGetValues(w, XmNheight, &height, XmNwidth, &width,
1562                   XmNmarginWidth, &margin_width,
1563                   NULL);
1564     XtVaGetValues(me->option_menu, XmNheight, &menu_h, XmNwidth, &menu_w,
1565                   NULL);
1566     XtVaGetValues(me->icon_label, XmNheight, &icon_h, XmNwidth, &icon_w,
1567                   NULL);
1568     /*
1569      * position controls side by side
1570      */
1571     menu_x = 0;
1572     icon_x = menu_x + menu_w;
1573     /*
1574      * center vertically
1575      */
1576     menu_y = (height - menu_h) / 2;
1577     icon_y = (height - icon_h) / 2;
1578     /*
1579      * set new positions
1580      */
1581     XtVaSetValues(me->option_menu, XmNx, menu_x, XmNy, menu_y, NULL);
1582     XtVaSetValues(me->icon_label, XmNx, icon_x, XmNy, icon_y, NULL);
1583     /*
1584      * update drawing area width
1585      */
1586     new_width = menu_x + menu_w + icon_w + margin_width;
1587     if(new_width > width)
1588         XtVaSetValues(w, XmNwidth, new_width, NULL);
1589 }
1590
1591 /*
1592  * ------------------------------------------------------------------------
1593  * Name: PlexCtlCreatePulldown
1594  *
1595  * Description:
1596  *
1597  *     
1598  *
1599  * Return value:
1600  *
1601  *     
1602  *
1603  */
1604 static void
1605 PlexCtlCreatePulldown(PlexCtl* me)
1606 {
1607     XmString* list;
1608     int count;
1609     /*
1610      * build a list of Xm strings for the supported plexes
1611      */
1612     list = CreateXmStringsFromOidList(me->plexes_supported);
1613     /*
1614      * create the option menu pulldown
1615      */
1616     count = PdmOidListCount(me->plexes_supported);
1617     CreateOptionMenuPulldown("PlexOptions",
1618                              me->option_menu,
1619                              PlexCtlSelectCB,
1620                              (XtPointer)me,
1621                              list, count,
1622                              me->selected_item);
1623     /*
1624      * clean up
1625      */
1626     FreeXmStringList(list, count);
1627 }
1628
1629 /*
1630  * ------------------------------------------------------------------------
1631  * Name: PlexCtlSelectCB
1632  *
1633  * Description:
1634  *
1635  *     
1636  *
1637  * Return value:
1638  *
1639  *     
1640  *
1641  */
1642 static void
1643 PlexCtlSelectCB(Widget w, XtPointer client_data, XtPointer call_data)
1644 {
1645     PlexCtl* me;
1646     int selected_item = (int)client_data;
1647
1648     XtVaGetValues(w, XmNuserData, &me, NULL);
1649     PlexCtlSetSelectedItem(me, selected_item);
1650     PlexCtlUpdateIcon(me);
1651 }
1652
1653 /*
1654  * ------------------------------------------------------------------------
1655  * Name: PlexCtlSetOrientation
1656  *
1657  * Description:
1658  *
1659  *     
1660  *
1661  * Return value:
1662  *
1663  *     
1664  *
1665  */
1666 static void
1667 PlexCtlSetOrientation(PlexCtl* me,
1668                       PdmOid orientation)
1669 {
1670     switch(orientation)
1671     {
1672     case pdmoid_val_content_orientation_landscape:
1673     case pdmoid_val_content_orientation_reverse_landscape:
1674         me->pixmap_list_ptr = &me->landscape_pixmap_list;
1675         me->i_pixmap_list_ptr = &me->i_landscape_pixmap_list;
1676         break;
1677     default:
1678         me->pixmap_list_ptr = &me->portrait_pixmap_list;
1679         me->i_pixmap_list_ptr = &me->i_portrait_pixmap_list;
1680         break;
1681     }
1682     PlexCtlUpdateIcon(me);
1683 }
1684
1685 /*
1686  * ------------------------------------------------------------------------
1687  * Name: PlexCtlInitPixmapLists
1688  *
1689  * Description:
1690  *
1691  *     
1692  *
1693  * Return value:
1694  *
1695  *     
1696  *
1697  */
1698 static void
1699 PlexCtlInitPixmapLists(PlexCtl* me)
1700 {
1701     int i;
1702     const char* portrait_image_name;
1703     const char* landscape_image_name;
1704     int count;
1705     Dimension max_width = 0;
1706     Dimension max_height = 0;
1707     
1708     /*
1709      * initialize the list of pixmaps based on the list of plexes
1710      */
1711     count = PdmOidListCount(me->plexes_supported);
1712     me->portrait_pixmap_list = PdmPixmapListNew(count, me->icon_label, False);
1713     me->i_portrait_pixmap_list = PdmPixmapListNew(count, me->icon_label, True);
1714     me->landscape_pixmap_list = PdmPixmapListNew(count, me->icon_label, False);
1715     me->i_landscape_pixmap_list = PdmPixmapListNew(count, me->icon_label, True);
1716     for(i = 0; i < count; i++)
1717     {
1718         switch(PdmOidListGetOid(me->plexes_supported, i))
1719         {
1720         case pdmoid_val_plex_simplex:
1721             portrait_image_name =
1722                 GetIconFileName(me->widget, "SimplexPortraitIconFileName");
1723             landscape_image_name =
1724                 GetIconFileName(me->widget, "SimplexLandscapeIconFileName");
1725             break;
1726         case pdmoid_val_plex_duplex:
1727             portrait_image_name =
1728                 GetIconFileName(me->widget, "DuplexPortraitIconFileName");
1729             landscape_image_name =
1730                 GetIconFileName(me->widget, "DuplexLandscapeIconFileName");
1731             break;
1732         case pdmoid_val_plex_tumble:
1733             portrait_image_name =
1734                 GetIconFileName(me->widget, "TumblePortraitIconFileName");
1735             landscape_image_name =
1736                 GetIconFileName(me->widget, "TumbleLandscapeIconFileName");
1737             break;
1738         default:
1739             continue;
1740         }
1741         PdmPixmapListSetImageName(me->portrait_pixmap_list,
1742                                   portrait_image_name, i);
1743         PdmPixmapListSetImageName(me->i_portrait_pixmap_list,
1744                                   portrait_image_name, i);
1745         PdmPixmapListSetImageName(me->landscape_pixmap_list,
1746                                   landscape_image_name, i);
1747         PdmPixmapListSetImageName(me->i_landscape_pixmap_list,
1748                                   landscape_image_name, i);
1749         IconMaxDimension(me->icon_label,
1750                          me->portrait_pixmap_list, i,
1751                          &max_width, &max_height);
1752         IconMaxDimension(me->icon_label,
1753                          me->landscape_pixmap_list, i,
1754                          &max_width, &max_height);
1755     }
1756     XtVaSetValues(me->icon_label,
1757                   XmNwidth, max_width,
1758                   XmNheight, max_height,
1759                   XmNrecomputeSize, False,
1760                   NULL);
1761 }
1762
1763 /*
1764  * ------------------------------------------------------------------------
1765  * Name: PlexCtlSetSelectedItem
1766  *
1767  * Description:
1768  *
1769  *     
1770  *
1771  * Return value:
1772  *
1773  *     
1774  *
1775  */
1776 static void
1777 PlexCtlSetSelectedItem(PlexCtl* me, int selected_item)
1778 {
1779     if(selected_item == -1)
1780         me->selected_item = 0;
1781     else
1782         me->selected_item = selected_item;
1783 }
1784
1785 /*
1786  * ------------------------------------------------------------------------
1787  * Name: PlexCtlUpdateIcon
1788  *
1789  * Description:
1790  *
1791  *     
1792  *
1793  * Return value:
1794  *
1795  *     
1796  *
1797  */
1798 static void
1799 PlexCtlUpdateIcon(PlexCtl* me)
1800 {
1801     if(me->icon_label != (Widget)NULL)
1802         XtVaSetValues(me->icon_label,
1803                       XmNlabelPixmap,
1804                       PdmPixmapListGetPixmap(*me->pixmap_list_ptr,
1805                                              me->selected_item),
1806                       XmNlabelInsensitivePixmap,
1807                       PdmPixmapListGetPixmap(*me->i_pixmap_list_ptr,
1808                                              me->selected_item),
1809                       NULL);
1810 }
1811
1812 /*
1813  * ------------------------------------------------------------------------
1814  * Name: PlexCtlGetPlex
1815  *
1816  * Description:
1817  *
1818  *     
1819  *
1820  * Return value:
1821  *
1822  *     
1823  *
1824  */
1825 static PdmOid
1826 PlexCtlGetPlex(PlexCtl* me)
1827 {
1828     if(me->plexes_supported == me->dummy_plexes_supported)
1829         return pdmoid_none;
1830     else
1831         return PdmOidListGetOid(me->plexes_supported, me->selected_item);
1832 }
1833
1834 /*
1835  * ------------------------------------------------------------------------
1836  * Name: TrayCtlNew
1837  *
1838  * Description:
1839  *
1840  *     
1841  *
1842  * Return value:
1843  *
1844  *     
1845  *
1846  */
1847 static TrayCtl*
1848 TrayCtlNew(SizeCtl* size_ctl)
1849 {
1850     TrayCtl* me = (TrayCtl*)XtCalloc(1, sizeof(TrayCtl));
1851
1852     me->size_ctl = size_ctl;
1853
1854     return me;
1855 }
1856
1857 /*
1858  * ------------------------------------------------------------------------
1859  * Name: TrayCtlDelete
1860  *
1861  * Description:
1862  *
1863  *     
1864  *
1865  * Return value:
1866  *
1867  *     
1868  *
1869  */
1870 static void
1871 TrayCtlDelete(TrayCtl* me)
1872 {
1873     XtFree((char*)me);
1874 }
1875
1876 /*
1877  * ------------------------------------------------------------------------
1878  * Name: TrayCtlCreate
1879  *
1880  * Description:
1881  *
1882  *     
1883  *
1884  * Return value:
1885  *
1886  *     
1887  *
1888  */
1889 static void
1890 TrayCtlCreate(TrayCtl* me,
1891               Widget parent,
1892               PdmOid default_input_tray,
1893               PdmOid default_medium,
1894               const PdmOidList* document_attrs_supported,
1895               const PdmOidList* input_trays,
1896               const PdmOidList* tray_sizes)
1897 {
1898     Boolean supported;
1899     /*
1900      * save the trays and sizes list pointers
1901      */
1902     me->input_trays = input_trays;
1903     me->tray_sizes = tray_sizes;
1904     /*
1905      * determine if setting the input tray is supported
1906      */
1907     if(PdmOidListHasOid(document_attrs_supported,
1908                         pdmoid_att_default_input_tray)
1909        &&
1910        PdmOidListCount(me->input_trays) > 0)
1911     {
1912         supported = True;
1913     }
1914     else
1915         supported = False;
1916     /*
1917      * set the initially selected list item
1918      */
1919     if(default_medium != pdmoid_none)
1920     {
1921         /*
1922          * default-medium has precedence; set "Auto-select" (index 0)
1923          */
1924         TrayCtlSetSelectedItem(me, 0);
1925     }
1926     else
1927     {
1928         int i = PdmOidListGetIndex(me->input_trays, default_input_tray);
1929         if(!supported || i == -1)
1930             /*
1931              * default-input-tray unsupported or not found in list; set
1932              * "Auto-select" (index 0)
1933              */
1934             TrayCtlSetSelectedItem(me, 0);
1935         else
1936             /*
1937              * Select the list item corresponding to default-input-tray -
1938              * ie. add 1 to the input trays list index since the option
1939              * menu is always built with "Auto-select" as the first
1940              * entry, followed by the input trays list entries.
1941              */
1942             TrayCtlSetSelectedItem(me, i+1);
1943     }
1944     /*
1945      * create the tray control window
1946      */
1947     TrayCtlCreateWindow(me, parent);
1948     /*
1949      * initialize the window components
1950      */
1951     TrayCtlCreatePulldown(me);
1952     /*
1953      * if tray selection is not supported, disable the control
1954      */
1955     if(!supported)
1956         TrayCtlDisable(me);
1957 }
1958
1959 /*
1960  * ------------------------------------------------------------------------
1961  * Name: TrayCtlCreateWindow
1962  *
1963  * Description:
1964  *
1965  *     
1966  *
1967  * Return value:
1968  *
1969  *     
1970  *
1971  */
1972 static void
1973 TrayCtlCreateWindow(TrayCtl* me, Widget parent)
1974 {
1975     Widget control_manager;
1976     
1977     /*
1978      * tray frame
1979      */
1980     me->widget = XtVaCreateManagedWidget("TrayCtlTop",
1981                                          xmFrameWidgetClass,
1982                                          parent,
1983                                          XmNshadowType, XmSHADOW_ETCHED_IN,
1984                                          NULL);
1985     /*
1986      * tray label
1987      */
1988     me->frame_label
1989         = XtVaCreateManagedWidget("TrayLabel",
1990                                   xmLabelGadgetClass,
1991                                   me->widget,
1992                                   XmNframeChildType, XmFRAME_TITLE_CHILD,
1993                                   NULL);
1994     /*
1995      * tray controls manager
1996      */
1997     control_manager =
1998         XtVaCreateManagedWidget("TrayControls",
1999                                 xmDrawingAreaWidgetClass,
2000                                 me->widget,
2001                                 XmNframeChildType, XmFRAME_WORKAREA_CHILD,
2002                                 NULL);
2003     XtAddCallback(control_manager, XmNresizeCallback, TrayCtlResizeCB, me);
2004     /*
2005      * trays option menu
2006      */
2007     me->option_menu = 
2008         XtVaCreateManagedWidget("TrayOptionMenu",
2009                                 xmRowColumnWidgetClass,
2010                                 control_manager,
2011                                 XmNmarginHeight, 0,
2012                                 XmNrowColumnType, XmMENU_OPTION,
2013                                 NULL);
2014 }
2015
2016 /*
2017  * ------------------------------------------------------------------------
2018  * Name: TrayCtlDisable
2019  *
2020  * Description:
2021  *
2022  *     Disable the input tray controls.
2023  *
2024  * Return value:
2025  *
2026  *     None.
2027  *
2028  */
2029 static void
2030 TrayCtlDisable(TrayCtl* me)
2031 {
2032     XtSetSensitive(me->frame_label, False);
2033     XtSetSensitive(me->option_menu, False);
2034 }
2035
2036 /*
2037  * ------------------------------------------------------------------------
2038  * Name: TrayCtlResizeCB
2039  *
2040  * Description:
2041  *
2042  *     
2043  *
2044  * Return value:
2045  *
2046  *     None.
2047  *
2048  */
2049 static void
2050 TrayCtlResizeCB(Widget w, XtPointer client_data, XtPointer call_data)
2051 {
2052     TrayCtl* me = (TrayCtl*)client_data;
2053     Dimension height, menu_h;
2054     Position menu_y;
2055     /*
2056      * get current layout info
2057      */
2058     XtVaGetValues(w, XmNheight, &height, NULL);
2059     XtVaGetValues(me->option_menu, XmNheight, &menu_h, NULL);
2060     /*
2061      * center vertically
2062      */
2063     menu_y = (height - menu_h) / 2;
2064     /*
2065      * set new position
2066      */
2067     XtVaSetValues(me->option_menu, XmNx, 0, XmNy, menu_y, NULL);
2068 }
2069
2070 /*
2071  * ------------------------------------------------------------------------
2072  * Name: TrayCtlGetTray
2073  *
2074  * Description:
2075  *
2076  *     
2077  *
2078  * Return value:
2079  *
2080  *     
2081  *
2082  */
2083 static PdmOid
2084 TrayCtlGetTray(TrayCtl* me)
2085 {
2086     if(me->selected_item == 0)
2087         return pdmoid_none;
2088     else
2089         return PdmOidListGetOid(me->input_trays, me->selected_item - 1);
2090 }
2091
2092 /*
2093  * ------------------------------------------------------------------------
2094  * Name: TrayCtlCreatePulldown
2095  *
2096  * Description:
2097  *
2098  *     
2099  *
2100  * Return value:
2101  *
2102  *     
2103  *
2104  */
2105 static void
2106 TrayCtlCreatePulldown(TrayCtl* me)
2107 {
2108     XmString* xmstr_list;
2109     int count;
2110     PdmOid oid;
2111     const char* str;
2112     int i;
2113     /*
2114      * create a list of XmStrings for the Auto-select item plus the list
2115      * of specific trays
2116      */
2117     count = 1 + PdmOidListCount(me->input_trays);
2118     xmstr_list = (XmString*)XtCalloc(count, sizeof(XmString));
2119     /*
2120      * set the "Auto-select" item as the first item
2121      */
2122     i = 0;
2123     xmstr_list[i++] = XmStringCreateLocalized((char*)PDM_MSG_TRAY_AUTO_SELECT);
2124     /*
2125      * add the input trays
2126      */
2127     for(; i < count; i++)
2128     {
2129         oid = PdmOidListGetOid(me->input_trays, i-1);
2130         str = DTPDM_GETMESSAGE(PdmOidMsgSet(oid),
2131                                PdmOidMsgNum(oid),
2132                                PdmOidDefaultMsg(oid));
2133         xmstr_list[i] = XmStringCreateLocalized((char*)str);
2134     }
2135     /*
2136      * create the option menu pulldown
2137      */
2138     CreateOptionMenuPulldown("TrayOptions",
2139                              me->option_menu,
2140                              TrayCtlSelectCB,
2141                              (XtPointer)me,
2142                              xmstr_list, count,
2143                              me->selected_item);
2144     /*
2145      * clean up
2146      */
2147     FreeXmStringList(xmstr_list, count);
2148 }
2149
2150 /*
2151  * ------------------------------------------------------------------------
2152  * Name: TrayCtlSetSelectedItem
2153  *
2154  * Description:
2155  *
2156  *     
2157  *
2158  * Return value:
2159  *
2160  *     
2161  *
2162  */
2163 static void
2164 TrayCtlSetSelectedItem(TrayCtl* me, int selected_item)
2165 {
2166     if(selected_item == -1)
2167         me->selected_item = 0;
2168     else
2169         me->selected_item = selected_item;
2170     /*
2171      * update the page size control accordingly
2172      */
2173     if(me->selected_item == 0)
2174         SizeCtlSetMultiSizeMode(me->size_ctl);
2175     else
2176         SizeCtlSetSingleSizeMode(me->size_ctl,
2177                                  PdmOidListGetOid(me->tray_sizes,
2178                                                   me->selected_item - 1));
2179 }
2180
2181 /*
2182  * ------------------------------------------------------------------------
2183  * Name: TrayCtlSelectCB
2184  *
2185  * Description:
2186  *
2187  *     
2188  *
2189  * Return value:
2190  *
2191  *     
2192  *
2193  */
2194 static void
2195 TrayCtlSelectCB(Widget w, XtPointer client_data, XtPointer call_data)
2196 {
2197     TrayCtl* me;
2198     int selected_item = (int)client_data;
2199
2200     XtVaGetValues(w, XmNuserData, &me, NULL);
2201     TrayCtlSetSelectedItem(me, selected_item);
2202 }
2203
2204
2205 /*
2206  * ------------------------------------------------------------------------
2207  * Name: SizeCtlNew
2208  *
2209  * Description:
2210  *
2211  *     
2212  *
2213  * Return value:
2214  *
2215  *     
2216  *
2217  */
2218 static SizeCtl*
2219 SizeCtlNew()
2220 {
2221     SizeCtl* me = (SizeCtl*)XtCalloc(1, sizeof(SizeCtl));
2222     return me;
2223 }
2224
2225 /*
2226  * ------------------------------------------------------------------------
2227  * Name: SizeCtlDelete
2228  *
2229  * Description:
2230  *
2231  *     
2232  *
2233  * Return value:
2234  *
2235  *     
2236  *
2237  */
2238 static void
2239 SizeCtlDelete(SizeCtl* me)
2240 {
2241     if(me != (SizeCtl*)NULL)
2242     {
2243         if(me->sizes_ready_xmstr != (XmString*)NULL)
2244             FreeXmStringList(me->sizes_ready_xmstr,
2245                              PdmOidListCount(me->sizes_ready));
2246         if(me->sizes_supported_xmstr != (XmString*)NULL)
2247             FreeXmStringList(me->sizes_supported_xmstr,
2248                              PdmOidListCount(me->sizes_supported));
2249         PdmOidListDelete(me->sizes_ready);
2250         PdmOidListDelete(me->sizes_supported);
2251         XtFree((char*)me);
2252     }
2253 }
2254
2255 /*
2256  * ------------------------------------------------------------------------
2257  * Name: SizeCtlStrColl
2258  *
2259  * Description:
2260  *
2261  *     An adaptor for using strcoll on SizeCtlSortRec's with qsort.
2262  *
2263  * Return value:
2264  *
2265  *     The return value for strcoll given the strings in the passed
2266  *     SizeCtlSortRec's.
2267  *
2268  */
2269 static int
2270 SizeCtlStrColl(void* e1, void* e2)
2271 {
2272     SizeCtlSortRec *r1 = e1, *r2 = e2;
2273
2274     return strcoll(r1->str, r2->str);
2275 }
2276
2277 /*
2278  * ------------------------------------------------------------------------
2279  * Name: SizeCtlSetSizeLists
2280  *
2281  * Description:
2282  *
2283  *     Creates a sorted XmStringTable and PdmOidList using
2284  *     the oids from the passed PdmOidLinkedList. The newly created lists
2285  *     are returned via the 'oids' and 'xmstrs' parms.
2286  *
2287  * Return value:
2288  *
2289  *     None.
2290  *
2291  */
2292 static void
2293 SizeCtlSetSizeLists(PdmOidList** oid_list,
2294                     XmStringTable* xmstrs,
2295                     PdmOidLinkedList* oid_ll)
2296 {
2297     int count;
2298
2299     count = PdmOidLinkedListCount(oid_ll);
2300     if(count == 0)
2301     {
2302         *oid_list = (PdmOidList*)NULL;
2303         *xmstrs = (XmStringTable)NULL;
2304     }
2305     else
2306     {   
2307         SizeCtlSortList sort_list;
2308         int i;
2309         PdmOid oid;
2310         /*
2311          * sort the passed sizes
2312          */
2313         sort_list = (SizeCtlSortList)XtCalloc(count, sizeof(SizeCtlSortRec));
2314         for(i = 0, oid = PdmOidLinkedListFirstOid(oid_ll);
2315             i < count;
2316             i++, oid = PdmOidLinkedListNextOid(oid_ll))
2317         {
2318             sort_list[i].oid = oid;
2319             sort_list[i].str = DTPDM_GETMESSAGE(PdmOidMsgSet(oid),
2320                                                 PdmOidMsgNum(oid),
2321                                                 PdmOidDefaultMsg(oid));
2322         }
2323         qsort(sort_list, count, sizeof(SizeCtlSortRec), SizeCtlStrColl);
2324         /*
2325          * create the return lists of oids and XmStrings
2326          */
2327         *oid_list = (PdmOidList*)XtCalloc(1, sizeof(PdmOidList));
2328         (*oid_list)->list = (PdmOid*)XtCalloc(count, sizeof(PdmOid));
2329         (*oid_list)->count = count;
2330         *xmstrs = (XmStringTable)XtCalloc(count, sizeof(XmString));
2331         for(i = 0; i < count; i++)
2332         {
2333             ((*oid_list)->list)[i] = sort_list[i].oid;
2334             (*xmstrs)[i] = XmStringCreateLocalized((char*)sort_list[i].str);
2335         }
2336         XtFree((char*)sort_list);
2337     }
2338 }
2339
2340 /*
2341  * ------------------------------------------------------------------------
2342  * Name: SizeCtlCreate
2343  *
2344  * Description:
2345  *
2346  *     
2347  *
2348  * Return value:
2349  *
2350  *     
2351  *
2352  */
2353 static void
2354 SizeCtlCreate(SizeCtl* me,
2355               Widget parent,
2356               PdmOid default_medium,
2357               const PdmOidList* document_attrs_supported,
2358               const PdmOidList* tray_sizes,
2359               PdmOidLinkedList* sizes_supported)
2360 {
2361     Boolean supported;
2362     int i;
2363     PdmOid oid;
2364     PdmOidLinkedList* sizes_ready_ll;
2365     /*
2366      * initialize the selected size
2367      */
2368     me->selected_size = default_medium;
2369     /*
2370      * build the sizes ready list using unique elements of the tray sizes
2371      * list
2372      */
2373     sizes_ready_ll = PdmOidLinkedListNew();
2374     for(i = 0; i < PdmOidListCount(tray_sizes); i++)
2375     {
2376         oid = PdmOidListGetOid(tray_sizes, i);
2377         if(!PdmOidLinkedListHasOid(sizes_ready_ll, oid))
2378         {
2379             PdmOidLinkedListAddOid(sizes_ready_ll, oid);
2380         }
2381     }
2382     /*
2383      * determine if setting the medium is supported
2384      */
2385     if(!PdmOidListHasOid(document_attrs_supported,
2386                          pdmoid_att_default_medium)
2387        ||
2388        PdmOidLinkedListCount(sizes_supported) == 0)
2389     {
2390         me->selected_list = SIZECTL_UNSUPPORTED;
2391     }
2392     else
2393     {
2394         /*
2395          * default to the ready list
2396          */
2397         me->selected_list = SIZECTL_SIZES_READY;
2398     }
2399     /*
2400      * create the XmString versions of the sizes lists
2401      */
2402     SizeCtlSetSizeLists(&me->sizes_ready, &me->sizes_ready_xmstr,
2403                         sizes_ready_ll);
2404     PdmOidLinkedListDelete(sizes_ready_ll);
2405     SizeCtlSetSizeLists(&me->sizes_supported, &me->sizes_supported_xmstr,
2406                         sizes_supported);
2407     /*
2408      * create the size control window
2409      */
2410     SizeCtlCreateWindow(me, parent);
2411     /*
2412      * update the control state
2413      */
2414     SizeCtlUpdate(me);
2415 }
2416
2417 /*
2418  * ------------------------------------------------------------------------
2419  * Name: SizeCtlCreateWindow
2420  *
2421  * Description:
2422  *
2423  *     
2424  *
2425  * Return value:
2426  *
2427  *     
2428  *
2429  */
2430 static void
2431 SizeCtlCreateWindow(SizeCtl* me, Widget parent)
2432 {
2433     Arg args[15];
2434     Cardinal n;
2435     Widget control_manager;
2436     Widget hscroll;
2437     XmString default_xmstr = (XmString)NULL;
2438     /*
2439      * page size frame
2440      */
2441     me->widget = XtVaCreateManagedWidget("PageSizeCtlTop",
2442                                          xmFrameWidgetClass,
2443                                          parent,
2444                                          XmNshadowType, XmSHADOW_ETCHED_IN,
2445                                          NULL);
2446     /*
2447      * page size label
2448      */
2449     me->frame_label
2450         = XtVaCreateManagedWidget("PageSizeLabel",
2451                                   xmLabelGadgetClass,
2452                                   me->widget,
2453                                   XmNframeChildType, XmFRAME_TITLE_CHILD,
2454                                   NULL);
2455
2456     /*
2457      * page size controls manager
2458      */
2459     control_manager =
2460         XtVaCreateManagedWidget("PageSizeControls",
2461                                 xmDrawingAreaWidgetClass,
2462                                 me->widget,
2463                                 XmNframeChildType, XmFRAME_WORKAREA_CHILD,
2464                                 NULL);
2465     XtAddCallback(control_manager, XmNresizeCallback, SizeCtlResizeCB, me);
2466     /*
2467      * page sizes list box
2468      */
2469     n = 0;
2470     XtSetArg(args[n], XmNvisibleItemCount, 3); n++;
2471     XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n++;
2472     XtSetArg(args[n], XmNhorizontalScrollBar, NULL); n++;
2473     /*
2474      * set the supported sizes list in the list box, in order to lock
2475      * down the maximum dimensions - the list box does not support
2476      * changes to the list size policy after creation
2477      */
2478     if(me->selected_list == SIZECTL_UNSUPPORTED)
2479     {
2480         /*
2481          * unsupported, use "Default"
2482          */
2483         default_xmstr =
2484             XmStringCreateLocalized((char*)PDM_MSG_SIZE_DEFAULT);
2485         XtSetArg(args[n], XmNitemCount, 1); n++;
2486         XtSetArg(args[n], XmNitems, &default_xmstr); n++;
2487     }
2488     else
2489     {
2490         XtSetArg(args[n], XmNitems, me->sizes_supported_xmstr); n++;
2491         XtSetArg(args[n], XmNitemCount,
2492                  PdmOidListCount(me->sizes_supported)); n++;
2493     }
2494     XtSetArg(args[n], XmNlistSizePolicy, XmCONSTANT); n++;
2495
2496     me->list_box = XmCreateScrolledList(control_manager, "PageSizes", args, n);
2497     if((XmString)NULL != default_xmstr) XmStringFree(default_xmstr);
2498     XtAddCallback(me->list_box, XmNbrowseSelectionCallback,
2499                   SizeCtlSelectCB, (XtPointer)me);
2500     /*
2501      * hide the horizontal scroll bar, since the width of the list has
2502      * been set to accomodate the widest item.
2503      */
2504     hscroll = XtNameToWidget(XtParent(me->list_box), "*HorScrollBar");
2505     XtVaSetValues(hscroll,
2506                   XmNmappedWhenManaged, False,
2507                   XmNx, 0, XmNy, 0, XmNwidth, 1, XmNheight, 1,
2508                   NULL);
2509     /*
2510      * manage the scrolled list
2511      */
2512     XtManageChild(me->list_box);
2513     XtManageChild(XtParent(me->list_box));
2514     /*
2515      * loaded / allowed sizes radio buttons
2516      */
2517     me->radio_box = XtVaCreateWidget(
2518                                      "LoadedAllowed",
2519                                      xmRowColumnWidgetClass,
2520                                      control_manager,
2521                                      XmNradioBehavior, True,
2522                                      NULL);
2523     me->ready_radio = XtVaCreateManagedWidget("button_0",
2524                                               xmToggleButtonWidgetClass,
2525                                               me->radio_box,
2526                                               NULL);
2527     XtAddCallback(me->ready_radio, XmNvalueChangedCallback,
2528                   SizeCtlReadyChangedCB, (XtPointer)me);
2529     me->supported_radio = XtVaCreateManagedWidget("button_1",
2530                                               xmToggleButtonWidgetClass,
2531                                               me->radio_box,
2532                                               NULL);
2533     XtAddCallback(me->supported_radio, XmNvalueChangedCallback,
2534                   SizeCtlSupportedChangedCB, (XtPointer)me);
2535     
2536     XtManageChild(me->radio_box);
2537 }
2538
2539 /*
2540  * ------------------------------------------------------------------------
2541  * Name: SizeCtlUpdate
2542  *
2543  * Description:
2544  *
2545  *     Update the state of the size control
2546  *
2547  * Return value:
2548  *
2549  *     None.
2550  *
2551  */
2552 static void
2553 SizeCtlUpdate(SizeCtl* me)
2554 {
2555     Boolean frame_label_sensitive = False;
2556     Boolean list_box_sensitive = False;
2557     Boolean list_box_traverse = False;
2558     Boolean ready_radio_sensitive = False;
2559     Boolean supported_radio_sensitive = False;
2560     /*
2561      * clear the current list
2562      */
2563     XmListDeleteAllItems(me->list_box);
2564
2565     if(me->single_size_mode)
2566     {
2567         XmString item;
2568         PdmOid oid = me->selected_size;
2569         
2570         item =
2571             XmStringCreateLocalized((char*)
2572                                     DTPDM_GETMESSAGE(PdmOidMsgSet(oid),
2573                                                      PdmOidMsgNum(oid),
2574                                                      PdmOidDefaultMsg(oid)));
2575         XmListAddItem(me->list_box, item, 0);
2576         XmListSelectPos(me->list_box, 0, False);
2577         XmStringFree(item);
2578
2579         if(me->selected_list != SIZECTL_UNSUPPORTED)
2580         {
2581             frame_label_sensitive = True;
2582             list_box_sensitive = True;
2583             me->selected_list = SIZECTL_SIZES_READY;
2584             XmToggleButtonSetState(me->ready_radio, True, False);
2585             XmToggleButtonSetState(me->supported_radio, False, False);
2586         }
2587     }
2588     else
2589     {
2590         if(me->selected_list == SIZECTL_UNSUPPORTED)
2591         {
2592             XmString default_item;
2593
2594             default_item =
2595               XmStringCreateLocalized((char*)PDM_MSG_SIZE_DEFAULT);
2596             XmListAddItem(me->list_box, default_item, 0);
2597             XmListSelectPos(me->list_box, 0, False);
2598             XmStringFree(default_item);
2599         }
2600         else
2601         {
2602             XmString* list;
2603             int count;
2604             int pos;
2605             /*
2606              * set control sensitivities
2607              */
2608             frame_label_sensitive = True;
2609             supported_radio_sensitive = True;
2610             list_box_sensitive = True;
2611             list_box_traverse = True;
2612             if(PdmOidListCount(me->sizes_ready) > 0)
2613                 ready_radio_sensitive = True;
2614             /*
2615              * check to see if the selected size is supported
2616              */
2617             if(!PdmOidListHasOid(me->sizes_supported, me->selected_size))
2618             {
2619                 /*
2620                  * the selected size is not supported
2621                  */
2622                 if(PdmOidListCount(me->sizes_ready) > 0)
2623                 {
2624                     /*
2625                      * use the 1st entry in the ready list
2626                      */
2627                     me->selected_size =
2628                         PdmOidListGetOid(me->sizes_ready, 0);
2629                     me->selected_list = SIZECTL_SIZES_READY;
2630                 }
2631                 else
2632                 {
2633                     /*
2634                      * the ready list is empty, use the 1st entry in the
2635                      * supported list
2636                      */
2637                     me->selected_size =
2638                         PdmOidListGetOid(me->sizes_supported, 0);
2639                     me->selected_list = SIZECTL_SIZES_SUPPORTED;
2640                 }
2641             }
2642             else if(me->selected_list == SIZECTL_SIZES_READY
2643                     &&
2644                     !PdmOidListHasOid(me->sizes_ready, me->selected_size))
2645             {
2646                 /*
2647                  * the selected size is not in the ready list; use the
2648                  * supported list instead
2649                  */
2650                 me->selected_list = SIZECTL_SIZES_SUPPORTED;
2651             }
2652             /*
2653              * set the appropriate radio button and update the list
2654              */
2655             if(me->selected_list == SIZECTL_SIZES_READY)
2656             {
2657                 XmToggleButtonSetState(me->ready_radio, True, False);
2658                 XmToggleButtonSetState(me->supported_radio, False, False);
2659
2660                 list = me->sizes_ready_xmstr;
2661                 count = PdmOidListCount(me->sizes_ready);
2662                 pos = 1 + PdmOidListGetIndex(me->sizes_ready,
2663                                              me->selected_size);
2664             }
2665             else
2666             {
2667                 XmToggleButtonSetState(me->supported_radio, True, False);
2668                 XmToggleButtonSetState(me->ready_radio, False, False);
2669
2670                 list = me->sizes_supported_xmstr;
2671                 count = PdmOidListCount(me->sizes_supported);
2672                 pos = 1 + PdmOidListGetIndex(me->sizes_supported,
2673                                              me->selected_size);
2674             }
2675             XmListAddItemsUnselected(me->list_box, list, count, 0);
2676             SetListBoxSelection(me->list_box, pos);
2677         }
2678     }
2679     /*
2680      * update control sensitivities
2681      */
2682     XtSetSensitive(me->frame_label, frame_label_sensitive);
2683     XtSetSensitive(me->list_box, list_box_sensitive);
2684     XtVaSetValues(me->list_box, XmNtraversalOn, list_box_traverse, NULL);
2685     XtSetSensitive(me->ready_radio, ready_radio_sensitive);
2686     XtSetSensitive(me->supported_radio, supported_radio_sensitive);
2687 }
2688
2689 /*
2690  * ------------------------------------------------------------------------
2691  * Name: SizeCtlResizeCB
2692  *
2693  * Description:
2694  *
2695  *     
2696  *
2697  * Return value:
2698  *
2699  *     None.
2700  *
2701  */
2702 static void
2703 SizeCtlResizeCB(Widget w, XtPointer client_data, XtPointer call_data)
2704 {
2705     SizeCtl* me = (SizeCtl*)client_data;
2706     Dimension height, width, margin_width, new_width;
2707     Position list_x, list_y, radio_x, radio_y;
2708     Dimension list_h, list_w, radio_h, radio_w;
2709     Widget scrolled_list = XtParent(me->list_box);
2710     /*
2711      * get current layout info
2712      */
2713     XtVaGetValues(w, XmNheight, &height, XmNwidth, &width,
2714                   XmNmarginWidth, &margin_width,
2715                   NULL);
2716     XtVaGetValues(scrolled_list, XmNheight, &list_h, XmNwidth, &list_w, NULL);
2717     XtVaGetValues(me->radio_box, XmNheight, &radio_h, XmNwidth, &radio_w,
2718                   NULL);
2719     /*
2720      * position controls side by side
2721      */
2722     list_x = margin_width;
2723     radio_x = list_x + list_w;
2724     /*
2725      * center vertically
2726      */
2727     list_y = (height - list_h) / 2;
2728     radio_y = (height - radio_h) / 2;
2729     /*
2730      * set new positions
2731      */
2732     XtVaSetValues(scrolled_list, XmNx, list_x, XmNy, list_y, NULL);
2733     XtVaSetValues(me->radio_box, XmNx, radio_x, XmNy, radio_y, NULL);
2734     /*
2735      * update drawing area width and height
2736      */
2737     new_width = list_x + list_w + radio_w;
2738     if(new_width > width)
2739         XtVaSetValues(w, XmNwidth, new_width, NULL);
2740 }
2741
2742 /*
2743  * ------------------------------------------------------------------------
2744  * Name: SizeCtlSetSingleSizeMode
2745  *
2746  * Description:
2747  *
2748  *     
2749  *
2750  * Return value:
2751  *
2752  *     
2753  *
2754  */
2755 static void
2756 SizeCtlSetSingleSizeMode(SizeCtl* me, PdmOid size)
2757 {
2758     if(size != pdmoid_none)
2759     {
2760         me->single_size_mode = True;
2761         me->selected_size = size;
2762         SizeCtlUpdate(me);
2763     }
2764 }
2765
2766 /*
2767  * ------------------------------------------------------------------------
2768  * Name: SizeCtlSetMultiSizeMode
2769  *
2770  * Description:
2771  *
2772  *     
2773  *
2774  * Return value:
2775  *
2776  *     
2777  *
2778  */
2779 static void
2780 SizeCtlSetMultiSizeMode(SizeCtl* me)
2781 {
2782     me->single_size_mode = False;
2783     SizeCtlUpdate(me);
2784 }
2785
2786
2787
2788 /*
2789  * ------------------------------------------------------------------------
2790  * Name: SizeCtlGetSize
2791  *
2792  * Description:
2793  *
2794  *     
2795  *
2796  * Return value:
2797  *
2798  *     
2799  *
2800  */
2801 static PdmOid
2802 SizeCtlGetSize(SizeCtl* me)
2803 {
2804     if(me->single_size_mode || me->selected_list == SIZECTL_UNSUPPORTED)
2805         return pdmoid_none;
2806     else
2807         return me->selected_size;
2808 }
2809
2810 /*
2811  * ------------------------------------------------------------------------
2812  * Name: SizeCtlReadyChangedCB
2813  *
2814  * Description:
2815  *
2816  *     
2817  *
2818  * Return value:
2819  *
2820  *     
2821  *
2822  */
2823 static void
2824 SizeCtlReadyChangedCB(Widget w,
2825                       XtPointer client_data,
2826                       XtPointer call_data)
2827 {
2828     XmToggleButtonCallbackStruct* cbs =
2829         (XmToggleButtonCallbackStruct*)call_data;
2830
2831     if(cbs->set)
2832     {
2833         SizeCtl* me = (SizeCtl*)client_data;
2834         me->selected_list = SIZECTL_SIZES_READY;
2835         if(!PdmOidListHasOid(me->sizes_ready, me->selected_size))
2836             me->selected_size = pdmoid_none;
2837         SizeCtlUpdate(me);
2838     }
2839 }
2840
2841 /*
2842  * ------------------------------------------------------------------------
2843  * Name: SizeCtlSupportedChangedCB
2844  *
2845  * Description:
2846  *
2847  *     
2848  *
2849  * Return value:
2850  *
2851  *     
2852  *
2853  */
2854 static void
2855 SizeCtlSupportedChangedCB(Widget w,
2856                           XtPointer client_data,
2857                           XtPointer call_data)
2858 {
2859     XmToggleButtonCallbackStruct* cbs =
2860         (XmToggleButtonCallbackStruct*)call_data;
2861
2862     if(cbs->set)
2863     {
2864         SizeCtl* me = (SizeCtl*)client_data;
2865         me->selected_list = SIZECTL_SIZES_SUPPORTED;
2866         SizeCtlUpdate(me);
2867     }
2868 }
2869
2870 /*
2871  * ------------------------------------------------------------------------
2872  * Name: SizeCtlSelectCB
2873  *
2874  * Description:
2875  *
2876  *     
2877  *
2878  * Return value:
2879  *
2880  *     
2881  *
2882  */
2883 static void
2884 SizeCtlSelectCB(Widget w,
2885                 XtPointer client_data,
2886                 XtPointer call_data)
2887 {
2888     XmListCallbackStruct* cbs = (XmListCallbackStruct*)call_data;
2889     SizeCtl* me = (SizeCtl*)client_data;
2890
2891     if(!me->single_size_mode)
2892     {
2893         switch(me->selected_list)
2894         {
2895         case SIZECTL_SIZES_READY:
2896             me->selected_size =
2897                 PdmOidListGetOid(me->sizes_ready, cbs->item_position - 1);
2898             break;
2899         case SIZECTL_SIZES_SUPPORTED:
2900             me->selected_size =
2901                 PdmOidListGetOid(me->sizes_supported, cbs->item_position - 1);
2902             break;
2903         }
2904     }
2905 }
2906
2907 /*
2908  * ------------------------------------------------------------------------
2909  * Name: CreateOptionMenuPulldown
2910  *
2911  * Description:
2912  *
2913  *     
2914  *
2915  * Return value:
2916  *
2917  *     
2918  *
2919  */
2920 static Widget
2921 CreateOptionMenuPulldown(String pulldown_name,
2922                          Widget option_menu,
2923                          XtCallbackProc activate_proc,
2924                          XtPointer user_data,
2925                          XmString* item_list,
2926                          int item_count,
2927                          int initial_item)
2928 {
2929     Widget cascade_button;
2930     Widget button;
2931     Widget initial_selected = (Widget)NULL;
2932     Widget pulldown;
2933     char button_name[48];
2934     int i;
2935
2936     pulldown =
2937         XmCreatePulldownMenu(XtParent(option_menu), pulldown_name, NULL, 0);
2938
2939     for(i = 0; i < item_count; i++)
2940     {
2941         sprintf(button_name, "button_%d", i);
2942         button = XtVaCreateManagedWidget(button_name,
2943                                          xmPushButtonGadgetClass,
2944                                          pulldown,
2945                                          XmNuserData, user_data,
2946                                          XmNlabelString, item_list[i],
2947                                          NULL);
2948         if(activate_proc != (XtCallbackProc)NULL)
2949             XtAddCallback(button, XmNactivateCallback,
2950                           activate_proc, (XtPointer)i);
2951         if(i == initial_item)
2952             initial_selected = button;
2953     }
2954     XtVaSetValues(option_menu,
2955                   XmNsubMenuId, pulldown,
2956                   XmNmenuHistory, initial_selected,
2957                   NULL);
2958
2959     return pulldown;
2960 }
2961
2962 /*
2963  * ------------------------------------------------------------------------
2964  * Name: CreateXmStringsFromOidList
2965  *
2966  * Description:
2967  *
2968  *     
2969  *
2970  * Return value:
2971  *
2972  *     
2973  *
2974  */
2975 static XmString*
2976 CreateXmStringsFromOidList(const PdmOidList* list)
2977 {
2978     int count = PdmOidListCount(list);
2979     XmString* xmstr_list = (XmString*)NULL;
2980     
2981     if(count > 0)
2982     {
2983         int i;
2984         PdmOid oid;
2985         const char* str;
2986         /*
2987          * build a list of Xm strings for the passed PdmOidList
2988          */
2989         xmstr_list = (XmString*)XtCalloc(count, sizeof(XmString));
2990         for(i = 0; i < count; i++)
2991         {
2992             oid = PdmOidListGetOid(list, i);
2993             str = DTPDM_GETMESSAGE(PdmOidMsgSet(oid),
2994                                    PdmOidMsgNum(oid),
2995                                    PdmOidDefaultMsg(oid));
2996             xmstr_list[i] = XmStringCreateLocalized((char*)str);
2997         }
2998     }
2999     return xmstr_list;
3000 }
3001
3002 /*
3003  * ------------------------------------------------------------------------
3004  * Name: FreeXmStringList
3005  *
3006  * Description:
3007  *
3008  *     
3009  *
3010  * Return value:
3011  *
3012  *     
3013  *
3014  */
3015 static void
3016 FreeXmStringList(XmString* list, int count)
3017 {
3018     int i;
3019     
3020     for(i = 0; i < count; i++)
3021         XmStringFree(list[i]);
3022     XtFree((char*)list);
3023 }
3024
3025 /*
3026  * ------------------------------------------------------------------------
3027  * Name: IconMaxDimension
3028  *
3029  * Description:
3030  *
3031  *     
3032  *
3033  * Return value:
3034  *
3035  *     
3036  *
3037  */
3038 static void
3039 IconMaxDimension(Widget icon_label,
3040                  PdmPixmapList* pixmap_list, int i,
3041                  Dimension* max_width, Dimension* max_height)
3042 {
3043     Dimension width, height;
3044     /*
3045      * set the pixmap in the label
3046      */
3047     XtVaSetValues(icon_label,
3048                   XmNlabelPixmap, PdmPixmapListGetPixmap(pixmap_list, i),
3049                   NULL);
3050     /*
3051      * get the label dimensions
3052      */
3053     XtVaGetValues(icon_label,
3054                   XmNwidth, &width,
3055                   XmNheight, &height,
3056                   NULL);
3057     /*
3058      * update the max dimensions
3059      */
3060     if(width > *max_width)
3061         *max_width = width;
3062     if(height > *max_height)
3063         *max_height = height;
3064 }
3065
3066 /*
3067  * ------------------------------------------------------------------------
3068  * Name: PdmPixmapListNew
3069  *
3070  * Description:
3071  *
3072  *     
3073  *
3074  * Return value:
3075  *
3076  *     
3077  *
3078  */
3079 static PdmPixmapList*
3080 PdmPixmapListNew(int count,
3081                  Widget w,
3082                  Boolean stipple)
3083 {
3084     PdmPixmapList* me = (PdmPixmapList*)XtCalloc(1, sizeof(PdmPixmapList));
3085
3086     me->pixmap = (Pixmap*)XtCalloc(count, sizeof(Pixmap));
3087     me->image_name = (char**)XtCalloc(count, sizeof(char*));
3088     me->screen = XtScreen(w);
3089     if(stipple)
3090     {
3091         Widget xmscr = XmGetXmScreen(me->screen);
3092         XtVaGetValues(xmscr, XmNinsensitiveStippleBitmap, &me->stipple, NULL);
3093     }
3094     else
3095     {
3096         me->stipple = None;
3097     }
3098     XtVaGetValues(w,
3099                   XmNforeground, &me->foreground,
3100                   XmNbackground, &me->background,
3101                   NULL);
3102
3103     return me;
3104 }
3105
3106 /*
3107  * ------------------------------------------------------------------------
3108  * Name: PdmPixmapListDelete
3109  *
3110  * Description:
3111  *
3112  *     
3113  *
3114  * Return value:
3115  *
3116  *     
3117  *
3118  */
3119 static void
3120 PdmPixmapListDelete(PdmPixmapList* me)
3121 {
3122     if(me != (PdmPixmapList*)NULL)
3123     {
3124         int i;
3125         for(i = 0; i < PdmPixmapListCount(me); i++)
3126         {
3127             if(me->pixmap[i] != (Pixmap)NULL)
3128             {
3129                 if(me->stipple == None)
3130                 {
3131                     if(me->pixmap[i] != None)
3132                         XmDestroyPixmap(me->screen, me->pixmap[i]);
3133                 }
3134                 else
3135                 {
3136                     if(me->pixmap[i] != None)
3137                         XFreePixmap(DisplayOfScreen(me->screen),
3138                                     me->pixmap[i]);
3139                 }
3140                 XtFree((char*)me->image_name[i]);
3141             }
3142         }
3143         XtFree((char*)me->pixmap);
3144         XtFree((char*)me->image_name);
3145         XtFree((char*)me);
3146     }
3147 }
3148
3149 /*
3150  * ------------------------------------------------------------------------
3151  * Name: PdmPixmapSetImageName
3152  *
3153  * Description:
3154  *
3155  *     
3156  *
3157  * Return value:
3158  *
3159  *     
3160  *
3161  */
3162 static void
3163 PdmPixmapListSetImageName(PdmPixmapList* me,
3164                           const char* image_name,
3165                           int i)
3166 {
3167     me->image_name[i] = XtNewString(image_name);
3168 }
3169
3170 /*
3171  * ------------------------------------------------------------------------
3172  * Name: PdmPixmapListGetPixmap
3173  *
3174  * Description:
3175  *
3176  *     
3177  *
3178  * Return value:
3179  *
3180  *     
3181  *
3182  */
3183 static Pixmap
3184 PdmPixmapListGetPixmap(PdmPixmapList* me, int i)
3185 {
3186     if(me->pixmap[i] == None)
3187     {
3188         me->pixmap[i] = XmGetPixmap(me->screen, me->image_name[i],
3189                                     me->foreground, me->background);
3190         if(me->pixmap[i] == XmUNSPECIFIED_PIXMAP)
3191         {
3192             me->pixmap[i] == None;
3193         }
3194         else if(me->stipple != None)
3195         {
3196             Pixmap xmpixmap = me->pixmap[i];
3197             Display* display = DisplayOfScreen(me->screen);
3198             Window root;
3199             int x, y;
3200             unsigned int width, height, border_width, depth;
3201             GC gc;
3202             XGCValues values;
3203             /*
3204              * make a copy of the pixmap cached by motif
3205              */
3206             XGetGeometry(display, xmpixmap, &root, &x, &y,
3207                          &width, &height, &border_width, &depth);
3208             me->pixmap[i] =
3209                 XCreatePixmap(display, xmpixmap, width, height, depth);
3210             gc = XCreateGC(display, me->pixmap[i], (unsigned long)0, &values);
3211             XCopyArea(display, xmpixmap, me->pixmap[i], gc,
3212                       0, 0, width, height, 0, 0);
3213             /*
3214              * stipple it
3215              */
3216             XSetFillStyle(display, gc, FillStippled);
3217             XSetStipple(display, gc, me->stipple);
3218             XFillRectangle(display, me->pixmap[i], gc, 0, 0, width, height);
3219             /*
3220              * clean up
3221              */
3222             XFreeGC(display, gc);       
3223             XmDestroyPixmap(me->screen, xmpixmap);
3224         }
3225     }
3226     return me->pixmap[i];
3227 }
3228
3229 /*
3230  * ------------------------------------------------------------------------
3231  * Name: SetListBoxSelection
3232  *
3233  * Description:
3234  *
3235  *
3236  * Return value:
3237  *
3238  *     None.
3239  *
3240  */
3241 static void
3242 SetListBoxSelection(Widget list_box, int position)
3243 {
3244     int visible_item_count;
3245     int item_count;
3246     int middle_offset;
3247     int first_visible_pos;
3248     /*
3249      * Scroll the list, making the item at the indicated position
3250      * visible in the center of the list box, and make
3251      * it the initial selection.
3252      */
3253     XtVaGetValues(list_box,
3254                   XmNitemCount, &item_count,
3255                   XmNvisibleItemCount, &visible_item_count,
3256                   NULL);
3257
3258     if(item_count > visible_item_count)
3259     {
3260         middle_offset = (visible_item_count+1) / 2;
3261         if(position > middle_offset)
3262             if(position > item_count - middle_offset)
3263                 first_visible_pos = item_count - visible_item_count +1;
3264             else
3265                 first_visible_pos = position - middle_offset + 1;
3266         else
3267             first_visible_pos = 1;
3268         XmListSetPos(list_box, first_visible_pos);
3269     }
3270
3271     if(position > 0)
3272         XmListSelectPos(list_box, position, False);
3273     else
3274         XmListDeselectAllItems(list_box);
3275 }
3276
3277 /*
3278  * ------------------------------------------------------------------------
3279  * Name: GetIconFileName
3280  *
3281  * Description:
3282  *
3283  *
3284  * Return value:
3285  *
3286  *     None.
3287  *
3288  */
3289 static String
3290 GetIconFileName(Widget w, String resource_name)
3291 {
3292     String icon_file_name;
3293     XtResource res_struct;
3294
3295     res_struct.resource_name = resource_name;
3296     res_struct.resource_class = resource_name;
3297     res_struct.resource_type =  XmRString;
3298     res_struct.resource_size = sizeof(String);
3299     res_struct.resource_offset = 0;
3300     res_struct.default_type = XmRImmediate;
3301     res_struct.default_addr = (XtPointer)NULL;
3302     XtGetApplicationResources(w, (XtPointer)&icon_file_name,
3303                               &res_struct, 1, (ArgList)NULL, 0);
3304
3305     return icon_file_name;
3306 }