Spelling fixes
[oweals/cde.git] / cde / lib / DtPrint / PsubDefProc.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: PsubDefProc.c /main/14 1996/12/02 10:51:20 rswiston $ */
24 /*
25  * DtPrint/PsubDefProc.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 /*
37  * ------------------------------------------------------------------------
38  * Include Files
39  *
40  */
41 #include <stdlib.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44
45 #include <Xm/XmAll.h>
46
47 #include <Dt/HelpDialog.h>
48 #include <Dt/DtNlUtils.h>
49 #include <Dt/HourGlass.h>
50
51 /*
52  * PrintSetupBP.h is included only for access to the DtPrintDefProcData
53  * member of the widget instance structure.
54  */
55 #include <Dt/PrintSetupBP.h>
56
57 #include <Dt/PsubUtilI.h>
58
59 /*
60  * ------------------------------------------------------------------------
61  * Constant Definitions
62  *
63  */
64 #define HELP_VOLUME "LibDtPrint"
65 #define PRINTER_INFO_HELP_ID "PrinterInfo"
66 #define SELECT_PRINTER_HELP_ID "SelectPrinter"
67 #define SELECT_FILE_HELP_ID "SelectFile"
68
69 /*
70  * ------------------------------------------------------------------------
71  * Static Function Declarations
72  *
73  */
74 static XtEnum BuildPrinterLists(
75                                 Widget w,
76                                 DtPrintDefaultProcData* dpd,
77                                 int* item_count);
78 static XmStringTable BuildPrinterSelectionItems(
79                                                 Display* display,
80                                                 DtPrintDefaultProcData* dpd,
81                                                 int item_count,
82                                                 String initial_printer,
83                                                 XmStringTag tag);
84 static void CloseSelectPrinterInfoConnection(
85                                              DtPrintDefaultProcData* dpd);
86 static int CompareSelectPrinterRecs(const void*,
87                                     const void*);
88 static String CompoundTextToString(
89                                    Display* display,
90                                    unsigned char* compound_text);
91 static XtEnum CreateFileSelectionBox(
92                                      Widget parent,
93                                      Widget psub,
94                                      DtPrintDefaultProcData* dpd);
95 static XtEnum CreatePrinterInfoBox(
96                                    Widget parent,
97                                    Widget psub,
98                                    DtPrintDefaultProcData* dpd);
99 static XtEnum CreatePrinterSelectionBox(
100                                         Widget parent,
101                                         Widget psub,
102                                         DtPrintDefaultProcData* dpd);
103 static void DestroyWidgetCB(
104                             Widget w,
105                             XtPointer client_data,
106                             XtPointer call_data);
107 static void DtPrintDefProcDestroyCB(Widget w,
108                                     XtPointer client_data,
109                                     XtPointer call_data);
110 static void ErrorMessageDestroyCB(
111                                   Widget w,
112                                   XtPointer client_data,
113                                   XtPointer call_data);
114 static String FindSelectedPrinter(
115                                   Display* display,
116                                   DtPrintDefaultProcData* dpd);
117 static void FreeSelectPrinterData(
118                                   DtPrintDefaultProcData* dpd);
119 static Widget GetWMShellAncestor(
120                                  Widget w);
121 static void HelpDialogDestroyCB(
122                                 Widget w,
123                                 XtPointer client_data,
124                                 XtPointer call_data);
125 static void InfoBoxLayoutCB(
126                             Widget widget,
127                             XtPointer client_data,
128                             XtPointer call_data);
129 static void ParseFileNameSpec(
130                               const char* file_name,
131                               XmString* pattern,
132                               char** name_only);
133 static void PresentErrorDialog(
134                                Widget w,
135                                String title,
136                                String message,
137                                ...);
138 static void PresentHelp(
139                         Widget w,
140                         const char* help_volume,
141                         const char* location_id);
142 static void PresentVerifyError(
143                                Widget w,
144                                XtEnum status,
145                                String printer_spec);
146 static void PrinterInfoDestroyCB(
147                                  Widget w,
148                                  XtPointer client_data,
149                                  XtPointer call_data);
150 static void PrinterInfoHelpCB(
151                               Widget w,
152                               XtPointer client_data,
153                               XtPointer call_data);
154 static void SelectFileDestroyCB(
155                                 Widget w,
156                                 XtPointer client_data,
157                                 XtPointer call_data);
158 static void SelectFileHelpCB(
159                              Widget w,
160                              XtPointer client_data,
161                              XtPointer call_data);
162 static void SelectPrinterCB(
163                             Widget w,
164                             XtPointer client_data,
165                             XtPointer call_data);
166 static void SelectPrinterDestroyCB(
167                                    Widget w,
168                                    XtPointer client_data,
169                                    XtPointer call_data);
170 static void SelectPrinterHelpCB(
171                                 Widget w,
172                                 XtPointer client_data,
173                                 XtPointer call_data);
174 static void SelectPrinterInfoCB(
175                                 Widget w,
176                                 XtPointer client_data,
177                                 XtPointer call_data);
178 static void SelectPrinterItemCB(
179                                 Widget w,
180                                 XtPointer client_data,
181                                 XtPointer call_data);
182 static void SetListBoxSelection(
183                                 Widget list_box,
184                                 int position);
185 static void UpdateFileNameCB(
186                              Widget w,
187                              XtPointer client_data,
188                              XtPointer call_data);
189
190 /*
191  * ------------------------------------------------------------------------
192  * Name: BuildPrinterLists
193  *
194  * Description:
195  *
196  *     Retrieves lists of printers from the Xp server found in the
197  *     XpServerList resource or XPSERVERLIST env var.
198  *
199  * Return value:
200  *
201  *
202  *
203  */
204 static XtEnum
205 BuildPrinterLists(
206                   Widget w,
207                   DtPrintDefaultProcData* dpd,
208                   int* item_count)
209 {
210     String* server_list;
211     int server_count;
212     int i, j;
213     Display* display;
214     int error_base;
215     int event_base;
216 #if 0 && defined(PRINTING_SUPPORTED)
217     XPPrinterList xp_printer_list;
218 #endif /* PRINTING_SUPPORTED */
219     DtPrintSelectPrinterList printer_list;
220     /*
221      * clean up previous lists if needed
222      */
223     FreeSelectPrinterData(dpd);
224     /*
225      * get the list of servers
226      */
227     server_list = _DtPrintGetXpServerList(w);
228     if((String*)NULL == server_list)
229         return DtPRINT_FAILURE;
230     /*
231      * get the printer list for each valid Xp server
232      */
233     for(server_count = 0;
234         (String)NULL != server_list[server_count];
235         server_count++);
236     dpd->xp_server_list =
237         (String*)XtCalloc(server_count, sizeof(String));
238     dpd->printer_lists = (DtPrintSelectPrinterList*)
239         XtCalloc(server_count, sizeof(DtPrintSelectPrinterList));
240     dpd->printer_counts =
241         (int*)XtCalloc(server_count, sizeof(int));
242     for(i = 0, *item_count = 0; i < server_count; i++)
243     {
244         /*
245          * ensure the server is a valid Xp server
246          */
247         display = XOpenDisplay(server_list[i]);
248         if((Display*)NULL == display)
249             continue;
250 #if 0 && defined(PRINTING_SUPPORTED)
251         if(!XpQueryExtension(display, &event_base, &error_base))
252         {
253 #endif /* PRINTING_SUPPORTED */
254             XCloseDisplay(display);
255             continue;
256 #if 0 && defined(PRINTING_SUPPORTED)
257         }
258 #endif /* PRINTING_SUPPORTED */
259         /*
260          * add the server to the xp server list
261          */
262         dpd->xp_server_list[dpd->xp_server_count] =
263             XtNewString(server_list[i]);
264         /*
265          * get the printer list for the server
266          */
267 #if 0 && defined(PRINTING_SUPPORTED)
268         xp_printer_list =
269             XpGetPrinterList(display, (char*)NULL,
270                              &dpd->printer_counts[dpd->xp_server_count]);
271 #endif /* PRINTING_SUPPORTED */
272         /*
273          * save a copy of the compound text printer name and
274          * string versions of the name and description for
275          * eventual use in the printer selection list.
276          */
277         dpd->printer_lists[dpd->xp_server_count] = (DtPrintSelectPrinterList)
278             XtCalloc(dpd->printer_counts[dpd->xp_server_count],
279                      sizeof(DtPrintSelectPrinterRec));
280         printer_list = dpd->printer_lists[dpd->xp_server_count];
281 #if 0 && defined(PRINTING_SUPPORTED)
282         for(j = 0; j < dpd->printer_counts[dpd->xp_server_count]; j++)
283         {
284             printer_list[j].printer_name_ct =
285                 XtNewString(xp_printer_list[j].name);
286             printer_list[j].printer_name =
287                 CompoundTextToString(display,
288                                      (unsigned char*)xp_printer_list[j].name);
289             printer_list[j].description =
290                 CompoundTextToString(display,
291                                      (unsigned char*)xp_printer_list[j].desc);
292         }
293         XpFreePrinterList(xp_printer_list);
294 #endif /* PRINTING_SUPPORTED */
295         /*
296          * sort the printer list
297          */
298         if(0 < dpd->printer_counts[dpd->xp_server_count])
299             qsort((void*)printer_list,
300                   dpd->printer_counts[dpd->xp_server_count],
301                   sizeof(DtPrintSelectPrinterRec), CompareSelectPrinterRecs);
302
303         *item_count += dpd->printer_counts[dpd->xp_server_count];
304         ++dpd->xp_server_count;
305         XCloseDisplay(display);
306     }
307     _DtPrintFreeStringList(server_list);
308     if(0 == *item_count)
309     {
310         FreeSelectPrinterData(dpd);
311         return DtPRINT_FAILURE;
312     }
313     else
314         return DtPRINT_SUCCESS;
315 }
316
317 /*
318  * ------------------------------------------------------------------------
319  * Name: BuildPrinterSelectionItems
320  *
321  * Description:
322  *
323  *     Builds the list of XmString items (printer name + desc) to be set
324  *     in the printer selection list box.
325  *
326  * Return value:
327  *
328  *     None.
329  *
330  */
331 static XmStringTable
332 BuildPrinterSelectionItems(
333                            Display* display,
334                            DtPrintDefaultProcData* dpd,
335                            int item_count,
336                            String initial_printer,
337                            XmStringTag tag)
338 {
339     XmStringTable items;
340     int i, j;
341     char* buf = (char*)NULL;
342     Cardinal buf_size = 0;
343     Cardinal new_size;
344     int current_item;
345     String name, full_name, desc;
346     char* server_name;
347     int server_len;
348     
349     items = (XmStringTable)XtCalloc(item_count, sizeof(XmString));
350     for(i = 0, current_item = 0; i < dpd->xp_server_count; i++)
351     {
352         server_name = dpd->xp_server_list[i];
353         server_len = strlen(server_name);
354         
355         for(j = 0; j < dpd->printer_counts[i]; j++, current_item++)
356         {
357             /*
358              * build a fully qualified X printer specifier
359              */
360             name = (dpd->printer_lists[i])[j].printer_name;
361             (dpd->printer_lists[i])[j].printer_name = (String)NULL;
362             full_name =
363                 _DtPrintCreateXPrinterSpecifier(name, server_name,
364                                                 DtPRINT_NET_UNSPECIFIED,
365                                                 -1, -1);
366             XtFree(name);
367             /*
368              * check to see if this should be the initially selected printer
369              */
370             if(dpd->selected_printer == 0
371                && (String)NULL != initial_printer)
372                 if(strcmp(initial_printer, full_name) == 0)
373                     dpd->selected_printer = current_item + 1;
374             /*
375              * convert the printer description
376              */
377             desc = (dpd->printer_lists[i])[j].description;
378             (dpd->printer_lists[i])[j].description = (String)NULL;
379             if((String)NULL != desc && '\0' != *desc)
380             {
381                 /*
382                  * chop the description after the 1st line
383                  */
384                 char* ptr = Dt_strchr(desc, '\n');
385                 if((char*)NULL != ptr)
386                     *ptr = '\0';
387             }
388             /*
389              * ensure the format buffer is large enough to contain
390              * the formatted list item
391              */
392             new_size = 2;
393             new_size += full_name ? strlen(full_name) : 0;
394             new_size += desc ? strlen(desc) : 0;
395             if(new_size > buf_size)
396             {
397                 buf_size = new_size;
398                 buf = XtRealloc(buf, buf_size);
399             }
400             /*
401              * format the item, and add it to the item list
402              */
403             sprintf(buf, "%s\t%s",
404                     full_name ? full_name : "",
405                     desc ? desc : "");
406             XtFree(desc);
407             XtFree(full_name);
408             items[current_item] =
409                 XmStringGenerate((XtPointer)buf, (XmStringTag)NULL,
410                                  XmMULTIBYTE_TEXT, tag);
411         }
412     }
413     XtFree(buf);
414     return items;
415 }
416
417 /*
418  * ------------------------------------------------------------------------
419  * Name: CloseSelectPrinterInfoConnection
420  *
421  * Description:
422  *
423  *     Close the X printer connection maintained for the Select Printer
424  *     dialog's Printer Information dialog.
425  *
426  * Return value:
427  *
428  *     None.
429  *
430  */
431 static void
432 CloseSelectPrinterInfoConnection(
433                                  DtPrintDefaultProcData* dpd)
434 {
435     if((Display*)NULL != dpd->select_printer_info_display)
436     {
437 #if 0 && defined(PRINTING_SUPPORTED)
438         if((XPContext)None != dpd->select_printer_info_context)
439         {
440             XpDestroyContext(dpd->select_printer_info_display,
441                              dpd->select_printer_info_context);
442             dpd->select_printer_info_context = (XPContext)None;
443         }
444 #endif /* PRINTING_SUPPORTED */
445         XCloseDisplay(dpd->select_printer_info_display);
446         dpd->select_printer_info_display = (Display*)NULL;
447     }
448 }
449
450 /*
451  * ------------------------------------------------------------------------
452  * Name: CompareSelectPrinterRecs
453  *
454  * Description:
455  *
456  *     Compares the printer names in two DtPrintSelectPrinterRecs.
457  *
458  * Return value:
459  *
460  *     Returns an integer greater than, equal to, or less than zero,
461  *     according to whether the printer name in spr1 is greater
462  *     than, equal to, or less than the printer name in spr2.
463  *
464  */
465 static int
466 CompareSelectPrinterRecs(const void* spr1,
467                          const void* spr2)
468 {
469     return strcoll(((DtPrintSelectPrinterRec*)spr1)->printer_name,
470                    ((DtPrintSelectPrinterRec*)spr2)->printer_name);
471 }
472
473 /*
474  * ------------------------------------------------------------------------
475  * Name: CompoundTextToString
476  *
477  * Description:
478  *
479  *     
480  *
481  * Return value:
482  *
483  *     None.
484  *
485  */
486 static String
487 CompoundTextToString(
488                      Display* display,
489                      unsigned char* compound_text)
490 {
491     String str = (String)NULL;
492
493     if((unsigned char*)NULL != compound_text)
494     {
495         XTextProperty text_prop;
496         char** list;
497         int count;
498
499         text_prop.encoding = XInternAtom(display, "COMPOUND_TEXT", False);
500         text_prop.format = 8;
501         text_prop.value = compound_text;
502         text_prop.nitems = strlen((char*)text_prop.value);
503         if(Success ==
504            XmbTextPropertyToTextList(display, &text_prop, &list, &count))
505         {
506             if(count > 0)
507                 str = XtNewString(list[0]);
508             XFreeStringList(list);
509         }
510     }
511     return str;
512 }
513
514 /*
515  * ------------------------------------------------------------------------
516  * Name: CreateFileSelectionBox
517  *
518  * Description:
519  *
520  *     Creates the file selection dialog box.
521  *
522  * Return value:
523  *
524  *     None.
525  *
526  */
527 static XtEnum
528 CreateFileSelectionBox(
529                        Widget parent,
530                        Widget psub,
531                        DtPrintDefaultProcData* dpd)
532 {
533     Arg args[15];
534     Cardinal n;
535     XmString title_xmstr;
536
537     title_xmstr = XmStringCreateLocalized(SELECT_FILE_TITLE);
538     
539     n = 0;
540     /*
541      * dialog resources
542      */
543     XtSetArg(args[n], XmNdialogTitle, title_xmstr); n++;
544     XtSetArg(args[n], XmNdialogStyle,
545              XmDIALOG_PRIMARY_APPLICATION_MODAL); n++;
546     XtSetArg(args[n], XmNdeleteResponse, XmUNMAP); n++;
547     /*
548      * file selection box resources
549      */
550     XtSetArg(args[n], XmNautoUnmanage, True); n++;
551     /*
552      * create the file selection box dialog
553      */
554     dpd->file_selection_box =
555         XmCreateFileSelectionDialog(parent, "_PsubDefProcFileSelectionBox",
556                                     args, n);
557     XmStringFree(title_xmstr);
558     if(dpd->file_selection_box == (Widget)NULL)
559         return DtPRINT_FAILURE;
560     /*
561      * add callbacks
562      */
563     XtAddCallback(dpd->file_selection_box, XmNokCallback,
564                   UpdateFileNameCB, (XtPointer)psub);
565     XtAddCallback(dpd->file_selection_box, XmNhelpCallback,
566                   SelectFileHelpCB, (XtPointer)psub);
567     XtAddCallback(dpd->file_selection_box, XmNdestroyCallback,
568                   SelectFileDestroyCB, (XtPointer)psub);
569     /*
570      * return
571      */
572     return DtPRINT_SUCCESS;
573 }
574
575 /*
576  * ------------------------------------------------------------------------
577  * Name: CreatePrinterInfoBox
578  *
579  * Description:
580  *
581  *     Creates the printer information dialog box.
582  *
583  * Return value:
584  *
585  *     None.
586  *
587  */
588 static XtEnum
589 CreatePrinterInfoBox(
590                      Widget parent,
591                      Widget psub,
592                      DtPrintDefaultProcData* dpd)
593 {
594     Arg args[15];
595     Cardinal n;
596     XmString title_xmstr;
597     Widget manager;
598     Widget description_label, description;
599     Widget name_label, name;
600     Widget format_label, format;
601     Widget model_label, model;
602     XmString label;
603     
604     title_xmstr = XmStringCreateLocalized(PRINTER_INFO_TITLE);
605     
606     n = 0;
607     /*
608      * dialog resources
609      */
610     XtSetArg(args[n], XmNdialogTitle, title_xmstr); n++;
611     XtSetArg(args[n], XmNdialogStyle,
612              XmDIALOG_PRIMARY_APPLICATION_MODAL); n++;
613     XtSetArg(args[n], XmNdeleteResponse, XmUNMAP); n++;
614     /*
615      * printer info box resources
616      */
617     XtSetArg(args[n], XmNautoUnmanage, True); n++;
618     /*
619      * create the dialog
620      */
621     dpd->printer_info_box =
622         XmCreateInformationDialog(parent, "_PsubDefProcPrinterInfoBox",
623                                   args, n);
624     XmStringFree(title_xmstr);
625     if(dpd->printer_info_box == (Widget)NULL)
626         return DtPRINT_FAILURE;
627     /*
628      * add callbacks
629      */
630     XtAddCallback(dpd->printer_info_box, XmNhelpCallback,
631                   PrinterInfoHelpCB, (XtPointer)psub);
632     XtAddCallback(dpd->printer_info_box, XmNdestroyCallback,
633                   PrinterInfoDestroyCB, (XtPointer)psub);
634     XtAddCallback(dpd->printer_info_box, XmNmapCallback,
635                   InfoBoxLayoutCB, (XtPointer)dpd);
636     /*
637      * unmanage unwanted children
638      */
639     XtUnmanageChild(XtNameToWidget(dpd->printer_info_box, "Cancel"));
640     XtUnmanageChild(XtNameToWidget(dpd->printer_info_box, "Message"));
641     XtUnmanageChild(XtNameToWidget(dpd->printer_info_box, "Symbol"));
642     /*
643      * create the control manager
644      */
645     manager =
646         XtVaCreateManagedWidget("PrinterInfoForm", xmFormWidgetClass,
647                                 dpd->printer_info_box,
648                                 XmNallowOverlap, False,
649                                 NULL);
650     /*
651      * printer description
652      */
653     label = XmStringCreateLocalized(DESCRIPTION_LABEL);
654     description_label =
655         XtVaCreateManagedWidget("DescriptionLabel",
656                                 xmLabelWidgetClass,
657                                 manager,
658                                 XmNlabelString, label,
659                                 XmNleftAttachment,   XmATTACH_FORM,
660                                 XmNtopAttachment,    XmATTACH_FORM,
661                                 XmNtopOffset,        5,
662                                 NULL);
663     XmStringFree(label);
664     description = 
665         XtVaCreateManagedWidget("Description",
666                                 xmLabelWidgetClass,
667                                 manager,
668                                 XmNalignment,        XmALIGNMENT_BEGINNING,
669                                 XmNleftAttachment,   XmATTACH_WIDGET,
670                                 XmNleftWidget,       description_label,
671                                 XmNleftOffset,       10,
672                                 XmNtopAttachment,    XmATTACH_OPPOSITE_WIDGET,
673                                 XmNtopWidget,        description_label,
674                                 NULL);
675     /*
676      * printer name
677      */
678     label = XmStringCreateLocalized(PRINTER_NAME_LABEL);
679     name_label =
680         XtVaCreateManagedWidget("NameLabel",
681                                 xmLabelWidgetClass,
682                                 manager,
683                                 XmNlabelString, label,
684                                 XmNleftAttachment,   XmATTACH_FORM,
685                                 XmNtopAttachment,    XmATTACH_WIDGET,
686                                 XmNtopWidget,        description,
687                                 XmNtopOffset,        5,
688                                 NULL);
689     XmStringFree(label);
690     name = 
691         XtVaCreateManagedWidget("Name",
692                                 xmLabelWidgetClass,
693                                 manager,
694                                 XmNleftAttachment,   XmATTACH_WIDGET,
695                                 XmNleftWidget,       name_label,
696                                 XmNleftOffset,       10,
697                                 XmNtopAttachment,    XmATTACH_OPPOSITE_WIDGET,
698                                 XmNtopWidget,        name_label,
699                                 NULL);
700     /*
701      * printer format
702      */
703     label = XmStringCreateLocalized(FORMAT_LABEL);
704     format_label =
705         XtVaCreateManagedWidget("FormatLabel",
706                                 xmLabelWidgetClass,
707                                 manager,
708                                 XmNlabelString, label,
709                                 XmNleftAttachment,   XmATTACH_FORM,
710                                 XmNtopAttachment,    XmATTACH_WIDGET,
711                                 XmNtopWidget,        name_label,
712                                 XmNtopOffset,        5,
713                                 NULL);
714     XmStringFree(label);
715     format = 
716         XtVaCreateManagedWidget("Format",
717                                 xmLabelWidgetClass,
718                                 manager,
719                                 XmNleftAttachment,   XmATTACH_WIDGET,
720                                 XmNleftWidget,       format_label,
721                                 XmNleftOffset,       10,
722                                 XmNtopAttachment,    XmATTACH_OPPOSITE_WIDGET,
723                                 XmNtopWidget,        format_label,
724                                 NULL);
725     /*
726      * printer model
727      */
728     label = XmStringCreateLocalized(MODEL_LABEL);
729     model_label =
730         XtVaCreateManagedWidget("ModelLabel",
731                                 xmLabelWidgetClass,
732                                 manager,
733                                 XmNlabelString, label,
734                                 XmNleftAttachment,   XmATTACH_FORM,
735                                 XmNtopAttachment,    XmATTACH_WIDGET,
736                                 XmNtopWidget,        format_label,
737                                 XmNtopOffset,        5,
738                                 NULL);
739     XmStringFree(label);
740     model = 
741         XtVaCreateManagedWidget("Model",
742                                 xmLabelWidgetClass,
743                                 manager,
744                                 XmNalignment,        XmALIGNMENT_BEGINNING,
745                                 XmNleftAttachment,   XmATTACH_WIDGET,
746                                 XmNleftWidget,       model_label,
747                                 XmNleftOffset,       10,
748                                 XmNtopAttachment,    XmATTACH_OPPOSITE_WIDGET,
749                                 XmNtopWidget,        model_label,
750                                 NULL);
751     /*
752      * return
753      */
754     return DtPRINT_SUCCESS;
755 }
756
757 /*
758  * ------------------------------------------------------------------------
759  * Name: CreatePrinterSelectionBox
760  *
761  * Description:
762  *
763  *     Creates the printer selection dialog box.
764  *
765  * Return value:
766  *
767  *     None.
768  *
769  */
770 static XtEnum
771 CreatePrinterSelectionBox(
772                           Widget parent,
773                           Widget psub,
774                           DtPrintDefaultProcData* dpd)
775 {
776     Arg args[15];
777     Cardinal n;
778     Widget control;
779     XmString list_label;
780     XmString title_xmstr;
781     XmString info_label;
782
783     title_xmstr = XmStringCreateLocalized(MORE_PRINTERS_TITLE);
784     list_label = XmStringCreateLocalized(PRINTER_LIST_LABEL);
785     info_label = XmStringCreateLocalized(PRINTER_INFO_LABEL);
786     
787     n = 0;
788     /*
789      * dialog resources
790      */
791     XtSetArg(args[n], XmNdialogTitle, title_xmstr); n++;
792     XtSetArg(args[n], XmNdialogStyle,
793              XmDIALOG_PRIMARY_APPLICATION_MODAL); n++;
794     XtSetArg(args[n], XmNdeleteResponse, XmDESTROY); n++;
795     /*
796      * selection box resources
797      */
798     XtSetArg(args[n], XmNautoUnmanage, True); n++;
799     XtSetArg(args[n], XmNlistLabelString, list_label); n++;
800     XtSetArg(args[n], XmNapplyLabelString, info_label); n++;
801     /*
802      * create the dialog
803      */
804     dpd->printer_selection_box =
805         XmCreateSelectionDialog(parent, "_PsubDefProcPrinterSelectionBox",
806                                 args, n);
807     XmStringFree(list_label);
808     XmStringFree(info_label);
809     XmStringFree(title_xmstr);
810     if(dpd->printer_selection_box == (Widget)NULL)
811         return DtPRINT_FAILURE;
812     /*
813      * add callbacks
814      */
815     XtAddCallback(dpd->printer_selection_box, XmNokCallback,
816                   SelectPrinterCB, (XtPointer)psub);
817     XtAddCallback(dpd->printer_selection_box, XmNapplyCallback,
818                   SelectPrinterInfoCB, (XtPointer)psub);
819     XtAddCallback(dpd->printer_selection_box, XmNcancelCallback,
820                   SelectPrinterCB, (XtPointer)psub);
821     XtAddCallback(dpd->printer_selection_box, XmNhelpCallback,
822                   SelectPrinterHelpCB, (XtPointer)psub);
823     XtAddCallback(dpd->printer_selection_box, XmNdestroyCallback,
824                   SelectPrinterDestroyCB, (XtPointer)psub);
825     /*
826      * get the list box widget ID
827      */
828     dpd->printer_list_box =
829         XtNameToWidget(dpd->printer_selection_box, "*ItemsList");
830     XtAddCallback(dpd->printer_list_box, XmNbrowseSelectionCallback,
831                   SelectPrinterItemCB, (XtPointer)psub);
832     /*
833      * unmanaged unwanted children
834      */
835     control = XtNameToWidget(dpd->printer_selection_box, "*Selection");
836     if(control != (Widget)NULL)
837         XtUnmanageChild(control);
838     control = XtNameToWidget(dpd->printer_selection_box, "*Text");
839     if(control != (Widget)NULL)
840         XtUnmanageChild(control);
841     /*
842      * return
843      */
844     return DtPRINT_SUCCESS;
845 }
846
847 /*
848  * ------------------------------------------------------------------------
849  * Name: DestroyWidgetCB
850  *
851  * Description:
852  *
853  *     Destroys the Widget passed as client_data.
854  *
855  * Return value:
856  *
857  *     None.
858  *
859  */
860 static void 
861 DestroyWidgetCB(
862                 Widget w,
863                 XtPointer client_data,
864                 XtPointer call_data)
865 {
866     XtDestroyWidget((Widget)client_data);
867 }
868
869 /*
870  * ------------------------------------------------------------------------
871  * Name: DtPrintDefProcDestroyCB
872  *
873  * Description:
874  *
875  *     Free resources allocated for the default procedure data structure
876  *     in response to the destruction of the DtPrintSetupBox.
877  *
878  *     Calls destroy callbacks for dialogs *directly* because the dialogs
879  *     aren't children of the DtPrintSetupBox, but instead are more like
880  *     siblings or cousins of the PrintSetupBox whose common ancestor is
881  *     the shell parent of the PrintSetupBox. As such the dialogs may or
882  *     may not otherwise be destroyed when the PrintSetupBox is
883  *     destroyed. Furthermore the 2nd phase of the XtDestroyWidget calls
884  *     made in this routine isn't reached until after the PrintSetupBox
885  *     instance record has been destroyed (as part of the destroy phase
886  *     of which *this* call is a part).
887  *
888  *     The main reason this is a concern is because data associated with
889  *     these dialogs is stored in the PrintSetupBox widget instance
890  *     structure.
891  *
892  * Return value:
893  *
894  *     None.
895  *
896  */
897 static void
898 DtPrintDefProcDestroyCB(Widget w,
899                         XtPointer client_data,
900                         XtPointer call_data)
901 {
902     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
903
904     if(dpd->error_message_box)
905     {
906         XtRemoveCallback(dpd->error_message_box, XmNdestroyCallback,
907                          ErrorMessageDestroyCB, (XtPointer)w);
908         XtDestroyWidget(dpd->error_message_box);
909         ErrorMessageDestroyCB(dpd->error_message_box,
910                               (XtPointer)w, (XtPointer)NULL);
911     }
912     if(dpd->help_dialog)
913     {
914         XtRemoveCallback(dpd->help_dialog, XmNdestroyCallback,
915                          HelpDialogDestroyCB, (XtPointer)w);
916         XtDestroyWidget(dpd->help_dialog);
917         HelpDialogDestroyCB(dpd->help_dialog,
918                             (XtPointer)w, (XtPointer)NULL);
919     }
920     if(dpd->file_selection_box)
921     {
922         XtRemoveCallback(dpd->file_selection_box, XmNdestroyCallback,
923                          SelectFileDestroyCB, (XtPointer)w);
924         XtDestroyWidget(dpd->file_selection_box);
925         SelectFileDestroyCB(dpd->file_selection_box,
926                             (XtPointer)w, (XtPointer)NULL);
927     }
928     if(dpd->printer_selection_box)
929     {
930         XtRemoveCallback(dpd->printer_selection_box, XmNdestroyCallback,
931                          SelectPrinterDestroyCB, (XtPointer)w);
932         XtDestroyWidget(dpd->printer_selection_box);
933         SelectPrinterDestroyCB(dpd->printer_selection_box,
934                                (XtPointer)w, (XtPointer)NULL);
935     }
936     if(dpd->printer_info_box)
937     {
938         XtRemoveCallback(dpd->printer_info_box, XmNdestroyCallback,
939                          PrinterInfoDestroyCB, (XtPointer)w);
940         XtDestroyWidget(dpd->printer_info_box);
941         PrinterInfoDestroyCB(dpd->printer_info_box,
942                              (XtPointer)w, (XtPointer)NULL);
943     }
944     
945 }
946
947 /*
948  * ------------------------------------------------------------------------
949  * Name: ErrorMessageDestroyCB
950  *
951  * Description:
952  *
953  *     Reset the error message widget ID instance data when the message
954  *     box is destroyed.
955  *
956  *     This callback is considered part of the default resource
957  *     procedures and not part of the setup box widget proper.
958  *
959  * Return value:
960  *
961  *     None.
962  *
963  */
964 static void 
965 ErrorMessageDestroyCB(
966                       Widget w,
967                       XtPointer client_data,
968                       XtPointer call_data)
969 {
970     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(client_data);
971     
972     dpd->error_message_box = (Widget)NULL;
973 }
974
975 /*
976  * ------------------------------------------------------------------------
977  * Name: FindSelectedPrinter
978  *
979  * Description:
980  *
981  *     Build a full printer name by locating the currently selected
982  *     printer in the server list and printer list.
983  *
984  *
985  * Return value:
986  *
987  *     A newly allocated full printer name. It is the caller's
988  *     responsibility to free the returned String by calling XtFree.
989  *
990  */
991 static String
992 FindSelectedPrinter(
993                     Display* display,
994                     DtPrintDefaultProcData* dpd)
995 {
996     int printer_count;
997     int i;
998     int printer_index;
999
1000     /*
1001      * return if any of the structures are not in place
1002      */
1003     if(dpd->xp_server_list == (String*)NULL
1004        ||
1005        dpd->printer_counts == (int*)NULL
1006        ||
1007        dpd->printer_lists == (DtPrintSelectPrinterList*)NULL)
1008     {
1009         return (String)NULL;
1010     }
1011     /*
1012      * find the printer list containing the selected printer
1013      */
1014     if(0 == dpd->selected_printer)
1015         return (String)NULL;
1016     else
1017         printer_index = dpd->selected_printer - 1;
1018     
1019     for(i = 0, printer_count = 0; i < dpd->xp_server_count; i++)
1020     {
1021         if(printer_index < printer_count + (dpd->printer_counts)[i])
1022             break;
1023         else
1024             printer_count += (dpd->printer_counts)[i];
1025     }
1026     if(i < dpd->xp_server_count)
1027     {
1028         /*
1029          * build and return the printer name
1030          */
1031         DtPrintSelectPrinterList printer_list;
1032         String printer_spec;
1033         String printer_name;
1034         char* printer_name_ct;
1035         char* display_spec;
1036
1037         display_spec = (dpd->xp_server_list)[i];
1038         printer_list = (dpd->printer_lists)[i];
1039         printer_name_ct =
1040             printer_list[printer_index - printer_count].printer_name_ct;
1041         printer_name =
1042             CompoundTextToString(display, (unsigned char*)printer_name_ct);
1043         if((String)NULL != printer_name)
1044         {
1045             printer_spec =
1046                 _DtPrintCreateXPrinterSpecifier(printer_name,
1047                                                 display_spec,
1048                                                 DtPRINT_NET_UNSPECIFIED,
1049                                                 -1, -1);
1050             XtFree(printer_name);
1051             return printer_spec;
1052         }
1053     }
1054     return (String)NULL;
1055 }
1056
1057 /*
1058  * ------------------------------------------------------------------------
1059  * Name: FreeSelectPrinterData
1060  *
1061  * Description:
1062  *
1063  *     Deallocate and reset data items associated with the printer
1064  *     selection dialog.
1065  *
1066  * Return value:
1067  *
1068  *     None.
1069  */
1070 static void
1071 FreeSelectPrinterData(
1072                       DtPrintDefaultProcData* dpd)
1073 {
1074     int i, j;
1075     DtPrintSelectPrinterList printer_list;
1076     
1077     for(i = 0; i < dpd->xp_server_count; i++)
1078     {
1079         printer_list = dpd->printer_lists[i];
1080         for(j = 0; j < dpd->printer_counts[i]; j++)
1081         {
1082             XtFree(printer_list[j].printer_name_ct);
1083         }
1084         XtFree((char*)printer_list);
1085     }
1086     XtFree((char*)dpd->printer_lists);
1087     dpd->printer_lists = (DtPrintSelectPrinterList*)NULL;
1088     XtFree((char*)dpd->xp_server_list);
1089     dpd->xp_server_list = (String*)NULL;
1090     dpd->xp_server_count = 0;
1091     dpd->selected_printer = 0;
1092 }
1093
1094 /*
1095  * ------------------------------------------------------------------------
1096  * Name: GetWMShellAncestor
1097  *
1098  * Description:
1099  *
1100  *     Obtains the widget ID of the closest WMShell ancestor for
1101  *     the passed widget.
1102  *
1103  * Return value:
1104  *
1105  *     The widget ID of the closest WMShell ancestor.
1106  *
1107  */
1108 static Widget
1109 GetWMShellAncestor(Widget w)
1110 {
1111     Widget wmshell_ancestor = XtParent(w);
1112     while(wmshell_ancestor != (Widget)NULL)
1113     {
1114         if(XtIsWMShell(wmshell_ancestor))
1115             break;
1116         else
1117             wmshell_ancestor = XtParent(wmshell_ancestor);
1118     }
1119     return wmshell_ancestor;
1120 }
1121
1122 /*
1123  * ------------------------------------------------------------------------
1124  * Name: HelpDialogDestroyCB
1125  *
1126  * Description:
1127  *
1128  *     Reset the help dialog widget ID instance data when the widget
1129  *     is destroyed.
1130  *
1131  *     This callback is considered part of the default resource
1132  *     procedures and not part of the setup box widget proper.
1133  *
1134  * Return value:
1135  *
1136  *     None.
1137  *
1138  */
1139 static void 
1140 HelpDialogDestroyCB(
1141                     Widget w,
1142                     XtPointer client_data,
1143                     XtPointer call_data)
1144 {
1145     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(client_data);
1146     
1147     dpd->help_dialog = (Widget)NULL;
1148 }
1149
1150 /*
1151  * ------------------------------------------------------------------------
1152  * Name: InfoBoxLayoutCB
1153  *
1154  * Description:
1155  *
1156  *     Callback to right justify printer information dialog labels at
1157  *     mapping time.
1158  *
1159  * Return value:
1160  *
1161  *     None.
1162  *
1163  *
1164  */
1165 static void
1166 InfoBoxLayoutCB(
1167                 Widget widget,
1168                 XtPointer client_data,
1169                 XtPointer call_data)
1170 {
1171     DtPrintDefaultProcData* dpd = (DtPrintDefaultProcData*)client_data;
1172     Widget w[4];
1173     int i, widest;
1174     Dimension width, max_width;
1175     /*
1176      * only need to do this once after the widget is created
1177      */
1178     XtRemoveCallback(widget, XmNmapCallback, InfoBoxLayoutCB, client_data);
1179     /*
1180      * get the label widget ids
1181      */
1182     w[0] = XtNameToWidget(dpd->printer_info_box,
1183                           "PrinterInfoForm.DescriptionLabel");
1184     w[1] = XtNameToWidget(dpd->printer_info_box,
1185                           "PrinterInfoForm.NameLabel");
1186     w[2] = XtNameToWidget(dpd->printer_info_box,
1187                           "PrinterInfoForm.FormatLabel");
1188     w[3] = XtNameToWidget(dpd->printer_info_box,
1189                           "PrinterInfoForm.ModelLabel");
1190     /*
1191      * find the widest label
1192      */
1193     for(i = 0, widest = 0, max_width = 0; i < 4; i++)
1194     {
1195         XtVaGetValues(w[i], XmNwidth, &width, NULL);
1196         if(width > max_width)
1197         {
1198             widest = i;
1199             max_width = width;
1200         }
1201     }
1202     /*
1203      * sever the top attachment on the widest label in order to avoid
1204      * circular dependencies in form children; apparently one of the form
1205      * widget's many talents is the inability to manage the vertical and
1206      * horizontal attachments independently...
1207      */
1208     XtVaSetValues(w[widest], XmNtopAttachment, XmATTACH_SELF, NULL);
1209     /*
1210      * attach the right side of the smaller labels to the right side of
1211      * the widest label
1212      */
1213     for(i = 0; i < 4; i++)
1214         if(i != widest)
1215             XtVaSetValues(w[i],
1216                           XmNleftAttachment, XmATTACH_NONE,
1217                           XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
1218                           XmNrightWidget, w[widest],
1219                           NULL);
1220 }
1221
1222 /*
1223  * ------------------------------------------------------------------------
1224  * Name: ParseFileNameSpec
1225  *
1226  * Description:
1227  *
1228  *     Parse the passed file name to create a file selection box filter
1229  *     pattern and the name only portion of the full name spec.
1230  *
1231  *     It is the caller's responsibility to free the allocated memory
1232  *     returned in 'pattern' and 'name_only' using XmStringFree and
1233  *     XtFree respectively.
1234  *
1235  * Return value:
1236  *
1237  *     None.
1238  *
1239  *
1240  */
1241 static void
1242 ParseFileNameSpec(const char* file_name,
1243                   XmString* pattern_xmstr,
1244                   char** name_only)
1245 {
1246     String ptr;
1247     String pattern;
1248     /*
1249      * start off with a copy of the file name, ensuring there is
1250      * enough space for the added "*" and the string terminator.
1251      */
1252     pattern = XtMalloc(strlen(file_name)+2);
1253     strcpy(pattern, file_name);
1254     /*
1255      * find the last slash
1256      */
1257     ptr = DtStrrchr(pattern, '/');
1258     if(ptr != (String)NULL)
1259     {
1260         /*
1261          * grab the name portion of the file name
1262          */
1263         *name_only = XtNewString(ptr+1);
1264         /*
1265          * set the wildcard character immediately following the last
1266          * slash
1267          */
1268         strcpy(ptr+1, "*");
1269         *pattern_xmstr = XmStringCreateLocalized(pattern);
1270     }
1271     else
1272     {
1273         /*
1274          * no slash found; use the default pattern
1275          */
1276         *pattern_xmstr = (XmString)NULL;
1277         *name_only = XtNewString(file_name);
1278     }
1279     XtFree(pattern);
1280 }
1281
1282 /*
1283  * ------------------------------------------------------------------------
1284  * Name: PresentErrorDialog
1285  *
1286  * Description:
1287  *
1288  *     This is a utility function that will present an Error Dialog. It
1289  *     takes a title, a message, and a variable list of Strings to
1290  *     include in the message. The message parm is treated like a
1291  *     printf-style format string, except that only the "%s" directive is
1292  *     supported.
1293  *
1294  *     This function is to be used exclusively by the default
1295  *     resource procedures (e.g. _DtPrintSetupBoxVerifyXPrinterProc).
1296  *
1297  *     The variable list of String parms must be terminated by
1298  *     (String)NULL.
1299  *
1300  * Return Value:
1301  *
1302  *     None.
1303  *
1304  */
1305 static void
1306 PresentErrorDialog(
1307                    Widget w,
1308                    String title,
1309                    String message,
1310                    ...)
1311 {
1312     Arg args[15];
1313     Cardinal n;
1314     String expanded_message;
1315     String str_n;
1316     XmString message_xmstr;
1317     XmString title_xmstr;
1318     int message_len;
1319     va_list arg_marker;
1320     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
1321     Widget wmshell_ancestor;
1322     WidgetList wmshell_ancestors_children = (WidgetList)NULL;
1323     
1324     wmshell_ancestor = GetWMShellAncestor(w);
1325
1326     if (wmshell_ancestor)
1327     {
1328         n = 0;
1329         XtSetArg(args[n], XmNchildren, &wmshell_ancestors_children); n++;
1330         XtGetValues(wmshell_ancestor, args, n);
1331     }
1332
1333     if(dpd->error_message_box != (Widget)NULL)
1334     {
1335         /*
1336          * present only one message box
1337          */
1338         XtDestroyWidget(dpd->error_message_box);
1339     }
1340     
1341     title_xmstr = XmStringCreateLocalized(title);
1342     /*
1343      * determine length of expanded message
1344      */
1345     message_len = strlen(message);
1346     va_start(arg_marker, message);
1347     while((str_n = va_arg(arg_marker, String)) != (String)NULL)
1348     {
1349         message_len += strlen(str_n);
1350     }
1351     va_end(arg_marker);
1352     ++message_len;
1353     /*
1354      * expand the message
1355      */
1356     expanded_message = XtMalloc(message_len);
1357     va_start(arg_marker, message);
1358     vsprintf(expanded_message, message, arg_marker);
1359     va_end(arg_marker);
1360     /*
1361      * convert message to XmString
1362      */
1363     message_xmstr = XmStringCreateLocalized(expanded_message);
1364     XtFree(expanded_message);
1365     /*
1366      * create the error dialog
1367      */
1368     n = 0;
1369     XtSetArg(args[n], XmNdialogTitle, title_xmstr); n++;
1370     XtSetArg(args[n], XmNmessageString, message_xmstr); n++;
1371     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL); n++;
1372     XtSetArg(args[n], XmNdeleteResponse, XmDESTROY); n++;
1373     dpd->error_message_box = 
1374         XmCreateErrorDialog(wmshell_ancestors_children ?
1375                             wmshell_ancestors_children[0] :
1376                             wmshell_ancestor,
1377                             "_PsubDefProcErrorMsg", args, n);
1378     XmStringFree(title_xmstr);
1379     XmStringFree(message_xmstr);
1380
1381     XtUnmanageChild(XtNameToWidget(dpd->error_message_box, "Cancel"));
1382     XtUnmanageChild(XtNameToWidget(dpd->error_message_box, "Help"));
1383
1384     XtAddCallback(dpd->error_message_box, XmNokCallback,
1385                   DestroyWidgetCB, (XtPointer)dpd->error_message_box);
1386     XtAddCallback(dpd->error_message_box, XmNcancelCallback,
1387                   DestroyWidgetCB, (XtPointer)dpd->error_message_box);
1388     XtAddCallback(dpd->error_message_box, XmNdestroyCallback,
1389                   ErrorMessageDestroyCB, (XtPointer)w);
1390     /*
1391      * manage the message box according to the hint
1392      */
1393     if(DtPRINT_HINT_MESSAGES_OK == dpd->messages_hint)
1394         XtManageChild(dpd->error_message_box);
1395
1396 #ifdef XXX_JUNGLE_REMOVE
1397     /*
1398      * manage the message box only if the psub is mapped
1399      * and the focus is not in the printer name field
1400      */
1401     {
1402         XWindowAttributes attr;
1403         Status status;
1404         Window window = XtWindow(w);
1405         if(window)
1406         {
1407             status = XGetWindowAttributes(XtDisplay(w), window, &attr);
1408             if(status == 0 || attr.map_state == IsViewable)
1409             {
1410                 Widget name_w = XtNameToWidget(w, "Name");
1411                 Widget child;
1412                 
1413                 for(child = XmGetFocusWidget(w);
1414                     child != wmshell_ancestor && child != name_w
1415                     && child != (Widget)NULL;
1416                     child = XtParent(child));
1417
1418                 if(child != name_w && child != (Widget)NULL)
1419                     XtManageChild(dpd->error_message_box);
1420             }
1421         }
1422     }
1423 #endif /* XXX_JUNGLE_REMOVE */
1424 }
1425
1426 /*
1427  * ------------------------------------------------------------------------
1428  * Name: PresentHelp
1429  *
1430  * Description:
1431  *
1432  *     Presents a help dialog whose widget instance may be shared between
1433  *     the default dialogs.
1434  *
1435  * Return value:
1436  *
1437  *     None.
1438  *
1439  */
1440 static void PresentHelp(
1441                         Widget w,
1442                         const char* help_volume,
1443                         const char* location_id)
1444 {
1445     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
1446     Widget wmshell_ancestor;
1447     Widget dialog_shell;
1448     
1449     wmshell_ancestor = GetWMShellAncestor(w);
1450
1451     if((Widget)NULL == dpd->help_dialog)
1452     {
1453         Arg args[5];
1454         Cardinal n;
1455         XmString title;
1456         
1457         n = 0;
1458         title = XmStringCreateLocalized(HELP_DLG_TITLE);
1459         XtSetArg(args[n], XmNdialogTitle, title); n++;
1460         dpd->help_dialog =
1461             DtCreateHelpDialog(wmshell_ancestor, "_PsubDefProcHelpDialog",
1462                                args, n);
1463         XmStringFree(title);
1464         XtAddCallback(dpd->help_dialog, XmNdestroyCallback,
1465                       HelpDialogDestroyCB, (XtPointer)w);
1466     }
1467     /*
1468      * set the help volume and location
1469      */
1470     XtVaSetValues(dpd->help_dialog,
1471                   DtNhelpVolume, help_volume,
1472                   DtNlocationId, location_id,
1473                   DtNhelpType, DtHELP_TYPE_TOPIC,
1474                   NULL);
1475     /*
1476      * pop up the help dialog
1477      */
1478     XtManageChild(dpd->help_dialog);
1479     dialog_shell = XtParent(dpd->help_dialog);
1480     if(None != XtWindow(dialog_shell))
1481         XRaiseWindow(XtDisplay(dialog_shell), XtWindow(dialog_shell));
1482 }
1483
1484 /*
1485  * ------------------------------------------------------------------------
1486  * Name: PresentVerifyError
1487  *
1488  * Description:
1489  *
1490  *     Presents a error dialog appropriate for an error status returned
1491  *     by _DtPrintVerifyXPrinter.
1492  *
1493  * Return value:
1494  *
1495  *     None.
1496  *
1497  */
1498 static void
1499 PresentVerifyError(
1500                    Widget w,
1501                    XtEnum status,
1502                    String printer_spec)
1503 {
1504     String printer_name;
1505     String display_spec;
1506     
1507     _DtPrintParseXPrinterSpecifier(printer_spec,
1508                                    &printer_name,
1509                                    &display_spec);
1510     switch(status)
1511     {
1512     case DtPRINT_PRINTER_MISSING:
1513         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1514                            PRINTER_MISSING_MESSAGE,
1515                            printer_spec,
1516                            (String)NULL);
1517         break;
1518
1519     case DtPRINT_NO_DEFAULT:
1520         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1521                            NO_DEFAULT_MESSAGE,
1522                            (String)NULL);
1523         break;
1524
1525     case DtPRINT_NO_DEFAULT_DISPLAY:
1526         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1527                            NO_DEFAULT_DISPLAY_MESSAGE,
1528                            printer_name,
1529                            (String)NULL);
1530         break;
1531         
1532     case DtPRINT_NO_PRINTER:
1533         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1534                            INVALID_PRINTER_MESSAGE,
1535                            printer_name, display_spec,
1536                            (String)NULL);
1537         break;
1538
1539     case DtPRINT_NOT_XP_DISPLAY:
1540         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1541                            NOT_XP_DISPLAY_MESSAGE,
1542                            display_spec,
1543                            (String)NULL);
1544         break;
1545
1546     case DtPRINT_INVALID_DISPLAY:
1547         PresentErrorDialog(w, INVALID_PRINTER_TITLE,
1548                            INVALID_DISPLAY_MESSAGE,
1549                            display_spec,
1550                            (String)NULL);
1551         break;
1552     }
1553     XtFree(printer_name);
1554     XtFree(display_spec);
1555 }
1556
1557
1558 /*
1559  * ------------------------------------------------------------------------
1560  * Name: PrinterInfoDestroyCB
1561  *
1562  * Description:
1563  *
1564  *     Reset data items used in conjunction with the
1565  *     printer information selection dialog.
1566  *
1567  * Return value:
1568  *
1569  *     None.
1570  *
1571  */
1572 static void
1573 PrinterInfoDestroyCB(
1574                     Widget w,
1575                     XtPointer client_data,
1576                     XtPointer call_data)
1577 {
1578     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(client_data);
1579
1580     dpd->printer_info_box = (Widget)NULL;
1581 }
1582
1583 /*
1584  * ------------------------------------------------------------------------
1585  * Name: PrinterInfoHelpCB
1586  *
1587  * Description:
1588  *
1589  *     Display context sensitive help.
1590  *
1591  * Return value:
1592  *
1593  *     None.
1594  *
1595  */
1596 static void
1597 PrinterInfoHelpCB(
1598                   Widget w,
1599                   XtPointer client_data,
1600                   XtPointer call_data)
1601 {
1602     PresentHelp((Widget)client_data, HELP_VOLUME, PRINTER_INFO_HELP_ID);
1603 }
1604
1605 /*
1606  * ------------------------------------------------------------------------
1607  * Name: SelectFileDestroyCB
1608  *
1609  * Description:
1610  *
1611  *     Reset data items used in conjunction with the
1612  *     file selection dialog.
1613  *
1614  * Return value:
1615  *
1616  *     None.
1617  *
1618  */
1619 static void
1620 SelectFileDestroyCB(
1621                     Widget w,
1622                     XtPointer client_data,
1623                     XtPointer call_data)
1624 {
1625     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(client_data);
1626
1627     dpd->file_selection_box = (Widget)NULL;
1628 }
1629
1630 /*
1631  * ------------------------------------------------------------------------
1632  * Name: SelectFileHelpCB
1633  *
1634  * Description:
1635  *
1636  *     Display context sensitive help.
1637  *
1638  * Return value:
1639  *
1640  *     None.
1641  *
1642  */
1643 static void
1644 SelectFileHelpCB(
1645                  Widget w,
1646                  XtPointer client_data,
1647                  XtPointer call_data)
1648 {
1649     PresentHelp((Widget)client_data, HELP_VOLUME, SELECT_FILE_HELP_ID);
1650 }
1651
1652 /*
1653  * ------------------------------------------------------------------------
1654  * Name: SelectPrinterCB
1655  *
1656  * Description:
1657  *
1658  *     Callback to handle the printer selection box OK and Cancel
1659  *     buttons.
1660  *
1661  * Return value:
1662  *
1663  *     None.
1664  *
1665  */
1666 static void
1667 SelectPrinterCB(
1668                 Widget w,
1669                 XtPointer client_data,
1670                 XtPointer call_data)
1671 {
1672     XmSelectionBoxCallbackStruct* cbs =
1673         (XmSelectionBoxCallbackStruct*)call_data;
1674     Widget psub = (Widget)client_data;
1675     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(psub);
1676     String printer_spec;
1677
1678     /*
1679      * close the info dialog display connection if it's been opened
1680      */
1681     CloseSelectPrinterInfoConnection(dpd);
1682
1683     switch(cbs->reason)
1684     {
1685     case XmCR_OK:
1686         /*
1687          * set the selected printer name in the PrintSetupBox
1688          */
1689         printer_spec = FindSelectedPrinter(XtDisplay(psub), dpd);
1690         if((String)NULL != printer_spec)
1691         {
1692             XtVaSetValues(psub, DtNprinterName, printer_spec, NULL);
1693             XtFree(printer_spec);
1694         }
1695         /*
1696          * no break
1697          */
1698
1699     case XmCR_CANCEL:
1700         /*
1701          * deallocate and reset the lists
1702          */
1703         FreeSelectPrinterData(dpd);
1704         if(dpd->printer_list_box != (Widget)NULL)
1705             XmListDeleteAllItems(dpd->printer_list_box);
1706         break;
1707     }
1708 }
1709
1710 /*
1711  * ------------------------------------------------------------------------
1712  * Name: SelectPrinterDestroyCB
1713  *
1714  * Description:
1715  *
1716  *     Deallocate and reset data items used in conjunction with the
1717  *     printer selection dialog.
1718  *
1719  * Return value:
1720  *
1721  *     None.
1722  *
1723  */
1724 static void
1725 SelectPrinterDestroyCB(
1726                        Widget w,
1727                        XtPointer client_data,
1728                        XtPointer call_data)
1729 {
1730     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(client_data);
1731
1732     dpd->printer_selection_box = (Widget)NULL;
1733     dpd->printer_list_box = (Widget)NULL;
1734     CloseSelectPrinterInfoConnection(dpd);
1735     FreeSelectPrinterData(dpd);
1736 }
1737
1738 /*
1739  * ------------------------------------------------------------------------
1740  * Name: SelectPrinterHelpCB
1741  *
1742  * Description:
1743  *
1744  *     Display context sensitive help.
1745  *
1746  * Return value:
1747  *
1748  *     None.
1749  *
1750  */
1751 static void
1752 SelectPrinterHelpCB(
1753                     Widget w,
1754                     XtPointer client_data,
1755                     XtPointer call_data)
1756 {
1757     PresentHelp((Widget)client_data, HELP_VOLUME, SELECT_PRINTER_HELP_ID);
1758 }
1759
1760 /*
1761  * ------------------------------------------------------------------------
1762  * Name: SelectPrinterInfoCB
1763  *
1764  * Description:
1765  *
1766  *     Callback attached to the printer selection box "Info..."
1767  *     button. The "Info..." button is intended to behave just like the
1768  *     PrintSetupBox "Info..." button, so it is implemented to call the
1769  *     procedure set for the PrintSetupBox DtNprinterInfoProc resource.
1770  *     As such, this function needs to open a new display connection to
1771  *     the print server indicated by the currently selected printer in
1772  *     the list. The connection is not closed until a selection is made
1773  *     in the list, or the printer selection dialog is dismissed. This is
1774  *     because no assumptions about the Printer Info dialog's widget
1775  *     hierarchy can be made.
1776  *
1777  * Return value:
1778  *
1779  *     None.
1780  *
1781  */
1782 static void
1783 SelectPrinterInfoCB(
1784                     Widget w,
1785                     XtPointer client_data,
1786                     XtPointer call_data)
1787 {
1788     Widget psub = (Widget)client_data;
1789     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(psub);
1790     DtPrintSetupProc info_proc;
1791
1792     CloseSelectPrinterInfoConnection(dpd);
1793     XtVaGetValues(psub, DtNprinterInfoProc, &info_proc, NULL);
1794     if((DtPrintSetupProc)NULL != info_proc)
1795     {
1796         String printer_spec;
1797         
1798         printer_spec = FindSelectedPrinter(XtDisplay(psub), dpd);
1799         if((String)NULL != printer_spec)
1800         {
1801             String new_printer_spec; /*
1802                                       * will always be set to NULL by
1803                                       * _DtPrintVerifyXPrinter when
1804                                       * called from within this routine
1805                                       */
1806             XtEnum status;
1807             
1808             /*
1809              * open a connection to the X printer
1810              */
1811             status =
1812                 _DtPrintVerifyXPrinter(psub,
1813                                        printer_spec,
1814                                        &new_printer_spec,
1815                                        &dpd->select_printer_info_display
1816 #if 0 && defined(PRINTING_SUPPORTED)
1817                                        ,&dpd->select_printer_info_context
1818 #endif /* PRINTING_SUPPORTED */
1819                                        );
1820             if(status == DtPRINT_SUCCESS)
1821             {
1822                 DtPrintSetupData psd;
1823
1824                 memset(&psd, 0, sizeof(DtPrintSetupData));
1825                 psd.printer_name = printer_spec;
1826                 psd.print_display = dpd->select_printer_info_display;
1827 #if 0 && defined(PRINTING_SUPPORTED)
1828                 psd.print_context = dpd->select_printer_info_context;
1829 #endif /* PRINTING_SUPPORTED */
1830                 (*info_proc)(psub, &psd);
1831             }
1832             else
1833             {
1834                 /*
1835                  * this should only happen if, while a user is viewing
1836                  * the printer selection dialog, a server rehash is
1837                  * performed that deletes the currently selected printer
1838                  */
1839                 PresentVerifyError(w, status, printer_spec);
1840             }
1841             XtFree(printer_spec);
1842         }
1843     }
1844 }
1845
1846 /*
1847  * ------------------------------------------------------------------------
1848  * Name: SelectPrinterItemCB
1849  *
1850  * Description:
1851  *
1852  *     Callback to handle the a selection in the printer selection list
1853  *     box.
1854  *
1855  * Return value:
1856  *
1857  *     None.
1858  *
1859  */
1860 static void
1861 SelectPrinterItemCB(
1862                     Widget w,
1863                     XtPointer client_data,
1864                     XtPointer call_data)
1865 {
1866     XmListCallbackStruct* cbs =
1867         (XmListCallbackStruct*)call_data;
1868     Widget psub = (Widget)client_data;
1869     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(psub);
1870     Widget info_button;
1871
1872     if(dpd->selected_printer != cbs->item_position)
1873     {
1874         dpd->selected_printer = cbs->item_position;
1875         info_button = XtNameToWidget(dpd->printer_selection_box, "*Apply");
1876         if(0 == dpd->selected_printer)
1877             XtSetSensitive(info_button, False);
1878         else
1879             XtSetSensitive(info_button, True);
1880         /*
1881          * update the default printer info dialog if it is visible
1882          */
1883         if(dpd->printer_info_box && XtIsManaged(dpd->printer_info_box))
1884             SelectPrinterInfoCB(w, client_data, (XtPointer)NULL);
1885     }
1886 }
1887
1888 /*
1889  * ------------------------------------------------------------------------
1890  * Name: SetListBoxSelection
1891  *
1892  * Description:
1893  *
1894  *
1895  * Return value:
1896  *
1897  *     None.
1898  *
1899  */
1900 static void
1901 SetListBoxSelection(Widget list_box, int position)
1902 {
1903     int visible_item_count;
1904     int item_count;
1905     int middle_offset;
1906     int first_visible_pos;
1907     /*
1908      * Scroll the list, making the item at the indicated position
1909      * visible in the center of the list box, and make
1910      * it the initial selection.
1911      */
1912     XtVaGetValues(list_box,
1913                   XmNitemCount, &item_count,
1914                   XmNvisibleItemCount, &visible_item_count,
1915                   NULL);
1916
1917     if(item_count > visible_item_count)
1918     {
1919         middle_offset = (visible_item_count+1) / 2;
1920         if(position > middle_offset)
1921             if(position > item_count - middle_offset)
1922                 first_visible_pos = item_count - visible_item_count +1;
1923             else
1924                 first_visible_pos = position - middle_offset + 1;
1925         else
1926             first_visible_pos = 1;
1927         XmListSetPos(list_box, first_visible_pos);
1928     }
1929
1930     if(position > 0)
1931         XmListSelectPos(list_box, position, True);
1932     else
1933         XmListDeselectAllItems(list_box);
1934 }
1935
1936 /*
1937  * ------------------------------------------------------------------------
1938  * Name: UpdateFileNameCB
1939  *
1940  * Description:
1941  *
1942  *     Updates the PrintSetupBox fileName resource based on the selection
1943  *     make in the file selection box.
1944  *
1945  * Return value:
1946  *
1947  *     None.
1948  *
1949  */
1950 static void 
1951 UpdateFileNameCB(
1952                  Widget w,
1953                  XtPointer client_data,
1954                  XtPointer call_data)
1955 {
1956     Widget text_field;
1957     Widget psub = (Widget)client_data;
1958     String file_name;
1959     /*
1960      * get the file name from the file selection box text field
1961      */
1962     text_field = XtNameToWidget(w, "Text");
1963     if(text_field)
1964     {
1965         XtVaGetValues(text_field, XmNvalue, &file_name, NULL);
1966         if(file_name)
1967         {
1968             /*
1969              * set the file name in the print setup box
1970              */
1971             XtVaSetValues(psub, DtNfileName, file_name, NULL);
1972             /*
1973              * free the file name retrieved from the text field
1974              */
1975             XtFree(file_name);
1976         }
1977     }
1978 }
1979
1980 /*
1981  * ------------------------------------------------------------------------
1982  * Name: _DtPrintDefProcInitialize
1983  *
1984  * Description:
1985  *
1986  *     
1987  *
1988  * Return value:
1989  *
1990  *
1991  */
1992 void
1993 _DtPrintDefProcInitialize(Widget w)
1994 {
1995     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
1996     
1997     dpd->error_message_box = (Widget)NULL;
1998     dpd->messages_hint = DtPRINT_HINT_MESSAGES_OK;
1999     dpd->help_dialog = (Widget)NULL;
2000     dpd->file_selection_box = (Widget)NULL;
2001     dpd->printer_selection_box = (Widget)NULL;
2002     dpd->printer_list_box = (Widget)NULL;
2003     dpd->xp_server_list = (String*)NULL;
2004     dpd->xp_server_count = 0;
2005     dpd->printer_lists = (DtPrintSelectPrinterList*)NULL;
2006     dpd->selected_printer = 0;
2007     dpd->select_printer_info_display = (Display*)NULL;
2008 #if 0 && defined(PRINTING_SUPPORTED)
2009     dpd->select_printer_info_context = (XPContext)None;
2010 #endif /* PRINTING_SUPPORTED */
2011     dpd->printer_info_box = (Widget)NULL;
2012
2013     XtAddCallback(w, XmNdestroyCallback,
2014                   DtPrintDefProcDestroyCB, (XtPointer)NULL);
2015 }
2016
2017 /*
2018  * ------------------------------------------------------------------------
2019  * Name: _DtPrintDefProcManageErrorBox
2020  *
2021  * Description:
2022  *
2023  *     Manage the Error Message Box if it exists.
2024  *
2025  * Return value:
2026  *
2027  *
2028  */
2029 void
2030 _DtPrintDefProcManageErrorBox(
2031                               DtPrintDefaultProcData* dpd)
2032 {
2033     if(dpd->error_message_box != (Widget)NULL)
2034         XtManageChild(dpd->error_message_box);
2035 }
2036
2037 /*
2038  * ------------------------------------------------------------------------
2039  * Name: _DtPrintSetupBoxXPrinterInfoProc
2040  *
2041  * Description:
2042  *
2043  *     Default Xp mode function for the DtNprinterInfoProc resource.
2044  *
2045  * Return value:
2046  *
2047  *
2048  */
2049 XtEnum
2050 _DtPrintSetupBoxXPrinterInfoProc(
2051                                  Widget w,
2052                                  DtPrintSetupData* print_data)
2053 {
2054     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
2055     Widget wmshell_ancestor;
2056     Widget ctl;
2057     XmString label;
2058     char* attr_value_ct = NULL;
2059     String attr_value = NULL;
2060     XmString empty_label;
2061     Widget name_label_top;
2062     Position max_y, y;
2063     Dimension height;
2064     Widget manager = NULL;
2065     Widget dialog_shell;
2066     
2067     wmshell_ancestor = GetWMShellAncestor(w);
2068     _DtTurnOnHourGlass(wmshell_ancestor);
2069     empty_label = XmStringCreateLocalized("");
2070     /*
2071      * if needed, create the printer information dialog
2072      */
2073     if(dpd->printer_info_box == (Widget)NULL)
2074     {
2075         XtEnum status = CreatePrinterInfoBox(wmshell_ancestor, w, dpd);
2076         if(status != DtPRINT_SUCCESS)
2077         {
2078             _DtTurnOffHourGlass(wmshell_ancestor);
2079             return status;
2080         }
2081         dialog_shell = XtParent(dpd->printer_info_box);
2082     }
2083     else
2084     {
2085         /*
2086          * hide the widget during re-layout
2087          */
2088         manager = XtNameToWidget(dpd->printer_info_box, "*PrinterInfoForm");
2089         XtUnmapWidget(dpd->printer_info_box);
2090         dialog_shell = XtParent(dpd->printer_info_box);
2091         XtVaSetValues(dialog_shell, XmNallowShellResize, False, NULL);
2092         XtUnmanageChild(manager);
2093     }
2094     /*
2095      * description
2096      */
2097     ctl = XtNameToWidget(dpd->printer_info_box, "*Description");
2098     XtVaSetValues(ctl, XmNlabelString, empty_label, NULL);
2099 #if 0 && defined(PRINTING_SUPPORTED)
2100     attr_value_ct = XpGetOneAttribute(print_data->print_display,
2101                                       print_data->print_context,
2102                                       XPPrinterAttr,
2103                                       "descriptor");
2104 #endif /* PRINTING_SUPPORTED */
2105     if((char*)NULL != attr_value_ct)
2106     {
2107         attr_value =
2108             CompoundTextToString(XtDisplay(w), (unsigned char*)attr_value_ct);
2109         XFree(attr_value_ct);
2110         if((String)NULL != attr_value)
2111         {
2112             label = XmStringGenerate((XtPointer)attr_value, (XmStringTag)NULL,
2113                                      XmMULTIBYTE_TEXT, (XmStringTag)NULL);
2114             XtFree(attr_value);
2115             XtVaSetValues(ctl, XmNlabelString, label, NULL);
2116             XmStringFree(label);
2117         }
2118     }
2119     /*
2120      * set the top attachment for the name label
2121      */
2122     XtVaGetValues(ctl, XmNy, &y, XmNheight, &height, NULL);
2123     max_y = y + height;
2124     name_label_top = ctl;
2125     ctl = XtNameToWidget(dpd->printer_info_box, "*DescriptionLabel");
2126     XtVaGetValues(ctl, XmNy, &y, XmNheight, &height, NULL);
2127     if(y+height > max_y)
2128         name_label_top = ctl;
2129     ctl = XtNameToWidget(dpd->printer_info_box, "*NameLabel");
2130     XtVaSetValues(ctl, XmNtopWidget, name_label_top, NULL);
2131     /*
2132      * printer name
2133      */
2134     ctl = XtNameToWidget(dpd->printer_info_box, "*Name");
2135     label = XmStringCreateLocalized(print_data->printer_name);
2136     XtVaSetValues(ctl, XmNlabelString, label, NULL);
2137     XmStringFree(label);
2138     /*
2139      * document format
2140      */
2141     ctl = XtNameToWidget(dpd->printer_info_box, "*Format");
2142     XtVaSetValues(ctl, XmNlabelString, empty_label, NULL);
2143 #if 0 && defined(PRINTING_SUPPORTED)
2144     attr_value = XpGetOneAttribute(print_data->print_display,
2145                                    print_data->print_context,
2146                                    XPDocAttr,
2147                                    "document-format");
2148 #endif /* PRINTING_SUPPORTED */
2149     if((String)NULL != attr_value)
2150     {
2151         char* format_start;
2152         format_start = strchr(attr_value, '{');
2153         if((char*)NULL != format_start)
2154         {
2155             char* format_end;
2156             ++format_start;
2157             format_end = strchr(format_start, '}');
2158             if((char*)NULL != format_end)
2159             {
2160                 *format_end = '\0';
2161                 label = XmStringCreateLocalized(format_start);
2162                 XtVaSetValues(ctl, XmNlabelString, label, NULL);
2163                 XmStringFree(label);
2164             }
2165         }
2166         XFree(attr_value);
2167     }
2168     /*
2169      * printer model
2170      */
2171     ctl = XtNameToWidget(dpd->printer_info_box, "*Model");
2172     XtVaSetValues(ctl, XmNlabelString, empty_label, NULL);
2173 #if 0 && defined(PRINTING_SUPPORTED)
2174     attr_value_ct = XpGetOneAttribute(print_data->print_display,
2175                                       print_data->print_context,
2176                                       XPPrinterAttr,
2177                                       "printer-model");
2178 #endif /* PRINTING_SUPPORTED */
2179     if((char*)NULL != attr_value_ct)
2180     {
2181         attr_value =
2182             CompoundTextToString(XtDisplay(w), (unsigned char*)attr_value_ct);
2183         XFree(attr_value_ct);
2184         if((String)NULL != attr_value)
2185         {
2186             label = XmStringGenerate((XtPointer)attr_value, (XmStringTag)NULL,
2187                                      XmCHARSET_TEXT, (XmStringTag)NULL);
2188             XtFree(attr_value);
2189             XtVaSetValues(ctl, XmNlabelString, label, NULL);
2190             XmStringFree(label);
2191         }
2192     }
2193     /*
2194      * pop up the printer info dialog and return
2195      */
2196     XmStringFree(empty_label);
2197     if(manager)
2198     {
2199         XtVaSetValues(dialog_shell, XmNallowShellResize, True, NULL);
2200         XtManageChild(manager);
2201         XtMapWidget(dpd->printer_info_box);
2202     }
2203     XtManageChild(dpd->printer_info_box);
2204     if(None != XtWindow(dialog_shell))
2205         XRaiseWindow(XtDisplay(dialog_shell), XtWindow(dialog_shell));
2206     _DtTurnOffHourGlass(wmshell_ancestor);
2207     return DtPRINT_SUCCESS;
2208 }
2209
2210 /*
2211  * ------------------------------------------------------------------------
2212  * Name: _DtPrintSetupBoxSelectFileProc
2213  *
2214  * Description:
2215  *
2216  *     Default function for the DtNselectFileProc resource.
2217  *
2218  * Return value:
2219  *
2220  *
2221  */
2222 XtEnum
2223 _DtPrintSetupBoxSelectFileProc(
2224                                Widget w,
2225                                DtPrintSetupData* print_data)
2226 {
2227     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
2228     String name_only;
2229     String file_name;
2230     XmString pattern;
2231     Widget file_list;
2232     Widget text_field;
2233     Widget wmshell_ancestor;
2234     
2235     wmshell_ancestor = GetWMShellAncestor(w);
2236     _DtTurnOnHourGlass(wmshell_ancestor);
2237     /*
2238      * if needed, create the file selection dialog
2239      */
2240     if(dpd->file_selection_box == (Widget)NULL)
2241     {
2242         XtEnum status = CreateFileSelectionBox(wmshell_ancestor, w, dpd);
2243         if(status != DtPRINT_SUCCESS)
2244         {
2245             _DtTurnOffHourGlass(wmshell_ancestor);
2246             return status;
2247         }
2248     }
2249     /*
2250      * get the file name passed from the PrintSetupBox
2251      */
2252     file_name = print_data->dest_info;
2253     /*
2254      * parse the file name to create the filter pattern and the name only
2255      * portion of the full name spec
2256      */
2257     ParseFileNameSpec(file_name, &pattern, &name_only);
2258     /*
2259      * set the filter pattern in the file selection box
2260      */
2261     XtVaSetValues(dpd->file_selection_box, XmNpattern, pattern, NULL);
2262     if(pattern != (XmString)NULL)
2263         XmStringFree(pattern);
2264     /*
2265      * select the current file name in the file names list
2266      */
2267     file_list = XtNameToWidget(dpd->file_selection_box, "*ItemsList");
2268     if(file_list != (Widget)NULL)
2269     {
2270         XmString file_name_xmstr;
2271         int position;
2272
2273         text_field = XtNameToWidget(dpd->file_selection_box, "Text");
2274         if(text_field != (Widget)NULL)
2275         {
2276             String dir_spec;
2277             /*
2278              * recreate the file name from the name_only and the current
2279              * dir spec as determined by the file selection box
2280              *
2281              * Note: the char* value retrieved directly from the text
2282              * field is used, because forming the file name from a
2283              * concatenation of XmStrings causes XmListItemPos to fail
2284              * even though the file name is actually in the list.
2285              */
2286             XtVaGetValues(text_field, XmNvalue, &dir_spec, NULL);
2287             file_name = XtMalloc(strlen(dir_spec)+strlen(name_only)+1);
2288             strcpy(file_name, dir_spec);
2289             strcat(file_name, name_only);
2290             file_name_xmstr = XmStringCreateLocalized(file_name);
2291             XtFree(dir_spec);
2292             XtFree(file_name);
2293         }
2294         else
2295             file_name_xmstr = XmStringCreateLocalized(file_name);
2296         /*
2297          * find the position of the file name in the list
2298          */
2299         position = XmListItemPos(file_list, file_name_xmstr);
2300         SetListBoxSelection(file_list, position);
2301         if(position == 0)
2302         {
2303             /*
2304              * The file name is not in the list. Manually set in the
2305              * "Selection" text field.
2306              */
2307             XtVaSetValues(dpd->file_selection_box,
2308                           XmNdirSpec, file_name_xmstr,
2309                           NULL);
2310         }
2311         XmStringFree(file_name_xmstr);
2312     }
2313     XtFree(name_only);
2314     /*
2315      * pop up the file selection dialog and return
2316      */
2317     XtManageChild(dpd->file_selection_box);
2318     _DtTurnOffHourGlass(wmshell_ancestor);
2319     return DtPRINT_SUCCESS;
2320 }
2321
2322 /*
2323  * ------------------------------------------------------------------------
2324  * Name: _DtPrintSetupBoxSelectXPrinterProc
2325  *
2326  * Description:
2327  *
2328  *     Default Xp mode function for the DtNselectPrinterProc resource.
2329  *
2330  * Return value:
2331  *
2332  *
2333  */
2334 XtEnum
2335 _DtPrintSetupBoxSelectXPrinterProc(
2336                                    Widget w,
2337                                    DtPrintSetupData* print_data)
2338 {
2339     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
2340     Widget wmshell_ancestor;
2341     XmStringTable items;
2342     int item_count;
2343     int i;
2344     XmTabList tab_list;
2345     XmRenderTable render_table, new_render_table;
2346     int count;
2347     XmStringTag* tags;
2348     XmRendition rendition;
2349     Arg args[2];
2350     Cardinal n;
2351
2352     wmshell_ancestor = GetWMShellAncestor(w);
2353     _DtTurnOnHourGlass(wmshell_ancestor);
2354     /*
2355      * build the list of servers and printers
2356      */
2357     if(DtPRINT_SUCCESS != BuildPrinterLists(w, dpd, &item_count))
2358     {
2359         PresentErrorDialog(w, PRLIST_ERROR_TITLE,
2360                            NO_PRINTERS_MESSAGE,
2361                            (String)NULL);
2362         _DtTurnOffHourGlass(wmshell_ancestor);
2363         return DtPRINT_FAILURE;
2364     }
2365     /*
2366      * create the dialog if it doesn't exist
2367      */
2368     if(dpd->printer_selection_box == (Widget)NULL)
2369     {
2370         XtEnum status = CreatePrinterSelectionBox(wmshell_ancestor, w, dpd);
2371         if(status != DtPRINT_SUCCESS)
2372         {
2373             _DtTurnOffHourGlass(wmshell_ancestor);
2374             return status;
2375         }
2376     }
2377     /*
2378      * get a copy of the list widget's render table
2379      */
2380     XtVaGetValues(dpd->printer_list_box,
2381                   XmNrenderTable, &render_table,
2382                   NULL);
2383     render_table = XmRenderTableCopy(render_table, (XmStringTag*)NULL, 0);
2384     /*
2385      * build the item list for the list box
2386      */
2387     count = XmRenderTableGetTags(render_table, &tags);
2388     items = BuildPrinterSelectionItems(XtDisplay(w), dpd, item_count,
2389                                        print_data->printer_name, tags[0]);
2390     /*
2391      * generate a tab list for the items
2392      */
2393     tab_list = XmStringTableProposeTablist(items, item_count,
2394                                            dpd->printer_list_box,
2395                                            20, XmRELATIVE);
2396     /*
2397      * get a copy of the first rendition in the render table
2398      */
2399     rendition = XmRenderTableGetRendition(render_table, tags[0]);
2400     for(i = 0; i < count; i++)
2401         XtFree(tags[i]);
2402     XtFree((char*)tags);
2403     /*
2404      * update the copy with the new tab list
2405      */
2406     n = 0;
2407     XtSetArg(args[n], XmNtabList, tab_list); n++;
2408     XmRenditionUpdate(rendition, args, n);
2409     XmTabListFree(tab_list);
2410     /*
2411      * create a new render table replacing the first entry with the
2412      * updated rendition
2413      */
2414     new_render_table = XmRenderTableAddRenditions(render_table, &rendition,
2415                                                   1, XmMERGE_REPLACE);
2416     XmRenditionFree(rendition);
2417     /*
2418      * set the new render table and list items in the list box
2419      */
2420     XtVaSetValues(dpd->printer_list_box,
2421                   XmNrenderTable, new_render_table,
2422                   XmNitems, items,
2423                   XmNitemCount, item_count,
2424                   NULL);
2425     XmRenderTableFree(new_render_table);
2426     for(i = 0; i < item_count; i++)
2427         XmStringFree(items[i]);
2428     XtFree((char*)items);
2429     SetListBoxSelection(dpd->printer_list_box, dpd->selected_printer);
2430     /*
2431      * disable the info button if nothing is selected
2432      */
2433     if(0 == dpd->selected_printer)
2434         XtSetSensitive(XtNameToWidget(dpd->printer_selection_box, "*Apply"),
2435                        False);
2436     /*
2437      * manage the dialog and return
2438      */
2439     XtManageChild(dpd->printer_selection_box);
2440     _DtTurnOffHourGlass(wmshell_ancestor);
2441     return DtPRINT_SUCCESS;
2442 }
2443
2444 /*
2445  * ------------------------------------------------------------------------
2446  * Name: _DtPrintSetupBoxVerifyXPrinterProc
2447  *
2448  * Description:
2449  *
2450  *     Default function for the DtNverifyPrinterProc resource when the
2451  *     setup mode is XP.
2452  *
2453  *     (this rest of this description outlines the responsibilities of a
2454  *     DtNverifyPrinterProc in general)
2455  *
2456  *     This function verifies the printer name passed in the
2457  *     PrintSetupData structure.
2458  *
2459  *     If needed, the DtNprintSetupMode resource may be obtained via a
2460  *     GetValues call in order to determine the current setup mode.
2461  *
2462  *     It is the responsibility of this proc to return a valid print
2463  *     Display handle and print context by setting the print_display and
2464  *     print_context in the PrintSetupData. Conceptually, this is a
2465  *     side-effect of this proc, but since it will be necessary to open a
2466  *     display connection in order to properly verify the X printer,
2467  *     there's no point in doing it twice.
2468  *
2469  *     If the passed printer name is incomplete, this proc may attempt to
2470  *     determine a default or fully-qualified name (e.g. fill in a
2471  *     missing display spec for an X Printer Specifier). The new default
2472  *     or fully-qualified printer name should be set in the PrintSetupBox
2473  *     by updating the DtNprinterName resource via a SetValues call. If a
2474  *     fully-qualified name cannot be determined, this proc simply
2475  *     returns DtPRINT_FAILURE.
2476  *
2477  *     If the printer cannot be verified, it is the responsibiliy of this
2478  *     function to present an appropriate message to the user.
2479  *
2480  * Return value:
2481  *
2482  *     DtPRINT_SUCCESS
2483  *         if the printer name has been successfully verified.
2484  *     
2485  *     DtPRINT_FAILURE
2486  *         if the printer name is invalid.
2487  *
2488  *
2489  */
2490 XtEnum
2491 _DtPrintSetupBoxVerifyXPrinterProc(
2492                                    Widget w,
2493                                    DtPrintSetupData* psd)
2494 {
2495     DtPrintDefaultProcData* dpd = &PSUB_DefaultProcData(w);
2496     XtEnum status;
2497     String new_printer_spec;
2498     Display* new_display;
2499 #if 0 && defined(PRINTING_SUPPORTED)
2500     XPContext new_context;
2501 #endif /* PRINTING_SUPPORTED */
2502     Widget wmshell_ancestor;
2503     
2504     wmshell_ancestor = GetWMShellAncestor(w);
2505     _DtTurnOnHourGlass(wmshell_ancestor);
2506     /*
2507      * verify the printer
2508      */
2509     status = _DtPrintVerifyXPrinter(w,
2510                                     psd->printer_name,
2511                                     &new_printer_spec,
2512                                     &new_display
2513 #if 0 && defined(PRINTING_SUPPORTED)
2514                                     ,&new_context
2515 #endif /* PRINTING_SUPPORTED */
2516                                     );
2517     if(status == DtPRINT_SUCCESS)
2518     {
2519         /*
2520          * update the passed print setup data with the new display and
2521          * context
2522          */
2523         psd->print_display = new_display;
2524 #if 0 && defined(PRINTING_SUPPORTED)
2525         psd->print_context = new_context;
2526 #endif /* PRINTING_SUPPORTED */
2527     }
2528     else
2529     {
2530         /*
2531          * unable to open the printer; present a message to the user
2532          * according to the hint set in the setup data
2533          */
2534         dpd->messages_hint = psd->messages_hint;
2535         PresentVerifyError(w, status,
2536                            new_printer_spec
2537                            ? new_printer_spec : psd->printer_name);
2538         /*
2539          * reset the hint since the error dialog is also used
2540          * by the other default procs
2541          */
2542         dpd->messages_hint = DtPRINT_HINT_MESSAGES_OK;
2543         /*
2544          * this function only indicates success or failure
2545          */
2546         status = DtPRINT_FAILURE;
2547     }
2548     if(new_printer_spec)
2549     {
2550         /*
2551          * set the new printer spec, even if the verify failed
2552          */
2553         XtVaSetValues(w,
2554                       DtNprinterName, new_printer_spec,
2555                       NULL);
2556         XtFree(new_printer_spec);
2557     }
2558     /*
2559      * return
2560      */
2561     _DtTurnOffHourGlass(wmshell_ancestor);
2562     return status;
2563 }