home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / directry / dirnotes / dirnotes.asm next >
Assembly Source File  |  1989-10-15  |  48KB  |  1,061 lines

  1. ;          Dirnotes.asm
  2. ;  FORMAT: DIRNOTES [d][path][directory]
  3.  
  4. ; *A  10-15-89 WCL ... Chg'd Home,End key defs to ^Home,^End respectively
  5. ;     rev 1.10         Added new Home,End,Tab,Sh-Tab,Ins,Del,^T,^Left,^Right KEY DEFS
  6. ;                      Reassembled with TASM 1.0, Linked with TLINK 2.0.
  7.  
  8. CODE SEGMENT                           ;*************************;
  9. ASSUME CS:CODE,DS:CODE                 ;*                       *;
  10. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *;
  11.                                        ;*                       *;
  12. START:         JMP    BEGINNING        ;*************************;
  13.  
  14. ;              DATA AREA
  15. ;              ---------
  16. COPYRIGHT      DB  'Copyright 1987 Ziff-Davis Publishing Co. - Rev 1.10',10,13
  17. PROGRAMMER     DB  'Michael J. Mefford - Updated 10-15-89 by WCL',1AH
  18. DIRNOTES       DB  'DIRN----.DAT',0
  19. STAR_DOT_STAR  DB  '*.*',0
  20.  
  21. CURRENT_DISK   DB  ?
  22. STATUS_REG     DW  ?
  23. VIDEO_SEG      DW  0B000H
  24. NORMAL         DB  07H
  25. INVERSE        DB  70H
  26.  
  27. CURSOR_ORG     DW  ?  ;*A    CH & CL registers: cursor height
  28. CURS_POS       DW  ?  ; row,col
  29. CUR_OFFSET     DW  OFFSET BUFFER
  30. END_OFFSET     DW  ?
  31. PAGE_END       DW  403+21*160
  32. COUNT          DW  1
  33. LINE           DW  403
  34.  
  35. EOF_FLAG       DB  0
  36. UPDATE_FLAG    DB  0
  37. INS_FLAG       DB  1   ;*A    1 = insert mode
  38.  
  39. NOT_ENOUGH     DB  'Not enough memory$'
  40. INVALID        DB  'Invalid directory$'
  41. TOO_MANY       DB  'Too many files$'
  42. LOADING        DB  'Loading and sorting directory notes.',0
  43. DIRECTORY      DB  'Directory of ',0
  44. FILES          DB  '    Files',0
  45. STATUS_LINE    DB  'Press Esc to exit',0
  46. SAVING         DB  'Saving ',0
  47.  
  48. ;----------------------------------------------------------------------------;
  49. ; Some housekeeping first. Since we will be changing the default drive       ;
  50. ; and directory to the requested drive and directory, we need to save the    ;
  51. ; current defaults, so they can be restored.  If less than 64K, exit.        ;
  52. ;----------------------------------------------------------------------------;
  53.  
  54. ;              CODE AREA
  55. ;              ---------
  56. BEGINNING:     CLD
  57.                MOV    AH,19H                 ;Get current drive.
  58.                INT    21H
  59.                MOV    CURRENT_DISK,AL        ;And save.
  60.  
  61.                MOV    SI,OFFSET CURRENT_DIR  ;Get current directory.
  62.                CALL   GET_DIR
  63.  
  64.                CMP    SP,65500               ;Do we have 64K?
  65.                MOV    DX,OFFSET NOT_ENOUGH
  66.                JA     PARSE
  67.                JMP    ERROR_EXIT             ;If no, exit.
  68.  
  69. ;-----------------------------------------------------------;
  70. ; Parse the command line for parameters and append the      ;
  71. ; DIRNOTES filename with the characters of directory name.  ;
  72. ;-----------------------------------------------------------;
  73.  
  74. PARSE:         CMP    BYTE PTR DS:[80H],0    ;Any parameters?
  75.                JZ     APPEND                 ;If no, skip parse.
  76.  
  77.                MOV    SI,81H                 ;Else, point to first character.
  78. NEXT_PARSE:    LODSB
  79.                CMP    AL,13                  ;Carriage return?
  80.                JZ     APPEND                 ;If yes, done here.
  81.                CMP    AL,32                  ;Leading space?
  82.                JBE    NEXT_PARSE             ;If yes, get next byte.
  83.                PUSH   SI                     ;Save start.
  84.  
  85. NEXT_PARA:     LODSB
  86.                CMP    AL,13                  ;End of parameter?
  87.                JZ     END_PARA               ;If yes, done here.
  88.                CMP    AL,':'                 ;Drive request?
  89.                JNZ    NEXT_PARA              ;If no, get next byte.
  90.                MOV    DL,BYTE PTR [SI-2]     ;Else, retrieve request.
  91.                AND    DL,5FH                 ;Capitalize.
  92.                SUB    DL,'A'                 ;Convert to DOS format.
  93.                MOV    AH,0EH                 ;And change drive.
  94.                INT    21H
  95.                JMP    SHORT NEXT_PARA        ;Find end of parameter.
  96.  
  97. END_PARA:      MOV    BYTE PTR DS:[SI-1],0   ;Convert parameter to ASCIIZ.
  98.                POP    DX                     ;Retrieve start.
  99.                DEC    DX                     ;Adjust.
  100.                MOV    AH,3BH                 ;Change directory.
  101.                INT    21H
  102.                MOV    DX,OFFSET INVALID      ;Exit if invalid parameter.
  103.                JNC    APPEND
  104.                JMP    ERROR_EXIT
  105.  
  106. APPEND:        MOV    SI,80H                 ;Get default directory.
  107.                CALL   GET_DIR
  108.                CLD
  109. NEXT_END:      LODSB                         ;Find end.
  110.                CMP    AL,0
  111.                JNZ    NEXT_END
  112.                DEC    SI
  113.                STD                           ;Reverse direction.
  114. NEXT_START:    AND    BYTE PTR [SI],5FH      ;Capitalize.
  115.                LODSB
  116.                CMP    AL,'\'                 ;Look for last path.
  117.                JNZ    NEXT_START
  118.                CLD                           ;Back to forward direction.
  119.                INC    SI
  120.                INC    SI
  121.                MOV    DI,OFFSET DIRNOTES+5   ;Insert three characters of path
  122.                MOV    CX,3                   ; into filename, DIRN----.DAT
  123. STORE_PATH:    CMP    BYTE PTR [SI],0
  124.                JZ     DISPLAY
  125.                MOVSB
  126.                LOOP   STORE_PATH
  127.  
  128. ;---------------------------------------------------------------------;
  129. ; More housekeeping. We will be writing directly to the screen buffer ;
  130. ; so we need the display card address and the status register.        ;
  131. ;---------------------------------------------------------------------;
  132.  
  133. DISPLAY:       MOV    AX,40H           ;Point to the ROM BIOS data area
  134.                MOV    DS,AX            ; and get base address of active
  135.                MOV    AX,DS:[63H]      ; display card.
  136.                ADD    AX,6             ;Add six to get status register
  137.                PUSH   CS               ;Done there, so restore data segment.
  138.                POP    DS
  139.                MOV    STATUS_REG,AX    ;Store status register.
  140.                CMP    AX,3BAH          ;Status port of MONO card is 3BAh.
  141.                JZ     MESSAGE          ;If that's what we got, it's MONO
  142.                MOV    VIDEO_SEG,0B800H       ; else COLOR so add 800h.
  143.                XOR    BH,BH                  ;Get current attribute
  144.                MOV    AH,8                   ; of display page zero.
  145.                INT    10H
  146.                MOV    NORMAL,AH              ;Store it.
  147.                XOR    AH,1110111B            ;Flip color bits.
  148.                MOV    INVERSE,AH             ;Save it.
  149.  
  150. MESSAGE:       CALL   CLS
  151.                MOV    SI,OFFSET LOADING      ;Display loading message.
  152.                MOV    DX,0C15H
  153.                CALL   DISPLAY_TEXT
  154.  
  155.                MOV    DI,OFFSET BUFFER       ;Fill buffer with spaces.
  156.                MOV    CX,30000
  157.                MOV    AX,2020H
  158.                REP    STOSW
  159.  
  160. ;------------------------------------------------------------------;
  161. ; Read all the directory filenames and store as records in buffer. ;
  162. ;------------------------------------------------------------------;
  163.  
  164. READ_DIR:      MOV    DX,OFFSET STAR_DOT_STAR
  165.                MOV    CX,6
  166.                MOV    AH,4EH                 ;Find first matching.
  167.                INT    21H
  168.                JNC    STORE_NAME
  169.                JMP    EXIT                   ;If empty directory, exit.
  170.  
  171. STORE_NAME:    MOV    DI,OFFSET BUFFER       ;Set up pointers and store
  172.                MOV    BP,60000               ; first filename.
  173.                CALL   BUFFER_NAME
  174.  
  175. FIND_NEXT:     MOV    AH,4FH                 ;Find next matching.
  176.                INT    21H
  177.                JC     STORE_COUNT            ;If carry, no more names.
  178.                INC    COUNT                  ;Inc count of names.
  179.                CALL   BUFFER_NAME
  180.                CMP    DI,BP                  ;Are we encroaching stack?
  181.                JB     FIND_NEXT              ;If no, find next.
  182.                MOV    DX,OFFSET TOO_MANY     ;Else, exit with message.
  183.                JMP    ERROR_EXIT
  184.  
  185. ;---------------------------------------------;
  186. ; Store buffer end address and page end,      ;
  187. ; number of files then alphabetize filenames. ;
  188. ;---------------------------------------------;
  189.  
  190. STORE_COUNT:   MOV    END_OFFSET,DI          ;Store ending offset.
  191.                MOV    BX,COUNT
  192.  
  193.                MOV    AX,BX
  194.                MOV    CL,10                  ;Convert to decimal.
  195.                STD                           ;Reverse direction.
  196.                MOV    DI,OFFSET FILES+2      ;Point to storage.
  197. NEXT_COUNT:    DIV    CL
  198.                XCHG   AL,AH
  199.                ADD    AL,'0'                 ;Convert to ASCII.
  200.                STOSB                         ;Store the remainder.
  201.                XCHG   AL,AH
  202.                XOR    AH,AH
  203.                CMP    AX,0                   ;Are we done?
  204.                JNZ    NEXT_COUNT
  205.  
  206.                CLD                           ;Back to forward direction.
  207.                CMP    BX,20                  ;Enough to file one page?
  208.                JA     SORT                   ;If yes, use default setting.
  209.                MOV    AX,160                 ;Else, calculate last record.
  210.                MUL    BL
  211.                ADD    AX,403                 ;Add bar offset.
  212.                MOV    PAGE_END,AX
  213.                CMP    BX,1                   ;Skip sort if only one filename.
  214.                JZ     OPEN_FILE
  215.  
  216. SORT:          MOV    DX,END_OFFSET          ;End of filenames in DX.
  217.                SUB    DX,81
  218. NEXT_PASS:     MOV    BP,0
  219.                MOV    BX,OFFSET BUFFER       ;Point to start of buffer.
  220.  
  221. NEXT_SORT:     MOV    SI,BX                  ;Put in source and destination
  222.                MOV    DI,BX                  ; registers.
  223.                ADD    DI,81
  224.                MOV    CX,12
  225.                REPZ   CMPSB                  ;Compare filenames.
  226.                JBE    END_SORT               ;If already in order, skip.
  227.  
  228.                MOV    SI,BX                  ;Else, recover pointers.
  229.                MOV    DI,BX
  230.                ADD    DI,81
  231.                MOV    CX,40                  ;Exchange the records.
  232. NEXT_SWAP:     MOV    AX,[DI]
  233.                MOVSW
  234.                MOV    [SI-2],AX
  235.                LOOP   NEXT_SWAP
  236.                MOV    BP,1                   ;Flag that exchange was made.
  237.  
  238. END_SORT:      ADD    BX,81                  ;Point to next record.
  239.                CMP    BX,DX                  ;End of top?
  240.                JB     NEXT_SORT              ;If no, bubble sort next.
  241.                CMP    BP,0                   ;Was there exchange made?
  242.                JZ     OPEN_FILE              ;If no, done here.
  243.                SUB    DX,81                  ;Else, move top down one record.
  244.                JMP    SHORT NEXT_PASS
  245.  
  246. ;-------------------------------;
  247. ; Attempt to read old dirnotes. ;
  248. ;-------------------------------;
  249.  
  250. OPEN_FILE:     MOV    DX,OFFSET DIRNOTES     ;Open DIRNOTES
  251.                MOV    AX,3D00H               ; for reading.
  252.                INT    21H
  253.                JC     READY                  ;If not found, skip to display.
  254.  
  255.                MOV    BX,AX
  256.                PUSH   BX                     ;Save filehandle.
  257. READ_FILE:     POP    BX
  258.                PUSH   BX
  259.                MOV    DX,60000               ;Point above directory listing.
  260.                MOV    CX,37*81               ;Read up to 37 records at a time.
  261.                MOV    AH,3FH
  262.                INT    21H
  263.  
  264.                CMP    AX,0                   ;End of file?
  265.                JZ     CLOSE_FILE             ;If yes, done here.
  266.                ADD    DX,AX
  267.                MOV    DI,DX                  ;Else, point to end and tack
  268.                MOV    BYTE PTR [DI],1AH      ; on Ctrl Z as end signature.
  269.                CMP    AX,37*81               ;Was it a full read?
  270.                JZ     COMPARE                ;If yes, compare records.
  271.                MOV    EOF_FLAG,1             ;Else, flag as end of file.
  272.  
  273. ;-------------------------------------------------------;
  274. ; Here we will match old DIRNOTES with new directory    ;
  275. ; listing. Notes for deleted files will not find match. ;
  276. ;-------------------------------------------------------;
  277.  
  278. COMPARE:       MOV    BP,OFFSET BUFFER       ;Point to first record.
  279. NEXT_FILE:     MOV    BX,60000               ;Point to read buffer.
  280. NEXT_MATCH:    MOV    SI,BX                  ;Set up source and destination.
  281.                MOV    DI,BP
  282.                MOV    CX,6                   ;Filename with extension.
  283.                REPZ   CMPSW                  ;Compare all 12 characters.
  284.                JNZ    END_NOTE               ;Skip if no match.
  285.                ADD    SI,28                  ; else point to note.
  286.                ADD    DI,28
  287.                MOV    CX,20
  288.                REP    MOVSW                  ;Store note.
  289.  
  290.                SUB    SI,67
  291.                SUB    DI,67
  292.                MOV    CX,13
  293.                REPZ   CMPSW                  ;Has size or date changed?
  294.                JNZ    END_MATCH
  295.                MOV    BYTE PTR [BP+39],32    ;If yes, remove "U".
  296.                JMP    SHORT END_MATCH        ;Skip rest and go to next record.
  297.  
  298. END_NOTE:      ADD    BX,81                  ;Point to next record.
  299.                CMP    BYTE PTR DS:[BX],1AH   ;Are we at the end?
  300.                JNZ    NEXT_MATCH             ;If no, compare.
  301. END_MATCH:     ADD    BP,81                  ;Point to next record.
  302.                CMP    BYTE PTR DS:[BP],32    ;End of directory listing?
  303.                JNZ    NEXT_FILE              ;If no, check for matches.
  304.                CMP    EOF_FLAG,1             ;Else, end of file?
  305.                JNZ    READ_FILE              ;If no, read more.
  306.  
  307. CLOSE_FILE:    POP    BX
  308.                MOV    AH,3EH                 ;Close file.
  309.                INT    21H
  310.  
  311. ;--------------------------------------------;
  312. ; Now, we are ready to initialize the screen ;
  313. ;--------------------------------------------;
  314.  
  315. READY:         MOV    AX,VIDEO_SEG           ;Initialize video segment.
  316.                MOV    ES,AX
  317.                MOV    DX,4                   ;Row 0; column 3.
  318.                MOV    SI,OFFSET DIRECTORY    ;Display "Directory ".
  319.                CALL   DISPLAY_TEXT
  320.                MOV    AH,19H
  321.                INT    21H                    ;Get drive.
  322.                ADD    AL,'A'                 ;Convert to ASCII.
  323.                CALL   WRITE_TEXT             ;Display it.
  324.                MOV    AL,':'                 ;Add colon.
  325.                CALL   WRITE_TEXT
  326.                MOV    SI,80H                 ;Get directory.
  327.                CALL   GET_DIR
  328.                DEC    SI
  329.                CALL   GET_TEXT               ;Write it as well.
  330.                MOV    DX,180EH               ;Row 24; column 13.
  331.                MOV    SI,OFFSET FILES        ;Display file count.
  332.                CALL   DISPLAY_TEXT
  333.                MOV    DX,1833H               ;Row 24; column 50.
  334.                MOV    SI,OFFSET STATUS_LINE  ;Display "Press Esc to exit".
  335.                CALL   DISPLAY_TEXT
  336.                MOV    BL,INVERSE             ;Put up cursor bar.
  337.                CALL   BAR
  338.                CALL   UPDATE_SCREEN          ;Display directory listing.
  339.                MOV    CURS_POS,229H          ;Initialize cursor position.
  340.                MOV    AH,03                  ;*A
  341.                MOV    BH,0                   ;*A
  342.                INT    10H                    ;*A Get original cursor size
  343.                MOV    CURSOR_ORG,CX          ;*A
  344.                CALL   SET_CUR_SIZE           ;*A Set cursor size
  345.  
  346. ;-----------------------------------------;
  347. ; We are ready for business now. We will  ;
  348. ; loop here, waiting for user keystrokes. ;
  349. ;-----------------------------------------;
  350.  
  351. GET_KEY:       CALL   SET_CURSOR             ;Update cursor position.
  352.                MOV    AH,0                   ;Wait for
  353.                INT    16H                    ;keystroke.
  354.  
  355. ASCII:         CMP    AL,32                  ;Is it space or above?
  356.                JB     CR                     ;If no, skip.
  357.                CMP    BYTE PTR CURS_POS,79   ;End of line?  Line: 42-79 physical
  358.                JZ     GET_KEY                ;If yes, skip.       41-78 logical
  359.                CMP    INS_FLAG, 1            ;Insert mode on?          *A
  360.                JNZ    WRT_ASCII              ;Jmp if not               *A
  361.                CALL   PUSHEM_OUT             ;Else push out characters *A
  362. WRT_ASCII:     CALL   STORE_CHAR             ;Else, store the ASCII character.
  363.                INC    BYTE PTR CURS_POS      ;Update cursor (points to next loc).
  364.                JMP    SHORT GET_KEY
  365.  
  366. CR:            CMP    AH,1CH                 ;Is it carriage return?
  367.                JNZ    BS
  368.                MOV    BYTE PTR CURS_POS,41   ;Cursor to beginning of line.
  369.                JMP    SCROLL_DOWN      ; and scroll down.
  370.  
  371. BS:            CMP    AH,0EH                 ;Backspace?
  372.                JNZ    TAB
  373.                CMP    BYTE PTR CURS_POS,41   ;Are we already at beginning?
  374.                JZ     GET_KEY                ;If yes, skip.
  375.                DEC    BYTE PTR CURS_POS      ;Else, cursor left one.
  376.                MOV    AL,32                  ;And replace with space.
  377.                CALL   STORE_CHAR
  378.                JMP    SHORT GET_KEY
  379.  
  380. TAB:           CMP    AH,0FH                 ;Tab?  *A
  381.                JNZ    LEFT_ARROW
  382.                CMP    AL,00H
  383.                JZ     SHFT_TAB
  384.                CMP    BYTE PTR CURS_POS,79   ;Are we already end of line?
  385.                JZ     GET_KEY
  386.                ADD    BYTE PTR CURS_POS,5    ;Cursor right.
  387.                CMP    BYTE PTR CURS_POS,79   ;Are we past end of line?
  388.                JBE    EXIT_TAB
  389.                MOV    BYTE PTR CURS_POS,79
  390. EXIT_TAB:      JMP    SHORT GET_KEY
  391.  
  392. SHFT_TAB:                                    ;Sh-Tab?  *A
  393.                CMP    BYTE PTR CURS_POS,41   ;Are we already start of line?
  394.                JZ     GET_KEY
  395.                SUB    BYTE PTR CURS_POS,5    ;Cursor left.
  396.                CMP    BYTE PTR CURS_POS,41   ;Are we before start of line?
  397.                JAE    EXIT_SH_TAB            ;Jump if not
  398.                MOV    BYTE PTR CURS_POS, 41
  399. EXIT_SH_TAB:   JMP    GET_KEY
  400.  
  401. LEFT_ARROW:    CMP    AH,4BH                 ;Left arrow?
  402.                JNZ    RIGHT_ARROW
  403.                CMP    BYTE PTR CURS_POS,41   ;Are we already home position?
  404.                JZ     LEFT_EXIT
  405.                DEC    BYTE PTR CURS_POS      ;If no, back cursor up one.
  406. LEFT_EXIT:     JMP    GET_KEY
  407.  
  408. RIGHT_ARROW:   CMP    AH,4DH                 ;Right arrow?
  409.                JNZ    CTL_LFT_ARR
  410.                CMP    BYTE PTR CURS_POS,79   ;Are we already end of line?
  411.                JZ     SKIP_CHK
  412.                INC    BYTE PTR CURS_POS      ;Cursor right one.
  413. SKIP_CHK:      JMP    GET_KEY
  414.  
  415. CTL_LFT_ARR:   CMP    AH,73H                 ;^Left arrow?
  416.                JNZ    CTL_RT_ARR
  417.                INC    BYTE PTR CURS_POS
  418. CHAR_L:        CALL   LOOPER_LEFT
  419.                JAE    CHAR_L
  420. NON_CHAR_L:    CALL   LOOPER_LEFT
  421.                JB     NON_CHAR_L
  422. CHAR_L2:       CALL   LOOPER_LEFT
  423.                JAE    CHAR_L2
  424.                INC    BYTE PTR CURS_POS
  425. EXIT_CTL_L:    JMP    GET_KEY
  426.  
  427. LOOPER_LEFT:
  428.                CMP    BYTE PTR CURS_POS,41
  429.                JZ     EXIT_CTL_L
  430.                DEC    BYTE PTR CURS_POS
  431.                CALL   GET_CHAR
  432.                CMP    BL,48
  433.                RET
  434.  
  435. CTL_RT_ARR:    CMP    AH,74H                 ;^Right arrow? *A
  436.                JNZ    UP_ARROW
  437.                DEC    BYTE PTR CURS_POS
  438. CHAR_R:        CALL   LOOPER_RT
  439.                JAE    CHAR_R
  440.                MOV    BH,BYTE PTR CURS_POS   ;Location of last non_char (space)
  441. NON_CHAR_R:    CALL   LOOPER_RT
  442.                JB     NON_CHAR_R
  443. CHK_END:       CMP    BYTE PTR CURS_POS,79
  444.                JB     EXIT_CTL_R1
  445.                DEC    BYTE PTR CURS_POS      ;Point to last logical char
  446.                CALL   GET_CHAR
  447.                CMP    BL,32
  448.                JNZ    EXIT_CTL_R0
  449.                INC    BH
  450.                MOV    BYTE PTR CURS_POS,BH
  451. FIND_CHAR:     CALL   LOOPIT_LEFT
  452.                JZ     FIND_CHAR
  453. EXIT_CTL_R0:   INC    BYTE PTR CURS_POS
  454. EXIT_CTL_R1:   JMP    GET_KEY
  455.  
  456. LOOPER_RT:     CMP    BYTE PTR CURS_POS,79
  457.                JZ     CHK_END
  458.                INC    BYTE PTR CURS_POS
  459.                CALL   GET_CHAR
  460.                CMP    BL,48
  461.                RET
  462.  
  463. LOOPIT_LEFT:
  464.                CMP    BYTE PTR CURS_POS,41
  465.                JZ     EXIT_CTL_R1
  466.                DEC    BYTE PTR CURS_POS
  467.                CALL   GET_CHAR
  468.                CMP    BL,32
  469.                RET
  470.  
  471. UP_ARROW:      CMP    AH,48H                 ;Up arrow?
  472.                JNZ    DN_ARROW
  473.                MOV    BP,-160                ;If yes, move bar up one line.
  474.                MOV    DX,0FF00H              ;And also the cursor.
  475.                CALL   SCROLL_BAR
  476.                JMP    GET_KEY
  477.  
  478. DN_ARROW:      CMP    AH,50H                 ;Down arrow?
  479.                JNZ    HOME
  480. SCROLL_DOWN:   MOV    BP,160                 ;If yes, move cursor and bar down.
  481.                MOV    DX,100H
  482.                CALL   SCROLL_BAR
  483.                JMP    GET_KEY
  484.  
  485. HOME:          CMP    AH,47H                 ;Home key?  *A
  486.                JNZ    END_KEY
  487. SET_MIN_POS:   MOV    BYTE PTR CURS_POS, 41
  488.                JMP    GET_KEY
  489.  
  490. END_KEY:       CMP    AH,4FH                 ;End key?   *A
  491.                JNZ    PG_UP
  492. SET_END_POS:   MOV    BYTE PTR CURS_POS, 79
  493. LOOP_END_POS:  CMP    BYTE PTR CURS_POS, 41
  494.                JZ     EXIT_END_POS
  495.                DEC    BYTE PTR CURS_POS
  496.                CALL   GET_CHAR
  497.                CMP    BL,32
  498.                JZ     LOOP_END_POS
  499.                INC    BYTE PTR CURS_POS
  500. EXIT_END_POS:  JMP    GET_KEY
  501.  
  502. PG_UP:         CMP    AH,49H                 ;Page up?
  503.                JNZ    PG_DN
  504.                MOV    BP,-81*21              ;If yes, move up 21 lines.
  505.                CALL   SCROLL
  506.                JMP    SHORT BOTTOM_BAR       ;And move bar to bottom.
  507.  
  508. PG_DN:         CMP    AH,51H                 ;Page down?
  509.                JNZ    CTRL_PG_UP
  510.                MOV    BP,81*21               ;If yes, move down 21 lines.
  511.                CALL   SCROLL
  512.                JMP    SHORT TOP_BAR          ;And move bar to top.
  513.  
  514. CTRL_PG_UP:    CMP    AH,84H                 ;Ctrl PgUp?
  515.                JNZ    CTRL_PG_DN
  516. TOP_BAR:       MOV    SI,403                 ;If yes, move bar to top.
  517.                MOV    CURS_POS,229H
  518.                JMP    SHORT UPDATE_BAR
  519.  
  520. CTRL_PG_DN:    CMP    AH,76H                 ;Ctrl PgDn?
  521.                JNZ    CTRL_HOME
  522. BOTTOM_BAR:    MOV    SI,PAGE_END            ;If yes, move bar to bottom.
  523.                MOV    AX,SI                  ;Divide page end by 160
  524.                SUB    SI,160                 ; to get cursor row position.
  525.                SUB    AX,403-160
  526.                XOR    DX,DX
  527.                MOV    BX,160
  528.                DIV    BX
  529.                MOV    DH,AL
  530.                MOV    DL,29H
  531.                MOV    CURS_POS,DX
  532. UPDATE_BAR:    CALL   MOVE_BAR               ;Display updates.
  533.                CALL   SET_CURSOR
  534.                CALL   UPDATE_SCREEN
  535.                JMP    NEXT_KEY
  536.  
  537. CTRL_HOME:     CMP    AH,77H                     ;^Home?  *A
  538.                JNZ    CTRL_END
  539.                MOV    CUR_OFFSET,OFFSET BUFFER   ;If yes, move listing and
  540.                JMP    SHORT TOP_BAR              ; bar to top.
  541.  
  542. CTRL_END:      CMP    AH,75H                 ;^End? *A
  543.                JNZ    INS_KEY
  544.                MOV    BX,END_OFFSET          ;If yes, move listing and
  545.                SUB    BX,81*21               ; bar to bottom.
  546.                CMP    BX,OFFSET BUFFER
  547.                JBE    BOTTOM_BAR
  548.                MOV    CUR_OFFSET,BX
  549.                JMP    SHORT BOTTOM_BAR
  550.  
  551. INS_KEY:       CMP    AH,52H                 ;Insert?  *A
  552.                JNZ    DEL
  553.                XOR    BYTE PTR INS_FLAG,1
  554.                CALL   SET_CUR_SIZE
  555.                JMP    GET_KEY
  556.  
  557. DEL:           CMP    AH,53H                 ;Del?  *A
  558.                JNZ    CTRL_T
  559.                CALL   DEL_CHAR
  560.                JMP    GET_KEY
  561.  
  562. CTRL_T:        CMP    AH,14H                 ;Ctrl T? *A
  563.                JNZ    CTRL_Y
  564.                MOV    BH,80
  565.                SUB    BH,BYTE PTR CURS_POS
  566.                CALL   GET_CHAR
  567.                CMP    BL,32
  568.                JZ     DEL_A_SPACE
  569. DEL_A_CHAR:    DEC    BH
  570.                CMP    BH,0
  571.                JZ     EXIT_T
  572.                CALL   DEL_CHAR
  573.                CALL   GET_CHAR
  574.                CMP    BL,32
  575.                JNZ    DEL_A_CHAR
  576. DEL_A_SPACE:   DEC    BH
  577.                CMP    BH,0
  578.                JZ     EXIT_T
  579.                CALL   DEL_CHAR
  580.                CALL   GET_CHAR
  581.                CMP    BL,32
  582.                JZ     DEL_A_SPACE
  583. EXIT_T:        JMP    GET_KEY
  584.  
  585. CTRL_Y:        CMP    AH,15H                 ;Ctrl-Y?  *A
  586.                JNZ    ESC
  587.                MOV    BYTE PTR CURS_POS,41
  588.                MOV    BH, 39
  589. EXIT_DEL_CHR:  CALL   DEL_CHAR
  590.                DEC    BH
  591.                CMP    BH,0
  592.                JNZ    EXIT_DEL_CHR
  593.                JMP    GET_KEY
  594.  
  595. ESC:           CMP    AH,1                   ;Esc?
  596.                JNZ    NEXT_KEY
  597.                JMP    EXIT                   ;If yes, exit.
  598.  
  599. NEXT_KEY:      JMP    GET_KEY
  600.  
  601.                 ;*************;
  602.                 ; SUBROUTINES ;
  603.                 ;*************;
  604.  
  605. ;--------------------------------------;
  606. ; This subroutine sets the cursor size ;
  607. ;--------------------------------------;
  608.  
  609. SET_CUR_SIZE:
  610.                CMP    BYTE PTR INS_FLAG,1
  611.                JZ     INSERT_ON
  612.                MOV    CX,CURSOR_ORG
  613.                JMP    DO_TEN
  614. INSERT_ON:     MOV    CX,080CH
  615. DO_TEN:        MOV    AH,01H
  616.                INT    10H
  617.                RET
  618.  
  619. ;-------------------------------------;
  620. ; This subroutine scrolls the screen. ;
  621. ;-------------------------------------;
  622.  
  623. SCROLL:        MOV    SI,CUR_OFFSET          ;Get current offset.
  624.                ADD    SI,BP                  ;Add requested direction.
  625.                JNS    CK_LOWER               ;If signed and PgUp request
  626.                CMP    BP,-81*21              ; then below start.
  627.                JZ     LOWER_LIMIT
  628. CK_LOWER:      CMP    SI,OFFSET BUFFER       ;If above start check upper limit.
  629.                JAE    UPPER_LIMIT
  630. LOWER_LIMIT:   MOV    CUR_OFFSET,OFFSET BUFFER    ;Else, make it start.
  631.                JMP    SHORT UPDATE                ;And update screen.
  632.  
  633. UPPER_LIMIT:   MOV    BX,END_OFFSET               ;See if beyond end of
  634.                CMP    BX,OFFSET BUFFER+21*81      ; directory listing as well.
  635.                JA     CK_UPPER
  636.                MOV    CUR_OFFSET,OFFSET BUFFER
  637.                JMP    SHORT UPDATE
  638.  
  639. CK_UPPER:      SUB    BX,21*81
  640.                CMP    SI,BX
  641.                JBE    END_SCROLL
  642.                MOV    SI,BX
  643.  
  644. END_SCROLL:    MOV    CUR_OFFSET,SI          ;Update current offset.
  645. UPDATE:        CALL   UPDATE_SCREEN
  646.                RET
  647.  
  648. ;--------------------------------------------------;
  649. ; This subroutine scrolls the bar if between start ;
  650. ; and end of page. Otherwise the page is scrolled. ;
  651. ;--------------------------------------------------;
  652.  
  653. SCROLL_BAR:    MOV    SI,LINE                ;Get current line.
  654.                ADD    SI,BP                  ;Add requested line.
  655.                MOV    BP,-81                 ;Assume below beginning.
  656.                CMP    SI,403                 ;Is it?
  657.                JB     SCROLL_PAGE            ;If yes, scroll page instead.
  658.                MOV    BP,81                  ;Do the same for end of page.
  659.                CMP    SI,PAGE_END
  660.                JAE    SCROLL_PAGE
  661.                ADD    CURS_POS,DX            ;If in range, update cursor
  662.                CALL   MOVE_BAR               ; and bar position.
  663.                RET
  664.  
  665. SCROLL_PAGE:   CALL   SCROLL
  666.                RET
  667.  
  668. ;----------------------------------------------------;
  669. ; This subroutine does the actual moving of the bar. ;
  670. ;----------------------------------------------------;
  671.  
  672. MOVE_BAR:      MOV    BL,NORMAL              ;Remove old bar.
  673.                CALL   BAR
  674.                MOV    LINE,SI                ;And move bar to new line.
  675.                MOV    BL,INVERSE
  676.                CALL   BAR
  677.                RET
  678.  
  679. BAR:           MOV    DI,LINE                ;Retrieve line.
  680.                MOV    BH,38                  ;Bar length 39.
  681.                MOV    DX,STATUS_REG
  682. NEXT_BAR:      MOV    CX,1                   ;Write one character at a time.
  683.                CALL   HORZ_RET
  684.                DEC    BH
  685.                JNZ    NEXT_BAR
  686.                RET
  687.  
  688. ;----------------------------------------------;
  689. ; This subroutine stores the ASCII characters. ;
  690. ;    AL = character to store                   ;
  691. ;----------------------------------------------;
  692.  
  693. STORE_CHAR:
  694.                CALL   GET_CHAR_LOC           ;*A
  695.                MOV    [SI],AL                ;Store it.
  696.                MOV    CX,1                   ;Write one character
  697.                CALL   WRITE_SCREEN           ;Display by updating screen.
  698.                MOV    UPDATE_FLAG,1          ;Flag as updated so file will
  699.                RET                           ; be written upon Esc.
  700.  
  701. ;------------------------------------------------;
  702. ; This subroutine retrieves the ASCII character. ;
  703. ;    BL = character to retrieve                  ;
  704. ;------------------------------------------------;
  705.  
  706. GET_CHAR:      CALL   GET_CHAR_LOC           ;*A
  707.                MOV    BL,DS:[SI]             ;Retrieve it.
  708.                RET                           ;
  709.  
  710. ;------------------------------------------------;
  711. ; This subroutine deletes an ASCII character.    ; *A
  712. ;------------------------------------------------;
  713.  
  714. DEL_CHAR:
  715.                CMP    BYTE PTR CURS_POS,79       ; Past last char?
  716.                JAE    EXIT_DEL_CHAR              ; Skip del if so, else
  717.                MOV    AX, CURS_POS               ;
  718.                PUSH   AX                         ; Save cursor position
  719. NEXTDEL:       INC    BYTE PTR CURS_POS          ; Point to next position
  720.                CMP    BYTE PTR CURS_POS,79       ; Is it past the last char?
  721.                JB     GETIT                      ; Jump if not
  722.                MOV    AL,32                      ; else fill last char with a space
  723.                JMP    MOVIT
  724. GETIT:         CALL   GET_CHAR                   ; Get char at next location
  725.                MOV    AL,BL                      ; mov it into AL
  726. MOVIT:         DEC    BYTE PTR CURS_POS          ; Point to current del char
  727.                CALL   STORE_CHAR                 ; Put new char there and show it
  728.                INC    BYTE PTR CURS_POS          ; Point to next del position
  729.                CMP    BYTE PTR CURS_POS,79       ; Past the last char yet?
  730.                JB     NEXTDEL                    ; No, continue processing
  731.                POP    AX                         ; Yes, restore old cursor position
  732.                MOV    CURS_POS,AX
  733. EXIT_DEL_CHAR: RET
  734.  
  735. ;------------------------------------------------;
  736. ; This subroutine push out trailing characters   ; *A
  737. ;------------------------------------------------;
  738.  
  739. PUSHEM_OUT:
  740.                CMP    BYTE PTR CURS_POS,78       ; At or past last valid char?
  741.                JAE    PUSH_RET                   ; Yes, Can't push any further
  742.                PUSH   AX                         ; Save current charcter
  743.                MOV    AX, CURS_POS               ;
  744.                PUSH   AX                         ; Save cursor position
  745.                MOV    BYTE PTR CURS_POS,78       ;
  746. NEXTADD:
  747.                POP    AX                         ; Restore cursor postion
  748.                DEC    BYTE PTR CURS_POS          ; Backup one character
  749.                CMP    BYTE PTR CURS_POS,AL       ; Is it prior to start loc?
  750.                PUSH   AX
  751.                JB     PUSH_RESTORE               ; Jump if not
  752.                CALL   GET_CHAR                   ; and get char at that location
  753.                MOV    AL,BL                      ; mov it into AL
  754.                INC    BYTE PTR CURS_POS          ; Point to next char
  755.                CALL   STORE_CHAR                 ; Put previous char there and show it
  756.                DEC    BYTE PTR CURS_POS          ; Backup one character
  757.                JMP    NEXTADD
  758. PUSH_RESTORE:
  759.                POP    AX
  760.                MOV    CURS_POS,AX
  761.                POP    AX
  762. PUSH_RET:      RET
  763.  
  764.  
  765. ;----------------------------------------------------------------; *A
  766. ; This subroutine causes [SI] to point to the current character  ;
  767. ;   Destroyed: CX,DL                                             ;
  768. ;----------------------------------------------------------------;
  769.  
  770. GET_CHAR_LOC:                                ;
  771.                PUSH   AX                     ;Save AX.
  772.                MOV    SI,CUR_OFFSET          ;Retrieve current starting offset.
  773.                MOV    AX,CURS_POS            ;Retrieve cursor position.
  774.                MOV    CX,AX                  ;Save it.
  775.                MOV    AL,AH
  776.                XOR    AH,AH                  ;Isolate row.
  777.                DEC    AX                     ;Adjust for offset.
  778.                DEC    AX
  779.                ADD    SI,AX                  ;Add to source.
  780.                MOV    DL,80                  ;Multiply by 80.
  781.                MUL    DL
  782.                ADD    SI,AX                  ;Add to source.
  783.                MOV    DI,AX                  ;DI is screen offset.
  784.                SHL    DI,1                   ;Adjust for attribute.
  785.                ADD    DI,2*160               ;Adjust for starting in row 3.
  786.                XOR    CH,CH                  ;Isolate column.
  787.                ADD    SI,CX                  ;Add column to offset.
  788.                SHL    CX,1                   ;Double for screen offset.
  789.                ADD    DI,CX                  ;Add it.  = screen offset
  790.                POP    AX                     ;Retrieve AX.
  791.                RET
  792.  
  793.  
  794. ;---------------------------------------------------;
  795. ; This subroutine writes the listing to the screen. ;
  796. ;---------------------------------------------------;
  797.  
  798. UPDATE_SCREEN: MOV    SI,CUR_OFFSET          ;Retrieve starting offset.
  799.                MOV    DI,2*160               ;Point to row three of screen.
  800.                MOV    BH,21                  ;21 lines to write.
  801. NEXT_WRITE:    MOV    CX,79                  ;79 characters per line.
  802.                CALL   WRITE_SCREEN           ;Write them.
  803.                ADD    SI,2                   ;Bump pointer past cr/lf.
  804.                ADD    DI,2                   ;Bump pointer to next line.
  805.                DEC    BH                     ;Do all 21 lines.
  806.                JNZ    NEXT_WRITE
  807.                RET
  808.  
  809. ;------------------------------------------------------------;
  810. ; This subroutine displays the directory by writing directly ;
  811. ; to the screen buffer. To avoid screen noise (snow) on the  ;
  812. ; color card, the horizontal retrace has to be monitored.    ;
  813. ;   CX = number of characters to write (79 max)              ;
  814. ;   DI = screen position                                     ;
  815. ;  Destroyed: BL, AL, DI                                     ;
  816. ;------------------------------------------------------------;
  817.  
  818. WRITE_SCREEN:
  819.                MOV    DX,STATUS_REG          ;Get status register.
  820. NEXT_BYTE:     LODSB                         ;Get a byte.
  821.                MOV    BL,AL                  ;Save it in BL.
  822.  
  823. HORZ_RET:      IN     AL,DX                  ;Get status.
  824.                TEST   AL,1                   ;Is it low?
  825.                JNZ    HORZ_RET               ;If not, wait until it
  826.                CLI                           ;No more interrupts.
  827.  
  828. WAIT:          IN     AL,DX                  ;Get status.
  829.                TEST   AL,1                   ;Is it high?
  830.                JZ     WAIT                   ;If no, wait until it is.
  831.                MOV    AL,BL                  ;Retrieve character; now it's OK
  832.                STOSB                         ; to write to screen buffer.
  833.                STI                           ;Interrupts back on.
  834.                INC    DI                     ;Bump pointer past attribute.
  835.                LOOP   NEXT_BYTE              ;Get next byte.
  836.                RET                           ;Return
  837.  
  838. ;------------------------------------;
  839. ; This subroutine clears the screen. ;
  840. ;------------------------------------;
  841.  
  842. CLS:           MOV    BH,NORMAL              ;Clear with original attribute.
  843.                XOR    CX,CX
  844.                MOV    DX,184FH               ;Entire screen.
  845.                MOV    AX,600H                ;Scroll active page.
  846.                INT    10H
  847.                RET                           ;Return.
  848.  
  849. ;-----------------------------------------;
  850. ; These subroutines display the messages. ;
  851. ;-----------------------------------------;
  852.  
  853. DISPLAY_TEXT:  MOV    CURS_POS,DX            ;Store requested cursor position.
  854.                CALL   SET_CURSOR             ;Move cursor.
  855. GET_TEXT:      LODSB
  856.                CMP    AL,0                   ;Zero marks end of string.
  857.                JZ     END_TEXT
  858.                CALL   WRITE_TEXT
  859.                JMP    SHORT GET_TEXT
  860. END_TEXT:      RET
  861.  
  862. WRITE_TEXT:    PUSH   SI                     ;BIOS does not save SI.
  863.                MOV    AH,0EH                 ;Write teletype
  864.                INT    10H
  865.                POP    SI
  866.                RET
  867.  
  868. ;----------------------------------------------------------------------;
  869. ; These two subroutines move the cursor and get the current directory. ;
  870. ;----------------------------------------------------------------------;
  871.  
  872. SET_CURSOR:    PUSH   SI                     ;Save SI pointer; BIOS doesn't.
  873.                MOV    DX,CURS_POS            ;Get requested cursor position.
  874.                XOR    BH,BH                  ;Page zero.
  875.                MOV    AH,2
  876.                INT    10H
  877.                POP    SI
  878.                RET
  879.  
  880. GET_DIR:       MOV    BYTE PTR [SI],'\'      ;DOS doesn't preface directory
  881.                INC    SI                     ; with slash so we must.
  882.                XOR    DL,DL
  883.                MOV    AH,47H                 ;Retrieve default directory.
  884.                INT    21H
  885.                RET
  886.  
  887. ;--------------------------------------------------;
  888. ; This long subroutine stores the filename in DIR  ;
  889. ; format. That is, filename, bytes, date and time. ;
  890. ;--------------------------------------------------;
  891.  
  892. BUFFER_NAME:   MOV    SI,158                 ;Point to filename.
  893.                MOV    CX,12                  ;Store 12 bytes of filename.
  894. NEXT_STORE:    LODSB                         ;Get a byte.
  895.                CMP    AL,0                   ;End of filename?
  896.                JZ     END_STORE              ;If yes, finish with blanks.
  897.                CMP    AL,'.'                 ;Is it the period?
  898.                JNZ    STORE_BYTE             ;If no, store.
  899.                SUB    CX,3                   ;Else store 3 spaces.
  900.                MOV    AL,32
  901.                REP    STOSB
  902.                ADD    CX,3
  903.                JMP    SHORT NEXT_STORE       ;Get next byte.
  904.  
  905. STORE_BYTE:    STOSB                         ;Store byte.
  906.                LOOP   NEXT_STORE             ;Get next byte.
  907. END_STORE:     MOV    AL,32                  ;Pad balance with spaces.
  908.                REP    STOSB
  909.  
  910. FILE_SIZE:     PUSH   DI                     ;Save pointer.
  911.                ADD    DI,8                   ;Move to end of bytes field.
  912.                MOV    DX,DS:[154]            ;Retrieve high and low words
  913.                MOV    AX,DS:[156]            ; of bytes.
  914.                MOV    BX,10                  ;Convert to decimal; divide by 10.
  915.                STD                           ;Reverse direction.
  916.  
  917. NEXT_SIZE:     MOV    CX,DX                  ;Low word in CX.
  918.                XOR    DX,DX                  ;Zero in high half.
  919.                DIV    BX                     ;Convert to decimal.
  920.                XCHG   AX,CX                  ;Retrieve low word.
  921.                DIV    BX
  922.                XCHG   AX,DX                  ;Retrieve remainder.
  923.                ADD    AL,'0'                 ;Convert to ASCII.
  924.                STOSB                         ;Store it.
  925.                MOV    AX,CX                  ;Are we done?
  926.                OR     CX,DX
  927.                JNZ    NEXT_SIZE              ;If no, divide again.
  928.  
  929.                CLD                           ;Back to forward direction.
  930.                POP    DI                     ;Retrieve pointer.
  931.                ADD    DI,11                  ;Move to date field.
  932. DATE:          MOV    DX,DS:[152]            ;Retrieve date.
  933.                MOV    AX,DX
  934.                MOV    CL,5                   ;Shift to lowest bits.
  935.                ROR    AX,CL
  936.                AND    AX,0FH                 ;Mask off all but month.
  937.                MOV    CL,0FFH                ;Flag as no leading zeros.
  938.                MOV    CH,'-'                 ;Delimiting character.
  939.                CALL   STORE_WORD             ;Store it.
  940.  
  941.                MOV    AX,DX                  ;Retrieve date.
  942.                AND    AX,1FH                 ;Mask off all but day.
  943.                MOV    CL,0                   ;Flag include leading zeros.
  944.                MOV    CH,'-'
  945.                CALL   STORE_WORD             ;Store it.
  946.  
  947.                MOV    AX,DX                  ;Retrieve date for last time.
  948.                MOV    CL,9
  949.                ROR    AX,CL
  950.                AND    AX,7FH                 ;Mask off all but year.
  951.                ADD    AX,80                  ;Adjust to ASCII.
  952.                CMP    AX,100                 ;Past year 2000?
  953.                JB     DISPLAY_DATE           ;If no, display. Else, adjust for
  954.                SUB    AX,100                 ; next century. (Planning ahead!)
  955. DISPLAY_DATE:  MOV    CL,0                   ;Display leading zeros.
  956.                MOV    CH,32
  957.                CALL   STORE_WORD             ;Store it.
  958.  
  959. TIME:          INC    DI                     ;Move to time field.
  960.                MOV    DX,DS:[150]            ;Retrieve time.
  961.                MOV    AX,DX
  962.                MOV    CL,11                  ;Shift to hours bits.
  963.                ROR    AX,CL
  964.                AND    AX,1FH                 ;Mask off all but hours.
  965.                PUSH   AX
  966.                CMP    AX,12                  ;Past noon?
  967.                JBE    MERIDIAN
  968.                SUB    AX,12                  ;If yes, adjust.
  969. MERIDIAN:      CMP    AX,0                   ;Midnight?
  970.                JNZ    NOT_MIDNIGHT
  971.                MOV    AX,12                  ;If yes, adjust.
  972. NOT_MIDNIGHT:  MOV    CL,0FFH                ;Suppress leading zeros.
  973.                MOV    CH,':'
  974.                CALL   STORE_WORD             ;Store it.
  975.  
  976.                MOV    AX,DX                  ;Retrieve time.
  977.                MOV    CL,5                   ;Shift to minutes bits.
  978.                ROR    AX,CL
  979.                AND    AX,3FH                 ;Mask off all but minutes.
  980.                MOV    CL,0
  981.                POP    DX                     ;Retrieve hours.
  982.                MOV    CH,'p'                 ;Assume PM.
  983.                CMP    DX,12                  ;Is it PM?
  984.                JAE    PM
  985.                MOV    CH,'a'                 ;If no, AM.
  986.  
  987. PM:            CALL   STORE_WORD             ;Store it.
  988.                MOV    BYTE PTR [DI],'U'      ;Assume for now updated.
  989.                MOV    BYTE PTR [DI+40],13    ;Tack on carriage return linefeed.
  990.                MOV    BYTE PTR [DI+41],10
  991.                ADD    DI,42                  ;Move pointer past note field
  992.                RET                           ; to start of next record.
  993.  
  994. STORE_WORD:    DIV    BL                     ;Divide by ten.
  995.                ADD    AX,'00'                ;Convert to ASCII.
  996.                CMP    CL,0                   ;Are we to display leading zero?
  997.                JZ     STORE_IT               ;If yes, store as is.
  998.                CMP    AL,'0'                 ;Is it a leading zero?
  999.                JNZ    STORE_IT               ;If no, store it.
  1000.                MOV    AL,32                  ;Else, store a space.
  1001. STORE_IT:      STOSW
  1002.                MOV    AL,CH                  ;Store delimiter character also.
  1003.                STOSB
  1004.                RET
  1005.  
  1006. ;-----------------------------------------------------------------;
  1007. ; This is the exit routines. Check if notes have been updated.    ;
  1008. ; If yes, write the file. Return to original drive and directory. ;
  1009. ;-----------------------------------------------------------------;
  1010.  
  1011. ERROR_EXIT:    MOV    AH,9                   ;Display error message.
  1012.                INT    21H
  1013.                CALL   RESTORE_PATH           ;Restore path.
  1014.                INT    20H                    ;Exit.
  1015.  
  1016. EXIT:          MOV    CURS_POS,1700H         ;Row 22; column 0.
  1017.                CALL   SET_CURSOR
  1018.                MOV    CX,CURSOR_ORG          ;*A
  1019.                MOV    AH,01H                 ;*A
  1020.                INT    10H                    ;*A
  1021.                CMP    BYTE PTR UPDATE_FLAG,1 ;Did we update notes?
  1022.                JNZ    NO_WRITE               ;If no, skip write
  1023.                MOV    SI,OFFSET SAVING       ;Display "Saving DIRN----.DAT.
  1024.                CALL   GET_TEXT
  1025.                MOV    SI,OFFSET DIRNOTES
  1026.                CALL   GET_TEXT
  1027.                MOV    DX,OFFSET DIRNOTES     ; else point to DIRNOTES
  1028.                MOV    CX,20H                 ; create the file.
  1029.                MOV    AH,3CH
  1030.                INT    21H
  1031.                MOV    BX,AX                  ;Filehandle.
  1032.                MOV    DX,OFFSET BUFFER       ;Point to the buffer
  1033.                MOV    CX,END_OFFSET
  1034.                SUB    CX,DX                  ;File size.
  1035.                MOV    AH,40H                 ;Write it.
  1036.                INT    21H
  1037.  
  1038. NO_WRITE:      CALL   RESTORE_PATH           ;Restore default directory.
  1039.                MOV    CURS_POS,0             ;Home the cursor.
  1040.                CALL   SET_CURSOR
  1041.                CALL   CLS                    ;Clear the screen.
  1042.                INT    20H                    ; and exit.
  1043.  
  1044. RESTORE_PATH:  MOV    DL,CURRENT_DISK        ;Reset the drive.
  1045.                MOV    AH,0EH
  1046.                INT    21H
  1047.                MOV    DX,OFFSET CURRENT_DIR  ;Reset the directory.
  1048.                MOV    AH,3BH
  1049.                INT    21H
  1050.                RET
  1051.  
  1052. ;-------------------------------------------------;
  1053. ; Approximate 700 filename buffer at end of code. ;
  1054. ;-------------------------------------------------;
  1055.  
  1056. CURRENT_DIR:
  1057. BUFFER         EQU    CURRENT_DIR+66
  1058.  
  1059. CODE ENDS
  1060. END  START
  1061.