home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol040 / run80-v2.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  39.8 KB  |  1,708 lines

  1. ;
  2. ;    RUN80 Version 2.0, Modified: 04/08/81 by Kelly Smith
  3. ;
  4. ;    Ver. 2.0 Mod's: changed BASE equate from 4200H to 0000H for
  5. ;                    "standard CP/M" compatiblity.
  6. ;
  7. ;                    changed all "-1" values to 0FFH to allow
  8. ;                    assembly with Digital Research's ASM.COM.
  9. ;
  10. ;                    made TITLE string a comment field to allow
  11. ;                    assemby with DR's ASM.COM and MAC.COM.
  12. ;
  13. ;                    removed "exclamation" in comment field string
  14. ;                    "SCARE YOU", that caused 'L' error using
  15. ;                    DR's ASM.COM.
  16. ;
  17. ;                    swapped order of first two characters in filetypes
  18. ;                    to OPEN (i.e., RNO and MEM) so that files WOULD open.
  19. ;                    Version 1.A was trying to OPEN NRO and EMM when using
  20. ;                    DR's ASM.COM...someone was confused here I think.
  21. ;
  22. ;                    cleaned-up some of the "free-form" editing job,
  23. ;                    to make it a little easier to read...I gave up at
  24. ;                    label CTR:, 'cause it's to much like work. Ahhh, for
  25. ;                    for the glory of Control-I...wish someone had used it.
  26. ;
  27. ; copyright (C) 1981, T. Shapin, Orange, Ca. This program may not be sold,
  28. ; but may be distributed without charge.
  29. ;
  30. ;<DP.SHAPIN>RUN80.S80.61,  7-Feb-80 09:44:46, Edit by DP.SHAPIN
  31. ;
  32. ;        TITLE   RUN80 - K AND P TEXT FORMATTER
  33. ;
  34. ; FROM DR. DOBBS JOURNAL, MAY 1979.
  35. ; FORMAT ... THE SOFTWARE TOOLS TEXT FORMATTER
  36. ;
  37. ; MIKE GABRIELSON   12/2/78
  38. ;
  39. ; THIS PROGRAM IS A SOMEWHAT MODIFIED VERSION
  40. ; OF THE FORMAT PROGRAM IN THE BOOK "SOFTWARE TOOLS" BY
  41. ; KERNIHAN AND PLAUGER. DON'T LET
  42. ; THE ABSENCE OF COMMENTS SCARE YOU. THE BOOK CONTAINS COMPLETE
  43. ; DOCUMENTATION FOR THIS CODE.
  44. ;
  45. ; MODIFIED FOR CP/M (C) DIGITAL RESEARCH BY
  46. ; TED SHAPIN
  47. ;
  48. ; START THIS PROGRAM BY GIVING THE COMMAND 'RUN80 filename'.
  49. ;  IT WILL READ A FILE filename.RNO AND WRITE A FORMATTED
  50. ;  FILE WITH THE NAME: filename.MEM
  51. ;
  52. ; FORMATTING COMMANDS
  53. ;
  54. ; COMMAND       BREAK?  DEFAULT FUNCTION
  55. ; -------       ------  ------- --------
  56. ; .BR           YES             CAUSE A LINE BREAK
  57. ; .CE   N       YES     N= 1    CENTER THE NEXT N LINES
  58. ; .FI           YES             START FILLING (MOVE WORDS TO FILL LINES)
  59. ; .FO           NO      EMPTY   FOOTER TITLE
  60. ; .HE           NO      EMPTY   HEADER TITLE
  61. ; .IN   N       NO      N=0     INDENT N SPACES
  62. ; .NF           YES             STOP FILLING
  63. ; .PG   N       YES     N=+1    BEGIN PAGE NUMBERED N
  64. ; .PL   N       NO      N=66    SET PAGE LENGTH TO N
  65. ; .RM   N       NO      N=60    SET RIGHT MARGIN TO N
  66. ; .SK   N       YES     N=1     SPACE DOWN N LINES
  67. ; .SP   N       NO      N=1     LINE SPACING IS N
  68. ; .TA N,N...    NO      CLEARS  SET TAB STOPS (10 MAX)
  69. ; .TI   N       YES     N=0     TEMPORARY INDENT OF N
  70. ; .UL   N       NO      N=1     UNDERLINE WORDS FROM NEXT N LINES
  71. ;
  72. ; -------------------------------------------------------------
  73. ;
  74. BACKSPACE    EQU    8
  75. EOS        EQU    0
  76. HUGE        EQU    1000
  77. LINSIZ        EQU    80
  78. LIT         EQU     '`'     ; SYMBOL TO TAKE NEXT CHAR LITERALLY
  79. NEWLINE        EQU    0DH
  80. NONEX       EQU     '#'     ; SYMBOL FOR NON-EXPANDING BLANK
  81.                         ;  IN FILLED TEXT
  82. NO        EQU    0
  83. PGLEN        EQU    66
  84. PAGENUM        EQU    '#' ; SYMBOL TO PRINT PAGE NUMBER IN HEADER OR FOOTER
  85. PGWID        EQU    60
  86. TAB        EQU    9
  87. TRIPLE        EQU    LINSIZ*3+3   ;UNDERLINING TRIPLES THE LENGTH
  88. YES        EQU    0FFH
  89. ;
  90. CR        EQU    0DH
  91. LF        EQU    0AH
  92. ;
  93. BASE    EQU     0000H           ; BASE OF CP/M VERSION
  94. BDOS    EQU     BASE+5
  95. BUFF    EQU     BASE+80H
  96. ;
  97. FCB     EQU     BASE+05CH       ; FILE CONTROL BLOCK
  98. FCBDN   EQU     FCB+0   ; NAME OF INPUT HEX FORMAT FILE
  99. FCBNM   EQU     FCB+1   ; FILE NAME
  100. FCBFT   EQU     FCB+9   ; DISK FILE TYPE (3 CHARS)
  101. FCBRL   EQU     FCB+12  ; FILE'S CURRENT REEL NUMBER
  102. FCBRC   EQU     FCB+15  ; FILE'S RECORD COUNT (0 TO 128)
  103. FCBBM   EQU     FCB+16  ; START OF BIT MAP
  104. FCBNM2  EQU     FCB+16  ; SECOND FILE NAME (OUTPUT)
  105. FCBCR   EQU     FCB+32  ; CURRENT (NEXT) RECORD NUMBER (0 TO 127)
  106. FCBDM   EQU     FCB+33  ; START OF DISK ALLOCATION MAP
  107. FCBLN   EQU     FCB+33  ; FCB LENGTH
  108. ;
  109. ;
  110.         ORG     100H+BASE
  111.         LXI     SP,STACK
  112.         CALL    DSKINI
  113.         CALL    INIT
  114.         JMP     MAINL
  115.   
  116. GNASC:  PUSH    H  ; GET NEXT ASCII 
  117.         PUSH    D ; LEAVE WITH CARRY SET IF AT EOF
  118.         PUSH    B
  119. GNA2:   LDA    IPTR       ; INPUT BUFFER POINTER
  120.         CPI    128        ; 128 BYTES PER SECTOR (INPUT RECORD)
  121.         JZ    FREAD      ; READ NEXT FILE RECORD
  122. GNA1:    MVI    D,00H
  123.         MOV    E,A
  124.         LXI    H,BUFF
  125.         DAD    D
  126.         MOV    A,M
  127.         CPI    1AH        ; CONTROL-Z IS EOF
  128.         JZ    GNA4
  129.         LXI    H,IPTR
  130.         INR    M
  131.         CPI     LF      ; DON'T TRANSMIT
  132.         JNZ     GNA3    ; LINE FEEDS
  133.         INX     D
  134.         JMP     GNA2
  135. GNA3:   ORA     A       ; CLEAR CARRY
  136.         JMP  GNA9
  137.  
  138. FREAD:            ; READ THE NEXT FILE RECORD
  139.         LXI     D,BUFF  ; SET DISK BUFFER ADDRESS
  140.         MVI     C,1AH   ; SET DMA ADDR
  141.         CALL    BDOS
  142.         MVI    C,14H      ;READ FILE RECORD
  143.         LXI    D,FCB
  144.         CALL    BDOS
  145.         ORA    A
  146.         JNZ    GNA4
  147.         STA    IPTR       ; ZERO PTR FOR START OF BUFFER
  148.         JMP    GNA1
  149.  
  150. GNA4:    MVI    A,1AH        ; INDICATE EOF
  151.         STC        ; BY SETTING CARRY
  152. GNA9:   POP    B
  153.     POP    D
  154.     POP    H
  155.     RET
  156. ;
  157. ;       
  158. PUTC:   PUSH    H       ; SEND A CHAR TO DISK BUFFER AND
  159.         PUSH    B       ; WRITE IT IF IT IS FULL
  160.         PUSH    D
  161.         PUSH    PSW     ; SAVE CHAR IN CASE ITS A CR
  162. PUTC2:  LHLD    OPTR
  163.         MOV     M,A     ; CHAR TO WRITE
  164.         INX     H
  165.         SHLD    OPTR
  166.         MOV     A,L     ; NOW SEE IF 128 BUFFER IS FULL
  167.         CPI     128
  168.         CNC     SAVDSK  ; WRITE THE BUFFER
  169.         POP     PSW
  170.         CPI     NEWLINE ; IF IT WAS A CR,
  171.         JNZ     PUTCX   ; WE NEED TO ADD
  172.         MVI     A,LF
  173.         PUSH    PSW     ; A LF
  174.         JMP     PUTC2
  175. PUTCX:  POP     D
  176.         POP     B
  177.         POP     H       ; DONE
  178.         RET
  179. ;
  180. SAVDSK:
  181.         LXI     H,DBUFF ;POINT TO START OF AREA TO SAVE
  182. SAVD10:
  183.         SHLD    OPTR            ;RESET POINTER
  184.         XCHG                    ;SET BUFFER ADR TO DBUFF
  185.         MVI     C,26
  186.         CALL    BDOS
  187.         LXI     D,OUTFCB                ;WRITE NEXT RECORD TO DISK
  188.         MVI     C,21
  189.         CALL    BDOS
  190.         CPI     0               ;WAS THERE AN ERROR?
  191.         RZ              ; NO. RETURN
  192.         LXI     D,DERMES        ;YES: COMPLAIN, CLOSE FILE & RET
  193.         MVI     C,9
  194.         CALL    BDOS
  195.         LXI     D,OUTFCB
  196.         MVI     C,16
  197.         CALL    BDOS
  198.         JMP     RETCPM
  199. ;
  200. AWAIT:  MVI     C,11    ; TEST CONSOLE STATUS
  201.         CALL    BDOS    ; FOR A CHARACTER
  202.         ANI     1       ; READY
  203.         JZ      AWAIT
  204.         RET             ; GOT ONE
  205.   
  206. DSKINI:                 ; INITIALIZE INPUT AND OUTPUT DISK FILES
  207.         LXI     D,IDMSG ; PRINT SIGN ON MSG
  208.         CALL    PRINT
  209.         LDA     FCBNM
  210.         CPI     20H
  211.         JZ      NONAME  ; PRINT HELP MESSAGE
  212.         LXI     H,'RN'  ; FILL IN 'RNO' FOR
  213.         SHLD    FCBFT   ; FILE NAME EXTENSION
  214.         MVI     A,'O'
  215.         STA     FCBFT+2
  216. ;
  217.         LXI     H,OUTFCB
  218.         LXI     D,FCB
  219. ;
  220.         MVI     B,13    ; NOW
  221. DSKL:   LDAX    D       ; MOVE OUTPUT FILE NAME TO OUTFCB
  222.         MOV     M,A     ; INCLUDING REEL NO.
  223.         INX     H
  224.         INX     D
  225.         DCR     B
  226.         JNZ     DSKL
  227. ;
  228.         LXI     H,'ME'  ; FILL IN 'MEM' FOR
  229.         SHLD    OUTFCB+9 ; FILE NAME EXTENSION
  230.         MVI     A,'M'
  231.         STA     OUTFCB+11
  232. ;
  233.         LXI     D,OUTFCB
  234.         PUSH    D
  235.         MVI     C,13H   ; DELETE OUTPUT FILE NAME
  236.         CALL    BDOS
  237.  
  238.         POP     D
  239.         MVI     C,22    ; MAKE A NEW OUTPUT FILE
  240.         CALL    BDOS
  241.  
  242.         CPI     0FFH
  243.         JZ      XOUTF   ; CANNOT CREATE NEW OUTPUT FILE NAME
  244.         XRA     A
  245.         STA     ORECN   ; SET OUTPUT RECORD NUMBER TO 0
  246.         LXI     H,DBUFF ; INITIALIZE DISK BUFFER
  247.         SHLD    OPTR    ; POINTER
  248.         MVI     C,0FH   ; OPEN INPUT FILE
  249.         LXI     D,FCB
  250.         CALL    BDOS
  251.  
  252.         CPI     0FFH
  253.         JZ      NOINF   ; INPUT FILE NOT FOUND
  254.         LXI     H,IPTR  ; SET POINTER TO END OF RECORD BUFF
  255.         MVI     M,128   ; SO INITIAL READ WILL HAPPEN
  256.         RET     
  257.  
  258. NOINF:  LXI     D,NOINFM
  259.         CALL    PRINT   
  260.         JMP     RETCPM
  261.         
  262. NOINFM: DB      CR,LF,'INPUT (.RNO) FILE NOT FOUND$'
  263.         
  264. DERMES: DB      CR,LF,'ERROR WRITING OUTPUT RECORD$'
  265.  
  266. IXM:    LXI     D,IXMS
  267.         CALL    PRINT   ;       PRINT   MSG
  268.         JMP     RETCPM
  269.         
  270. IDMSG:  DB      CR,LF,'RUN80 TEXT FORMATTER, Ver. 2.0 as of 04/08/81',CR,LF,'$'
  271.  
  272. IXMS:   DB      CR,LF,'INPUT READ ERROR$'
  273.         
  274. NONAME: DB      CR,LF,'START THIS PROGRAM AS: RUN80 filename$'
  275.         
  276. XOUTF:  LXI     D,XOUTM
  277.         CALL    PRINT   ;       PRINT   MSG
  278.         JMP     RETCPM
  279.  
  280. XOUTM:  DB      'CANNOT CREATE OUTPUT FILE$'
  281.         
  282. PRINT:  MVI     C,9     ;PRINT A MSG TO '$'
  283.         CALL    BDOS
  284.         RET     
  285.  
  286. RETCPM  JMP     BASE
  287. ;
  288. ;       DATA    AREAS
  289. ;
  290. IPTR:   DW      0       ;POINTER TO ASCII CHAR. IN INPUT BUFFER
  291. OUTFCB: DS      33      ; FCB FOR OUTPUT FILE
  292. ORECN   EQU     OUTFCB+32       ; RECORD NUMBER
  293. ;
  294.         DS      2       ; SAFETY SPACE
  295. MAINL:
  296.         LXI    H,INBUF
  297.         CALL    GETLIN
  298.         JC    FLUSH
  299.         MVI    A,'.'       ; COMMAND STARTS WITH PERIOD
  300.         CMP    M
  301.         JNZ    ITSTEXT
  302.         CALL     COMAND
  303.         JMP    MAINL
  304. ITSTEXT:
  305.         CALL    TEXT
  306.         JMP    MAINL
  307. FLUSH:  CALL    BRK        ; FINISH ANY POSSIBLE LINE 0
  308.         LHLD    LINENO
  309.         MOV    A,H
  310.         ORA    L
  311.         CZ      FINISH  ; TRULY AT TOP OF A PAGE
  312.         LXI    H,HUGE
  313.         CALL    SPACE
  314. FINISH: MVI     A,1AH   ; WRITE CP/M EOF CHARACTER
  315.         CALL    PUTC
  316.         LHLD    OPTR    ; SMALL CHANCE THAT WE JUST
  317.         LXI     D,DBUFF ; FINISHED WRITING A DISK BUFFER
  318.         CALL    COMPARE
  319.         CNZ     SAVDSK  ; WRITE BUFFER ON DISK
  320.         MVI     C,16    ; NOW CLOSE
  321.         LXI     D,FCB   ; INPUT FILE
  322.         CALL    BDOS
  323.         LXI     D,OUTFCB        ; AND CLOSE
  324.         MVI     C,16    ; OUTPUT FILE
  325.         CALL    BDOS
  326.         CALL    RETCPM
  327. ;
  328. FOOTER: DS LINSIZ+3     ; INCLUDES CR, LF AND EOS
  329. HEADER: DS LINSIZ+3
  330. INBUF:  DS TRIPLE       ; HOLDS INPUT LINE
  331. OUTBUF: DS TRIPLE       ; LINES TO BE FILLED COLLECT HERE
  332. WRDBUF: DS TRIPLE       ; USED BY PUTWRD
  333. BACKUP: DS 1    ; ROOM FOR ONE CHAR PUSHED BACK ONTO INPUT STREAM
  334. BOTTOM: DS 2    ; LAST LIVE LINE = PLVAL-M3VAL-M4VAL
  335. CEVAL:  DS 2    ; NUMBER OF INPUT LINES TO CENTER
  336. CURPAG: DS 2    ; CURRENT OUTPUT PAGE NO. (INIT = 0)
  337. DIR:    DS      1       ; DIRECTION OF SPREADING LINE TO ADD SPACES
  338. FILL:   DS 1    ; FILL IF YES (INIT = YES)
  339. INVAL:  DS 2    ; CURRENT INDENT VALUE. (INIT = 0)
  340. LAST:   DS 2
  341. LINENO: DS 2    ; NEXT LINE TO BE PRINTED. (INIT = 0)
  342. LLVAL:  DS 2
  343. LSVAL:  DS 2    ; CURRENT LINE SPACING (INIT = 1)
  344. M1VAL:  DS 2    ; MARGIN BEFORE AND INCLUDING HEADER (INIT = 3)
  345. M2VAL:  DS 2    ; MARGIN AFTER HEADER
  346. M3VAL:  DS 2    ; MARGIN AFTER LAST TEXT LINE
  347. M4VAL:  DS 2    ; BOTTOM MARGIN, INCLUDING FOOTER
  348. NB:     DS 2
  349. NNE:    DS 2
  350. NEWPAG: DS 2    ; NEXT OUTPUT PAGE NUMBER. (INIT = 1)
  351. NEXTRA: DS 2
  352. NHOLES: DS 2
  353. OUTP:   DS 2    ; LAST CHAR POSITION IN OUTBUF. (INIT = 0)
  354. OUTW:   DS 2    ; WIDTH OF TEXT NOW IN OUTPUT BUFF. (INIT = 0)
  355. OUTWDS: DS 2    ; NUMBER OF WORDS IN OUTBUF. (INIT = 0)
  356. PLVAL:  DS 2    ; PAGE LENGTH IN LINES. (INIT = PAGELEN)
  357. RMVAL:  DS 2    ; CURRENT RIGHT MARGIN. (INIT = PAGEWID)
  358. SPVAL:  DS 2
  359. TABSON: DS 1    ; SPACE FOR TABS FLAG. (INIT = NO TABS)
  360. TABPOS: DS 11   ; SPACE FOR UP TO 10 TAB STOPS AND END MARKER
  361. TIVAL:  DS 2    ; TEMPORARY INDENT VALUE. (INIT = 0)
  362. ULVAL:  DS 2    ; NUMBER OF INPUT LINES TO UNDERLINE
  363. WAITUP: DS 1            ;YES IF FORMAT SHOULD WAIT AT START OF EACH
  364. ;                       ; PAGE
  365. CMDTAB:
  366.         DB      'BR'
  367.         DW      BREAKC
  368.         DB      'CE'
  369.         DW      CTRC
  370.         DB      'FI'
  371.         DW      FILLC
  372.         DB      'FO'
  373.         DW      FOOTC
  374.         DB      'HE'
  375.         DW      HDR
  376.         DB      'IN'
  377.         DW      IND
  378.         DB      'NF'
  379.         DW      NOFILL
  380.         DB      'PG'
  381.         DW      PAGEC
  382.         DB      'PL'
  383.         DW      LGT
  384.         DB      'RM'
  385.         DW      MARGIN
  386.         DB      'SK'
  387.         DW      SKP
  388.         DB      'SP'
  389.         DW      SPACEC
  390.         DB      'TA'
  391.         DW      TABSET
  392.         DB      'TI'
  393.         DW      TEMPI
  394.         DB      'UL'
  395.         DW      UNDERC
  396. ;
  397.         DB      0       ; FLAG END OF TABLE
  398. ;
  399. ;-----
  400. ; ALPHA - TEST CHARACTER FOR LETTER
  401. ; ACCEPTS: A = CHARACTER
  402. ; RETURNS: CARRY SET IF A = A-Z OR a-z
  403. ;-----
  404. ;
  405. ALPHA:  CPI    'a'
  406.         JC    NOTLC
  407.         CPI    'z'+1
  408.         RC
  409. NOTLC:  CPI    'Z'+1
  410.         RNC
  411.         CPI    'A'
  412.         CMC
  413.         RET
  414. ;
  415. ; BRK - END CURRENT FILLED LINE
  416. ;-----
  417. ;
  418. BRK:    PUSH    PSW
  419.         PUSH    B
  420.         PUSH    D
  421.         PUSH    H
  422.         LXI    D,0
  423.         LHLD    OUTP
  424.         CALL    COMPARE
  425.         JNC    EMPTY
  426.         LXI    D,OUTBUF
  427.         DAD    D
  428.         MVI    M,EOS
  429.         DCX     H
  430.         MVI     M,NEWLINE
  431.         XCHG
  432.         CALL    PUT
  433. EMPTY:  LXI    H,0
  434.         SHLD    OUTP
  435.         SHLD    OUTW
  436.         SHLD    OUTWDS
  437.         POP    H
  438.         POP     D
  439.         POP    B
  440.         POP    PSW
  441.         RET
  442. ;
  443. ;-----
  444. ; CENTER - CENTER A LINE BY SETTING TIVAL
  445. ; ACCEPTS: HL = A LINE
  446. ;-----
  447. ;
  448. CTR:    PUSH H
  449.         CALL WIDTH
  450.         LHLD TIVAL
  451.         XCHG
  452.         CALL DELESSHL
  453.         XCHG
  454.         LHLD RMVAL
  455.         DAD D
  456.         CALL DIVBY2
  457.         LXI D,0
  458.         CALL MAX
  459.         SHLD TIVAL
  460.         POP H
  461.         RET
  462. ;
  463. ;-----
  464. ; CHRBAK - PUSH CHARACTER BACK ONTO INPUT
  465. ; ACCEPTS: B = CHARACTER
  466. ;-----
  467. ;
  468. CHRBAK: MOV A,B
  469.         STA BACKUP
  470.         RET
  471. ;
  472. ;-----
  473. ; COMMAND - PERFORM FORMATTING COMMAND
  474. ;-----
  475. ;
  476. COMAND:
  477.         LXI D,CMDTAB
  478.         INX H           ;GET ADDR KEYWORD (SKIP .)
  479.         CALL SEARCH     ;COMMAND IN TABLE?
  480.         RC              ;NO, IGNORE
  481.         PUSH D          ;STACK DISPATCH ADDRESS
  482.         CALL GETVAL
  483.         RET             ;JUMP TO COMMAND HANDLER
  484. ;                       ;DE = ADDR END OF COMMAND.
  485. ;                       ;HL = ARGUMENT VALUE
  486. BREAKC: CALL BRK
  487.         RET
  488. ;
  489. CTRC:
  490.         CALL BRK
  491.         LXI B,0
  492.         PUSH B
  493.         INX B
  494.         LXI D,HUGE
  495.         PUSH D
  496.         XCHG
  497.         LHLD CEVAL
  498.         CALL PSET
  499.         SHLD CEVAL
  500.         RET
  501. ;
  502. FOOTC:
  503.         LXI H,FOOTER
  504.         CALL GETTL
  505.         RET
  506. ;
  507. TEMPI:
  508.         CALL    BRK
  509.         LXI B,0
  510.         PUSH B
  511.         XCHG
  512.         LHLD RMVAL
  513.         PUSH H
  514.         LHLD TIVAL
  515.         CALL PSET
  516.         SHLD TIVAL
  517.         RET
  518. ;
  519. HDR:
  520.         LXI H,HEADER
  521.         CALL GETTL
  522.         RET
  523. ;
  524. IND:
  525.         LXI B,0
  526.         PUSH B
  527.         XCHG
  528.         LHLD RMVAL
  529.         DCX H
  530.         PUSH H
  531.         LHLD INVAL
  532.         CALL PSET
  533.         SHLD INVAL
  534.         SHLD TIVAL
  535.         RET
  536. ;
  537. NOFILL:
  538.         CALL BRK
  539.         MVI A,NO
  540.         STA FILL
  541.         RET
  542. ;
  543. FILLC:
  544.         CALL BRK
  545.         MVI A,YES
  546.         STA FILL
  547.         RET
  548. ;
  549. LGT:
  550.         PUSH H
  551.         LHLD M1VAL
  552.         XCHG
  553.         LHLD M2VAL
  554.         DAD D
  555.         XCHG
  556.         LHLD M3VAL
  557.         DAD D
  558.         XCHG
  559.         LHLD M4VAL
  560.         DAD D
  561.         INX H
  562.         XTHL
  563.         LXI B,HUGE
  564.         PUSH B
  565.         LXI B,PGLEN
  566.         XCHG
  567.         LHLD PLVAL
  568.         CALL PSET
  569.         SHLD PLVAL
  570.         XCHG
  571.         LHLD M3VAL
  572.         CALL DELESSHL
  573.         XCHG
  574.         LHLD M4VAL
  575.         CALL DELESSHL
  576.         SHLD BOTTOM
  577.         RET
  578. ;
  579. MARGIN:
  580.         XCHG
  581.         LHLD TIVAL
  582.         INX H
  583.         PUSH H
  584.         LXI H,HUGE
  585.         PUSH H
  586.         LXI B,PGWID
  587.         LHLD RMVAL
  588.         CALL PSET
  589.         SHLD RMVAL
  590.         RET
  591. ;
  592. PAGEC:  PUSH H
  593.         PUSH PSW
  594.         LXI D,0
  595.         LHLD LINENO
  596.         CALL COMPARE
  597.         LXI H,HUGE
  598.         CC SPACE
  599.         POP PSW
  600.         POP D
  601.         LXI B,-HUGE
  602.         PUSH B
  603.         LXI B,HUGE
  604.         PUSH B
  605.         LHLD CURPAG
  606.         MOV B,H
  607.         MOV C,L
  608.         INX B
  609.         CALL PSET
  610.         SHLD CURPAG
  611.         SHLD NEWPAG
  612.         RET
  613. ;
  614. SKP:    LXI B,0         ;STACK MINIMUM
  615.         PUSH B
  616.         INX B           ;FORM DEFAULT
  617.         LXI D,HUGE      ;STACK MAXIMUM
  618.         PUSH D
  619.         XCHG
  620.         LHLD SPVAL
  621.         CALL PSET
  622.         SHLD SPVAL
  623.         CALL SPACE
  624.         RET
  625. SPACEC: LXI B,1         ;GET MINIMUM AND DEFAULT
  626.         PUSH B          ;STACK MINIMUM
  627.         LXI D,HUGE      ;STACK MAXIMUM
  628. ;
  629.         PUSH D
  630.         XCHG            ;DE := ARGUMENT VALUE
  631.         LHLD LSVAL
  632.         CALL PSET
  633.         SHLD LSVAL
  634.         RET
  635. ;
  636. UNDERC: LXI B,1
  637.         PUSH B
  638.         DCX B
  639.         LXI D,HUGE
  640.         PUSH D
  641.         XCHG
  642.         LHLD ULVAL
  643.         CALL PSET
  644.         SHLD ULVAL
  645.         RET
  646. ;
  647. ;-----
  648. ; COMPARE - COMPARE TWO SIGNED NUMBERS
  649. ; ACCEPTS:  NUMBERS IN DE, HL
  650. ; RETURNS:  Z SET IF DE = HL
  651. ;           C SET IF DE < HL
  652. ;           C CLEAR IF DE >= HL
  653. ; DO THE USUAL SUBTACT, BUT COMPLEMENT THE CARRY
  654. ; IF THE ORIGINAL SIGNS ARE NOT EQUAL
  655. ;-----
  656. ;
  657. COMPARE:
  658.         MOV A,E
  659.         SUB L
  660.         MOV A,D
  661.         SBB H
  662.         PUSH PSW
  663.         MOV A,D
  664.         XRA H
  665.         ANI 80H
  666.         JNZ SIGNEQ
  667.         POP PSW
  668.         RET
  669. ;
  670. SIGNEQ: POP PSW
  671.         CMC
  672.         RET
  673. ;
  674. ;-----
  675. ; DELESSHL - SUBTRACT HL FROM DE
  676. ; RETURNS: HL = DE - HL
  677. ;-----
  678. ;
  679. DELESSHL:
  680.         MOV A,E
  681.         SUB L
  682.         MOV L,A
  683.         MOV A,D
  684.         SBB H
  685.         MOV H,A
  686.         RET
  687. ;
  688. ;-----
  689. ; DIVBY2 - DIVIDE SIGNED NUMBER IN HL BY TWO
  690. ; (SHIFT RIGHT BUT PROPAGATE THE SIGN)
  691. ;-----
  692. ;
  693. DIVBY2: MOV A,H
  694.         RAL
  695.         MOV A,H
  696.         RAR
  697.         MOV H,A
  698.         MOV A,L
  699.         RAR
  700.         MOV L,A
  701.         RET
  702. ;
  703. ;-----
  704. ; DIVIDE - DIVIDE DE BY HL
  705. ; ACCEPTS: HL = DIVISOR
  706. ;          DE = DIVIDEND
  707. ; RETURNS: HL = QUOTIENT
  708. ;-----
  709. ;
  710. DIVIDE: MOV B,H         ;MOVE DIVISOR TO BC
  711.         MOV C,L
  712.         LXI H,0         ;FORM INITIAL QUOTIENT
  713. DVLOOP: MOV A,E         ;DIVIDE BY SUBTRACTION
  714.         SUB C           ;(DE := DE - BC)
  715.         MOV E,A
  716.         MOV A,D
  717.         SBB B
  718.         MOV D,A
  719.         RC
  720.         INX H
  721.         JMP DVLOOP
  722. ;
  723. ;-----
  724. ; EXTEND - EXTEND A STRING BY INSERTING ONE CHARACTER
  725. ; ACCEPTS: C = CHAR TO INSERT
  726. ;          HL = ADDR OF WHERE TO INSERT IT IN STRING
  727. ;-----
  728. ;
  729. EXTEND: PUSH    H
  730.         PUSH    B
  731. EXTD2:  MOV     A,M     ; GET CHAR TO BE MOVED
  732.         MOV     M,C     ; REPLACE IT WITH CHAR IN C
  733.         MOV     C,A     ; AND REPEAT
  734.         INX     H       ; STEP TO NEXT CHAR
  735.         CPI     EOS     ; UNTIL THE END OF STRING
  736.         JNZ     EXTD2
  737.         MOV     M,C     ; STORE THE LAST CHAR = EOS
  738.         POP     B
  739.         POP     H
  740.         RET
  741. ;-----
  742. ; GETCHR - GET NEXT CHARACTER
  743. ; RETURNS:  CARRY SET IF EOF
  744. ;           ELSE A = CHARACTER
  745. ;-----
  746. ;
  747. GETCHR: LDA BACKUP      ;ANY CHARACTER BACKED UP?
  748.         CPI NEWLINE     ;(NEWLINE CAN'T BE BACKED UP,
  749. ;                       ; IT MEANS BACKUP IS EMPTY)
  750.         JZ GETC         ;NO, READ NEXT CHARACTER
  751.         MOV B,A         ;YES, SAVE CHARACTER IN B
  752.         MVI A,NEWLINE   ;GET NEWLINE
  753.         STA BACKUP      ;EMPTY BACKUP
  754.         MOV A,B         ;RESTORE CHARACTER
  755.         ORA A           ;CLEAR CARRY
  756.         RET
  757. GETC:   CALL GNASC      ;GET NEXT CHARACTER
  758.         RET
  759. ;
  760. ;-----
  761. ; GETLIN - FILL BUFFER WITH NEXT INPUT LINE
  762. ; ACCEPTS:  HL (SAVED) = ADDR BUFFER
  763. ; RETURNS:  CARRY SET IF EOF
  764. ;           ELSE LINE TERMINATED BY EOL, EOS
  765. ;-----
  766. ;
  767. GETLIN: MOV D,H         ;SAVE ADDR OF  BUFFER IN DE
  768.         MOV E,L
  769.         MVI C,0         ;INITIALIZE LINE LENGTH
  770. GETNXT: MVI A,LINSIZ    ; GET MAXIMUM CHARACTERS PER LINE
  771.         CMP C           ;LINE BUFFER FULL?
  772.         JZ LINFIN       ;YES, FORCE NEW LINE
  773.         CALL    GETCHR  ;GET NEXT CHARACTER
  774.         JC LINEND       ;HANDLE EOF
  775.         MOV B,A         ;SAVE CHARACTER IN B
  776.         CPI NEWLINE     ;END OF LINE?
  777.         JZ      LINFIN  ; FOUND END OF LINE
  778.         MOV M,B         ;SAVE CHARACTER IN BUFFER
  779.         INX H           ;POINT TO NEXT CHARACTER POSITION
  780.         INR C           ;ADJUST # OF CHARACTERS SAVED
  781.         JMP GETNXT      ;GET NEXT CHARACTER
  782. ;
  783. LINFIN: MVI M,NEWLINE   ;END LINE WITH CARRIAGE RETURN
  784.         INX H           ;AND
  785.         MVI M,EOS       ;END OF STRING
  786.         XCHG            ;RESTORE HL
  787.         ORA A           ;CLEAR CARRY
  788.         RET
  789. LINEND: MOV A,C         ;BUFFER EMPTY?
  790.         ORA C           ;( COUNT ZERO?)
  791.         JNZ LINFIN      ;NO, PROVIDE EOL 
  792.         STC             ;YES, TRUE EOF
  793.         RET
  794. ;
  795. ;-----
  796. ; GETTL - COPY TITLE
  797. ; ACCEPTS:  DE = ADDR END OF COMMAND
  798. ;           HL = ADDR DESTINATION
  799. ;
  800. ;-----
  801. ;
  802. GETTL:          ; called after leading blanks and tabs have been skipped
  803.         LDAX D
  804.         INX D
  805.         CPI ''''
  806.         JZ COPYTL
  807.         CPI '"'
  808.         JZ COPYTL
  809.         DCX D
  810. COPYTL: CALL SCOPY
  811.         RET
  812. ;
  813. ;-----
  814. ; GETVAL - EVALUATE OPTIONAL NUMERIC ARGUMENT
  815. ; ACCEPTS:  DE = ADDR OF END OF COMMAND
  816. ; RETURNS:   A = ARGTYP
  817. ;           HL = ARGUMENT VALUE
  818. ;           DE = ADDR OF COMMAND PAST ARGUMENT
  819. ;-----
  820. ;
  821. FNDARG: INX H           ;GET ADDR NEXT CHARACTER
  822. GETVAL:
  823.         MOV A,M         ;GET NEXT CHARACTER
  824.         CPI ' '         ;BLANK?
  825.         JZ FNDARG       ;YES, KEEP SEARCHING FOR ARGUMENT
  826.         CPI TAB         ;NO, TAB?
  827.         JZ FNDARG       ;YES, KEEP SEARCHING
  828.         CPI ','         ; COMMA ALSO CAN BE
  829.         JZ FNDARG       ; ALLOWED AS DELIMITER
  830.         INX H           ;ASSUME CHARACTER IS '+' OR '-'
  831.         CPI '+'         ;IS IT '+'?
  832.         JZ CTOI         ;YES
  833.         CPI '-'         ;NO, IS IT '-'?
  834.         JZ CTOI         ;YES
  835.         DCX H           ;NO, RESTORE ADDR ARGUMENT
  836. CTOI:   PUSH PSW        ;SAVE ARGTYP
  837.         XCHG            ;KEEP ADDR ARGUMENT IN DE
  838.         LXI H,0         ;INITIALIZE ARGUMENT CHARACTER
  839. VALOOP: LDAX D          ;GET NEXT ARGUMENT CHARACTER
  840.         CPI '0'         ;< '0'?
  841.         JC GOTVAL       ;YES, END OF ARGUMENT
  842.         CPI '9'+1       ;NO, >'9'?
  843.         JNC GOTVAL      ;YES, END OF ARGUMENT
  844.         INX D           ;GET ADDR NEW ARGUMENT CHARACTER
  845.         MOV B,H         ;NO, SAVE CURRENT VALUE
  846.         MOV C,L         ;IN BC
  847.         DAD H           ;DOUBLE CURRENT VALUE
  848.         DAD H           ;QUADRUPLE
  849.         DAD B           ;QUINTUPLE
  850.         DAD H           ;DECTUPLE
  851.         SUI '0'         ;CONVERT NEW CHARACTER IN BINARY
  852.         ADD L           ;ADD TO NEW VALUE
  853.         MOV L,A
  854.         JNC VALOOP
  855.         INR H
  856.         JMP VALOOP
  857. GOTVAL: POP PSW         ;RESTORE ARGTYP
  858.         RET
  859. ;
  860. ;-----
  861. ; GETWRD - GET NEXT WORD
  862. ; ACCEPTS:  HL = ADDR TEXT
  863. ; RETURNS:  CARRY SET IF NONE FOUND
  864. ;           ELSE HL = ADDR EORD, EOS
  865. ;                DE = ADDR TEXT FOLLOWING WORD
  866. ;-----
  867. ;
  868. GETWRD: MOV A,M
  869.         INX H
  870.         CPI ' '
  871.         JZ GETWRD
  872.         CPI TAB
  873.         JZ GETWRD
  874.         DCX H
  875.         MOV D,H
  876.         MOV E,L
  877. GWLOOP: MOV A,M
  878.         INX H
  879.         CPI EOS
  880.         JZ WRDEND
  881.         CPI NEWLINE
  882.         JZ WRDEND
  883.         CPI TAB
  884.         JZ WRDEND
  885.         CPI ' '
  886.         JNZ GWLOOP
  887. WRDEND: DCX H
  888.         MVI M,EOS
  889.         CALL COMPARE
  890.         XCHG
  891.         CMC
  892.         INX D
  893.         RET
  894. ;
  895. ;-----
  896. ; INIT - INITIALIZE VARIABLES
  897. ;-----
  898. ;
  899. INIT:   MVI A,NO
  900.         STA WAITUP      ;SAVE WAIT OPTION FLAG
  901.         STA TABSON      ; TURN TABS OFF
  902.         STA TABPOS      ; FLAG END OF TABSTOP ARRAY
  903.         MVI A,NEWLINE   ;INITIALIZE
  904.         STA BACKUP      ;BACKUP CHARACTER
  905.         STA HEADER
  906.         STA FOOTER
  907.         MVI A,EOS
  908.         STA HEADER+1
  909.         STA FOOTER+1
  910.         MVI A,YES
  911.         STA FILL
  912.         LXI H,0
  913.         SHLD INVAL
  914.         SHLD TIVAL
  915.         SHLD CEVAL
  916.         SHLD ULVAL
  917.         SHLD LINENO
  918.         SHLD CURPAG
  919.         SHLD OUTP
  920.         SHLD OUTW
  921.         SHLD OUTWDS
  922.         INX H
  923.         SHLD LSVAL
  924.         SHLD NEWPAG
  925.         INX H
  926.         SHLD M2VAL
  927.         SHLD M3VAL
  928.         INX H
  929.         SHLD M1VAL
  930.         SHLD M4VAL
  931.         LXI H,PGWID
  932.         SHLD RMVAL
  933.         LXI H,PGLEN
  934.         SHLD PLVAL
  935.         XCHG
  936.         LHLD M3VAL
  937.         CALL DELESSHL
  938.         XCHG
  939.         LHLD M4VAL
  940.         CALL DELESSHL
  941.         SHLD BOTTOM
  942.         RET
  943. ;
  944. ;-----
  945. ; LEADBL - "DELETE"  LEADING BLANKS, SET TIVAL
  946. ; ACCEPTS: HL = ADDR LINE
  947. ; RETURNS: HL = ADDR FIRST NON-BLANK
  948. ;-----
  949. ;
  950. LEADBL: CALL BRK
  951.         LXI D,0
  952. LBLOOP: MOV A,M
  953.         INX D
  954.         INX H
  955.         CPI ' '
  956.         JZ LBLOOP
  957.         DCX H
  958.         CPI NEWLINE
  959.         RZ
  960.         XCHG
  961.         SHLD TIVAL
  962.         XCHG
  963.         RET
  964. ;
  965. ;-----
  966. ; LENGTH - COMPUTE LENGTH OF STRING
  967. ; ACCEPTS:  HL = ADDR STRING
  968. ; RETURNS:  DE = LENGTH
  969. ;-----
  970. LENGTH: LXI D,0
  971. LENEXT: MOV A,M
  972.         CPI EOS
  973.         RZ
  974.         INX D
  975.         INX H
  976.         JMP LENEXT
  977. ;
  978. ;-----
  979. ; MAX DETERMINE LARGER OF TWO NUMBERS
  980. ; ACCEPTS: NUMBERS IN DE, HL
  981. ; RETURNS:  HL = LARGER
  982. ;           DE = SMALLER
  983. ;-----
  984. ;
  985. MAX:    CALL MIN
  986.         XCHG
  987.         RET
  988. ;
  989. ;-----
  990. ; MIN DETERMINE SMALLER OF TWO NUMBERS
  991. ; ACCEPTS: NUMBERS IN DE, HL
  992. ; RETURNS:  DE = LARGER
  993. ;           HL = SMALLER
  994. ;-----
  995. ;
  996. MIN:    CALL COMPARE
  997.         RNC
  998.         XCHG
  999.         RET
  1000. ;
  1001. ;-----
  1002. ; PFOOT - PUT OUT PAGE FOOTER
  1003. ;-----
  1004. ;
  1005. PFOOT:  LHLD M3VAL
  1006.         CALL SKIP
  1007.         LXI D,0
  1008.         LHLD M4VAL
  1009.         CALL COMPARE
  1010.         RNC
  1011.         LXI D,FOOTER
  1012.         LHLD CURPAG
  1013.         CALL PUTTL
  1014.         LHLD M4VAL
  1015.         DCX H
  1016.         CALL SKIP
  1017.         RET
  1018. ;
  1019. ;-----
  1020. ; PHEAD - PUT OUT PAGE HEADER
  1021. ;-----
  1022. ;
  1023. PHEAD:  PUSH D
  1024.         PUSH H          
  1025.         LDA WAITUP      ;GET W: OPTION FLAG
  1026.         CPI YES         ;WAIT FOR OPERATOR?
  1027.         CZ AWAIT        ;YES, WAIT FOR CONSOLE INPUT
  1028.         LHLD NEWPAG
  1029.         SHLD CURPAG
  1030.         INX H
  1031.         SHLD NEWPAG
  1032.         LHLD M1VAL
  1033.         PUSH H
  1034.         LXI D,0
  1035.         CALL COMPARE
  1036.         JNC SKPHDR
  1037.         DCX H
  1038.         CALL SKIP
  1039.         LXI D,HEADER
  1040.         LHLD CURPAG
  1041.         CALL PUTTL
  1042. SKPHDR: LHLD M2VAL
  1043.         PUSH H
  1044.         CALL SKIP
  1045.         POP H
  1046.         POP D
  1047.         DAD D
  1048.         INX H
  1049.         SHLD LINENO
  1050.         POP H
  1051.         POP D
  1052.         RET
  1053. ;
  1054. ;-----
  1055. ; PUT - PUT OUT LINE WITH PROPER SPACING AND INDENTING
  1056. ; ACCEPTS:  HL = ADDR LINE
  1057. ;-----
  1058. ;
  1059. PUT:    PUSH H
  1060.         LHLD LINENO
  1061.         MOV A,H
  1062.         ORA L
  1063.         JNZ NOT0
  1064.         CALL PHEAD
  1065.         JMP HEADED
  1066. NOT0:   XCHG
  1067.         LHLD BOTTOM
  1068.         XCHG
  1069.         CALL COMPARE
  1070.         JNC HEADED
  1071.         CALL PHEAD
  1072. HEADED: LHLD TIVAL
  1073. TITEST: MOV A,H
  1074.         ORA L
  1075.         JZ TIZERO
  1076.         MVI A,' '
  1077.         CALL PUTC
  1078.         DCX H
  1079.         JMP TITEST
  1080. TIZERO: LHLD INVAL
  1081.         SHLD TIVAL
  1082.         POP H
  1083.         CALL PUTLIN     ; PUT LINE OUT IN DISK BUFFER
  1084.         LHLD BOTTOM
  1085.         XCHG
  1086.         LHLD LINENO
  1087.         CALL DELESSHL
  1088.         XCHG
  1089.         LHLD LSVAL
  1090.         DCX H
  1091.         CALL MIN
  1092.         CALL SKIP
  1093.         LHLD LSVAL
  1094.         XCHG
  1095.         LHLD LINENO
  1096.         DAD D
  1097.         SHLD LINENO
  1098.         XCHG
  1099.         LHLD BOTTOM
  1100.         XCHG
  1101.         CALL COMPARE
  1102.         CC PFOOT
  1103.         RET
  1104. ;
  1105. ;-----
  1106. ; PUTDEC - OUTPUT DECIMAL NUMBER
  1107. ; ACCEPTS:  HL = NUMBER
  1108. ;-----
  1109. ;
  1110. PUTDEC: PUSH D
  1111.         PUSH H
  1112.         LXI D,TENTAB
  1113.         PUSH D
  1114.         MVI C,1
  1115. DOTPOS: XTHL
  1116.         MOV E,M
  1117.         INX H
  1118.         MOV D,M
  1119.         INX H
  1120.         XTHL
  1121.         MVI B,0FFH
  1122. DOTDIV: INR B
  1123.         MOV A,L
  1124.         SUB E
  1125.         MOV L,A
  1126.         MOV A,H
  1127.         SBB D
  1128.         MOV H,A
  1129.         JNC DOTDIV
  1130.         DAD D
  1131.         XRA A
  1132.         ORA B
  1133.         JNZ DOTPRI
  1134.         ORA C
  1135.         JNZ DOTSKP
  1136. DOTPRI: ORI '0'
  1137.         MVI C,0
  1138.         CALL PUTC
  1139. DOTSKP: MOV A,E
  1140.         CPI 1
  1141.         JNZ DOTPOS
  1142.         POP D
  1143.         POP H
  1144.         POP D
  1145.         RET
  1146. TENTAB: DW  10000
  1147.         DW 1000
  1148.         DW 100
  1149.         DW 10
  1150.         DW 1
  1151. ;
  1152. ;-----
  1153. ; PUTLIN - OUTPUT LINE
  1154. ; ACCEPTS: HL = ADDR LINE
  1155. ;-----
  1156. ;
  1157. PUTLIN: MOV A,M
  1158.         CPI EOS
  1159.         RZ
  1160.         LDA     FILL    ; IF FILLING
  1161.         CPI     NO      ; THEN POSSIBLE
  1162.         MOV     A,M     ; (GET CHAR BACK)
  1163.         JZ      PUTL6   ; TRANSLATION NEEDED
  1164.         CPI     LIT     ; IS NEXT CHAR TO BE
  1165.         JNZ     PUTL2   ; SENT LITERALLY?
  1166.         INX     H       ; YES. SO
  1167.         MOV     A,M     ; GET IT
  1168.         JMP     PUTL6
  1169. PUTL2:  CPI     NONEX   ; IS IT A NON-EXPANDABLE BLANK?
  1170.         JNZ     PUTL6   ; NO
  1171.         MVI     A,' '   ; YES. SO CHANGE IT TO BLANK.
  1172. PUTL6:  CALL PUTC
  1173.         INX H
  1174.         JMP PUTLIN
  1175. ;-----
  1176. ; PUTTL - PUT OUT TITLE LINE WITH OPTIONAL PAGE NUMBER
  1177. ; ACCEPTS:  DE = ADDR LINE
  1178. ;           HL = PAGE #
  1179. ;-----
  1180. ;
  1181. PUTTL:  LDAX D
  1182.         INX D
  1183.         CPI EOS
  1184.         RZ
  1185.         CPI PAGENUM
  1186.         JNZ TLCOPY
  1187.         CALL PUTDEC
  1188.         JMP PUTTL
  1189. TLCOPY: CALL PUTC
  1190.         JMP PUTTL
  1191. ;
  1192. ;-----
  1193. ; PUTWRD - PUT A WORD IN OUTBUF
  1194. ; ACCEPTS: HL = ADDR WORD
  1195. ;-----
  1196. ;
  1197. PUTWRD: PUSH D
  1198.         PUSH H
  1199.         CALL WIDTH
  1200.         MOV B,D         ;BC := W
  1201.         MOV C,E
  1202.         POP H
  1203.         PUSH H
  1204.         CALL LENGTH
  1205.         LHLD OUTP
  1206.         DAD D
  1207.         INX H
  1208.         SHLD LAST
  1209.         LHLD RMVAL
  1210.         XCHG
  1211.         LHLD TIVAL
  1212.         CALL DELESSHL
  1213.         SHLD LLVAL
  1214.         XCHG
  1215.         LHLD OUTW
  1216.         DAD B
  1217.         CALL COMPARE
  1218.         JC MAYFIT
  1219.         LHLD LAST
  1220.         XCHG
  1221.         LXI H,TRIPLE
  1222.         CALL COMPARE
  1223.         JC FITS
  1224. MAYFIT: LXI D,0
  1225.         LHLD OUTP
  1226.         CALL COMPARE
  1227.         JNC FITS
  1228.         XCHG
  1229.         LHLD LAST
  1230.         XCHG
  1231.         CALL DELESSHL
  1232.         SHLD LAST
  1233.         LHLD LLVAL
  1234.         XCHG
  1235.         LHLD OUTW
  1236.         CALL DELESSHL
  1237.         INX H
  1238.         SHLD NEXTRA
  1239.         PUSH B
  1240.         PUSH H
  1241.         CALL SPREAD
  1242.         POP H
  1243.         POP B
  1244.         LXI D,0
  1245.         CALL COMPARE
  1246.         JNC FLUSHIT
  1247.         INX D
  1248.         LHLD OUTWDS
  1249.         CALL COMPARE
  1250.         JNC FLUSHIT
  1251.         LHLD NEXTRA
  1252.         XCHG
  1253.         LHLD OUTP
  1254.         DAD D
  1255.         SHLD OUTP
  1256. FLUSHIT:        
  1257.         CALL BRK
  1258. FITS:   LXI D,OUTBUF
  1259.         LHLD OUTP
  1260.         DAD D
  1261.         POP D
  1262.         CALL SCOPY
  1263.         LHLD LAST
  1264.         SHLD OUTP
  1265.         LXI D,OUTBUF
  1266.         DAD D
  1267.         DCX H
  1268.         MVI M, ' '
  1269.         LHLD OUTW
  1270.         DAD B
  1271.         INX H
  1272.         SHLD OUTW
  1273.         LHLD OUTWDS
  1274.         INX H
  1275.         SHLD OUTWDS
  1276.         POP D
  1277.         RET
  1278. ;
  1279. ;-----
  1280. ; SCOPY - COPY STRINGS
  1281. ; ACCEPTS:  DE = ADDR SOURCE
  1282. ;           HL = ADDR DESTINATION
  1283. ;-----
  1284. ;
  1285. SCOPY:  LDAX D
  1286.         MOV M,A
  1287.         CPI EOS
  1288.         RZ
  1289.         INX D
  1290.         INX H
  1291.         JMP SCOPY
  1292. ;
  1293. ;-----
  1294. ; SEARCH - SEARCH TABLE FOR A COMMAND
  1295. ; ACCEPTS:
  1296. ;           DE = ADDR CMMND TABLE
  1297. ;           HL = ADDR COMMAND
  1298. ; RETURNS:  CARRY SET IF COMMAND NOT IN TABLE
  1299. ;           ELSE DE = ADDRESS FROM TABLE
  1300. ;                HL = ADDR END OF COMMAND
  1301. ;-----
  1302. ;
  1303. SEARCH: PUSH    H       ; SAVE START OF COMMAND
  1304.         LDAX    D       ; GET TABLE ENTRY
  1305.         ANA     A       ; AT END?
  1306.         JNZ     SRCH1   ; NO
  1307.         POP     H       ; NOT FOUND
  1308.         STC             ; YES
  1309.         RET
  1310. SRCH1:  XRA     M       ; COMBINE WITH FIRST COMMAND LETTER
  1311.         ANI     5FH     ; MAKE UPPER CASE
  1312.         JNZ     SRCH3   ; NO MATCH
  1313.         INX     D
  1314.         INX     H
  1315.         LDAX    D
  1316.         XRA     M
  1317.         ANI     5FH     ; CHECK SECOND CHARACTER
  1318.         JNZ     SRCH2   ; NO MATCH
  1319. ; WE FOUND A COMMAND
  1320.         INX     D
  1321.         XCHG            ; POINT HL TO COMMAND ADDRESS
  1322.         MOV     E,M     ; PUT COMMAND ADDRESS
  1323.         INX     H
  1324.         MOV     D,M     ; IN DE
  1325.         POP     H       ; GET OLD START OF COMMAND
  1326.         INX     H       ; POINT PAST COMMAND
  1327. SRCH8:  INX     H       ; NOW MOVE TO END OF CMND WORD
  1328.         MOV     A,M
  1329.         CPI     EOS
  1330.         JZ      SRCH9   ; NO MORE ON LINE
  1331.         CPI     ' '     ; BLANK
  1332.         JZ      SRCH9
  1333.         CPI     TAB     ; OR TAB
  1334.         JNZ     SRCH8   ; MUST BE A LETTER
  1335. SRCH9:  ORA     A       ; CLEAR CARRY
  1336.         RET
  1337. ;
  1338. SRCH3:  INX     D
  1339. SRCH2:  INX     D
  1340.         INX     D       ; BYPASS COMMAND ADDRESS
  1341.         INX     D
  1342.         POP     H
  1343.         JMP     SEARCH  ; AND LOOK SOME MORE
  1344. ;
  1345. ;
  1346. ;-----
  1347. ; SET - SET PARAMETER AND CHECK RANGE
  1348. ; ACCEPTS:  A = ARGTYP
  1349. ;          BC = DEFAULT VALUE
  1350. ;          DE = ARGUMENT VALUE
  1351. ;          HL = PARAMETER VALUE
  1352. ;          TOP OF STACK = MAXIMUM VALUE
  1353. ;          NEXT STACKED = MINIMUM VALUE
  1354. ; RETURNS: HL = NEW PARAMETER VALUE
  1355. ;-----
  1356. ;
  1357. PSET:   CPI NEWLINE     ;IS THERE AN ARGUMENT?
  1358.         JZ DEFAULTED    ;NO
  1359.         CPI '+'         ;YES, INCREASE?
  1360.         JZ RELPLUS      ;YES
  1361.         CPI '-'         ;NO, DECREASE?
  1362.         XCHG            ;(ASSUME NOT: USE ABSOLUTE ARGUMENT)
  1363.         JZ RELMINUS     ;YES
  1364. MINMAX: POP B           ;GET RETURN ADDRESS
  1365.         POP D           ;HL = PARAM, GET MAXVAL
  1366.         CALL MIN        ;USE SMALLER OF MAXVAL AND PARAM
  1367.         POP D           ;GET MINVAL
  1368.         CALL MAX        ;USE LARGER OF MINVAL AND PARAM
  1369.         PUSH B
  1370.         RET
  1371. DEFAULTED:
  1372.         MOV H,B         ;USE DEFVAL
  1373.         MOV L,C         ;FOR PARAM
  1374.         JMP MINMAX
  1375. RELPLUS:
  1376.         DAD D           ;INCREASE PARAM
  1377.         JMP MINMAX
  1378. RELMINUS:
  1379.         CALL DELESSHL   ;DECREASE PARAM
  1380.         JMP MINMAX
  1381. ;
  1382. ;-----
  1383. ; SKIP - OUTPUT BLANK LINES
  1384. ; ACCEPTS:  HL = # OF LINES TO SKIP
  1385. ;-----
  1386. ;
  1387. SKIP:   MOV     A,H
  1388.         ORA L
  1389.         RZ
  1390.         MVI A,NEWLINE
  1391.         CALL PUTC
  1392.         DCX H
  1393.         JMP SKIP
  1394. ;
  1395. ;-----
  1396. ; SPACE - SPACE SOME LINES OR TO BOTTOM OF PAGE
  1397. ; ACCEPTS: HL = # OF LINES
  1398. ;-----
  1399. ;
  1400. SPACE:  CALL BRK
  1401.         MOV B,H
  1402.         MOV C,L
  1403.         LHLD BOTTOM
  1404.         XCHG
  1405.         LHLD LINENO
  1406.         CALL COMPARE
  1407.         RC
  1408.         PUSH B
  1409.         MOV A,H
  1410.         ORA L
  1411.         CZ PHEAD
  1412.         INX D
  1413.         CALL DELESSHL
  1414.         POP B
  1415.         MOV D,B
  1416.         MOV E,C
  1417.         CALL MIN
  1418.         CALL SKIP
  1419.         LHLD LINENO
  1420.         DAD B
  1421.         SHLD LINENO
  1422.         XCHG
  1423.         LHLD BOTTOM
  1424.         XCHG
  1425.         CALL COMPARE
  1426.         CC PFOOT
  1427.         RET
  1428. ;
  1429. ;-----
  1430. ; SPREAD - SPREAD WORDS TO JUSTIFY RIGHT MARGIN
  1431. ;-----
  1432. ;
  1433. SPREAD: LXI D,0
  1434.         LHLD NEXTRA
  1435.         CALL COMPARE
  1436.         RNC
  1437.         INX D
  1438.         LHLD OUTWDS
  1439.         CALL COMPARE
  1440.         RNC
  1441.         LDA DIR
  1442.         CMA
  1443.         STA DIR
  1444.         DCX H
  1445.         SHLD NHOLES
  1446.         LHLD NEXTRA
  1447.         SHLD NNE
  1448.         XCHG
  1449.         LHLD OUTP
  1450.         DCX H
  1451.         PUSH H
  1452.         DAD D
  1453.         LXI D,TRIPLE-2
  1454.         CALL MIN
  1455.         LXI D,OUTBUF
  1456.         DAD D
  1457.         XTHL
  1458.         DAD D
  1459.         POP D
  1460.         XCHG
  1461. SPLOOP: DCX D
  1462.         DCX H
  1463.         CALL COMPARE
  1464.         RNC
  1465.         LDAX D
  1466.         MOV M,A
  1467.         CPI ' '
  1468.         JNZ SPLOOP
  1469.         PUSH D
  1470.         PUSH H
  1471.         LDA DIR
  1472.         PUSH PSW
  1473.         LHLD NNE
  1474.         CPI 0
  1475.         JNZ SP1
  1476.         DCX H
  1477. SP1:    XCHG
  1478.         LHLD NHOLES
  1479.         CALL DIVIDE
  1480.         POP PSW
  1481.         CPI 0
  1482.         JNZ SP2
  1483.         INX H
  1484. SP2:    SHLD NB
  1485.         XCHG
  1486.         LHLD NNE
  1487.         XCHG
  1488.         CALL DELESSHL
  1489.         SHLD NNE
  1490.         LHLD NHOLES
  1491.         DCX H
  1492.         SHLD NHOLES
  1493.         LXI D,0
  1494.         LHLD NB
  1495. SP3:    CALL COMPARE
  1496.         JNC SP4
  1497.         XTHL
  1498.         DCX H
  1499.         MVI M,' '
  1500.         XTHL
  1501.         DCX H
  1502.         JMP SP3
  1503. SP4:    POP H
  1504.         POP D
  1505.         JMP SPLOOP
  1506. ;-----
  1507. ; TABS - EXPAND TABS IN A LINE TO SPACES USING A TABPOS ARRAY
  1508. ; ACCEPTS: HL = ADDR OF LINE
  1509. ; RETURNS: HL UNCHANGED
  1510. ;-----
  1511. ;
  1512. TABS:   PUSH    H       ; SAVE FOR EXIT
  1513.         MVI     B,1     ; B COUNTS POSITION OF CHAR IN LINE
  1514.         LXI     D,TABPOS+10 ; ADDRESS OF FIRST TAB STOP
  1515. ; LOOK FOR A TAB
  1516. TABS2:  MOV     A,M     ; GET CHAR
  1517.         CPI     TAB     ; IS IT A TAB?
  1518.         JZ      TABS4   ; YES
  1519.         CPI     EOS     ; IS IT THE END OF THE LINE
  1520.         JZ      TABSX   ; YES
  1521. TABS3:  INX     H       ; ADVANCE TO NEXT CHAR IN LINE
  1522.         INR     B       ; ADVANCE POSITION COUNT
  1523.         JMP     TABS2
  1524. TABS4:  LDA     FILL    ; IF WE NOT FILLING
  1525.         CPI     YES
  1526.         JZ      TABS5
  1527.         MVI     C,' '   ; USE A SPACE
  1528.         JMP     TABS6   ; OTHERWISE
  1529. TABS5:  MVI     C,NONEX ; USE A NON-EXPANDABLE BLANK
  1530. TABS6:  MOV     M,C     ; REPLACE TAB
  1531. TABS7:  INX     H
  1532.         INR     B
  1533. TABS8:  LDAX    D       ; GET TAB STOP POSITION
  1534.         CPI     0       ; AT END?
  1535.         JZ      TABSX   ; YES
  1536.         CMP     B       ; CHECK IT AGAINST LINE POSITION
  1537.         JZ      TABS3   ; ONE POSITION TOOK US TO NEXT STOP
  1538.         JC      TABS9   ; TRY THE NEXT TAB STOP
  1539.         CALL    EXTEND  ; MOVE THE LINE BY INSERTING REG C
  1540.         JMP     TABS7   ; SEE IF AT STOP NOW
  1541. ;
  1542. TABS9:  DCX     D       ; TRY NEXT TAB STOP POSITION
  1543.         JMP     TABS8
  1544. ;
  1545. TABSX:  POP     H
  1546.         RET
  1547. ;
  1548. ;-----
  1549. ; TABSET - SCAN COMMAND LINE FOR TAB STOP POSITIONS
  1550. ; ACCEPTS: HL = FIRST VALUE
  1551. ;-----
  1552. ;
  1553. ;
  1554. TABSET:         ; SET TABSTOP ARRAY
  1555.         LXI     B,10
  1556.         MVI     A,NO    ; TURN OFF
  1557.         STA     TABSON  ; TABS. (DEFAULT)
  1558. TABSE2: MOV     A,L     ; GET FIRST VALUE
  1559.         LXI     H,TABPOS        ; ARRAY OF STOPS
  1560.         DAD     B
  1561.         MOV     M,A     ; AND STORE IT
  1562.         CPI     0       ; IF ZERO,
  1563.         RZ              ; WE ARE DONE
  1564.         MVI     A,YES
  1565.         STA     TABSON  ; TURN ON TABS
  1566.         XCHG            ; HL POINTS AT DELIM. OF VALUE
  1567.         PUSH    B       ; SAVE COUNT
  1568.         CALL    GETVAL  ; LOOK FOR MORE TAB POSITIONS
  1569.         POP     B
  1570.         DCX     B
  1571.         JNZ     TABSE2
  1572.         RET
  1573. ;
  1574. ;-----
  1575. ; TEXT - PROCESS TEXT LINES
  1576. ; ACCEPT:  HL = ADDR LINE
  1577. ;-----
  1578. ;
  1579. TEXT:   LDA     TABSON  ; SHOULD WE LOOK FOR TABS?
  1580.         CPI     NO
  1581.         JZ      TEXT2
  1582.         CALL    TABS    ; GO CONVERT TABS
  1583. TEXT2:  MOV A,M
  1584.         CPI ' '
  1585.         JZ MOVLFT
  1586.         CPI NEWLINE
  1587.         JNZ UNDERG
  1588. MOVLFT: CALL LEADBL
  1589. UNDERG:
  1590.         PUSH H
  1591.         LXI D,0
  1592.         LHLD ULVAL
  1593.         CALL COMPARE
  1594.         JNC CENTG
  1595.         LXI H,TRIPLE
  1596.         LXI D,WRDBUF
  1597.         POP B
  1598.         PUSH B
  1599.         CALL UNDERL
  1600.         LHLD ULVAL
  1601.         DCX H
  1602.         SHLD ULVAL
  1603. CENTG:
  1604.         LXI D,0
  1605.         LHLD CEVAL
  1606.         CALL COMPARE
  1607.         JNC ALLBLANK
  1608.         POP H
  1609.         CALL CTR
  1610.         CALL PUT
  1611.         LHLD CEVAL
  1612.         DCX H
  1613.         SHLD CEVAL
  1614.         RET
  1615. ALLBLANK:
  1616.         POP H
  1617.         MOV A,M
  1618.         CPI NEWLINE
  1619.         JNZ UNFILLED
  1620.         CALL PUT
  1621.         RET
  1622. UNFILLED:
  1623.         LDA FILL
  1624.         CPI NO
  1625.         JNZ FILLED
  1626.         CALL PUT
  1627.         RET
  1628. FILLED: CALL GETWRD
  1629.         RC
  1630.         CALL PUTWRD
  1631.         XCHG
  1632.         JMP FILLED
  1633. ;
  1634. ;-----
  1635. ; UNDERL - UNDERLINE A LINE
  1636. ; ACCEPTS:  BC = ADDR LINE
  1637. ;           DE = ADDR TEMPORARY BUFFER
  1638. ;           HL = SIZE OF LINE BUFFERS
  1639. ;
  1640. ;-----
  1641. ;
  1642. UNDERL: PUSH B
  1643.         PUSH D
  1644.         DAD D           ;GET ADDR END OF TEMP BUF +1
  1645.         DCX H           ;GET ADDR LAST POSSIBLE CHAR POSITION
  1646.         DCX H           ;(NEWLINE & EOS TAKE LAST TWO)
  1647.         DCX H
  1648.         DCX H
  1649.         DCX H
  1650.         XCHG            ;DE "= ADDR LAST,  HL := TEMP BUF
  1651. UNLOOP: LDAX B
  1652.         CPI NEWLINE
  1653.         JZ ULINED
  1654.         CALL COMPARE
  1655.         JC ULINED
  1656.         LDAX B
  1657.         INX B
  1658.         MOV M,A
  1659.         INX H
  1660.         CPI ' '
  1661.         JZ UNLOOP
  1662.         CPI TAB
  1663.         JZ UNLOOP
  1664.         CPI BACKSPACE
  1665.         JZ UNLOOP
  1666.         MVI M,BACKSPACE
  1667.         INX H
  1668.         MVI M,'_'
  1669.         INX H
  1670.         JMP UNLOOP
  1671. ULINED: MVI M,NEWLINE
  1672.         INX H
  1673.         MVI M,EOS
  1674.         POP D
  1675.         POP H
  1676.         CALL SCOPY
  1677.         RET
  1678. ;
  1679. ;-----
  1680. ; WIDTH - COMPUTE WIDTH OF CHARACTER STRING
  1681. ; ACCEPTS:  HL = ADDR STRING
  1682. ; RETURNS:  DE = WIDTH
  1683. ;-----
  1684. ;
  1685. WIDTH:  LXI D,0
  1686. WIDNXT: MOV A,M
  1687.         CPI EOS
  1688.         RZ
  1689.         INX H
  1690.         CPI BACKSPACE
  1691.         JZ NEGWID
  1692.         CPI NEWLINE
  1693.         JZ WIDNXT
  1694.         INX D
  1695.         JMP WIDNXT
  1696. ;
  1697. NEGWID: DCX D
  1698.         JMP WIDNXT
  1699. ;
  1700. OPTR:   DS      2       ; POINTER INTO DISK OUTPUT BUFFER
  1701.         DS      48
  1702. STACK   EQU     $
  1703. ;
  1704. DBUFF   EQU     (($ SHR 8)+1) SHL 8     ;START OF FREE STORAGE FOR DISK BUFFER
  1705. ;
  1706.         END
  1707. @