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