summaryrefslogtreecommitdiff
path: root/v4.0/src/SELECT/PRN_DEF.ASM
blob: 3494d7a4a5d63d1751dae497c87048c4f32ce3d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
;********************************************************************************
; File: PRN_DEF.ASM
;
; Subroutines to read the printer profile file, extract the printer names,
; build a scroll list for the cas services and retrieve addition information
; from the file on a specific printer.
; Also contains a subroutine to change the parameters for the SELECT command
; in the autoexec.bat file.
;
;********************************************************************************
PAGE	, 132				   ;AN000;
.ALPHA					;AN000;
.XLIST					;AN000;
INCLUDE MACROS.INC			;AN000;
INCLUDE STRUC.INC			;AN000;
.LIST					;AN000;

;***************************************************************************
; Define the public subroutines in this module
;***************************************************************************
PUBLIC	 GET_PRINTER_TITLES_ROUTINE	 ;AN000;
PUBLIC	 GET_PRINTER_INFO_ROUTINE	 ;AN000;
PUBLIC	 RELEASE_PRINTER_INFO_ROUTINE	 ;AN000;
PUBLIC	 CHANGE_AUTOEXEC_ROUTINE	 ;AN000;
;***************************************************************************
; Define the public values in this module
;***************************************************************************
PUBLIC	 SEG_LOC			;AN000; The segment where the printer data is stored
PUBLIC	 NAMES_OFF			;AN000; The offset in the segment of the names table
PUBLIC	 N_PRN_NAMES			;AN000; The number of printer definitions read from the profile
PUBLIC	 MAX_NAME			;AN000; The longest name in the list
PUBLIC	 SIZE_NAMES			;AN000; The number of bytes between each printer name (abs)
PUBLIC	 SEL_FLG			;AN000; AN000; SELECT runtime flag

EXTRN	 SYSPARSE: FAR;AN000;
EXTRN	 POS_ZERO: FAR;AN000;
EXTRN	 COPY_ROUTINE: FAR;AN000;
EXTRN	 I_PRINTER: WORD;AN000;
EXTRN	 N_PRINTER_TYPE: BYTE;AN000;
EXTRN	 S_MODE_PARM: WORD;AN000;
EXTRN	 S_CP_DRIVER: WORD;AN000;
EXTRN	 S_CP_PREPARE: WORD;AN000;
EXTRN	 S_GRAPH_PARM: WORD;AN000;
EXTRN	 HOOK_INT_24:FAR;AN000;
EXTRN	 RESTORE_INT_24:FAR;AN000;
EXTRN	 INT_24_ERROR:WORD;AN000;


EXTRN	 BIN_TO_CHAR_ROUTINE:FAR;AN000;

DATA	SEGMENT BYTE PUBLIC 'DATA';AN000;


SEL_FLG 	   DB	     0	  ;AN000; Select flag byte
;INSTALLRW	   EQU	     80H  ;AN000; INSTALL diskette is R/W

SEG_LOC 	   DW	     0	  ;AN000; Location of the segment where the data is
NAMES_OFF	   DW	     0	  ;AN000; The offset of the names table in the segment
SEGMENT_SIZE	   DW	     0	  ;AN000; Amount of memory available
BUFFER_START	   DW	     0	  ;AN000; Starting offset of the file data buffer
BUFFER_SIZE	   DW	     0	  ;AN000; Number of bytes in the file data buffer
FILE_PTR_AT_START  DD	     0	  ;AN000; The file pointer for the data which is at
				  ;  the beginning of the file data buffer
AMOUNT_OF_DATA	   DW	     0	  ;AN000; The number of bytes in the file data buffer
CURRENT_PARSE_LOC  DW	     0	  ;AN000; The location to start the next parse.
END_CUR_LINE	   DW	     0	  ;AN000; The address of the end of the line currently being parsed
CX_ORDINAL_VALUE   DW	     0	  ;AN000; The value returned by the parse for next call
NUM_PRINTER_DEFS   DB	     0	  ;AN000; The number of printer definitions in the file
N_PRN_NAMES	   DW	     0	  ;AN000; The next free index into the names table
FILE_HANDLE	   DW	     0	  ;AN000; Handle for the printer definition file.
MAX_NAME	   DW	     0	  ;AN000; The length of the longest printer name found in the file
START_NEXT_LINE    DW	     0	  ;AN000; The starting offset of the next line to parse
APPEND_POINTER	   DW	     0	  ;AN000; Offset of the ASCII-N string to append to the SELECT line
FILENAME	   DW	     0	  ;AN000; Offset of the ASCII-N string containing the filename
CDP_FOUND	   DB	     0	  ;AN000;
CPP_FOUND	   DB	     0	  ;AN000;


W_VALUE       DW	0	;AN000;
STRING_N      DB   10 DUP(0);AN000;


;AD000;JW BLANK_MODE	     DW   END_BLANK_MODE - $ - 3   ; The blank line for inserting mode parameters
;AD000;JW	   DB	'     , , , , ',?
;AD000;JW	   END_BLANK_MODE EQU  $

BLANK_STRING	   DW	0			 ;AN000; Blank values for the other printer profile parameters

E_SIZE_CR_LF	   EQU	2			 ;AN000; The number of bytes in W_CR_LF
W_CR_LF 	   DB	13,10			 ;AN000; Carrage return and line feed to append to the select line

READ_FLAG	   DB	     0			 ;AN000; Flag for use when reading data
    AT_EOF	   EQU	     1B 		 ;AN000; Indicates when the end of file has been reached
    LAST_LINE	   EQU	     10B		 ;AN000; Indicates if this is the last line in the buffer

    RESET_EOF	   EQU	     11111110B		 ;AN000; Masks for resetting the flags
    RESET_LST_LINE EQU	     11111101B ;AN000;

PARSE_FLAG	   DB	     0			 ;AN000; Flag for use when parsing the data
    FIRST_PARSE    EQU	     1B 		 ;AN000; Indicates if this is the first line being parsed
    LINE_DONE	   EQU	     10B		 ;AN000; Indicates if the current line has already been parsed
    FIRST_NAME	   EQU	     100B		 ;AN000; Indicates if a printer names has already been found

    RESET_FIRST_PARSE	EQU  11111110B		 ;AN000; Masks for resetting the flags
    RESET_LINE_DONE	EQU  11111101B	   ;AN000;
    RESET_FIRST_NAME	EQU  11111011B	  ;AN000;

;***************************************************************************
; Error codes returned.
;***************************************************************************
ERR_NOT_ENOUGH_MEM	EQU	  1		 ;AN000; There was not enough memory to build the names table
ERR_OPENING_FILE	EQU	  2		 ;AN000; Error opening a file
ERR_READING_FILE	EQU	  3		 ;AN000; Error reading from a file
ERR_FINDING_VALUE	EQU	  4		 ;AN000; Error finding the number of prn defs at the beginning of the file
ERR_LINE_TOO_LONG	EQU	  5		 ;AN000; There was a line too long for the buffer
ERR_FINDING_NAME	EQU	  6		 ;AN000; There was an error locating a printer name after a P or S
ERR_ACCESSING_FILE	EQU	  7		 ;AN000; There was an error updating the file pointer
ERR_TOO_MANY_DEFS	EQU	  8		 ;AN000; There are too many defintion in the file
ERR_NUMBER_MATCH	EQU	  9		 ;AN000; The number of actual definition do not match the number expected
ERR_ALLOCATING_MEM	EQU	  10		 ;AN000; There was an error allocating memory
ERR_CDP_CPP		EQU	  11		 ;AN000; A prn defn had either a CDP or CPP but not both
ERR_PRN_DEFN		EQU	  12  ;AN000;

TRUE			EQU	  1	     ;AN000;
FALSE			EQU	  0	    ;AN000;


E_CR			EQU	  13	     ;AN000;
E_LF			EQU	  10	     ;AN000;
E_FILE_TERM		EQU	  1AH  ;AN000;

E_MAX_PRN_NAME_LEN	EQU	  40		 ;AN000; The maximum printer name length
LENGTH_FILE_PTR 	EQU	  4		 ;AN000; The number of bytes in the file pointer
MAX_NUM_PRINTER_DEFS	EQU	  31		 ;AC089;SEH ;AC073; The maximum number of printer definitions
MIN_SIZE_FILE_BUFFER	EQU	  0400H 	 ;AN000; The minimum amount of memory needed for the file data buffer
LENGTH_PRT_TYPE_IND	EQU	  1		 ;AN000; The length of the printer type indicator
SIZE_NAMES		EQU	  E_MAX_PRN_NAME_LEN+LENGTH_FILE_PTR+LENGTH_PRT_TYPE_IND ;AN000; The size of one entry in the names table
NAMES_TABLE_SIZE	EQU	  SIZE_NAMES * MAX_NUM_PRINTER_DEFS	     ;AN000; The size of the names table
MINIMUM_MEMORY		EQU	  NAMES_TABLE_SIZE + MIN_SIZE_FILE_BUFFER		 ;AN000; The minimum amount of memory required

RANGE_ONLY		EQU	  1		 ;AN000; The parser is only to look for ranges of values
RANGE_AND_STRING	EQU	  3		 ;AN000; The parser is to look for ranges and strings

NUMERIC_VALUE		EQU	  08000H	 ;AN000; Parser constant for searching for numeric values
SIMPLE_STRING		EQU	  02000H	 ;AN000; Parser constant for searching for strings


; Control blocks for the parser.
;  The PARMS INPUT BLOCK
PARMS	      LABEL	BYTE	   ;AN000;
    PAR_EXTEN	   DW	OFFSET PARMSX	 ;AN000; Offset of the PARMS EXTENSION BLOCK
    PAR_NUM	   DB	2		 ;AN000; The number of further definitions
		   DB	0	      ;AN000;
		   DB	1	      ;AN000;
		   DB	1AH	      ;AN000;

; The PARMS EXTENSION BLOCK
PARMSX	      LABEL	BYTE;AN000;
    PAX_MINP	   DB	0  ;AN000;
    PAX_MAXP	   DB	1  ;AN000;
		   DW	CONTROL_P1    ;AN000;
    PAX_MAX_SW	   DB	0;AN000;
    PAX_MAX_K1	   DB	0;AN000;

; The control blocks for the definition of positional parameters, switch and
; keywords.
CONTROL_P1    EQU  $  ;AN000;
CTL_FUNC_FL	   DW	2000H;AN000;
		   DW	0002H	      ;AN000;
		   DW	RESULT_P1     ;AN000;
		   DW	VALUE_LIST_P1 ;AN000;
		   DB	0	      ;AN000;

VALUE_LIST_P1	   EQU	$;AN000;
VAL_NUM 	   DB	1	  ;AN000; Number of value definitions
		   DB	1	  ;AN000; Number of range definitions
		   DB	8	  ;AN000; Return value if parameter is in this range
		   DD	0   ;AN000;
		   DD	255 ;AN000;
		   DB	0	  ;AN000; Number of actual value definitions
NUM_STRINGS	   DB	2	  ;AN000; Number of string definitions
		   DB	1	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_PARALLEL;AN000;
		   DB	2	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_SERIAL;AN000;

		   DB	3	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_MODE;AN000;
		   DB	4	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_CODE_DRIVER;AN000;
		   DB	5	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_CODE_PREPARE;AN000;
		   DB	6	  ;AN000; Value to be returned if this string is matched
		   DW	OFFSET KEYWORD_GRAPHICS;AN000;

KEYWORD_PARALLEL	DB   'P',0;AN000;
KEYWORD_SERIAL		DB   'S',0;AN000;
KEYWORD_MODE		DB   'SP',0;AN000;
KEYWORD_CODE_DRIVER	DB   'CDP',0;AN000;
KEYWORD_CODE_PREPARE	DB   'CPP',0;AN000;
KEYWORD_GRAPHICS	DB   'GP',0;AN000;

RESULT_P1	   LABEL     BYTE;AN000;
		   DB	0	  ;AN000; Type of operand returned
MATCHED_TAG	   DB	0	  ;AN000; Matched item tag
SYNONYM_PTR	   DW	0	  ;AN000; Offset of synonym returned
RESULT_FIELD	   DB	0,0,0,0   ;AN000; Unsure what this is...


;AD000;JW ;***************************************************************************
;AD000;JW ; Parser control blocks for parsing the mode parameters
;AD000;JW ;***************************************************************************
;AD000;JW MODE_PARMS	LABEL	  BYTE
;AD000;JW		DW   MODE_PARMSX
;AD000;JW		DB   0
;AD000;JW
;AD000;JW MODE_PARMSX	LABEL	  BYTE
;AD000;JW		DB   0,0
;AD000;JW		DB   0
;AD000;JW		DB   1
;AD000;JW		DW   OFFSET CNTL_BAUD
;AD000;JW
;AD000;JW CNTL_BAUD	LABEL	  BYTE
;AD000;JW		DW   SIMPLE_STRING
;AD000;JW		DW   2
;AD000;JW		DW   RESULT_P1
;AD000;JW		DW   MODE_VALUES
;AD000;JW		DB   5
;AD000;JW SYN_BAUD	DB   'BAUD',0
;AD000;JW SYN_PARITY	DB   'PARITY',0
;AD000;JW SYN_DATA	DB   'DATA',0
;AD000;JW SYN_STOP	DB   'STOP',0
;AD000;JW SYN_RETRY	DB   'RETRY',0
;AD000;JW
;AD000;JW MODE_VALUES	LABEL	  BYTE
;AD000;JW		DB	  0


;***************************************************************************
; Parser control blocks for parsing the AUTOEXEC.BAT file for 'SELECT'
;***************************************************************************
SELECT_PARMX  LABEL	BYTE	 ;AN000;
	      DB   1,1		    ;AN000;
	      DW   SELECT_CONTROL   ;AN000;
	      DB   0		    ;AN000;
	      DB   0		    ;AN000;

SELECT_CONTROL	   LABEL     BYTE;AN000;
	      DW   2000H	    ;AN000;
	      DW   2		    ;AN000;
	      DW   RESULT_P1	    ;AN000;
	      DW   SELECT_VALUE     ;AN000;
	      DB   0		    ;AN000;

SELECT_VALUE  LABEL	BYTE	 ;AN000;
	      DB   3		    ;AN000;
	      DB   0		    ;AN000;
	      DB   0		    ;AN000;
	      DB   1		    ;AN000;
	      DB   1		    ;AN000;
	      DW   OFFSET SELECT_STR;AN000;

SELECT_STR    DB   'SELECT',0;AN000;
ALLOC_FLAG    DB   0
ALLOCATED     EQU  80H


DATA	ENDS			;AN000;

CODE_FAR SEGMENT BYTE PUBLIC 'CODE';AN000;

	ASSUME	CS:CODE_FAR, DS:DATA, ES:DATA;AN000;

;***************************************************************************
; Routines for extracting the printer names from the file data and storing
; them in a table located in high memory.  In addition to the name, the
; type of printer, whether Parallel or Serial and the location in the file
; of this printer name is also saved in the table.
;***************************************************************************

;******************************************************************************
;
; Routine:  GET_PRINTER_TITLES_ROUTINE - Reads the names of all the printers
;			      and their location in the file into a data
;			      buffer in high memory.
;
; Input:
;    DI - The offset of name of the file which contains the printer definitions
;	  in ASCII-N format.
;
; Output:
;    If CY = 1: Indicates that an error has occured.
;	  BX - The error code for the error which this subroutine detected.
;	  AX - The error code which was returned if the error was as a result
;	       of a DOS call.
;    If CY = 0: No error has occured.
;	  AX, BX - Undefined.
;
;******************************************************************************
GET_PRINTER_TITLES_ROUTINE   PROC FAR		 ;AN000;
						 ;
    CALL HOOK_INT_24				 ;AN000;
;;  int 3
;;  nop

    PUSH ES					 ;AN000;
    ;**********************************************************************
    ; Allocate the necessary memory for the buffer.  A maximum of 64K is
    ; allocated.
    ;**********************************************************************
    CALL ALLOCATE_MEMORY			 ;AN000; Allocate the memory for the printer data
    .IF < C >					 ;AN000; Was there an error?
	 JMP  EXIT_WITH_ERROR			 ;AN000; If so, exit the subroutine
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; See if there is enough memory to continue.
    ;**********************************************************************
    .IF < SEGMENT_SIZE B MINIMUM_MEMORY>	 ;AN000; Is there enough memory?
	 MOV  BX, ERR_NOT_ENOUGH_MEM		 ;AN000; No! Return error code.
	 JMP  EXIT_WITH_ERROR			 ;AN000; Exit the subroutine
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Set the pointer for the file data buffer and save the size of this buffer.
    ;**********************************************************************
    MOV  BUFFER_START, NAMES_TABLE_SIZE 	 ;AN000; Starting address of the file data buffer
    MOV  BX, SEGMENT_SIZE			 ;AN000; Total amount of memory available
    SUB  BX, NAMES_TABLE_SIZE			 ;AN000; Calculate the size of the file data buffer
    MOV  BUFFER_SIZE, BX			 ;AN000; Save this size.
    MOV  NAMES_OFF, 0				 ;AN000; Offset of the printer names table
    ;**********************************************************************
    ; Open the printer definition file.
    ;**********************************************************************
    MOV  INT_24_ERROR, 0			 ;AN000;
    CALL POS_ZERO				 ;AN000; Turn the ASCII-N string into an ASCII-Z string
    MOV  DX, DI 				 ;AN000; Get address of the ASCII-N string
    ADD  DX, 2					 ;AN000; Address of the filename
    MOV  AX, 3D00H				 ;AN000; Open file for reading.
    DOSCALL					 ;AN000;
    .IF < C >					 ;AN000; Was there an error opening the file?
	 MOV  BX, ERR_OPENING_FILE		 ;AN000; Yes! Return this error code
	 JMP  EXIT_WITH_ERROR			 ;AN000;
    .ENDIF					 ;AN000;
    MOV  FILE_HANDLE, AX			 ;AN000; Save the handle for the file
    ;**********************************************************************
    ; Initialize the variable which holds the file pointer at the beginning
    ; of the buffer.
    ;**********************************************************************
    MOV  WORD PTR FILE_PTR_AT_START, 0		 ;AN000; Zero the low word
    MOV  WORD PTR FILE_PTR_AT_START+2, 0	 ;AN000; Zero the high word
    AND  READ_FLAG, RESET_EOF			 ;AN000; Indicate we are not at EOF
    ;**********************************************************************
    ; Read data into the file buffer.
    ;**********************************************************************
    MOV  DI, BUFFER_START			 ;AN000; Start reading at this offset
    SUB  DI, NAMES_TABLE_SIZE			 ;AN000; Make into an offset in the buffer instead of the segment
    CALL READ_FROM_HERE 			 ;AN000; Read in the data.
    .IF < C >					 ;AN000; Was there an error reading from the file?
	 MOV  BX, ERR_READING_FILE		 ;AN000; Return this error code
	 JMP  EXIT_WITH_ERROR			 ;AN000; Return from this subroutine
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Initialize the variables needed for the parsing.
    ;**********************************************************************
    MOV  CURRENT_PARSE_LOC, NAMES_TABLE_SIZE	 ;AN000; Start parsing from the beginning.
    MOV  CX_ORDINAL_VALUE, 0			 ;AN000; The first parse, CX must be zero.
    MOV  N_PRN_NAMES, 0 			 ;AN000; There are not names in the table now
    AND  PARSE_FLAG, RESET_LINE_DONE		 ;AN000; The current line has NOT been parsed
    OR	 PARSE_FLAG, FIRST_PARSE		 ;AN000; Indicate that this is the first parse
    ;**********************************************************************
    ; Setup the control blocks for the parser
    ;**********************************************************************
    MOV   PAR_EXTEN, OFFSET PARMSX		 ;AN000; Load the address of the parse extention block
    ;**********************************************************************
    ; Parse the data.  If this is the first parse, then look for the number
    ; of printer definitions.  If it is not, then look for the parameters
    ; P and S which preface the printer names.
    ;**********************************************************************
    MOV  VAL_NUM, RANGE_ONLY			 ;AN000; Parse for a range of values only
    MOV  CTL_FUNC_FL, NUMERIC_VALUE		 ;AN000; Indicate we are looking for numbers
    MOV  NUM_STRINGS, 2 			 ;AN000; The number of parameters to look for
    ;**********************************************************************
    ; See if there is a complete line in the remainder of the buffer.  If there
    ; is not, then read more data into the buffer starting with the start of
    ; the current line.
    ;**********************************************************************
PARSE_NEXT_LINE:				 ;AN000;
    CALL SEARCH_LINE				 ;AN000; Search for the first parameter on the line
    .IF < C >					 ;AN000; Was there an error?
	 JMP  EXIT_WITH_ERROR			 ;AN000; Yes! Exit the routine
    .ENDIF					 ;AN000;
    .IF < BIT PARSE_FLAG AND FIRST_PARSE >	 ;AN000; Looking for a value or a string?
	 .IF < AX NE 0 >			 ;AN000; Was there an error?
	      MOV  BX, ERR_FINDING_VALUE	 ;AN000; Yes! Return with this error code
	      JMP  EXIT_WITH_ERROR		 ;AN000;
	 .ENDIF 				 ;AN000;
	 MOV  AL, RESULT_FIELD			 ;AN000; Get the low order byte of the value
	 MOV  NUM_PRINTER_DEFS, AL		 ;AN000; Store the number of definitions
	 AND  PARSE_FLAG, RESET_FIRST_PARSE	 ;AN000; Indicate the first parse is finished
	 MOV  VAL_NUM, RANGE_AND_STRING 	 ;AN000; Specify strings and ranges
	 MOV  CTL_FUNC_FL, SIMPLE_STRING	 ;AN000; Look for specific strings only.
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; See if we found a printer name
    ;**********************************************************************
    .IF < AX EQ 0 >				 ;AN000; Was an error found parsing the buffer
	 .IF < N_PRN_NAMES AE MAX_NUM_PRINTER_DEFS >	 ;AN000; Are there more the 255 printer defs?
	      MOV  BX, ERR_TOO_MANY_DEFS	 ;AN000; If so, return this error.
	      JMP  EXIT_WITH_ERROR		 ;AN000; Terminate the subroutine.
	 .ENDIF 		     ;AN000;
						 ; DX contains the address of the result block
	 CALL COPY_PRINTER_NAME 		 ;AN000; Copy the name to the table
	 .IF < C >				 ;AN000; Was there an error?
	      MOV  BX, ERR_FINDING_NAME 	 ;AN000; Yes! Return this error code
	      JMP  EXIT_WITH_ERROR		 ;AN000;
	 .ENDIF 				 ;AN000;
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Start scanning the next line.
    ;**********************************************************************
    MOV  DI, START_NEXT_LINE			 ;AN000; Get the address of the next line to parse
    MOV  CURRENT_PARSE_LOC, DI			 ;AN000; Save it
    .IF < CURRENT_PARSE_LOC EQ 0 >		 ;AN000; Is there more data?
	 JMP  EXIT_WITHOUT_ERROR		 ;AN000; No! Exit the routine
    .ENDIF		    ;AN000;
    JMP  PARSE_NEXT_LINE			 ;AN000; Start processing this line
						 ;
EXIT_WITH_ERROR:				 ;AN000;
    STC 					 ;AN000; Set the carry flag, indicating error.
    JMP  EXIT_ROUTINE				 ;AN000;
EXIT_WITHOUT_ERROR:				 ;AN000;
    MOV  CX, N_PRN_NAMES			 ;AN000; The number of entries in the table
    .IF < CL NE NUM_PRINTER_DEFS >		 ;AN000; Did the number of definitions agree with the expected number?
	 MOV  BX, ERR_NUMBER_MATCH		 ;AN000; Return this error message
	 JMP  EXIT_WITH_ERROR			 ;AN000; Return, setting the carry flag.
    .ENDIF		  ;AN000;
    CLC 					 ;AN000; Clear the carry flag - No error.
EXIT_ROUTINE:					 ;AN000;
    CALL DEALLOCATE_MEMORY
    POP  ES					 ;AN000;
    CALL RESTORE_INT_24;AN000;
    RET 					 ;AN000;
						 ;
GET_PRINTER_TITLES_ROUTINE   ENDP		 ;AN000;
;********************************************************************************
;
;SEARCH_LINE: Search for the first parameter on a line.
;
;INPUT:
;    None.
;
;OUTPUT:
;    AX - Contains the return codes from the parser
;    If CY = 1: There was an error - BX contains an error code
;    if CY = 0: There were NO errors.
;    All the registers are set from the parser return.
;
;OPERATION:
;
;********************************************************************************
SEARCH_LINE   PROC NEAR 	    ;AN000;

    MOV  DI, CURRENT_PARSE_LOC			 ;AN000; Get the current location in the buffer
    CALL SCAN_FOR_EOLN				 ;AN000; Search for the end of the line
    MOV  START_NEXT_LINE, DI			 ;AN000; Save the start address of the next line
    .IF < C >					 ;AN000; Was the END OF LINE found?
	 .IF <BIT READ_FLAG AND AT_EOF> 	 ;AN000; Are we at the end of the file?
	      MOV  START_NEXT_LINE, 0		 ;AN000; Yes!  Indicate that this is the last line
	 .ELSE					 ;AN000; We are not the the end of the file
	      MOV  DI, CURRENT_PARSE_LOC	 ;AN000; The location to read from in the file
	      SUB  DI, NAMES_TABLE_SIZE 	 ;AN000; Make into an offset in the buffer instead of the segment
	      CALL READ_FROM_HERE		 ;AN000; Read in more data
	      .IF < C > 			 ;AN000; Was there an error reading from the file?
		   MOV	BX, ERR_READING_FILE	 ;AN000; Return this error code
		   JMP	EXIT_SEARCH_ERROR	 ;AN000; Return from this subroutine
	      .ENDIF				 ;AN000;
	      MOV  CURRENT_PARSE_LOC, NAMES_TABLE_SIZE ;AN000; Start back at the beginning of the buffer
	      MOV  DI, CURRENT_PARSE_LOC	 ;AN000; Get the current parse location again.
	      CALL SCAN_FOR_EOLN		 ;AN000; Once again look for the end of the line
	      MOV  START_NEXT_LINE, DI		 ;AN000; Save the start address of the nest line
	      .IF < C > 			 ;AN000; Was it found?
		   MOV	BX, ERR_LINE_TOO_LONG	 ;AN000; No! Indicate an error.
		   JMP	EXIT_SEARCH_ERROR	 ;AN000; Return with this error
	      .ENDIF				 ;AN000;
	 .ENDIF 				 ;AN000;
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Set up the input parameters for the parse subroutine
    ;**********************************************************************
    MOV  DI, OFFSET PARMS			 ;AN000; Offset into ES of the PARMS control block
    MOV  SI, CURRENT_PARSE_LOC			 ;AN000; Where to start parsing
    MOV  DX, 0					 ;AN000;
    MOV  CX, CX_ORDINAL_VALUE			 ;AN000; The value returned by the parse last time.
    PUSH DS					 ;AN000; Save the current data segment
    PUSH ES					 ;AN000; Save the file data segment
    MOV  AX, DATA				 ;AN000; Get the current data segment
    MOV  ES, AX 				 ;AN000; This is the parser control blocks.
    MOV  AX, SEG_LOC			;AN000; Where the data to parse is located
    MOV  DS, AX 				 ;AN000;
    CALL SYSPARSE				 ;AN000; Do the parsing
    POP  ES					 ;AN000; Restore the file data segment
    POP  DS					 ;AN000; Restore the data segment
    CLC 					 ;AN000; Indicate there were no errors
    RET 					 ;AN000;
EXIT_SEARCH_ERROR:				 ;AN000; Here if there were errors
    STC 					 ;AN000; Indicate so to the calling program
    RET 					 ;AN000;

SEARCH_LINE   ENDP;AN000;
;********************************************************************************
; ALLOCATE_MEMORY: Allocate a maximum of 64K of memory.
;
; INPUT:
;    None.
;
; OUTPUT:
;    SEGMENT_SIZE = The size of the segment allocated.
;    SEG_LOC =	The location of the segment allocated.
;    If CY = 1: There was an error - BX contains an error code
;    If CY = 0: There was NO errors.
;
; Operation:
;
;********************************************************************************
ALLOCATE_MEMORY    PROC NEAR;AN000;

    AND  ALLOC_FLAG,NOT ALLOCATED
    MOV  BX, 0FFFH				 ;AN000; Try to allocate this amount of memory
    MOV  SEGMENT_SIZE, BX			 ;AN000; Save the amount of memory asked for
    MOV  AH, 48H				 ;AN000; DOS Fn. for allocating memory
    DOSCALL					 ;AN000; Allocate the memory
    .IF < C >					 ;AN000; Was there an error?
	 MOV  SEGMENT_SIZE, BX			 ;AN000; Save the size asked for in this request
	 MOV  AH, 48H				 ;AN000; DOS Fn. for allocating memory
	 DOSCALL				 ;AN000; Allocate the memory
    .ENDIF					 ;AN000;
    .IF < C >					 ;AN000; Was there an error allocating the memory?
	 MOV  BX, ERR_ALLOCATING_MEM		 ;AN000; Yes! Return an error code
	 STC					 ;AN000; Indicate that there was an error
    .ELSE					 ;AN000; Otherwise...
	 MOV  SEG_LOC, AX		;AN000; Save the location of the memory block allocated
	 MOV  ES, AX				 ;AN000; Save in the extra segment
	 MOV  CL, 4				 ;AN000; Multiply the number of paragraphs by 16
	 SHL  SEGMENT_SIZE, CL			 ;AN000;  to get the number of bytes.
	 OR   ALLOC_FLAG,ALLOCATED
	 CLC					 ;AN000; Indicate there was no error
    .ENDIF					 ;AN000;
    RET 					 ;AN000;

ALLOCATE_MEMORY    ENDP;AN000;


;********************************************************************************
; DEALLOCATE_MEMORY: deallocate memory.
;
; INPUT:
;    SEG_LOC   previously allocated segment
;
; OUTPUT:
;    None.
;
;********************************************************************************
DEALLOCATE_MEMORY PROC NEAR

	   TEST ALLOC_FLAG,ALLOCATED
	   JZ DEM10

	   PUSH ES
	   MOV	AX,SEG_LOC
	   MOV	ES,AX
	   MOV	AH,49H
	   INT	21H
	   POP	ES
DEM10:
	   RET
DEALLOCATE_MEMORY ENDP

;*******************************************************************************
;
; Routine: SCAN_FOR_EOLN - Scan the given string, for CR and LF.
;
; Input:
;    DI - Address of the string to scan for the eoln.
;
; Output:
;    If CY = 0: The end of the line was found.
;	DI - Contains the address of the start of the next line in the buffer.
;	   - If DI = 0, the data ends just after either the CR, LF or the
;	     CR and LF.  Therefore, more data must be read before the next line
;	     can be parsed.
;
;    If CY = 1: The end of the line was not found.
;
;*******************************************************************************
SCAN_FOR_EOLN PROC NEAR;AN000;

    MOV  CX, BUFFER_START			 ;AN000; The offset in the segment of the buffer
    ADD  CX, AMOUNT_OF_DATA			 ;AN000; Get the offset of the end of the data
    SUB  CX, DI 				 ;AN000; Subtract the file data pointer
						 ; CX - Contains the amount of data after pointer
    MOV  AL, 0					 ;AN000; Flag to indicate CR-LF has not been found yet
    .WHILE < CX A 0 >				 ;AN000; Search until the end of the data
	 .IF < <BYTE PTR ES:[DI]> EQ E_FILE_TERM >;AN000;
	      .IF < ZERO AL >	 ;AN000;
		   MOV	END_CUR_LINE, DI	 ;AN000; Save this location in the string
		   DEC	END_CUR_LINE		 ;AN000; Point to the real end of the line
	      .ENDIF	       ;AN000;
	      STC	       ;AN000;
	      MOV  DI, 0       ;AN000;
	      JMP  EXIT_SCAN   ;AN000;
	 .ENDIF 	       ;AN000;
	 .IF < <BYTE PTR ES:[DI]> EQ E_LF > OR	 ;AN000; Is this character a CR or a LF?
	 .IF < <BYTE PTR ES:[DI]> EQ E_CR >	;AN000;
	      .IF < ZERO AL >			 ;AN000; Has a CR or a LF already been found?
		   MOV	END_CUR_LINE, DI	 ;AN000; Save this location in the string
		   DEC	END_CUR_LINE		 ;AN000; Point to the real end of the line
	      .ENDIF	       ;AN000;
	      INC  AL				 ;AN000; Indicate that a CR or a LF has been found
	 .ELSEIF < NONZERO AL > 		 ;AN000; If we have passed the CR-LF,
	      CLC				 ;AN000;  Indicate we have found EOLN
	      JMP  EXIT_SCAN			 ;AN000; Leave the subroutine
	 .ENDIF 		;AN000;
	 DEC  CX				 ;AN000; One less character to the end
	 INC  DI				 ;AN000; Point to the next character
    .ENDWHILE ;AN000;

    .IF < AL AE 2 >				 ;AN000; Does the data run out right after the CR-LF?
	 MOV  DI, 0				 ;AN000; Return 0 indicating so.
    .ENDIF	 ;AN000;
    STC 					 ;AN000; Indicate that the whole line is not there

EXIT_SCAN:    ;AN000;
    RET       ;AN000;

SCAN_FOR_EOLN ENDP;AN000;
;*******************************************************************************
;
; Routine: COPY_PRINTER_NAME - Copy the name of the printer from the file
;		    into the buffer holding all the names.
;
; Input:
;    SI - Contains the address of the start of the printer name.
;    DX - Contains the address of the parse result block
;
; Output:
;    CY = 1: An error has occured.  The name of the printer has not been found.
;    CY = 0: No error.
;
; Operation:   The name from the file buffer is copied to the printer name
;	  table.  Starting from the address passed in DI, the file buffer is
;	  scanned until a valid character is found.  Starting from this point
;	  up to forty characters are transferred to the name table.  If no
;	  name is found, the carry flag is set, and nothing is recorded in the
;	  name table.
;	       After the name is copied, the remainder of the field in the table
;	  is cleared.
;
;*******************************************************************************
COPY_PRINTER_NAME  PROC NEAR;AN000;

    PUSH DS   ;AN000;
    PUSH ES   ;AN000;
    PUSH DX					 ;AN000; Save the address of the result block
    ;**********************************************************************
    ; Calculate the offset into the file data table for this entry
    ;**********************************************************************
    MOV  AX, N_PRN_NAMES		  ;AN000; The next free index into the names table
    MOV  BX, SIZE_NAMES 	     ;AN000; Get the number of bytes per entry
    MUL  BX					 ;AN000; Multiply by the index into the table
    MOV  DI, AX 				 ;AN000; Move the offset into an index register
    ;**********************************************************************
    ; Copy the type of printer first
    ;**********************************************************************
    POP  BX					 ;AN000; Get the result block address
    MOV  AL, DS:[BX+1]				 ;AN000; Get the matched item tag
    .IF < AL EQ 1 >				 ;AN000; Was the parameter a P?
	 MOV  AL, 'P'                            ;AN000; Yes!
    .ELSE					 ;AN000;
	 MOV  AL, 'S'                            ;AN000; No! It was an S
    .ENDIF					 ;AN000;
    MOV  ES:[DI+40], AL 			 ;AN000; Store in the table
    ;**********************************************************************
    ; Skip the spaces between the printer type indicator and the printer name
    ;**********************************************************************
    MOV  AL, 32 				 ;AN000; Character to skip - space
    XCHG SI, DI 				 ;AN000; Point DI to the line being scanned
    MOV  CX, END_CUR_LINE			 ;AN000; Get address of the last char in line
    SUB  CX, DI 				 ;AN000; Subtract start
    INC  CX					 ;AN000; Get the length of the line
    CLD 					 ;AN000; Scan forward
    REPZ  SCASB 				 ;AN000; Repeat search until character found
    JZ	 NAME_NOT_FOUND 			 ;AN000; If all spaces, then it is an error
    INC  CX					 ;AN000; Increment character count
    DEC  DI					 ;AN000; Decrement pointer to character
    ;***********************************************************************
    ; Move the printer name to the names list
    ;***********************************************************************
    XCHG SI, DI 				 ;AN000; Exchange the pointers again
    MOV  CX, END_CUR_LINE			 ;AN000; Get the address of the last char
    SUB  CX, SI 				 ;AN000; Subtract start
    INC  CX					 ;AN000; Get the length of the line
    .IF < CX A E_MAX_PRN_NAME_LEN >		 ;AN000; Is the length of the line too long?
	 MOV  CX, E_MAX_PRN_NAME_LEN		 ;AN000; Yes! Make the line length the maximum size
    .ENDIF					 ;AN000;
    MOV  DX, CX 				 ;AN000; Save the line length for later use
    .WHILE < NONZERO CX >			 ;AN000; Do while there are more characters in the string
	 MOV  AL, BYTE PTR ES:[SI]		 ;AN000; Get a character from the file data
	 .IF < AL NE 32 >			 ;AN000; Is this character a space?
	      MOV  BX, DX			 ;AN000; Get the line length
	      SUB  BX, CX			 ;AN000; Get the length of the line copied so far
	      INC  BX				 ;AN000;
	      .IF < MAX_NAME B BX >	     ;AN000; Is this name longer than the longest so far?
		   MOV	MAX_NAME, BX	     ;AN000; Yes! This is the new maximum
	      .ENDIF		  ;AN000;
	 .ENDIF 		  ;AN000;
	 MOV  BYTE PTR ES:[DI], AL		 ;AN000; Put the character in the names table
	 INC  SI				 ;AN000; Increment string pointers
	 INC  DI     ;AN000;
	 DEC  CX				 ;AN000; Decrement the number of characters left
    .ENDWHILE ;AN000;
    ;***********************************************************************
    ; Fill in the rest of the name area with spaces
    ;***********************************************************************
    MOV  CX, E_MAX_PRN_NAME_LEN 		 ;AN000; The maximum line length
						 ; DX contains the line length from last section
    SUB  CX, DX 				 ;AN000; Calculate the space left in the line
    MOV  AL, 32 				 ;AN000; Character to store
    REP  STOSB					 ;AN000; Store the blank characters
    ;***********************************************************************
    ; Store the file pointer to this printer name in the name list
    ;***********************************************************************
    INC  DI					 ;AN000; Point DI passed the printer type indicator
    MOV  SI, CURRENT_PARSE_LOC			 ;AN000; Get the start of the current line
    SUB  SI, NAMES_TABLE_SIZE			 ;AN000; Subtract offset of the start of the buffer
    MOV  CX, WORD PTR FILE_PTR_AT_START 	 ;AN000; Get the low order word of the pointer
    MOV  DX, WORD PTR FILE_PTR_AT_START[2]	 ;AN000; Get the high order word
    ADD  CX, SI 				 ;AN000; Add the offset of the start of this line
    ADC  DX, 0					 ;AN000; Add the high word
    MOV  WORD PTR ES:[DI], CX			 ;AN000; Store the low order word in the list
    MOV  WORD PTR ES:[DI+2], DX 		 ;AN000; Store the high order word
    INC  N_PRN_NAMES			  ;AN000; Point to the next free area in the list
    CLC 		 ;AN000;
    JMP  EXIT_COPY	 ;AN000;
NAME_NOT_FOUND: 	 ;AN000;
    STC 		 ;AN000;
EXIT_COPY:		 ;AN000;
    POP  ES		 ;AN000;
    POP  DS		 ;AN000;
    RET 		 ;AN000;

COPY_PRINTER_NAME  ENDP  ;AN000;

;*******************************************************************************
; Routine: READ_FROM_HERE - Read from the file into the buffer starting from
;		    the file position pointed to by CURRENT_PARSE_LOC.
;
; Input:
;    DI - Contains the current parsing location in the buffer.
;
; Output:
;    FILE_PTR_AT_START - Updated for the new data read.
;
; Operation:
;
;*******************************************************************************
READ_FROM_HERE	   PROC NEAR;AN000;
						 ;
    ;**********************************************************************
    ; Update the R/W pointer in the file.
    ;**********************************************************************
    MOV  DX, WORD PTR FILE_PTR_AT_START 	 ;AN000; Get the low order word of the pointer
    MOV  CX, WORD PTR FILE_PTR_AT_START[2]	 ;AN000; Get the high order word of the pointer
    ADD  DX, DI 				 ;AN000; Add the offset of where to start reading
    ADC  CX, 0					 ;AN000; Take care of the carry condition
    MOV  WORD PTR FILE_PTR_AT_START, DX 	 ;AN000; Store the new starting position
    MOV  WORD PTR FILE_PTR_AT_START[2], CX	 ;AN000; Store the high word of pointer
    MOV  INT_24_ERROR, 0			 ;AN000;
    MOV  AX, 4200H				 ;AN000; DOS Function for moving the file pointer
    MOV  BX, FILE_HANDLE			 ;AN000; Load the file handle
    DOSCALL					 ;AN000; Move the file pointer
    .IF < C >					 ;AN000; Was an error encountered?
	 JMP  RETURN_WITH_ERROR 		 ;AN000; Yes! Exit the subroutine.
    .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Read from the file into the data buffer
    ;**********************************************************************
    MOV  CX, BUFFER_SIZE			 ;AN000; Number of bytes to read.  As many as will fit.
    MOV  BX, FILE_HANDLE			 ;AN000; Load the DOS file handle for this file
    MOV  AH, 03FH				 ;AN000; The DOS function to perform
    MOV  DX, BUFFER_START			 ;AN000; The offset of the file data buffer
    MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
    PUSH DS					 ;AN000; Save the current data segment
    PUSH ES					 ;AN000; Push the file data buffer
    POP  DS					 ;AN000; DS now points to the file data buffer
    DOSCALL					 ;AN000; Read from the file.
    POP  DS					 ;AN000; Restore the original data segment
    ;**********************************************************************
    ; See if the buffer was filled.
    ;**********************************************************************
    MOV  AMOUNT_OF_DATA, AX			 ;AN000; Save the amount of data that was read.
    .IF < AX B BUFFER_SIZE >			 ;AN000; Were less bytes read then we asked for?
	 OR   READ_FLAG, AT_EOF 		 ;AN000; Yes! Indicate that we are at EOF
;	 MOV  DI, AX				 ; Move number of characters into an index pointer
;	 MOV  BYTE PTR ES:[DI+NAMES_TABLE_SIZE], 00   ; Place a terminator at the end
    .ENDIF		    ;AN000;
    CLC 		    ;AN000;
    RET 		    ;AN000;

RETURN_WITH_ERROR:	    ;AN000;
    STC 		    ;AN000;
    RET 		    ;AN000;

READ_FROM_HERE	   ENDP      ;AN000;

;********************************************************************************
; Routines for extracting all the information supplied in the profile for a
; specific printer.  Given the printer number, the location of its definition
; is looked up in the names table.  The file is them parsed for the information.
;********************************************************************************

;******************************************************************************
; GET_PRINTER_INFO_ROUTINE - Get all the information contained in the printer
;	       profile file for the specified printer.
;
; INPUT:
;    AX - The number of the printer to return the information on.  The number
;	  is the index into the names table for this printer.
;
; OUTPUT:
;	If CY = 0, there were no errors.
;	The following variable are updated with the information found in
;	the file:
;	      I_PRINTER
;	      N_PRINTER_TYPE
;	      S_MODE_PARM
;	      S_CP_DRIVER
;	      S_CP_PREPARE
;	      S_GRAPH_PARM
;
;	If CY = 1, There were errors encountered.
;	     BX = An error code indicating the type of error that occured.
;
;		= 3  There was an error reading the file
;		= 7  There was a error accessing the file
;		= 11 A printer definition has either a CDP or a CPP
;		       Prefix, but BOTH were not present.
;		= 12 There was an error in the printer definition.
;		       - A line was found with an invalid prefix
;
;		If the error was a result of a DOS function, then
;		on return, AX will contain the DOS error code.
;
; Operation:
;
; Note:
;   The first printer name has an index of 1.
;
;******************************************************************************
GET_PRINTER_INFO_ROUTINE     PROC FAR;AN000;



    CALL HOOK_INT_24				 ;AN000;



    PUSH ES					 ;AN000; Save the extra segment register
    ;**********************************************************************
    ; Calculate the address of the specifed printer
    ;**********************************************************************
    MOV  I_PRINTER, AX				 ;AN000; Save the printer index
    DEC  AX					 ;AN000; Make the first index a 0
    MOV  BX, SIZE_NAMES 	     ;AN000; Number of bytes in each table entry
    MUL  BX					 ;AN000; Address is returned in AX
    MOV  DI, AX 				 ;AN000; Move the address to an index register
    ;**********************************************************************
    ; Get the file location for this printer name
    ;**********************************************************************
    MOV  AX, SEG_LOC			;AN000; Get the segment where the data is
    MOV  ES, AX 				 ;AN000; Save in a segment register
    MOV  CX, WORD PTR ES:[DI+41]		 ;AN000; Get the low order word of the file location
    MOV  DX, WORD PTR ES:[DI+43]		 ;AN000; Get the high order word of the file location
    ;**********************************************************************
    ; Determine if the information is already in the buffer or do we  have
    ; to read more information from the printer profile.
    ;**********************************************************************
    .IF < DX B <WORD PTR FILE_PTR_AT_START+2>>	 ;AN000; Compare the high order words
	 JMP  READ_MORE_INFORMATION		 ;AN000; Info in buffer is passed where we want.
    .ELSE					 ;AN000;
	 .IF < DX EQ < WORD PTR FILE_PTR_AT_START+2>> AND ;AN000; High words equal so
	 .IF < CX B <WORD PTR FILE_PTR_AT_START>>	  ;AN000; compare the low order words
	      JMP  READ_MORE_INFORMATION	 ;AN000; Info in buffer is passed where we want.
	 .ENDIF 			  ;AN000;
    .ENDIF			   ;AN000;
    MOV  BX, WORD PTR FILE_PTR_AT_START+2	 ;AN000; File location at beginning of buffer
    MOV  SI, WORD PTR FILE_PTR_AT_START 	 ;AN000; Low order word
    ADD  SI, AMOUNT_OF_DATA			 ;AN000; Get the file pointer of the end of the buffer
    ADC  BX, 0					 ;AN000; Add in the high word
    .IF < DX A BX >				 ;AN000; If data we want is further in the file,
	 JMP  READ_MORE_INFORMATION		 ;AN000; Read in more data
    .ELSE		       ;AN000;
	 .IF < DX EQ BX > AND			 ;AN000; If the high words are equal do the
	 .IF < CX A SI >			 ;AN000; comparison on the low order words
	      JMP  READ_MORE_INFORMATION	 ;AN000; Still not there, so read more info
	 .ENDIF 			  ;AN000;
    .ENDIF			   ;AN000;
    MOV  AX, I_PRINTER				 ;AN000; Get the index of this printer name
    .IF < AL EQ NUM_PRINTER_DEFS >		 ;AN000; Is this the last one in the list?
	 .IF < BIT READ_FLAG AND AT_EOF >	 ;AN000; If it is, and all the data has been read, process it
	      JMP  PARSE_HERE		   ;AN000;
	 .ELSE				   ;AN000;
	      JMP  READ_MORE_INFORMATION	 ;AN000; Not EOF, so read in more data just for safety
	 .ENDIF 			  ;AN000;
    .ENDIF			   ;AN000;
    MOV  CX, WORD PTR ES:[DI+SIZE_NAMES+41] ;AN000; Get the pointer to the NEXT printer name
    MOV  DX, WORD PTR ES:[DI+SIZE_NAMES+43] ;AN000; Get the high order word
    .IF < DX A BX >				 ;AN000; See if the next printer name is in the buffer
	 JMP  READ_MORE_INFORMATION		 ;AN000; If not, get more information
    .ELSE		       ;AN000;
	 .IF < DX EQ BX > AND			 ;AN000; If the high order words are equal,
	 .IF < CX A SI >			 ;AN000; Compare the low order.  Is the name there?
	      JMP  READ_MORE_INFORMATION	 ;AN000; If not, read more.
	 .ENDIF 			  ;AN000;
    .ENDIF			   ;AN000;
    JMP  PARSE_HERE				 ;AN000; The necessary info is there, so parse it.
    ;**********************************************************************
    ; The specified printer information is not currently in the buffer.  It
    ; is necessary to read it from the printer profile file.
    ;**********************************************************************
READ_MORE_INFORMATION:				 ;AN000;
    MOV  CX, WORD PTR ES:[DI+43]		 ;AN000; Get the file pointer of this printer name
    MOV  DX, WORD PTR ES:[DI+41]		 ;AN000; Get the low order word of pointer
    MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
    MOV  AX, 4200H				 ;AN000; DOS Fn. for positioning file pointer
    MOV  BX, FILE_HANDLE			 ;AN000; Get the handle of the file
    DOSCALL					 ;AN000; Position the pointer
    .IF < C >					 ;AN000; If CY = 1, there was an error
	 MOV  BX, ERR_ACCESSING_FILE		 ;AN000; Return this error code
	 JMP  ERROR_EXIT			 ;AN000; Jump to exit routine
    .ENDIF	     ;AN000;
    MOV  WORD PTR FILE_PTR_AT_START, AX 	 ;AN000; Set the new pointer at the beginning of the buffer
    MOV  WORD PTR FILE_PTR_AT_START+2, DX	 ;AN000; Set the high order word
    MOV  AH, 3FH				 ;AN000; DOS Fn. for reading from a file
    MOV  DX, BUFFER_START			 ;AN000; Offset of the start of the data buffer
    MOV  BX, FILE_HANDLE			 ;AN000; Get the file handle
    MOV  CX, BUFFER_SIZE			 ;AN000; Read as many bytes as the buffer will hold
    MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
    PUSH DS					 ;AN000; Save the current data segment
    PUSH ES					 ;AN000; Push the segment of the data buffer
    POP  DS					 ;AN000; Load DS with the segment where to store the data
    DOSCALL					 ;AN000; Read in the data
    POP  DS					 ;AN000; Restore the data segment
    .IF < C >	 ;AN000;
	 MOV  BX, ERR_READING_FILE;AN000;
	 JMP  ERROR_EXIT;AN000;
    .ENDIF	 ;AN000;
    .IF < AX NE BUFFER_SIZE >			 ;AN000; Were less bytes read then asked for?
	 OR   READ_FLAG, AT_EOF 		 ;AN000; If so, then we are at the end of file
    .ELSE					 ;AN000; Otherwise...
	 AND  READ_FLAG, RESET_EOF		 ;AN000; We are not at end of file
    .ENDIF		      ;AN000;
    MOV  AMOUNT_OF_DATA, AX			 ;AN000; Save the amount of data actually read
    ;**********************************************************************
    ; The printer data is in the data buffer.  Begin to parse the data.
    ;**********************************************************************
PARSE_HERE:		       ;AN000;
    MOV  CDP_FOUND, FALSE      ;AN000;
    MOV  CPP_FOUND, FALSE      ;AN000;
    PUSH DI					 ;AN000; Save the pointer into the names table
    ;**********************************************************************
    ; Load the printer profile fields with defaults.
    ;**********************************************************************
    COPY_STRING    S_MODE_PARM, 40, BLANK_STRING  ;AC000;JW
    COPY_STRING    S_CP_DRIVER, 22, BLANK_STRING  ;AN000;
    COPY_STRING    S_CP_PREPARE, 12, BLANK_STRING ;AN000;
    COPY_STRING    S_GRAPH_PARM, 20, BLANK_STRING ;AN000;
    POP  DI					 ;AN000; Restore the pointer into the names table
    ;**********************************************************************
    ; Get the type of printer.
    ;**********************************************************************
    MOV  AL, ES:[DI+40] 			 ;AN000; Get the printer type - Parallel or Serial from the table
    MOV  N_PRINTER_TYPE, AL			 ;AN000; Save in the appropriate variable
    ;**********************************************************************
    ; Get the offset of the start of this printer definition
    ;**********************************************************************
    MOV  CX, ES:[DI+41] 			 ;AN000; Get the low order word of the file pointer
    MOV  DX, ES:[DI+43] 			 ;AN000; Get the high order word
    SUB  DX, WORD PTR FILE_PTR_AT_START[2]	 ;AN000; Subtract the high order words
    SBB  CX, WORD PTR FILE_PTR_AT_START 	 ;AN000; Subtract the low order words
    ADD  CX, BUFFER_START			 ;AN000; Get the offset of the start of the definition
    MOV  CURRENT_PARSE_LOC, CX			 ;AN000; Save as the scan position
    OR	 PARSE_FLAG, FIRST_NAME    ;AN000;
PARSE_NEXT_PARM:		  ;AN000;
    MOV  DI, CURRENT_PARSE_LOC			 ;AN000; Get the current scan position
    CALL SCAN_FOR_EOLN				 ;AN000; Search for the end of this line
    MOV  START_NEXT_LINE, DI			 ;AN000; Save the position of the start of the next line
    MOV  SI, CURRENT_PARSE_LOC			 ;AN000; The position in the buffer to scan
    MOV  NUM_STRINGS, 6 			 ;AN000; Number of parameters to parse for
    MOV  DI, OFFSET PARMS			 ;AN000; Offset of the parameter blocks
    MOV  DX, 0					 ;AN000; The parser wants DX = 0.
    MOV  CX, 0					 ;AN000; Tell the parser this is the first scan of this line
    PUSH DS					 ;AN000; Save the current data segment
    PUSH ES					 ;AN000; Save the file data segment
    MOV  AX, DATA				 ;AN000; Get the current data segment
    MOV  ES, AX 				 ;AN000; This is the parser control blocks.
    MOV  AX, SEG_LOC				 ;AN000; Where the data to parse is located
    MOV  DS, AX 				 ;AN000;
    CALL SYSPARSE				 ;AN000; Do the parsing
    POP  ES					 ;AN000; Restore the file data segment
    POP  DS					 ;AN000; Restore the data segment
    .IF < AX EQ 0FFFFH >			 ;AN000; Was the end of the line found?
	 JMP  UPDATE_PARSE_PTR			 ;AN000; If so, start the next one
    .ELSEIF < NONZERO AX >			 ;AN000; Was an error encountered parsing the line?
	 MOV  BX, ERR_PRN_DEFN	     ;AN000;
	 JMP  ERROR_EXIT			 ;AN000; If so, exit the subroutine
    .ENDIF	     ;AN000;
    MOV  AL, MATCHED_TAG			 ;AN000; Get which string was matched
    .IF < AL EQ 1 > OR				 ;AN000; Was this a printer name and type?
    .IF < AL EQ 2 >	   ;AN000;
	 .IF < BIT PARSE_FLAG AND FIRST_NAME >	 ;AN000; Is this the first name encountered?
	      AND  PARSE_FLAG, RESET_FIRST_NAME  ;AN000; Indicate that the a name has been found
	 .ELSE					 ;AN000; Otherwise...
	      JMP  PARSING_DONE 		 ;AN000; This is the second name.  We are finished.
	 .ENDIF 		   ;AN000;
    .ELSEIF < AL EQ 3 > 			 ;AN000; AL = 3 ==> Mode parameters
	 CALL HANDLE_MODE			 ;AN000; Process
    .ELSEIF < AL EQ 4 > 			 ;AN000; AL = 4 ==> Code page driver parameters
	 MOV  CDP_FOUND, TRUE	   ;AN000;
	 CALL HANDLE_CODE_DRIVER		 ;AN000; Process
    .ELSEIF < AL EQ 5 > 			 ;AN000; AL = 5 ==> Code page preparation parameters
	 MOV  CPP_FOUND, TRUE	   ;AN000;
	 CALL HANDLE_CODE_PREPARE		 ;AN000; Process
    .ELSEIF < AL EQ 6 > 			 ;AN000; AL = 6 ==> Graphics parameters
	 CALL HANDLE_GRAPHICS			 ;AN000; Process
    .ENDIF		  ;AN000;
    ;**********************************************************************
    ; The current line has been parsed.  Point to the next line.
    ;**********************************************************************
UPDATE_PARSE_PTR:	  ;AN000;
    MOV  AX, START_NEXT_LINE			 ;AN000; Get the address of the start of the next line
    MOV  CURRENT_PARSE_LOC, AX			 ;AN000; Save this as the start of the current line
    .IF < CURRENT_PARSE_LOC EQ 0 >		 ;AN000; Is there any more data?
	 JMP  PARSING_DONE			 ;AN000; No. Exit the routine
    .ENDIF					 ;AN000;
    JMP  PARSE_NEXT_PARM			 ;AN000; Start the parsing again
    ;**********************************************************************
    ; The subroutine is finished.
    ;**********************************************************************
PARSING_DONE:		    ;AN000;
    MOV  AL, CDP_FOUND	    ;AN000;
    XOR  AL, CPP_FOUND	    ;AN000;
    .IF < NZ >		    ;AN000;
	 MOV  BX, ERR_CDP_CPP	   ;AN000;
	 JMP  ERROR_EXIT	   ;AN000;
    .ENDIF		    ;AN000;
    CLC 					 ;AN000; Clear the carry - No errors
    JMP  EXIT_INFO				 ;AN000; Exit the subroutine
ERROR_EXIT:	       ;AN000;
    STC 					 ;AN000; Set the carry - There were errors
EXIT_INFO:    ;AN000;
    POP  ES					 ;AN000; Restore the extra segment
    CALL RESTORE_INT_24;AN000;
    RET 					 ;AN000; return

GET_PRINTER_INFO_ROUTINE     ENDP;AN000;
;********************************************************************************
; HANDLE_MODE - Subroutine to process the mode parameter line in the printer
;    profile.
;
; INPUT:
;    SI - Points to the beginning of the line to process
;
; OUTPUT:
;    S_MODE_PARM - Filled with the information from the line.  The line will be
;	  in a format for use as the parameters for the MODE command.
;
;********************************************************************************
HANDLE_MODE   PROC NEAR;AN000;

;AD000;JW     PUSH SI
;AD000;JW     COPY_STRING    S_MODE_PARM, 13, BLANK_MODE
;AD000;JW     POP  SI
;AD000;JW
;AD000;JW NEXT_MODE_SCAN:				   ; Scan for the next keyword.
;AD000;JW     MOV  DI, OFFSET MODE_PARMS		   ; Offset of the control blocks for parsing the mode parameters
;AD000;JW     MOV  CX, 0				   ; Always tell the parser this is the first parse
;AD000;JW     MOV  DX, 0				   ; The parse wants DX = 0
;AD000;JW     PUSH ES					   ; Save the segment registers
;AD000;JW     PUSH DS
;AD000;JW     MOV  AX, DATA				   ; Get the location of the data segment
;AD000;JW     MOV  ES, AX				   ; Load in the extra segment register - The segment of the control blocks
;AD000;JW     MOV  AX, SEG_LOC				   ; Get the location of the printer data
;AD000;JW     MOV  DS, AX				   ; Load into the data segment - The segment of the data to parse
;AD000;JW     CALL SYSPARSE				   ; Parse the line.
;AD000;JW     POP  DS					   ; Restore the segment registers
;AD000;JW     POP  ES
;AD000;JW
;AD000;JW ;   PUSHH	<AX,BX,CX,DX,SI,DI>
;AD000;JW ;   MOV  W_VALUE, AX
;AD000;JW ;   WORD_TO_CHAR   W_VALUE, STRING_N
;AD000;JW ;   PRINTN	STRING_N
;AD000;JW ;   CR_LF
;AD000;JW ;   POPP	<DI,SI,DX,CX,BX,AX>
;AD000;JW
;AD000;JW     .IF < NONZERO AX >			   ; If errors or the end of the line, end the routine
;AD000;JW	   JMP	EXIT_MODE_SCAN
;AD000;JW     .ENDIF
;AD000;JW     MOV  BX, DX				   ; Move result pointer into an index register
;AD000;JW     .IF <<WORD PTR [BX+2]> EQ <OFFSET SYN_BAUD>>	     ; Was this the BAUD keyword?
;AD000;JW	   MOV	AX, 5				   ; Maximum number of character to copy
;AD000;JW	   MOV	DI, OFFSET S_MODE_PARM+2	   ; Where to put the baud parameters
;AD000;JW     .ELSEIF <<WORD PTR [BX+2]> EQ <OFFSET SYN_PARITY>>     ; Was this the PARITY keyword?
;AD000;JW	   MOV	AX, 1				   ; Maximum number of character to copy
;AD000;JW	   MOV	DI, OFFSET S_MODE_PARM+8	   ; Where to put the parity parameters
;AD000;JW     .ELSEIF <<WORD PTR [BX+2]> EQ <OFFSET SYN_DATA>>	     ; Was this the DATA keyword?
;AD000;JW	   MOV	AX, 1				   ; Maximum number of character to copy
;AD000;JW	   MOV	DI, OFFSET S_MODE_PARM+10	   ; Where to put the data parameters
;AD000;JW     .ELSEIF <<WORD PTR [BX+2]> EQ <OFFSET SYN_STOP>>	     ; Was this the STOP keyword?
;AD000;JW	   MOV	AX, 1				   ; Maximum number of character to copy
;AD000;JW	   MOV	DI, OFFSET S_MODE_PARM+12	   ; Where to put the stop parameters
;AD000;JW     .ELSEIF <<WORD PTR [BX+2]> EQ <OFFSET SYN_RETRY>>      ; Was this the RETRY keyword?
;AD000;JW	   MOV	AX, 1				   ; Maximum number of character to copy
;AD000;JW	   MOV	DI, OFFSET S_MODE_PARM+14	   ; Where to put the retry parameters
;AD000;JW     .ENDIF
;AD000;JW     CALL COPY_RESULT				   ; Copy the string
;AD000;JW     JMP  NEXT_MODE_SCAN			   ; Scan for the next keyword
;AD000;JW EXIT_MODE_SCAN:
;AD000;JW     CALL REMOVE_BLANKS			   ; Remove the blanks from the mode line
;AD000;JW

    MOV  DI, OFFSET S_MODE_PARM 		 ;AN000; Offset of the variable to load     JW
    MOV  CX, 40 				 ;AN000; Maximum width of the field		    JW
    CALL COPY_LINE				 ;AN000; Copy the information from the file data  JW
    RET 					 ;AN000; Return 			    JW

HANDLE_MODE   ENDP;AN000;
;AD000;JW ;********************************************************************************
;AD000;JW ; REMOVE_BLANKS: Remove the blanks from the S_MODE_PARM string.  Any trailing
;AD000;JW ;    commas are also removed.
;AD000;JW ;
;AD000;JW ; INPUT:
;AD000;JW ;    None.
;AD000;JW ;
;AD000;JW ; OUTPUT:
;AD000;JW ;    None.
;AD000;JW ;
;AD000;JW ; OPERATION:
;AD000;JW ;
;AD000;JW ;
;AD000;JW ;********************************************************************************
;AD000;JW REMOVE_BLANKS PROC NEAR
;AD000;JW
;AD000;JW     MOV  CX, WORD PTR S_MODE_PARM
;AD000;JW     LEA  SI, S_MODE_PARM
;AD000;JW     INC  SI
;AD000;JW     ADD  SI, CX
;AD000;JW     MOV  BX, CX
;AD000;JW     .WHILE < CX AE 0 >
;AD000;JW	   .IF < <BYTE PTR [SI]> EQ <' '> > OR
;AD000;JW	   .IF < <BYTE PTR [SI]> EQ <','> >
;AD000;JW		DEC  BX
;AD000;JW	   .ELSE
;AD000;JW		.LEAVE
;AD000;JW	   .ENDIF
;AD000;JW	   DEC	SI
;AD000;JW	   DEC	CX
;AD000;JW     .ENDWHILE
;AD000;JW     MOV  WORD PTR S_MODE_PARM, BX
;AD000;JW
;AD000;JW     MOV  CX, BX
;AD000;JW     LEA  SI, S_MODE_PARM
;AD000;JW     ADD  SI, 2
;AD000;JW     MOV  DI, SI
;AD000;JW     .WHILE < CX A 0 >
;AD000;JW	   .IF < <BYTE PTR [SI]> NE <' '>>
;AD000;JW		.IF < SI NE DI >
;AD000;JW		     MOV  AL, [SI]
;AD000;JW		     MOV  [DI], AL
;AD000;JW		.ENDIF
;AD000;JW		INC  DI
;AD000;JW	   .ELSE
;AD000;JW		DEC  BX
;AD000;JW	   .ENDIF
;AD000;JW	   INC	SI
;AD000;JW	   DEC	CX
;AD000;JW     .ENDWHILE
;AD000;JW     MOV  WORD PTR S_MODE_PARM, BX
;AD000;JW     RET
;AD000;JW
;AD000;JW REMOVE_BLANKS ENDP
;********************************************************************************
; HANDLE_CODE_DRIVER - Subroutine to process the code page driver parameter
;    line in the printer profile.
;
; INPUT:
;    SI - Points to the beginning of the line to process
;
; OUTPUT:
;    S_CP_DRIVER - Filled with the information from the line.
;
; OPERATION: The line from the file is copied to the S_CP_DRIVER variable.
;    This variable is assumed to be a maximum of 22 characters wide.
;
;********************************************************************************
HANDLE_CODE_DRIVER PROC NEAR;AN000;

    MOV  DI, OFFSET S_CP_DRIVER 		 ;AN000; Offset of the variable to load
    MOV  CX, 22 				 ;AN000; Maximum width of the field
    CALL COPY_LINE				 ;AN000; Copy the information from the file data
    RET 	       ;AN000;

HANDLE_CODE_DRIVER ENDP;AN000;

;********************************************************************************
; HANDLE_CODE_PREPARE - Subroutine to process the code prepare parameter line
;    in the printer profile.
;
; INPUT:
;    SI - Points to the beginning of the line to process
;
; OUTPUT:
;    S_CP_PREPARE - Filled with the information from the line.
;
; OPERATION: The line from the file is copied to the variable S_CP_PREPARE.
;    The variable is assumed to be a maximum of 12 characters long.
;
;********************************************************************************
HANDLE_CODE_PREPARE	PROC NEAR;AN000;

    MOV  DI, OFFSET S_CP_PREPARE		 ;AN000; Offset of the variable to load
    MOV  CX, 12 				 ;AN000; Maximum length of the variable
    CALL COPY_LINE				 ;AN000; Copy the information from the file data
    RET 	       ;AN000;

HANDLE_CODE_PREPARE	ENDP;AN000;

;********************************************************************************
; HANDLE_GRAPHICS - Subroutine to process the graphics parameter line in the
;    printer profile.
;
; INPUT:
;    SI - Points to the beginning of the line to process
;
; OUTPUT:
;    S_GRAPH_PARM - Filled with the information from the line.
;
; OPERATION: The line from the file is copied to the S_GRAPH_PARM variable.
;    The variable is assumed to be a maximum of 20 characters long.
;
;********************************************************************************
HANDLE_GRAPHICS    PROC NEAR;AN000;

    MOV  DI, OFFSET S_GRAPH_PARM		 ;AN000; Offset of the variable to load
    MOV  CX, 20 				 ;AN000; Maximum width of the variable
    CALL COPY_LINE				 ;AN000; Load the variable with the data from the file
    RET 	       ;AN000;

HANDLE_GRAPHICS    ENDP;AN000;

;********************************************************************************
; COPY_RESULT: Copy the string pointed to in the result block to the specified
;    destination.
;
; INPUT:
;    AX - The maximum length of the string to copy.
;    DX - The offset in DS of the result block.
;    DI - The offset of where the string is to be stored
;
;
; OUTPUT:
;    CX - The length of the string copied.
;
; Operation: The string is copied from the result block to the area pointed to
;    by DS:DI.	The string is copied until a null character is encountered.
;
;********************************************************************************
COPY_RESULT   PROC NEAR;AN000;

    PUSH ES	       ;AN000;
    PUSH SI	       ;AN000;
    MOV  BX, DX 				 ;AN000; Put address into an index register
    LES  SI, [BX+4]				 ;AN000; Get the address of the string to copy
    MOV  CX, 0					 ;AN000; Zero the string length indicator
    .WHILE < CX B AX >				 ;AN000; Copy up to the number of character in AX
	 MOV  DL, BYTE PTR ES:[SI]		 ;AN000; Get the first byte
	 .LEAVE < ZERO DL >			 ;AN000; Terminate loop if this is a null char
	 MOV  BYTE PTR [DI], DL 		 ;AN000; Save character in the destination string
	 INC  SI				 ;AN000; Increment source pointer
	 INC  DI				 ;AN000; Increment destination pointer
	 INC  CX				 ;AN000; Increment number of characters moved
    .ENDWHILE ;AN000;
    POP  SI   ;AN000;
    POP  ES   ;AN000;
    RET       ;AN000;

COPY_RESULT   ENDP;AN000;

;********************************************************************************
; COPY_LINE - Copy a line from the printer profile data to a specified area.
;
; INPUT:
;    DI - Points to the location the data is to be copied to.
;    CX - Contains the maximum number of bytes copied.
;
; OUTPUT:
;    None.
;
; OPERATION: The current line being parsed is copied to the specified area.
;    The length of the line is calculated with the use of the variable
;    CUR_END_LINE.  If the lenght of the line is longer then the number passed
;    in CX, then only a portion of the line will be copied.
;
;********************************************************************************
COPY_LINE     PROC NEAR;AN000;


    PUSH SI					 ;AN000; Save the index regiter used by the parser
    PUSH DI					 ;AN000; Save the pointer to the variable to load
    ADD  DI, 2					 ;AN000; Push pointer passed the lenght word
    MOV  AX, END_CUR_LINE			 ;AN000; Get the pointer to the end of this line
    SUB  AX, SI 				 ;AN000; Get the distance to the end
    INC  AX					 ;AN000; Add to get the length of the line
    .IF < AX B CX >				 ;AN000; If length is greater then the maximum allowed,
	 MOV  CX, AX				 ;AN000; use the shorter length
    .ENDIF	  ;AN000;
    PUSH CX					 ;AN000; Save the length used.
    PUSH ES					 ;AN000; Swap the values in the segment registers
    PUSH DS	 ;AN000;
    POP  ES	 ;AN000;
    POP  DS	 ;AN000;
    CLD 					 ;AN000; Move in the forward direction
    REP  MOVSB					 ;AN000; Move the data
    POP  CX					 ;AN000; Restore the line length
    POP  DI					 ;AN000; Restore the pointer to the variable
    MOV  WORD PTR ES:[DI], CX			 ;AN000; Save the length of the string
    POP  SI					 ;AN000; Restore the parser pointer
    PUSH DS					 ;AN000; Swap the segment registers again
    PUSH ES	 ;AN000;
    POP  DS	 ;AN000;
    POP  ES	 ;AN000;
    RET 	 ;AN000;

COPY_LINE     ENDP;AN000;

;********************************************************************************
; Routine to deallocate the memory used for the storage of the printer profile
; data and the table of printer names.	These routines also close the profile
; file.
;********************************************************************************

;********************************************************************************
; RELEASE_PRINTER_INFO_ROUTINE - Close the printer profile file and free the
;	 allocated memory.
;
; INPUT:
;    None.
;
; OUTPUT:
;    If CY = 0, There were no error encountered.
;    If CY = 1, There was an error.
;	 AX = The DOS error code for the deallocate memory function
;
; OPERATION: Closes the printer file and deallocated the memory.
;
;********************************************************************************
RELEASE_PRINTER_INFO_ROUTINE	PROC FAR;AN000;




    CALL HOOK_INT_24				 ;AN000;


    PUSH ES					 ;AN000;
    ;**********************************************************************
    ; Close the printer definition file
    ;**********************************************************************
    MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
    MOV  BX, FILE_HANDLE			 ;AN000; File handle of the profile file
    MOV  AH, 3EH				 ;AN000; DOS Fn. for closing a file
    DOSCALL					 ;AN000; Close the file
    ;**********************************************************************
    ; Deallocate the memory used for the data buffer
    ;**********************************************************************
    MOV  AX, SEG_LOC				 ;AN000; Location of the data buffer
    MOV  ES, AX 				 ;AN000;
    MOV  AH, 49H				 ;AN000; DOS Fn. for freeing allocated memory
    DOSCALL					 ;AN000; Free the memory
    POP  ES					 ;AN000;
    CALL RESTORE_INT_24;AN000;
    RET 	 ;AN000;

RELEASE_PRINTER_INFO_ROUTINE ENDP;AN000;

;*******************************************************************************
; Routines for changing the SELECT command line in the AUTOEXEC.BAT.
;*******************************************************************************

;********************************************************************************
; CHANGE_AUTOEXEC_ROUTINE: Search a file for a line beginning with SELECT, and
;			   change its parameters.
;
; INPUT:
;    DI - The offset of an ASCII-N string containing the file to search.
;    SI - The offset of an ASCII-N string containing the data to append as
;	  parameters.
;
; OUTPUT:
;    None.
;
; Operation:
;
;********************************************************************************
CHANGE_AUTOEXEC_ROUTINE PROC FAR;AN000;



    TEST SEL_FLG,INSTALLRW			 ;AN000; Is the install
						 ;AN000;    diskette read/write
						 ;AN000;   (has DISKCOPY occurred?)
    JNZ  AUTO_OK				 ;AN000;
    CLC 					 ;AN000; no error
    JMP  AUTO_EXIT_RO				 ;AN000; If not, exit

AUTO_OK:		  ;AN000;
    CALL HOOK_INT_24				 ;AN000;
    PUSH ES					 ;AN000;
    MOV  APPEND_POINTER, SI			 ;AN000; Save the address of the string to be appended
    MOV  FILENAME, DI				 ;AN000; Save the address of the string containing the filename
    ;**********************************************************************
    ; Allocate the memory needed for reading the autoexec file.  A maximum
    ; of 64K is allocated for use.
    ;**********************************************************************
    CALL ALLOCATE_MEMORY			 ;AN000; Allocate the memory needed
    .IF < C >					 ;AN000; Was there an error?
	 JMP  AUTO_EXIT_ERROR			 ;AN000; Yes!  Exit the subroutine
    .ENDIF					 ;AN000;
    MOV  BUFFER_START, 0			 ;AN000; Save the offset of the start of the buffer
    COPY_WORD BUFFER_SIZE, SEGMENT_SIZE 	 ;AN000; Save the size of the buffer
    ;**********************************************************************
    ; Open the input file
    ;**********************************************************************
    MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
						 ; DI contains the address of the filename
    CALL POS_ZERO				 ;AN000; Make the string into an ASCII-Z string
    MOV  DX, DI 				 ;AN000; Load string offset
    ADD  DX, 2					 ;AN000; Adjust for length word
    MOV  AX, 3D02H				 ;AN000; DOS Fn. for opening a file for reading and writing
    DOSCALL					 ;AN000; Open the file
    .IF < C >					 ;AN000; Was there an error?
	 JMP  AUTO_EXIT_ERROR			 ;AN000; Exit the subroutine
    .ENDIF					 ;AN000;
    MOV  FILE_HANDLE, AX			 ;AN000; Save the file handle
    ;**********************************************************************
    ; Set the file pointer
    ;**********************************************************************
    MOV  WORD PTR FILE_PTR_AT_START[0], 0	 ;AN000; Set the file pointer of the data in the buffer
    MOV  WORD PTR FILE_PTR_AT_START[2], 0	 ;AN000; Set the high word
    MOV  CURRENT_PARSE_LOC, 0			 ;AN000; Set the current parsing location
    AND  READ_FLAG, RESET_EOF			 ;AN000; Indicate that the end of file has not been reached
    ;**********************************************************************
    ; Read data into the buffer
    ;**********************************************************************
    MOV  DI, CURRENT_PARSE_LOC			 ;AN000; Get the current parsing location
    CALL READ_FROM_HERE 			 ;AN000; Read data starting from this position
    .IF < C >					 ;AN000; Was there an error?
	 JMP  AUTO_EXIT_ERROR			 ;AN000; Yes! Exit the subroutine
   .ENDIF					 ;AN000;
    ;**********************************************************************
    ; Setup the control blocks for the parser
    ;**********************************************************************
    MOV   PAR_EXTEN, OFFSET SELECT_PARMX	  ;AN000; Address of the parameters extension block
    ;**********************************************************************
    ; Parse the file for 'SELECT'
    ;**********************************************************************
PARSE_FOR_SELECT:				 ;AN000; Here to parse the line
    CALL SEARCH_LINE				 ;AN000; Parse the line.
    .IF < C >					 ;AN000; Was there an error?
	 JMP  AUTO_EXIT_ERROR			 ;AN000; Yes! Exit the subroutine
    .ENDIF					 ;AN000;
    .IF < AX EQ 0 >				 ;AN000; Did the parser file 'SELECT'?
	 MOV  CURRENT_PARSE_LOC, SI		 ;AN000; Yes!  Save the position after select as parse location
	 MOV  DX, WORD PTR FILE_PTR_AT_START[0];AN000;
	 MOV  CX, WORD PTR FILE_PTR_AT_START[2];AN000;
	 ADD  DX, CURRENT_PARSE_LOC   ;AN000;
	 ADC  CX, 0		      ;AN000;
	 MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
	 MOV  BX, FILE_HANDLE	 ;AN000;
	 MOV  AX, 4200H 	 ;AN000;
	 DOSCALL		 ;AN000;
	 .IF < C >				 ;AN000; Was there an error writing the data?
	      JMP  AUTO_EXIT_ERROR		 ;AN000; Yes! Exit the subroutine
	 .ENDIF 				 ;AN000;
	 ;*****************************************************************
	 ; Write the select parameters to the file
	 ;*****************************************************************
	 MOV  SI, APPEND_POINTER		 ;AN000; Address of the string to add to the select line
	 MOV  CX, [SI]				 ;AN000; Size of the string
	 MOV  DX, SI				 ;AN000; Get the address again
	 ADD  DX, 2				 ;AN000; Adjust pointer past length word
	 MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
	 MOV  BX, FILE_HANDLE			 ;AN000; Get the handle for this file
	 MOV  AH, 40H				 ;AN000; DOS Fn. number for writing data
	 DOSCALL				 ;AN000; Write the data
	 ;*****************************************************************
	 ; Write a carrage return and a line feed to the file
	 ;*****************************************************************
	 MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
	 MOV  DX, OFFSET W_CR_LF		 ;AN000; Address of string to write
	 MOV  CX, E_SIZE_CR_LF			 ;AN000; Size of the string
	 MOV  BX, FILE_HANDLE			 ;AN000; Get the file handle
	 MOV  AH, 40H				 ;AN000; DOS Fn. for writing data
	 DOSCALL				 ;AN000; Write the data
	 ;*****************************************************************
	 ; Truncate the file at the current file position
	 ;*****************************************************************
	 MOV  INT_24_ERROR, 0			 ;AN000; Indicate that no critical errors have occured yet
	 MOV  CX, 0		 ;AN000;
	 MOV  BX, FILE_HANDLE	 ;AN000;
	 MOV  AH, 40H		 ;AN000;
	 DOSCALL		 ;AN000;
	 ;*****************************************************************
	 ; Close the file.
	 ;*****************************************************************
	 CALL RELEASE_PRINTER_INFO_ROUTINE	 ;AN000; Close the original autoexec file
    .ELSE			     ;AN000;
	 ;*****************************************************************
	 ; Parse the next line.
	 ;*****************************************************************
	 MOV  DI, START_NEXT_LINE		 ;AN000; Get the address of the next line
	 MOV  CURRENT_PARSE_LOC, DI		 ;AN000; Save this as the current parse location
	 .IF < CURRENT_PARSE_LOC EQ 0 > 	 ;AN000; If this is zero, then there is no more data
	      JMP  AUTO_EXIT_CLEAR		 ;AN000; Exit the subroutine - No errors
	 .ENDIF 				 ;AN000;
	 JMP  PARSE_FOR_SELECT			 ;AN000; Parse the next line
    .ENDIF					 ;AN000;
    JMP  AUTO_EXIT_CLEAR			 ;AN000; Exit the subroutine - No errors

AUTO_EXIT_ERROR:				 ;AN000; Here if there was an error
    CALL RELEASE_PRINTER_INFO_ROUTINE		 ;AN000; Close the original file
    STC 					 ;AN000; Indicate that there was an error
    JMP  AUTO_EXIT				 ;AN000; Exit the subroutine

AUTO_EXIT_CLEAR:				 ;AN000; Exit here if NO errors.
    CLC 					 ;AN000; Indicate there were no errors
AUTO_EXIT:					 ;AN000; Here to exit
    CALL DEALLOCATE_MEMORY
    POP  ES					 ;AN000; Restore the extra segment
    CALL RESTORE_INT_24;AN000;
AUTO_EXIT_RO:	 ;AN000;
    RET 					 ;AN000;

CHANGE_AUTOEXEC_ROUTINE ENDP;AN000;

CODE_FAR    ENDS;AN000;

END	      ;AN000;