Patch from ICS to do proper subclassing - this will make it more immune to
[nedit.git] / util / printUtils.c
blob6794723b35f000c702019115ac1dd1ba25802e7e
1 static const char CVSID[] = "$Id: printUtils.c,v 1.25 2004/08/01 10:06:12 yooden Exp $";
2 /*******************************************************************************
3 * *
4 * printUtils.c -- Nirvana library Printer Menu & Printing Routines *
5 * *
6 * Copyright (C) 1999 Mark Edel *
7 * *
8 * This is free software; you can redistribute it and/or modify it under the *
9 * terms of the GNU General Public License as published by the Free Software *
10 * Foundation; either version 2 of the License, or (at your option) any later *
11 * version. In addition, you may distribute version of this program linked to *
12 * Motif or Open Motif. See README for details. *
13 * *
14 * This software is distributed in the hope that it will be useful, but WITHOUT *
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License along with *
20 * software; if not, write to the Free Software Foundation, Inc., 59 Temple *
21 * Place, Suite 330, Boston, MA 02111-1307 USA *
22 * *
23 * Nirvana Text Editor *
24 * *
25 * April 20, 1992 *
26 * *
27 * Written by Arnulfo Zepeda-Navratil *
28 * Centro de Investigacion y Estudio Avanzados ( CINVESTAV ) *
29 * Dept. Fisica - Mexico *
30 * BITNET: ZEPEDA@CINVESMX *
31 * *
32 * Modified by Donna Reid and Joy Kyriakopulos 4/8/93 - VMS port *
33 * *
34 *******************************************************************************/
36 #ifdef HAVE_CONFIG_H
37 #include "../config.h"
38 #endif
40 #include "printUtils.h"
41 #include "DialogF.h"
42 #include "misc.h"
43 #include "prefFile.h"
45 #include <string.h>
46 #include <errno.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <ctype.h>
50 #include <sys/types.h>
51 #ifdef VMS
52 #include "vmsparam.h"
53 #include <ssdef.h>
54 #include <lib$routines.h>
55 #include <descrip.h>
56 #include <starlet.h>
57 #include <lnmdef.h>
58 #include <clidef.h>
59 #else
60 #ifdef USE_DIRENT
61 #include <dirent.h>
62 #else
63 #include <sys/dir.h>
64 #endif /* USE_DIRENT */
65 #ifndef __MVS__
66 #include <sys/param.h>
67 #endif
68 #endif /*VMS*/
69 #include <sys/stat.h>
71 #include <X11/StringDefs.h>
72 #include <X11/Intrinsic.h>
73 #include <X11/Shell.h>
74 #include <Xm/Xm.h>
75 #include <Xm/Form.h>
76 #include <Xm/LabelG.h>
77 #include <Xm/PushB.h>
78 #include <Xm/SeparatoG.h>
79 #include <Xm/Text.h>
81 #ifdef HAVE_DEBUG_H
82 #include "../debug.h"
83 #endif
85 /* Separator between directory references in PATH environmental variable */
86 #ifdef __EMX__ /* For OS/2 */
87 #define SEPARATOR ';'
88 #else
89 #define SEPARATOR ':'
90 #endif
92 /* Number of extra pixels down to place a label even with a text widget */
93 #define LABEL_TEXT_DIFF 6
95 /* Maximum text string lengths */
96 #define MAX_OPT_STR 20
97 #define MAX_QUEUE_STR 60
98 #define MAX_INT_STR 13
99 #define MAX_HOST_STR 100
100 #define MAX_PCMD_STR 100
101 #define MAX_NAME_STR 100
102 #define MAX_CMD_STR 256
103 #define VMS_MAX_JOB_NAME_STR 39
105 #define N_PRINT_PREFS 7 /* must agree with number of preferences below */
106 struct printPrefDescrip {
107 PrefDescripRec printCommand;
108 PrefDescripRec copiesOption;
109 PrefDescripRec queueOption;
110 PrefDescripRec nameOption;
111 PrefDescripRec hostOption;
112 PrefDescripRec defaultQueue;
113 PrefDescripRec defaultHost;
116 /* Function Prototypes */
117 static Widget createForm(Widget parent);
118 static void allowOnlyNumInput(Widget widget, caddr_t client_data,
119 XmTextVerifyCallbackStruct *call_data);
120 static void noSpaceOrPunct(Widget widget, caddr_t client_data,
121 XmTextVerifyCallbackStruct *call_data);
122 static void updatePrintCmd(Widget w, caddr_t client_data, caddr_t call_data);
123 static void printCmdModified(Widget w, caddr_t client_data, caddr_t call_data);
124 static void printButtonCB(Widget widget, caddr_t client_data, caddr_t call_data);
125 static void cancelButtonCB(Widget widget, caddr_t client_data, caddr_t call_data);
126 static void setQueueLabelText(void);
127 static int fileInDir(const char *filename, const char *dirpath, unsigned short mode_flags);
128 static int fileInPath(const char *filename, unsigned short mode_flags);
129 static int flprPresent(void);
130 #ifdef USE_LPR_PRINT_CMD
131 static void getLprQueueDefault(char *defqueue);
132 #endif
133 #ifndef USE_LPR_PRINT_CMD
134 static void getLpQueueDefault(char *defqueue);
135 #endif
136 static void setHostLabelText(void);
137 #ifdef VMS
138 static void getVmsQueueDefault(char *defqueue);
139 #else
140 static void getFlprHostDefault(char *defhost);
141 static void getFlprQueueDefault(char *defqueue);
142 #endif
144 /* Module Global Variables */
145 static Boolean DoneWithDialog;
146 static Boolean PreferencesLoaded = False;
147 static Widget Form;
148 static Widget Label2;
149 static Widget Label3;
150 static Widget Text1;
151 static Widget Text2;
152 static Widget Text3;
153 static Widget Text4;
154 static const char *PrintFileName;
155 static const char *PrintJobName;
156 static char PrintCommand[MAX_PCMD_STR]; /* print command string */
157 static char CopiesOption[MAX_OPT_STR]; /* # of copies argument string */
158 static char QueueOption[MAX_OPT_STR]; /* queue name argument string */
159 static char NameOption[MAX_OPT_STR]; /* print job name argument string */
160 static char HostOption[MAX_OPT_STR]; /* host name argument string */
161 static char DefaultQueue[MAX_QUEUE_STR];/* default print queue */
162 static char DefaultHost[MAX_HOST_STR]; /* default host name */
163 static char Copies[MAX_INT_STR] = ""; /* # of copies last entered by user */
164 static char Queue[MAX_QUEUE_STR] = ""; /* queue name last entered by user */
165 static char Host[MAX_HOST_STR] = ""; /* host name last entered by user */
166 static char CmdText[MAX_CMD_STR] = ""; /* print command last entered by user */
167 static int CmdFieldModified = False; /* user last changed the print command
168 field, so don't trust the rest */
169 #ifdef VMS
170 static int DeleteFile; /* append /DELETE to VMS print command*/
171 #endif /*VMS*/
173 static struct printPrefDescrip PrintPrefDescrip = {
174 {"printCommand", "PrintCommand", PREF_STRING, NULL,
175 PrintCommand, (void *)MAX_PCMD_STR, False},
176 {"printCopiesOption", "PrintCopiesOption", PREF_STRING, NULL,
177 CopiesOption, (void *)MAX_OPT_STR, False},
178 {"printQueueOption", "PrintQueueOption", PREF_STRING, NULL,
179 QueueOption, (void *)MAX_OPT_STR, False},
180 {"printNameOption", "PrintNameOption", PREF_STRING, NULL,
181 NameOption, (void *)MAX_OPT_STR, False},
182 {"printHostOption", "PrintHostOption", PREF_STRING, NULL,
183 HostOption, (void *)MAX_OPT_STR, False},
184 {"printDefaultQueue", "PrintDefaultQueue", PREF_STRING, NULL,
185 DefaultQueue, (void *)MAX_QUEUE_STR, False},
186 {"printDefaultHost", "PrintDefaultHost", PREF_STRING, NULL,
187 DefaultHost, (void *)MAX_HOST_STR, False},
191 ** PrintFile(Widget parent, char *printFile, char *jobName);
193 ** function to put up an application-modal style Print Panel dialog
194 ** box.
196 ** parent Parent widget for displaying dialog
197 ** printFile File to print (assumed to be a temporary file
198 ** and not revealed to the user)
199 ** jobName Title for the print banner page
201 #ifdef VMS
202 void PrintFile(Widget parent, const char *printFile, const char *jobName, int delete)
203 #else
204 void PrintFile(Widget parent, const char *printFile, const char *jobName)
205 #endif /*VMS*/
207 /* In case the program hasn't called LoadPrintPreferences, set up the
208 default values for the print preferences */
209 if (!PreferencesLoaded)
210 LoadPrintPreferences(NULL, "", "", True);
212 /* Make the PrintFile information available to the callback routines */
213 PrintFileName = printFile;
214 PrintJobName = jobName;
215 #ifdef VMS
216 DeleteFile = delete;
217 #endif /*VMS*/
219 /* Create and display the print dialog */
220 DoneWithDialog = False;
221 Form = createForm(parent);
222 ManageDialogCenteredOnPointer(Form);
224 /* Process events until the user is done with the print dialog */
225 while (!DoneWithDialog)
226 XtAppProcessEvent(XtWidgetToApplicationContext(Form), XtIMAll);
228 /* Destroy the dialog. Print dialogs are not preserved across calls
229 to PrintFile so that it may be called with different parents and
230 to generally simplify the call (this, of course, makes it slower) */
231 XtDestroyWidget(Form);
235 ** LoadPrintPreferences
237 ** Read an X database to obtain print dialog preferences.
239 ** prefDB X database potentially containing print preferences
240 ** appName Application name which can be used to qualify
241 ** resource names for database lookup.
242 ** appClass Application class which can be used to qualify
243 ** resource names for database lookup.
244 ** lookForFlpr Check if the flpr print command is installed
245 ** and use that for the default if it's found.
246 ** (flpr is a Fermilab utility for printing on
247 ** arbitrary systems that support the lpr protocol)
249 void LoadPrintPreferences(XrmDatabase prefDB, const char *appName,
250 const char *appClass, int lookForFlpr)
252 static char defaultQueue[MAX_QUEUE_STR], defaultHost[MAX_HOST_STR];
254 #ifdef VMS
255 /* VMS built-in print command */
256 getVmsQueueDefault(defaultQueue);
257 PrintPrefDescrip.printCommand.defaultString = "print";
258 PrintPrefDescrip.copiesOption.defaultString = "/copies=";
259 PrintPrefDescrip.queueOption.defaultString = "/queue=";
260 PrintPrefDescrip.nameOption.defaultString = "/name=";
261 PrintPrefDescrip.hostOption.defaultString = "";
262 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue;
263 PrintPrefDescrip.defaultHost.defaultString = "";
264 #else
266 /* check if flpr is installed, and otherwise choose appropriate
267 printer per system type */
268 if (lookForFlpr && flprPresent()) {
269 getFlprQueueDefault(defaultQueue);
270 getFlprHostDefault(defaultHost);
271 PrintPrefDescrip.printCommand.defaultString = "flpr";
272 PrintPrefDescrip.copiesOption.defaultString = "";
273 PrintPrefDescrip.queueOption.defaultString = "-q";
274 PrintPrefDescrip.nameOption.defaultString = "-j ";
275 PrintPrefDescrip.hostOption.defaultString = "-h";
276 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue;
277 PrintPrefDescrip.defaultHost.defaultString = defaultHost;
278 } else {
279 #ifdef USE_LPR_PRINT_CMD
280 getLprQueueDefault(defaultQueue);
281 PrintPrefDescrip.printCommand.defaultString = "lpr";
282 PrintPrefDescrip.copiesOption.defaultString = "-# ";
283 PrintPrefDescrip.queueOption.defaultString = "-P ";
284 PrintPrefDescrip.nameOption.defaultString = "-J ";
285 PrintPrefDescrip.hostOption.defaultString = "";
286 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue;
287 PrintPrefDescrip.defaultHost.defaultString = "";
288 #else
289 getLpQueueDefault(defaultQueue);
290 PrintPrefDescrip.printCommand.defaultString = "lp"; /* was lp -c */
291 PrintPrefDescrip.copiesOption.defaultString = "-n";
292 PrintPrefDescrip.queueOption.defaultString = "-d";
293 PrintPrefDescrip.nameOption.defaultString = "-t";
294 PrintPrefDescrip.hostOption.defaultString = "";
295 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue;
296 PrintPrefDescrip.defaultHost.defaultString = "";
297 #endif
299 #endif
301 /* Read in the preferences from the X database using the mechanism from
302 prefFile.c (this allows LoadPrintPreferences to work before any
303 widgets are created, which is more convenient than XtGetApplication-
304 Resources for applications which have no main window) */
305 RestorePreferences(NULL, prefDB, appName, appClass,
306 (PrefDescripRec *)&PrintPrefDescrip, N_PRINT_PREFS);
308 PreferencesLoaded = True;
311 static Widget createForm(Widget parent)
313 Widget form, printOk, printCancel, label1, separator;
314 Widget topWidget = NULL;
315 XmString st0;
316 Arg args[65];
317 int argcnt;
318 Widget bwidgetarray [30];
319 int bwidgetcnt = 0;
321 /************************ FORM ***************************/
322 argcnt = 0;
323 XtSetArg(args[argcnt], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
324 argcnt++;
325 XtSetArg(args[argcnt], XmNdialogTitle, (st0=XmStringCreateLtoR(
326 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++;
327 XtSetArg(args[argcnt], XmNautoUnmanage, False); argcnt++;
328 form = CreateFormDialog(parent, "printForm", args, argcnt);
329 XtVaSetValues(form, XmNshadowThickness, 0, NULL);
331 XmStringFree( st0 );
333 /*********************** LABEL 1 and TEXT BOX 1 *********************/
334 if (CopiesOption[0] != '\0') {
335 argcnt = 0;
336 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
337 "Number of copies (1)", XmSTRING_DEFAULT_CHARSET))); argcnt++;
338 XtSetArg(args[argcnt], XmNmnemonic, 'N'); argcnt++;
339 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_FORM); argcnt++;
340 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+5); argcnt++;
341 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
342 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++;
343 label1 = XmCreateLabelGadget(form, "label1", args, argcnt);
344 XmStringFree( st0 );
345 bwidgetarray[bwidgetcnt] = label1; bwidgetcnt++;
347 argcnt = 0;
348 XtSetArg(args[argcnt], XmNshadowThickness, (short)2); argcnt++;
349 XtSetArg(args[argcnt], XmNcolumns, 3); argcnt++;
350 XtSetArg(args[argcnt], XmNrows, 1); argcnt++;
351 XtSetArg(args[argcnt], XmNvalue , Copies); argcnt++;
352 XtSetArg(args[argcnt], XmNmaxLength, 3); argcnt++;
353 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_FORM); argcnt++;
354 XtSetArg(args[argcnt], XmNtopOffset, 5); argcnt++;
355 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++;
356 XtSetArg(args[argcnt], XmNleftWidget, label1); argcnt++;
357 Text1 = XmCreateText(form, "text1", args, argcnt);
358 bwidgetarray[bwidgetcnt] = Text1; bwidgetcnt++;
359 XtAddCallback(Text1, XmNmodifyVerifyCallback,
360 (XtCallbackProc)allowOnlyNumInput, NULL);
361 XtAddCallback(Text1, XmNvalueChangedCallback,
362 (XtCallbackProc)updatePrintCmd, NULL);
363 RemapDeleteKey(Text1);
364 topWidget = Text1;
365 XtVaSetValues(label1, XmNuserData, Text1, NULL); /* mnemonic procesing */
368 /************************ LABEL 2 and TEXT 2 ************************/
369 if (QueueOption[0] != '\0') {
370 argcnt = 0;
371 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
372 " ", XmSTRING_DEFAULT_CHARSET))); argcnt++;
373 XtSetArg(args[argcnt], XmNmnemonic, 'Q'); argcnt++;
374 XtSetArg(args[argcnt], XmNrecomputeSize, True); argcnt++;
375 XtSetArg(args[argcnt], XmNtopAttachment,
376 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++;
377 XtSetArg(args[argcnt], XmNtopWidget, topWidget); argcnt++;
378 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
379 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+4); argcnt++;
380 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++;
381 Label2 = XmCreateLabelGadget(form, "label2", args, argcnt);
382 XmStringFree(st0);
383 bwidgetarray[bwidgetcnt] = Label2; bwidgetcnt++;
384 setQueueLabelText();
386 argcnt = 0;
387 XtSetArg(args[argcnt], XmNshadowThickness, (short)2); argcnt++;
388 XtSetArg(args[argcnt], XmNcolumns, (short)17); argcnt++;
389 XtSetArg(args[argcnt], XmNmaxLength, MAX_QUEUE_STR); argcnt++;
390 XtSetArg(args[argcnt], XmNvalue, Queue); argcnt++;
391 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++;
392 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++;
393 XtSetArg(args[argcnt], XmNleftWidget, Label2 ); argcnt++;
394 XtSetArg(args[argcnt], XmNtopAttachment,
395 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++;
396 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
397 XtSetArg(args[argcnt], XmNrightOffset, 8); argcnt++;
398 XtSetArg(args[argcnt], XmNtopOffset, 4); argcnt++;
399 Text2 = XmCreateText(form, "text2", args, argcnt);
400 XtAddCallback(Text2, XmNmodifyVerifyCallback,
401 (XtCallbackProc)noSpaceOrPunct, NULL);
402 XtAddCallback(Text2, XmNvalueChangedCallback,
403 (XtCallbackProc)updatePrintCmd, NULL);
404 bwidgetarray[bwidgetcnt] = Text2; bwidgetcnt++;
405 RemapDeleteKey(Text2);
406 XtVaSetValues(Label2, XmNuserData, Text2, NULL); /* mnemonic procesing */
407 topWidget = Text2;
410 /****************** LABEL 3 and TEXT 3 *********************/
411 if (HostOption[0] != '\0') {
412 argcnt = 0;
413 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
414 " ", XmSTRING_DEFAULT_CHARSET))); argcnt++;
415 XtSetArg(args[argcnt], XmNmnemonic, 'H'); argcnt++;
416 XtSetArg(args[argcnt], XmNrecomputeSize, True); argcnt++;
417 XtSetArg(args[argcnt], XmNvalue , ""); argcnt++;
418 XtSetArg(args[argcnt], XmNtopAttachment,
419 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++;
420 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
421 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
422 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++;
423 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+4); argcnt++;
424 Label3 = XmCreateLabelGadget(form, "label3", args, argcnt);
425 XmStringFree(st0);
426 bwidgetarray[bwidgetcnt] = Label3; bwidgetcnt++;
427 setHostLabelText();
429 argcnt = 0;
430 XtSetArg(args[argcnt], XmNcolumns, 17); argcnt++;
431 XtSetArg(args[argcnt], XmNrows, 1); argcnt++;
432 XtSetArg(args[argcnt], XmNvalue, Host); argcnt++;
433 XtSetArg(args[argcnt], XmNmaxLength, MAX_HOST_STR); argcnt++;
434 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++;
435 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++;
436 XtSetArg(args[argcnt], XmNleftWidget, Label3 ); argcnt++;
437 XtSetArg(args[argcnt], XmNtopAttachment,
438 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++;
439 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
440 XtSetArg(args[argcnt], XmNrightOffset, 8); argcnt++;
441 XtSetArg(args[argcnt], XmNtopOffset, 4); argcnt++;
442 Text3 = XmCreateText(form, "Text3", args, argcnt);
443 XtAddCallback(Text3, XmNmodifyVerifyCallback,
444 (XtCallbackProc)noSpaceOrPunct, NULL);
445 XtAddCallback(Text3, XmNvalueChangedCallback,
446 (XtCallbackProc)updatePrintCmd, NULL);
447 bwidgetarray[bwidgetcnt] = Text3; bwidgetcnt++;
448 RemapDeleteKey(Text3);
449 XtVaSetValues(Label3, XmNuserData, Text3, NULL); /* mnemonic procesing */
450 topWidget = Text3;
453 /************************** TEXT 4 ***************************/
454 argcnt = 0;
455 XtSetArg(args[argcnt], XmNvalue, CmdText); argcnt++;
456 XtSetArg(args[argcnt], XmNcolumns, 50); argcnt++;
457 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
458 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++;
459 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++;
460 XtSetArg(args[argcnt], XmNtopOffset, 8); argcnt++;
461 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
462 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++;
463 XtSetArg(args[argcnt], XmNrightOffset, 8); argcnt++;
464 Text4 = XmCreateText(form, "Text4", args, argcnt);
465 XtAddCallback(Text4, XmNmodifyVerifyCallback,
466 (XtCallbackProc)printCmdModified, NULL);
467 bwidgetarray[bwidgetcnt] = Text4; bwidgetcnt++;
468 RemapDeleteKey(Text4);
469 topWidget = Text4;
470 if (!CmdFieldModified)
471 updatePrintCmd(NULL, NULL, NULL);
473 /*********************** SEPARATOR **************************/
474 argcnt = 0;
475 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++;
476 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++;
477 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++;
478 XtSetArg(args[argcnt], XmNtopOffset, 8); argcnt++;
479 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
480 separator = XmCreateSeparatorGadget(form, "separator", args, argcnt);
481 bwidgetarray[bwidgetcnt] = separator; bwidgetcnt++;
482 topWidget = separator;
484 /********************** CANCEL BUTTON *************************/
485 argcnt = 0;
486 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
487 "Cancel", XmSTRING_DEFAULT_CHARSET))); argcnt++;
488 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_POSITION); argcnt++;
489 XtSetArg(args[argcnt], XmNleftPosition, 60); argcnt++;
490 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++;
491 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
492 XtSetArg(args[argcnt], XmNtopOffset, 7); argcnt++;
493 printCancel = XmCreatePushButton(form, "printCancel", args, argcnt);
494 XmStringFree( st0 );
495 bwidgetarray[bwidgetcnt] = printCancel; bwidgetcnt++;
496 XtAddCallback (printCancel, XmNactivateCallback,
497 (XtCallbackProc)cancelButtonCB, NULL);
499 /*********************** PRINT BUTTON **************************/
500 argcnt = 0;
501 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
502 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++;
503 XtSetArg(args[argcnt], XmNshowAsDefault, True); argcnt++;
504 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_POSITION); argcnt++;
505 XtSetArg(args[argcnt], XmNrightPosition, 40); argcnt++;
506 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++;
507 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++;
508 XtSetArg(args[argcnt], XmNtopOffset, 7); argcnt++;
509 printOk = XmCreatePushButton(form, "printOk", args, argcnt);
510 XmStringFree( st0 );
511 bwidgetarray[bwidgetcnt] = printOk; bwidgetcnt++;
512 XtAddCallback (printOk, XmNactivateCallback,
513 (XtCallbackProc)printButtonCB, NULL);
515 argcnt = 0;
516 XtSetArg(args[argcnt], XmNcancelButton, printCancel); argcnt++;
517 XtSetArg(args[argcnt], XmNdefaultButton, printOk); argcnt++;
518 XtSetValues(form, args, argcnt);
520 XtManageChildren(bwidgetarray, bwidgetcnt);
521 AddDialogMnemonicHandler(form, FALSE);
522 return form;
525 static void setQueueLabelText(void)
527 Arg args[15];
528 int argcnt;
529 XmString st0;
530 char tmp_buf[MAX_QUEUE_STR+8];
532 if (DefaultQueue[0] != '\0')
533 sprintf(tmp_buf, "Queue (%s)", DefaultQueue);
534 else
535 sprintf(tmp_buf, "Queue");
536 argcnt = 0;
537 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
538 tmp_buf, XmSTRING_DEFAULT_CHARSET))); argcnt++;
539 XtSetValues (Label2, args, argcnt);
540 XmStringFree( st0 );
543 static void setHostLabelText(void)
545 Arg args[15];
546 int argcnt;
547 XmString st0;
548 char tmp_buf[MAX_HOST_STR+7];
550 if (strcmp(DefaultHost, ""))
551 sprintf(tmp_buf, "Host (%s)", DefaultHost);
552 else
553 sprintf(tmp_buf, "Host");
554 argcnt = 0;
555 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR(
556 tmp_buf, XmSTRING_DEFAULT_CHARSET))); argcnt++;
558 XtSetValues (Label3, args, argcnt);
559 XmStringFree( st0 );
562 static void allowOnlyNumInput(Widget widget, caddr_t client_data,
563 XmTextVerifyCallbackStruct *call_data)
565 int i, textInserted, nInserted;
567 nInserted = call_data->text->length;
568 textInserted = (nInserted > 0);
569 if ((call_data->reason == XmCR_MODIFYING_TEXT_VALUE) && textInserted) {
570 for (i=0; i<nInserted; i++) {
571 if (!isdigit((unsigned char)call_data->text->ptr[i])) {
572 call_data->doit = False;
573 return;
577 call_data->doit = True;
581 ** Prohibit a relatively random sampling of characters that will cause
582 ** problems on command lines
584 static void noSpaceOrPunct(Widget widget, caddr_t client_data,
585 XmTextVerifyCallbackStruct *call_data)
587 int i, j, textInserted, nInserted;
588 #ifndef VMS
589 static char prohibited[] = " \t,;|<>()[]{}!@?";
590 #else
591 static char prohibited[] = " \t,;|@+";
592 #endif
594 nInserted = call_data->text->length;
595 textInserted = (nInserted > 0);
596 if ((call_data->reason == XmCR_MODIFYING_TEXT_VALUE) && textInserted) {
597 for (i=0; i<nInserted; i++) {
598 for (j=0; j<(int)XtNumber(prohibited); j++) {
599 if (call_data->text->ptr[i] == prohibited[j]) {
600 call_data->doit = False;
601 return;
606 call_data->doit = True;
609 static void updatePrintCmd(Widget w, caddr_t client_data, caddr_t call_data)
611 char command[MAX_CMD_STR], copiesArg[MAX_OPT_STR+MAX_INT_STR];
612 char jobArg[MAX_NAME_STR], hostArg[MAX_OPT_STR+MAX_HOST_STR];
613 char queueArg[MAX_OPT_STR+MAX_QUEUE_STR];
614 char *str;
615 int nCopies;
616 #ifdef VMS
617 char printJobName[VMS_MAX_JOB_NAME_STR+1];
618 #endif /*VMS*/
620 /* read each text field in the dialog and generate the corresponding
621 command argument */
622 if (CopiesOption[0] == '\0') {
623 copiesArg[0] = '\0';
624 } else {
625 str = XmTextGetString(Text1);
626 if (str[0] == '\0') {
627 copiesArg[0] = '\0';
628 } else {
629 if (sscanf(str, "%d", &nCopies) != 1) {
630 copiesArg[0] = '\0';
631 } else {
632 sprintf(copiesArg, " %s%s", CopiesOption, str);
635 XtFree(str);
637 if (QueueOption[0] == '\0') {
638 queueArg[0] = '\0';
639 } else {
640 str = XmTextGetString(Text2);
641 if (str[0] == '\0')
642 queueArg[0] = '\0';
643 else
644 sprintf(queueArg, " %s%s", QueueOption, str);
645 XtFree(str);
647 if (HostOption[0] == '\0') {
648 hostArg[0] = '\0';
649 } else {
650 str = XmTextGetString(Text3);
651 if (str[0] == '\0')
652 hostArg[0] = '\0';
653 else
654 sprintf(hostArg, " %s%s", HostOption, str);
655 XtFree(str);
657 if (NameOption[0] == '\0')
658 jobArg[0] = '\0';
659 else {
660 #ifdef VMS
661 /* truncate job name on VMS systems or it will cause problems */
662 strncpy(printJobName,PrintJobName,VMS_MAX_JOB_NAME_STR);
663 printJobName[VMS_MAX_JOB_NAME_STR] = '\0';
664 sprintf(jobArg, " %s\"%s\"", NameOption, printJobName);
665 #else
666 sprintf(jobArg, " %s\"%s\"", NameOption, PrintJobName);
667 #endif
670 /* Compose the command from the options determined above */
671 sprintf(command, "%s%s%s%s%s", PrintCommand, copiesArg,
672 queueArg, hostArg, jobArg);
674 /* display it in the command text area */
675 XmTextSetString(Text4, command);
677 /* Indicate that the command field was synthesized from the other fields,
678 so future dialog invocations can safely re-generate the command without
679 overwriting commands specifically entered by the user */
680 CmdFieldModified = False;
683 static void printCmdModified(Widget w, caddr_t client_data, caddr_t call_data)
685 /* Indicate that the user has specifically modified the print command
686 and that this field should be left as is in subsequent dialogs */
687 CmdFieldModified = True;
690 static void printButtonCB(Widget widget, caddr_t client_data, caddr_t call_data)
692 char *str, command[MAX_CMD_STR];
693 #ifdef VMS
694 int spawn_sts;
695 int spawnFlags=CLI$M_NOCLISYM;
696 struct dsc$descriptor cmdDesc;
698 /* get the print command from the command text area */
699 str = XmTextGetString(Text4);
701 /* add the file name to the print command */
702 sprintf(command, "%s %s", str, PrintFileName);
704 XtFree(str);
706 /* append /DELETE to print command if requested */
707 if (DeleteFile)
708 strcat(command, "/DELETE");
710 /* spawn the print command */
711 cmdDesc.dsc$w_length = strlen(command);
712 cmdDesc.dsc$b_dtype = DSC$K_DTYPE_T;
713 cmdDesc.dsc$b_class = DSC$K_CLASS_S;
714 cmdDesc.dsc$a_pointer = command;
715 spawn_sts = lib$spawn(&cmdDesc,0,0,&spawnFlags,0,0,0,0,0,0,0,0);
717 if (spawn_sts != SS$_NORMAL)
719 DialogF(DF_WARN, widget, 1, "Print Error",
720 "Unable to Print:\n%d - %s\n spawnFlags = %d\n", "OK",
721 spawn_sts, strerror(EVMSERR, spawn_sts), spawnFlags);
722 return;
724 #else
725 int nRead;
726 FILE *pipe;
727 char errorString[MAX_PRINT_ERROR_LENGTH], discarded[1024];
729 /* get the print command from the command text area */
730 str = XmTextGetString(Text4);
732 /* add the file name and output redirection to the print command */
733 sprintf(command, "cat %s | %s 2>&1", PrintFileName, str);
734 XtFree(str);
736 /* Issue the print command using a popen call and recover error messages
737 from the output stream of the command. */
738 pipe = popen(command,"r");
739 if (pipe == NULL)
741 DialogF(DF_WARN, widget, 1, "Print Error", "Unable to Print:\n%s",
742 "OK", strerror(errno));
743 return;
746 errorString[0] = 0;
747 nRead = fread(errorString, sizeof(char), MAX_PRINT_ERROR_LENGTH-1, pipe);
748 /* Make sure that the print command doesn't get stuck when trying to
749 write a lot of output on stderr (pipe may fill up). We discard
750 the additional output, though. */
751 while (fread(discarded, sizeof(char), 1024, pipe) > 0);
753 if (!ferror(pipe))
755 errorString[nRead] = '\0';
758 if (pclose(pipe))
760 DialogF(DF_WARN, widget, 1, "Print Error", "Unable to Print:\n%s",
761 "OK", errorString);
762 return;
764 #endif /*(VMS)*/
766 /* Print command succeeded, so retain the current print parameters */
767 if (CopiesOption[0] != '\0') {
768 str = XmTextGetString(Text1);
769 strcpy(Copies, str);
770 XtFree(str);
772 if (QueueOption[0] != '\0') {
773 str = XmTextGetString(Text2);
774 strcpy(Queue, str);
775 XtFree(str);
777 if (HostOption[0] != '\0') {
778 str = XmTextGetString(Text3);
779 strcpy(Host, str);
780 XtFree(str);
782 str = XmTextGetString(Text4);
783 strcpy(CmdText, str);
784 XtFree(str);
787 /* Pop down the dialog */
788 DoneWithDialog = True;
791 static void cancelButtonCB(Widget widget, caddr_t client_data, caddr_t call_data)
793 DoneWithDialog = True;
794 CmdFieldModified = False;
797 #ifndef VMS
799 ** Is the filename file in the directory dirpath
800 ** and does it have at least some of the mode_flags enabled ?
802 static int fileInDir(const char *filename, const char *dirpath, unsigned short mode_flags)
804 DIR *dfile;
805 #ifdef USE_DIRENT
806 struct dirent *DirEntryPtr;
807 #else
808 struct direct *DirEntryPtr;
809 #endif
810 struct stat statbuf;
811 char fullname[MAXPATHLEN];
813 dfile = opendir(dirpath);
814 if (dfile != NULL) {
815 while ((DirEntryPtr=readdir(dfile)) != NULL) {
816 if (!strcmp(DirEntryPtr->d_name, filename)) {
817 strcpy(fullname,dirpath);
818 strcat(fullname,"/");
819 strcat(fullname,filename);
820 stat(fullname,&statbuf);
821 closedir(dfile);
822 return statbuf.st_mode & mode_flags;
825 closedir(dfile);
827 return False;
831 ** Is the filename file in the environment path directories
832 ** and does it have at least some of the mode_flags enabled ?
834 static int fileInPath(const char *filename, unsigned short mode_flags)
836 char path[MAXPATHLEN];
837 char *pathstring,*lastchar;
839 /* Get environmental value of PATH */
840 pathstring = getenv("PATH");
841 if (pathstring == NULL)
842 return False;
844 /* parse the pathstring and search on each directory found */
845 do {
846 /* if final path in list is empty, don't search it */
847 if (!strcmp(pathstring, ""))
848 return False;
849 /* locate address of next : character */
850 lastchar = strchr(pathstring, SEPARATOR);
851 if (lastchar != NULL) {
852 /* if more directories remain in pathstring, copy up to : */
853 strncpy(path, pathstring, lastchar-pathstring);
854 path[lastchar-pathstring] = '\0';
855 } else {
856 /* if it's the last directory, just copy it */
857 strcpy(path, pathstring);
859 /* search for the file in this path */
860 if(fileInDir(filename, path, mode_flags))
861 return True; /* found it !! */
862 /* point pathstring to start of new dir string */
863 pathstring = lastchar + 1;
864 } while( lastchar != NULL );
865 return False;
869 ** Is flpr present in the search path and is it executable ?
871 static int flprPresent(void)
873 /* Is flpr present in the search path and is it executable ? */
874 return fileInPath("flpr",0111);
877 static int foundTag(const char *tagfilename, const char *tagname, char *result)
879 FILE *tfile;
880 char tagformat[512],line[512];
882 strcpy(tagformat, tagname);
883 strcat(tagformat, " %s");
885 tfile = fopen(tagfilename,"r");
886 if (tfile != NULL) {
887 while (!feof(tfile)) {
888 fgets(line,sizeof(line),tfile);
889 if (sscanf(line,tagformat,result) != 0) {
890 fclose(tfile);
891 return True;
894 fclose(tfile);
896 return False;
899 static int foundEnv(const char *EnvVarName, char *result)
901 char *dqstr;
903 dqstr = getenv(EnvVarName);
904 if (dqstr != NULL) {
905 strcpy(result,dqstr);
906 return True;
908 return False;
911 static void getFlprHostDefault(char *defhost)
913 if (!foundEnv("FLPHOST",defhost))
914 if(!foundTag("/usr/local/etc/flp.defaults", "host", defhost))
915 strcpy(defhost,"");
918 static void getFlprQueueDefault(char *defqueue)
920 if (!foundEnv("FLPQUE",defqueue))
921 if (!foundTag("/usr/local/etc/flp.defaults", "queue", defqueue))
922 strcpy(defqueue,"");
925 #ifdef USE_LPR_PRINT_CMD
926 static void getLprQueueDefault(char *defqueue)
928 if (!foundEnv("PRINTER",defqueue))
929 strcpy(defqueue,"");
931 #endif
933 #ifndef USE_LPR_PRINT_CMD
934 static void getLpQueueDefault(char *defqueue)
936 if (!foundEnv("LPDEST",defqueue))
937 defqueue[0] = '\0';
939 #endif
940 #endif
942 #ifdef VMS
943 static void getVmsQueueDefault(char *defqueue)
945 int translate_sts;
946 short ret_len;
947 char logicl[12], tabl[15];
948 struct itemList {
949 short bufL;
950 short itemCode;
951 char *queName;
952 short *lngth;
953 int end_entry;
954 } translStruct;
955 struct dsc$descriptor tabName;
956 struct dsc$descriptor logName;
958 sprintf(tabl, "LNM$FILE_DEV");
960 tabName.dsc$w_length = strlen(tabl);
961 tabName.dsc$b_dtype = DSC$K_DTYPE_T;
962 tabName.dsc$b_class = DSC$K_CLASS_S;
963 tabName.dsc$a_pointer = tabl;
965 sprintf(logicl, "SYS$PRINT");
967 logName.dsc$w_length = strlen(logicl);
968 logName.dsc$b_dtype = DSC$K_DTYPE_T;
969 logName.dsc$b_class = DSC$K_CLASS_S;
970 logName.dsc$a_pointer = logicl;
972 translStruct.itemCode = LNM$_STRING;
973 translStruct.lngth = &ret_len;
974 translStruct.bufL = 99;
975 translStruct.end_entry = 0;
976 translStruct.queName = defqueue;
977 translate_sts = sys$trnlnm(0,&tabName,&logName,0,&translStruct);
979 if (translate_sts != SS$_NORMAL && translate_sts != SS$_NOLOGNAM){
980 fprintf(stderr, "Error return from sys$trnlnm: %d\n", translate_sts);
981 DialogF(DF_WARN, Label2, 1, "Error", "Error translating SYS$PRINT",
982 "OK");
983 defqueue[0] = '\0';
984 } else
986 /* printf("return status from sys$trnlnm = %d\n", translate_sts); */
987 if (translate_sts == SS$_NOLOGNAM)
989 defqueue[0] = '\0';
990 } else
992 strncpy(defqueue, translStruct.queName, ret_len);
993 defqueue[ret_len] = '\0';
994 /* printf("defqueue = %s, length = %d\n", defqueue, ret_len); */
998 #endif /*(VMS)*/