source: trunk/gui/shared/PrManUtl.VRS@ 51

Last change on this file since 51 was 51, checked in by Alex Taylor, 10 years ago

Try to fix spurious error when updating PrinterPak files if there are no PPDs to reimport.

File size: 39.0 KB
Line 
1/*:VRX DriverIsInstalled
2*/
3/* Checks if a given print driver (without extension) is installed, and if so
4 * returns the path to the active files. Returns '' if the driver is not
5 * installed.
6 */
7DriverIsInstalled: PROCEDURE
8 ARG driver
9 PARSE VALUE VRGetIni('PM_DEVICE_DRIVERS', driver, 'USER') WITH drv_path '00'x .
10 IF ( drv_path <> '') THEN
11 drv_path = STREAM( drv_path, 'C', 'QUERY EXISTS')
12RETURN drv_path
13
14
15/*:VRX GetDriverSource
16*/
17/* Figure out where to look for the PrinterPak driver files used as the install
18 * source. Preference is given to the local repository (PDR_DIR); if it's not
19 * there, we look in a couple of other places where it might have ended up.
20 * Note that we don't look for the actual installed driver files under \OS2\DLL;
21 * that logic is handled in LocateDriverFiles(), which calls this routine.
22 *
23 * Various global values are assumed to be set already:
24 * - globals.!prdrv: filespec of \OS2\INSTALL\PRDRV.LST
25 * - globals.!repository: value indicated by PM_INSTALL->PDR_DIR in OS2.INI
26 *
27 * Arguments: The print driver name without path or extension
28 *
29 * Returns the path, or '' if not found. Also, 'pmdx' will be 0-9 if the
30 * driver is in the repository (indicating the repository subdirectory), or
31 * '' if the driver is not in the repository.
32 */
33GetDriverSource: PROCEDURE EXPOSE globals. pmdx
34 ARG driver
35 IF driver == '' THEN RETURN ''
36
37 drv_file = ''
38 IF globals.!repository <> '' THEN DO
39
40 /* See if the driver is defined in the local repository. (This is the
41 * directory where installable printer drivers are kept. OS/2 gets them
42 * from here when you select 'Printer driver included with OS/2'.)
43 */
44 pmdx = GetDriverPMDD( driver, globals.!prdrv )
45 IF pmdx == '' THEN DO
46 /* Hmm, the driver isn't listed in PRDRV.LST. Let's check to see if
47 * it's in the default repository location anyway.
48 */
49 IF WORDPOS( driver, 'ECUPS ECUPS-HP PSPRINT PSPRINT2') > 0 THEN
50 pmdx = '9'
51 ELSE
52 pmdx = '0'
53 drv_file = STREAM( globals.!repository'\PMDD_'pmdx'\'driver'.DRV', 'C', 'QUERY EXISTS')
54 IF drv_file <> '' THEN DO
55 /* We found the driver in the repository, even though it isn't
56 * defined as such. So let's add the proper definition to
57 * PRDRV.LST now.
58 */
59 CALL LINEOUT globals.!prdrv, LEFT( driver'.DRV', 14 ) pmdx ||,
60 ' (added automatically)'
61 CALL LINEOUT globals.!prdrv
62 END
63 ELSE
64 pmdx = ''
65 END
66 ELSE DO
67 /* The driver is listed; now make sure it's actually there.
68 */
69 drv_file = STREAM( globals.!repository'\PMDD_'pmdx'\'driver'.DRV', 'C', 'QUERY EXISTS')
70 END
71 END
72
73 IF drv_file == '' THEN DO
74 CALL LINEOUT globals.!log1, 'Driver' driver 'is not in the local repository.'
75 /* If the driver really isn't in the repository, there are a couple of
76 * other places that various install utilities might have put it...
77 */
78 PARSE VALUE VRGetIni('PM_INSTALL', driver'_DIR', 'USER') WITH drvr_dir '00'x .
79 IF drvr_dir == '' THEN
80 PARSE VALUE VRGetIni('InstPDR', 'PATH_TO_'driver, 'USER') WITH drvr_dir '00'x .
81 IF drvr_dir <> '' THEN DO
82 drv_file = drvr_dir'\'driver'.DRV'
83 CALL LINEOUT globals.!log1, 'Found driver in' drvr_dir'.'
84 END
85 END
86
87RETURN drv_file
88
89
90/*:VRX GetDriverPMDD
91*/
92/* Check to see which repository directory the specified driver resides in.
93 * Returns the number suffix of the PMDD_* subdirectory name, or '' if either
94 * the driver or the index file could not be located.
95 *
96 * Arguments: The print driver name without path or extension
97 */
98GetDriverPMDD: PROCEDURE
99 PARSE ARG driver, prdrv_lst
100
101 IF prdrv_lst <> '' THEN DO
102 CALL LINEIN prdrv_lst, 1, 0
103 DO WHILE LINES( prdrv_lst ) > 0
104 PARSE VALUE LINEIN( prdrv_lst ) WITH (driver)'.DRV' pmdx .
105 IF pmdx <> '' THEN LEAVE
106 END
107 CALL STREAM prdrv_lst, 'C', 'CLOSE'
108 END
109 ELSE pmdx = ''
110
111RETURN pmdx
112
113
114/*:VRX LocateDriverFiles
115*/
116/* Locates the source files for a PostScript-based driver that will be required in
117 * order to import a PPD using PIN. Not to be used with non-PostScript drivers,
118 * since it will fail if PIN or PPDENC are not found.
119 *
120 * Arguments: The print driver name without path or extension
121 *
122 * Returns:
123 * 0 - Driver files not found.
124 * 1 - Driver files found, path saved in 'driver_path'; 'driver_repo' will be 1
125 * if the driver is 'shipped' (i.e. defined in PRDRV.LST) or 0 otherwise.
126 * 2 - Only found installed driver files in (\OS2\DLL\xxx, saved in 'driver_path');
127 * will need to copy them somewhere for future installs.
128 */
129LocateDriverFiles: PROCEDURE EXPOSE globals. driver_path driver_repo
130 ARG driver
131 IF driver == '' THEN driver = 'PSCRIPT'
132
133 CALL LINEOUT globals.!log1, 'Looking for' driver 'files'
134
135 mustcopy = 0
136 driver_path = GetDriverSource( driver )
137
138 IF driver_path == '' THEN DO
139 /* No source found. We'll have to try copying the actual installed
140 * driver files from under \OS2\DLL.
141 */
142 CALL LINEOUT globals.!log1, 'Driver source not found. Trying installed driver.'
143 PARSE VALUE VRGetIni('PM_DEVICE_DRIVERS', driver, 'USER') WITH drv_used '00'x .
144 IF ( drv_used <> '') & VRFileExists( drv_used ) THEN
145 driver_path = drv_used
146 END
147 IF driver_path <> '' THEN DO
148 srcdir = VRParseFilePath( driver_path, 'DP')
149 pin = STREAM( srcdir'\PIN.EXE', 'C', 'QUERY EXISTS')
150 ppdenc = STREAM( srcdir'\PPDENC.EXE', 'C', 'QUERY EXISTS')
151 /* TODO should we check for all the REQUIREDDRIVER FILES as well? */
152 END
153
154 IF pmdx == '' THEN
155 driver_repo = 0
156 ELSE
157 driver_repo = 1
158
159 /* Driver (or one of its required files) was not found.
160 */
161 IF ( driver_path == '') | ( pin == '') | ( ppdenc == '') | ,
162 ( VerifyDriverEAs( driver_path ) == 0 ) THEN
163 DO
164 CALL LINEOUT globals.!log1, ' - Missing required driver files.'
165 RETURN 0
166 END
167
168 IF mustcopy THEN RETURN 2
169RETURN 1
170
171
172/*:VRX VerifyDriverEAs
173*/
174/* Make sure the driver has its extended attributes. If not, look for an
175 * accompanying .EA or .EA_ file, and join it to the driver.
176 */
177VerifyDriverEAs: PROCEDURE EXPOSE globals.
178 PARSE ARG driver
179 eas.0 = 0
180 CALL SysQueryEAList driver, 'eas.'
181 IF eas.0 == 0 THEN DO
182 ea_file = SUBSTR( driver, 1, LASTPOS('.', driver )) || 'EA'
183 IF STREAM( ea_file, 'C', 'QUERY EXISTS') == '' THEN
184 ea_file = ea_file || '_'
185 IF STREAM( ea_file, 'C', 'QUERY EXISTS') == '' THEN
186 RETURN 0
187
188 ADDRESS CMD '@UNLOCK' driver '2>NUL 1>NUL'
189 ADDRESS CMD '@EAUTIL' driver ea_file '/j /p 2>NUL 1>NUL'
190 END
191RETURN 1
192
193
194/*:VRX BldLevelVersion
195*/
196/* Parse the revision (version) number from a BLDLEVEL string
197 */
198BldLevelVersion: PROCEDURE EXPOSE globals.
199 ARG module
200 revision = ''
201
202 _nq = RXQUEUE('CREATE')
203 _oq = RXQUEUE('SET', _nq )
204
205 ADDRESS CMD '@bldlevel' module '2>&1 | RXQUEUE' _nq
206 DO QUEUED()
207 PARSE PULL _blline
208 IF LEFT( _blline, 9 ) == 'Revision:' THEN DO
209 PARSE VAR _blline 'Revision:' revision .
210 LEAVE
211 END
212 END
213
214 CALL RXQUEUE 'SET', _oq
215 CALL RXQUEUE 'DELETE', _nq
216
217 IF revision == '' THEN revision = '-'
218
219RETURN revision
220
221
222/*:VRX CopyPrinterPak
223*/
224/* Copies a printerpak driver and all its dependent files from one directory
225 * to another.
226 *
227 * driver - The fully-qualified filename of the printerpak .DRV
228 * newdrvdir - The directory where the files will be copied; must exist
229 *
230 * Returns: 1 on success, 0 on failure
231 */
232CopyPrinterPak: PROCEDURE EXPOSE globals.
233 PARSE ARG driver, newdrvdir
234
235 drv_dir = VRParseFilePath( driver, 'DP')
236 drv_name = VRParseFilePath( driver, 'NE')
237 IF drv_dir == '' THEN RETURN 0
238
239 IF VerifyDriverEAs( driver ) == 0 THEN RETURN 0
240
241 CALL LINEOUT globals.!log1, 'Copying driver files from' drv_dir 'to' newdrvdir'...'
242
243 /* Read the list of required driver files from the EAs, and copy them
244 * all to the target directory.
245 */
246 IF SysGetEA( driver, 'REQUIREDDRIVERFILES', 'reqfiles') == 0 THEN DO
247 PARSE VAR reqfiles 5 filelist
248 filelist = TRANSLATE( filelist, ' ', ',')
249 DO i = 1 TO WORDS( filelist )
250 copyfile = drv_dir'\' || WORD( filelist, i )
251 ok = VRCopyFile( copyfile, newdrvdir'\' || WORD( filelist, i ))
252 CALL LINEOUT globals.!log1, ' -' copyfile '(REQUIRED):' ok
253 END
254 DROP copyfile
255 DROP filelist
256 END
257 ELSE RETURN 0
258
259 /* If there are optional files defined as well, try to copy those also.
260 */
261 IF SysGetEA( driver, 'OPTIONALDRIVERFILES', 'reqfiles') == 0 THEN DO
262 PARSE VAR reqfiles 5 filelist
263 filelist = TRANSLATE( filelist, ' ', ',')
264 DO i = 1 TO WORDS( filelist )
265 copyfile = drv_dir'\' || WORD( filelist, i )
266 IF STREAM( copyfile, 'C', 'QUERY EXISTS') == '' THEN ITERATE
267 ok = VRCopyFile( copyfile, newdrvdir'\' || WORD( filelist, i ))
268 CALL LINEOUT globals.!log1, ' -' copyfile '(OPTIONAL):' ok
269 END
270 DROP copyfile
271 DROP filelist
272 END
273
274 /* If AUXPRINT.PAK exists, copy it as well */
275 copyfile = drv_dir'\AUXPRINT.PAK'
276 IF STREAM( copyfile, 'C', 'QUERY EXISTS') <> '' THEN DO
277 ok = VRCopyFile( copyfile, newdrvdir'\AUXPRINT.PAK')
278 CALL LINEOUT globals.!log1, ' -' copyfile ':' ok
279 END
280
281 /* Create an EA file if necessary */
282 eafile = VRParseFilePath( driver, 'N') || '.EA'
283 IF VRFileExists( newdrvdir'\'eafile ) THEN
284 CALL VRDeleteFile newdrvdir'\'eafile
285 ADDRESS CMD '@EAUTIL' newdrvdir'\'drv_name newdrvdir'\'eafile '/s /p 2>NUL 1>NUL'
286
287RETURN 1
288
289
290/*:VRX PrinterExistsInDRV
291*/
292/* Determine if the specified PrinterPak driver already contains support
293 * for the specified printer model.
294 *
295 * If so, return the name of the model as found in the driver (necessary in
296 * order to make sure the correct case is retained, which may be different
297 * from what was requested). Otherwise return ''.
298 */
299PrinterExistsInDRV: PROCEDURE EXPOSE globals.
300 PARSE UPPER ARG driver_name, printer_name
301 printer_name = TRANSLATE( printer_name, '_', '.')
302
303 printer_drv = globals.!os2dir'\DLL\'driver_name'\'driver_name'.DRV'
304 /* ?? TODO: install driver_name if not found (prompt first) ?? */
305
306 IF SysGetEA( printer_drv, '.EXPAND', 'exist_ea') <> 0 THEN RETURN 0
307 PARSE VAR exist_ea 1 _eatype 3 .
308 IF C2X( _eatype ) <> 'FDFF' THEN RETURN 0
309
310 PARSE VAR exist_ea 3 _ealen 5 exist_models
311 total_len = C2D( REVERSE( _ealen ))
312
313 /* The variable exist_models now contains a null-separated list of printer
314 * models supported by the driver (including those from previously-imported
315 * PPD files). Next we check each one against our requested printer name.
316 */
317 start = 1
318 found = ''
319 DO WHILE ( found == 0 ) & ( start < total_len )
320 _strend = POS('0'x, exist_models, start )
321 IF _strend == 0 THEN LEAVE
322 _model = SUBSTR( exist_models, start, _strend - start )
323 IF TRANSLATE( _model ) == printer_name THEN
324 found = _model
325 ELSE
326 start = _strend + 1
327 END
328
329RETURN found
330
331
332/*:VRX CreateDriverList
333*/
334/* Generate a driver listfile from the .EXPAND EA
335 */
336CreateDriverList: PROCEDURE EXPOSE globals.
337 ARG driver, listfile
338
339 IF STREAM( listfile, 'C', 'QUERY EXISTS') <> '' THEN
340 CALL SysFileDelete listfile
341
342 drv_name = FILESPEC('NAME', driver )
343 IF SysGetEA( driver, '.EXPAND', 'eaval') == 0 THEN DO
344 PARSE VAR eaval 3 ealen 5 models
345 offs = 1
346 datalen = C2D( REVERSE( ealen ))
347 DO WHILE offs <= datalen
348 start = SUBSTR( models, offs )
349 inc = POS('00'x, start )
350 IF inc > 1 THEN DO
351 current_name = STRIP( SUBSTR( start, 1, inc-1 ))
352 CALL LINEOUT listfile, current_name':' current_name '('drv_name')'
353 END
354 offs = offs + inc
355 END
356 CALL LINEOUT listfile
357 CALL LINEOUT globals.!log1, 'Created driver list' listfile 'for' driver'.'
358 END
359 ELSE
360 CALL LINEOUT globals.!log1, 'No drivers found in' driver '(missing .EXPAND extended attribute?)'
361
362RETURN 1
363
364
365/*:VRX AddPort_CUPS
366*/
367/* Adds a new CUPS port. Returns 0 on full success, 1 if the port was created
368 * but could not be configured, and an OS/2 or PM error code otherwise.
369 */
370AddPort_CUPS: PROCEDURE EXPOSE globals.
371 PARSE ARG portname, hostname, queuename
372 CALL LINEOUT globals.!log1, 'Creating new port' portname
373 ADDRESS CMD '@cupsport' portname hostname queuename '>>' globals.!log2
374 IF rc == 1 THEN DO
375 CALL VRSetIni 'PM_'portname, 'INITIALIZATION', hostname'#'queuename||'00'x, 'SYSTEM', 'NoClose'
376 CALL VRSetIni 'PM_'portname, 'DESCRIPTION', hostname':'queuename||'00'x, 'SYSTEM'
377 END
378RETURN rc
379
380
381/*:VRX DeletePort
382*/
383/* Deletes a printer port (any type).
384 */
385DeletePort: PROCEDURE EXPOSE globals.
386 PARSE ARG portname
387 CALL SysIni 'SYSTEM', 'PM_'portname, 'DELETE:'
388 CALL SysIni 'SYSTEM', 'PM_SPOOLER_PORT', portname, 'DELETE:'
389RETURN 1
390
391
392/*:VRX GetNextPortName
393*/
394/* Get the next unique (non-existing) port name for the specified port driver.
395 */
396GetNextPortName: PROCEDURE
397 ARG portdrv
398
399 maxports = 64 /* should be smarter about this if possible */
400 exists = 1
401 x = 0
402 DO WHILE ( x < maxports ) & ( exists == 1 )
403 x = x + 1
404 portname = portdrv || x
405 nextport = SysIni('SYSTEM', 'PM_SPOOLER_PORT', portname )
406 IF LEFT( nextport, 6 ) == 'ERROR:' THEN exists = 0
407 END
408 IF exists == 1 THEN
409 portname = ''
410
411RETURN portname
412
413
414/*:VRX GetPortDrivers
415*/
416/* Get the list of currently-installed port drivers. NOTE: we exclude LPRPDRVR
417 * from this list, because it has to be managed via the TCP/IP configuration
418 * program.
419 */
420GetPortDrivers: PROCEDURE EXPOSE portdrivers.
421 ok = SysIni('SYSTEM', 'PM_PORT_DRIVER', 'ALL:', 'installed.')
422 IF LEFT( ok, 6 ) == 'ERROR:' THEN RETURN 0
423 count = 0
424 DO i = 1 TO installed.0
425 IF installed.i = 'LPRPDRVR' THEN ITERATE
426 fullpath = STRIP( SysIni('SYSTEM', 'PM_PORT_DRIVER', installed.i ), 'T', '00'x )
427 IF LEFT( fullpath, 6 ) == 'ERROR:' THEN fullpath = ''
428 fullpath = STREAM( fullpath , 'C', 'QUERY EXISTS')
429 count = count + 1
430 portdrivers.count = installed.i || ' ' || fullpath
431 END
432 portdrivers.0 = count
433RETURN portdrivers.0
434
435
436/*:VRX GetQueueName
437*/
438/* Generate a unique queue name from the specified printer name.
439 */
440GetQueueName: PROCEDURE
441 ARG queuename
442
443 DO UNTIL badchar = 0
444 badchar = VERIFY( queuename, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ-_0123456789 ')
445 IF badchar > 0 THEN
446 queuename = OVERLAY(' ', queuename, badchar, 1 )
447 END
448 queuename = LEFT( SPACE( queuename, 0 ), 8 )
449
450 tail = 0
451 PARSE VALUE VRGetIni('PM_SPOOLER', 'DIR', 'SYSTEM') WITH spldir ';' .
452 DO WHILE VRFileExists( spldir'\'queuename ) == 1
453 tail = tail + 1
454 queuename = STRIP( LEFT( queuename, 8 - LENGTH( tail ))) || tail
455 END
456
457RETURN queuename
458
459
460/*:VRX InstallPortDriver
461*/
462/* Installs a new port driver.
463 *
464 * Returns: 0 on success, 1 on error
465 */
466InstallPortDriver: PROCEDURE EXPOSE globals.
467 ARG new_pdr
468 filename = VRParseFileName( new_pdr, 'NE')
469 IF filename == '' THEN RETURN
470 installed_pdr = TRANSLATE( globals.!os2dir'\DLL\'filename )
471 IF installed_pdr <> new_pdr THEN DO
472 ok = VRCopyFile( new_pdr, installed_pdr )
473 IF ok == 0 THEN RETURN 1
474 /* Try to copy any optional files as well */
475 IF SysGetEA( new_pdr, 'OPTIONALDRIVERFILES', 'reqfiles') == 0 THEN DO
476 drv_dir = VRParseFilePath( new_pdr, 'DP')
477 PARSE VAR reqfiles 5 filelist
478 filelist = TRANSLATE( filelist, ' ', ',')
479 DO i = 1 TO WORDS( filelist )
480 copyfile = drv_dir'\' || WORD( filelist, i )
481 IF STREAM( copyfile, 'C', 'QUERY EXISTS') == '' THEN ITERATE
482 ok = VRCopyFile( copyfile, newdrvdir'\' || WORD( filelist, i ))
483 /*CALL LINEOUT globals.!log1, ' -' copyfile '(OPTIONAL):' ok*/
484 END
485 END
486 END
487
488 key = VRParseFileName( installed_pdr, 'N')
489 CALL VRSetIni 'PM_PORT_DRIVER', key, installed_pdr||'00'x, 'SYSTEM'
490RETURN 0
491
492
493/*:VRX InstallPrintDriver
494*/
495/* 'Installs' (that is to say, registers with the spooler) an OS printer
496 * device driver/model. Installs the corresponding printerpak driver if
497 * necessary.
498 *
499 * driver - The name of the printerpak driver (without path or extension)
500 * driverfull - The fully-qualified filename of the printerpak driver
501 * model - The printer make/model name used by the driver
502 *
503 * Returns: 0 on success, 1 on error
504 */
505InstallPrintDriver: PROCEDURE EXPOSE globals.
506 PARSE ARG driver, driverfull, model
507
508 ok = 0
509 targetdir = globals.!os2dir'\DLL\'driver
510 targetdrv = targetdir'\'driver'.DRV'
511 CALL LINEOUT globals.!log1, 'Installing' driver'.'model 'from' driverfull '(target' targetdrv')'
512
513 IF ( VRFileExists( targetdrv ) == 0 ) THEN DO
514 CALL VRMkDir targetdir
515 r = CopyPrinterPak( driverfull, targetdir )
516 IF r <> 1 THEN ok = 1
517 END
518 IF ok == 0 THEN DO
519 IF VRGetIni('PM_DEVICE_DRIVERS', driver, 'USER') <> targetdrv THEN
520 CALL VRSetIni 'PM_DEVICE_DRIVERS', driver, targetdrv||'00'x, 'USER'
521 CALL VRSetIni 'PM_SPOOLER_DD', driver'.'model, driver'.DRV;;;'||'00'x, 'SYSTEM'
522 END
523RETURN ok
524
525/*:VRX DeletePrintDriver
526*/
527/* Removes (that is to say, de-registers with the spooler) a PM printer
528 * device driver/model.
529 *
530 * driver - The name of the printerpak driver (without path or extension)
531 * model - The printer make/model name used by the driver
532 *
533 * Returns: 0 on success, 1 on error
534 */
535DeletePrintDriver: PROCEDURE EXPOSE globals.
536 PARSE ARG driver, model
537
538 ok = VRDelIni('PM_SPOOLER_DD', driver'.'model, 'SYSTEM')
539RETURN ok
540
541/*:VRX CreatePrinterObject
542*/
543/* Create the specified printer using SysCreateObject (this should create the
544 * queue automatically).
545 *
546 * Returns: 0 on success or non-zero return code on error.
547 */
548CreatePrinterObject: PROCEDURE EXPOSE globals.
549 PARSE ARG driver, model, portname, queuename, printername
550
551 CALL LINEOUT globals.!log1, 'Creating new printer:' printername '('queuename')'
552 ok = RPUPrinterCreate( printername, queuename, portname, driver'.'model )
553RETURN ok
554
555/*:VRX GetNameFromPPD
556*/
557GetNameFromPPD: PROCEDURE
558 ARG ppd_file
559
560 IF STREAM( ppd_file, 'C', 'QUERY EXISTS') == '' THEN RETURN ''
561 nickname = ''
562 IF VRParseFilePath( ppd_file, 'E') == 'GZ' THEN DO
563 nq = RXQUEUE('CREATE')
564 oq = RXQUEUE('SET', nq )
565 ADDRESS CMD '@gzip -c -d' ppd_file '| RXQUEUE' nq
566 DO QUEUED()
567 PARSE PULL line
568 line = STRIP( line )
569 IF LEFT( line, 15 ) == '*ShortNickName:' THEN DO
570 PARSE VAR line . ':' _nick '0D'x .
571 nickname = STRIP( _nick )
572 nickname = STRIP( nickname, 'B', '"')
573 LEAVE
574 END
575 END
576 CALL RXQUEUE 'SET', oq
577 CALL RXQUEUE 'DELETE', nq
578 END
579 ELSE DO
580 CALL LINEIN ppd_file, 1, 0
581 DO WHILE LINES( ppd_file ) <> 0
582 line = STRIP( LINEIN( ppd_file ))
583 IF LEFT( line, 15 ) == '*ShortNickName:' THEN DO
584 PARSE VAR line . ':' _nick '0D'x .
585 nickname = STRIP( _nick )
586 nickname = STRIP( nickname, 'B', '"')
587 LEAVE
588 END
589 END
590 CALL STREAM ppd_file, 'C', 'CLOSE'
591 END
592
593RETURN nickname
594
595/*:VRX CleanPPD
596*/
597/* Clean out lines from Gutenprint and Foomatic PPD files that are known to
598 * cause problems when importing with PIN. (Partially based on work by Paul
599 * Smedley and Peter Brown).
600 */
601CleanPPD: PROCEDURE
602 PARSE ARG in_ppd, logfile
603 IF logfile <> '' THEN
604 logfile = STREAM( logfile, 'C', 'QUERY EXISTS')
605
606 out_ppd = VRParseFilePath( in_ppd, 'DPN') || '.TMP'
607 IF STREAM( out_ppd, 'C', 'QUERY EXISTS') \= '' THEN
608 CALL SysFileDelete out_ppd
609
610 IF logfile <> '' THEN
611 CALL CHAROUT logfile, 'Doing cleanup on' in_ppd '...'
612
613 skip_next = 0
614 DO WHILE LINES( in_ppd ) \= 0
615 line = LINEIN( in_ppd )
616 SELECT
617 WHEN skip_next == 1 THEN DO
618 line = STRIP( TRANSLATE( line ))
619 IF line == '*END' THEN skip_next = 0
620 END
621 WHEN LEFT( line, 11 ) == '*StpDefault' THEN NOP
622 WHEN LEFT( line, 7 ) == '*StpStp' THEN NOP
623 WHEN LEFT( line, 18 ) == '*StpResolutionMap:' THEN NOP
624 WHEN LEFT( line, 14 ) == '*OPOptionHints' THEN NOP
625 WHEN LEFT( line, 4 ) == '*da.' THEN NOP
626 WHEN LEFT( line, 4 ) == '*de.' THEN NOP
627 WHEN LEFT( line, 4 ) == '*es.' THEN NOP
628 WHEN LEFT( line, 4 ) == '*fi.' THEN NOP
629 WHEN LEFT( line, 4 ) == '*fr.' THEN NOP
630 WHEN LEFT( line, 4 ) == '*it.' THEN NOP
631 WHEN LEFT( line, 4 ) == '*ja.' THEN NOP
632 WHEN LEFT( line, 4 ) == '*ko.' THEN NOP
633 WHEN LEFT( line, 4 ) == '*nb.' THEN NOP
634 WHEN LEFT( line, 4 ) == '*nl.' THEN NOP
635 WHEN LEFT( line, 4 ) == '*pt.' THEN NOP
636 WHEN LEFT( line, 4 ) == '*sv.' THEN NOP
637 WHEN LEFT( line, 7 ) == '*zh_CN.' THEN NOP
638 WHEN LEFT( line, 7 ) == '*zh_TW.' THEN NOP
639 WHEN LEFT( line, 9 ) == '*Foomatic' THEN DO
640 line = STRIP( line )
641 IF RIGHT( line, 2 ) == '&&' THEN skip_next = 1
642 END
643 OTHERWISE DO
644 CALL LINEOUT out_ppd, line
645 skip_next = 0
646 END
647 END
648 END
649 CALL STREAM in_ppd, 'C', 'CLOSE'
650 CALL STREAM out_ppd, 'C', 'CLOSE'
651
652 ok = VRCopyFile( out_ppd, in_ppd )
653 IF logfile <> '' THEN DO
654 IF ok == 1 THEN
655 CALL LINEOUT logfile, 'OK'
656 ELSE DO
657 CALL LINEOUT logfile, 'Failed!'
658 CALL LINEOUT logfile, ' ->' VRError()
659 END
660 CALL LINEOUT logfile, ''
661 END
662 CALL SysFileDelete out_ppd
663
664RETURN
665
666/*:VRX MatchPrinterModel
667*/
668/* Find a set of printers supported by the OS/2 driver which mostly closely
669 * match the given name.
670 */
671MatchPrinterModel: PROCEDURE EXPOSE globals. models.
672 PARSE UPPER ARG driver_name, printer_name
673 printer_name = TRANSLATE( printer_name, '_', '.')
674 printer_drv = globals.!os2dir'\DLL\'driver_name'\'driver_name'.DRV'
675 models.0 = 0
676
677 IF SysGetEA( printer_drv, '.EXPAND', 'exist_ea') <> 0 THEN RETURN 0
678 PARSE VAR exist_ea 1 _eatype 3 .
679 IF C2X( _eatype ) <> 'FDFF' THEN RETURN 0
680
681 PARSE VAR exist_ea 3 _ealen 5 exist_models
682 total_len = C2D( REVERSE( _ealen ))
683
684 /* The variable exist_models now contains a null-separated list of printer
685 * models supported by the driver (including those from previously-imported
686 * PPD files). Next we check each one against our requested printer name.
687 */
688 start = 1
689 count = 0
690 best = 0
691 DO WHILE start < total_len
692 _strend = POS('0'x, exist_models, start )
693 IF _strend == 0 THEN LEAVE
694 _model = TRANSLATE( SUBSTR( exist_models, start, _strend - start ))
695 _model = TRANSLATE( _model, ' ', '-')
696 _comp = COMPARE( _model, printer_name )
697 IF WORD( _model, 1 ) == WORD( printer_name, 1 ) THEN DO
698 count = count + 1
699 IF _comp == 0 THEN DO
700 _comp = 9999
701 best = count
702 END
703 ELSE IF ( best == 0 ) & ( _comp > LENGTH( printer_name )) THEN
704 best = count
705/*
706 models.count = RIGHT( _comp, 4, '0') SUBSTR( exist_models, start, _strend - start )
707*/
708 models.count = SUBSTR( exist_models, start, _strend - start )
709 END
710 start = _strend + 1
711 END
712 models.0 = count
713
714/*
715 CALL SysStemSort 'models.', 'D', 'I',,, 1, 4
716 DO i = 1 TO count
717 models.i = SUBWORD( models.i, 2 )
718 END
719*/
720RETURN best
721
722
723/*:VRX CheckWritablePath
724*/
725CheckWritablePath: PROCEDURE EXPOSE globals.
726 ARG path
727
728 /* Make sure path exists & is a directory */
729 IF \VRIsDir( path ) THEN RETURN 1
730
731 /* Make sure the drive is accessible */
732 di = SysDriveInfo( VRParseFilePath( path, 'DP'))
733 IF di == '' THEN RETURN 2
734
735 /* Make sure the drive has a supported filesystem */
736 fs = SysFileSystemType( prdrv )
737 IF WORDPOS( fs, 'HPFS JFS FAT FAT32') == 0 THEN RETURN 3
738
739RETURN 0
740
741
742/*:VRX QueryAvailableDrivers
743*/
744/* Determine which of our supported PrinterPak drivers are currently available.
745 */
746QueryAvailableDrivers: PROCEDURE EXPOSE globals. drv_list.
747 drv_list.0 = 0
748
749 test_drivers = 'ECUPS ECUPS-HP PSPRINT'
750 DO i = 1 TO WORDS( test_drivers )
751 driver = WORD( test_drivers, i )
752 ok = GetDriverSource( driver )
753 IF ok == '' THEN
754 ok = VRGetIni('PM_DEVICE_DRIVERS', driver, 'USER')
755 IF ok <> '' THEN
756 CALL SysStemInsert 'drv_list.', drv_list.0+1, driver
757 END
758
759RETURN drv_list.0
760
761
762/*:VRX PinWrapper
763*/
764/* Wrapper for PIN, which performs the following tasks:
765 * - Create a temporary working directory & copy the PrinterPak files there.
766 * - Pre-process the PPD file to make it ready for import, and saves it in
767 * a driver-specific 'saved PPDs' directory for future use.
768 * - Uses PIN to import the PPD into our temporary working copy of the driver.
769 * - Copy the updated driver back to our installable copy.
770 * - If update_all is 1 then also do the following:
771 * - If the driver is actually installed, copy the updated driver back
772 * over the installed version as well.
773 * - If this is a 'shipped' driver (i.e. one listed in PRDRV.LST) then
774 * add the newly-defined printer to PRDESC.LST.
775 */
776PinWrapper: PROCEDURE EXPOSE globals. driver_path driver_repo
777 ARG update_all, driver, ppdfile
778
779 CALL LINEOUT globals.!log1, 'Driver source: ' driver_path
780
781 workdir = SysTempFileName( globals.!tmpdir'\PPD_????')
782 ok = VRMkDir( workdir )
783 IF ok == 1 THEN ok = VrMkDir( workdir'\OUT')
784 IF ok <> 1 THEN
785 RETURN 5 /** RC=5 failed to create directory */
786
787 CALL LINEOUT globals.!log1, 'Temporary directory: ' workdir
788
789 SELECT
790 WHEN driver == 'ECUPS' THEN ppddir = globals.!repository'\PPD_E'
791 WHEN driver == 'ECUPS-HP' THEN ppddir = globals.!repository'\PPD_EHP'
792 WHEN driver == 'PSPRINT' THEN ppddir = globals.!repository'\PPD_PS'
793 WHEN driver == 'PSPRINT2' THEN ppddir = globals.!repository'\PPD_PS2'
794 WHEN driver == 'PSCRIPT2' THEN ppddir = globals.!repository'\PPD2'
795 WHEN driver == 'GUTENPRT' THEN ppddir = globals.!repository'\PPD_GP'
796 OTHERWISE ppddir = globals.!repository'\PPD'
797 END
798
799 /* Make sure ppddir (for keeping PPD files) exists */
800 CALL SysFileTree ppddir, 'dirs.', 'DO'
801 IF dirs.0 == 0 THEN DO
802 IF ppdfile == '' THEN RETURN 0 /* No PPDs - nothing to do */
803 ok = VRMkDir( ppddir )
804 IF ok <> 1 THEN
805 RETURN 5 /** RC=5 failed to create directory */
806 END
807
808 CALL LINEOUT globals.!log1, 'Directory for PPD files:' ppddir
809
810 /***
811 *** Now do the actual work.
812 ***/
813
814 /* Copy the needed driver files to our working directories.
815 */
816 drvr_dir = VRParseFileName( driver_path, 'DP')
817 drv_out = workdir'\OUT\'driver'.DRV'
818 pin_exe = workdir'\PIN.EXE'
819 ppd_exe = workdir'\PPDENC.EXE'
820 ok = VRCopyFile( driver_path, drv_out )
821 IF ok == 1 THEN ok = VRCopyFile( drvr_dir'\PIN.EXE', pin_exe )
822 IF ok == 1 THEN ok = VRCopyFile( drvr_dir'\PPDENC.EXE', ppd_exe )
823 IF ok == 0 THEN DO
824 RETURN 4 /*** RC=4 Failed to copy driver files ***/
825 END
826
827 /* Set up the output redirection.
828 */
829 nq = RXQUEUE('CREATE')
830 oq = RXQUEUE('SET', nq )
831
832 /* If we are importing a new PPD file, prep it first.
833 * (If ppdfile is undefined, it means we are reimporting a directory of
834 * previously-imported PPDs, and we can assume they are already prepped.)
835 */
836 IF ppdfile <> '' THEN DO
837
838 /* If the PPD file is compressed, uncompress it.
839 */
840 IF VRParseFilePath( ppdfile, 'E') == 'GZ' THEN DO
841 decppd = workdir'\' || VRParseFilePath( ppdfile, 'N')
842 CALL LINEOUT globals.!log1, 'Decompressing' ppdfile 'to' decppd
843 ADDRESS CMD '@'globals.!programs.!gzip '-c -d' ppdfile '| RXQUEUE' nq
844 DO QUEUED()
845 PARSE PULL line
846 CALL LINEOUT decppd, line
847 END
848 CALL LINEOUT decppd
849 ppdfile = decppd
850 END
851
852 IF VRFileExists( ppdfile ) == 0 THEN DO
853 CALL LINEOUT globals.!log1, 'PPD file' ppdfile 'could not be found.'
854 RETURN 6 /** RC=6 PPD import failed **/
855 END
856
857 ppd_use = ppddir'\' || VRParseFileName( ppdfile, 'NE')
858
859 /* Now we have to clean up and validate the PPD file so PIN can use it.
860 * First, PPDENC converts the codepage if necessary, and copies the results
861 * to our working directory.
862 */
863 CALL LINEOUT globals.!log1, 'Converting PPD with:' ppd_exe ppdfile ppd_use
864 ADDRESS CMD '@'ppd_exe ppdfile ppd_use '2>NUL | RXQUEUE' nq
865 DO QUEUED()
866 PULL output
867 CALL LINEOUT globals.!log2, output
868 END
869 CALL LINEOUT globals.!log2, ''
870 CALL LINEOUT globals.!log2
871
872 IF VRFileExists( ppd_use ) == 0 THEN DO
873 CALL LINEOUT globals.!log1, 'Hmm,' ppd_use 'was not created. Copying manually.'
874 CALL VRCopyFile ppdfile, ppd_use
875 END
876
877 /* Next we strip out some problematic PPD statements which are often
878 * encountered in (for example) CUPS-based PPD files.
879 */
880 CALL CleanPPD ppd_use, globals.!log1
881
882 END
883
884 /* Preparation complete. Now do the import.
885 */
886 count = 0
887 ADDRESS CMD '@'pin_exe 'ppd' ppddir drv_out '2>NUL | RXQUEUE' nq
888 DO QUEUED()
889 PARSE PULL output
890 CALL LINEOUT globals.!log2, output
891 PARSE VAR output . 'OK (' nickname
892 IF nickname <> '' THEN DO
893 count = count + 1
894 newprinters.count = STRIP( nickname, 'T', ')')
895 END
896 END
897 newprinters.0 = count
898 CALL LINEOUT globals.!log2, ''
899 CALL LINEOUT globals.!log2
900
901 /* End the output redirection.
902 */
903 CALL RXQUEUE 'SET', oq
904 CALL RXQUEUE 'DELETE', nq
905
906 IF newprinters.0 == 0 THEN DO
907 RETURN 6 /** RC=6 PPD import failed **/
908 END
909
910 /***
911 *** Post-import processing.
912 ***/
913
914 IF ( driver_repo == 1 ) & ( update_all <> 0 ) THEN DO
915 /* If we're working out of the repository, we need to update the
916 * driver table in PRDESC.LST to add the new driver(s).
917 */
918
919 CALL LINEOUT globals.!log1, 'Updating' globals.!prdesc 'with new entries from' drv_out
920
921/* -- This causes a SYS3175 in the .DRV for some reason...
922 ok = UpdatePrDesc( driver'.DRV', drv_out )
923 IF ok <> 0 THEN
924 CALL LINEOUT globals.!log1, 'Failed to update' globals.!prdesc '(are EAs on' drv_out ' valid?)'
925*/
926
927 count = 0
928
929 /* First, copy all lines that don't refer to the driver just updated */
930 CALL LINEIN globals.!prdesc, 1, 0
931 DO WHILE LINES( globals.!prdesc )
932 _next = LINEIN( globals.!prdesc )
933 PARSE UPPER VAR _next . ':' _rest
934 _tail = SUBSTR( _rest, LASTPOS('(', _rest ))
935 PARSE VAR _tail '('_prdrv')' .
936 IF _prdrv == driver'.DRV' THEN ITERATE
937 count = count + 1
938 defs.count = _next
939 END
940 CALL STREAM globals.!prdesc, 'C', 'CLOSE'
941
942 /* Next, create a new list for the updated driver and merge that in */
943 newlist = workdir'\'driver'.LST'
944 CALL CreateDriverList drv_out, newlist
945 DO WHILE LINES( newlist )
946 _line = LINEIN( newlist )
947 count = count + 1
948 defs.count = _line
949 END
950 CALL STREAM newlist, 'C', 'CLOSE'
951 defs.0 = count
952
953 /* Now sort the list and recreate PRDESC.LST */
954 CALL SysStemSort 'defs.',, 'I'
955 prdesc_tmp = workdir'\PRDESC.LST'
956 IF STREAM( prdesc_tmp, 'C', 'QUERY EXISTS') <> '' THEN
957 CALL VRDeleteFile prdesc_tmp
958 DO i = 1 TO defs.0
959 CALL LINEOUT prdesc_tmp, defs.i
960 END
961 CALL LINEOUT prdesc_tmp
962 ok = VRCopyFile( prdesc_tmp, globals.!prdesc )
963 IF ok == 0 THEN DO
964 RETURN 7 /** RC=7 Error updating PRDESC.LST **/
965 END
966 CALL VRDeleteFile prdesc_tmp
967
968 END
969
970 /* Finally, copy the updated driver files.
971 */
972 target = VRParseFilePath( driver_path, 'DP')
973 CALL LINEOUT globals.!log1, 'Copying files from' workdir'\OUT to' target
974 CALL PRReplaceModule target'\'driver'.DRV', '', ''
975 ok = VRCopyFile( workdir'\OUT\'driver'.DRV', target'\'driver'.DRV')
976 IF ok == 1 THEN
977 ok = VRCopyFile( workdir'\OUT\AUXPRINT.PAK', target'\AUXPRINT.PAK')
978
979 IF ( ok == 1 ) & ( update_all <> 0 ) THEN DO
980 /* Copy the updated files to \OS2\DLL\<driver>, replacing any
981 * existing copies. (This prevents problems if the OS/2 driver
982 * installation fails to copy them, which can happen under some
983 * circumstances.)
984 */
985 IF VRFileExists( globals.!os2dir'\DLL\'driver'\'driver'.DRV') THEN DO
986 CALL VRCopyFile workdir'\OUT\AUXPRINT.PAK',,
987 globals.!os2dir'\DLL\'driver'\AUXPRINT.PAK'
988 CALL PRReplaceModule globals.!os2dir'\DLL\'driver'\'driver'.DRV', '', ''
989 CALL VRCopyFile workdir'\OUT\'driver'.DRV', globals.!os2dir'\DLL\'driver'\'driver'.DRV'
990 END
991 END
992 IF ok == 0 THEN DO
993 CALL LINEOUT globals.!log1, VRError()
994 RETURN 4 /*** RC=4 Failed to copy driver files ***/
995 END
996
997 CALL LINEOUT globals.!log1, newprinters.0 'printers imported successfully.'
998 DO i = 1 TO newprinters.0
999 CALL LINEOUT globals.!log1, ' ->' newprinters.i
1000 END
1001 CALL LINEOUT globals.!log1, ''
1002 CALL LINEOUT globals.!log1
1003
1004 /* Clean up our work directories.
1005 */
1006 CALL VRDeleteFile workdir'\OUT\*'
1007 CALL VRDeleteFile workdir'\*'
1008 CALL VRRmDir( workdir'\OUT')
1009 CALL VRRmDir( workdir )
1010
1011RETURN 0
1012
1013
1014/*:VRX UpdatePrDesc
1015*/
1016UpdatePrDesc: PROCEDURE EXPOSE globals.
1017 ARG driver, fqn
1018
1019 IF globals.!prdesc == '' THEN RETURN 1
1020
1021 ok = RPUEnumModels( fqn, 'newdevs.')
1022 IF ok == 0 THEN RETURN 2
1023
1024 _count = 0
1025 CALL LINEIN globals.!prdesc, 1, 0
1026 DO WHILE LINES( globals.!prdesc )
1027 _next = LINEIN( globals.!prdesc )
1028 PARSE UPPER VAR _next WITH . ':' . '('_prdrv')' .
1029 IF _prdrv == driver THEN ITERATE
1030 _count = _count + 1
1031 prdefs.count = _next
1032 END
1033 CALL STREAM globals.!prdesc, 'C', 'CLOSE'
1034
1035 DO i = 1 TO newdevs.0
1036 _count = _count + 1
1037 prdefs._count = newdevs.i':' newdevs.i '('driver')'
1038 END
1039 prdefs.0 = count
1040
1041 CALL VRSortStem 'prdefs.'
1042
1043 _prdir = VRParseFileName( globals.!prdesc, 'DP')
1044 CALL VRCopyFile globals.!prdesc, _prdir'\PRDESC.BAK'
1045 CALL VRDeleteFile globals.!prdesc
1046 DO i = 1 TO prdefs.0
1047 CALL LINEOUT globals.!prdesc, prdefs.i
1048 END
1049 CALL LINEOUT globals.!prdesc
1050
1051RETURN 0
1052
1053
1054/*:VRX NLSGetMessage
1055*/
1056/*
1057 * Gets the message text associated with the given message number from the
1058 * current language file.
1059 */
1060NLSGetMessage: PROCEDURE EXPOSE globals.
1061 PARSE ARG msgnum, .
1062 args = ARG()
1063
1064 msgfile = globals.!messages
1065 IF msgnum == '' THEN RETURN ''
1066
1067 sub_parms = ''
1068 DO i = 2 TO args
1069 sub_parms = sub_parms', "'ARG( i )'"'
1070 END
1071
1072 INTERPRET 'msgfromfile = SysGetMessage( msgnum, msgfile' sub_parms ')'
1073
1074 PARSE VAR msgfromfile message '0D'x .
1075 IF SUBSTR( message, 1, 4 ) == 'SYS0' THEN message = ''
1076
1077RETURN message
1078
1079
1080/*:VRX NLSSetText
1081*/
1082/*
1083 * Sets the specified property of the specified control to the specified
1084 * message text.
1085 */
1086NLSSetText: PROCEDURE EXPOSE globals.
1087 PARSE ARG control, property, message, substitution
1088 args = ARG()
1089
1090 success = 1
1091 IF args < 4 THEN
1092 text = NLSGetMessage( message )
1093 ELSE DO
1094 sub_parms = ''
1095 DO i = 4 TO args
1096 sub_parms = sub_parms '"'|| ARG( i ) ||'",'
1097 END
1098 sub_parms = STRIP( sub_parms, 'T', ',')
1099 INTERPRET 'text = NLSGetMessage( message, 'sub_parms')'
1100 END
1101
1102 IF text == '' THEN success = 0
1103 ELSE CALL VRSet control, property, text
1104
1105RETURN success
1106
1107/*:VRX StringTokenize
1108*/
1109StringTokenize:
1110 PARSE ARG string, separator, __stem
1111 CALL __StringTokenize string, separator, __stem
1112 DROP __stem
1113RETURN
1114
1115/*:VRX __StringTokenize
1116*/
1117__StringTokenize: PROCEDURE EXPOSE (__stem)
1118 PARSE ARG string, separator, tokens
1119
1120 /* Note: this differs slightly from my usual implementation in that
1121 * each token is STRIPped of leading and trailing spaces.
1122 */
1123
1124 IF ( string = '') THEN RETURN string
1125 IF ( separator = '') THEN separator = ' '
1126
1127 i = 0
1128 CALL VALUE tokens || '0', i
1129 DO WHILE LENGTH( string ) > 0
1130 x = 1
1131 y = POS( separator, string, x )
1132 IF y > 0 THEN DO
1133 current = SUBSTR( string, 1, y-1 )
1134 x = y + 1
1135 i = i + 1
1136 CALL VALUE tokens || 'i', STRIP( current )
1137 END
1138 ELSE DO
1139 current = STRIP( string, 'B', separator )
1140 i = i + 1
1141 CALL VALUE tokens || 'i', STRIP( current )
1142 x = LENGTH( string ) + 1
1143 END
1144 string = SUBSTR( string, x )
1145 END
1146 CALL VALUE tokens || '0', i
1147
1148RETURN
1149
Note: See TracBrowser for help on using the repository browser.