source: trunk/gui/shared/PrintUtl.VRS@ 11

Last change on this file since 11 was 11, checked in by Alex Taylor, 14 years ago

Add support for drivers other than ECUPS.DRV.

File size: 18.5 KB
Line 
1/*:VRX GetDriverSource
2*/
3/* Figure out where to look for the PrinterPak driver files used as the install
4 * source. Preference is given to the local repository (PDR_DIR); if it's not
5 * there, we look in a couple of other places where it might have ended up.
6 * Note that we don't look for the actual installed driver files under \OS2\DLL;
7 * if the application wants to fall back to those in some way, then it will have
8 * to take care of that logic itself.
9 *
10 * Various global values are assumed to be set already:
11 * - globals.!prdrv: filespec of \OS2\INSTALL\PRDRV.LST
12 * - globals.!repository: value indicated by PM_INSTALL->PDR_DIR in OS2.INI
13 *
14 * Returns the path, or '' if not found. Also, 'pmdx' will be 0-9 if the
15 * driver is in the repository (indicating the repository subdirectory), or
16 * '' if the driver is not in the repository.
17 */
18GetDriverSource: PROCEDURE EXPOSE globals. pmdx
19 ARG driver
20 IF driver == '' THEN RETURN ''
21
22 drv_file = ''
23 IF globals.!repository <> '' THEN DO
24
25 /* See if the driver is defined in the local repository. (This is the
26 * directory where installable printer drivers are kept. OS/2 gets them
27 * from here when you select 'Printer driver included with OS/2'.)
28 */
29 pmdx = GetDriverPMDD( driver, globals.!prdrv )
30 IF pmdx == '' THEN DO
31 /* Hmm, the driver isn't listed in PRDRV.LST. Let's check to see if
32 * it's in the default repository location anyway.
33 */
34 IF WORDPOS( driver, 'ECUPS ECUPS-HP PSPRINT PSPRINT2') > 0 THEN
35 pmdx = '9'
36 ELSE
37 pmdx = '0'
38 drv_file = STREAM( globals.!repository'\PMDD_'pmdx'\'driver'.DRV', 'C', 'QUERY EXISTS')
39 IF drv_file <> '' THEN DO
40 /* We found the driver in the repository, even though it isn't
41 * defined as such. So let's add the proper definition to
42 * PRDRV.LST now.
43 */
44 CALL LINEOUT globals.!prdrv, LEFT( driver'.DRV', 14 ) pmdx ||,
45 ' (added automatically)'
46 CALL LINEOUT globals.!prdrv
47 END
48 ELSE
49 pmdx = ''
50 END
51 ELSE DO
52 /* The driver is listed; now make sure it's actually there.
53 */
54 drv_file = STREAM( globals.!repository'\PMDD_'pmdx'\'driver'.DRV', 'C', 'QUERY EXISTS')
55 END
56 END
57
58 IF drv_file == '' THEN DO
59 CALL LINEOUT globals.!log1, 'Driver' driver 'is not in the local repository.'
60 /* If the driver really isn't in the repository, there are a couple of
61 * other places that various install utilities might have put it...
62 */
63 PARSE VALUE VRGetIni('PM_INSTALL', driver'_DIR', 'USER') WITH drvr_dir '00'x .
64 IF drvr_dir == '' THEN
65 PARSE VALUE VRGetIni('InstPDR', 'PATH_TO_'driver, 'USER') WITH drvr_dir '00'x .
66 IF drvr_dir <> '' THEN DO
67 drv_file = drvr_dir'\'driver'.DRV'
68 CALL LINEOUT globals.!log1, 'Found driver in' drvr_dir'.'
69 END
70 END
71
72RETURN drv_file
73
74
75/*:VRX GetDriverPMDD
76*/
77/* Check to see which repository directory the specified driver resides in.
78 * Returns the number suffix of the PMDD_* subdirectory name, or '' if either
79 * the driver or the index file could not be located.
80 */
81GetDriverPMDD: PROCEDURE
82 PARSE ARG driver, prdrv_lst
83
84 IF prdrv_lst <> '' THEN DO
85 CALL LINEIN prdrv_lst, 1, 0
86 DO WHILE LINES( prdrv_lst ) > 0
87 PARSE VALUE LINEIN( prdrv_lst ) WITH (driver)'.DRV' pmdx .
88 IF pmdx <> '' THEN LEAVE
89 END
90 CALL STREAM prdrv_lst, 'C', 'CLOSE'
91 END
92 ELSE pmdx = ''
93
94RETURN pmdx
95
96
97/*:VRX VerifyDriverEAs
98*/
99/* Make sure the driver has its extended attributes. If not, look for an
100 * accompanying .EA or .EA_ file, and join it to the driver.
101 */
102VerifyDriverEAs: PROCEDURE EXPOSE globals.
103 PARSE ARG driver
104 eas.0 = 0
105 CALL SysQueryEAList driver, 'eas.'
106 IF eas.0 == 0 THEN DO
107 ea_file = SUBSTR( driver, 1, LASTPOS('.', driver )) || 'EA'
108 IF STREAM( ea_file, 'C', 'QUERY EXISTS') == '' THEN
109 ea_file = ea_file || '_'
110 IF STREAM( ea_file, 'C', 'QUERY EXISTS') == '' THEN
111 RETURN 0
112
113 ADDRESS CMD '@UNLOCK' driver '2>NUL 1>NUL'
114 ADDRESS CMD '@EAUTIL' driver ea_file '/j /p 2>NUL 1>NUL'
115 END
116RETURN 1
117
118
119/*:VRX CopyDriverToSource
120*/
121/* Copy driver files to the source (repository) directory used for installation.
122 */
123CopyDriverToSource: PROCEDURE EXPOSE globals.
124 PARSE ARG driver, newdrvdir
125
126 drv_dir = VRParseFilePath( driver, 'DP')
127 IF drv_dir == '' THEN RETURN 0
128
129 IF VerifyDriverEAs( driver ) == 0 THEN RETURN 0
130
131 CALL LINEOUT globals.!log1, 'Copying driver files from' drv_dir 'to' newdrvdir'...'
132
133 /* Read the list of required driver files from the EAs, and copy them
134 * all to the target directory.
135 */
136 IF SysGetEA( driver, 'REQUIREDDRIVERFILES', 'reqfiles') == 0 THEN DO
137 PARSE VAR reqfiles 5 filelist
138 filelist = TRANSLATE( filelist, ' ', ',')
139 DO i = 1 TO WORDS( filelist )
140 copyfile = drv_dir'\' || WORD( filelist, i )
141 ok = VRCopyFile( copyfile, newdrvdir'\' || WORD( filelist, i ))
142 CALL LINEOUT globals.!log1, ' -' copyfile '(REQUIRED):' ok
143 END
144 DROP copyfile
145 DROP filelist
146 END
147 ELSE RETURN 0
148
149 /* If there are optional files defined as well, try to copy those also.
150 */
151 IF SysGetEA( driver, 'OPTIONALDRIVERFILES', 'reqfiles') == 0 THEN DO
152 PARSE VAR reqfiles 5 filelist
153 filelist = TRANSLATE( filelist, ' ', ',')
154 DO i = 1 TO WORDS( filelist )
155 copyfile = drv_dir'\' || WORD( filelist, i )
156 IF STREAM( copyfile, 'C', 'QUERY EXISTS') == '' THEN ITERATE
157 ok = VRCopyFile( copyfile, newdrvdir'\' || WORD( filelist, i ))
158 CALL LINEOUT globals.!log1, ' -' copyfile '(OPTIONAL):' ok
159 END
160 DROP copyfile
161 DROP filelist
162 END
163
164RETURN 1
165
166
167/*:VRX PrinterExistsInDRV
168*/
169/* Determine if the specified PrinterPak driver already contains support
170 * for the specified printer model.
171 */
172PrinterExistsInDRV: PROCEDURE EXPOSE globals.
173 PARSE UPPER ARG driver_name, printer_name
174 printer_name = TRANSLATE( printer_name, '_', '.')
175
176 printer_drv = globals.!bootdrv'\OS2\DLL\'driver_name'\'driver_name'.DRV'
177 /* ?? TODO: install driver_name if not found (prompt first) ?? */
178
179 IF SysGetEA( printer_drv, '.EXPAND', 'exist_ea') <> 0 THEN RETURN 0
180 PARSE VAR exist_ea 1 _eatype 3 .
181 IF C2X( _eatype ) <> 'FDFF' THEN RETURN 0
182
183 PARSE VAR exist_ea 3 _ealen 5 exist_models
184 total_len = C2D( REVERSE( _ealen ))
185
186 /* The variable exist_models now contains a null-separated list of printer
187 * models supported by the driver (including those from previously-imported
188 * PPD files). Next we check each one against our requested printer name.
189 */
190 start = 1
191 found = 0
192 DO WHILE ( found == 0 ) & ( start < total_len )
193 _strend = POS('0'x, exist_models, start )
194 IF _strend == 0 THEN LEAVE
195 _model = TRANSLATE( SUBSTR( exist_models, start, _strend - start ))
196 IF _model == printer_name THEN
197 found = 1
198 ELSE
199 start = _strend + 1
200 END
201
202RETURN found
203
204
205/*:VRX CreateDriverList
206*/
207/* Generate a driver listfile from the .EXPAND EA
208 */
209CreateDriverList: PROCEDURE EXPOSE globals.
210 ARG driver, listfile
211
212 IF STREAM( listfile, 'C', 'QUERY EXISTS') <> '' THEN
213 CALL SysFileDelete listfile
214
215 drv_name = FILESPEC('NAME', driver )
216 IF SysGetEA( driver, '.EXPAND', 'eaval') == 0 THEN DO
217 PARSE VAR eaval 3 ealen 5 models
218 offs = 1
219 datalen = C2D( REVERSE( ealen ))
220 DO WHILE offs <= datalen
221 start = SUBSTR( models, offs )
222 inc = POS('00'x, start )
223 IF inc > 1 THEN DO
224 current_name = STRIP( SUBSTR( start, 1, inc-1 ))
225 CALL LINEOUT listfile, current_name':' current_name '('drv_name')'
226 END
227 offs = offs + inc
228 END
229 CALL LINEOUT listfile
230 END
231
232RETURN 1
233
234
235/*:VRX AddPort_CUPS
236*/
237/* Adds a new CUPS port. Returns 0 on full success, 1 if the port was created
238 * but could not be configured, and an OS/2 or PM error code otherwise.
239 */
240AddPort_CUPS: PROCEDURE EXPOSE globals.
241 PARSE ARG portname, hostname, queuename
242 CALL LINEOUT globals.!log1, 'Creating new port' portname
243 ADDRESS CMD '@cupsport' portname hostname queuename '>>' globals.!log2
244 IF rc == 1 THEN DO
245 CALL VRSetIni 'PM_'portname, 'INITIALIZATION', hostname'#'queuename||'00'x, 'SYSTEM', 'NoClose'
246 CALL VRSetIni 'PM_'portname, 'DESCRIPTION', hostname':'queuename||'00'x, 'SYSTEM'
247 END
248RETURN rc
249
250
251/*:VRX DeletePort
252*/
253/* Deletes a printer port (any type).
254 */
255DeletePort: PROCEDURE EXPOSE globals.
256 PARSE ARG portname
257 CALL SysIni 'SYSTEM', 'PM_'portname, 'DELETE:'
258 CALL SysIni 'SYSTEM', 'PM_SPOOLER_PORT', portname, 'DELETE:'
259RETURN 1
260
261
262/*:VRX GetNextPortName
263*/
264/* Get the next unique (non-existing) port name for the specified port driver.
265 */
266GetNextPortName: PROCEDURE
267 ARG portdrv
268
269 maxports = 64 /* should be smarter about this if possible */
270 exists = 1
271 x = 0
272 DO WHILE ( x < maxports ) & ( exists == 1 )
273 x = x + 1
274 portname = portdrv || x
275 nextport = SysIni('SYSTEM', 'PM_SPOOLER_PORT', portname )
276 IF LEFT( nextport, 6 ) == 'ERROR:' THEN exists = 0
277 END
278 IF exists == 1 THEN
279 portname = ''
280
281RETURN portname
282
283
284/*:VRX GetQueueName
285*/
286/* Generate a unique queue name from the specified printer name.
287 */
288GetQueueName: PROCEDURE
289 ARG queuename
290
291 DO UNTIL badchar = 0
292 badchar = VERIFY( queuename, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ-_0123456789 ')
293 IF badchar > 0 THEN
294 queuename = OVERLAY(' ', queuename, badchar, 1 )
295 END
296 queuename = LEFT( SPACE( queuename, 0 ), 8 )
297
298 tail = 0
299 PARSE VALUE VRGetIni('PM_SPOOLER', 'DIR', 'SYSTEM') WITH spldir ';' .
300 DO WHILE VRFileExists( spldir'\'queuename ) == 1
301 tail = tail + 1
302 queuename = STRIP( LEFT( queuename, 8 - LENGTH( tail ))) || tail
303 END
304
305RETURN queuename
306
307
308/*:VRX RSPCreatePort
309*/
310/* Create/update a RINSTPRN response file to create the specified port.
311 */
312RSPCreatePort: PROCEDURE
313 PARSE ARG rsp, portdriver, portname, hostname, printername
314
315 CALL LINEOUT rsp, '* Creates a new printer port.'
316 CALL LINEOUT rsp, '*'
317 CALL LINEOUT rsp, 'ADDPORT'
318 CALL LINEOUT rsp, ' NAME =' portname
319 CALL LINEOUT rsp, ' PORTDRIVER =' portdriver
320 CALL LINEOUT rsp, ' DESCRIPTION =' hostname':'printername
321 CALL LINEOUT rsp, ' INITIALIZATION =' hostname'#'printername
322 CALL LINEOUT rsp, ' TERMINATION = ;'
323 CALL LINEOUT rsp, ' TIMEOUT = 45;'
324 CALL LINEOUT rsp, 'ENDPORT'
325 CALL LINEOUT rsp, ''
326 CALL LINEOUT rsp
327RETURN 1
328
329
330/*:VRX RSPCreatePrinter
331*/
332/* Create a RINSTPRN response file to create the specified printer.
333 */
334RSPCreatePrinter: PROCEDURE
335 PARSE ARG rsp, driver, model, portname, queuename, printername
336
337 IF STREAM( rsp, 'C', 'QUERY EXISTS') <> '' THEN
338 CALL SysFileDelete rsp
339
340/* temporary for testing */
341 PARSE UPPER VALUE VALUE('LANG',,'OS2ENVIRONMENT') WITH 1 . 4 _ctry 6 .
342 IF _ctry == 'CA' | _ctry == 'US' THEN
343 page = 'Letter'
344 ELSE
345 page = 'A4'
346 o9n = 'PORTRAIT'
347/* */
348
349 CALL LINEOUT rsp, '* Installs the' driver 'PrinterPak driver.'
350 CALL LINEOUT rsp, '*'
351 CALL LINEOUT rsp, 'ADDPRINTDRIVER'
352 CALL LINEOUT rsp, ' NAME =' driver
353 CALL LINEOUT rsp, 'ENDPRINTDRIVER'
354 CALL LINEOUT rsp, ''
355 CALL LINEOUT rsp, '* Installs support for the' model 'device.'
356 CALL LINEOUT rsp, '*'
357 CALL LINEOUT rsp, 'ADDPRINTDEVICE'
358 CALL LINEOUT rsp, ' NAME =' model
359 CALL LINEOUT rsp, ' DRIVER =' driver
360 CALL LINEOUT rsp, 'ENDPRINTDEVICE'
361 CALL LINEOUT rsp, ''
362 CALL LINEOUT rsp, '* Creates both a printer queue and a desktop object for this printer.'
363 CALL LINEOUT rsp, '*'
364 CALL LINEOUT rsp, 'ADDQUEUE'
365 CALL LINEOUT rsp, ' NAME =' queuename
366 CALL LINEOUT rsp, ' COMMENT =' printername
367 CALL LINEOUT rsp, ' DRIVERNAME =' driver'.'model
368 CALL LINEOUT rsp, ' PORT =' portname
369 CALL LINEOUT rsp, ' DEFINEQUEUEPROPS'
370 CALL LINEOUT rsp, ' FORMNAME =' page
371 CALL LINEOUT rsp, ' ORIENTATION =' o9n
372 CALL LINEOUT rsp, ' ENDQUEUEPROPS'
373 CALL LINEOUT rsp, 'ENDQUEUE'
374 CALL LINEOUT rsp
375RETURN 1
376
377
378/*:VRX GetNameFromPPD
379*/
380GetNameFromPPD: PROCEDURE
381 ARG ppd_file
382
383 IF STREAM( ppd_file, 'C', 'QUERY EXISTS') == '' THEN RETURN ''
384 nickname = ''
385 IF VRParseFilePath( ppd_file, 'E') == 'GZ' THEN DO
386 nq = RXQUEUE('CREATE')
387 oq = RXQUEUE('SET', nq )
388 ADDRESS CMD '@gzip -c -d' ppd_file '| RXQUEUE' nq
389 DO QUEUED()
390 PARSE PULL line
391 line = STRIP( line )
392 IF LEFT( line, 15 ) == '*ShortNickName:' THEN DO
393 PARSE VAR line . ':' _nick '0D'x .
394 nickname = STRIP( _nick )
395 nickname = STRIP( nickname, 'B', '"')
396 LEAVE
397 END
398 END
399 CALL RXQUEUE 'SET', oq
400 CALL RXQUEUE 'DELETE', nq
401 END
402 ELSE DO
403 CALL LINEIN ppd_file, 1, 0
404 DO WHILE LINES( ppd_file ) <> 0
405 line = STRIP( LINEIN( ppd_file ))
406 IF LEFT( line, 15 ) == '*ShortNickName:' THEN DO
407 PARSE VAR line . ':' _nick '0D'x .
408 nickname = STRIP( _nick )
409 nickname = STRIP( nickname, 'B', '"')
410 LEAVE
411 END
412 END
413 CALL STREAM ppd_file, 'C', 'CLOSE'
414 END
415
416RETURN nickname
417
418/*:VRX CleanPPD
419*/
420/* Clean out lines from Gutenprint and Foomatic PPD files that are known to
421 * cause problems when importing with PIN. (Partially based on work by Paul
422 * Smedley and Peter Brown).
423 */
424CleanPPD: PROCEDURE
425 PARSE ARG in_ppd, logfile
426 IF logfile <> '' THEN
427 logfile = STREAM( logfile, 'C', 'QUERY EXISTS')
428
429 out_ppd = VRParseFilePath( in_ppd, 'DPN') || '.TMP'
430 IF STREAM( out_ppd, 'C', 'QUERY EXISTS') \= '' THEN
431 CALL SysFileDelete out_ppd
432
433 IF logfile <> '' THEN
434 CALL CHAROUT logfile, 'Doing cleanup on' in_ppd '...'
435
436 skip_next = 0
437 DO WHILE LINES( in_ppd ) \= 0
438 line = LINEIN( in_ppd )
439 SELECT
440 WHEN skip_next == 1 THEN DO
441 line = STRIP( TRANSLATE( line ))
442 IF line == '*END' THEN skip_next = 0
443 END
444 WHEN LEFT( line, 11 ) == '*StpDefault' THEN NOP
445 WHEN LEFT( line, 7 ) == '*StpStp' THEN NOP
446 WHEN LEFT( line, 18 ) == '*StpResolutionMap:' THEN NOP
447 WHEN LEFT( line, 14 ) == '*OPOptionHints' THEN NOP
448 WHEN LEFT( line, 9 ) == '*Foomatic' THEN DO
449 line = STRIP( line )
450 IF RIGHT( line, 2 ) == '&&' THEN skip_next = 1
451 END
452 OTHERWISE DO
453 CALL LINEOUT out_ppd, line
454 skip_next = 0
455 END
456 END
457 END
458 CALL STREAM in_ppd, 'C', 'CLOSE'
459 CALL STREAM out_ppd, 'C', 'CLOSE'
460
461 ok = VRCopyFile( out_ppd, in_ppd )
462 IF logfile <> '' THEN DO
463 IF ok == 1 THEN
464 CALL LINEOUT logfile, 'OK'
465 ELSE DO
466 CALL LINEOUT logfile, 'Failed!'
467 CALL LINEOUT logfile, ' ->' VRError()
468 END
469 CALL LINEOUT logfile, ''
470 END
471 CALL SysFileDelete out_ppd
472
473RETURN
474
475/*:VRX MatchPrinterModel
476*/
477/* Find a set of printers supported by the OS/2 driver which mostly closely
478 * match the given name.
479 */
480MatchPrinterModel: PROCEDURE EXPOSE globals. models.
481 PARSE UPPER ARG driver_name, printer_name
482 printer_name = TRANSLATE( printer_name, '_', '.')
483 printer_drv = globals.!bootdrv'\OS2\DLL\'driver_name'\'driver_name'.DRV'
484 models.0 = 0
485
486 IF SysGetEA( printer_drv, '.EXPAND', 'exist_ea') <> 0 THEN RETURN 0
487 PARSE VAR exist_ea 1 _eatype 3 .
488 IF C2X( _eatype ) <> 'FDFF' THEN RETURN 0
489
490 PARSE VAR exist_ea 3 _ealen 5 exist_models
491 total_len = C2D( REVERSE( _ealen ))
492
493 /* The variable exist_models now contains a null-separated list of printer
494 * models supported by the driver (including those from previously-imported
495 * PPD files). Next we check each one against our requested printer name.
496 */
497 start = 1
498 count = 0
499 best = 0
500 DO WHILE start < total_len
501 _strend = POS('0'x, exist_models, start )
502 IF _strend == 0 THEN LEAVE
503 _model = TRANSLATE( SUBSTR( exist_models, start, _strend - start ))
504 _model = TRANSLATE( _model, ' ', '-')
505 _comp = COMPARE( _model, printer_name )
506 IF WORD( _model, 1 ) == WORD( printer_name, 1 ) THEN DO
507 count = count + 1
508 IF _comp == 0 THEN DO
509 _comp = 9999
510 best = count
511 END
512 ELSE IF ( best == 0 ) & ( _comp > LENGTH( printer_name )) THEN
513 best = count
514/*
515 models.count = RIGHT( _comp, 4, '0') SUBSTR( exist_models, start, _strend - start )
516*/
517 models.count = SUBSTR( exist_models, start, _strend - start )
518 END
519 start = _strend + 1
520 END
521 models.0 = count
522
523/*
524 CALL SysStemSort 'models.', 'D', 'I',,, 1, 4
525 DO i = 1 TO count
526 models.i = SUBWORD( models.i, 2 )
527 END
528*/
529RETURN best
530
531/*:VRX QueryAvailableDrivers
532*/
533/* Determine which of our supported PrinterPak drivers are currently available.
534 */
535QueryAvailableDrivers: PROCEDURE EXPOSE globals. drv_list.
536 drv_list.0 = 0
537
538 test_drivers = 'ECUPS ECUPS-HP PSPRINT'
539 DO i = 1 TO WORDS( test_drivers )
540 driver = WORD( test_drivers, i )
541 ok = GetDriverSource( driver )
542 IF ok == '' THEN
543 ok = VRGetIni('PM_DEVICE_DRIVERS', driver, 'USER')
544 IF ok <> '' THEN
545 CALL SysStemInsert 'drv_list.', drv_list.0+1, driver
546 END
547
548RETURN drv_list.0
549
Note: See TracBrowser for help on using the repository browser.