UNIXworkcode

1 /******************************************************************************* 2 * * 3 * printUtils.c -- Nirvana library Printer Menu & Printing Routines * 4 * * 5 * Copyright (C) 1999 Mark Edel * 6 * * 7 * This is free software; you can redistribute it and/or modify it under the * 8 * terms of the GNU General Public License as published by the Free Software * 9 * Foundation; either version 2 of the License, or (at your option) any later * 10 * version. In addition, you may distribute version of this program linked to * 11 * Motif or Open Motif. See README for details. * 12 * * 13 * This software is distributed in the hope that it will be useful, but WITHOUT * 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * 16 * for more details. * 17 * * 18 * You should have received a copy of the GNU General Public License along with * 19 * software; if not, write to the Free Software Foundation, Inc., 59 Temple * 20 * Place, Suite 330, Boston, MA 02111-1307 USA * 21 * * 22 * Nirvana Text Editor * 23 * * 24 * April 20, 1992 * 25 * * 26 * Written by Arnulfo Zepeda-Navratil * 27 * Centro de Investigacion y Estudio Avanzados ( CINVESTAV ) * 28 * Dept. Fisica - Mexico * 29 * BITNET: ZEPEDA@CINVESMX * 30 * * 31 * Modified by Donna Reid and Joy Kyriakopulos 4/8/93 - VMS port * 32 * * 33 *******************************************************************************/ 34 35 #ifdef HAVE_CONFIG_H 36 #include "../config.h" 37 #endif 38 39 #include "printUtils.h" 40 #include "DialogF.h" 41 #include "misc.h" 42 #include "prefFile.h" 43 #include "nedit_malloc.h" 44 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 #include <dirent.h> 52 #include <sys/param.h> 53 #include <sys/stat.h> 54 #include <X11/StringDefs.h> 55 #include <X11/Intrinsic.h> 56 #include <X11/Shell.h> 57 #include <Xm/Xm.h> 58 #include <Xm/Form.h> 59 #include <Xm/LabelG.h> 60 #include <Xm/PushB.h> 61 #include <Xm/SeparatoG.h> 62 #include <Xm/Text.h> 63 64 #ifdef HAVE_DEBUG_H 65 #include "../debug.h" 66 #endif 67 68 /* Separator between directory references in PATH environmental variable */ 69 #ifdef __EMX__ /* For OS/2 */ 70 #define SEPARATOR ';' 71 #else 72 #define SEPARATOR ':' 73 #endif 74 75 /* Number of extra pixels down to place a label even with a text widget */ 76 #define LABEL_TEXT_DIFF 6 77 78 /* Maximum text string lengths */ 79 #define MAX_OPT_STR 20 80 #define MAX_QUEUE_STR 60 81 #define MAX_INT_STR 13 82 #define MAX_HOST_STR 100 83 #define MAX_PCMD_STR 100 84 #define MAX_NAME_STR 100 85 #define MAX_CMD_STR 256 86 #define VMS_MAX_JOB_NAME_STR 39 87 88 #define N_PRINT_PREFS 7 /* must agree with number of preferences below */ 89 struct printPrefDescrip { 90 PrefDescripRec printCommand; 91 PrefDescripRec copiesOption; 92 PrefDescripRec queueOption; 93 PrefDescripRec nameOption; 94 PrefDescripRec hostOption; 95 PrefDescripRec defaultQueue; 96 PrefDescripRec defaultHost; 97 }; 98 99 /* Function Prototypes */ 100 static Widget createForm(Widget parent); 101 static void allowOnlyNumInput(Widget widget, caddr_t client_data, 102 XmTextVerifyCallbackStruct *call_data); 103 static void noSpaceOrPunct(Widget widget, caddr_t client_data, 104 XmTextVerifyCallbackStruct *call_data); 105 static void updatePrintCmd(Widget w, caddr_t client_data, caddr_t call_data); 106 static void printCmdModified(Widget w, caddr_t client_data, caddr_t call_data); 107 static void printButtonCB(Widget widget, caddr_t client_data, caddr_t call_data); 108 static void cancelButtonCB(Widget widget, caddr_t client_data, caddr_t call_data); 109 static void setQueueLabelText(void); 110 static int fileInDir(const char *filename, const char *dirpath, unsigned short mode_flags); 111 static int fileInPath(const char *filename, unsigned short mode_flags); 112 static int flprPresent(void); 113 #ifdef USE_LPR_PRINT_CMD 114 static void getLprQueueDefault(char *defqueue); 115 #endif 116 #ifndef USE_LPR_PRINT_CMD 117 static void getLpQueueDefault(char *defqueue); 118 #endif 119 static void setHostLabelText(void); 120 static void getFlprHostDefault(char *defhost); 121 static void getFlprQueueDefault(char *defqueue); 122 123 /* Module Global Variables */ 124 static Boolean DoneWithDialog; 125 static Boolean PreferencesLoaded = False; 126 static Widget Form; 127 static Widget Label2; 128 static Widget Label3; 129 static Widget Text1; 130 static Widget Text2; 131 static Widget Text3; 132 static Widget Text4; 133 static const char *PrintFileName; 134 static const char *PrintJobName; 135 static char PrintCommand[MAX_PCMD_STR]; /* print command string */ 136 static char CopiesOption[MAX_OPT_STR]; /* # of copies argument string */ 137 static char QueueOption[MAX_OPT_STR]; /* queue name argument string */ 138 static char NameOption[MAX_OPT_STR]; /* print job name argument string */ 139 static char HostOption[MAX_OPT_STR]; /* host name argument string */ 140 static char DefaultQueue[MAX_QUEUE_STR];/* default print queue */ 141 static char DefaultHost[MAX_HOST_STR]; /* default host name */ 142 static char Copies[MAX_INT_STR] = ""; /* # of copies last entered by user */ 143 static char Queue[MAX_QUEUE_STR] = ""; /* queue name last entered by user */ 144 static char Host[MAX_HOST_STR] = ""; /* host name last entered by user */ 145 static char CmdText[MAX_CMD_STR] = ""; /* print command last entered by user */ 146 static int CmdFieldModified = False; /* user last changed the print command 147 field, so don't trust the rest */ 148 149 static struct printPrefDescrip PrintPrefDescrip = { 150 {"printCommand", "PrintCommand", PREF_STRING, NULL, 151 PrintCommand, (void *)MAX_PCMD_STR, False}, 152 {"printCopiesOption", "PrintCopiesOption", PREF_STRING, NULL, 153 CopiesOption, (void *)MAX_OPT_STR, False}, 154 {"printQueueOption", "PrintQueueOption", PREF_STRING, NULL, 155 QueueOption, (void *)MAX_OPT_STR, False}, 156 {"printNameOption", "PrintNameOption", PREF_STRING, NULL, 157 NameOption, (void *)MAX_OPT_STR, False}, 158 {"printHostOption", "PrintHostOption", PREF_STRING, NULL, 159 HostOption, (void *)MAX_OPT_STR, False}, 160 {"printDefaultQueue", "PrintDefaultQueue", PREF_STRING, NULL, 161 DefaultQueue, (void *)MAX_QUEUE_STR, False}, 162 {"printDefaultHost", "PrintDefaultHost", PREF_STRING, NULL, 163 DefaultHost, (void *)MAX_HOST_STR, False}, 164 }; 165 166 /* 167 ** PrintFile(Widget parent, char *printFile, char *jobName); 168 ** 169 ** function to put up an application-modal style Print Panel dialog 170 ** box. 171 ** 172 ** parent Parent widget for displaying dialog 173 ** printFile File to print (assumed to be a temporary file 174 ** and not revealed to the user) 175 ** jobName Title for the print banner page 176 */ 177 void PrintFile(Widget parent, const char *printFile, const char *jobName) 178 { 179 /* In case the program hasn't called LoadPrintPreferences, set up the 180 default values for the print preferences */ 181 if (!PreferencesLoaded) 182 LoadPrintPreferences(NULL, "", "", True); 183 184 /* Make the PrintFile information available to the callback routines */ 185 PrintFileName = printFile; 186 PrintJobName = jobName; 187 188 /* Create and display the print dialog */ 189 DoneWithDialog = False; 190 Form = createForm(parent); 191 ManageDialogCenteredOnPointer(Form); 192 193 /* Process events until the user is done with the print dialog */ 194 while (!DoneWithDialog) 195 XtAppProcessEvent(XtWidgetToApplicationContext(Form), XtIMAll); 196 197 /* Destroy the dialog. Print dialogs are not preserved across calls 198 to PrintFile so that it may be called with different parents and 199 to generally simplify the call (this, of course, makes it slower) */ 200 XtDestroyWidget(Form); 201 } 202 203 /* 204 ** LoadPrintPreferences 205 ** 206 ** Read an X database to obtain print dialog preferences. 207 ** 208 ** prefDB X database potentially containing print preferences 209 ** appName Application name which can be used to qualify 210 ** resource names for database lookup. 211 ** appClass Application class which can be used to qualify 212 ** resource names for database lookup. 213 ** lookForFlpr Check if the flpr print command is installed 214 ** and use that for the default if it's found. 215 ** (flpr is a Fermilab utility for printing on 216 ** arbitrary systems that support the lpr protocol) 217 */ 218 void LoadPrintPreferences(XrmDatabase prefDB, const char *appName, 219 const char *appClass, int lookForFlpr) 220 { 221 static char defaultQueue[MAX_QUEUE_STR], defaultHost[MAX_HOST_STR]; 222 223 /* check if flpr is installed, and otherwise choose appropriate 224 printer per system type */ 225 if (lookForFlpr && flprPresent()) { 226 getFlprQueueDefault(defaultQueue); 227 getFlprHostDefault(defaultHost); 228 PrintPrefDescrip.printCommand.defaultString = "flpr"; 229 PrintPrefDescrip.copiesOption.defaultString = ""; 230 PrintPrefDescrip.queueOption.defaultString = "-q"; 231 PrintPrefDescrip.nameOption.defaultString = "-j "; 232 PrintPrefDescrip.hostOption.defaultString = "-h"; 233 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue; 234 PrintPrefDescrip.defaultHost.defaultString = defaultHost; 235 } else { 236 #ifdef USE_LPR_PRINT_CMD 237 getLprQueueDefault(defaultQueue); 238 PrintPrefDescrip.printCommand.defaultString = "lpr"; 239 PrintPrefDescrip.copiesOption.defaultString = "-# "; 240 PrintPrefDescrip.queueOption.defaultString = "-P "; 241 PrintPrefDescrip.nameOption.defaultString = "-J "; 242 PrintPrefDescrip.hostOption.defaultString = ""; 243 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue; 244 PrintPrefDescrip.defaultHost.defaultString = ""; 245 #else 246 getLpQueueDefault(defaultQueue); 247 PrintPrefDescrip.printCommand.defaultString = "lp"; /* was lp -c */ 248 PrintPrefDescrip.copiesOption.defaultString = "-n"; 249 PrintPrefDescrip.queueOption.defaultString = "-d"; 250 PrintPrefDescrip.nameOption.defaultString = "-t"; 251 PrintPrefDescrip.hostOption.defaultString = ""; 252 PrintPrefDescrip.defaultQueue.defaultString = defaultQueue; 253 PrintPrefDescrip.defaultHost.defaultString = ""; 254 #endif 255 } 256 257 258 /* Read in the preferences from the X database using the mechanism from 259 prefFile.c (this allows LoadPrintPreferences to work before any 260 widgets are created, which is more convenient than XtGetApplication- 261 Resources for applications which have no main window) */ 262 RestorePreferences(NULL, prefDB, appName, appClass, 263 (PrefDescripRec *)&PrintPrefDescrip, N_PRINT_PREFS); 264 265 PreferencesLoaded = True; 266 } 267 268 static Widget createForm(Widget parent) 269 { 270 Widget form, printOk, printCancel, label1, separator; 271 Widget topWidget = NULL; 272 XmString st0; 273 Arg args[65]; 274 int argcnt; 275 Widget bwidgetarray [30]; 276 int bwidgetcnt = 0; 277 278 /************************ FORM ***************************/ 279 argcnt = 0; 280 XtSetArg(args[argcnt], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); 281 argcnt++; 282 XtSetArg(args[argcnt], XmNdialogTitle, (st0=XmStringCreateLtoR( 283 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++; 284 XtSetArg(args[argcnt], XmNautoUnmanage, False); argcnt++; 285 form = CreateFormDialog(parent, "printForm", args, argcnt); 286 XtVaSetValues(form, XmNshadowThickness, 0, NULL); 287 288 XmStringFree( st0 ); 289 290 /*********************** LABEL 1 and TEXT BOX 1 *********************/ 291 if (CopiesOption[0] != '\0') { 292 argcnt = 0; 293 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 294 "Number of copies (1)", XmSTRING_DEFAULT_CHARSET))); argcnt++; 295 XtSetArg(args[argcnt], XmNmnemonic, 'N'); argcnt++; 296 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_FORM); argcnt++; 297 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+5); argcnt++; 298 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++; 299 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++; 300 label1 = XmCreateLabelGadget(form, "label1", args, argcnt); 301 XmStringFree( st0 ); 302 bwidgetarray[bwidgetcnt] = label1; bwidgetcnt++; 303 304 argcnt = 0; 305 XtSetArg(args[argcnt], XmNshadowThickness, (short)2); argcnt++; 306 XtSetArg(args[argcnt], XmNcolumns, 3); argcnt++; 307 XtSetArg(args[argcnt], XmNrows, 1); argcnt++; 308 XtSetArg(args[argcnt], XmNvalue , Copies); argcnt++; 309 XtSetArg(args[argcnt], XmNmaxLength, 3); argcnt++; 310 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_FORM); argcnt++; 311 XtSetArg(args[argcnt], XmNtopOffset, 5); argcnt++; 312 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++; 313 XtSetArg(args[argcnt], XmNleftWidget, label1); argcnt++; 314 Text1 = XmCreateText(form, "text1", args, argcnt); 315 bwidgetarray[bwidgetcnt] = Text1; bwidgetcnt++; 316 XtAddCallback(Text1, XmNmodifyVerifyCallback, 317 (XtCallbackProc)allowOnlyNumInput, NULL); 318 XtAddCallback(Text1, XmNvalueChangedCallback, 319 (XtCallbackProc)updatePrintCmd, NULL); 320 RemapDeleteKey(Text1); 321 topWidget = Text1; 322 XtVaSetValues(label1, XmNuserData, Text1, NULL); /* mnemonic procesing */ 323 } 324 325 /************************ LABEL 2 and TEXT 2 ************************/ 326 if (QueueOption[0] != '\0') { 327 argcnt = 0; 328 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 329 " ", XmSTRING_DEFAULT_CHARSET))); argcnt++; 330 XtSetArg(args[argcnt], XmNmnemonic, 'Q'); argcnt++; 331 XtSetArg(args[argcnt], XmNrecomputeSize, True); argcnt++; 332 XtSetArg(args[argcnt], XmNtopAttachment, 333 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++; 334 XtSetArg(args[argcnt], XmNtopWidget, topWidget); argcnt++; 335 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++; 336 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+4); argcnt++; 337 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++; 338 Label2 = XmCreateLabelGadget(form, "label2", args, argcnt); 339 XmStringFree(st0); 340 bwidgetarray[bwidgetcnt] = Label2; bwidgetcnt++; 341 setQueueLabelText(); 342 343 argcnt = 0; 344 XtSetArg(args[argcnt], XmNshadowThickness, (short)2); argcnt++; 345 XtSetArg(args[argcnt], XmNcolumns, (short)17); argcnt++; 346 XtSetArg(args[argcnt], XmNmaxLength, MAX_QUEUE_STR); argcnt++; 347 XtSetArg(args[argcnt], XmNvalue, Queue); argcnt++; 348 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++; 349 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++; 350 XtSetArg(args[argcnt], XmNleftWidget, Label2 ); argcnt++; 351 XtSetArg(args[argcnt], XmNtopAttachment, 352 topWidget==NULL?XmATTACH_FORM:XmATTACH_WIDGET); argcnt++; 353 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++; 354 XtSetArg(args[argcnt], XmNrightOffset, 8); argcnt++; 355 XtSetArg(args[argcnt], XmNtopOffset, 4); argcnt++; 356 Text2 = XmCreateText(form, "text2", args, argcnt); 357 XtAddCallback(Text2, XmNmodifyVerifyCallback, 358 (XtCallbackProc)noSpaceOrPunct, NULL); 359 XtAddCallback(Text2, XmNvalueChangedCallback, 360 (XtCallbackProc)updatePrintCmd, NULL); 361 bwidgetarray[bwidgetcnt] = Text2; bwidgetcnt++; 362 RemapDeleteKey(Text2); 363 XtVaSetValues(Label2, XmNuserData, Text2, NULL); /* mnemonic procesing */ 364 topWidget = Text2; 365 } 366 367 /****************** LABEL 3 and TEXT 3 *********************/ 368 if (HostOption[0] != '\0') { 369 argcnt = 0; 370 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 371 " ", XmSTRING_DEFAULT_CHARSET))); argcnt++; 372 XtSetArg(args[argcnt], XmNmnemonic, 'H'); argcnt++; 373 XtSetArg(args[argcnt], XmNrecomputeSize, True); argcnt++; 374 XtSetArg(args[argcnt], XmNvalue , ""); 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], XmNleftOffset, 8); argcnt++; 380 XtSetArg(args[argcnt], XmNtopOffset, LABEL_TEXT_DIFF+4); argcnt++; 381 Label3 = XmCreateLabelGadget(form, "label3", args, argcnt); 382 XmStringFree(st0); 383 bwidgetarray[bwidgetcnt] = Label3; bwidgetcnt++; 384 setHostLabelText(); 385 386 argcnt = 0; 387 XtSetArg(args[argcnt], XmNcolumns, 17); argcnt++; 388 XtSetArg(args[argcnt], XmNrows, 1); argcnt++; 389 XtSetArg(args[argcnt], XmNvalue, Host); argcnt++; 390 XtSetArg(args[argcnt], XmNmaxLength, MAX_HOST_STR); argcnt++; 391 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++; 392 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_WIDGET); argcnt++; 393 XtSetArg(args[argcnt], XmNleftWidget, Label3 ); 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 Text3 = XmCreateText(form, "Text3", args, argcnt); 400 XtAddCallback(Text3, XmNmodifyVerifyCallback, 401 (XtCallbackProc)noSpaceOrPunct, NULL); 402 XtAddCallback(Text3, XmNvalueChangedCallback, 403 (XtCallbackProc)updatePrintCmd, NULL); 404 bwidgetarray[bwidgetcnt] = Text3; bwidgetcnt++; 405 RemapDeleteKey(Text3); 406 XtVaSetValues(Label3, XmNuserData, Text3, NULL); /* mnemonic procesing */ 407 topWidget = Text3; 408 } 409 410 /************************** TEXT 4 ***************************/ 411 argcnt = 0; 412 XtSetArg(args[argcnt], XmNvalue, CmdText); argcnt++; 413 XtSetArg(args[argcnt], XmNcolumns, 50); argcnt++; 414 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++; 415 XtSetArg(args[argcnt], XmNleftOffset, 8); argcnt++; 416 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++; 417 XtSetArg(args[argcnt], XmNtopOffset, 8); argcnt++; 418 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++; 419 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++; 420 XtSetArg(args[argcnt], XmNrightOffset, 8); argcnt++; 421 Text4 = XmCreateText(form, "Text4", args, argcnt); 422 XtAddCallback(Text4, XmNmodifyVerifyCallback, 423 (XtCallbackProc)printCmdModified, NULL); 424 bwidgetarray[bwidgetcnt] = Text4; bwidgetcnt++; 425 RemapDeleteKey(Text4); 426 topWidget = Text4; 427 if (!CmdFieldModified) 428 updatePrintCmd(NULL, NULL, NULL); 429 430 /*********************** SEPARATOR **************************/ 431 argcnt = 0; 432 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_FORM); argcnt++; 433 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++; 434 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_FORM); argcnt++; 435 XtSetArg(args[argcnt], XmNtopOffset, 8); argcnt++; 436 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++; 437 separator = XmCreateSeparatorGadget(form, "separator", args, argcnt); 438 bwidgetarray[bwidgetcnt] = separator; bwidgetcnt++; 439 topWidget = separator; 440 441 /********************** CANCEL BUTTON *************************/ 442 argcnt = 0; 443 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 444 "Cancel", XmSTRING_DEFAULT_CHARSET))); argcnt++; 445 XtSetArg(args[argcnt], XmNleftAttachment, XmATTACH_POSITION); argcnt++; 446 XtSetArg(args[argcnt], XmNleftPosition, 60); argcnt++; 447 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++; 448 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++; 449 XtSetArg(args[argcnt], XmNtopOffset, 7); argcnt++; 450 printCancel = XmCreatePushButton(form, "printCancel", args, argcnt); 451 XmStringFree( st0 ); 452 bwidgetarray[bwidgetcnt] = printCancel; bwidgetcnt++; 453 XtAddCallback (printCancel, XmNactivateCallback, 454 (XtCallbackProc)cancelButtonCB, NULL); 455 456 /*********************** PRINT BUTTON **************************/ 457 argcnt = 0; 458 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 459 "Print", XmSTRING_DEFAULT_CHARSET))); argcnt++; 460 XtSetArg(args[argcnt], XmNshowAsDefault, True); argcnt++; 461 XtSetArg(args[argcnt], XmNrightAttachment, XmATTACH_POSITION); argcnt++; 462 XtSetArg(args[argcnt], XmNrightPosition, 40); argcnt++; 463 XtSetArg(args[argcnt], XmNtopAttachment, XmATTACH_WIDGET); argcnt++; 464 XtSetArg(args[argcnt], XmNtopWidget, topWidget ); argcnt++; 465 XtSetArg(args[argcnt], XmNtopOffset, 7); argcnt++; 466 printOk = XmCreatePushButton(form, "printOk", args, argcnt); 467 XmStringFree( st0 ); 468 bwidgetarray[bwidgetcnt] = printOk; bwidgetcnt++; 469 XtAddCallback (printOk, XmNactivateCallback, 470 (XtCallbackProc)printButtonCB, NULL); 471 472 argcnt = 0; 473 XtSetArg(args[argcnt], XmNcancelButton, printCancel); argcnt++; 474 XtSetArg(args[argcnt], XmNdefaultButton, printOk); argcnt++; 475 XtSetValues(form, args, argcnt); 476 477 XtManageChildren(bwidgetarray, bwidgetcnt); 478 AddDialogMnemonicHandler(form, FALSE); 479 return form; 480 } 481 482 static void setQueueLabelText(void) 483 { 484 Arg args[15]; 485 int argcnt; 486 XmString st0; 487 char tmp_buf[MAX_QUEUE_STR+8]; 488 489 if (DefaultQueue[0] != '\0') 490 sprintf(tmp_buf, "Queue (%s)", DefaultQueue); 491 else 492 sprintf(tmp_buf, "Queue"); 493 argcnt = 0; 494 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 495 tmp_buf, XmSTRING_DEFAULT_CHARSET))); argcnt++; 496 XtSetValues (Label2, args, argcnt); 497 XmStringFree( st0 ); 498 } 499 500 static void setHostLabelText(void) 501 { 502 Arg args[15]; 503 int argcnt; 504 XmString st0; 505 char tmp_buf[MAX_HOST_STR+7]; 506 507 if (strcmp(DefaultHost, "")) 508 sprintf(tmp_buf, "Host (%s)", DefaultHost); 509 else 510 sprintf(tmp_buf, "Host"); 511 argcnt = 0; 512 XtSetArg(args[argcnt], XmNlabelString, (st0=XmStringCreateLtoR( 513 tmp_buf, XmSTRING_DEFAULT_CHARSET))); argcnt++; 514 515 XtSetValues (Label3, args, argcnt); 516 XmStringFree( st0 ); 517 } 518 519 static void allowOnlyNumInput(Widget widget, caddr_t client_data, 520 XmTextVerifyCallbackStruct *call_data) 521 { 522 int i, textInserted, nInserted; 523 524 nInserted = call_data->text->length; 525 textInserted = (nInserted > 0); 526 if ((call_data->reason == XmCR_MODIFYING_TEXT_VALUE) && textInserted) { 527 for (i=0; i<nInserted; i++) { 528 if (!isdigit((unsigned char)call_data->text->ptr[i])) { 529 call_data->doit = False; 530 return; 531 } 532 } 533 } 534 call_data->doit = True; 535 } 536 537 /* 538 ** Prohibit a relatively random sampling of characters that will cause 539 ** problems on command lines 540 */ 541 static void noSpaceOrPunct(Widget widget, caddr_t client_data, 542 XmTextVerifyCallbackStruct *call_data) 543 { 544 int i, j, textInserted, nInserted; 545 static char prohibited[] = " \t,;|<>()[]{}!@?"; 546 547 nInserted = call_data->text->length; 548 textInserted = (nInserted > 0); 549 if ((call_data->reason == XmCR_MODIFYING_TEXT_VALUE) && textInserted) { 550 for (i=0; i<nInserted; i++) { 551 for (j=0; j<(int)XtNumber(prohibited); j++) { 552 if (call_data->text->ptr[i] == prohibited[j]) { 553 call_data->doit = False; 554 return; 555 } 556 } 557 } 558 } 559 call_data->doit = True; 560 } 561 562 static void updatePrintCmd(Widget w, caddr_t client_data, caddr_t call_data) 563 { 564 char command[MAX_CMD_STR], copiesArg[MAX_OPT_STR+MAX_INT_STR]; 565 char jobArg[MAX_NAME_STR], hostArg[MAX_OPT_STR+MAX_HOST_STR]; 566 char queueArg[MAX_OPT_STR+MAX_QUEUE_STR]; 567 char *str; 568 int nCopies; 569 570 /* read each text field in the dialog and generate the corresponding 571 command argument */ 572 if (CopiesOption[0] == '\0') { 573 copiesArg[0] = '\0'; 574 } else { 575 str = XmTextGetString(Text1); 576 if (str[0] == '\0') { 577 copiesArg[0] = '\0'; 578 } else { 579 if (sscanf(str, "%d", &nCopies) != 1) { 580 copiesArg[0] = '\0'; 581 } else { 582 sprintf(copiesArg, " %s%s", CopiesOption, str); 583 } 584 } 585 NEditFree(str); 586 } 587 if (QueueOption[0] == '\0') { 588 queueArg[0] = '\0'; 589 } else { 590 str = XmTextGetString(Text2); 591 if (str[0] == '\0') 592 queueArg[0] = '\0'; 593 else 594 sprintf(queueArg, " %s%s", QueueOption, str); 595 NEditFree(str); 596 } 597 if (HostOption[0] == '\0') { 598 hostArg[0] = '\0'; 599 } else { 600 str = XmTextGetString(Text3); 601 if (str[0] == '\0') 602 hostArg[0] = '\0'; 603 else 604 sprintf(hostArg, " %s%s", HostOption, str); 605 NEditFree(str); 606 } 607 if (NameOption[0] == '\0') 608 jobArg[0] = '\0'; 609 else { 610 sprintf(jobArg, " %s\"%s\"", NameOption, PrintJobName); 611 } 612 613 /* Compose the command from the options determined above */ 614 sprintf(command, "%s%s%s%s%s", PrintCommand, copiesArg, 615 queueArg, hostArg, jobArg); 616 617 /* display it in the command text area */ 618 XmTextSetString(Text4, command); 619 620 /* Indicate that the command field was synthesized from the other fields, 621 so future dialog invocations can safely re-generate the command without 622 overwriting commands specifically entered by the user */ 623 CmdFieldModified = False; 624 } 625 626 static void printCmdModified(Widget w, caddr_t client_data, caddr_t call_data) 627 { 628 /* Indicate that the user has specifically modified the print command 629 and that this field should be left as is in subsequent dialogs */ 630 CmdFieldModified = True; 631 } 632 633 static void printButtonCB(Widget widget, caddr_t client_data, caddr_t call_data) 634 { 635 char *str, command[MAX_CMD_STR]; 636 int nRead; 637 FILE *pipe; 638 char errorString[MAX_PRINT_ERROR_LENGTH], discarded[1024]; 639 640 /* get the print command from the command text area */ 641 str = XmTextGetString(Text4); 642 643 /* add the file name and output redirection to the print command */ 644 sprintf(command, "cat %s | %s 2>&1", PrintFileName, str); 645 NEditFree(str); 646 647 /* Issue the print command using a popen call and recover error messages 648 from the output stream of the command. */ 649 pipe = popen(command,"r"); 650 if (pipe == NULL) 651 { 652 DialogF(DF_WARN, widget, 1, "Print Error", "Unable to Print:\n%s", 653 "OK", strerror(errno)); 654 return; 655 } 656 657 errorString[0] = 0; 658 nRead = fread(errorString, sizeof(char), MAX_PRINT_ERROR_LENGTH-1, pipe); 659 /* Make sure that the print command doesn't get stuck when trying to 660 write a lot of output on stderr (pipe may fill up). We discard 661 the additional output, though. */ 662 while (fread(discarded, sizeof(char), 1024, pipe) > 0); 663 664 if (!ferror(pipe)) 665 { 666 errorString[nRead] = '\0'; 667 } 668 669 if (pclose(pipe)) 670 { 671 DialogF(DF_WARN, widget, 1, "Print Error", "Unable to Print:\n%s", 672 "OK", errorString); 673 return; 674 } 675 676 /* Print command succeeded, so retain the current print parameters */ 677 if (CopiesOption[0] != '\0') { 678 str = XmTextGetString(Text1); 679 strcpy(Copies, str); 680 NEditFree(str); 681 } 682 if (QueueOption[0] != '\0') { 683 str = XmTextGetString(Text2); 684 strcpy(Queue, str); 685 NEditFree(str); 686 } 687 if (HostOption[0] != '\0') { 688 str = XmTextGetString(Text3); 689 strcpy(Host, str); 690 NEditFree(str); 691 } 692 str = XmTextGetString(Text4); 693 strcpy(CmdText, str); 694 NEditFree(str); 695 696 697 /* Pop down the dialog */ 698 DoneWithDialog = True; 699 } 700 701 static void cancelButtonCB(Widget widget, caddr_t client_data, caddr_t call_data) 702 { 703 DoneWithDialog = True; 704 CmdFieldModified = False; 705 } 706 707 /* 708 ** Is the filename file in the directory dirpath 709 ** and does it have at least some of the mode_flags enabled ? 710 */ 711 static int fileInDir(const char *filename, const char *dirpath, unsigned short mode_flags) 712 { 713 DIR *dfile; 714 struct dirent *DirEntryPtr; 715 struct stat statbuf; 716 char fullname[MAXPATHLEN]; 717 718 dfile = opendir(dirpath); 719 if (dfile != NULL) { 720 while ((DirEntryPtr=readdir(dfile)) != NULL) { 721 if (!strcmp(DirEntryPtr->d_name, filename)) { 722 strcpy(fullname,dirpath); 723 strcat(fullname,"/"); 724 strcat(fullname,filename); 725 stat(fullname,&statbuf); 726 closedir(dfile); 727 return statbuf.st_mode & mode_flags; 728 } 729 } 730 closedir(dfile); 731 } 732 return False; 733 } 734 735 /* 736 ** Is the filename file in the environment path directories 737 ** and does it have at least some of the mode_flags enabled ? 738 */ 739 static int fileInPath(const char *filename, unsigned short mode_flags) 740 { 741 char path[MAXPATHLEN]; 742 char *pathstring,*lastchar; 743 744 /* Get environmental value of PATH */ 745 pathstring = getenv("PATH"); 746 if (pathstring == NULL) 747 return False; 748 749 /* parse the pathstring and search on each directory found */ 750 do { 751 /* if final path in list is empty, don't search it */ 752 if (!strcmp(pathstring, "")) 753 return False; 754 /* locate address of next : character */ 755 lastchar = strchr(pathstring, SEPARATOR); 756 if (lastchar != NULL) { 757 /* if more directories remain in pathstring, copy up to : */ 758 strncpy(path, pathstring, lastchar-pathstring); 759 path[lastchar-pathstring] = '\0'; 760 } else { 761 /* if it's the last directory, just copy it */ 762 strcpy(path, pathstring); 763 } 764 /* search for the file in this path */ 765 if(fileInDir(filename, path, mode_flags)) 766 return True; /* found it !! */ 767 /* point pathstring to start of new dir string */ 768 pathstring = lastchar + 1; 769 } while( lastchar != NULL ); 770 return False; 771 } 772 773 /* 774 ** Is flpr present in the search path and is it executable ? 775 */ 776 static int flprPresent(void) 777 { 778 /* Is flpr present in the search path and is it executable ? */ 779 return fileInPath("flpr",0111); 780 } 781 782 static int foundTag(const char *tagfilename, const char *tagname, char *result) 783 { 784 FILE *tfile; 785 char tagformat[512],line[512]; 786 787 strcpy(tagformat, tagname); 788 strcat(tagformat, " %s"); 789 790 tfile = fopen(tagfilename,"r"); 791 if (tfile != NULL) { 792 while (!feof(tfile)) { 793 if (fgets(line,sizeof(line),tfile)) { 794 if (sscanf(line,tagformat,result) != 0) { 795 fclose(tfile); 796 return True; 797 } 798 } 799 } 800 fclose(tfile); 801 } 802 return False; 803 } 804 805 static int foundEnv(const char *EnvVarName, char *result) 806 { 807 char *dqstr; 808 809 dqstr = getenv(EnvVarName); 810 if (dqstr != NULL) { 811 strcpy(result,dqstr); 812 return True; 813 } 814 return False; 815 } 816 817 static void getFlprHostDefault(char *defhost) 818 { 819 if (!foundEnv("FLPHOST",defhost)) 820 if(!foundTag("/usr/local/etc/flp.defaults", "host", defhost)) 821 strcpy(defhost,""); 822 } 823 824 static void getFlprQueueDefault(char *defqueue) 825 { 826 if (!foundEnv("FLPQUE",defqueue)) 827 if (!foundTag("/usr/local/etc/flp.defaults", "queue", defqueue)) 828 strcpy(defqueue,""); 829 } 830 831 #ifdef USE_LPR_PRINT_CMD 832 static void getLprQueueDefault(char *defqueue) 833 { 834 if (!foundEnv("PRINTER",defqueue)) 835 strcpy(defqueue,""); 836 } 837 #endif 838 839 #ifndef USE_LPR_PRINT_CMD 840 static void getLpQueueDefault(char *defqueue) 841 { 842 if (!foundEnv("LPDEST",defqueue)) 843 defqueue[0] = '\0'; 844 } 845 #endif 846 847 848 849