home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / pibterm / pibt41s3.arc / PIBSCRN2.MOD < prev    next >
Text File  |  1988-01-29  |  58KB  |  1,000 lines

  1. (*----------------------------------------------------------------------*)
  2. (*       Get_Screen_Text_Line --- Extract text from screen image        *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Get_Screen_Text_Line( VAR Text_Line     : AnyStr;
  6.                                     Screen_Line   : INTEGER;
  7.                                     Screen_Column : INTEGER );
  8.  
  9. (*----------------------------------------------------------------------*)
  10. (*                                                                      *)
  11. (*     Procedure:  Get_Screen_Text_Line                                 *)
  12. (*                                                                      *)
  13. (*     Purpose:    Extracts text from current screen image              *)
  14. (*                                                                      *)
  15. (*     Calling Sequence:                                                *)
  16. (*                                                                      *)
  17. (*       Get_Screen_Text_Line( VAR  Text_Line     : AnyStr;             *)
  18. (*                                  Screen_Line   : INTEGER;            *)
  19. (*                                  Screen_Column : INTEGER );          *)
  20. (*                                                                      *)
  21. (*           Text_Line        --- receives text extracted from screen   *)
  22. (*           Screen_Line      --- line on screen to extract             *)
  23. (*           Screen_Column    --- starting column to extract            *)
  24. (*                                                                      *)
  25. (*     Calls:   None                                                    *)
  26. (*                                                                      *)
  27. (*     Remarks:                                                         *)
  28. (*                                                                      *)
  29. (*        Only the text -- not attributes -- from the screen is         *)
  30. (*        returned.                                                     *)
  31. (*                                                                      *)
  32. (*----------------------------------------------------------------------*)
  33.  
  34. VAR
  35.    First_Pos  : INTEGER;
  36.    Len        : INTEGER;
  37.    I          : INTEGER;
  38.    J          : INTEGER;
  39.    Regs       : Registers;
  40.    SaveX      : INTEGER;
  41.    SaveY      : INTEGER;
  42.    C          : BYTE;
  43.    Attr       : BYTE;
  44.    LBuffer    : ARRAY[1..256] OF CHAR;
  45.  
  46. BEGIN  (* Get_Screen_Text_Line *)
  47.  
  48.    Screen_Line   := Max( Min( Screen_Line   , Max_Screen_Line ) , 1 );
  49.    Screen_Column := Max( Min( Screen_Column , Max_Screen_Col  ) , 1 );
  50.  
  51.    Text_Line[0]  := #0;
  52.  
  53.    IF Write_Screen_Memory THEN
  54.       BEGIN
  55.  
  56.          First_Pos     := ( ( Screen_Line - 1 ) * Max_Screen_Col +
  57.                             Screen_Column ) SHL 1 - 1;
  58.          Len           := Max_Screen_Col - Screen_Column + 1;
  59.          J             := 0;
  60.  
  61.          IF TimeSharingActive THEN
  62.             BEGIN
  63.                TurnOffTimeSharing;
  64.                Get_Screen_Address( Actual_Screen );
  65.             END;
  66.  
  67.          IF Wait_For_Retrace THEN
  68.             MoveFromScreen( Actual_Screen^.Screen_Image[ First_Pos ],
  69.                             LBuffer[1], Len )
  70.          ELSE
  71.             Move( Actual_Screen^.Screen_Image[ First_Pos ], LBuffer[1], Len SHL 1 );
  72.  
  73.          I := 1;
  74.  
  75.          FOR J := 1 TO Len DO
  76.             BEGIN
  77.                Text_Line[J] := LBuffer[I];
  78.                I            := I + 2;
  79.             END;
  80.  
  81.          Text_Line[0] := CHR( Len );
  82.  
  83.          IF TimeSharingActive THEN
  84.             TurnOnTimeSharing;
  85.  
  86.       END
  87.    ELSE
  88.       BEGIN                        (* Use BIOS to extract line *)
  89.                                    (* Save current position    *)
  90.          SaveX := WhereX;
  91.          SaveY := WhereY;
  92.          J     := 0;
  93.                                    (* Loop over columns to extract *)
  94.  
  95.          FOR I := Screen_Column TO Max_Screen_Col DO
  96.             BEGIN
  97.                                    (* Pick up character *)
  98.  
  99.                ReadCXY( C, I, Screen_Line, Attr );
  100.  
  101.                                    (* Insert character in result string *)
  102.  
  103.                J            := SUCC( J );
  104.                Text_Line[J] := CHR ( C );
  105.  
  106.             END;
  107.                                    (* Set length of string extracted *)
  108.          Text_Line[0] := CHR( J );
  109.                                    (* Restore previous position   *)
  110.          GoToXY( SaveX, SaveY );
  111.  
  112.       END;
  113.  
  114. END    (* Get_Screen_Text_Line *);
  115.  
  116. (*----------------------------------------------------------------------*)
  117. (*                Print_Screen --- Print current screen image           *)
  118. (*----------------------------------------------------------------------*)
  119.  
  120. PROCEDURE Print_Screen;
  121.  
  122. (*----------------------------------------------------------------------*)
  123. (*                                                                      *)
  124. (*     Procedure:  Print_Screen                                         *)
  125. (*                                                                      *)
  126. (*     Purpose:    Prints current screen image (memory mapped area)     *)
  127. (*                                                                      *)
  128. (*     Calling Sequence:                                                *)
  129. (*                                                                      *)
  130. (*        Print_Screen;                                                 *)
  131. (*                                                                      *)
  132. (*     Calls:   None                                                    *)
  133. (*                                                                      *)
  134. (*     Remarks:                                                         *)
  135. (*                                                                      *)
  136. (*        Only the text from the screen is printed, not the attributes. *)
  137. (*                                                                      *)
  138. (*----------------------------------------------------------------------*)
  139.  
  140. VAR
  141.    I         : INTEGER;
  142.    Text_Line : AnyStr;
  143.  
  144. BEGIN  (* Print_Screen *)
  145.  
  146.    FOR I := 1 TO Max_Screen_Line DO
  147.       BEGIN
  148.          Get_Screen_Text_Line( Text_Line, I, 1 );
  149.          Write_Prt_Str( Text_Line );
  150.          Write_Prt_Str( CRLF_String );
  151.       END;
  152.  
  153. END    (* Print_Screen *);
  154.  
  155. (*----------------------------------------------------------------------*)
  156. (*        Write_Screen --- Write current screen image to file           *)
  157. (*----------------------------------------------------------------------*)
  158.  
  159. PROCEDURE Write_Screen( Fname : AnyStr );
  160.  
  161. (*----------------------------------------------------------------------*)
  162. (*                                                                      *)
  163. (*     Procedure:  Write_Screen                                         *)
  164. (*                                                                      *)
  165. (*     Purpose:    Write current screen image (memory mapped area) to   *)
  166. (*                 a file.                                              *)
  167. (*                                                                      *)
  168. (*     Calling Sequence:                                                *)
  169. (*                                                                      *)
  170. (*        Write_Screen( Fname : AnyStr );                               *)
  171. (*                                                                      *)
  172. (*           Fname --- Name of file to write screen to                  *)
  173. (*                                                                      *)
  174. (*     Calls:   Open_For_Append                                         *)
  175. (*                                                                      *)
  176. (*     Remarks:                                                         *)
  177. (*                                                                      *)
  178. (*        Only the text from the screen is written, not the attributes. *)
  179. (*        If the file already exists, then the new screen is appended   *)
  180. (*        to the end of the file.                                       *)
  181. (*                                                                      *)
  182. (*----------------------------------------------------------------------*)
  183.  
  184. VAR
  185.    I         : INTEGER;
  186.    Text_Line : AnyStr;
  187.    F         : Text_File;
  188.    Cur_Vid   : INTEGER;
  189.  
  190. BEGIN  (* Write_Screen *)
  191.  
  192.                                    (* Don't write screen in graphics mode *)
  193.    Cur_Vid := Current_Video_Mode;
  194.  
  195.    IF ( ( Cur_Vid < MedRes_GraphMode ) OR ( Cur_Vid = Mono_TextMode ) ) THEN
  196.  
  197.                                    (* Open screen file for append -- new  *)
  198.                                    (* screen dump written at end of file. *)
  199.  
  200.       IF Open_For_Append( F , Fname , I ) THEN
  201.          BEGIN
  202.  
  203.             FOR I := 1 TO Max_Screen_Line DO
  204.                BEGIN
  205.                   Get_Screen_Text_Line( Text_Line, I, 1 );
  206.                   WRITELN( F , Text_Line );
  207.                END;
  208.  
  209.             (*!I-*)
  210.             CLOSE( F );
  211.             (*!I+*)
  212.  
  213.          END;
  214.  
  215. END    (* Write_Screen *);
  216.  
  217. (*----------------------------------------------------------------------*)
  218. (*  Write_Graphics_Screen --- Write current screen image to file        *)
  219. (*----------------------------------------------------------------------*)
  220.  
  221. PROCEDURE Write_Graphics_Screen( Fname : AnyStr );
  222.  
  223. (*----------------------------------------------------------------------*)
  224. (*                                                                      *)
  225. (*     Procedure:  Write_Graphics_Screen                                *)
  226. (*                                                                      *)
  227. (*     Purpose:    Write current screen image (memory mapped area) to   *)
  228. (*                 a file.                                              *)
  229. (*                                                                      *)
  230. (*     Calling Sequence:                                                *)
  231. (*                                                                      *)
  232. (*        Write_Graphics_Screen( Fname : AnyStr );                      *)
  233. (*                                                                      *)
  234. (*           Fname --- Name of file to write screen to                  *)
  235. (*                                                                      *)
  236. (*     Calls:   None                                                    *)
  237. (*                                                                      *)
  238. (*     Remarks:                                                         *)
  239. (*                                                                      *)
  240. (*        If the file already exists, then the new screen is appended   *)
  241. (*        to the end of the file.                                       *)
  242. (*                                                                      *)
  243. (*----------------------------------------------------------------------*)
  244.  
  245. VAR
  246.    I           : INTEGER;
  247.    F           : FILE;
  248.    L           : WORD;
  249.    Cur_Vid     : INTEGER;
  250.    Screen_APtr : Screen_Ptr;
  251.  
  252. BEGIN  (* Write_Graphics_Screen *)
  253.                                    (* Get length of graphics screen  *)
  254.    Cur_Vid := Current_Video_Mode;
  255.  
  256.    CASE Cur_Vid OF
  257.       EGA_GraphMode   :  BEGIN
  258.                             L           := EGA_Graphics_Scr_Length;
  259.                             Screen_APtr := PTR( EGA_Screen_Address , 0 )
  260.                          END;
  261.       HiRes_GraphMode :  BEGIN
  262.                             L           := Graphics_Screen_Length;
  263.                             Screen_APtr := PTR( Color_Screen_Address , 0 );
  264.                             IF ( MultiTasker = DoubleDos ) THEN
  265.                                Get_Screen_Address( Screen_APtr );
  266.                          END;
  267.       ELSE               L := 0;
  268.    END (* CASE *);
  269.                                    (* Don't write if not graphics mode *)
  270.    IF ( L = 0 ) THEN EXIT;
  271.                                    (* Assign graphics dump file name *)
  272.    ASSIGN( F , Fname );
  273.    REWRITE( F , L );
  274.                                    (* Turn off timesharing while writing screen *)
  275.  
  276.    IF ( MultiTasker = DoubleDos ) THEN
  277.       TurnOffTimeSharing;
  278.  
  279.    BlockWrite( F, Screen_APtr^, 1 );
  280.  
  281.    CLOSE( F );
  282.      (*!I+*)
  283.                                    (* Restore timesharing mode *)
  284.  
  285.    IF ( MultiTasker = DoubleDos ) THEN
  286.       TurnOnTimeSharing;
  287.  
  288. END    (* Write_Graphics_Screen *);
  289.  
  290. (*----------------------------------------------------------------------*)
  291. (*      Get_Screen_Size --- Get maximum rows, columns of display        *)
  292. (*----------------------------------------------------------------------*)
  293.  
  294. PROCEDURE Get_Screen_Size( VAR Rows: INTEGER; VAR Columns: INTEGER );
  295.  
  296. (*----------------------------------------------------------------------*)
  297. (*                                                                      *)
  298. (*     Procedure:  Get_Screen_Size                                      *)
  299. (*                                                                      *)
  300. (*     Purpose:    Gets maximum rows, columns in current display        *)
  301. (*                                                                      *)
  302. (*     Calling Sequence:                                                *)
  303. (*                                                                      *)
  304. (*        Get_Screen_Size( VAR Rows: INTEGER; VAR Columns: INTEGER );   *)
  305. (*                                                                      *)
  306. (*           Rows    --- # of rows in current display                   *)
  307. (*           Columns --- # of columns in current display                *)
  308. (*                                                                      *)
  309. (*     Calls:   Bios                                                    *)
  310. (*                                                                      *)
  311. (*----------------------------------------------------------------------*)
  312.  
  313. VAR
  314.    Regs : Registers;
  315.    I    : INTEGER;
  316.  
  317. BEGIN  (* Get_Screen_Size *)
  318.                                    (* Set defaults *)
  319.    Regs.AH := $0F;
  320.    INTR( $10 , Regs );
  321.  
  322.    Rows    := 25;
  323.    Columns := MAX( Regs.AH , 80 );
  324.  
  325.                                    (* If EGA installed, check for other *)
  326.                                    (* line values.                      *)
  327.    IF EGA_Present THEN
  328.       BEGIN
  329.                                    (* Get # of rows in current EGA display *)
  330.          Rows := Get_Rows_For_EGA;
  331.  
  332.                                    (* If 25 lines returned, set        *)
  333.                                    (* EGA 25-line mode to avoid cursor *)
  334.                                    (* problems later on, but only if   *)
  335.                                    (* 80 column text mode.             *)
  336.  
  337.          IF ( ( Rows = 25 ) AND ( Columns = 80 ) ) THEN
  338.             BEGIN
  339.                                    (* Load font for 25 line mode *)
  340.                Regs.AX := $1111;
  341.                Regs.BL := 0;
  342.                INTR( $10, Regs );
  343.                                    (* Reset cursor for 25 line mode *)
  344.                Regs.CX := $0607;
  345.                Regs.AH := 01;
  346.                INTR( $10 , Regs );
  347.  
  348.             END;
  349.  
  350.       END;
  351.  
  352. END    (* Get_Screen_Size *);
  353.  
  354. (*----------------------------------------------------------------------*)
  355. (*      Set_EGA_Text_Mode --- Set character set, cursor for EGA         *)
  356. (*----------------------------------------------------------------------*)
  357.  
  358. PROCEDURE Set_EGA_Text_Mode( EGA_Rows : INTEGER );
  359.  
  360. (*----------------------------------------------------------------------*)
  361. (*                                                                      *)
  362. (*     Procedure:  Set_EGA_Text_Mode                                    *)
  363. (*                                                                      *)
  364. (*     Purpose:    Set character set, cursor for EGA/VGA                *)
  365. (*                                                                      *)
  366. (*     Calling Sequence:                                                *)
  367. (*                                                                      *)
  368. (*        Set_EGA_Text_Mode( EGA_Rows : INTEGER );                      *)
  369. (*                                                                      *)
  370. (*           Rows    --- # of rows to set in current display            *)
  371. (*                       25, 35, 43, and 50 lines are supported for     *)
  372. (*                       EGA; 25 and 50 lines for VGA.                  *)
  373. (*                                                                      *)
  374. (*----------------------------------------------------------------------*)
  375.  
  376. (* STRUCTURED *) CONST
  377.    Table_Ofs : POINTER = NIL;
  378.  
  379. BEGIN (* Set_EGA_Text_Mode *)
  380.  
  381.    Table_Ofs := @Sector_Data;
  382.  
  383. INLINE(
  384.   $55/                      {                PUSH    BP}
  385.   $1E/                      {                PUSH    DS                      ; Save registers}
  386.                             {;}
  387.   $FC/                      {                CLD                             ; All strings forward}
  388.                             {;}
  389.   $8B/$86/>EGA_ROWS/        {                MOV     AX,[BP+>EGA_Rows]       ; Pick up # lines}
  390.   $3C/$19/                  {                CMP     BYTE AL,25}
  391.   $74/$16/                  {                JE      Line25}
  392.   $3C/$23/                  {                CMP     BYTE AL,35}
  393.   $74/$3A/                  {                JE      Line35}
  394.   $3C/$2B/                  {                CMP     BYTE AL,43}
  395.   $74/$74/                  {                JE      Line43}
  396.   $3C/$32/                  {                CMP     BYTE AL,50}
  397.   $75/$03/                  {                JNE     Check66}
  398.   $E9/$80/$00/              {                JMP     Line50}
  399.   $3C/$42/                  {Check66:        CMP     BYTE AL,66}
  400.   $75/$03/                  {                JNE     Line25}
  401.   $E9/$BA/$00/              {                JMP     Line66}
  402.                             {;                                               ; Assume 25 lines if bogus}
  403.   $B3/$00/                  {Line25:         MOV     BL,0}
  404.                             {;}
  405.   $F6/$06/>VGA_PRESENT/$01/ {                TEST    BYTE [>VGA_Present],1   ; Check for VGA}
  406.   $74/$17/                  {                JZ      Line25a}
  407.                             {;}
  408.                             {;;              MOV     AX,$1114                ; Load 8 x 16 font for VGA}
  409.                             {;;              INT     $10}
  410.                             {;;              JMP     Exit}
  411.   $B8/$30/$11/              {                MOV     AX,$1130                ; Get pointer to 8 x 16 font}
  412.   $B7/$06/                  {                MOV     BH,6}
  413.   $CD/$10/                  {                INT     $10}
  414.                             {;}
  415.   $B8/$10/$11/              {                MOV     AX,$1110}
  416.   $BB/$00/$10/              {                MOV     BX,$1000}
  417.   $B9/$00/$01/              {                MOV     CX,$0100}
  418.   $31/$D2/                  {                XOR     DX,DX}
  419.                             {;}
  420.   $CD/$10/                  {                INT     $10                     ; Load 8 x 16 font}
  421.   $E9/$D1/$00/              {                JMP     Exit}
  422.                             {;}
  423.   $B8/$11/$11/              {Line25a:        MOV     AX,$1111                ; Load 8 x 14 font for EGA}
  424.   $CD/$10/                  {                INT     $10}
  425.   $E9/$C9/$00/              {                JMP     Exit}
  426.                             {;}
  427.   $F6/$06/>VGA_PRESENT/$01/ {Line35:         TEST    BYTE [>VGA_Present],1   ; Check for VGA}
  428.   $75/$03/                  {                JNZ     Line35a                 ; Do nothing if so}
  429.   $E9/$BF/$00/              {                JMP     Exit}
  430.                             {;}
  431.   $B8/$30/$11/              {Line35a:        MOV     AX,$1130                ; Load 8 x 8 font}
  432.   $B7/$03/                  {                MOV     BH,3}
  433.   $CD/$10/                  {                INT     $10}
  434.   $06/                      {                PUSH    ES}
  435.   $C4/$3E/>TABLE_OFS/       {                LES     DI,[>Table_Ofs]}
  436.   $1F/                      {                POP     DS}
  437.   $89/$EE/                  {                MOV     SI,BP                   ; DS:SI point to font}
  438.   $BB/$00/$01/              {                MOV     BX,$0100                ; Number of chars}
  439.   $29/$C0/                  {                SUB     AX,AX}
  440.                             {;}
  441.   $B9/$04/$00/              {Loop35:         MOV     CX,4                    ; Bytes per char}
  442.   $F3/$A5/                  {                REPZ    MOVSW}
  443.   $AB/                      {                STOSW}
  444.   $4B/                      {                DEC     BX}
  445.   $75/$F7/                  {                JNZ     Loop35}
  446.   $1F/                      {                POP     DS}
  447.   $1E/                      {                PUSH    DS}
  448.   $A1/>TABLE_OFS/           {                MOV     AX,[>Table_Ofs]}
  449.   $89/$C5/                  {                MOV     BP,AX                   ; Points to font}
  450.   $31/$D2/                  {                XOR     DX,DX                   ; Starting char}
  451.   $B9/$00/$01/              {                MOV     CX,$0100                ; Number of chars}
  452.   $BB/$00/$0A/              {                MOV     BX,$0A00                ; Bytes/char}
  453.   $B8/$10/$11/              {                MOV     AX,$1110                ; Load user font}
  454.   $CD/$10/                  {                INT     $10}
  455.   $E9/$8B/$00/              {                JMP     Exit}
  456.                             {;}
  457.   $F6/$06/>VGA_PRESENT/$01/ {Line43:         TEST    BYTE [>VGA_Present],1   ; Check for VGA}
  458.   $74/$03/                  {                JZ      Line43a                 ; Do nothing if so}
  459.   $E9/$81/$00/              {                JMP     Exit}
  460.                             {;}
  461.   $B8/$12/$11/              {Line43a:        MOV     AX,$1112                ; Load 8 x 8 font}
  462.   $B3/$00/                  {                MOV     BL,0}
  463.   $CD/$10/                  {                INT     $10}
  464.   $EB/$78/                  {                JMP     Short Exit}
  465.                             {;}
  466.   $F6/$06/>VGA_PRESENT/$01/ {Line50:         TEST    BYTE [>VGA_Present],1   ; Check for VGA}
  467.   $74/$09/                  {                JZ      Line50a                 ;}
  468.                             {;}
  469.   $B8/$12/$11/              {                MOV     AX,$1112                ; Load 8 x 8 font}
  470.   $B3/$00/                  {                MOV     BL,0}
  471.   $CD/$10/                  {                INT     $10}
  472.   $EB/$68/                  {                JMP     Short Exit}
  473.                             {;}
  474.   $B8/$30/$11/              {Line50a:        MOV     AX,$1130                ; Load 8 x 8 font}
  475.   $B7/$03/                  {                MOV     BH,3}
  476.   $CD/$10/                  {                INT     $10}
  477.   $06/                      {                PUSH    ES}
  478.   $C4/$3E/>TABLE_OFS/       {                LES     DI,[>Table_Ofs]}
  479.   $1F/                      {                POP     DS}
  480.   $89/$EE/                  {                MOV     SI,BP                   ; DS:SI point to font}
  481.   $BB/$00/$01/              {                MOV     BX,$0100                ; Number of chars}
  482.                             {;}
  483.   $B9/$07/$00/              {Loop50:         MOV     CX,7                    ; Bytes per char}
  484.   $F3/$A4/                  {                REPZ    MOVSB}
  485.   $46/                      {                INC     SI}
  486.   $4B/                      {                DEC     BX}
  487.   $75/$F7/                  {                JNZ     Loop50}
  488.   $1F/                      {                POP     DS}
  489.   $1E/                      {                PUSH    DS}
  490.   $A1/>TABLE_OFS/           {                MOV     AX,[>Table_Ofs]}
  491.   $89/$C5/                  {                MOV     BP,AX                   ; Points to font}
  492.   $31/$D2/                  {                XOR     DX,DX                   ; Starting char}
  493.   $B9/$00/$01/              {                MOV     CX,$0100                ; Number of chars}
  494.   $BB/$00/$07/              {                MOV     BX,$0700                ; Bytes/char, block load}
  495.   $B8/$10/$11/              {                MOV     AX,$1110                ; Load user font}
  496.   $CD/$10/                  {                INT     $10}
  497.   $EB/$37/                  {                JMP     SHORT Exit}
  498.                             {;}
  499.   $F6/$06/>VGA_PRESENT/$01/ {Line66:         TEST    BYTE [>VGA_Present],1   ; Check for VGA}
  500.   $74/$30/                  {                JZ      Exit                    ;}
  501.                             {;}
  502.   $B8/$30/$11/              {                MOV     AX,$1130                ; Load 8 x 8 font}
  503.   $B7/$03/                  {                MOV     BH,3}
  504.   $CD/$10/                  {                INT     $10}
  505.   $06/                      {                PUSH    ES}
  506.   $C4/$3E/>TABLE_OFS/       {                LES     DI,[>Table_Ofs]}
  507.   $1F/                      {                POP     DS}
  508.   $89/$EE/                  {                MOV     SI,BP                   ; DS:SI point to font}
  509.   $BB/$00/$01/              {                MOV     BX,$0100                ; Number of chars}
  510.                             {;}
  511.   $B9/$06/$00/              {Loop66:         MOV     CX,6                    ; Bytes per char}
  512.   $F3/$A4/                  {                REPZ    MOVSB}
  513.   $46/                      {                INC     SI}
  514.   $46/                      {                INC     SI}
  515.   $4B/                      {                DEC     BX}
  516.   $75/$F6/                  {                JNZ     Loop66}
  517.   $1F/                      {                POP     DS}
  518.   $1E/                      {                PUSH    DS}
  519.   $A1/>TABLE_OFS/           {                MOV     AX,[>Table_Ofs]}
  520.   $89/$C5/                  {                MOV     BP,AX                   ; Points to font}
  521.   $31/$D2/                  {                XOR     DX,DX                   ; Starting char}
  522.   $B9/$00/$01/              {                MOV     CX,$0100                ; Number of chars}
  523.   $BB/$00/$06/              {                MOV     BX,$0600                ; Bytes/char, block load}
  524.   $B8/$10/$11/              {                MOV     AX,$1110                ; Load user font}
  525.   $CD/$10/                  {                INT     $10}
  526.                             {;}
  527.   $1F/                      {Exit:           POP     DS}
  528.   $5D);                     {                POP     BP}
  529.  
  530.                                    (* Remember if 8x8 font loaded *)
  531.  
  532.    Font8x8Loaded := ( EGA_Rows = 35 ) OR
  533.                     ( EGA_Rows = 43 ) OR
  534.                     ( EGA_Rows = 50 ) OR
  535.                     ( EGA_Rows = 66 );
  536.  
  537.                                    (* Make sure cursor is OK *)
  538.    CursorOn;
  539.  
  540. END   (* Set_EGA_Text_Mode *);
  541.  
  542. (*----------------------------------------------------------------------*)
  543. (*          WriteSXY --- Write text string to specified row/column      *)
  544. (*----------------------------------------------------------------------*)
  545.  
  546. PROCEDURE WriteSXY( S: AnyStr; X: INTEGER; Y: INTEGER; Color: INTEGER );
  547.  
  548. (*----------------------------------------------------------------------*)
  549. (*                                                                      *)
  550. (*     Procedure:  WriteSXY                                             *)
  551. (*                                                                      *)
  552. (*     Purpose:    Writes text string at specified row and column       *)
  553. (*                 position on screen.                                  *)
  554. (*                                                                      *)
  555. (*     Calling Sequence:                                                *)
  556. (*                                                                      *)
  557. (*        WriteSXY( S: AnyStr; X: INTEGER; Y: INTEGER; Color: INTEGER );*)
  558. (*                                                                      *)
  559. (*           S      --- String to be written                            *)
  560. (*           X      --- Column position to write string                 *)
  561. (*           Y      --- Column position to write string                 *)
  562. (*           Color  --- Color in which to write string                  *)
  563. (*                                                                      *)
  564. (*     Calls:   None                                                    *)
  565. (*                                                                      *)
  566. (*----------------------------------------------------------------------*)
  567.  
  568. BEGIN (* WriteSXY *)
  569.                                    (* Freeze screen for DoubleDos *)
  570.  
  571.    IF ( MultiTasker = DoubleDos ) THEN
  572.       BEGIN
  573.          TurnOffTimeSharing;
  574.          Get_Screen_Address( DesqView_Screen );
  575.       END;
  576.  
  577. INLINE(
  578.   $1E/                              {         PUSH  DS                            ;Save data segment register}
  579.                                     {;}
  580.                                     {;  Check if we're using BIOS.}
  581.                                     {;}
  582.   $F6/$06/>WRITE_SCREEN_MEMORY/$01/ {         TEST  BYTE [>Write_Screen_Memory],1 ;Direct screen write?}
  583.   $74/$54/                          {         JZ    Bios                          ;No -- go use BIOS}
  584.                                     {;}
  585.                                     {;  Set up for direct screen write.}
  586.                                     {;  Get row position and column positions, and offset in screen buffer.}
  587.                                     {;}
  588.   $C4/$3E/>DESQVIEW_SCREEN/         {         LES   DI,[>DesqView_Screen]         ;Get base address of screen}
  589.   $8B/$4E/<Y/                       {         MOV   CX,[BP+<Y]                    ;CX = Row}
  590.   $49/                              {         DEC   CX                            ;Row to 0..Max_Screen_Line-1 range}
  591.   $A1/>MAX_SCREEN_COL/              {         MOV   AX,[>Max_Screen_Col]          ;Physical screen width}
  592.   $F7/$E1/                          {         MUL   CX                            ;Row * Max_Screen_Col}
  593.   $8B/$5E/<X/                       {         MOV   BX,[BP+<X]                    ;BX = Column}
  594.   $4B/                              {         DEC   BX                            ;Col to 0..Max_Screen_Col-1 range}
  595.   $01/$D8/                          {         ADD   AX,BX                         ;AX = (Row * Max_Screen_Col) + Col}
  596.   $D1/$E0/                          {         SHL   AX,1                          ;Account for attribute bytes}
  597.   $89/$FB/                          {         MOV   BX,DI                         ;Get base offset of screen}
  598.   $01/$C3/                          {         ADD   BX,AX                         ;Add computed offset}
  599.   $89/$DF/                          {         MOV   DI,BX                         ;Move result into DI}
  600.   $A0/>WAIT_FOR_RETRACE/            {         MOV   AL,[<Wait_For_Retrace]        ;Grab this before changing DS}
  601.   $16/                              {         PUSH  SS}
  602.   $1F/                              {         POP   DS}
  603.   $8D/$B6/>S/                       {         LEA   SI,[BP+>S]                    ;DS:SI will point to S[0]}
  604.   $31/$C9/                          {         XOR   CX,CX                         ;Clear CX}
  605.   $8A/$0C/                          {         MOV   CL,[SI]                       ;CL = Length(S)}
  606.   $E3/$27/                          {         JCXZ  Exit1                         ;If string empty, Exit}
  607.   $46/                              {         INC   SI                            ;DS:SI points to S[1]}
  608.   $8A/$66/<COLOR/                   {         MOV   AH,[BP+<Color]                ;AH = Attribute}
  609.   $FC/                              {         CLD                                 ;Set direction to forward}
  610.   $A8/$01/                          {         TEST  AL,1                          ;If we don't wait for retrace, ...}
  611.   $74/$1A/                          {         JZ    Mono                          ; use "Mono" routine}
  612.                                     {;}
  613.                                     {;  Color routine (used only when Wait_For_Retrace is True) **}
  614.                                     {;}
  615.   $BA/>CRT_STATUS/                  {         MOV   DX,>CRT_Status                ;Point DX to CGA status port}
  616.   $AC/                              {GetNext: LODSB                               ;Load next character into AL}
  617.                                     {                                             ; AH already has Attr}
  618.   $89/$C3/                          {         MOV   BX,AX                         ;Store video word in BX}
  619.                                     {;}
  620.   $EC/                              {WaitNoH: IN    AL,DX                         ;Get 6845 status}
  621.   $A8/$01/                          {         TEST  AL,1                          ;Wait for horizontal}
  622.   $75/$FB/                          {         JNZ   WaitNoH                       ; retrace to finish}
  623.                                     {;}
  624.   $FA/                              {         CLI                                 ;Turn off interrupts}
  625.   $EC/                              {WaitH:   IN    AL,DX                         ;Get 6845 status again}
  626.   $A8/$01/                          {         TEST  AL,1                          ;Wait for horizontal retrace}
  627.   $74/$FB/                          {         JZ    WaitH                         ; to start}
  628.                                     {;}
  629.   $89/$D8/                          {Store:   MOV   AX,BX                         ;Restore attribute}
  630.   $AB/                              {         STOSW                               ; and then to screen}
  631.   $FB/                              {         STI                                 ;Allow interrupts}
  632.   $E2/$EC/                          {         LOOP  GetNext                       ;Get next character}
  633.   $E9/$62/$00/                      {         JMP   Exit                          ;Done}
  634.                                     {;}
  635.                                     {;  Mono routine (used whenever Wait_For_Retrace is False) **}
  636.                                     {;}
  637.   $AC/                              {Mono:    LODSB                               ;Load next character into AL}
  638.                                     {                                             ; AH already has Attr}
  639.   $AB/                              {         STOSW                               ;Move video word into place}
  640.   $E2/$FC/                          {         LOOP  Mono                          ;Get next character}
  641.                                     {;}
  642.   $E9/$5B/$00/                      {Exit1:   JMP   Exit                          ;Done}
  643.                                     {;}
  644.                                     {;  Use BIOS to display string (if Write_Screen is False) **}
  645.                                     {;}
  646.   $B4/$03/                          {Bios:    MOV   AH,3                          ;BIOS get cursor position}
  647.   $B7/$00/                          {         MOV   BH,0}
  648.   $55/                              {         PUSH  BP}
  649.   $CD/$10/                          {         INT   $10                           ;Get current cursor position}
  650.   $5D/                              {         POP   BP}
  651.   $52/                              {         PUSH  DX                            ;Save current cursor position}
  652.                                     {;}
  653.   $8A/$76/<Y/                       {         MOV   DH,[BP+<Y]                    ;Get starting row}
  654.   $FE/$CE/                          {         DEC   DH                            ;Drop by one for BIOS}
  655.   $8A/$56/<X/                       {         MOV   DL,[BP+<X]                    ;Get starting column}
  656.   $FE/$CA/                          {         DEC   DL                            ;Drop for indexing}
  657.   $FE/$CA/                          {         DEC   DL                            ;}
  658.   $16/                              {         PUSH  SS}
  659.   $1F/                              {         POP   DS}
  660.   $8D/$B6/>S/                       {         LEA   SI,[BP+>S]                    ;DS:SI will point to S[0]}
  661.   $31/$C9/                          {         XOR   CX,CX                         ;Clear out CX}
  662.   $8A/$0C/                          {         MOV   CL,[SI]                       ;CL = Length(S)}
  663.   $E3/$31/                          {         JCXZ  Bios2                         ;If string empty, Exit}
  664.   $46/                              {         INC   SI                            ;DS:SI points to S[1]}
  665.   $52/                              {         PUSH  DX                            ;Save X and Y}
  666.   $1E/                              {         PUSH  DS                            ;Save string address}
  667.   $56/                              {         PUSH  SI                            ;}
  668.   $FC/                              {         CLD                                 ;Forward direction}
  669.                                     {;}
  670.   $B4/$02/                          {Bios1:   MOV   AH,2                          ;BIOS Position cursor}
  671.   $B7/$00/                          {         MOV   BH,0                          ;Page zero}
  672.   $5E/                              {         POP   SI                            ;Get S address}
  673.   $1F/                              {         POP   DS                            ;}
  674.   $5A/                              {         POP   DX                            ;X and Y}
  675.   $FE/$C2/                          {         INC   DL                            ;X + 1}
  676.   $52/                              {         PUSH  DX                            ;Save X and Y}
  677.   $1E/                              {         PUSH  DS                            ;Save strin address}
  678.   $56/                              {         PUSH  SI}
  679.   $51/                              {         PUSH  CX                            ;Push length}
  680.   $55/                              {         PUSH  BP}
  681.   $CD/$10/                          {         INT   $10                           ;Call BIOS to move to (X,Y)}
  682.   $5D/                              {         POP   BP}
  683.   $59/                              {         POP   CX                            ;Get back length}
  684.   $5E/                              {         POP   SI                            ;Get String address}
  685.   $1F/                              {         POP   DS                            ;}
  686.   $AC/                              {         LODSB                               ;Next character into AL}
  687.   $1E/                              {         PUSH  DS                            ;Save String address}
  688.   $56/                              {         PUSH  SI                            ;}
  689.   $51/                              {         PUSH  CX                            ;Length left to do}
  690.   $55/                              {         PUSH  BP}
  691.   $B4/$09/                          {         MOV   AH,9                          ;BIOS Display character}
  692.   $B7/$00/                          {         MOV   BH,0                          ;Display page zero}
  693.   $8A/$5E/<COLOR/                   {         MOV   BL,[BP+<Color]                ;BL = Attribute}
  694.   $B9/$01/$00/                      {         MOV   CX,1                          ;One character}
  695.   $CD/$10/                          {         INT   $10                           ;Call BIOS}
  696.   $5D/                              {         POP   BP}
  697.   $59/                              {         POP   CX                            ;Get back length}
  698.   $E2/$D7/                          {         LOOP  Bios1}
  699.                                     {;                                            ;Remove stuff left on stack}
  700.   $5E/                              {         POP   SI}
  701.   $1F/                              {         POP   DS}
  702.   $5A/                              {         POP   DX}
  703.                                     {;}
  704.   $5A/                              {Bios2:   POP   DX                            ;Restore previous cursor position}
  705.   $B7/$00/                          {         MOV   BH,0}
  706.   $B4/$02/                          {         MOV   AH,2                          ;BIOS set cursor position}
  707.   $55/                              {         PUSH  BP}
  708.   $CD/$10/                          {         INT   $10}
  709.   $5D/                              {         POP   BP}
  710.                                     {;}
  711.   $1F);                             {Exit:    POP   DS                            ;Restore DS}
  712.  
  713.                                    (* Unfreeze screen in DoubleDos *)
  714.  
  715.    IF ( MultiTasker = DoubleDos ) THEN
  716.       TurnOnTimeSharing
  717.                                    (* Synchronize screen for TopView *)
  718.  
  719.    ELSE IF ( MultiTasker = TopView ) THEN
  720.       IF Write_Screen_Memory THEN
  721.          Sync_Screen( PRED( ( PRED( Y ) * Max_Screen_Col + X ) SHL 1 ) , LENGTH( S ) );
  722.  
  723. END   (* WriteSXY *);
  724.  
  725. (*----------------------------------------------------------------------*)
  726. (*       Set_Graphics_Colors --- Set colors for graphics mode           *)
  727. (*----------------------------------------------------------------------*)
  728.  
  729. PROCEDURE Set_Graphics_Colors( EGA_On : BOOLEAN;
  730.                                GMode  : INTEGER;
  731.                                FG     : INTEGER;
  732.                                BG     : INTEGER );
  733.  
  734. (*----------------------------------------------------------------------*)
  735. (*                                                                      *)
  736. (*     Procedure:  Set_Graphics_Colors                                  *)
  737. (*                                                                      *)
  738. (*     Purpose:    Sets colors for graphics modes                       *)
  739. (*                                                                      *)
  740. (*     Calling Sequence:                                                *)
  741. (*                                                                      *)
  742. (*        Set_Graphics_Colors( EGA_On: BOOLEAN; GMode: INTEGER;         *)
  743. (*                             FG    : INTEGER; BG   : INTEGER );       *)
  744. (*                                                                      *)
  745. (*           EGA_On --- TRUE if EGA installed                           *)
  746. (*           GMode  --- Graphics mode to set                            *)
  747. (*           FG     --- Foreground color                                *)
  748. (*           BG     --- Background color                                *)
  749. (*                                                                      *)
  750. (*----------------------------------------------------------------------*)
  751.  
  752. VAR
  753.    Regs: Registers;
  754.  
  755. BEGIN (* Set_Graphics_Colors *)
  756.  
  757.                                    (* Request 640x200 graphics mode    *)
  758.    IF EGA_On THEN
  759.       BEGIN (* Set up EGA mode *)
  760.  
  761.          WITH Regs DO
  762.             BEGIN
  763.                Regs.Ah := 0;
  764.                Regs.Al := GMode;
  765.                INTR( $10, Regs );
  766.             END;
  767.                                    (* Set graphics border color *)
  768.         WITH Regs DO
  769.            BEGIN
  770.               Regs.Ah := 16;
  771.               Regs.Al := 01;
  772.               Regs.Bh := BG;
  773.               Regs.Bl := 0;
  774.               INTR( $10, Regs );
  775.           END;
  776.                                    (* Set graphics foreground color *)
  777.         WITH Regs DO
  778.            BEGIN
  779.               Regs.Ah := 16;
  780.               Regs.Al := 00;
  781.               Regs.Bh := FG;
  782.               Regs.Bl := 1;
  783.               INTR( $10, Regs );
  784.           END;
  785.                                    (* Set graphics background color *)
  786.         WITH Regs DO
  787.            BEGIN
  788.               Regs.Ah := 16;
  789.               Regs.Al := 00;
  790.               Regs.Bh := BG;
  791.               Regs.Bl := 0;
  792.               INTR( $10, Regs );
  793.            END;
  794.                                    (* Set foreground intensity *)
  795.  
  796.         IF ( FG > 7 ) THEN
  797.            WITH Regs DO
  798.               BEGIN
  799.                  Regs.Ah := 16;
  800.                  Regs.Al := 03;
  801.                  Regs.Bh := FG;
  802.                  Regs.Bl := 0;
  803.                  INTR( $10, Regs );
  804.               END;
  805.  
  806.       END   (* Set up EGA mode *)
  807.    ELSE
  808.       BEGIN (* Set up CGA mode *)
  809.  
  810.          WITH Regs DO
  811.             BEGIN
  812.                Regs.Ah := 0;
  813.                Regs.Al := GMode;
  814.                INTR( $10, Regs );
  815.             END;
  816.  
  817.          WITH Regs DO
  818.             BEGIN
  819.                Regs.Ah := 11;
  820.                Regs.BH := 0;
  821.                Regs.BL := FG;
  822.                INTR( $10, Regs );
  823.             END;
  824.  
  825.       END   (* Set up CGA mode *);
  826.  
  827. END   (* Set_Graphics_Colors *);
  828.  
  829. (*----------------------------------------------------------------------*)
  830. (*   WriteLXY --- Write screen line string to specified row/column      *)
  831. (*----------------------------------------------------------------------*)
  832.  
  833. PROCEDURE WriteLXY( VAR S;  X: INTEGER; Y: INTEGER; Len : INTEGER );
  834.  
  835. (*----------------------------------------------------------------------*)
  836. (*                                                                      *)
  837. (*     Procedure:  WriteLXY                                             *)
  838. (*                                                                      *)
  839. (*     Purpose:    Writes screen line at specified row and column       *)
  840. (*                 position on screen.                                  *)
  841. (*                                                                      *)
  842. (*     Calling Sequence:                                                *)
  843. (*                                                                      *)
  844. (*        WriteLXY( VAR S: My_Line_Type; X: INTEGER; Y: INTEGER;        *)
  845. (*                  LEN : INTEGER );                                    *)
  846. (*                                                                      *)
  847. (*           S      --- Screen line to be written                       *)
  848. (*                      ( S[I] = char, S[I+1] = attribute )             *)
  849. (*           X      --- Column position to write string                 *)
  850. (*           Y      --- Column position to write string                 *)
  851. (*           Len    --- # of characters to write                        *)
  852. (*                                                                      *)
  853. (*     Calls:   None                                                    *)
  854. (*                                                                      *)
  855. (*----------------------------------------------------------------------*)
  856.  
  857. BEGIN (* WriteLXY *)
  858.                                    (* Freeze screen for DoubleDos *)
  859.  
  860.    IF ( MultiTasker = DoubleDos ) THEN
  861.       BEGIN
  862.          TurnOffTimeSharing;
  863.          Get_Screen_Address( DesqView_Screen );
  864.       END;
  865.  
  866. INLINE(
  867.   $1E/                              {         PUSH  DS                              ;Save DS}
  868.                                     {;}
  869.                                     {;  Check if we're going to use BIOS}
  870.                                     {;}
  871.   $F6/$06/>WRITE_SCREEN_MEMORY/$01/ {         TEST  BYTE [<Write_Screen_Memory],1   ;See if we're to use BIOS}
  872.   $74/$4D/                          {         JZ    BIOS                            ;Yes -- skip to BIOS code}
  873.                                     {;}
  874.                                     {;  Set up for direct screen write.}
  875.                                     {;  Get row position and column positions, and offset in screen buffer.}
  876.                                     {;}
  877.   $C4/$3E/>DESQVIEW_SCREEN/         {         LES   DI,[>DesqView_Screen]         ;Get base address of screen}
  878.   $8B/$4E/<Y/                       {         MOV   CX,[BP+<Y]                    ;CX = Row}
  879.   $49/                              {         DEC   CX                            ;Row to 0..Max_Screen_Line-1 range}
  880.   $A1/>MAX_SCREEN_COL/              {         MOV   AX,[>Max_Screen_Col]          ;Physical screen width}
  881.   $F7/$E1/                          {         MUL   CX                            ;Row * Max_Screen_Col}
  882.   $8B/$5E/<X/                       {         MOV   BX,[BP+<X]                    ;BX = Column}
  883.   $4B/                              {         DEC   BX                            ;Col to 0..Max_Screen_Col-1 range}
  884.   $01/$D8/                          {         ADD   AX,BX                         ;AX = (Row * Max_Screen_Col) + Col}
  885.   $D1/$E0/                          {         SHL   AX,1                          ;Account for attribute bytes}
  886.   $89/$FB/                          {         MOV   BX,DI                         ;Get base offset of screen}
  887.   $01/$C3/                          {         ADD   BX,AX                         ;Add computed offset}
  888.   $89/$DF/                          {         MOV   DI,BX                         ;Move result into DI}
  889.   $A0/>WAIT_FOR_RETRACE/            {         MOV   AL,[<Wait_For_Retrace]        ;Grab this before changing DS}
  890.   $C5/$76/<S/                       {         LDS   SI,[BP+<S]                    ;DS:SI will point to S}
  891.   $8B/$8E/>LEN/                     {         MOV   CX,[BP+>Len]                  ;CL = Length(S)}
  892.   $E3/$7B/                          {         JCXZ  Exit                          ;If string empty, Exit}
  893.   $FC/                              {         CLD                                 ;Set direction to forward}
  894.   $D0/$D8/                          {         RCR   AL,1                          ;If we don't wait for retrace, ...}
  895.   $73/$1A/                          {         JNC   Mono                          ; use "Mono" routine}
  896.                                     {;}
  897.                                     {;  Color routine (used only when Wait_Retrace is True) **}
  898.                                     {;}
  899.   $BA/>CRT_STATUS/                  {         MOV   DX,>CRT_Status                ;Point DX to CGA status port}
  900.   $AD/                              {GetNext: LODSW                               ;Load next char/attrib to AX}
  901.   $89/$C3/                          {         MOV   BX,AX                         ;Store video word in BX}
  902.                                     {;}
  903.   $EC/                              {WaitNoH: IN    AL,DX                         ;Get 6845 status}
  904.   $A8/$01/                          {         TEST  AL,1                          ;Wait for horizontal}
  905.   $75/$FB/                          {         JNZ   WaitNoH                       ; retrace to finish}
  906.                                     {;}
  907.   $FA/                              {         CLI                                 ;Turn off interrupts}
  908.   $EC/                              {WaitH:   IN    AL,DX                         ;Get 6845 status again}
  909.   $A8/$01/                          {         TEST  AL,1                          ;Wait for horizontal retrace}
  910.   $74/$FB/                          {         JZ    WaitH                         ; to start}
  911.                                     {;}
  912.   $89/$D8/                          {Store:   MOV   AX,BX                         ;Restore attribute}
  913.   $AB/                              {         STOSW                               ; and then to screen}
  914.   $FB/                              {         STI                                 ;Allow interrupts}
  915.   $E2/$EC/                          {         LOOP  GetNext                       ;Get next character}
  916.   $E9/$5C/$00/                      {         JMP   Exit                          ;Done}
  917.                                     {;}
  918.                                     {;  Mono routine (used whenever Wait_Retrace is False) **}
  919.                                     {;}
  920.   $AD/                              {Mono:    LODSW                        ;Load next char/attribute into AX}
  921.   $AB/                              {         STOSW                        ;Move video word into place}
  922.   $E2/$FC/                          {         LOOP  Mono                   ;Get next character}
  923.   $E9/$55/$00/                      {         JMP   Exit                   ;Done}
  924.                                     {;}
  925.                                     {;  Use BIOS to display string (if Write_Screen is False) **}
  926.                                     {;}
  927.   $B4/$03/                          {Bios:    MOV   AH,3                   ;Get current cursor position}
  928.   $B7/$00/                          {         MOV   BH,0}
  929.   $55/                              {         PUSH  BP}
  930.   $CD/$10/                          {         INT   $10}
  931.   $5D/                              {         POP   BP}
  932.   $52/                              {         PUSH  DX                     ;Save current cursor position}
  933.   $8A/$76/<Y/                       {         MOV   DH,[BP+<Y]             ;Get starting row}
  934.   $FE/$CE/                          {         DEC   DH                     ;Drop by one for BIOS}
  935.   $8A/$56/<X/                       {         MOV   DL,[BP+<X]             ;Get starting column}
  936.   $FE/$CA/                          {         DEC   DL                     ;Drop for indexing}
  937.   $FE/$CA/                          {         DEC   DL                     ;}
  938.   $C5/$76/<S/                       {         LDS   SI,[BP+<S]             ;DS:SI will point to S[1]}
  939.   $8B/$4E/<LEN/                     {         MOV   CX,[BP+<Len]           ;CX = Length(S)}
  940.   $E3/$2F/                          {         JCXZ  Bios2                  ;If string empty, Exit}
  941.   $52/                              {         PUSH  DX                     ;Save X and Y}
  942.   $1E/                              {         PUSH  DS                     ;Save string address}
  943.   $56/                              {         PUSH  SI                     ;}
  944.   $FC/                              {         CLD                          ;Forward direction}
  945.                                     {;}
  946.   $B4/$02/                          {Bios1:   MOV   AH,2                   ;BIOS Position cursor}
  947.   $B7/$00/                          {         MOV   BH,0                   ;Page zero}
  948.   $5E/                              {         POP   SI                     ;Get S address}
  949.   $1F/                              {         POP   DS                     ;}
  950.   $5A/                              {         POP   DX                     ;X and Y}
  951.   $FE/$C2/                          {         INC   DL                     ;X + 1}
  952.   $52/                              {         PUSH  DX                     ;Save X and Y}
  953.   $1E/                              {         PUSH  DS                     ;Save string address}
  954.   $56/                              {         PUSH  SI}
  955.   $51/                              {         PUSH  CX                     ;Push length}
  956.   $55/                              {         PUSH  BP}
  957.   $CD/$10/                          {         INT   $10                    ;Call BIOS to move to (X,Y)}
  958.   $5D/                              {         POP   BP}
  959.   $59/                              {         POP   CX                     ;Get back length}
  960.   $5E/                              {         POP   SI                     ;Get String address}
  961.   $1F/                              {         POP   DS                     ;}
  962.   $AD/                              {         LODSW                        ;Next char/attribute into AX}
  963.   $1E/                              {         PUSH  DS                     ;Save String address}
  964.   $56/                              {         PUSH  SI                     ;}
  965.   $51/                              {         PUSH  CX                     ;Length left to do}
  966.   $88/$E3/                          {         MOV   BL,AH                  ;BL = Attribute}
  967.   $B4/$09/                          {         MOV   AH,9                   ;BIOS Display character}
  968.   $B7/$00/                          {         MOV   BH,0                   ;Display page zero}
  969.   $B9/$01/$00/                      {         MOV   CX,1                   ;One character}
  970.   $55/                              {         PUSH  BP}
  971.   $CD/$10/                          {         INT   $10                    ;Call BIOS}
  972.   $5D/                              {         POP   BP}
  973.   $59/                              {         POP   CX                     ;Get back length}
  974.   $E2/$D8/                          {         LOOP  Bios1}
  975.                                     {;                                     ;Remove stuff left on stack}
  976.   $5E/                              {         POP   SI}
  977.   $1F/                              {         POP   DS}
  978.   $5A/                              {         POP   DX}
  979.                                     {;}
  980.   $5A/                              {Bios2:   POP   DX                     ;Restore previous cursor position}
  981.   $B7/$00/                          {         MOV   BH,0}
  982.   $B4/$02/                          {         MOV   AH,2}
  983.   $55/                              {         PUSH  BP}
  984.   $CD/$10/                          {         INT   $10}
  985.   $5D/                              {         POP   BP}
  986.                                     {;}
  987.   $1F);                             {Exit:    POP   DS                     ;Restore DS}
  988.  
  989.                                    (* Unfreeze screen in DoubleDos *)
  990.  
  991.    IF ( MultiTasker = DoubleDos ) THEN
  992.       TurnOnTimeSharing
  993.                                    (* Synchronize screen for TopView *)
  994.  
  995.    ELSE IF ( MultiTasker = TopView ) THEN
  996.       IF Write_Screen_Memory THEN
  997.          Sync_Screen( ( ( Y - 1 ) * Max_Screen_Col + X ) SHL 1 - 1 , Len );
  998.  
  999. END   (* WriteLXY *);
  1000.