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