home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1988 / 15 / fontedit.asm < prev    next >
Assembly Source File  |  1988-09-12  |  58KB  |  1,315 lines

  1. ;----------------------------------------------------------------------
  2. ;  Fontedit - Loads the current screen font and lets you modify it.
  3. ;  Saves font in a COM file with integral loader. Requires EGA or VGA.
  4. ;  Syntax:  FONTEDIT [filespec]
  5. ;  PC Magazine September 13, 1988
  6. ;----------------------------------------------------------------------
  7. _TEXT          SEGMENT PUBLIC 'CODE'
  8.                ASSUME  CS:_TEXT,DS:_TEXT
  9.                ASSUME  ES:_TEXT,SS:_TEXT
  10.  
  11.                ORG     100H
  12. START:         JMP     MAIN
  13.  
  14. ;              DATA AREA
  15. ;              ---------
  16.                DB      CR,SPACE,SPACE,SPACE,CR,LF
  17.  
  18. COPYRIGHT      DB      "FONTEDIT 1.0 (C) 1988 Ziff Communications Co. ",BOX
  19. PROGRAMMER1    DB      " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
  20.  
  21. CR             EQU     13
  22. LF             EQU     10
  23. CTRL_Z         EQU     26
  24. SPACE          EQU     32
  25. BOX            EQU     254
  26.  
  27. ESC_SCAN       EQU     1
  28. ENTER_SCAN     EQU     1CH
  29. UP_ARROW       EQU     48H
  30. DN_ARROW       EQU     50H
  31. LEFT_ARROW     EQU     4BH
  32. RIGHT_ARROW    EQU     4DH
  33. Y_SCAN         EQU     15H
  34. BS_SCAN        EQU     0EH
  35. TAB_CHAR       EQU     9
  36.  
  37. MAX_POINTS     EQU     16
  38. PIXEL_OFF      EQU     177
  39. PIXEL_ON       EQU     219
  40. EDIT_COL       EQU     32
  41. EDIT_ROW       EQU     8
  42. EDIT_TOP       EQU     EDIT_ROW SHL 8 + EDIT_COL
  43. TEMPLATE_TOP   EQU     EDIT_TOP - 28
  44. CHAR_TOP       EQU     EDIT_TOP + 28
  45. BOX_TOP        EQU     EDIT_TOP + 1 - 400H
  46. INTENSITY      EQU     1000B
  47. MICKEY         EQU     20
  48.  
  49. BUTTONS        LABEL   WORD
  50. LEFT_BUTTON    DB      0
  51. RIGHT_BUTTON   DB      0
  52. SHIFT_KEYS     EQU     3
  53. SHIFT_STATE    DB      ?
  54.  
  55. HORIZONTAL     DW      0
  56. VERTICAL       DW      0
  57.  
  58. NORMAL         EQU     07H
  59. ATTRIBUTE      DB      07H
  60. INVERSE        DB      70H
  61. ROWS           DB      ?
  62. MAX_LINES      DW      16
  63. MOUSE_FLAG     DB      0
  64. MODIFY_FLAG    DB      0
  65. BLANKS         DB      0,32,255
  66. FILE_FLAG      DB      0
  67. FILE_HANDLE    DW      ?
  68. FILENAME       DW      ?
  69. LAST_PIXEL     DB      ?
  70.  
  71. ;format: reg,value    SEQUENCER REGISTERS     GRAPHICS CONTROLLER REGISTERS
  72. ;                     MAP MASK   MEMORY MODE  MODE REG    MISC  READ MAP SELECT
  73. ACCESS_A000H   DB     2,4,        4,7,        5,0,        6,4,        4,2
  74. PROTECT_A000H  DB     2,3,        4,3,        5,10H,      6,0AH,      4,0
  75.  
  76. MENU           LABEL   BYTE
  77. DB "F1 Del row    F2 Ins row    F3 Dup row    F4 Save $"
  78. MENU1          LABEL   BYTE
  79. DB "F5 Copy template char.    Tab = select edit/char box"
  80. DB "   Use: arrow keys or mouse",CR,LF
  81. DB "Hold Shift key or mouse button to drag.    Esc to exit"
  82. DB "     Rows displayed = ",CR,LF
  83. DB "Left button  = pixel on",CR,LF
  84. DB "Right button = pixel off",CR,LF
  85. DB "Space bar = toggle pixel$"
  86. MENU2          LABEL   BYTE
  87. DB "Enter = select char.",0
  88. DB "Button = select char.",0
  89. DB "PgUp/PgDn prev./next char.",0
  90.  
  91. CAPTIONS       DW      TEMPLATE_TOP - 2
  92.                DB      "Template Char",0
  93.                DW      EDIT_TOP - 2
  94.                DB      "  Edit Char",0
  95.                DW      CHAR_TOP - 2
  96.                DB      "Character Set",0
  97.  
  98. CURRENT_BOX    DB      218, 5 DUP (196),   194, 5 DUP (196),   191
  99.                DB      179, 5 DUP (SPACE), 179, 5 DUP (SPACE), 179
  100.                DB      192, 5 DUP (196),   193, 5 DUP (196),   217
  101.  
  102. NOT_ENOUGH     DB      "Not enough memory$"
  103. NOT_SUPPORTED  DB      "Font too tall$"
  104. NOT_EGA_VGA    DB      "Ega/Vga not found$"
  105. SAVE_MSG       DB      CR,LF,"Save ",0
  106. FILE_MSG       DB      "file",0
  107. CREATE_MSG     DB      CR,LF,"Create ",0
  108. EXIST_MSG      DB      CR,LF,"Write over existing ",0
  109. YES_NO         DB      "?  Y/N",0
  110. FAILED_MSG     DB      CR,LF,"Failed$"
  111. FILENAME_MSG   DB      CR,LF,"Enter filename",CR,LF,"$"
  112. NOT_FONT_MSG   DB      " not font$"
  113. COM            DB      ".COM",0
  114. WARNING_MSG    DB      LF,"Warning!  The cursor row will be deleted in"
  115.                DB      " EVERY character in this font.",CR,LF,"Continue$"
  116.  
  117. DISPATCH_KEY   DB      1,        4BH,      4DH,    48H,     50H,     49H
  118.                DB      51H,      0FH,      39H,    1CH,     3BH,     53H
  119.                DB      3CH,      52H,      3DH,    3EH,     3FH
  120. DISPATCH_CNT   EQU     $ - DISPATCH_KEY
  121.  
  122. DISPATCH_TABLE DW      EXIT,    LEFT,    RIGHT,     UP,    DOWN,    PGUP
  123.                DW      PGDN,    TAB,     SPACE_BAR, ENTER, DEL_ROW, DEL_ROW
  124.                DW      INS_ROW, INS_ROW, DUP_ROW,   SAVE,  COPY_TEMP
  125. DISPATCH_END   EQU     $ - 2
  126.  
  127. ;              CODE AREA
  128. ;              ---------
  129. MAIN           PROC    NEAR
  130.  
  131.                CLD                             ;All string operations forward.
  132.  
  133.                MOV     BX,1024                 ;Allocate 1024 paragraphs; 16K.
  134.                MOV     AH,4AH
  135.                INT     21H
  136.                MOV     DX,OFFSET NOT_ENOUGH    ;Exit with message if not enough.
  137.                JC      ERROR_MSG
  138.  
  139.                MOV     AX,500H                 ;Make sure zero video page.
  140.                INT     10H
  141.  
  142.                MOV     AX,40H                  ;Point to BIOS data area.
  143.                MOV     ES,AX
  144.  
  145.                MOV     AX,1A00H                ;Get display info.
  146.                INT     10H
  147.                CMP     AL,1AH                  ;Function supported?
  148.                JNZ     CK_EGA                  ;If no, not VGA; check EGA.
  149.                CMP     BL,7                    ;Else, monochrome VGA?
  150.                JZ      GET_CRT_MODE            ;If yes, OK.
  151.                CMP     BL,8                    ;Else, color VGA?
  152.                JZ      GET_CRT_MODE            ;If yes, OK.
  153.  
  154. CK_EGA:        MOV     MAX_LINES,14            ;Else, use 14 max lines for EGA.
  155.                MOV     BL,10H                  ;Get EGA information.
  156.                MOV     AH,12H
  157.                INT     10H
  158.                MOV     DX,OFFSET NOT_EGA_VGA
  159.                CMP     BL,10H                  ;Is there an EGA?
  160.                JZ      ERROR_MSG               ;If no, exit with message.
  161.                TEST    ES:BYTE PTR [87H],8     ;Is EGA active?
  162.                JNZ     ERROR_MSG               ;If no, exit with message.
  163.  
  164. GET_CRT_MODE:  MOV     BL,ES:[49H]             ;Retrieve CRT_MODE.
  165.                CALL    INFORMATION             ;Get font information.
  166.                MOV     DX,OFFSET NOT_SUPPORTED
  167.                CMP     CX,MAX_POINTS           ;Font greater than 16 points?
  168.                JBE     CK_MODE                 ;If no, OK.
  169.  
  170. ERROR_MSG:     CALL    PRINT_STRING            ;Print error message.
  171. ERROR_EXIT:    MOV     AL,1                    ;ERRORLEVEL = 1
  172.                JMP     TERMINATE               ;Exit.
  173.  
  174. CK_MODE:       CMP     BL,7                            ;CRT_MODE mono?
  175.                JZ      SAVE_MODE                       ;If yes, skip.
  176.                MOV     BYTE PTR PROTECT_A000H + 7,0EH  ;Else, change parameter.
  177.                CMP     BL,2                            ;Is mode BW80?
  178.                JZ      SAVE_MODE               ;If yes, defaults.
  179.                MOV     ATTRIBUTE,17H           ;Else, use color attributes.       
  180.                MOV     INVERSE,71H
  181.                CMP     BL,3                    ;Are we in CO80?
  182.                JZ      SAVE_MODE               ;If yes, done here.
  183.                MOV     AX,3                    ;Else, change to CO80.
  184.                INT     10H
  185.                MOV     BL,3
  186.  
  187. SAVE_MODE:     MOV     CRT_MODE,BL             ;Save CRT_MODE in loader.
  188.                CALL    SETUP                   ;Setup the display.
  189.  
  190. ;************************** MAIN LOOP **************************;
  191. ; User input dispatcher.  AH = ASCII character; AL = Scan Code. ;
  192. ;***************************************************************;
  193.  
  194. INPUT:         CALL    HIDE_CURSOR             ;Park cursor off screen.
  195.                CALL    GET_INPUT               ;Get some input from user.
  196.                CMP     BUTTONS,0               ;Was a mouse button pressed?
  197.                JZ      CK_ASCII                ;If no, check keyboard input.
  198.                CALL    BUTTON_PRESS            ;Else, process button press.
  199.                JMP     SHORT INPUT             ;Next input.
  200.  
  201. CK_ASCII:      OR      AL,AL                   ;Scan code zero?
  202.                JZ      ALT_INPUT               ;If yes, ALT keypad entry.
  203.                MOV     DI,OFFSET DISPATCH_KEY  ;Else, check dispatch table.
  204.                MOV     CX,DISPATCH_CNT
  205.                REPNZ   SCASB
  206.                JNZ     ALT_INPUT               ;If no match, keyboard char.
  207.                SHL     CX,1                    ;Else, look up subroutine
  208.                MOV     DI,OFFSET DISPATCH_END
  209.                SUB     DI,CX
  210.                CALL    [DI]                    ; and process command.
  211.                JMP     SHORT INPUT             ;Next input.
  212.  
  213. ALT_INPUT:     OR      AH,AH                   ;ASCII zero?
  214.                JZ      INPUT                   ;If yes, skip.
  215.                MOV     EDIT_CHAR,AH            ;Else, store as new character.
  216.                CALL    SETUP_END               ;Display new edit character.
  217.                JMP     SHORT INPUT             ;Next input.
  218.  
  219. ;---------------------------------------------------;
  220. ; Exit.  If font was modified, prompt user to save. ;
  221. ;---------------------------------------------------;
  222.  
  223. EXIT:          CALL    CLS                     ;Clear the screen.
  224.                CMP     MODIFY_FLAG,1           ;Font modified?
  225.                JNZ     GOOD_EXIT               ;If no, return to DOS.
  226.                MOV     SI,OFFSET FILE_MSG
  227.                CMP     FILE_FLAG,1             ;If there a filename?
  228.                JZ      DO_FILE                 ;If yes, display it.
  229.                MOV     FILENAME,SI             ;Else, display "file".
  230. DO_FILE:       MOV     SI,OFFSET SAVE_MSG
  231.                CALL    PROMPT                  ;Prompt user to save.
  232.                JNZ     GOOD_EXIT               ;If "Y"es not pressed, exit.
  233.                CMP     FILE_FLAG,1             ;Else, is there a filename?
  234.                JZ      DO_SAVE                 ;If yes, save it.
  235.                CALL    GET_NAME                ;Else, get a filename.
  236.                JC      GOOD_EXIT               ;If aborted, exit.
  237.  
  238. DO_SAVE:       CALL    SAVE_FILE               ;Save the font COM file.
  239.  
  240. GOOD_EXIT:     CALL    CLS                     ;Clear the screen.
  241.                XOR     AL,AL                   ;ERRORLEVEL zero.
  242. TERMINATE:     MOV     AH,4CH                  ;Return to DOS.
  243.                INT     21H
  244.  
  245. MAIN           ENDP
  246.  
  247. ;            ***************
  248. ;            * SUBROUTINES *
  249. ;            ***************
  250.  
  251. ;-------------------------------------------------------------;
  252. ; What follows is the user input command processing routines. ;
  253. ;-------------------------------------------------------------;
  254.  
  255. BUTTON_PRESS:  CALL    GET_CURSOR              ;Is cursor in character box?
  256.                JNZ     DO_ENTER                ;If yes, process as if Enter.
  257.                CMP     LEFT_BUTTON,0           ;Else, left button press
  258.                JZ      TURN_OFF                ; will turn on pixel.
  259.                CALL    GET_PIXEL               ;Get the pixel.
  260.                OR      [DI],AH                 ;Turn it on.
  261.                JMP     SHORT BUTTON_END
  262.  
  263. TURN_OFF:      CALL    GET_PIXEL               ;Right button will turn off pixel
  264.                XOR     AH,0FFH                 ;Invert bit mask.
  265.                AND     [DI],AH                 ;Turn it off.
  266.  
  267. BUTTON_END:    CALL    UPDATE_CURSOR           ;Update the cursor.
  268.                CALL    LOAD_CHAR               ;Load the character.
  269.                RET
  270.  
  271. ;--------------------------------;
  272.  
  273. ENTER:         CALL    GET_CURSOR              ;Is cursor in character box?
  274.                JZ      ENTER_END               ;If no, ignore.
  275. DO_ENTER:      CALL    GET_CHAR                ;Else, get the highlighted char.
  276.                MOV     EDIT_CHAR,AL            ;Store it as new edit char.
  277.                CALL    NEW_CHAR                ;Display the edit character.
  278. ENTER_END:     RET
  279.  
  280. ;--------------------------------;
  281.  
  282. LEFT:          MOV     BP,0FFH                 ;Movement = 0 rows; -1 cols.
  283.                JMP     SHORT ARROWS
  284.  
  285. RIGHT:         MOV     BP,1                    ;Movement = 0 rows; +1 cols.
  286.                JMP     SHORT ARROWS
  287.  
  288. UP:            MOV     BP,0FF00H               ;Movement = -1 rows; 0 cols.
  289.                JMP     SHORT ARROWS
  290.  
  291. DOWN:          MOV     BP,100H                 ;Movement = +1 rows; 0 cols.
  292.  
  293. ARROWS:        CALL    RESTORE                 ;Restore current cursor position.
  294.                CALL    GET_CURSOR              ;Cursor in edit box?
  295.                MOV     CX,BP
  296.                JNZ     CHAR_ARROW              ;If no, do character movement.
  297.                ADD     CL,CL                   ;Else, double up col. movement.
  298.                CALL    CK_BOUNDS               ;Move cursor; check the boundary.
  299.                SUB     AX,EDIT_TOP             ;AX has position; make relative.
  300.                MOV     EDIT_CURSOR,AX          ;Store as new edit cursor.
  301.                MOV     BH,LAST_PIXEL           ;Retrieve the last pixel.
  302.                CALL    GET_PIXEL               ;Get pixel in new position.
  303.                CMP     SHIFT_STATE,0           ;Button or Shift key depressed?
  304.                JZ      UPDATE_PIXEL2           ;If no, update new cursor pos.
  305.  
  306.                OR      BH,BH                   ;Else, was last pixel on?
  307.                JNZ     BIT_ON                  ;If yes, drag to new position.
  308.                XOR     AH,0FFH                 ;Else, invert mask
  309.                AND     BYTE PTR [DI],AH;       ; and drag pixel off.
  310.                JMP     SHORT UPDATE_PIXEL1
  311.  
  312. BIT_ON:        OR      BYTE PTR [DI],AH        ;Turn the pixel on.
  313.  
  314. UPDATE_PIXEL1: CALL    LOAD_CHAR               ;Load the character.
  315.  
  316. UPDATE_PIXEL2: CALL    UPDATE_CURSOR           ;Update the cursor display.
  317.                RET
  318.  
  319. ;--------------------------------;
  320.  
  321. CHAR_ARROW:    CALL    CK_BOUNDS               ;Move cursor; check the boundary.
  322.                SUB     AX,CHAR_TOP             ;Convert to relative position.
  323.                MOV     CHAR_CURSOR,AX          ;Store new character box pos.
  324.                CMP     SHIFT_STATE,0           ;Button or Shift key depressed?
  325.                JZ      CHAR_END                ;If no, done here.
  326. NEW_CHAR:      CALL    GET_CHAR                ;Else, get the character
  327.                MOV     EDIT_CHAR,AL            ; and use as new edit character.
  328.                CALL    DISPLAY_FONT            ;Display it.
  329.  
  330. CHAR_END:      CALL    UPDATE_CURSOR           ;Update the cursor display.
  331.                RET
  332.  
  333. ;--------------------------------; 
  334.  
  335. PGUP:          DEC     EDIT_CHAR               ;Next lower edit character.
  336.                JMP     SHORT PAGE_END
  337.  
  338. PGDN:          INC     EDIT_CHAR               ;Next higher edit character.
  339.  
  340. PAGE_END:      CALL    SETUP_END               ;Display it.
  341.                RET
  342.  
  343. ;--------------------------------;
  344.  
  345. TAB:           CALL    RESTORE                 ;Restore current cursor position.
  346.                XOR     EDIT_FLAG,1             ;Toggle Edit/char active box.
  347.                CALL    UPDATE_CURSOR           ;Display cursor in new box.
  348.                RET
  349.  
  350. ;--------------------------------;
  351.  
  352. SPACE_BAR:     CALL    GET_CURSOR              ;Is cursor in character box?
  353.                JNZ     SPACE_END               ;If yes, ignore.
  354.                CALL    GET_PIXEL               ;Else, get the pixel.
  355.                XOR     [DI],AH                 ;Toggle the pixel.
  356.                CALL    UPDATE_PIXEL1           ;Update character and cursor.
  357. SPACE_END:     RET
  358.  
  359. ;--------------------------------;
  360.  
  361. DEL_ROW:       CALL    GET_CURSOR              ;Is cursor in character box?
  362.                JNZ     DELETE_RETURN           ;If yes, ignore.
  363.                MOV     BP,POINTS               ;Else, retrieve scan line points.
  364.                CMP     BP,1                    ;Is there only one scan line?
  365.                JZ      DELETE_RETURN           ;If yes, ignore.
  366.                MOV     AL,AH                   ;Else, delete position equals
  367.                XOR     AH,AH                   ; POINTS - relative ROW.
  368.                SUB     BP,AX
  369.  
  370.                CALL    CLEAR_MENU              ;Clear part of the menu and
  371.                MOV     DX,OFFSET WARNING_MSG   ; display warning message.
  372.                CALL    PRINT_STRING
  373.                CALL    QUERY                   ;Should we delete?
  374.                JNZ     DELETE_END              ;If no, done here.
  375.  
  376.                MOV     BX,POINTS               ;Else, retrieve bytes/char.
  377.                MOV     SI,OFFSET EDIT_FONT     ;Delete edit font.
  378.                CALL    DELETE
  379.                MOV     SI,OFFSET TEMPLATE_FONT ;Do same to template font.
  380.                CALL    DELETE
  381.  
  382.                DEC     BX                             ;One less byte/char.
  383.                MOV     BH,BL
  384.                CMP     BYTE PTR EDIT_CURSOR + 1,BL    ;Was last row deleted?
  385.                JNZ     LOAD_IT                        ;If no, OK.
  386.                DEC     BL                             ;Else, move cursor up one
  387.                MOV     BYTE PTR EDIT_CURSOR + 1,BL    ; row so it's on new char.
  388.  
  389. LOAD_IT:       MOV     BP,OFFSET EDIT_FONT
  390.                CALL    USER_LOAD               ;Load the new font.
  391.                CALL    INFORMATION             ;Get font information.
  392.                MOV     MODIFY_FLAG,1           ;Note that font's been modified.
  393.                CALL    CLS                     ;Clear the old display.
  394. DELETE_END:    XOR     DX,DX
  395.                CALL    SET_CURSOR
  396.                CALL    DISPLAY_COPY            ;Display new font.
  397. DELETE_RETURN: RET
  398.  
  399. ;-----------------;
  400.  
  401. DELETE:        MOV     DI,SI                   ;Destination starts at source.
  402.                MOV     CX,256                  ;256 characters to do.
  403. NEXT_DELETE:   PUSH    CX                      ;Save character count.
  404.                MOV     CX,BX                   ;BX has bytes/character.
  405. CK_SKIP:       CMP     CX,BP                   ;Is this the row to delete?
  406.                JZ      SKIP_ROW                ;If yes, skip it.
  407.                MOVSB                           ;Else, move it down.
  408.                JMP     SHORT LOOP_DELETE
  409. SKIP_ROW:      INC     SI                      ;Skip deletion row.
  410. LOOP_DELETE:   LOOP    CK_SKIP                 ;Do all character rows.
  411.                POP     CX
  412.                LOOP    NEXT_DELETE             ;Do all 256 characters.
  413.                RET
  414.  
  415. ;--------------------------------;
  416.  
  417. INS_ROW:       XOR     BL,BL                   ;Insert a zero byte.
  418.                JMP     SHORT INS_EDIT
  419.  
  420. ;--------------------------------;
  421.  
  422. DUP_ROW:       MOV     BL,-1                   ;Insert a duplicate byte.
  423. INS_EDIT:      CALL    GET_CURSOR              ;Is cursor in character box?
  424.                JNZ     INSERT_END              ;If yes, ignore.
  425.                MOV     BH,AH                   ;Row to be inserted.
  426.                INC     BH                      ;Adjust.
  427.                MOV     BP,POINTS               ;Retrieve bytes/char.
  428.                CMP     BP,MAX_LINES            ;Character maxed out?
  429.                JZ      INSERT_END              ;If yes, done here.
  430.                STD                             ;Else, backward moves.
  431.                MOV     SI,OFFSET EDIT_FONT     ;Insert a row.
  432.                CALL    INSERT
  433.                MOV     SI,OFFSET TEMPLATE_FONT ;Do same to template font.
  434.                CALL    INSERT
  435.  
  436.                CLD                             ;String operation back forward.
  437.                MOV     BX,BP                   ;Increment bytes/character.
  438.                MOV     BH,BL
  439.                INC     BH
  440.                MOV     BP,OFFSET EDIT_FONT     ;Load the new font.
  441.                CALL    USER_LOAD
  442.                CALL    INFORMATION             ;Get font information.
  443.                MOV     MODIFY_FLAG,1           ;Note that font's been modified.
  444.                CALL    SETUP_END               ;Display new font.
  445. INSERT_END:    RET
  446.  
  447. ;-----------------;
  448.  
  449. INSERT:        MOV     AX,BP                   ;Go to end of font
  450.                MOV     CX,256                  ; (256 * points) - 1
  451.                MUL     CX
  452.                DEC     AX
  453.                ADD     SI,AX
  454.                MOV     DI,SI
  455.                ADD     DI,CX                   ;New font = old font + 256.
  456.  
  457. NEXT_INSERT:   PUSH    CX                      ;Save character count.
  458.                MOV     CX,BP                   ;Retrieve bytes/char.
  459. MOVE_BYTE:     MOVSB                           ;Move a byte.
  460.                CMP     CL,BH                   ;Is there an insert row?
  461.                JNZ     LOOP_INSERT
  462.                MOV     AL,BL                   ;If yes, assume zero insert.
  463.                OR      BL,BL                   ;Is zero to be inserted?
  464.                JZ      INSERT_IT               ;If yes, guessed right.
  465.                MOV     AL,[SI+1]               ;Else, duplicate with byte below.
  466. INSERT_IT:     STOSB                           ;Insert it.
  467. LOOP_INSERT:   LOOP    MOVE_BYTE               ;Do all bytes/char.
  468.                POP     CX
  469.                LOOP    NEXT_INSERT             ;Do all 256 characters.
  470.                RET
  471.  
  472. ;--------------------------------;
  473.  
  474. COPY_TEMP:     CALL    GET_PIXEL               ;Get index to current char.
  475.                MOV     DI,SI                   ;Destination = Source+(16 * 256).
  476.                ADD     SI,MAX_POINTS * 256
  477.                MOV     CX,POINTS               ;Bytes/character to copy.
  478.                REP     MOVSB                   ;Copy them.
  479.                CALL    SETUP_END               ;Update the display.
  480.                CALL    LOAD_CHAR               ;Load the new character.
  481.                RET
  482.  
  483. ;--------------------------------;
  484.  
  485. SAVE:          CMP     FILE_FLAG,1             ;Is there a filename?
  486.                JZ      SAVE_IT                 ;If yes, save it.
  487.                CALL    CLS                     ;Else, clear screen.
  488.                CALL    GET_NAME                ;Get a filename.
  489.                PUSHF                           ;Save results.
  490.                CALL    DISPLAY_HEAD            ;Redisplay menu.
  491.                POPF                            ;Retrieve results.
  492.                JC      SAVE_END                ;If user aborted, skip save.
  493. SAVE_IT:       CALL    SAVE_FILE               ;Save the file.
  494. SAVE_END:      RET
  495.  
  496. ;*********** END OF COMMAND PROCESSING ROUTINES ***********;
  497.  
  498. ;---------------------------;
  499. ; OUTPUT                    ;
  500. ;   If Edit cursor, ZF = 1  ;
  501. ;   If Char cursor, ZF = 0  ;
  502. ;   DX = cursor position.   ;
  503. ;   AX = relative position. ;
  504. ;---------------------------;
  505.  
  506. GET_CURSOR:    MOV     AX,EDIT_CURSOR          ;Assume edit cursor; retrieve it.
  507.                MOV     DX,AX                   ;Cursor position = relative
  508.                ADD     DX,EDIT_TOP             ; position + top left of edit box
  509.                CMP     EDIT_FLAG,1             ;Are we in edit box?
  510.                JZ      CURSOR_END              ;If yes, guessed right.
  511.                MOV     AX,CHAR_CURSOR          ;Else, retrieve char. cursor.
  512.                MOV     DX,AX                   ;Calculate cursor position.
  513.                ADD     DX,CHAR_TOP
  514.  
  515. CURSOR_END:    RET
  516.  
  517. ;---------------------------------------------------;
  518. ; Return highlighted cursor position to background. ;
  519. ;---------------------------------------------------;
  520.  
  521. RESTORE:       MOV     BL,ATTRIBUTE            ;Background attribute.
  522.                CALL    GET_CURSOR              ;Is cursor in character box?
  523.                JNZ     CHAR_RESTORE            ;If yes, restore char box.
  524.                CALL    GET_PIXEL               ;Else, get pixel and write.
  525.                CALL    WRITE_PIXEL
  526.                RET
  527.  
  528. CHAR_RESTORE:  CALL    GET_CHAR                ;Get character and write.
  529.                CALL    WRITE_CHAR
  530.                RET
  531.  
  532. ;--------------------------------;
  533. ; Highlight new cursor position. ;
  534. ;--------------------------------;
  535.  
  536. UPDATE_CURSOR: MOV     BL,ATTRIBUTE            ;Retrieve background attribute.
  537.                OR      BL,INTENSITY            ;Turn on intensity bit.
  538.                CALL    GET_CURSOR              ;Is cursor in character box?
  539.                JNZ     DO_CHAR                 ;If yes, do character cursor.
  540.  
  541. FONT_CURSOR:   CALL    GET_PIXEL               ;Else, get pixel and write it.
  542.                CALL    WRITE_PIXEL
  543.                RET
  544.  
  545. DO_CHAR:       CALL    GET_CHAR                ;Retrieve character.
  546.                MOV     DI,OFFSET BLANKS        ;Use inverse video for invisible
  547.                MOV     CX,3                    ; characters 0, 32 and 255.
  548.                REPNZ   SCASB
  549.                JNZ     DO_CURSOR
  550.                MOV     BL,INVERSE
  551.  
  552. DO_CURSOR:     CALL    WRITE_CHAR              ;Update the character cursor.
  553.                RET
  554.  
  555. ;-----------------------------------;
  556. ; INPUT                             ;
  557. ;   AX = Relative cursor position.  ;
  558. ;   DX = Actual cursor position.    ;
  559. ;   CX = Direction.                 ;
  560. ;                                   ;
  561. ; OUTPUT                            ;
  562. ;   DX = New cursor position.       ;
  563. ;   AX = New cursor position.       ;
  564. ;   BX preserved.                   ;
  565. ;-----------------------------------;
  566.  
  567. CK_BOUNDS:     ADD     DH,CH                   ;Add row direction
  568.                ADD     DL,CL                   ; and column direction.
  569.                PUSH    BX                      ;Save BX.
  570.                MOV     BL,16                   ;Use 16 as bounds for char.
  571.                CMP     EDIT_FLAG,1             ; box bottom.
  572.                JNZ     CK_LEFT                 ;Use bytes/char bounds for edit
  573.                MOV     BX,POINTS               ; box bottom.
  574.  
  575. CK_LEFT:       ADD     AL,CL                   ;Add column to relative pos.
  576.                JGE     CK_RIGHT
  577.                ADD     DL,16                   ;If too far left, 
  578.                JMP     SHORT BOUNDS_END        ; wrap to right.
  579.  
  580. CK_RIGHT:      CMP     AL,16                   ;If too far right,
  581.                JB      CK_UP
  582.                SUB     DL,16                   ; wrap to left.
  583.  
  584. CK_UP:         ADD     AH,CH                   ;Add row to relative position.
  585.                JGE     CK_DOWN
  586.                ADD     DH,BL                   ;If too far up,
  587.                JMP     SHORT BOUNDS_END        ; wrap to bottom
  588.  
  589. CK_DOWN:       CMP     AH,BL                   ;If too far down,
  590.                JB      BOUNDS_END              ; wrap to top.
  591.                MOV     DH,EDIT_ROW
  592.  
  593. BOUNDS_END:    MOV     AX,DX                   ;Return copy of cursor position.
  594.                POP     BX                      ;Restore BX.
  595.                RET
  596.  
  597. ;----------------------------------;
  598. ; INPUT                            ;
  599. ;   AX = Relative cursor position. ;
  600. ;                                  ;
  601. ; OUTPUT                           ;
  602. ;   AL = character.                ;
  603. ;----------------------------------;
  604.  
  605. GET_CHAR:      MOV     CL,4                    ;Character = row * 16 + column.
  606.                SHL     AH,CL
  607.                ADD     AL,AH
  608.                RET
  609.  
  610. ;-------------------;
  611. ; Font information. ;
  612. ;-------------------;
  613.  
  614. INFORMATION:   MOV     BH,2                    ;Get information.
  615.                MOV     AX,1130H
  616.                INT     10H
  617.                PUSH    CS                      ;Restore extra segment.
  618.                POP     ES
  619.                MOV     POINTS,CX               ;Store bytes/character.
  620.                MOV     ROWS,DL                 ;Store rows on screen.
  621.                RET
  622.  
  623. ;----------------------------------------------------------------;
  624. ; Filename is parsed of white space and COM extension tacked on. ;
  625. ;----------------------------------------------------------------;
  626.  
  627. PARSE_FILE:    MOV     SI,81H                  ;Point to parameter.
  628. NEXT_PARSE:    LODSB                           ;Get a byte.
  629.                CMP     AL,SPACE                ;Is it leading space?
  630.                JZ      NEXT_PARSE              ;If yes, ignore.
  631.                CMP     AL,TAB_CHAR             ;Is it leading tab?
  632.                JZ      NEXT_PARSE              ;If yes, ignore.
  633.                DEC     SI                      ;Adjust pointer.
  634.                MOV     FILENAME,SI             ;Store start of filename.
  635.  
  636. FIND_END:      LODSB                           ;Get a byte.
  637.                CMP     AL,SPACE                ;Is it space or below?
  638.                JBE     PARSE_END               ;If yes, end of filename.
  639.                CMP     AL,"a"                  ;Capitalize.
  640.                JB      CK_DOT
  641.                CMP     AL,"z"
  642.                JA      CK_DOT
  643.                AND     BYTE PTR [SI-1],5FH
  644. CK_DOT:        CMP     AL,"."                  ;Is it a dot?
  645.                JNZ     FIND_END                ;If no, continue.
  646. PARSE_END:     MOV     DI,SI                   ;Else, if dot or end of filename
  647.                DEC     DI                      ; tack on ".COM".
  648.                MOV     SI,OFFSET COM
  649.                MOV     CX,5
  650.                REP     MOVSB
  651.                RET
  652.  
  653. ;-----------------------------;
  654. ; OUTPUT                      ;
  655. ;   If file exists,    CY = 0 ;
  656. ;   If file not found, CY = 1 ;
  657. ;-----------------------------;
  658.  
  659. OPEN_FILE:     MOV     DX,FILENAME
  660.                MOV     AX,3D02H                ;Open file for reading, writing.
  661.                INT     21H
  662. SAVE_HANDLE:   MOV     FILE_HANDLE,AX          ;Save filehandle.
  663.                MOV     BX,AX
  664.                RET
  665.  
  666. ;------------------------;
  667. ; OUTPUT                 ;
  668. ;   If successful CY = 0 ;
  669. ;   If failed     CY = 1 ;
  670. ;------------------------;
  671.  
  672. CREATE_FILE:   MOV     DX,FILENAME
  673.                XOR     CX,CX                   ;Create normal file.
  674.                MOV     AH,3CH
  675.                INT     21H
  676.                JC      CREATE_END
  677.                CALL    SAVE_HANDLE             ;If successful, save filehandle
  678.                CALL    SAVE_FILE               ; and save font file.
  679. CREATE_END:    RET
  680.  
  681. ;-----------------------------------------------------------------------; 
  682. ; Read the parsed file.  Check if legitimate font file.  Load the font. ;
  683. ;-----------------------------------------------------------------------;
  684.  
  685. READ_FILE:     MOV     BX,FILE_HANDLE          ;Retrieve filehandle.
  686.                MOV     DX,OFFSET LOADER        ;Point to loader.
  687.                MOV     CX,LOADER_LENGTH        ;Bytes to read.
  688.                MOV     AH,3FH                  ;Read from disk.
  689.                INT     21H
  690.                MOV     SI,OFFSET PROGRAMMER1   ;Use name as legitimate font
  691.                MOV     DI,OFFSET PROGRAMMER2   ; file signature.
  692.                MOV     CX,SIGNATURE_LEN / 2
  693.                REPZ    CMPSW
  694.                JZ      READ_END
  695.                CALL    DISP_FILENAME
  696.                MOV     DX,OFFSET NOT_FONT_MSG  ;If not font file, exit
  697.                JMP     ERROR_MSG               ; with message.
  698.  
  699. READ_END:      MOV     FILE_FLAG,1             ;Else, note that filename found.
  700.                PUSH    BX                      ;Save filehandle.
  701.                MOV     BP,OFFSET EDIT_FONT     ;Point to font.
  702.                MOV     BH,BYTE PTR POINTS      ;Bytes/character.
  703.                CALL    USER_LOAD               ;Load the font.
  704.                CALL    INFORMATION             ;Get font information.
  705.                POP     BX                      ;Retrieve filehandle.
  706.  
  707. ;--------------------------------;
  708.  
  709. CLOSE_FILE:    MOV     AH,3EH
  710.                INT     21H
  711.                RET
  712.  
  713. ;--------------------------------;
  714.  
  715. SAVE_FILE:     CALL    OPEN_FILE               ;Open the file and write
  716.                MOV     DX,OFFSET LOADER        ; font image and loader to disk.
  717.                MOV     CX,LOADER_LENGTH
  718.                MOV     AH,40H
  719.                INT     21H
  720.                MOV     MODIFY_FLAG,0           ;Reset modify flag.
  721.                MOV     FILE_FLAG,1             ;Note that have a filename.
  722.                JMP     SHORT CLOSE_FILE
  723.  
  724. ;-------------------------------; 
  725. ; INPUT                         ;
  726. ;   SI = first string to write. ;
  727. ;                               ;
  728. ; OUTPUT                        ;
  729. ;   If "Y"es pressed, ZF = 1    ;
  730. ;   Else,             ZF = 0    ;
  731. ;-------------------------------;
  732.  
  733. PROMPT:        CALL    TTY_STRING              ;Write preface string.
  734.                CALL    DISP_FILENAME           ;Write filename.
  735. QUERY:         MOV     SI,OFFSET YES_NO        ;Write query string.
  736.                CALL    TTY_STRING
  737.                CALL    GET_KEY                 ;Get a response.
  738.                CMP     AH,Y_SCAN               ;Check if "Y" pressed.
  739.                RET
  740.  
  741. ;-------------------------------; 
  742. ; OUTPUT                        ;
  743. ;   If name valid,       CY = 0 ;
  744. ;   If invalid or abort, CY = 1 ;
  745. ;-------------------------------;
  746.  
  747. GET_NAME:      MOV     DX,OFFSET FILENAME_MSG  ;Ask for filename.
  748.                CALL    PRINT_STRING
  749.                MOV     DI,81H                  ;Use PSP's DTA for input.
  750. NEXT_NAME:     CALL    GET_KEY                 ;Get a keystroke.
  751.                CMP     AH,ESC_SCAN             ;Esc?
  752.                STC
  753.                JZ      NAME_END                ;If yes, abort with CY = 1.
  754.                CMP     AH,LEFT_ARROW           ;Backspace with left arrow
  755.                JZ      DO_BS                   ; or backspace key.
  756.                CMP     AH,BS_SCAN
  757.                JZ      DO_BS
  758.                CMP     AH,ENTER_SCAN           ;If Enter key, done here.
  759.                JZ      STORE_BYTE
  760.                CMP     AL,SPACE                ;Ignore space and below.
  761.                JBE     NEXT_NAME
  762.                JMP     SHORT STORE_BYTE
  763.  
  764. DO_BS:         DEC     DI                      ;TTY Backspace = the characters
  765.                MOV     AL,8                    ; 8, space and 8.
  766.                PUSH    AX
  767.                CALL    WRITE_TTY
  768.                MOV     AL,SPACE
  769.                CALL    WRITE_TTY
  770.                POP     AX
  771.                JMP     SHORT DISPLAY_BYTE
  772.  
  773. STORE_BYTE:    STOSB
  774.                CMP     AH,ENTER_SCAN           ;Done if Enter.
  775.                JZ      PARSE_IT
  776. DISPLAY_BYTE:  CALL    WRITE_TTY               ;Echo input to screen.
  777.                JMP     SHORT NEXT_NAME
  778.  
  779. PARSE_IT:      CALL    PARSE_FILE              ;Parse the filename.
  780.                CALL    OPEN_FILE               ;See if it exists.
  781.                JC      CREATE_IT               ;If no, create it.
  782.                MOV     SI,OFFSET EXIST_MSG     ;Else, ask if should write
  783.                CALL    PROMPT                  ; over existing file.
  784.                JNZ     GET_NAME
  785.  
  786. CREATE_IT:     CALL    CREATE_FILE             ;Create the file.
  787.                JNC     NAME_END
  788.                MOV     DX,OFFSET FAILED_MSG    ;If failed, inform user
  789.                CALL    PRINT_STRING            ; and ask for new filename.
  790.                JMP     SHORT GET_NAME
  791. NAME_END:      RET
  792.  
  793. ;--------------------------------------;
  794. ; OUTPUT                               ;
  795. ;   AH = Bit mask                      ;
  796. ;   AL = PIXEL_ON or PIXEL_OFF         ;
  797. ;   SI = Pointer to start of Character ;
  798. ;   DI = Pointer to start of Scan Line ;
  799. ;   PIXEL = 0 or -1                    ;
  800. ;--------------------------------------;
  801.  
  802. GET_PIXEL:     MOV     SI,OFFSET EDIT_FONT     ;Point to start of edit font.
  803.                CALL    CHAR_START              ;Index to current character.
  804.                MOV     DI,SI                   ;Also into DI.
  805.                MOV     CX,EDIT_CURSOR          ;Retrieve edit cursor.
  806.                SHR     CL,1                    ;Two col/bit so divide by two.
  807.                MOV     AH,10000000B            ;Bit starts in most significant.
  808.                SHR     AH,CL                   ;Shift bit to column position.
  809.                MOV     CL,CH                   ;Row in CL.
  810.                XOR     CH,CH                   ;Zero in high half.
  811.                ADD     DI,CX                   ;Add to character start.
  812.                MOV     CL,[DI]                 ;Retrieve the current byte.
  813.                MOV     AL,PIXEL_OFF            ;Assume it is off.
  814.                MOV     LAST_PIXEL,0
  815.                AND     CL,AH                   ;AND with bit mask.
  816.                JZ      END_PIXEL               ;If off, guessed right.
  817.                MOV     AL,PIXEL_ON             ;Else, pixel is on.
  818.                MOV     LAST_PIXEL,-1
  819. END_PIXEL:     RET
  820.  
  821. ;--------------------------------;
  822.  
  823. WRITE_PIXEL:   CALL    WRITE_CHAR              ;Two characters/pixel.
  824.                INC     DL
  825.                CALL    WRITE_CHAR
  826.                INC     DL
  827.                RET
  828.  
  829. ;----------------------------;
  830. ; INPUT                      ;
  831. ;   SI = Font start.         ;
  832. ;                            ;
  833. ; OUTPUT                     ;
  834. ;   AX = Edit character.     ;
  835. ;   SI = Start of character. ;
  836. ;----------------------------;
  837.  
  838. CHAR_START:    MOV     CX,POINTS               ;Retrieve bytes/character.
  839.                MOV     AL,EDIT_CHAR            ;Retrieve edit character.
  840.                XOR     AH,AH                   ;Zero in high half.
  841.                PUSH    AX                      ;Preserve character.
  842.                MUL     CL                      ;Char start = bytes/char * char.
  843.                ADD     SI,AX                   ;Add to index.
  844.                POP     AX                      ;Retrieve character.
  845.                RET
  846.  
  847. ;--------------------------------------------;
  848. ; OUTPUT                                     ;
  849. ;   AH = ASCII character.                    ;
  850. ;   AL = Scan code.                          ;
  851. ;   BUTTONS = button pressed.                ;
  852. ;   SHIFT_STATE = Shift or button depressed. ;
  853. ;--------------------------------------------;
  854.  
  855. GET_INPUT:     XOR     BP,BP                   ;Store input in BP; start with 0.
  856.                MOV     SHIFT_STATE,0           ;Zero in Shift state.
  857.                MOV     BUTTONS,0               ;Zero in Buttons also.
  858.                CMP     MOUSE_FLAG,1            ;Is the mouse active?
  859.                JNZ     CK_KEYBOARD             ;If no, skip mouse poll.
  860.  
  861.                XOR     BX,BX                   ;Left button.
  862.                MOV     AX,5                    ;Button press information.
  863.                INT     33H
  864.                OR      SHIFT_STATE,AL          ;Store button depressed info.
  865.                OR      LEFT_BUTTON,BL          ;Store button press info.
  866.                MOV     BX,1                    ;Do same for right button.
  867.                MOV     AX,5
  868.                INT     33H
  869.                OR      RIGHT_BUTTON,BL         ;Store button pressed info.
  870.                CMP     BUTTONS,0               ;Any button pressed?
  871.                JNZ     INPUT_END               ;If yes, done here.
  872.  
  873. MOUSE_MOTION:  MOV     AX,0BH                  ;Read mouse motion.
  874.                INT     33H
  875.                ADD     CX,HORIZONTAL           ;Add in last horizontal motion.
  876.                ADD     DX,VERTICAL             ; and last vertical motion.
  877.                MOV     AX,MICKEY               ;Retrieve mouse unit of motion.
  878.  
  879.                MOV     SI,RIGHT_ARROW          ;Assume right movement.
  880.                CMP     CX,AX                   ;Is horizontal > mickey?
  881.                JG      HORIZ                   ;If yes, guessed right.
  882.                MOV     SI,DN_ARROW             ;Assume down movement.
  883.                CMP     DX,AX                   ;Is vertical > mickey?
  884.                JG      VERT                    ;if yes, guessed right.
  885.  
  886.                NEG     AX                      ;Else, negate mickey.
  887.                MOV     SI,LEFT_ARROW           ;Assume left movement.
  888.                CMP     CX,AX                   ;Is horizontal < mickey?
  889.                JL      HORIZ                   ;If yes, guessed right.
  890.                MOV     SI,UP_ARROW             ;Assume up movement.
  891.                CMP     DX,AX                   ;Is vertical < mickey?
  892.                JGE     STORE_MOTION            ;If yes, guessed right.
  893.  
  894. VERT:          SUB     DX,AX                   ;Subtract vertical mickey.
  895.                JMP     SHORT STORE_SCAN        ;Update vertical.
  896.  
  897. HORIZ:         SUB     CX,AX                   ;Subtract horizontal mickey.
  898.  
  899. STORE_SCAN:    MOV     BP,SI                   ;Store scan code in BP.
  900. STORE_MOTION:  MOV     HORIZONTAL,CX           ;Update movements.
  901.                MOV     VERTICAL,DX
  902.  
  903. CK_KEYBOARD:   MOV     AH,2                    ;Keyboard Shift state.
  904.                INT     16H
  905.                AND     AL,SHIFT_KEYS           ;Mask off all but Shift keys.
  906.                OR      SHIFT_STATE,AL          ;Store Shift state.
  907.  
  908.                MOV     AH,1                    ;Keystroke status.
  909.                INT     16H
  910.                JZ      STORE_INPUT             ;If none available, done here.
  911.                CALL    GET_KEY                 ;Else, get keystroke
  912.                XCHG    AL,AH                   ;Exchange scan/ASCII code.
  913.                JMP     SHORT INPUT_END
  914.  
  915. STORE_INPUT:   MOV     AX,BP                   ;Return input in AX
  916.                OR      AX,AX                   ;Is there input?
  917.                JNZ     INPUT_END               ;If yes, done here.
  918.                CMP     BUTTONS,0               ;Is there button pressed?
  919.                JNZ     INPUT_END               ;If yes, done here.
  920.                JMP     GET_INPUT               ;Else, wait until input.
  921. INPUT_END:     RET
  922.  
  923. ;--------------------------------;
  924.  
  925. DISPLAY_FONT:  MOV     AL,ROWS                 ;Retrieve rows on screen.
  926.                INC     AL                      ;Zero based; adjust.
  927.                MOV     DX,34EH                 ;Display at Row 2; Col. 77.
  928.                MOV     CX,3                    ;Three bytes to write.
  929.                MOV     BL,ATTRIBUTE            ;Use background attribute.
  930.                CALL    DIVIDE                  ;Display the number.
  931.  
  932.                MOV     DX,BOX_TOP + 103H       ;Point to inside of info box.
  933.                MOV     AL,EDIT_CHAR            ;Retrieve character.
  934.                CALL    WRITE_CHAR              ;Display it.
  935.  
  936.                ADD     DL,7                    ;Move to end of number col.
  937.                MOV     CX,3                    ;Three bytes to write.
  938.                CALL    DIVIDE                  ;Display the number.
  939.  
  940.                MOV     BP,TEMPLATE_TOP         ;Display template character.
  941.                MOV     SI,OFFSET TEMPLATE_FONT
  942.                CALL    UPDATE_FONT
  943.  
  944.                MOV     BP,EDIT_TOP             ;Display edit character.
  945.                MOV     SI,OFFSET EDIT_FONT
  946.  
  947. UPDATE_FONT:   CALL    CHAR_START              ;Retrieve index to character.
  948.  
  949. NEXT_LINE:     LODSB                           ;Get a byte.
  950.                MOV     AH,AL                   ;Store in AH.
  951.                MOV     DI,AX                   ;Store in DI.
  952.                PUSH    CX                      ;Preserve bytes/char.
  953.                MOV     CX,8                    ;Eight bits/byte.
  954.                MOV     DX,BP                   ;Top left of font display.
  955.  
  956. NEXT_PIXEL:    RCL     DI,1                    ;Get a bit.
  957.                MOV     AL,PIXEL_ON             ;Assume it's on.
  958.                JC      DISPLAY_IT              ;Did bit end up in carry flag?
  959.                MOV     AL,PIXEL_OFF            ;If no, guessed wrong; pixel off.
  960.  
  961. DISPLAY_IT:    CALL    WRITE_PIXEL             ;Display the pixel.
  962.                LOOP    NEXT_PIXEL              ;Do all 8 pixels.
  963.  
  964.                ADD     BP,100H                 ;Next display row.
  965.                POP     CX                      ;Retrieve bytes/char.
  966.                LOOP    NEXT_LINE               ;Do all rows.
  967.                RET
  968.  
  969. ;---------------------------;
  970. ; INPUT                     ;
  971. ;   Entry point = DIVIDE.   ;
  972. ;   AL = Number to display. ;
  973. ;   BL = Attribute.         ;
  974. ;   CX = Places to display. ;
  975. ;   DX = Cursor position.   ;
  976. ;---------------------------;
  977.  
  978. NEXT_COUNT:    MOV     AH,SPACE                ;Assume zero.
  979.                OR      AL,AL                   ;Is it a zero?
  980.                JZ      ASCII                   ;If yes, display space instead.
  981. DIVIDE:        MOV     BH,10                   ;Divisor of ten.
  982.                XOR     AH,AH                   ;Zero in high half.
  983.                DIV     BH                      ;Divide by ten.
  984.                ADD     AH,"0"                  ;Convert to ASCII.
  985. ASCII:         XCHG    AL,AH                   ;Remainder in AL.
  986.                CALL    WRITE_CHAR              ;Display it.
  987.                XCHG    AL,AH                   ;Back to AH.
  988.                DEC     DL                      ;Move back one column.
  989.                LOOP    NEXT_COUNT              ;Display all three bytes.
  990.                RET
  991.  
  992. ;---------------------;
  993. ; INPUT               ;
  994. ;   AL = Character    ;
  995. ;   BL = Attribute    ;
  996. ;   AX, CX preserved. ;
  997. ;---------------------;
  998.  
  999. WRITE_CHAR:    PUSH    AX
  1000.                PUSH    CX
  1001.                CALL    SET_CURSOR
  1002.                MOV     CX,1
  1003.                MOV     AH,9                    ;Write attribute/character.
  1004.                INT     10H
  1005.                POP     CX
  1006.                POP     AX
  1007.                RET
  1008.  
  1009. ;------------------------------------------------------------------------------;
  1010. ; The Ega/Vga registers are programmed to access segment A000h where the       ;
  1011. ; fonts are stored.  The font is retrieved and registers reset back to normal. ;
  1012. ;------------------------------------------------------------------------------;
  1013.  
  1014. RETRIEVE_FONT: MOV     SI,OFFSET ACCESS_A000H  ;Point to access parameters.
  1015.                CALL    SET_REGISTERS           ;Set the registers.
  1016.  
  1017.                MOV     BX,POINTS               ;Retrieve bytes/character.
  1018.                MOV     AX,0A000H               ;Point to font segment.
  1019.                MOV     DS,AX
  1020.                MOV     DI,OFFSET EDIT_FONT     ;Point to destination.
  1021.                MOV     BP,256                  ;256 characters.
  1022.                XOR     DX,DX                   ;Source starting offset of zero.
  1023.  
  1024. NEXT_CHAR:     MOV     SI,DX                   ;Point to source.
  1025.                MOV     CX,BX                   ;Bytes/character.
  1026.                REP     MOVSB                   ;Retrieve the bytes.
  1027.                ADD     DX,20H                  ;Next character two paragraphs.
  1028.                DEC     BP                      ;Do all 256 characters.
  1029.                JNZ     NEXT_CHAR
  1030.  
  1031.                PUSH    CS                      ;Restore data segment.
  1032.                POP     DS
  1033.  
  1034.                MOV     SI,OFFSET EDIT_FONT     ;Copy the edit font to template.
  1035.                MOV     DI,OFFSET TEMPLATE_FONT
  1036.                MOV     CX,MAX_POINTS * 256 / 2
  1037.                REP     MOVSW
  1038.  
  1039.                MOV     SI,OFFSET PROTECT_A000H ;Point to normal parameters.
  1040.  
  1041. SET_REGISTERS: MOV     CX,2                    ;Two sequencer registers.
  1042.                MOV     DX,3C4H                 ;Indexing register.
  1043.                CALL    NEXT_REGISTER
  1044.  
  1045.                MOV     CX,3                    ;Three graphics controller regs.
  1046.                MOV     DL,0CEH                 ;Indexing registers.
  1047. NEXT_REGISTER: LODSB                           ;Get index.
  1048.                OUT     DX,AL
  1049.                INC     DX
  1050.                LODSB                           ;Get value.
  1051.                OUT     DX,AL
  1052.                DEC     DX
  1053.                LOOP    NEXT_REGISTER
  1054.                RET
  1055.  
  1056. ;-----------------------------------------------------;
  1057. ; Similar to RETRIEVE_FONT procedure except character ;
  1058. ; is uploaded instead of entire font down loaded.     ;
  1059. ;-----------------------------------------------------;
  1060.  
  1061. LOAD_CHAR:     MOV     SI,OFFSET ACCESS_A000H
  1062.                CLI
  1063.                CALL    SET_REGISTERS
  1064.                MOV     SI,OFFSET EDIT_FONT     ;Point to character
  1065.                CALL    CHAR_START              ; to upload.
  1066.                PUSH    CX                      ;Preserve bytes/char.
  1067.                MOV     CL,5                    ;32 bytes record for A000h font.
  1068.                SHL     AX,CL                   ;Index to appropriate character.
  1069.                MOV     DI,AX
  1070.                POP     CX
  1071.                MOV     AX,0A000H               ;Point to font segment.
  1072.                MOV     ES,AX
  1073.                REP     MOVSB                   ;Upload the bytes.
  1074.                PUSH    CS                      ;Restore extra segment.
  1075.                POP     ES
  1076.                MOV     SI,OFFSET PROTECT_A000H
  1077.                CALL    SET_REGISTERS
  1078.                STI
  1079.                MOV     MODIFY_FLAG,1           ;Note that font modified.
  1080.                RET
  1081.  
  1082. ;--------------------------------;
  1083.  
  1084. SET_CURSOR:    PUSH    AX
  1085.                XOR     BH,BH
  1086.                MOV     AH,2                    ;Set cursor position.
  1087.                INT     10H
  1088.                POP     AX
  1089.                RET
  1090.  
  1091. ;--------------------------------;
  1092.  
  1093. HIDE_CURSOR:   MOV     DH,ROWS
  1094.                INC     DH
  1095.                XOR     DL,DL                   ;Hide cursor one row below
  1096.                CALL    SET_CURSOR              ; displayable rows.
  1097.                RET
  1098.  
  1099. ;--------------------------------;
  1100.  
  1101. CLEAR_MENU:    MOV     CX,100H                 ;Row 1; column zero.
  1102.                MOV     DX,34FH                 ;Row 3; column 79.
  1103.                JMP     SHORT SCROLL
  1104.  
  1105. CLS:           XOR     CX,CX                   ;Row zero; column zero.
  1106.                MOV     DH,ROWS                 ;Rows.
  1107.                MOV     DL,79                   ;Column 79.
  1108. SCROLL:        MOV     BH,7                    ;Attribute.
  1109.                MOV     AX,600H                 ;Scroll window of active page.
  1110.                INT     10H
  1111.  
  1112.                XOR     DX,DX
  1113.                CALL    SET_CURSOR
  1114.                RET
  1115.  
  1116. ;--------------------------------;
  1117.  
  1118. GET_KEY:       XOR     AH,AH
  1119.                INT     16H
  1120.                RET
  1121.  
  1122. ;--------------------------------;
  1123.  
  1124. PRINT_STRING:  MOV     AH,9
  1125.                INT     21H
  1126.                RET
  1127.  
  1128. ;--------------------------------;
  1129.  
  1130. DISP_FILENAME: MOV     SI,FILENAME
  1131.                JMP     SHORT TTY_STRING
  1132.  
  1133. ;-----------------;
  1134.  
  1135. DO_WRITE:      CALL    WRITE_TTY
  1136. TTY_STRING:    LODSB
  1137.                OR      AL,AL
  1138.                JNZ     DO_WRITE
  1139.                RET
  1140.  
  1141. ;-----------------;
  1142.  
  1143. WRITE_TTY:     MOV     AH,0EH
  1144.                INT     10H
  1145.                RET
  1146.  
  1147. ;--------------------------------;
  1148.  
  1149. DO_CHAR_ATTR:  CALL    WRITE_CHAR
  1150.                INC     DL
  1151. CHAR_ATTRIB:   LODSB
  1152.                OR      AL,AL
  1153.                JNZ     DO_CHAR_ATTR
  1154.                RET
  1155.  
  1156. ;--------------------------------;                               
  1157.  
  1158. SETUP:         CLI                             ;No interrupts.
  1159.                CALL    RETRIEVE_FONT           ;Retrieve font.
  1160.                STI                             ;Interrupts back on.
  1161.                CMP     BYTE PTR DS:[80H],0     ;Command line parameter?
  1162.                JZ      CK_MOUSE                ;If no, skip to mouse.
  1163.                CALL    PARSE_FILE              ;Else, parse the parameter.
  1164.                CALL    OPEN_FILE               ;Try to open the file.
  1165.                JC      CREATE_PROMPT           ;If not found, ask to create.
  1166.                CALL    READ_FILE               ;Else, read the file.
  1167.                JMP     SHORT CK_MOUSE          ;Done here.
  1168.  
  1169. CREATE_PROMPT: MOV     SI,OFFSET CREATE_MSG    ;Display create query.
  1170.                CALL    PROMPT
  1171.                JZ      CREATE                  ;If got thumbs up, create it.
  1172.                JMP     ERROR_EXIT              ;Else, exit.
  1173.  
  1174. CREATE:        CALL    CREATE_FILE             ;Create the file.
  1175.                MOV     DX,OFFSET FAILED_MSG    ;If failed, exit with message.
  1176.                JNC     CK_MOUSE
  1177.                JMP     ERROR_MSG
  1178.  
  1179. CK_MOUSE:      XOR     AX,AX                   ;Mouse reset and status.
  1180.                INT     33H
  1181.                OR      AX,AX                   ;Is mouse active?
  1182.                JZ      DISPLAY_HEAD            ;If no, skip.
  1183.                MOV     MOUSE_FLAG,1            ;Else, flag.
  1184.  
  1185. DISPLAY_HEAD:  CALL    CLS                     ;Clear the screen.
  1186. DISPLAY_COPY:  MOV     SI,OFFSET COPYRIGHT     ;Display copyright in
  1187.                MOV     BL,INVERSE              ; inverse video.
  1188.                CALL    CHAR_ATTRIB
  1189.  
  1190.                MOV     DX,100H                 ;Row 1; column 0.
  1191.                CALL    SET_CURSOR
  1192.                MOV     DX,OFFSET MENU          ;Display menu.
  1193.                CALL    PRINT_STRING
  1194.                CMP     FILE_FLAG,1             ;If filename, display it.
  1195.                JNZ     DISPLAY_MENU
  1196.                CALL    DISP_FILENAME
  1197.  
  1198. DISPLAY_MENU:  MOV     DX,200H                 ;Row 2; column 0.
  1199.                CALL    SET_CURSOR
  1200.                MOV     DX,OFFSET MENU1         ;Display more menu.
  1201.                CALL    PRINT_STRING
  1202.  
  1203.                MOV     SI,OFFSET MENU2
  1204.                MOV     BL,NORMAL
  1205.                MOV     DX,436H
  1206.                CALL    CHAR_ATTRIB
  1207.                MOV     DX,536H
  1208.                CALL    CHAR_ATTRIB
  1209.                MOV     DX,636H
  1210.                CALL    CHAR_ATTRIB
  1211.  
  1212.                MOV     SI,OFFSET CAPTIONS      ;Display three captions.
  1213.                MOV     CX,3
  1214.  
  1215. NEXT_CAPTION:  LODSW
  1216.                MOV     DX,AX                   ;Caption starting cursor pos.
  1217. NEXT_CAP:      LODSB
  1218.                CMP     AL,0                    ;End of string?
  1219.                JZ      END_CAPTION
  1220.                CALL    WRITE_CHAR              ;Write the caption.
  1221.                INC     DH                      ;Next row.
  1222.                JMP     SHORT NEXT_CAP
  1223. END_CAPTION:   LOOP    NEXT_CAPTION            ;Do all three captions.
  1224.  
  1225.                MOV     BL,ATTRIBUTE            ;Background attribute.
  1226.                MOV     SI,OFFSET CURRENT_BOX   ;Display char/ASCII box.
  1227.                MOV     DX,BOX_TOP              ;Starting position.
  1228.                MOV     BP,3                    ;Three rows.
  1229. NEXT_BOX:      MOV     CX,13                   ;13 characters/row.
  1230. NEXT_BOX_CHAR: LODSB
  1231.                CALL    WRITE_CHAR
  1232.                INC     DL                      ;Next column.
  1233.                LOOP    NEXT_BOX_CHAR
  1234.                MOV     DL,LOW BOX_TOP          ;Starting column.
  1235.                INC     DH                      ;Next row.
  1236.                DEC     BP
  1237.                JNZ     NEXT_BOX
  1238.  
  1239.                MOV     DX,CHAR_TOP             ;Display character set.
  1240.                XOR     AL,AL                   ;Start with ASCII zero.
  1241. NEXT_SET:      MOV     CX,16                   ;16 bytes/row.
  1242. NEXT_BYTE:     CALL    WRITE_CHAR
  1243.                INC     AL                      ;Next character.
  1244.                JZ      SETUP_END
  1245.                INC     DL                      ;Next row.
  1246.                LOOP    NEXT_BYTE
  1247.                MOV     DL,LOW CHAR_TOP         ;Starting column.
  1248.                INC     DH
  1249.                JMP     NEXT_SET
  1250.  
  1251. SETUP_END:     CALL    DISPLAY_FONT            ;Display the edit and template.
  1252.                CALL    UPDATE_CURSOR           ;Display the cursor.
  1253.                RET
  1254.  
  1255. ;**************** FONTLOADER ****************;
  1256. ; This is the code to load the font and      ;
  1257. ; is followed by the edit and template font  ;
  1258. ;********************************************;
  1259.  
  1260. LOADER         LABEL   BYTE
  1261. LOADER_OFFSET  EQU     100H - LOADER
  1262.  
  1263.                JMP     BEGINNING
  1264.  
  1265. ;              DATA AREA
  1266. ;              ---------
  1267.                DB      CR,SPACE,SPACE,SPACE,CR,LF
  1268.  
  1269. PROGRAMMER2    DB      " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
  1270. SIGNATURE_LEN  EQU     $ - PROGRAMMER2
  1271.  
  1272. CRT_MODE       DB      ?
  1273. EDIT_CURSOR    DW      102H
  1274. CHAR_CURSOR    DW      401H
  1275. EDIT_CHAR      DB      65
  1276. POINTS         DW      ?
  1277. EDIT_FLAG      DB      1
  1278.  
  1279. ;              CODE AREA
  1280. ;              ---------
  1281.  
  1282. BEGINNING:     MOV     AX,500H                 ;Active page zero
  1283.                INT     10H
  1284.  
  1285.                MOV     AH,0FH                  ;Current video state.
  1286.                INT     10H
  1287.                MOV     DI,OFFSET CRT_MODE + LOADER_OFFSET ;Font CRT_MODE.
  1288.                MOV     AH,[DI]
  1289.                CMP     AL,AH                   ;Same mode?
  1290.                JZ      LOAD_FONT               ;If yes, skip.
  1291.                MOV     AL,AH                   ;Else, change video mode.
  1292.                XOR     AH,AH
  1293.                INT     10H
  1294.  
  1295. LOAD_FONT:     MOV     BP,OFFSET EDIT_FONT + LOADER_OFFSET
  1296.                MOV     DI,OFFSET POINTS + LOADER_OFFSET
  1297.                MOV     BH,[DI]
  1298. USER_LOAD:     MOV     CX,256
  1299.                XOR     DX,DX
  1300.                XOR     BL,BL
  1301.                MOV     AX,1110H                ;User alpha load.
  1302.                INT     10H
  1303.                RET                             ;Terminate.
  1304.  
  1305. ;--------------------------------;
  1306.  
  1307. EVEN
  1308. EDIT_FONT      LABEL   BYTE
  1309. TEMPLATE_FONT  EQU     EDIT_FONT + MAX_POINTS * 256
  1310. LOADER_END     EQU     TEMPLATE_FONT + MAX_POINTS * 256
  1311. LOADER_LENGTH  EQU     LOADER_END - LOADER
  1312.  
  1313. _TEXT          ENDS
  1314.                END     START
  1315.