summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/TREE/TREE.ASM
blob: 22bb9d669bd3b8a7149fe342b0b3bc81a5347cc8 (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
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
	PAGE	90,132			;AN000;A2
	TITLE	TREE.SAL - DISPLAY THE SUBDIRECTORY TREE ;AN000;
LISTPARM =	1			;AN000;0=SUPPRESS LIST; 1=ALLOW LIST
;	.XLIST
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: TREE

; DESCRIPTIVE NAME: Tree structure of subdirectories is displayed.

; FUNCTION: Displays to standard output a graphic representation
;	    of the subdirectory tree structure, beginning
;	    with the specified subdirectory, and optionally
;	    displaying all filenames in that tree.

; ENTRY POINT: START

; INPUT: (DOS COMMAND LINE PARAMETERS)

;	      [d:][path] TREE [D:][path] [/F] [/A]

;	 WHERE
;	      [d:][path] - Path where the TREE command resides.

;	      [D:][path] - Display of subdirectories starts with this
;			   specified subdirectory.  If this is not
;			   specified, the default is the drive root directory.

;	      [/F]	 - This requests the files in each subdirectory
;			   in addition to the subdirectories themselves
;			   are to be listed.

;	      [/A]	 - This requests use of alternate graphic chars

; EXIT-NORMAL:	ERRORLEVEL 0 - Normal completion

; EXIT-ERROR:	ERRORLEVEL 1 - I/O error

;		ERRORLEVEL 2 - Incorrect DOS version

;		ERRORLEVEL 3 - Control Break termination

; EFFECTS: The result is a display of the Tree of subdirectories.
;	   No changes are made to the system, to the current subdirectory,
;	   nor to the current DOS default drive.

;		    1. NO FILES, JUST SUBDIRECTORIES

;		 D:\ROOT
;		 ����SUBDIR1
;		 ����SUBDIR2
;		 �   ����SUBDIR21
;		 �   ����SUBDIR22
;		 ����SUBDIR3
;		     ����SUBDIR31
;		     ����SUBDIR32

;		    2. FILES AND SUBDIRECTORIES

;		 D:\ROOT
;		 �   MAINFIL1
;		 �   MAINFIL2
;		 �
;		 ����SUBDIR1
;		 �	 FILE1
;		 �	 FILE2
;		 �
;		 ����SUBDIR2
;		 �   �	 FILE2A
;		 �   �	 FILE2B
;		 �   �
;		 �   ����SUBDIR21
;		 �   �	     FILEA
;		 �   �	     FILEB
;		 �   �
;		 �   ����SUBDIR22
;		 �	     FILEC
;		 �	     FILED
;		 �	     FILEF
;		 �
;		 ����SUBDIR3
;		     ����SUBDIR31
;		     ����SUBDIR32
;			     FILE32A
;			     FILE32B

; INCLUDED FILES: TREEQU.INC - EQUATES
;		  PATHMAC.INC - PATHGEN MACRO

; INTERNAL REFERENCES:
;    ROUTINES:

;     BEGIN - VERSION CHECK, SYSMSG INIT, EXIT TO DOS
;     DEFINE_GRAPHICS - GET GRAPHIC CHARS FROM MSG
;     PARSE - TOKENIZE THE DOS COMMAND LINE PARMS
;     VERIFY_DRIVE - CHECK IF USER DRIVE ID IS OK
;     INIT_CONDITIONS - GET INITIAL SUBDIR, APPEND,CTL_BREAK
;     GET_VOL_LABEL - GET VOLUME LABEL ON SPECIFIED DRIVE
;     VOLSER - DISPLAY VOLUME SERIAL NUMBER, IF ANY AN001
;     LEN_ASCIIZ - GET LENGTH OF ASCIIZ STRING
;     EXECUTE - LOOK THRU DIRECTORY LIST FOR SUBDIRS
;     ANY_MORE_SUBDIR - LOOK AHEAD,SEE IF MORE SUBDIR
;     FIND_TYPE_NORMAL - PROCESS NORMAL, NON-DIR, FILES
;     FIND_TYPE_DIR - PROCESS THE DIRECTORY
;     NEXT_LEVEL - SET UP TO LOOK AT LOWER LEVEL SUBDIR
;     BEGIN_FIND - DO FIND FIRST FILE
;     FIND_NEXT - LOOK FOR NEXT ENTRY IN DIRECTORY
;     SHOW_FN - DISPLAY THE FILENAME FOUND
;     FLN_TO_BUF - MOVE FILENAME TO BUFFER
;     GRAF_TO_BUF - SELECT LEADING GRAPHIC CHAR FOR BUF
;     BLANK_DASH - PUT BLANKS OR DASHES BEFORE FILENAME
;     FIX_GRAF - CHANGE CURRENT GRAPHIC FOR NEXT LINE
;     ANY_SUBDIRS - DISPLAY MSG IF NO SUBDIRS PRINTED
;     DO_WRITE - SEND STRING TO STDOUT
;     IF_NOMOREFILES - ASK EXTENDED ERROR FOR WHY IS ERROR
;     GET_EXTERR - CALL EXTENDED ERROR
;     SENDMSG - PASS IN REGS DATA FROM MSG DESCRIPTOR TO DISP MSG
;     BREAK_HANDLER - CONTROL BREAK VECTOR POINTS HERE
;     RESTORE - RETURN TO INITIAL DOS DEFAULT DRIVE
;     MYERRORHANDLER - SERVICE CRITICAL ERROR HANDLER
;     CHK_DBCS -SEE IF SPECIFIED BYTE IS A DBCS LEAD BYTE

;    DATA AREAS:
;	PSP - Contains the DOS command line parameters.
;	STACK - Dynamic allocation of workareas.

; EXTERNAL REFERENCES:
;    ROUTINES:
;	SYSDISPMSG (FAR)  - MESSAGE DISPLAY ROUTINE
;	SYSLOADMSG (FAR)  - SYSTEM MESSAGE LOADER
;	PARSER	   (NEAR) - INTERROGATE DOS COMMAND LINE PARMS

;    DATA AREAS:
;	DTA - defined by the DOS FINDFIRST function.

; NOTES:
;	 This module should be processed with the SALUT pre-processor
;	 with the re-alignment not requested, as:

;		SALUT TREE,NUL

;	 To assemble these modules, the sequential or alphabetical
;	 ordering of segments may be used.

;	 Sample LINK command:

; LINK @TREE.ARF

; Where the TREE.ARF is defined as:
;	       TREE+
;	       TREEPAR+
;	       TREESYSP+
;	       TREESYSM
;	       TREE

;	 These modules should be linked in this order.	The load module is
;	 a COM file.  It should be converted via EXE2BIN to a .COM file.

; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler,
;		    Display graphically the subdirectories and their files.
;		    A001 DCR 27, display vol serial number, if present.
;		    A002 Add support for /A switch for alternate graphics.
;		    A003 PTM 471 Avoid duplicate switches
;		    A004 PTM 537 Display parm in error
;		    A005 PTM 692 Remove period from vol label field
;		    A006 PTR1044 Append interface change
;		    A007 PTM1082 Critical error handler
;		    A008 PTM1199 DEFAULT DIR OF TARGET ALTERED
;		    A009 PTM1416 INT24 CLOBBERED USER'S RESPONSE
;		    A010 PTM1406 GET MEDIA ID WITH 69H, NOT IOCTL
;		    A011 PTM1821 COPYRIGH.INC moved to within msgserv.asm
;		    A012 PTM2352 DBCS ENABLING, CHECKING FOR "\"
;		    A013 PTM3512 PATHGEN
;		    A014 PTM3560 INVALID PATH DOES NOT DISPLAY PATHNAME
;
;     Label: The following notice is found in the OBJ code generated from
;	     the "TREESYSM.SAL" module:

;	     "Version 4.00 (C) Copyright 1988 Microsoft
;	     "Licensed Material - Program Property of Microsoft

;****************** END OF SPECIFICATIONS *****************************
	IF1				;AN000;
	    %OUT    COMPONENT=TREE, MODULE=TREE.SAL... ;AN000;
	ENDIF				;AN000;
	HEADER	<MACRO DEFINITIONS>	;AN000;
	INCLUDE PATHMAC.INC		;AN013;
; =  =	=  =  =  =  =  =  =  =	=  =
FIXLIST MACRO	LP,DOIT 		;;AN000;
	IF	LP			;;AN000;
	    DOIT			;;AN000;
	ENDIF				;;AN000;
	ENDM				;;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
HEADER	MACRO	TEXT			;;AN000;
	FIXLIST LISTPARM,.XLIST 	;;AN000;
	SUBTTL	TEXT			;;AN000;
	FIXLIST LISTPARM,.LIST		;;AN000;
	PAGE				;;AN000;
	ENDM				;;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
;				   $SALUT (0,36,41,52) ;AN000;
DOSCALL 			   MACRO FN,SF	   ;;AN000;
				   IFNB <FN>	   ;;AN000;ARE THERE ANY PARMS AT ALL?
				   IFNB <SF>	   ;;AN000;
				   MOV	AX,(FN SHL 8)+SF ;;AN000;AH=FN;AH=SF
				   ELSE 	   ;;AN000;SINCE THERE IS NO SUB FUNC
				   MOV	AH,FN	   ;;AN000;
				   ENDIF	   ;;AN000;
				   ENDIF	   ;;AN000;
				   INT	21H	   ;;AN000;
				   ENDM 	   ;;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
;	     $SALUT (0,14,19,36)   ;AN000;
	     HEADER <EQUATES - DOS FUNCTION CALLS> ;AN000;
	     INCLUDE TREEQU.INC    ;AN000;EQUATES, CONTROL BLOCKS
; =  =	=  =  =  =  =  =  =  =	=  =
LISTPARM     =	  1		   ;AN000;PERMIT LISTING
.LIST				   ;AN000;
	     HEADER <STATIC DATA AREA> ;AN000;
CSEG	     SEGMENT PARA PUBLIC 'CODE' ;AN000;
	     ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:CSEG ;AN000;AS SET BY DOS LOADER
; $SALUT (4,3,8,36)		   ;AN000;
  EXTRN SUBLIST_PARSE:WORD	   ;AN004;PARSE ERROR XX - %0

  EXTRN MSGNUM_VOL:WORD 	   ;AN000;"Directory PATH listing for Volume %1"
  EXTRN SUBLIST_VOL:WORD	   ;AN000;SUBLIST TO VOL LABEL IN FIX_DTA_FILN

  EXTRN MSGNUM_LIST:WORD	   ;AN000;"Directory PATH listing"

  EXTRN MSGNUM_INVPATH:WORD	   ;AN000;"INVALID PATH"
  EXTRN SUBLIST_INVPATH:WORD	   ;AN014;THE ASCIIZ PATH CONSIDERED INVALID

  EXTRN MSGNUM_EXTERR:WORD	   ;AN000;ALL EXTENDED ERRORS
  EXTRN MSGNUM_NOSUB:WORD	   ;AN000;"No subdirectories exists"

  EXTRN MSGNUM_SERNO:WORD	   ;AN001;"Volume Serial Number is %1-%2"
  EXTRN SUBLIST_6A:WORD 	   ;AN001;FIRST PART OF SERIAL NUMBER
  EXTRN SUBLIST_6B:WORD 	   ;AN001;SECOND PART OF SERIAL NUMBER

  EXTRN CURRENT_PARM:WORD	   ;AN000;POINT TO NEXT PARM TO PARSE
  EXTRN ORDINAL:WORD		   ;AN000;NUMBER OF CURRENT PARM
  EXTRN LAST_BYTE:BYTE		   ;AN000;TAG AT END OF USED MEMORY, BEFORE STACK

  EXTRN SYSDISPMSG:NEAR 	   ;AN000;MESSAGE DISPLAY ROUTINE
  EXTRN SYSLOADMSG:NEAR 	   ;AN000;SYSTEM MESSAGE LOADER
  EXTRN SYSGETMSG:NEAR		   ;AN002;SYSTEM MESSAGE LOCATER ROUTINE
  EXTRN PARSER:NEAR		   ;AN000;INTERROGATE DOS COMMAND LINE PARMS
; =  =	=  =  =  =  =  =  =  =	=  =
;	     $SALUT (0,14,19,36)   ;AN000;
	     ORG  80H		   ;AN000;
	     PUBLIC COMMAND	   ;AN000;
COMMAND      DB   128 DUP (?)	   ;AN000;DOS INPUT COMMAND LINE
; =  =	=  =  =  =  =  =  =  =	=  =
	     ORG  100H		   ;AN000;REQUIRED LOCATION OF ENTRY POINT
START:	     JMP  BEGIN 	   ;AN000;DOS ENTRY POINT
; =  =	=  =  =  =  =  =  =  =	=  =
;THERE ARE TWO SETS OF DEFINITIONS OF THE GRAPHIC CHARACTERS USED IN THE DISPLAY.
;THE FIRST SET LOOKS THE BEST, BUT ON SOME PRINTERS IS A TEDIOUS, SLOW PROCESS.
;THERE ARE SOME CODEPAGES THAT DO NOT HAVE THESE SAME GRAPHIC CHARACTERS IN
;THESE CORRESPONDING CODE POINT POSITIONS.  JAPAN HAS ITS KATAKANA CHARACTER
;SET WHERE THESE GRAPHICS ARE DEFINED, AND WOULD THUS NOT WANT TO USE THIS
;FIRST GRAPHIC CHARACTERS SET.	THE SECOND SET OF EQUATES DEFINE ALTERNATE
;CHARACTERS THAT, ALTHOUGH THE OUTPUT DOES NOT LOOK AS GOOD, AT LEAST WILL
;PRINT NORMALLY, AND DOES USE THE TRADITIONAL ASCII LOWER 128 AS ITS CODE
;POINTS, THUS WOULD BE AVAILABLE FOR THOSE OTHER CODEPAGES, LIKE JAPAN'S.

;IF IT BECOMES DESIRABLE TO GENERATE YET ANOTHER DEFINITION OF THESE CHARACTERS,
;THE REQUIREMENTS ARE:
;	1. NONE OF THE FOUR CAN BE BLANK
;	2. EACH OF THE FOUR MUST BE UNIQUE
;	3. EACH CHAR MUST BE A SINGLE BYTE (NO DBCS)

;		GRAPHIC CHARACTERS
;THIS SET OF GRAPHIC CHARACTERS ARE ACTUALLY DEFINED BY THE MESSAGE 7,
;WHERE TRANSLATORS HAVE PROVIDED THE CHARACTERS COMPATABLE WITH THEIR
;NATIONAL CHARACTER CODEPAGE SET.
GRAF_TABLE   LABEL BYTE 	   ;AN002;DEFINITION OF FOUR GRAPHIC CHARACTERS
	     PUBLIC GRAF_TABLE	   ;AN002;
GRAF_ELBO    DB   "�"		   ;AN000;192 DECIMAL ASCII VAL
GRAF_DASH    DB   "�"		   ;AN000;196 DECIMAL ASCII VALUE
GRAF_TEE     DB   "�"		   ;AN000;195 DECIMAL ASCII VALUE
GRAF_BAR     DB   "�"		   ;AN000;179 DECIMAL ASCII VALUE


;		ALTERNATE SET OF GRAPHIC CHARACTERS
;IF THE "/A" SWITCH IS SPECIFIED, THIS SET OF FOUR CHARACTERS WILL
;OVERLAY THE ABOVE SET OF GRAPHIC CHARACTERS.

GRAF_TABLE_ALT LABEL BYTE	   ;AN002;ALTERNATE SET OF GRAPHIC CHARACTERS
	     PUBLIC GRAF_TABLE_ALT ;AN002;
A_GRAF_ELBO  DB   "\"		   ;AN000;
A_GRAF_DASH  DB   "-"		   ;AN000;
A_GRAF_TEE   DB   "+"		   ;AN000;
A_GRAF_BAR   DB   "|"		   ;AN000;

; =  =	=  =  =  =  =  =  =  =	=  =
FLAGS	     DB   0		   ;AN000;INITIALIZE ALL FLAGS TO "FALSE"
	     PUBLIC FLAGS,F_SWITCH ;AN000;ADD ENTRIES IN LINK MAP
F_DEF_PAT_TAR EQU 40H		   ;AN008;IF ON, DEFAULT SUBDIR OF TARGET DRIVE IS KNOWN
				   ;IF OFF, DEF SUBDIR OF TARGET NOT KNOWN     ;AN008;
F_SUBDIR     EQU  20H		   ;AN000;IF ON, A SUBDIR HAS BEEN DISPLAYED
				   ;IF OFF, A SUBDIR HAS NOT YET BEED DISPLAYED
F_FAILING    EQU  10H		   ;AN000;IF ON, DO NOT RESTORE SUBDIR ON FAILING DRIVE
				   ;IF OFF, DO RESTORE SUBDIR ON TARGET DRIVE	;AN000;
F_FLN	     EQU  08H		   ;AN000;IF ON, A FILENAME HAS BEEN DISPLAYED
				   ;IF OFF, NO FILNAME FOR THIS SUBDIR YET
F_FIRSTIME   EQU  04H		   ;AN000;IF ON, DISPLAY OF NAME ALREADY DONE
				   ;IF OFF, DISPLAY OF NAME NEVER DONE
F_SWITCH     EQU  02H		   ;AN000;IF ON, THE /F SPECIFIED
				   ;IF OFF, THEN /F NOT SPECIFIED
F_APPEND     EQU  01H		   ;AC006;IF ON, DOS APPEND IS IN THE MULTIPLEXOR
				   ;IF OFF, DOS APPEND IS NOT THE MULTIPLEXOR

APPEND_FLAGS DW   0		   ;AN006;RECORDS ORIGINAL STATE OF APPEND
				   ;8000H = /X:1
				   ;4000H = /E
				   ;2000H = /PATH:1
				   ;1000H = /DRIVE:1
				   ;0001H = ENABLE APPEND

DBCSENV      DD   0		   ;AN000;POINTER TO DBCS RANGES
ORIG_AX      DW   0		   ;AN000;DRIVE VERIFICATION FROM DOS AT ENTRY
CURRENT_COL  DW   1		   ;AN000;IN BUF, WHERE IS ELBO/TEE?
				   ; INITIALLY SET TO START IN COLUMN ONE
MEDIA_ID_BUF A_MEDIA_ID_INFO <>    ;AN001;AREA TO READ VOL SERIAL NUMBER WITH GET_MEDIA_ID
BUF	     DB   ((DASH_NUM+1)*LEVEL_LIMIT) DUP(0) ;AN000;HAS ELBO,TEE,DASH,NUL ENDED
JUSTIN_CASE  DB   64 DUP(0)	   ;AN000;CATCHES THE OVERFLOW
CRLF	     DB   CR,LF,NUL	   ;AN000;LINE TERMINATOR
LEN_CRLF     EQU  2		   ;AN000;LENGTH OF CR, LF FIELDS IN PREVIOUS MSG
EXITFL	     DB   EXOK		   ;AN000;RETURN CODE, INITIALLY "NORMAL"
;	   (SEE INCLUDED FILE OF EQUATES FOR DEFINITIONS OF VALUES)

;		REMEMBER THE DOS DEFAULT DRIVE AND SUBDIRECTORY
DEFAULT_DR   DB   ?		   ;AN000;ALPHA LETTER OF DOS DEFAULT DRIVE
START_DR_NUM DB   ?		   ;AN000;NUMERIC VALUE OF DOS DEFAULT DRIVE
				   ; WHERE 0=A:, 1=B:, ETC...
DEFAULT_PATH DB   BACK_SLASH	   ;AN000;FIRST BYTE OF PATH IS BACKSLASH
	     DB   MAX_PATH DUP(0)  ;AN000;ORIGINAL DEFAULT PATH
JUSTIN_CASE2 DB   64 DUP(0)	   ;AN000;CATCHES THE OVERFLOW
OLDINT23     DD   ?		   ;AN000;ORIGINAL CONTENTS OF CTRL-BREAK VECTOR
OLDINT24     DD   ?		   ;AN000;ORIGINAL CONTENTS OF CRITICAL ERROR VECTOR

FIX_DTA_RES  DB   21 DUP(?)	   ;AN000;RESERVED FOR FIND NEXT CALLS
FIX_DTA_ATTR DB   ?		   ;AN000;ATTRIBUTE
FIX_DTA_TIME DW   ?		   ;AN000;TIME
FIX_DTA_DATE DW   ?		   ;AN000;DATE
FIX_DTA_LSIZ DW   ?		   ;AN000;LOW WORD OF FILE SIZE
FIX_DTA_HSIZ DW   ?		   ;AN000;HIGH WORD OF FILE SIZE
FIX_DTA_FILN DB   13 DUP(?)	   ;AN000;FILENAME, WITH PERIOD, +0 BYTE
	     PUBLIC FIX_DTA_FILN   ;AN000;USED TO DISPLAY VOLUME LABEL
STAR_STAR    DB   "*.*",0	   ;AN000;UNIVERSAL FILENAME, +0
STAR_STAR_L  EQU  $-STAR_STAR	   ;AN000;LENGTH OF UNIVERSAL FILENAME, INCL NUL
SAVEFILN     DB   13 DUP(?)	   ;AN000;COPY OF FIX_DTA_FILN, ABOVE
;	 THIS NEXT SET OF WORKSPACE DEFINES THE PATH BEING PROCESSED.
;	 THESE ITEMS MUST REMAIN TOGETHER, IN THIS ORDER:
START_DRIVE  DB   0,":" 	   ;AN000;DRIVE LETTER NEEDS TO BE FILLED IN HERE
	     PUBLIC START_DRIVE,START_PATH ;AN000;
START_PATH   DB   PERIOD	   ;AN000;AREA TO RECEIVE STARTING PATH ASCIIZ
	     DB   (MAX_PATH+SIZE FIX_DTA_FILN) DUP(0) ;AN000;
JUSTIN_CASE3 DB   64 DUP(0)	   ;AN000;CATCHES THE OVERFLOW
;	END OF CONTIGUOUS WORKSPACE DEFINING PATH
; =  =	=  =  =  =  =  =  =  =	=  =
	     PATHLABL TREE	   ;AN013;
	     HEADER <BEGIN - VERSION CHECK, SYSMSG INIT, EXIT TO DOS> ;AN000;
; $SALUT (4,3,8,36)		   ;AN000;
BEGIN PROC NEAR 		   ;AN000;
  PUBLIC BEGIN			   ;AN000;
;INPUT - DOS COMMAND LINE PARMS, AS DEFINED IN MODULE PROLOG.
;	  CONTROL IS PASSED HERE FROM "START" AT ORG 100H.
;	 AX IS SET BY DOS TO FLAG ANY INVALID DRIVE SPECIFIED ON PARMS.
;OUTPUT - "EXITFL" HAS ERRORLEVEL RETURN CODE
; =  =	=  =  =  =  =  =  =  =	=  =

  MOV  ORIG_AX,AX		   ;AN000;SAVE ORIGINAL VALUE OF AX

;SINCE THIS IS A .COM STYLE UTILITY, THE SEG ID IN THE MSG SUBLIST
;CANNOT BE SET BY THE LOADER, BUT MUST BE SET HERE, AT RUN TIME.

  MOV  SUBLIST_VOL.SUB_VALUE_SEG,CS ;AN000;MAKE SUBLIST VARIABLE ADDRESSABLE
  MOV  SUBLIST_6A.SUB_VALUE_SEG,CS ;AN001;
  MOV  SUBLIST_6B.SUB_VALUE_SEG,CS ;AN001;
  MOV  SUBLIST_PARSE.SUB_VALUE_SEG,CS ;AN004;
  MOV  SUBLIST_INVPATH.SUB_VALUE_SEG,CS ;AN014;

  CALL SYSLOADMSG		   ;AN000; INIT SYSMSG HANDLER

; $IF  C			   ;AN000; IF THERE WAS A PROBLEM
  JNC $$IF1
      CALL SYSDISPMSG		   ;AN000; LET HIM SAY WHY HE HAD A PROBLEM

      MOV  EXITFL,EXVER 	   ;AN000; TELL ERRORLEVEL BAD DOS VERSION
; $ELSE 			   ;AN000; SINCE SYSDISPMSG IS HAPPY
  JMP SHORT $$EN1
$$IF1:
      CLD			   ;AN000;CLEAR DIRECTION FLAG TO AUTO-INCREMENT

;		GET CURRENT DRIVE ID
      DOSCALL CURRDISK		   ;AN000;(19H) SET AL=0 IF A:, 1 IF B:, ETC...

      MOV  START_DR_NUM,AL	   ;AN000;SAVE NUMERIC VALUE OF DOS DEFAULT DRIVE
      ADD  AL,DRIVEA		   ;AN000;CONVERT DRIVE NUMBER TO LETTER
      MOV  DEFAULT_DR,AL	   ;AN000;REMEMBER ALPHA OF DEFAULT DRIVE
				   ; OF FILENAME TO BE SEARCHED FOR
;		    RECORD THE INITIAL SET UP
      CALL INIT_CONDITIONS	   ;AC007;SET DTA,APPEND STATUS,CAPTURE CTL-BREAK VEC


      CALL DEFINE_GRAPHICS	   ;AN002;GET PROPER GRAPHIC CHARS FROM MSG

      CALL PARSE		   ;AN000;LOOK AT DOS COMMAND LINE PARAMETERS,
				   ; AND DISPLAY ERR MSG IF BAD
;     $IF  NC			   ;AN000;PARMS ARE OK?
      JC $$IF3
;	    CURIOUS ODDITY:
;	    "CURRDISK"	  AL=0 DRIVE A:,      AL=1 DRIVE B: ETC...
;	    "GET_CUR_DIR" AL=0 DEFAULT DRIVE, AL=1 DRIVE A: ETC...
;	    "SELECT_DISK" AL=0 DRIVE A:,      AL=1 DRIVE B: ETC...
;	    SO... THE NUMBER WE HAVE HERE AGREES WITH "SELECT_DISK", BUT
;	    WE MUST ADD ONE WHEN WE DO THE "GET_CUR_DIR".

;		GET CURRENT DIRECTORY OF TARGET DRIVE
				   ;DS:SI = POINTER TO 64 BYTE USER AREA
				   ;DL = DRIVE NUM (0=DEF, 1=A, ETC)
				   ;OUTPUT: DS:SI POINTS TO FULL PATH NAME
; "DEFAULT_PATH" WILL HAVE THE DOS DEFAULT SUBDIRECTORY PATH.

	  MOV  SI,OFFSET DEFAULT_PATH+1 ;AN000;PASS 64 BYTE AREA
	  MOV  DL,START_DRIVE	   ;AN000;PASS NUMERIC VALUE
	  SUB  DL,DRIVEA	   ;AN000;  OF DRIVE TO BE SCANNED
	  INC  DL		   ;AN000;SEE "CURIOUS ODDITY" ABOVE...
	  DOSCALL GET_CUR_DIR	   ;AN000;(47H) GET THE CURRENT SDIR OF TARGET DRIVE

	  OR   FLAGS,F_DEF_PAT_TAR ;AN008;INDICATE DEFAULT PATH OF TARGET IS KNOWN


;		     DISPLAY FUNCTION HEADER
	  CALL GET_VOL_LABEL	   ;AN000;GET VOLUME LABEL TO FIX_DTA_FILN

;		     DISPLAY VOLUME SERIAL ID
	  CALL EXECUTE		   ;AN000;DISPLAY THE SET OF SUBDIRS

	  CALL ANY_SUBDIRS	   ;AN000;DISPLAY FINAL MSG IN CASE NO SUBDIRS

;     $ELSE			   ;AN000;SINCE PARMS HAD A PROBLEM,
      JMP SHORT $$EN3
$$IF3:
	  MOV  EXITFL,EXERR	   ;AN000;SET ERROR RETURN CODE
;     $ENDIF			   ;AN000;PARMS OK?
$$EN3:
;		     RESTORE SYSTEM TO INITIAL CONDITIONS
      CALL RESTORE		   ;AN007;RETURN TO INITIAL DOS DEFAULT DRIVE,
				   ; THE INITIAL DEFAULT PATH,
				   ; AND THE INITIAL "APPEND" STATE.
; $ENDIF			   ;AN000;OK WITH SYSDISPMSG?
$$EN1:

  MOV  AL,EXITFL		   ;AN000;PASS BACK ERRORLEVEL RET CODE
  DOSCALL RET_CD_EXIT		   ;AN000;(4CH) RETURN TO DOS WITH RET CODE

  INT  20H			   ;AN000; IF ABOVE NOT WORK, EXIT ANYWAY

;FOR CONTROL-BREAK, "TREE" WILL EXIT TO DOS AT "CTL_BREAK" PROC
; IN STEAD OF HERE.
BEGIN ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <DEFINE_GRAPHICS - GET GRAPHIC CHARS FROM MSG> ;AN002;
DEFINE_GRAPHICS PROC NEAR	   ;AN002;
  PUBLIC DEFINE_GRAPHICS	   ;AN002;
;INPUT - MESSAGE 7 HAS THE FOUR GRAPIC CHARS, DEFINED BY THE TRANSLATORS
;	 TO BE ACCEPTABLE TO THIS NATIONAL CODEPAGE.
;OUTPUT- THE "GRAF_TABLE" AREA IS Revised TO HAVE THE 4 GRAPHIC CHARS
;	 AS DEFINED BY THE MESSAGE
; =  =	=  =  =  =  =  =  =  =	=  =
;		DEFINE THE GRAPHIC CHARACTERS
  MOV  AX,GRAPHIC_MSGNUM	   ;AN002;REQUEST THE MESSAGE WITH GRAPHIC CHAR DEFS
  MOV  DH,UTILITY_MSG_CLASS	   ;AN002;
  CALL SYSGETMSG		   ;AN002;ASK WHERE THOSE GRAPHIC CHARS ARE
				   ;IF ANY PROBLEM HERE, JUST LEAVE
				   ; THE GRAPHICS AS DEFINED AT ASSEMBLY TIME.
; $IF  NC			   ;AN002;IF ALL OK, DS:SI POINTS TO MESSAGE
  JC $$IF7
      LEA  DI,GRAF_TABLE	   ;AN002;POINT TO WHERE GRAPHIC CHARS ARE TO GO
      LODSW			   ;AN002;GET FIRST PAIR OF CHARS
      STOSW			   ;AN002;SAVE THEM
      LODSW			   ;AN002;GET SECOND PAIR OF CHARS
      STOSW			   ;AN002;AND SAVE THEM ALSO
; $ENDIF			   ;AN002;
$$IF7:
  RET				   ;AN002;
DEFINE_GRAPHICS ENDP		   ;AN002;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <PARSE - TOKENIZE THE DOS COMMAND LINE PARMS> ;AN000;
PARSE PROC NEAR 		   ;AN000;
  PUBLIC PARSE			   ;AN000;
;INPUT - PSP HAS DOS COMMAND LINE PARAMETERS
;OUTPUT- CARRY IS SET IF THERE IS A PROBLEM
;	 CARRY IS CLEAR IF PARMS ARE OK

;	 IF THERE WERE ANY PARMS, THEY ARE MOVED FROM THE PSP
;	   INTO THE STRING, "COMMAND", WHERE THE PARSER WILL LOOK AT THEM.

;	 IF THE SWITCH "/F" WAS SPECIFIED, "F_SWITCH" IS SET TO "ON"
;	 IF THE SWITCH IS NOT SPECIFIED, "F_SWITCH" IS LEFT "OFF".

;	 IF THERE ARE NO PARMS, THE DEFAULTS OF CURRENT DRIVE AND CURRENT
;	   SUBDIRECTORY ARE SET UP TO BE WHERE THE SUBDIR SEARCH WILL
;	   START, AND THE "/F" SWITCH IS ASSUMED NOT SPECIFIED, SO
;	   THE DEFAULT DISPLAY WILL SHOW SUBDIRS ONLY, NO FILES.

;	 "START_DRIVE" EITHER HAS THE SPECIFIED STARTING DRIVE, OR
;		WILL HAVE THE CURRENT DOS DEFAULT DRIVE.
;	 "START_PATH" EITHER WILL HAVE THE SPECIFIED STARTING PATH, OR
;		WILL HAVE THE CURRENT DEFAULT PATH
; =  =	=  =  =  =  =  =  =  =	=  =

  MOV  CURRENT_PARM,OFFSET COMMAND+1 ;AN000;SET POINT TO BEGINNING OF STRING
  MOV  ORDINAL,ZERO		   ;AN000;START WITH FIRST PARM
  CALL PARSER			   ;AN000;INTERROGATE THE DOS COMMAND LINE PARMS
				   ;OUTPUT: SET CARRY IF PROBLEM
				   ;	    CLEAR CARRY IF ALL OK
; $IF  NC			   ;AN000;IF ALL OK SO FAR WITH PARSER,
  JC $$IF9
      CMP  START_DRIVE,NUL	   ;AN000;SEE IF START_DRIVE FILLED IN YET
;     $IF  E			   ;AN000;NO, NOT FILLED IN YET
      JNE $$IF10
	  MOV  AL,DEFAULT_DR	   ;AN000;GET ALPHA LETTER OF DEFAULT DRIVE
	  MOV  START_DRIVE,AL	   ;AN000;SET WHERE TO SEARCH FOR SUBDIRS
	  CLC			   ;AN000;NO ERROR SO FAR
;     $ELSE			   ;AN000;SINCE START_DRIVE WAS SPECIFIED
      JMP SHORT $$EN10
$$IF10:
	  CALL VERIFY_DRIVE	   ;AN000;SEE IF USER SPECIFIED DRIVE IS OK, AND
				   ; IF SO, CHANGE DOS DEFAULT DRIVE TO IT
				   ;CARRY WILL BE SET IF ERROR

				   ;IF A NEW DRIVE WAS SPECIFIED,
				   ; DEFAULT DRIVE HAS BEEN CHANGED TO
				   ; NEW DEFAULT DRIVE, USER SPECIFIED

;     $ENDIF			   ;AN000;FILLED IN START_DRIVE YET?
$$EN10:
;     $IF  NC			   ;AN000;IF ALL OK SO FAR,
      JC $$IF13
	  CMP  START_PATH,NUL	   ;AN000;SEE IF START_PATH FILLED IN YET
;	  $IF  E		   ;AN000;NO, NOT FILLED IN YET,
	  JNE $$IF14
	      MOV  DI,OFFSET START_PATH ;AN000;SET WHERE TO PUT STARTING PATH
	      MOV  AL,BACK_SLASH   ;AN000;START CURRENT SUBDIR AT ROOT
	      STOSB		   ;AN000;  SO START WITH BACK SLASH

				   ;DI POINTS TO BYTE AFTER BACK SLASH
				   ; JUST ADDED TO "START_PATH"

	      MOV  SI,DI	   ;AN000;DS:SI = POINTER TO 64 BYTE USER AREA
	      MOV  DL,DEFDRIVE	   ;AN000;DL = DRIVE NUM (0=DEF, 1=A, ETC)
	      DOSCALL GET_CUR_DIR  ;AN000;(47H) GET CURRENT DIRECTORY
				   ;OUTPUT: DS:SI POINTS TO FULL PATH NAME
;	  $ENDIF		   ;AN000;START_PATH FILLED IN YET?
$$IF14:
	  CLC			   ;AN000;INDICATE NO PROBLEM WITH PARMS
;     $ENDIF			   ;AN000;ALL OK SO FAR?
$$IF13:
; $ENDIF			   ;AN000;ALL OK WITH PARSER?
$$IF9:
  RET				   ;AN000;RETURN TO CALLER
PARSE ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <VERIFY_DRIVE - CHECK IF USER DRIVE ID IS OK> ;AN000;
VERIFY_DRIVE PROC NEAR		   ;AN000;
  PUBLIC VERIFY_DRIVE		   ;AN000;
;THE USER HAS SPECIFIED A DRIVE LETTER.  VERIFY IT IS A PROPER DRIVE.
;IF THE DRIVE LETTER SPECIFIED IS THE SAME AS THE DEFAULT DRIVE, IT IS OK.
;IF DIFFERENT, ADDITIONAL VERIFICATION TESTS MUST BE MADE.
;THIS TEST IS DONE BY TRYING TO CHANGE THE CURRENT DRIVE TO THE SPECIFIED
; DRIVE, THEN BY ASKING WHAT IS THE CURRENT DRIVE.  IF THE CURRENT DRIVE
; HAS CHANGED FROM WHAT IT WAS ORIGINALLY, THEN THE NEW DRIVE LETTER IS OK.
; IF IT DID NOT CHANGE, THEN IT WAS A BOGUS DRIVE LETTER AND WE QUIT.

;INPUT: "START_DRIVE" - USER SPECIFIED DRIVE LETTER TO BE TESTED
;	"DEFAULT_DR" - ORIGINAL DOS DEFAULT DRIVE
;	"START_DR_NUM" - NUMERIC EQUIVALENT OF THE ORIGINAL DOS DEFAULT DRIVE
;	"ORIG_AX" - HAS FLAGS TO VERIFY DRIVE, SET BY DOS AT LOAD TIME.
;OUTPUT: CARRY SET IF BAD, CARRY CLEAR IF OK
;	IF BAD, ERROR MESSAGE IS DISPLAYED: "INVALID DRIVE SPECIFICATION"
; =  =	=  =  =  =  =  =  =  =	=  =
  MOV  DL,START_DRIVE		   ;AN000;USING THE DRIVE SPECIFIED IN PARMS,
  CMP  DL,DEFAULT_DR		   ;AN000;DID PARMS SPECIFY DRIVE SAME AS DEFAULT?
; $IF  NE			   ;AN000;IF DRIVE SPECIFIED IS DIFFERENT
  JE $$IF18
      MOV  AX,ORIG_AX		   ;AN000;GET DRIVE VERIFICATION FLAGS, SAVED FROM AX
      OR   AL,AH		   ;AN000;COMBINE FLAGS FOR BOTH DRIVE ID'S, IF GIVEN
;     $IF  NZ,OR		   ;AN000;IF THERE IS A PROBLEM, OR...
      JNZ $$LL19

      SUB  DL,DRIVEA		   ;AN000;CONVERT DRIVE LETTER TO DRIVE NUMBER
				   ; DL=DRIVE NUMBER (0=A,1=B)
      DOSCALL SELECT_DISK	   ;AN000;(0EH) SET DEFAULT DRIVE
				   ;OUTPUT: AL=NUM. OF DRIVES (MIN 5) (NOT USED);AN000;
				   ; (NOT INTERESTED...)
      DOSCALL CURRDISK		   ;AN000;(19H) GET CURRENT DEFAULT DRIVE
				   ;OUTPUT: AL = CURRENT DRIVE
				   ;  0=A,1=B,ETC.
      CMP  AL,START_DR_NUM	   ;AN000;HAS THE ORIGINAL DOS DEFAULT DRIVE CHANGED?
      CLC			   ;AN000;NO ERROR
;     $IF  E			   ;AN000;IF NO CHANGE, THEN USER SPECIFIED
      JNE $$IF19
$$LL19:
				   ; INVALID DRIVE
	  MOV  MSGNUM_EXTERR,INVDRSPEC ;AN000;"INVALID DRIVE SPECIFICATION"
	  MOV  DI,OFFSET MSGNUM_EXTERR ;AN000;
	  CALL SENDMSG		   ;AN000;TELL USER HE SAID BAD DRIVE LETTER

	  STC			   ;AN000;RETURN AN ERROR
;     $ENDIF			   ;AN000;NO CHANGE?
$$IF19:
; $ELSE 			   ;AN000;SINCE DRIVE SPECIFIED IS THE SAME
  JMP SHORT $$EN18
$$IF18:
      CLC			   ;AN000;NO ERROR
; $ENDIF			   ;AN000;NEW DRIVE SPECIFIED?
$$EN18:
  RET				   ;AN000;RETURN TO CALLER
VERIFY_DRIVE ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <INIT_CONDITIONS - GET INITIAL SUBDIR, APPEND,CTL_BREAK> ;AN000;
INIT_CONDITIONS PROC NEAR	   ;AN000;
  PUBLIC INIT_CONDITIONS	   ;AN000; MAKE ENTRY IN LINK MAP
;INPUT	- "START_DR_NUM" WILL HAVE THE NUMERIC VALUE OF DOS DEFAULT DRIVE.
;	- "DEFAULT_DR" WILL HAVE THE LETTER DRIVE ID OF DOS DEFAULT DRIVE.
;OUTPUT - "APPEND_FLAGS" RECORDS ORIGINAL STATUS OF /X OF APPEND.
;		APPEND IS COMMANDED TO HALT ITS /X PROCESSING.
;	  CONTROL BREAK VECTOR IS ALTERED TO POINT TO MY HANDLER.
; =  =	=  =  =  =  =  =  =  =	=  =
;		SET UP THE LOCAL DTA
  MOV  DX,OFFSET FIX_DTA_RES	   ;AN000;PASS POINTER TO DTA BUFFER
  DOSCALL SET_DTA		   ;AN000;(1AH) SET DTA FOR FIND FIRST/NEXT
;		GET CURRENT APPEND STATUS
  MOV  AX,APPEND_CHECK		   ;AN006;SEE IF APPEND IS ACTIVE
  INT  2FH			   ;AN006;CALL THE MULTIPLEXOR FUNCTION

  OR   AL,AL			   ;AN006;TEST THE RESULTS
; $IF  NZ,AND			   ;AN006;IF INSTALLED
  JZ $$IF23

  MOV  AX,APPEND_VERSION	   ;AN006;ASK IF DOS VERSION OF APPEND
  INT  2FH			   ;AN006;CALL THE MULTIPLEXOR FUNCTION
  CMP  AX,DOS_APPEND_VER	   ;AN006;IS THIS THE DOS VERSION OF APPEND
; $IF  E			   ;AN006;YES, DEAL WITH THIS VERSION
  JNE $$IF23
      OR   FLAGS,F_APPEND	   ;AN000;FLAG IT AS THE DOS VERSION
      MOV  AX,GET_APPEND	   ;AN000;
      INT  2FH			   ;AN000;READ STATUS OF /X FROM APPEND
				   ;OUTPUT-BX=(SEE "APPEND_FLAGS" FOR DEFINITION
      MOV  APPEND_FLAGS,BX	   ;AC006;REMEMBER APPEND STATUS
; $ENDIF			   ;AN000;APPEND INSTALLED?
$$IF23:


;		CAPTURE THE CRITICAL ERROR VECTOR
  PUSH ES			   ;AN000;SAVE SEGREG
				   ;AL = INTERRUPT NUMBER
  DOSCALL GET_VECTOR,VEC_CRITERR   ;AN000;(3524H) GET INTERRUPT VECTOR
				   ;OUTPUT: ES:BX = CONTENTS OF VECTOR
  MOV  WORD PTR OLDINT24,BX	   ;AN000;SAVE THE ORIGINAL
  MOV  WORD PTR OLDINT24+WORD,ES   ;AN000; CRITICAL ERROR HANDLER VECTOR
  POP  ES			   ;AN000;RESTORE SEGREG

  MOV  DX,OFFSET MYERRORHANDLER    ;AN000;DS:DX = VECTOR TO INT HANDLER
				   ;AL = INTERRUPT NUMBER
  DOSCALL SET_VECTOR,VEC_CRITERR   ;AN000;(25H) SET INTERRUPT VECTOR

;		CAPTURE THE CONTROL BREAK VECTOR
  PUSH ES			   ;AN000;SAVE SEGREG
				   ;AL = INTERRUPT NUMBER
  DOSCALL GET_VECTOR,VEC_CTLBREAK  ;AN000;(3523H) GET INTERRUPT VECTOR
				   ;OUTPUT: ES:BX = CONTENTS OF VECTOR
  MOV  WORD PTR OLDINT23,BX	   ;AN000;SAVE THE ORIGINAL
  MOV  WORD PTR OLDINT23+WORD,ES   ;AN000; CTRL-BREAK VECTOR
  POP  ES			   ;AN000;RESTORE SEGREG

  MOV  DX,OFFSET BREAK_HANDLER	   ;AN000;DS:DX = VECTOR TO INT HANDLER
				   ;AL = INTERRUPT NUMBER
  DOSCALL SET_VECTOR,VEC_CTLBREAK  ;AN000;(25H) SET INTERRUPT VECTOR

;		STOP THE APPEND FUNCTION.
  MOV  AX,SET_APPEND		   ;AN000;CHANGE APPEND /X STATUS
  XOR  BX,BX			   ;AN000;REQUEST TERMINATION OF /X SUPPORT OF APPEND
  INT  2FH			   ;AN000;SET IT

  RET				   ;AN000;RETURN TO CALLER
INIT_CONDITIONS ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <GET_VOL_LABEL - GET VOLUME LABEL ON SPECIFIED DRIVE> ;AN000;
GET_VOL_LABEL PROC NEAR 	   ;AN000;
  PUBLIC GET_VOL_LABEL		   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - "START_PATH" IS ASCIIZ OF STARTING PATH
;OUTPUT - "FIX_DTA_FILN" WILL HAVE ASCIIZ STRING OF VOLUMN LABEL.
;	  STARTING DRIVE AND PATH TO SPECIFIED SUBDIR IS DISPLAYED.
; =  =	=  =  =  =  =  =  =  =	=  =

  MOV  CX,ATTR_VOLID		   ;AN000;REQUEST THE VOLUME ID
  MOV  DX,OFFSET STAR_STAR	   ;AN000;PASS FILENAME TO BE LOOKED FOR
  DOSCALL FINDFIRST		   ;AN000;LOOK FOR VOLUME LABEL

; $IF  NC			   ;AN000;IF LABEL FOUND OK,
  JC $$IF25

				   ;FIX_DTA_FILN HAS VOLUME LABEL
      MOV  DI,OFFSET MSGNUM_VOL    ;AN000; "Directory PATH listing for Volume %1"
      MOV  AX,WORD PTR FIX_DTA_FILN+9 ;AN005;CONVERT LABELNAME FROM
      MOV  WORD PTR FIX_DTA_FILN+8,AX ;AN005;	12345678.123 FORMAT
      MOV  AX,WORD PTR FIX_DTA_FILN+11 ;AN005;	TO REMOVE PERIOD
      MOV  WORD PTR FIX_DTA_FILN+10,AX ;AN005;	TO BECOME 12345678123 INSTEAD
; $ELSE 			   ;AN000;SINCE LABEL NOT FOUND,
  JMP SHORT $$EN25
$$IF25:
      MOV  DI,OFFSET MSGNUM_LIST   ;AN000; "Directory PATH listing"
; $ENDIF			   ;AN000;LABEL FOUND?
$$EN25:
  CALL SENDMSG			   ;AN000;DISPLAY STARTING MESSAGE

  CALL VOLSER			   ;AN001;DISPLAY VOLUME SERIAL NUMBER, IF ANY


;		DISPLAY THE STARTING DRIVE AND SUBDIRECTORY
  MOV  DX,OFFSET START_DRIVE	   ;AN000;PASS POINTER TO STRING TO BE DISPLAYED
  CALL LEN_ASCIIZ		   ;AN000;SETS CX = NUMBER OF BYTES TO WRITE

				   ;DS:DX = ADDRESS OF DATA TO WRITE
  CALL DO_WRITE 		   ;AN000;DISPLAY STARTING SUBDIR TO STDOUT

  RET				   ;AN000;RETURN TO CALLER
GET_VOL_LABEL ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <VOLSER - DISPLAY VOLUME SERIAL NUMBER, IF ANY> ;AN001;
VOLSER PROC NEAR		   ;AN001;
  PUBLIC VOLSER 		   ;AN001;
;IF THE MEDIA SUPPORTS A VOL SERIAL NUMBER, DISPLAY IT
; =  =	=  =  =  =  =  =  =  =	=  =
;	       ISSUE GET MEDIA ID
  MOV  BH,ZERO			   ;AN001;BH=0, RES
  MOV  BL,START_DRIVE		   ;AN001;GET LETTER OF DRIVE BEING LOOKED AT
  SUB  BL,DRIVEA-1		   ;AN001;(BACK UP 40H) BL=DRIVE NUM (1=A:, 2=B:, ETC)
  MOV  DX,OFFSET MEDIA_ID_BUF	   ;AN001;DS:DX=BUFFER (see A_MEDIA_ID_INFO STRUC)
  DOSCALL GSET_MEDIA_ID,GET_ID	   ;AC010;(6900H) GET MEDIA ID
				   ;CARRY SET ON ERROR (OLD STYLE BOOT RECORD)

; $IF  NC			   ;AN001;IF THE GET MEDIA ID WORKED OK,
  JC $$IF28

; NOTE: IN THE FOLLOWING TWO SUBLISTS, WE ARE GOING TO DISPLAY, IN HEX,
; A CONSECUTIVE SET OF 4 BYTES, THE VOLUME SERIAL NUMBER.  THE ORDER OF
; THESE TWO WORDS OF HEX IS, LEAST SIGNIFICANT WORD FIRST, THEN THE
; MOST SIGNIFICANT WORD.  WHEN DISPLAYED, THE MOST SIGNIFICANT IS TO BE
; DISPLAYED FIRST, SO THE VALUE AT SERIAL+2 GOES TO THE 6A SUBLIST,
; AND THE LEAST SIGNIFICANT VALUE AT SERIAL+0 GOES TO THE SECOND POSITION,
; REPRESENTED BY THE 6B SUBLIST.

      LEA  AX,MEDIA_ID_BUF.MI_SERIAL ;AN001;GET POINTER TO DATA TO BE PRINTED
      MOV  SUBLIST_6B.SUB_VALUE,AX ;AN001; INTO THE SUBLIST FOR %2

      LEA  AX,MEDIA_ID_BUF.MI_SERIAL+WORD ;AN001;GET POINTER TO DATA TO BE PRINTED
      MOV  SUBLIST_6A.SUB_VALUE,AX ;AN001; INTO THE SUBLIST FOR %1

				   ;"Volume Serial Number is %1-%2"
      MOV  DI,OFFSET MSGNUM_SERNO  ;AN001;DISPLAY THE NEW SERIAL NUMBER
      CALL SENDMSG		   ;AN001;DISPLAY THE MESSAGE

; $ENDIF			   ;AN001;IS VOL SERIAL NUM PRESENT?
$$IF28:
  RET				   ;AN001;RETURN TO CALLER
VOLSER ENDP			   ;AN001;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <LEN_ASCIIZ - GET LENGTH OF ASCIIZ STRING> ;AN000;
LEN_ASCIIZ PROC NEAR		   ;AN000;
  PUBLIC LEN_ASCIIZ		   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - ES:DX = POINTS TO START OF ASCIIZ STRING
;OUTPUT - CX = LENGTH OF CHARACTERS, INCLUDING THE NUL AT THE END
; =  =	=  =  =  =  =  =  =  =	=  =

  PUSH AX			   ;AN000;SAVE THE CALLER'S
  PUSH DI			   ;AN000; REGISTERS
  MOV  CX,FULL_SEG_SIZE 	   ;AN000;BETTER FIND THAT NUL SOMEWHERE...
  MOV  DI,DX			   ;AN000;SET INDEX TO WALK THRU THE STRING
  MOV  AL,NUL			   ;AN000;THIS IS THE CHAR I AM LOOKING FOR
  REPNE SCASB			   ;AN000;LOOK FOR IT

  SUB  DI,DX			   ;AN000;TAKE AWAY WHERE WE STARTED, FROM WHERE WE AT
  MOV  CX,DI			   ;AN000; TO FIND NOW FAR WE MOVED
  POP  DI			   ;AN000;RESTORE THE CALLER'S
  POP  AX			   ;AN000; REGISTERS

  RET				   ;AN000;RETURN TO CALLER
LEN_ASCIIZ ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <EXECUTE - LOOK THRU DIRECTORY LIST FOR SUBDIRS> ;AN000;
EXECUTE PROC NEAR		   ;AN000;
  PUBLIC EXECUTE		   ;AN000;MAKE ENTRY IN LINK MAP
;BECAUSE OF THE RECURSIVE NATURE OF THIS ROUTINE, ALL ITS LOCAL WORKAREA
;MUST BE DYNAMICALLY ALLOCATED BY USING A PORTION OF THE STACK.  AS EACH
;LOWER LEVEL OF STACK IS PROCESSED, A NEW CALL IS MADE TO THIS SUBROUTINE
;WHICH THEN CREATES A NEW WORKAREA FOR THAT SUBDIRECTORY.
;THE CURRENT STACK SIZE IS CHECKED TO SEE IF THERE IS ENOUGH ROOM FOR
;THE NEW STACK WORKAREA.
;INPUT:START_PATH - STRING OF PATHNAME OF PATH TO BE PROCESSED
;OUTPUT: WHEN THIS PROC RETURNS, ALL FILES IN THIS SUBDIR AND LOWER
;	LEVELS OF SUBDIRS HAVE BEEN PROCESSED.
; =  =	=  =  =  =  =  =  =  =	=  =

  PUSH BP			   ;AN000;SAVE CALLER'S BP REG
  SUB  SP,WA_SIZE		   ;AN000;ALLOCATE STACK SPACE AS WORKAREA
  MOV  BP,SP			   ;AN000;SET BASE FOR WORKAREA CALLED "FRAME"

  MOV  AX,BP			   ;AN000;
  SUB  AX,OFFSET LAST_BYTE	   ;AN000;WHERE MY CODE ENDS
  CMP  AX,MIN_STACK		   ;AN000;IS THE MINIMUM STACK REMAINING?
; $IF  AE			   ;AN000;IF ENUF STILL THERE, CONTINUE,
  JNAE $$IF30

      CMP  START_PATH,BACK_SLASH   ;AN000;WAS A BACKSLASH SDIR SPECIFIED,
;     $IF  NE			   ;AN000;NO BACKSLASH USED
      JE $$IF31
	  MOV  DX,OFFSET START_PATH ;AN000;POINT TO SPECIFIED PATH
	  DOSCALL CHDIR 	   ;AN000;(3BH) CHANGE CURRENT DIR

;	  $IF  NC		   ;AN000;IF CHDIR WORKED OK,
	  JC $$IF32
	      MOV  DL,START_DRIVE  ;AN000;GET TARGET DRIVE
	      SUB  DL,DRIVEA-1	;AN000;CONVERT TO NUM (A=1,B=2,ETC.)
	      LEA  SI,[BP].FRAM_CURR_PATH+1 ;AN000;WHERE TO PUT PATH
	      MOV  [BP].FRAM_CURR_PATH,BACK_SLASH ;AN000;
	      DOSCALL GET_CUR_DIR  ;AN000;FIND WHERE WE ARE NOW

	      LEA  SI,[BP].FRAM_CURR_PATH ;AN000;WHERE PATH WENT, WITH BACKSLASH
	      MOV  DI,OFFSET START_PATH ;AN000;WHERE TO PUT IT
	      MOV  CX,MAX_PATH+1 ;AN000;MOVE FULL LENGTH PLUS BACKSLASH
	      REP  MOVSB	   ;AN000; TO START_PATH

;	  $ENDIF		   ;AN000;CHDIR OK?
$$IF32:

;     $ELSE			   ;AN000;SINCE SPECIFIED PATH STARTS WITH BACKSLASH
      JMP SHORT $$EN31
$$IF31:
	  MOV  SI,OFFSET START_PATH ;AN000;USING THE STARTING PATH,
	  LEA  DI,[BP].FRAM_CURR_PATH ;AN000;SAVE IT IN THE STACK WORKAREA
				   ;(at times like this, sure is nice to
				   ; have ES=SS.  .EXE would be a problem..)
	  MOV  CX,MAX_PATH+1	;AN000;MOVE THE ENTIRE STARTING PATH+LEADING "\"
	  REP  MOVSB		   ;AN000;INTO THE WORKAREA

	  MOV  DX,OFFSET START_PATH ;AN000;POINT TO SPECIFIED PATH
	  DOSCALL CHDIR 	   ;AN000;(3BH) CHANGE CURRENT SDIR TO SPECIFIED SDIR

;     $ENDIF			   ;AN000;PERIOD SDIR SPECIFIED?
$$EN31:

;     $IF  NC			   ;AN000;IF CHDIR WORKED OK,
      JC $$IF36
	  CALL ANY_MORE_SUBDIR	   ;AN000;SEE IF MORE SUBDIRS BELOW THIS ONE
				   ;SETS "FRAM_CHAR" TO:
				   ;  "ELBO" - NO MORE DIR BELOW THIS ONE
				   ;  "TEE" - THERE IS ANOTHER DIR BELOW HERE
	  TEST FLAGS,F_SWITCH	   ;AN000;ARE ALL FILES ASKED FOR?
				   ; (TEST WILL CLEAR CARRY FLAG)
;	  $IF  NZ		   ;AN000;IS /F SET?
	  JZ $$IF37
	      CALL FIND_TYPE_NORMAL ;AN000;DISPLAY ALL THE FILENAMES

;	  $ENDIF		   ;AN000;/F?
$$IF37:
	  CALL FIND_TYPE_DIR	   ;AN000;DISPLAY ALL THE DIRECTORIES

;     $ELSE			   ;AN000;SINCE CHDIR FAILED
      JMP SHORT $$EN36
$$IF36:
	  MOV  DI,OFFSET MSGNUM_INVPATH ;AN000;"INVALID PATH"
	  CALL SENDMSG		   ;AN000;SAY WHY I QUIT

	  MOV  EXITFL,EXERR	   ;AN000;SET ERROR FLAG TO QUIT
;     $ENDIF			   ;AN000;CHDIR OK?
$$EN36:
				   ;FINISHED WITH THIS SUBDIRECTORY, SO
; $ELSE 			   ;AN000;SINCE STACK TOO SMALL
  JMP SHORT $$EN30
$$IF30:
      MOV  DI,OFFSET MSGNUM_EXTERR ;AN000;DESCRIPTOR FOR EXTENDED ERRORS
      MOV  [DI].MSG_NUM,INSUF_MEM  ;AN000;"INSUFFICIENT MEMORY"
      CALL SENDMSG		   ;AN000;

      MOV  EXITFL,EXERR 	   ;AN000;SET ERRORLEVEL RET CODE
; $ENDIF			   ;AN000;
$$EN30:
  ADD  SP,WA_SIZE		   ;AN000;DISCARD WORKAREA
  POP  BP			   ;AN000;RESTORE CALLER'S BP REG
  RET				   ;AN000;RETURN TO CALLER
EXECUTE ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <ANY_MORE_SUBDIR - LOOK AHEAD,SEE IF MORE SUBDIR> ;AN000;
ANY_MORE_SUBDIR PROC		   ;AN000;
;HAVING JUST DONE A FIND FIRST/NEXT FOR A SUBDIRECTORY,LOOK FOR ANOTHER
;INPUT: BP=DYNAMIC WORKAREA
;	"FLAGS" FIRST TIME SWITCH
;	FOR FIRST TIME, "START_DRIVE" AND "START_PATH" SET WITH WHERE TO LOOK.
;	FIX_DTA_FILN MAY HAVE LATEST FILE PROCESSED, OR NOTHING
;OUTPUT:"FRAM_CHAR"="ELBO" = NO MORE SUBDIRS AFTER THIS ONE.
;	"FRAM_CHAR"="TEE"  = ANOTHER SUBDIR AFTER THIS ONE
;	"EXITFL" SET TO NON ZERO IF REAL ERROR OCCURRED.
;	FIX_DTA_FILN IS RESTORED TO WHATEVER IT HAD.
; =  =	=  =  =  =  =  =  =  =	=  =
  MOV  SI,OFFSET FIX_DTA_FILN	   ;AN000;FROM THE DTA, FILENAME AREA
  MOV  DI,OFFSET SAVEFILN	   ;AN000; TO A TEMPORARY LOCATION
  MOV  CX,LENGTH SAVEFILN	   ;AN000; SAVE THE ENTIRE FILENAME FIELD
  REP  MOVSB			   ;AN000; INTO THE TEMPORARY LOCATION

  TEST FLAGS,F_FIRSTIME 	   ;AN000;IS THIS THE FIRST TIME?
; $IF  Z			   ;AN000;IF THE FIRST TIME
  JNZ $$IF43
      MOV  CX,ATTR_DIR		   ;AN000;SET ATTRIBUTE TO SUBDIR
      MOV  DX,OFFSET STAR_STAR	   ;AN000;PASS FILENAME TO BE LOOKED FOR
      DOSCALL FINDFIRST 	   ;AN000;

; $ELSE 			   ;AN000;SINCE NOT FIRST TIME
  JMP SHORT $$EN43
$$IF43:
      DOSCALL FINDNEXT		   ;AN000;LOOK FOR ANOTHER SUBDIR

; $ENDIF			   ;AN000;FIRSTIME?
$$EN43:
; $SEARCH COMPLEX		   ;AN000;
  JMP SHORT $$SS46
$$DO46:
      DOSCALL FINDNEXT		   ;AN000;LOOK FOR ANOTHER SUBDIR
; $STRTSRCH			   ;AN000;
$$SS46:
; $EXITIF C			   ;AN000;IF ERROR WITH FINDNEXT
  JNC $$IF46
      CALL IF_NOMOREFILES	   ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
				   ;CY NOT SET = "NO MORE FILES"
				   ;CY IS SET = OTHER PROBLEM, "EXITFL" SET
      MOV  AL,GRAF_ELBO 	   ;AN002;CHANGE TO ELBO
      MOV  [BP].FRAM_CHAR,AL	   ;AC002;SAY NO MORE SUBDIR
; $ORELSE			   ;AN000;SINCE NO ERROR WITH FINDNEXT
  JMP SHORT $$SR46
$$IF46:
      CMP  FIX_DTA_ATTR,ATTR_DIR   ;AN000;DID I FIND A SUBDIR?
; $ENDLOOP E,AND		   ;AN000;FINDNEXT OK?
  JNE $$DO46
      CMP  FIX_DTA_FILN,PERIOD	   ;AN000;IS THIS FILENAME STARTING WITH "PERIOD"?
; $ENDLOOP NE			   ;AN000;IF NOT, FOUND A REAL SUBDIR
  JE $$DO46
      MOV  AL,GRAF_TEE		   ;AN002;CHANGE TO TEE
      MOV  [BP].FRAM_CHAR,AL	   ;AN002;SAY STILL MORE SUBDIR
; $ENDSRCH			   ;AN000;
$$SR46:

  TEST FLAGS,F_FIRSTIME 	   ;AN000;IS THIS THE FIRST TIME?
; $IF  NZ			   ;AN000;IF NOT THE FIRST TIME
  JZ $$IF52
      MOV  DI,OFFSET FIX_DTA_RES   ;AN000;MOVE TO THE FIXED DTA AREA
      LEA  SI,[BP].FRAM_DTA_RES    ;AN000; FROM DYNAMIC AREA IN STACK
      MOV  CX,LENGTH FIX_DTA_RES   ;AN000;SET COUNT TO FIELD SIZE
      REP  MOVSB		   ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK

; $ENDIF			   ;AN000;
$$IF52:
  MOV  DI,OFFSET FIX_DTA_FILN	   ;AN000;FROM A TEMPORARY LOCATION
  MOV  SI,OFFSET SAVEFILN	   ;AN000; TO THE DTA, FILENAME AREA
  MOV  CX,LENGTH SAVEFILN	   ;AN000; RESTORE THE ENTIRE FILENAME FIELD
  REP  MOVSB			   ;AN000; FROM THE TEMPORARY LOCATION

  RET				   ;AN000;RETURN TO CALLER
ANY_MORE_SUBDIR ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <FIND_TYPE_NORMAL - PROCESS NORMAL, NON-DIR, FILES> ;AN000;
FIND_TYPE_NORMAL PROC NEAR	   ;AN000;
  PUBLIC FIND_TYPE_NORMAL	   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - PB=BASE OF FRAME, DYNAMIC WORKAREA WITH DTA
;OUTPUT - CY SET IF A PROBLEM, AND "EXITFL" HAS ERROR CODE
;	  CY CLEAR IF NORMAL "NO MORE FILES" FROM FIND FIRST/NEXT.
; =  =	=  =  =  =  =  =  =  =	=  =

  AND  FLAGS,0FFH-F_FLN 	   ;AN000;CLEAR INDICATOR FOR THIS SUBDIR
				   ;  TO SAY NO FILES PRINTED YET FOR THIS SDIR ;AN000;
  MOV  CX,ATTR_NORMAL		   ;AN000;SET TO LOOK FOR ALL FILES
  CALL BEGIN_FIND		   ;AN000;DO FIND FIRST

; $DO				   ;AN000;STEP THRU EACH ENTRY IN THIS SUBDIR
$$DO54:
; $LEAVE C			   ;AN000;QUIT IF ERROR
  JC $$EN54
      OR   FLAGS,F_FLN		   ;AN000;REQUEST THIS PRINTOUT BE DONE
      CALL SHOW_FN		   ;AN000;SHOW THIS FILE JUST FOUND

      CALL FIND_NEXT		   ;AN000;LOOK FOR ANOTHER

; $ENDDO			   ;AN000;LEAVE WILL QUIT IF PROBLEM WITH FINDNEXT
  JMP SHORT $$DO54
$$EN54:
  CALL IF_NOMOREFILES		   ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
				   ;CY NOT SET = "NO MORE FILES"
				   ;CY IS SET = OTHER PROBLEM, "EXITFL" SET
; $IF  NC			   ;AN000;IF NO MORE FILES,
  JC $$IF57
      MOV  AL,BLANK		   ;AN000;
      MOV  DI,OFFSET FIX_DTA_FILN  ;AN000;WHERE NAME IS TO GO
      MOV  CX,LENGTH FIX_DTA_FILN  ;AN000;NO. BYTES IN FILENAME FIELD
      REP  STOSB		   ;AN000;FILL FILENAME FIELD WITH BLANKS

      MOV  AL,ATTR_NORMAL	   ;AN000;SAY IT IS JUST A FILENAME
      CALL SHOW_FN		   ;AN000;OUTPUT A BLANK LINE

; $ENDIF			   ;AN000;NO MORE FILES?
$$IF57:

  RET				   ;AN000;RETURN TO CALLER
FIND_TYPE_NORMAL ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <FIND_TYPE_DIR - PROCESS THE DIRECTORY> ;AN000;
FIND_TYPE_DIR PROC NEAR 	   ;AN000;
  PUBLIC FIND_TYPE_DIR		   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - PB=BASE OF FRAME, DYNAMIC WORKAREA WITH DTA
;OUTPUT - CY SET IF A PROBLEM
;	  CY CLEAR IF NORMAL "NO MORE FILES" FROM FIND FIRST/NEXT.
; =  =	=  =  =  =  =  =  =  =	=  =
  OR   FLAGS,F_FLN		   ;AN000;PERMIT DISPLAY OF BUFFER
  MOV  CX,ATTR_DIR		   ;AN000;LOOK FOR DIRECTORY ATTRIBUTE
  CALL BEGIN_FIND		   ;AN000;DO FIND FIRST

; $SEARCH			   ;AN000;STEP THRU EACH ENTRY IN THIS SUBDIR
$$DO59:
; $LEAVE C			   ;AN000;QUIT IF ERROR
  JC $$EN59
      CMP  FIX_DTA_FILN,PERIOD	   ;AN000;WAS THAT A "PERIOD" FILENAME?
;     $IF  NE			   ;AN000;IF NOT, GO CHECK IT OUT
      JE $$IF61
	  MOV  AL,FIX_DTA_ATTR	   ;AN000;LOOK AT ATTRIB OF THIS FILE
	  CMP  AL,ATTR_DIR	   ;AN000;IS THIS A DIRECTORY?
;	  $IF  E		   ;AN000;IF DIR,
	  JNE $$IF62
	      CALL SHOW_FN	   ;AN000;SHOW THIS FILE JUST FOUND

	      ADD  CURRENT_COL,DASH_NUM+1 ;AN000;LOCATE SDIR NAME IN PRINTOUT LINE
	      MOV  SI,CURRENT_COL  ;AN000;
	      LEA  SI,BUF-1[SI] ;AN000;POINT AT SUBDIR NAME JUST PRINTED
	      MOV  DI,OFFSET FIX_DTA_FILN ;AN000;WHERE "NEXT_LEVEL" EXPECTS IT
	      MOV  CX,LENGTH FIX_DTA_FILN ;AN000;
	      REP  MOVSB	   ;AN000;SET UP SUBDIR NAME TO GO PROCESS

	      CALL NEXT_LEVEL	   ;AN000;SHIFT TO LOWER LEVEL SUBDIRECTORY

	      CALL EXECUTE	   ;AN000;RECURSIVE CALL, PROCESS NEW LEVEL OF SUBDIR

	      SUB  CURRENT_COL,DASH_NUM+1 ;AN000;BACK TO ORIGINAL LEVEL
	      LEA  DX,[BP].FRAM_CURR_PATH ;AN000;DS:DX = POINTER TO ASCIIZ STRING
	      DOSCALL CHDIR	   ;AN000;(3BH) CHANGE CURRENT DIRECTORY
				   ;GO BACK TO THE DIRECTORY THIS LEVEL OF
				   ; STACK WORKAREA HAS BEEN DEALING WITH,
				   ; SINCE "EXECUTE" HAD CHANGED IT TO WORK ON
				   ; A LOWER SUBDIRECTORY.
;	  $ENDIF		   ;AN000;DIR?
$$IF62:
;     $ENDIF			   ;AN000;"PERIOD" FILENAME?
$$IF61:
      CMP  EXITFL,EXOK		   ;AN000;ANY ERRORS SO FAR?
; $EXITIF NE,NUL		   ;AN000;YES, QUIT THIS MESS; OTHERWISE KEEP LOOKING
  JNE $$SR59
      CALL FIND_NEXT		   ;AN000;LOOK FOR ANOTHER

; $ENDLOOP			   ;AN000;LEAVE WILL QUIT IF PROBLEM WITH FINDNEXT
  JMP SHORT $$DO59
$$EN59:
      CMP  EXITFL,EXOK		   ;AN000;IF NO ERROR FOUND SO FAR
;     $IF  E			   ;AN000;
      JNE $$IF67
	  CALL IF_NOMOREFILES	   ;AN000;SEE IF REASON FOR ERROR IS NO MORE FILES
				   ;CY NOT SET = "NO MORE FILES"
				   ;CY IS SET = OTHER PROBLEM, "EXITFL" SET
;     $ENDIF			   ;AN000;ANY ERRORS SO FAR?
$$IF67:
; $ENDSRCH			   ;AN000;
$$SR59:
  RET				   ;AN000;RETURN TO CALLER
FIND_TYPE_DIR ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <NEXT_LEVEL - SET UP TO LOOK AT LOWER LEVEL SUBDIR> ;AN000;
NEXT_LEVEL PROC NEAR		   ;AN000;
  PUBLIC NEXT_LEVEL		   ;AN000;
;INPUT: FIX_DTA_FILN - FILE NAME OF LOWER LEVEL SUBDIR
;OUTPUT: START_PATH - HAS COMPLETE PATH TO THE NEW LEVEL SUBDIR
; =  =	=  =  =  =  =  =  =  =	=  =

  MOV  SI,OFFSET START_PATH+1	;AN000;WHERE TO SAVE CURRENT PATH
  MOV  DL,DEFDRIVE		   ;AN000;DL = DRIVE NUM (0=DEF, 1=A, ETC)
  DOSCALL GET_CUR_DIR		   ;AN000;(47H) GET CURRENT DIRECTORY
				   ;OUTPUT: DS:SI POINTS TO FULL PATH NAME
  DEC  SI			   ;AN012;START SCAN AT START_PATH
  CALL SCAN_DBCS		   ;AN012;GET LAST 2 CHARS IN DL,DH
				   ; SI NOW AT END OF STRING
  MOV  DI,SI			   ;AN012;GET POINTER TO NUL
  CMP  DL,BACK_SLASH		   ;AN000;
; $IF  NE			   ;AN012;IF PATH NOT ALREADY TERMINATED WITH A "\"
  JE $$IF70
      MOV  BYTE PTR [DI],BACK_SLASH ;AN000;TERMINATE PREVIOUS PATH
      INC  DI			   ;AN000;DI POINTS TO NEXT NUL AT END OF STRING
; $ENDIF			   ;AN000;END IN "\"?
$$IF70:
  MOV  SI,OFFSET FIX_DTA_FILN	   ;AN000;GET NAME OF NEW SUBDIR
  MOV  CX,LENGTH FIX_DTA_FILN	   ;AN000;
  REP  MOVSB			   ;AN000;ADD THE NEW SUBDIR TO END

  AND  FLAGS,0FFH - F_FIRSTIME	   ;AN000;IN NEW SUBDIR, REQUEST FIND FIRST TO START
  RET				   ;AN000;RETURN TO CALLER
NEXT_LEVEL ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <SCAN_DBCS - FIND LAST 2 SBCS CHARS IN ASCIIZ> ;AN000;
SCAN_DBCS PROC NEAR		   ;AN000;
  PUBLIC SCAN_DBCS		   ;AN000;
;INPUT: DS:SI = ASCIIZ STRING TO BE SCANNED
;OUTPUT: DL=LAST SBCS CHAR BEFORE NUL
;	 DH=NEXT TO LAST SBCS CHAR BEFORE NUL
;	 IF NO SBCS CHAR FOUND, DL OR DH WILL BE NUL
;	 SI=OFFSET TO NUL DELIMITER

  XOR  DX,DX			   ;AN000;CLEAR CHAR ACCUMULATOR
; $DO				   ;AN000;
$$DO72:
      LODSB			   ;AN000;GET NEXT CHAR FROM DS:SI TO AL
      CMP  AL,NUL		   ;AN000;IS THAT THE DELIMITER?
; $LEAVE E			   ;AN000;FOUND THE END, SO QUIT
  JE $$EN72
      CALL CHK_DBCS		   ;AN000;IS THIS THE FIRST OF A DBCS PAIR?

;     $IF  C			   ;AN000;IF SO, FOUND A DBCS PAIR
      JNC $$IF74
	  INC  SI		   ;AN000;SKIP ITS PARTNER
	  MOV  AL,NUL		   ;AN000;PASS BACK A NUL, INSTEAD OF AN SBCS CHAR
;     $ENDIF			   ;AN000;
$$IF74:
      MOV  DH,DL		   ;AN000;SAVE PREVIOUS CHAR
      MOV  DL,AL		   ;AN000;REMEMBER THE CHAR JUST FOUND
; $ENDDO			   ;AN000;
  JMP SHORT $$DO72
$$EN72:
  DEC  SI			   ;AN000;LODSB SET SI ONE BEYOND NUL
				   ; SO SET SI BACK TO POINT TO THE NUL
  RET				   ;AN000;RETURN TO CALLER
SCAN_DBCS ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <BEGIN_FIND - DO FIND FIRST FILE> ;AN000;
BEGIN_FIND PROC NEAR		   ;AN000;
  PUBLIC BEGIN_FIND		   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT- CURRENT DOS DEFAULT DRIVE HAS TARGET DRIVE TO BE RESEARCHED.
;	CURRENT DEFAULT SUBDIRECTORY HAS SUBDIR TO BE RESEARCHED.
;	CX = ATTRIBUTE OF FILE TYPE TO LOOK FOR
;	BP = OFFSET OF DYNAMIC WORKAREA
;OUTPUT - DTA IS SET UP WITH FIRST FILE FOUND, READY TO BE USED BY FIND NEXT.
;	WORKAREA HAS SAVED THE RESULT OF FINDFIRST.
; =  =	=  =  =  =  =  =  =  =	=  =

  MOV  DX,OFFSET STAR_STAR	   ;AN000;PASS FILENAME TO BE LOOKED FOR
  DOSCALL FINDFIRST		   ;AN000;(4EH) LOOK FOR FIRST SUBDIRECTORY

  MOV  SI,OFFSET FIX_DTA_RES	   ;AN000;MOVE FROM THE FIXED DTA AREA
  LEA  DI,[BP].FRAM_DTA_RES	   ;AN000; TO THE DYNAMIC AREA IN STACK
  MOV  CX,LENGTH FIX_DTA_RES	   ;AN000;SET COUNT TO FIELD SIZE
  REP  MOVSB			   ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK

  RET				   ;AN000;RETURN TO CALLER
BEGIN_FIND ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <FIND_NEXT - LOOK FOR NEXT ENTRY IN DIRECTORY> ;AN000;
FIND_NEXT PROC NEAR		   ;AN000;
  PUBLIC FIND_NEXT		   ;AN000;
;INPUT: RESERVED FIELD, LEFT FROM PREVIOUS FIND FIRST/NEXT, IN [BP].FRAM_DTA_RES
;OUTPUT: [BP].FRAM_DTA_RES UPDATED WITH NEW RESERVED DATA, FROM CURRENT DTA
;	FIX_DTA.? FIELDS ARE SET UP TO DEFINE NEW FILE JUST FOUND.
;	CY SET IF NO MORE FILES FOUND, CY CLEAR IF A NEW FILE FOUND.
; =  =	=  =  =  =  =  =  =  =	=  =
  LEA  SI,[BP].FRAM_DTA_RES	   ;AN000;GET WHAT WAS LEFT FROM LAST FIND
  MOV  DI,OFFSET FIX_DTA_RES	   ;AN000;INTO THE FIXED DTA AREA
  MOV  CX,LENGTH FIX_DTA_RES	   ;AN000;SET COUNT TO FIELD SIZE
  REP  MOVSB			   ;AN000;SET UP DTA FOR FIND

  DOSCALL FINDNEXT		   ;AN000;(4FH) CARRY WILL BE SET TO REFLECT RESULT

  MOV  SI,OFFSET FIX_DTA_RES	   ;AN000;MOVE FROM THE FIXED DTA AREA
  LEA  DI,[BP].FRAM_DTA_RES	   ;AN000; TO THE DYNAMIC AREA IN STACK
  MOV  CX,LENGTH FIX_DTA_RES	   ;AN000;SET COUNT TO FIELD SIZE
  REP  MOVSB			   ;AN000;SAVE THIS IN DYNAMIC WORKAREA STACK

  RET				   ;AN000;RETURN TO CALLER
FIND_NEXT ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <SHOW_FN - DISPLAY THE FILENAME FOUND> ;AN000;
SHOW_FN PROC NEAR		   ;AN000;
  PUBLIC SHOW_FN		   ;AN000;MAKE ENTRY IN LINK MAP
;INPUT - BP=OFFSET TO WORKAREA IN STACK
;	 AL=ATTRIBUTE OF FILENAME AS DEFINED IN DIR ENTRY
;	 FLAGS (F_FLN) INDICATOR OF FLN HAVING BEEN PRINTED
;OUTPUT - "BUF" IS SET UP TO CONTAIN THE DISPLAY LINE, AND IS SENT TO STDOUT.
; =  =	=  =  =  =  =  =  =  =	=  =
;DESCRIPTION OF THE LINE TO BE DISPLAYED, IN "BUF":
;"CURRENT_COL" HAS COL NUMBER WHERE LEADING GRAPHIC IS TO GO.
;"DASH_NUM" IS THE NUM OF DASHES THAT IMMEDIATELY FOLLOWS THE LEADING
;   GRAPHIC.  (FOR SUBDIRECTORIES ONLY - FOR REGULAR FILENAMES, THIS
;   FIELD WOULD HAVE SPACES INSTEAD OF DASHES.)
;"FLN_INDENT" IS THE NUMBER OF SPACES TO BE PUT RIGHT IN FRONT OF A
;   FILENAME.  FOR SUBDIRS, THERE IS NO SUCH FIELD
;EXAMPLE, FOR SUBDIRS
;      ����DIR_FILN
;	  FOR ORDINARY FILES
;      �xxxssssANY_FILN.EXT  (WHERE x AND s ARE SPACES)
; =  =	=  =  =  =  =  =  =  =	=  =

  CMP  FIX_DTA_FILN,PERIOD	   ;AN000;DOES FILENAME START WITH PERIOD?
; $IF  NE			   ;AN000;IF NOT, CONTINUE...
  JE $$IF77
      MOV  BL,AL		   ;AN000;SAVE FILE ATTRIBUTE IN AL INTO BL

      CALL FLN_TO_BUF		   ;AN000; MOVE NAME OF FILE TO OUTPUT BUFFER

      CALL GRAF_TO_BUF		   ;AN000;DETERMINE LEADING GRAPHIC FOR BUFFER

      CALL BLANK_DASH		   ;AN000;PUT BLANKS OR DASHES INTO BUF BEFORE FILENAME

;		BUFFER INITIALIZED, DISPLAY IT

      MOV  DX,OFFSET BUF	   ;AN000;DISPLAY FILENAME OF FILE FOUND
      CALL LEN_ASCIIZ		   ;AN000;SET CX=LEN OF DX@ BUFFER, UP THRU NUL

      DEC  CX			   ;AN000;FORGET THE NUL
      TEST FLAGS,F_FLN		   ;AN000;HAVE ANY FLN BEEN PRINTED YET?
;     $IF  NZ			   ;AN000;IF SO, PRINT THIS
      JZ $$IF78
	  CALL DO_WRITE 	   ;AN000;DISPLAY FILENAME IN DX TO STDOUT

;     $ENDIF			   ;AN000;FILES PRINTED YET?
$$IF78:
;		CLEAN UP BUFFER FOR NEXT TIME

      CALL FIX_GRAF		   ;AN000;SET UP GRAPHIC FOR NEXT LINE

      MOV  AL,[BP].FRAM_CHAR	   ;AN000;GET ALTERED GRAPHIC CHAR
      MOV  DI,CURRENT_COL	   ;AN000;FIND WHERE IN "BUF"
      LEA  DI,BUF-1[DI]    ;AN000; TO PUT ALTERED GRAPHIC
      STOSB			   ;AN000;STORE ALTERED GRAPHIC INTO BUFFER

      CMP  BL,ATTR_DIR		   ;AN000;LOOK AT ATTRIB OF FILENAME
;     $IF  E			   ;AN000;IF IS A SUBDIRECTORY
      JNE $$IF80
	  OR   FLAGS,F_SUBDIR	   ;AN000;SAY, "A SUBDIR HAS BEEN PRINTED"

	  MOV  DI,CURRENT_COL	   ;AN000;GET COL NUM OF ELBO/TEE
	  LEA  DI,BUF[DI]	   ;AN000;POINT TO JUST AFTER ELBO/TEE
	  MOV  AL,BLANK 	   ;AN000;BLANK OUT THE HORIZONTAL DASHES
	  MOV  CX,DASH_NUM	   ;AN000;HOW MANY DASHES WERE PUT IT
	  REP  STOSB		   ;AN000;WIPE OUT THOSE DASHES FOR NEXT GUY
;     $ENDIF			   ;AN000;
$$IF80:
; $ENDIF			   ;AN000;PERIOD FILENAME?
$$IF77:
  RET				   ;AN000;RETURN TO CALLER
SHOW_FN ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <FLN_TO_BUF - MOVE FILENAME TO BUFFER> ;AN000;
FLN_TO_BUF PROC NEAR		   ;AN000;
  PUBLIC FLN_TO_BUF		   ;AN000;
;INPUT: CURRENT_COL - INDEX INTO "BUF" WHERE THIS DISPLAY STARTS
;	FIX_DTA_FILN - NAME OF FILE TO BE DISPLAYED
;OUTPUT: "BUF" HAS LEADING GRAPHIC AND FILENAME READY FOR DISPLAY.
; =  =	=  =  =  =  =  =  =  =	=  =
  MOV  DI,CURRENT_COL		   ;AN000;
  CMP  BL,ATTR_DIR		   ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF  NE			   ;AN000;IF NOT A SUBDIRECTORY
  JE $$IF83
      LEA  DI,BUF+DASH_NUM+FLN_INDENT[DI] ;AN000;SET DESTINATION TO "BUF"+
; $ELSE 			   ;AN000;SINCE IT IS SUBDIRECTORY
  JMP SHORT $$EN83
$$IF83:
      LEA  DI,BUF+DASH_NUM[DI]	   ;AN000;SET DESTINATION TO "BUF"+
; $ENDIF			   ;AN000;
$$EN83:
  MOV  CX,LENGTH FIX_DTA_FILN	   ;AN000;SET COUNT TO MOVE ENTIRE FILE NAME
  MOV  SI,OFFSET FIX_DTA_FILN	   ;AN000;FROM DTA OF FIND FIRST
; $DO				   ;AN000;
$$DO86:
      LODSB			   ;AN000;GET FIRST\NEXT CHAR OF FILENAME
      STOSB			   ;AN000;MOVE THAT BYTE TO OUTPUT MSG FIELD
      CMP  AL,NUL		   ;AN000;IS THIS THE NUL CHAR DELIMITER?
; $LEAVE E			   ;AN000;QUIT IF NUL FOUND
  JE $$EN86
; $ENDDO LOOP			   ;AN000;
  LOOP $$DO86
$$EN86:
  RET				   ;AN000;RETURN TO CALLER
FLN_TO_BUF ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <GRAF_TO_BUF - SELECT LEADING GRAPHIC CHAR FOR BUF> ;AN000;
GRAF_TO_BUF PROC NEAR		   ;AN000;
  PUBLIC GRAF_TO_BUF		   ;AN000;
;INPUT: BL = ATTRIBUTE OF FILENAME
;	FLAGS (F_FIRSTIME BIT)
;	FRAM_CHAR = LEADING CHAR, FOR FILENAME DISPLAY
;	CURRENT_COL = WHERE IN BUF TO PUT CHARS
;	BUF = TO RECEIVE LEADING CHAR
;OUTPUT: BUF HAS LEADING CHAR
; =  =	=  =  =  =  =  =  =  =	=  =
  TEST FLAGS,F_SWITCH		   ;AN000;ARE FILENAMES TO BE LISTED
; $IF  Z			   ;AN000;NO, JUST SUBDIRS
  JNZ $$IF89
      OR   FLAGS,F_FIRSTIME	   ;AN000;DO NOT DO FIND FIRST SUBDIR
; $ENDIF			   ;AN000;
$$IF89:
  CMP  BL,ATTR_DIR		   ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF  E			   ;AN000;IF A SUBDIR
  JNE $$IF91
      CALL ANY_MORE_SUBDIR	   ;AN000;SEE IF ANOTHER SUBDIR AFTER THIS ONE

; $ELSE 			   ;AN000;SINCE NOT A SUBDIR
  JMP SHORT $$EN91
$$IF91:
      TEST FLAGS,F_FIRSTIME	   ;AN000;IS THIS THE FIRST TIME HERE?
;     $IF  Z			   ;AN000;IF FIRST TIME,
      JNZ $$IF93
	  CALL FIX_GRAF 	   ;AN000;SET UP GRAPHIC FOR NEXT LINE

;     $ENDIF			   ;AN000;FIRST TIME?
$$IF93:
; $ENDIF			   ;AN000;SUBDIR?
$$EN91:
  OR   FLAGS,F_FIRSTIME 	   ;AN000;FLAG, THIS HAS BEEN DONE
  MOV  AL,[BP].FRAM_CHAR	   ;AN000;START BUF WITH CURRENT GRAPHIC CHAR
  MOV  DI,CURRENT_COL		   ;AN000;
  LEA  DI,BUF-1[DI]	   ;AN000;
  STOSB 			   ;AN000;
  RET				   ;AN000;RETURN TO CALLER
GRAF_TO_BUF ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <BLANK_DASH - PUT BLANKS OR DASHES BEFORE FILENAME> ;AN000;
BLANK_DASH PROC NEAR		   ;AN000;
  PUBLIC BLANK_DASH		   ;AN000;
;INPUT: BL - FILE ATTRIBUTE
;	CURRENT_COL - WHERE THIS DISPLAY STARTS IN "BUF"
;	BUF - PARTLY READY CHARS FOR DISPLAY
;OUTPUT: BUF HAS PROPER CHARS BETWEEN LEADING GRAPHIC AND FILENAME FIELDS.
; =  =	=  =  =  =  =  =  =  =	=  =
  CMP  BL,ATTR_DIR		   ;AN000;LOOK AT ATTRIB OF FILENAME
; $IF  NE			   ;AN000;IF NOT A SUBDIRECTORY
  JE $$IF96
      MOV  AL,BLANK		   ;AN000;PUT IN BLANKS
      MOV  CX,DASH_NUM + FLN_INDENT ;AN000;SPECIFY HOW MANY BLANKS TO PUT IN
; $ELSE 			   ;AN000;SINCE IT IS A SUBDIR
  JMP SHORT $$EN96
$$IF96:
      MOV  AL,GRAF_DASH 	   ;AN000;PUT IN THE DASHES
      MOV  CX,DASH_NUM		   ;AN000;SPECIFY HOW MANY DASHES TO PUT IN
; $ENDIF			   ;AN000;
$$EN96:
  MOV  DI,CURRENT_COL		   ;AN000;GET COL NUM OF ELBO/TEE
  LEA  DI,BUF[DI]		   ;AN000;POINT TO JUST AFTER ELBO/TEE
  REP  STOSB			   ;AN000;ADD DASHES/BLANKS TO PRINT LINE IN "BUF"
  RET				   ;AN000;RETURN TO CALLER
BLANK_DASH ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <FIX_GRAF - CHANGE CURRENT GRAPHIC FOR NEXT LINE> ;AN000;
  PUBLIC FIX_GRAF		   ;AN000;MAKE ENTRY IN LINK MAP
FIX_GRAF PROC NEAR		   ;AN000;
;IN THE WORKAREA, IS A CHAR THAT SHOWS WHAT HAS BEEN FOUND REGARDING ANY
;LOWER LEVELS OF SUBDIRS.
;WHEN DISPLAYING A SUBDIR, THE PRINT LINE STARTS EITHER WITH "ELBO",
;MEANING, NO LOWER LEVELS AFTER THIS ONE, OR WITH "TEE" WHICH MEANS
;THERE IS ANOTHER LEVEL OF SUBDIR BELOW THIS ONE.  AFTER THE DISPLAY,
;THE REST OF THE DISPLAY OF FILENAMES WITHIN THIS SUBDIR, WILL SHOW
;THIS CHARACTER, BUT IN A Revised FORMAT.  THIS SUBROUTINE PERFORMS
;THE MODIFICATION, AS:
;CHANGE "ELBO" TO "BLANK, OR CHANGE "TEE" TO "VERTICAL BAR".
;INPUT: BP=POINTER TO STACK WORKAREA
;	FRAM_CHAR=FIELD IN WORKAREA WITH CHAR TO BE Revised
; =  =	=  =  =  =  =  =  =  =	=  =
  PUSH AX			   ;AN002;SAVE WORK REG
  MOV  AL,GRAF_ELBO		   ;AN002;GET ELBO CHAR
  CMP  [BP].FRAM_CHAR,AL	   ;AN000;FOR NEXT DISPLAY LINE AFTER THIS ONE,
; $IF  E			   ;AN000;IF CURRENT LINE STARTS WITH "ELBO"
  JNE $$IF99
      MOV  [BP].FRAM_CHAR,BLANK    ;AN000;CHANGE IT TO JUST A BLANK
; $ELSE 			   ;AN000;SINCE NOT ELBO
  JMP SHORT $$EN99
$$IF99:
      MOV  AL,GRAF_TEE		   ;AN002;GET THE TEE CHAR
      CMP  [BP].FRAM_CHAR,AL	   ;AC002;CHANGE A "TEE"
;     $IF  E			   ;AN000;
      JNE $$IF101
	  MOV  AL,GRAF_BAR	   ;AN002;GET BAR CHAR
	  MOV  [BP].FRAM_CHAR,AL   ;AC002; TO A VERTICAL "BAR"
;     $ENDIF			   ;AN000;
$$IF101:
; $ENDIF			   ;AN000;ELBO?
$$EN99:
  POP  AX			   ;AN002;RESTORE REG
  RET				   ;AN000;RETURN TO CALLER
FIX_GRAF ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <ANY_SUBDIRS - DISPLAY MSG IF NO SUBDIRS PRINTED> ;AN000;
ANY_SUBDIRS PROC NEAR		   ;AN000;
;INPUT:FLAGS (F_SUBDIR BIT) IS SET IF ANY SUBDIR HAD BEEN DISPLAYED.  IF THIS
;	BIT IS OFF, THEN DISPLAY THE MESSAGE
; =  =	=  =  =  =  =  =  =  =	=  =

  TEST FLAGS,F_SUBDIR		   ;AN000;HAVE ANY SUBDIRS BEEN PRINTED YET?
; $IF  Z			   ;AN000;NO, NONE PRINTED SO FAR
  JNZ $$IF104
      MOV  DI,OFFSET MSGNUM_NOSUB  ;AN000;"No sub-directories exist"
      CALL SENDMSG		   ;AN000;DISPLAY THE MESSAGE

; $ENDIF			   ;AN000;ANY SUBDIRS PRINTED?
$$IF104:
  RET				   ;AN000;RETURN TO CALLER
ANY_SUBDIRS ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <DO_WRITE - SEND STRING TO STDOUT> ;AN000;
DO_WRITE PROC NEAR		   ;AN000;
  PUBLIC DO_WRITE		   ;AN000;
;AFTER THE REQUESTED STRING IS SEND TO STDOUT, IT IS TERMINATED BY CR,LF
;INPUT: DX=OFFSET TO STRING TO BE WRITTEN
;	CX=LENGTH
;OUTPUT: STRING IS SENT TO STDOUT, FOLLOWED BY CR,LF.
;	BX = SAVED AND RESTORED.
; =  =	=  =  =  =  =  =  =  =	=  =

  PUSH BX			   ;AN000;SAVE CALLER'S REG
  MOV  BX,STDOUT		   ;AN000;BX = FILE HANDLE
  DOSCALL WRITE 		   ;AN000;(40H) WRITE FUNCTION

  MOV  DX,OFFSET CRLF		   ;AN000;CLOSE MSG WITH CRLF
  MOV  CX,LEN_CRLF		   ;AN000;
  DOSCALL WRITE 		   ;AN000;(40H) WRITE FUNCTION

  POP  BX			   ;AN000;RESTORE CALLER'S REG
  RET				   ;AN000;RETURN TO CALLER
DO_WRITE ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <IF_NOMOREFILES - ASK EXTENDED ERROR FOR WHY IS ERROR> ;AN000;
IF_NOMOREFILES PROC NEAR	   ;AN000;
  PUBLIC IF_NOMOREFILES 	   ;AN000;
;INPUT - A DOS FUNCTION HAS JUST RETURNED WITH A CARRY INDICATING ERROR
;OUTPUT - AX=EXTENDED ERROR CODE
;	IF THE ERROR IS JUST A NO MORE FILES, CARRY IS CLEAR
;	IF ANY OTHER ERROR, THEN CARRY IS SET, AND "EXITFL" HAS RET CODE
; =  =	=  =  =  =  =  =  =  =	=  =

  CALL GET_EXTERR		   ;AN000;GET THE EXTENDED ERROR TO AX

  CMP  AX,NO_MORE_FILES 	   ;AN000;SEE IF FILE WAS NOT FOUND
; $IF  E			   ;AN000;IF NO MORE FILES,
  JNE $$IF106
      CLC			   ;AN000;INDICATE A NORMAL RETURN
; $ELSE 			   ;AN000;SINCE ERROR IS SOMETHING ELSE
  JMP SHORT $$EN106
$$IF106:
      STC			   ;AN000;INDICATE AN ABNORMAL RETURN
      MOV  EXITFL,EXERR 	   ;AN000;INDICATE A PROBLEM TO RETURN CODE
; $ENDIF			   ;AN000;NO MORE FILES?
$$EN106:

  RET				   ;AN000;RETURN TO CALLER
IF_NOMOREFILES ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <GET_EXTERR - CALL EXTENDED ERROR> ;AN000;
GET_EXTERR PROC NEAR		   ;AN000;
  PUBLIC GET_EXTERR		   ;AN000;
;INPUT - A DOS FUNCTION HAS JUST RETURNED WITH A CARRY INDICATING ERROR
;OUTPUT: AX HAS EXTENDED ERROR CODE
;	NOTE: OTHER REGS, BX, CX, NORMALLY SET BY THE EXTERROR CALL
;	      ARE NOT KEPT.  THESE CONTAIN "LOCUS" AND SECONDARY LEVEL CODES
;	      THAT ARE NOT USED.
; =  =	=  =  =  =  =  =  =  =	=  =
  PUSH BX			   ;AN000;SAVE THE
  PUSH DS			   ;AN000; CALLER'S
  PUSH ES			   ;AN000;  REGISTERS
  PUSH CX			   ;AN000;

  MOV  BX,LEVEL_0		   ;AN000;BX=LEVEL NUMBER
  DOSCALL EXTERROR		   ;AN000;(59H) SET REGS TO SAY WHY PROBLEM

  POP  CX			   ;AN000;RESTORE REGS
  POP  ES			   ;AN000; CLOBBERED BY
  POP  DS			   ;AN000;  THE DOSCALL
  POP  BX			   ;AN000;

  RET				   ;AN000;RETURN TO CALLER
GET_EXTERR ENDP 		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <SENDMSG - PASS IN REGS DATA FROM MSG DESCRIPTOR TO DISP MSG> ;AN000;
SENDMSG PROC NEAR		   ;AN000;
  PUBLIC SENDMSG		   ;AN000;
; INPUT - DI=POINTER TO MSG_DESC STRUC FOR THIS MESSAGE
; OUTPUT - IF CARRY SET, EXTENDED ERROR MSG ATTEMPTED DISPLAYED
;	   IF CARRY CLEAR, ALL OK
;	   IN EITHER CASE, DI AND AX ALTERED, OTHERS OK

;  =  =  =  =  =  =  =	=  =  =  =  =

  PUSH BX			   ;AN000; SAVE CALLER'S REGS
  PUSH CX			   ;AN000;
  PUSH DX			   ;AN000;
  PUSH SI			   ;AN000;

;		 PASS PARMS TO MESSAGE HANDLER IN
;		 THE APPROPRIATE REGISTERS IT NEEDS.
  MOV  AX,[DI].MSG_NUM		   ;AN000; MESSAGE NUMBER
  MOV  BX,[DI].MSG_HANDLE	   ;AN000; HANDLE TO DISPLAY TO
  MOV  SI,[DI].MSG_SUBLIST	   ;AN000; OFFSET IN ES: OF SUBLIST, OR 0 IF NONE
  MOV  CX,[DI].MSG_COUNT	   ;AN000; NUMBER OF %PARMS, 0 IF NONE
  MOV  DX,[DI].MSG_CLASS	   ;AN000; CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW
  CALL SYSDISPMSG		   ;AN000; DISPLAY THE MESSAGE

; $IF  C			   ;AN000; IF THERE IS A PROBLEM,
  JNC $$IF109
				   ; AX=EXTENDED ERROR NUMBER
      MOV  DI,OFFSET MSGNUM_EXTERR ;AN000; GET REST OF ERROR DESCRIPTOR
      MOV  BX,[DI].MSG_HANDLE	   ;AN000; HANDLE TO DISPLAY TO
      MOV  SI,[DI].MSG_SUBLIST	   ;AN000; OFFSET IN ES: OF SUBLIST, OR 0 IF NONE
      MOV  CX,[DI].MSG_COUNT	   ;AN000; NUMBER OF %PARMS, 0 IF NONE
      MOV  DX,[DI].MSG_CLASS	   ;AN000; CLASS IN HIGH BYTE, INPUT FUNCTION IN LOW
      CALL SYSDISPMSG		   ;AN000; TRY TO SAY WHAT HAPPENED

      STC			   ;AN000; REPORT PROBLEM
; $ENDIF			   ;AN000; PROBLEM WITH DISPLAY?
$$IF109:

  POP  SI			   ;AN000; RESTORE CALLER'S REGISTERS
  POP  DX			   ;AN000;
  POP  CX			   ;AN000;
  POP  BX			   ;AN000;

  RET				   ;AN000;RETURN TO CALLER
SENDMSG ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=
  HEADER <BREAK_HANDLER - CONTROL BREAK VECTOR POINTS HERE> ;AN000;
BREAK_HANDLER PROC FAR		   ;AN000;"FAR" HERE IS REQUIRED FOR
  PUBLIC BREAK_HANDLER		   ;AN000; BREAK INTERRUPT HANDLERS
;THE INT 23H VECTOR HAS BEEN SET TO POINT HERE.
;THIS ROUTINE GETS CONTROL IF CONTROL-BREAK IS PRESSED.
;OUTPUT: THE "STC" REQUESTS THAT DOS ABORT WHEN I RETURN.
;	THERE IS NO ERRORLEVEL VALUE TO BE PASSED BACK TO DOS AT THIS POINT.

  CALL RESTORE			   ;AN000;PUT THINGS BACK LIKE THEY WERE

  DOSCALL RET_CD_EXIT,EXCTL	   ;AN000;RETURN TO DOS, WITH CTL-BREAK ERROR CODE
  INT  20H			   ;AN000;IN CASE ABOVE FAILS

;NOTE: THIS IS NOT THE MAIN EXIT FROM "TREE".
;      THE USUAL EXIT IS IN "BEGIN" PROC.
BREAK_HANDLER ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <RESTORE - RETURN TO INITIAL DOS DEFAULT DRIVE> ;AN000;
RESTORE PROC NEAR		   ;AN000;
  PUBLIC RESTORE		   ;AN000;
;SET DOS DEFAULT DRIVE BACK TO THE INITIAL VALUE, AND
; RESTORE THE INITIAL DEFAULT PATH,
; AND THE INITIAL "APPEND" STATE,
; AND THE ORIGINAL CONTROL BREAK VECTOR.
;INPUT - "DEFAULT_DR" SET TO ALPHA LETTER OF ORIGINAL DOS DEFAULT DRIVE.
;	 "START_DR_NUM" SET TO NUMERIC VALUE OF ORIGINAL DOS DEFAULT DRIVE
;	 "DEFAULT_PATH" SET TO ORIGINAL CURRENT PATH OF DOS DEFAULT DRIVE
;	 "APPEND_FLAGS" HAS ORIGINAL STATUS OF /X OF APPEND
;	 "OLDINT23" HAS ORIGINAL OWNER OF CONTROL BREAK VECTOR 23H
;	 "OLDINT24" HAS ORIGINAL OWNER OF CRITICAL ERROR VECTOR 24H
; =  =	=  =  =  =  =  =  =  =	=  =

  TEST FLAGS,F_FAILING		   ;AN000;IS RESTORING SUBDIR PERMITTED?
; $IF  Z,AND			   ;AN000;YES, DO IT
  JNZ $$IF111
  TEST FLAGS,F_DEF_PAT_TAR	   ;AN000;HAS ORIGINAL SUBDIR BE FOUND YET?
; $IF  NZ			   ;AN000;YES, DO IT
  JZ $$IF111

;		RESTORE THE CURRENT SUBDIRECTORY TO ITS ORIGINAL PATH

      MOV  DX,OFFSET DEFAULT_PATH  ;AN000;DS:DX = POINTER TO ASCIIZ STRING
      DOSCALL CHDIR		   ;AN000;(3BH) CHANGE CURRENT DIRECTORY

; $ENDIF			   ;AN000;
$$IF111:

;		RESTORE THE DOS DEFAULT DRIVE TO ITS ORIGINAL DRIVE

  MOV  DL,START_DR_NUM		   ;AN000; DL=DRIVE NUMBER (0=A,1=B)
  DOSCALL SELECT_DISK		   ;AN000;(0EH) SETS DEFAULT DRIVE

;		SET APPEND BACK TO ITS ORIGINAL STATUS

  TEST FLAGS,F_APPEND		   ;AN006;IF DOS VERSION OF APPEND IS ACTIVE
; $IF  NZ			   ;AN006;IT NEEDS TO BE FIXED BACK LIKE IT WAS
  JZ $$IF113
      MOV  AX,SET_APPEND	   ;AN000;RESTORE APPEND TO PREVIOUS /X STATUS
      MOV  BX,APPEND_FLAGS	   ;AC006;GET PREVIOUS STATUS
      INT  2FH			   ;AN000;SET IT BACK AS IT WAS

; $ENDIF			   ;AN006;DOS VERSION OF APPEND?
$$IF113:

;		FIXUP THE CONTROL BREAK VECTOR TO ITS ORIGINAL CONTENTS

  PUSH DS			   ;AN000;SAVE THE SEGREG
  LDS  DX,OLDINT23		   ;AN000;USING THE ORIGINAL CONTENTS OF THE VECTOR
				   ;DS:DX = DWORD POINTER TO BE PUT INTO VECTOR
  DOSCALL SET_VECTOR,VEC_CTLBREAK  ;AN000;(25H) RESTORE THE ORIG INT 23 HANDLER

  POP  DS			   ;AN000;RESTORE THE SEGREG

;		FIXUP THE CRITICAL ERROR VECTOR TO ITS ORIGINAL CONTENTS

  PUSH DS			   ;AN000;SAVE THE SEGREG
  LDS  DX,OLDINT24		   ;AN000;USING THE ORIGINAL CONTENTS OF THE VECTOR
				   ;DS:DX = DWORD POINTER TO BE PUT INTO VECTOR
  DOSCALL SET_VECTOR,VEC_CRITERR   ;AN000;(25H) RESTORE THE ORIG INT 24 HANDLER

  POP  DS			   ;AN000;RESTORE THE SEGREG
  RET				   ;AN000;RETURN TO CALLER
RESTORE ENDP			   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <MYERRORHANDLER - SERVICE CRITICAL ERROR HANDLER> ;AN000;
MYERRORHANDLER PROC NEAR	   ;AN000;
;INPUT: DOS HAS CALLED THE CRITICAL ERROR INTERRUPT, VECTOR 24
;	AL=FAILING DRIVE NUMBER (A:=0; B:=1; ETC.)
;OUTPUT: EITHER TREE IS TERMINATED (ON ABORT OR FAIL), OR
;	AL HAS OPERATOR RESPONSE, AND IRET BACK TO DOS TO HANDLE IT.
; =  =	=  =  =  =  =  =  =  =	=  =
  ASSUME CS:CSEG		   ;AN000;ONLY THE CS REG IS WORTH A HOOT
  ASSUME DS:NOTHING		   ;AN000;
  ASSUME ES:NOTHING		   ;AN000;
  ASSUME SS:NOTHING		   ;AN000;

  PUSH AX			   ;AN000;SAVE FAILING DRIVE NUMBER (A:=0, B:=1, ETC)
  PUSHF 			   ;AN000;SAVE THE FLAGS
				   ;(THIS IS NEEDED BECAUSE THE OLD INT 24
				   ;  HANDLER WILL EXIT WITH AN "IRET")
  CALL DWORD PTR OLDINT24	   ;AN000;INVOKE THE DOS ERROR HANDLER
				   ;RESPONSE WILL BE RETURNED IN AL
				   ;AL=0=IGNORE
				   ;AL=1=RETRY
				   ;AL=2=ABORT
				   ;AL=3=FAIL
  CMP  AL,ABORT 		   ;AN000;DID USER SAY ABORT ?
; $IF  GE			   ;AN000;YES, PROCESS "ABORT"
  JNGE $$IF115
      PUSH CS			   ;AN000;SET UP SEGREGS
      PUSH CS			   ;AN000; SO "RESTORE" WILL LIKE THEM
      POP  ES			   ;AN000;
      POP  DS			   ;AN000;
      ASSUME DS:CSEG,ES:CSEG	   ;AN000;TELL THE ASSEMBLER WHAT I JUST DID
      POP  AX			   ;AN007;GET AL=FAILING DRIVE NUMBER
      MOV  AH,START_DRIVE	   ;AN007;GET THE TARGET DRIVE BEING USED
      SUB  AH,DRIVEA		   ;AN007; A:=0, B:=1, ETC
      CMP  AH,AL		   ;AN007;IS START DRIVE SAME AS FAILING DRIVE?
;     $IF  E			   ;AN007;IF SAME DRIVE
      JNE $$IF116
	  OR   FLAGS,F_FAILING	   ;AN007;REQUEST CHDIR ON FAILING DRIVE NOT TO BE DONE
;     $ENDIF			   ;AN007;
$$IF116:

      CALL RESTORE		   ;AN000;RESTORE ORIGINAL CONDITIONS

      DOSCALL RET_CD_EXIT,EXABORT  ;AN000;QUIT, RETURN ERRORLEVEL CODE TO DOS
; = = = = = = = = = = = = = = = = =
; $ENDIF			   ;AN000;
$$IF115:
  ADD  SP,WORD			   ;AC009;UNDO THE PUSH AX ABOVE
  IRET				   ;AN000;
MYERRORHANDLER ENDP		   ;AN000;
; =  =	=  =  =  =  =  =  =  =	=  =
  HEADER <CHK_DBCS -SEE IF SPECIFIED BYTE IS A DBCS LEAD BYTE> ;AN012;
;*****************************************************************************
; Check DBCS environment
;*****************************************************************************

; Function: Check if a specified byte is in ranges of the DBCS lead bytes
; Input:    AL = Code to be examined
; Output:   If CF is on then a lead byte of DBCS
; Register: FL is used for the output, others are unchanged.

  PUBLIC CHK_DBCS		   ;AN012;
Chk_DBCS PROC			   ;AN012;
  PUSH DS			   ;AN012;save these regs, about to be clobbered
  PUSH SI			   ;AN012;
  LDS  SI,DBCSENV		   ;AN012;GET VECTOR OF DBCS RANGES

  ASSUME DS:NOTHING		   ;AN012;that function clobbered old DS

  OR   SI,SI			   ;AN012;IS THIS VECTOR SET YET?
; $IF  Z			   ;AN012;NO, GO GET THE VECTOR
  JNZ $$IF119
      PUSH AX			   ;AN012;
      DOSCALL DBCS_ENV,GET_DBCS_ENV ;AN012;SET DS:SI TO POINT TO DBCS VECTOR

      MOV  WORD PTR DBCSENV,SI	   ;AN012;SAVE THE DBCS VECTOR OFFSET
      MOV  WORD PTR DBCSENV+WORD,DS ;AN012; AND ITS SEGID
      POP  AX			   ;AN012;REGAIN THE CHAR TO BE CHECKED
; $ENDIF			   ;AN000;
$$IF119:
; $SEARCH			   ;AN012;
$$DO121:
      CMP  WORD PTR [SI],NUL	   ;AN012;vector ends with a nul terminator entry
; $LEAVE E			   ;AN012;if that was the terminator entry, quit
  JE $$EN121
      CMP  AL,[SI]		   ;AN012;look at LOW value of vector
; $EXITIF NB,AND		   ;AN012;if this byte is in range with respect to LOW
  JB $$IF121
      CMP  AL,[SI+1]		   ;AN012;look at HIGH value of vector
; $EXITIF NA			   ;AN012;if this byte is still in range
  JA $$IF121
      STC			   ;AN012;set flag to say, found a DBCS char.
; $ORELSE			   ;AN012;since char not in this vector
  JMP SHORT $$SR121
$$IF121:
      ADD  SI,WORD		   ;AN012;go look at next vector in dbcs table
; $ENDLOOP			   ;AN012;go back and check out new vector entry
  JMP SHORT $$DO121
$$EN121:
      CLC			   ;AN012;set flag to say this is not a DBCS character
; $ENDSRCH			   ;AN012;
$$SR121:
  POP  SI			   ;AN012;restore the regs
  POP  DS			   ;AN012;

  ASSUME DS:CSEG		   ;AN012;tell masm, DS back to normal

  RET				   ;AN012;
Chk_DBCS ENDP			   ;AN012;
; =  =	=  =  =  =  =  =  =  =	=  =
  PATHLABL TREE 		   ;AN013;
CSEG ENDS			   ;AN000;
  END  START			   ;AN000;