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

  1. (*----------------------------------------------------------------------*)
  2. (*       PIBSCREN.PAS --- Screen Handling Routines for Turbo Pascal     *)
  3. (*----------------------------------------------------------------------*)
  4. (*                                                                      *)
  5. (*  Author:  Philip R. Burns                                            *)
  6. (*                                                                      *)
  7. (*  Date:    Version 1.0: January, 1985 (Part of PibMenus)              *)
  8. (*           Version 1.1: March, 1985   (Part of PibMenus)              *)
  9. (*           Version 1.2: May, 1985     (Part of PibMenus)              *)
  10. (*           Version 2.0: June, 1985    (Split from PibMenus)           *)
  11. (*           Version 3.0: October, 1985                                 *)
  12. (*           Version 3.1: October, 1985                                 *)
  13. (*           Version 3.2: November, 1985                                *)
  14. (*           Version 4.0: March, 1987                                   *)
  15. (*                                                                      *)
  16. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  17. (*           Note:  I have checked these on Zenith 151s under           *)
  18. (*                  MSDOS 2.1 and IBM PCs under PCDOS 2.0.              *)
  19. (*                  Version 4.0 provides automatic support for          *)
  20. (*                  SoftLogic's DoubleDos and TopView-like systems.     *)
  21. (*                                                                      *)
  22. (*  History: These routines provide a simple windowing facility for     *)
  23. (*           Turbo Pascal as well as routines for direct access to the  *)
  24. (*           screen memory area.                                        *)
  25. (*                                                                      *)
  26. (*           The windowing facility provides windows similar to those   *)
  27. (*           implemented in QMODEM by John Friel III.                   *)
  28. (*                                                                      *)
  29. (*           Version 1.0 of these routines formed part of the           *)
  30. (*           PIBMENUS.PAS include file.  These routines were split off  *)
  31. (*           into a separate PIBSCREN.PAS file at version 2.0.          *)
  32. (*                                                                      *)
  33. (*           Starting with version 3.2, PibScren uses a (hopefully)     *)
  34. (*           version-independent method for ascertaining the size       *)
  35. (*           of the current window.  The method relies on the 1-pass    *)
  36. (*           construction of Turbo, so that the standard built-in       *)
  37. (*           procedure WINDOW can be replaced by one defined here, and  *)
  38. (*           the built-in version then referred to by the name          *)
  39. (*           TurboWindow.                                               *)
  40. (*                                                                      *)
  41. (*           Version 4.0 adds DoubleDos, DesqView, and TopView compati- *)
  42. (*           bility.  MS Windows is supported via TopView emulation.    *)
  43. (*           Many thanks to Barry Kasindorf and Gary Saxer for their    *)
  44. (*           assistance with the DesqView interface.                    *)
  45. (*                                                                      *)
  46. (*           Suggestions for improvements or corrections are welcome.   *)
  47. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  48. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  49. (*                                                                      *)
  50. (*           If you use this code in your own programs, please be nice  *)
  51. (*           and give all of us credit.                                 *)
  52. (*                                                                      *)
  53. (*----------------------------------------------------------------------*)
  54. (*                                                                      *)
  55. (*    Note that code for stacked windows is available here.  You may    *)
  56. (*    want to modify this to use compile-time window spaces, or remove  *)
  57. (*    the current push-down stack structure.                            *)
  58. (*                                                                      *)
  59. (*----------------------------------------------------------------------*)
  60.  
  61. (*----------------------------------------------------------------------*)
  62. (*     PibTerm_Window --- PibTerm interface to TP4 WINDOW procedure     *)
  63. (*----------------------------------------------------------------------*)
  64.  
  65. PROCEDURE PibTerm_Window( X1, Y1, X2, Y2 : INTEGER );
  66.  
  67. (*----------------------------------------------------------------------*)
  68. (*                                                                      *)
  69. (*     Procedure:  PibTerm_Window                                       *)
  70. (*                                                                      *)
  71. (*     Purpose:    Redefines built-in Turbo procedure WINDOW so that    *)
  72. (*                 we can keep track of window boundaries.              *)
  73. (*                                                                      *)
  74. (*----------------------------------------------------------------------*)
  75.  
  76. BEGIN (* PibTerm_Window *)
  77.                                    (* Set Turbo's window guys *)
  78.  
  79.    WindMin := PRED( Y1 ) SHL 8 + PRED( X1 );
  80.    WindMax := PRED( Y2 ) SHL 8 + PRED( X2 );
  81.  
  82.                                    (* Save new window coords *)
  83.    Upper_Left_Column  := X1;
  84.    Upper_Left_Row     := Y1;
  85.    Lower_Right_Column := X2;
  86.    Lower_Right_Row    := Y2;
  87.  
  88. END   (* PibTerm_Window *);
  89.  
  90. (*----------------------------------------------------------------------*)
  91. (*                    Set_Text_Mode --- Set text mode                   *)
  92. (*----------------------------------------------------------------------*)
  93.  
  94. PROCEDURE Set_Text_Mode( Text_Mode : INTEGER );
  95.  
  96. BEGIN (* Set_Text_Mode *)
  97.  
  98.    TextMode( Text_Mode );
  99. {
  100.    DirectVideo := Write_Screen_Memory AND ( NOT TimeSharingActive );
  101. }
  102.    DirectVideo := FALSE;
  103.  
  104. END   (* Set_Text_Mode *);
  105.  
  106. (*----------------------------------------------------------------------*)
  107. (*    Color_Screen_Active --- Determine if color or mono screen         *)
  108. (*----------------------------------------------------------------------*)
  109.  
  110. FUNCTION Color_Screen_Active;
  111.  
  112. (*----------------------------------------------------------------------*)
  113. (*                                                                      *)
  114. (*     Function:   Color_Screen_Active                                  *)
  115. (*                                                                      *)
  116. (*     Purpose:    Determines if color or mono screen active            *)
  117. (*                                                                      *)
  118. (*     Calling Sequence:                                                *)
  119. (*                                                                      *)
  120. (*        Color_Active := Color_Screen_Active : BOOLEAN;                *)
  121. (*                                                                      *)
  122. (*           Color_Active --- set to TRUE if the color screen is        *)
  123. (*                            active, FALSE if the mono screen is       *)
  124. (*                            active.                                   *)
  125. (*                                                                      *)
  126. (*     Calls:   INTR                                                    *)
  127. (*                                                                      *)
  128. (*----------------------------------------------------------------------*)
  129.  
  130. VAR
  131.    Regs : Registers;
  132.  
  133. BEGIN  (* Color_Screen_Active *)
  134.  
  135.    Regs.Ax := 15 SHL 8;
  136.  
  137.    INTR( $10 , Regs );
  138.  
  139.    Color_Screen_Active := ( Regs.Al <> 7 );
  140.  
  141. End    (* Color_Screen_Active *);
  142.  
  143. (*----------------------------------------------------------------------*)
  144. (*     Current_Video_Mode --- Determine current video mode setting      *)
  145. (*----------------------------------------------------------------------*)
  146.  
  147. FUNCTION Current_Video_Mode: INTEGER;
  148.  
  149. (*----------------------------------------------------------------------*)
  150. (*                                                                      *)
  151. (*     Function:   Current_Video_Mode                                   *)
  152. (*                                                                      *)
  153. (*     Purpose:    Gets current video mode setting from system          *)
  154. (*                                                                      *)
  155. (*     Calling Sequence:                                                *)
  156. (*                                                                      *)
  157. (*        Current_Mode := Current_Video_Mode : INTEGER;                 *)
  158. (*                                                                      *)
  159. (*           Current_Mode --- set to integer representing current       *)
  160. (*                            video mode inherited from system.         *)
  161. (*                                                                      *)
  162. (*     Calls:   INTR                                                    *)
  163. (*                                                                      *)
  164. (*----------------------------------------------------------------------*)
  165.  
  166. VAR
  167.    Regs : Registers;
  168.  
  169. BEGIN  (* Current_Video_Mode *)
  170.  
  171.    Regs.Ax := 15 SHL 8;
  172.  
  173.    INTR( $10 , Regs );
  174.  
  175.    Current_Video_Mode := Regs.Al;
  176.  
  177. END    (* Current_Video_Mode *);
  178.  
  179. (*----------------------------------------------------------------------*)
  180. (*     EGA_Installed  ---  Test if Enhanced Graphics Adapter installed  *)
  181. (*----------------------------------------------------------------------*)
  182.  
  183. FUNCTION EGA_Installed : BOOLEAN;
  184.  
  185. (*----------------------------------------------------------------------*)
  186. (*                                                                      *)
  187. (*     Function:   EGA_Installed                                        *)
  188. (*                                                                      *)
  189. (*     Purpose:    Checks if Enhanced Graphics Adapter is installed.    *)
  190. (*                                                                      *)
  191. (*     Calling Sequence:                                                *)
  192. (*                                                                      *)
  193. (*        EGA_There := EGA_Installed : BOOLEAN;                         *)
  194. (*                                                                      *)
  195. (*           EGA_There --- TRUE if EGA installed                        *)
  196. (*                                                                      *)
  197. (*     Calls:   INTR                                                    *)
  198. (*                                                                      *)
  199. (*----------------------------------------------------------------------*)
  200.  
  201. VAR
  202.    Regs : Registers;
  203.  
  204. BEGIN  (* EGA_Installed *)
  205.                                    (* Determine if EGA installed       *)
  206.    Regs.AH := $12;
  207.    Regs.BX := $FF10;
  208.    INTR( $10 , Regs );
  209.  
  210.    IF ( Regs.BH = $FF ) THEN       (* EGA not installed *)
  211.       EGA_Installed := FALSE
  212.    ELSE IF ( Regs.CL = 9 ) THEN
  213.       BEGIN (* EGA present with enhanced display *)
  214.          EGA_Installed := TRUE;
  215.       END
  216.    ELSE IF ( Regs.CL = 13 ) THEN
  217.       BEGIN (* EGA present with monochrome display *)
  218.          EGA_Installed := TRUE;
  219.       END
  220.    ELSE (* EGA present but with old color display  *)
  221.       EGA_Installed := FALSE;
  222.  
  223. END    (* EGA_Installed *);
  224.  
  225. (*----------------------------------------------------------------------*)
  226. (*     VGA_Installed  ---  Test if Virtual Graphics Array installed     *)
  227. (*----------------------------------------------------------------------*)
  228.  
  229. FUNCTION VGA_Installed : BOOLEAN;
  230.  
  231. (*----------------------------------------------------------------------*)
  232. (*                                                                      *)
  233. (*     Function:   VGA_Installed                                        *)
  234. (*                                                                      *)
  235. (*     Purpose:    Checks if Virtual Graphics Array is installed.       *)
  236. (*                                                                      *)
  237. (*     Calling Sequence:                                                *)
  238. (*                                                                      *)
  239. (*        VGA_There := VGA_Installed : BOOLEAN;                         *)
  240. (*                                                                      *)
  241. (*           VGA_There --- TRUE if VGA installed                        *)
  242. (*                                                                      *)
  243. (*     Calls:   INTR                                                    *)
  244. (*                                                                      *)
  245. (*----------------------------------------------------------------------*)
  246.  
  247. VAR
  248.    Regs : Registers;
  249.  
  250. BEGIN  (* VGA_Installed *)
  251.  
  252.    Regs.AX := $1A00;
  253.    Regs.BL := 0;
  254.  
  255.    INTR( $10 , Regs );
  256.  
  257.    VGA_Installed := ( Regs.BL = 8 ) OR ( Regs.BL = 7 );
  258.  
  259. END    (* VGA_Installed *);
  260.  
  261. (*----------------------------------------------------------------------*)
  262. (*        Get_Screen_Address --- Get address of current screen          *)
  263. (*----------------------------------------------------------------------*)
  264.  
  265. PROCEDURE Get_Screen_Address( VAR Actual_Screen : Screen_Ptr );
  266.  
  267. (*----------------------------------------------------------------------*)
  268. (*                                                                      *)
  269. (*     Procedure:  Get_Screen_Address                                   *)
  270. (*                                                                      *)
  271. (*     Purpose:    Gets screen address for current type of display      *)
  272. (*                                                                      *)
  273. (*     Calling Sequence:                                                *)
  274. (*                                                                      *)
  275. (*        Get_Screen_Address( VAR Actual_Screen : Screen_Ptr );         *)
  276. (*                                                                      *)
  277. (*           Actual_Screen --- pointer whose value receives the         *)
  278. (*                             current screen address.                  *)
  279. (*                                                                      *)
  280. (*     Calls:   Color_Screen_Active                                     *)
  281. (*              PTR                                                     *)
  282. (*              Get_Virtual_Screen_Address                              *)
  283. (*              TimeSharingActive                                       *)
  284. (*                                                                      *)
  285. (*----------------------------------------------------------------------*)
  286.  
  287. VAR
  288.    Regs: Registers;
  289.  
  290. BEGIN  (* Get_Screen_Address *)
  291.                                    (* Check if timesharing active.   *)
  292.    IF TimeSharingActive THEN
  293.       CASE MultiTasker OF
  294.          DoubleDos:  BEGIN
  295.                         Regs.Ax := $EC00;
  296.                         MsDos( Regs );
  297.                         Actual_Screen := PTR( Regs.Es, 0 );
  298.                      END;
  299.          TaskView,
  300.          TopView,
  301.          MSWindows,
  302.          DesqView:   CASE Current_Video_Mode OF
  303.                         HiRes_GraphMode : Actual_Screen := PTR( Color_Screen_Address , 0 );
  304.                         EGA_GraphMode   : Actual_Screen := PTR( EGA_Screen_Address , 0 );
  305.                         ELSE              Actual_Screen := DesqView_Screen;
  306.                      END (* CASE *);
  307.          ELSE;
  308.       END
  309.    ELSE
  310.       IF Color_Screen_Active THEN
  311.          Actual_Screen := PTR( Color_Screen_Address , 0 )
  312.       ELSE
  313.          Actual_Screen := PTR( Mono_Screen_Address , 0 );
  314.  
  315. END    (* Get_Screen_Address *);
  316.  
  317. (*----------------------------------------------------------------------*)
  318. (*        Get_Rows_For_EGA  --- Get # of rows in display for EGA        *)
  319. (*----------------------------------------------------------------------*)
  320.  
  321. FUNCTION Get_Rows_For_EGA : INTEGER;
  322.  
  323. VAR
  324.    Regs: Registers;
  325.  
  326. BEGIN (* Get_Rows_For_EGA *)
  327.                                    (* Get # of rows in current EGA display *)
  328.    Regs.AH := $11;
  329.    Regs.AL := $30;
  330.    Regs.BH := 0;
  331.  
  332.    INTR( $10 , Regs );
  333.  
  334.    IF ( Regs.DL > 0 ) THEN
  335.       Get_Rows_For_EGA := SUCC( Regs.DL )
  336.    ELSE
  337.       Get_Rows_For_EGA := 25;
  338.  
  339. END   (* Get_Rows_For_EGA *);
  340.  
  341. (*----------------------------------------------------------------------*)
  342. (*                Video Display Control Routines                        *)
  343. (*----------------------------------------------------------------------*)
  344. (*                                                                      *)
  345. (*       RvsVideoOn  --- Turn On Reverse Video                          *)
  346. (*       RvsVideoOff --- Turn Off Reverse Video                         *)
  347. (*                                                                      *)
  348. (*----------------------------------------------------------------------*)
  349.  
  350. PROCEDURE RvsVideoOn( Foreground_Color, Background_Color : INTEGER );
  351.  
  352. BEGIN (* RvsVideoOn *)
  353.  
  354.    TextColor     ( Background_color );
  355.    TextBackGround( Foreground_color );
  356.  
  357. END   (* RvsVideoOn *);
  358.  
  359. (*----------------------------------------------------------------------*)
  360.  
  361. PROCEDURE RvsVideoOff( Foreground_Color, Background_Color : INTEGER );
  362.  
  363. BEGIN (* RvsVideoOff *)
  364.  
  365.    TextColor     ( Foreground_color );
  366.    TextBackGround( Background_color );
  367.  
  368. END   (* RvsVideoOff *);
  369.  
  370. (*----------------------------------------------------------------------*)
  371. (*                Cursor Display Control Routines                       *)
  372. (*----------------------------------------------------------------------*)
  373. (*                                                                      *)
  374. (*       CursorOn    --- Turn On Cursor                                 *)
  375. (*       CursorOff   --- Turn Off Cursor                                *)
  376. (*       CursorGet   --- Get current cursor type                        *)
  377. (*       CursorSet   --- Set cursor type                                *)
  378. (*                                                                      *)
  379. (*----------------------------------------------------------------------*)
  380.  
  381. PROCEDURE CursorOn;
  382.  
  383. VAR
  384.    Regs: Registers;
  385.    I   : INTEGER;
  386.  
  387. BEGIN (* CursorOn *)
  388.                                    (* Change cursor back to underline *)
  389.    Regs.Ax := $0100;
  390.                                    (* Turn off cursor emulation to *)
  391.                                    (* avoid bug in some EGAs       *)
  392.    IF Font8x8Loaded THEN
  393.       BEGIN
  394.          Regs.CX      := $0507;
  395.          I            := MEM[$0:$487];
  396.          MEM[$0:$487] := I OR 1;
  397.       END
  398.    ELSE
  399.       IF ( Current_Video_Mode = 7 ) THEN
  400.          Regs.CX := $0B0C
  401.       ELSE
  402.          Regs.CX := $0607;
  403.  
  404.    INTR( $10, Regs );
  405.                                    (* Turn cursor emulation back on *)
  406.    IF Font8x8Loaded THEN
  407.       MEM[$0:$487] := I;
  408.  
  409. END   (* CursorOn *);
  410.  
  411. (*----------------------------------------------------------------------*)
  412.  
  413. PROCEDURE CursorOff;
  414.  
  415. VAR
  416.    Regs: Registers;
  417.  
  418. BEGIN (* CursorOff *)
  419.                                    (* Make cursor invisible *)
  420.    Regs.Ax := $0100;
  421.    Regs.Ch := 32;
  422.  
  423.    INTR( $10, Regs );
  424.  
  425. END   (* CursorOff *);
  426.  
  427. (*----------------------------------------------------------------------*)
  428.  
  429. PROCEDURE CursorGet( VAR Current_Cursor : INTEGER );
  430.  
  431. VAR
  432.    Regs: Registers;
  433.  
  434. BEGIN (* CursorGet *)
  435.                                    (* Get current cursor type *)
  436.    Regs.Ax := $0300;
  437.    Regs.Bh := 0;
  438.  
  439.    INTR( $10, Regs );
  440.  
  441.    CASE Regs.CX of
  442.       $0067 : Current_Cursor := $0607;    (* Compaq's bug *)
  443.       $0607 : IF ( ( Current_Video_Mode = 7 ) AND
  444.                    ( NOT Font8x8Loaded      ) ) THEN
  445.                  Current_Cursor := $0C0D  (* IBM's bug    *)
  446.               ELSE
  447.                  Current_Cursor := $0607;
  448.       ELSE    Current_Cursor := Regs.CX;
  449.    END;
  450.  
  451. END   (* CursorGet *);
  452.  
  453. (*----------------------------------------------------------------------*)
  454.  
  455. PROCEDURE CursorSet( New_Cursor_Type : INTEGER );
  456.  
  457. VAR
  458.    Regs: Registers;
  459.    I   : INTEGER;
  460.  
  461. BEGIN (* CursorSet *)
  462.                                    (* Set cursor *)
  463.    Regs.Ax := $0100;
  464.    Regs.Cx := New_Cursor_Type;
  465.                                    (* Turn off cursor emulation to *)
  466.                                    (* avoid bug in some EGAs       *)
  467.    IF Font8x8Loaded THEN
  468.       BEGIN
  469.          I            := MEM[$0:$487];
  470.          MEM[$0:$487] := I OR 1;
  471.       END;
  472.  
  473.    INTR( $10, Regs );
  474.                                    (* Turn cursor emulation back on *)
  475.    IF Font8x8Loaded THEN
  476.       MEM[$0:$487] := I;
  477.  
  478. END   (* CursorSet *);
  479.  
  480. (*----------------------------------------------------------------------*)
  481. (*            Upper_Left ---  Upper Position of current window          *)
  482. (*----------------------------------------------------------------------*)
  483.  
  484. PROCEDURE Upper_Left( VAR X1, Y1 : INTEGER );
  485.  
  486. (*----------------------------------------------------------------------*)
  487. (*                                                                      *)
  488. (*     Procedure:   Upper_Left                                          *)
  489. (*                                                                      *)
  490. (*     Purpose:     Returns upper position of current TURBO window      *)
  491. (*                                                                      *)
  492. (*     Calling Sequence:                                                *)
  493. (*                                                                      *)
  494. (*        Upper_Left( VAR X1, Y1 : INTEGER );                           *)
  495. (*                                                                      *)
  496. (*           X1   --- returned upper left column                        *)
  497. (*           Y1   --- returned upper left row                           *)
  498. (*                                                                      *)
  499. (*     Calls:   None                                                    *)
  500. (*                                                                      *)
  501. (*----------------------------------------------------------------------*)
  502.  
  503. BEGIN  (* Upper_Left *)
  504.  
  505.     Y1 := Upper_Left_Row;          (* get Row *)
  506.     X1 := Upper_Left_Column        (* get Column *)
  507.  
  508. END    (* Upper_Left *);
  509.  
  510. (*----------------------------------------------------------------------*)
  511. (*                Set/Reset Text Color Routines                         *)
  512. (*----------------------------------------------------------------------*)
  513. (*                                                                      *)
  514. (*   These routines set and reset the global text foreground and        *)
  515. (*   background colors.                                                 *)
  516. (*                                                                      *)
  517. (*----------------------------------------------------------------------*)
  518.  
  519.                    (* Global Text Color Variables *)
  520.  
  521. PROCEDURE Set_Global_Colors( ForeGround, BackGround : INTEGER );
  522.  
  523. (*----------------------------------------------------------------------*)
  524. (*                                                                      *)
  525. (*     Procedure:  Set_Global_Colors                                    *)
  526. (*                                                                      *)
  527. (*     Purpose:    Sets global text foreground, background colors.      *)
  528. (*                                                                      *)
  529. (*     Calling Sequence:                                                *)
  530. (*                                                                      *)
  531. (*        Set_Global_Colors( ForeGround, BackGround : INTEGER );        *)
  532. (*                                                                      *)
  533. (*           ForeGround --- Default foreground color                    *)
  534. (*           BackGround --- Default background color                    *)
  535. (*                                                                      *)
  536. (*     Calls:   TextColor                                               *)
  537. (*              TextBackGround                                          *)
  538. (*                                                                      *)
  539. (*----------------------------------------------------------------------*)
  540.  
  541. VAR
  542.    My_Blink : INTEGER;
  543.  
  544. BEGIN  (* Set_Global_Colors *)
  545.  
  546.    Global_ForeGround_Color := ForeGround;
  547.    Global_BackGround_Color := BackGround;
  548.  
  549.    IF ( ForeGround >= Blink ) THEN
  550.       BEGIN
  551.          ForeGround := ForeGround - Blink;
  552.          My_Blink   := 8;
  553.       END
  554.    ELSE
  555.       My_Blink := 0;
  556.  
  557.    Global_Text_Attribute   := ( ( BackGround AND 7 ) OR My_Blink ) SHL 4 +
  558.                                 ForeGround;
  559.  
  560.    TextColor     ( Global_ForeGround_Color );
  561.    TextBackground( Global_BackGround_Color );
  562.  
  563. END    (* Set_Global_Colors *);
  564.  
  565. (*----------------------------------------------------------------------*)
  566. (*  Reset_Global_Colors --- Reset global foreground, background cols.   *)
  567. (*----------------------------------------------------------------------*)
  568.  
  569. PROCEDURE Reset_Global_Colors;
  570.  
  571. (*----------------------------------------------------------------------*)
  572. (*                                                                      *)
  573. (*     Procedure:  Reset_Global_Colors                                  *)
  574. (*                                                                      *)
  575. (*     Purpose:    Resets text foreground, background colors to global  *)
  576. (*                 defaults.                                            *)
  577. (*                                                                      *)
  578. (*     Calling Sequence:                                                *)
  579. (*                                                                      *)
  580. (*        Reset_Global_Colors;                                          *)
  581. (*                                                                      *)
  582. (*     Calls:   TextColor                                               *)
  583. (*              TextBackGround                                          *)
  584. (*                                                                      *)
  585. (*----------------------------------------------------------------------*)
  586.  
  587. BEGIN  (* Reset_Global_Colors *)
  588.  
  589.    TextColor     ( Global_ForeGround_Color );
  590.    TextBackground( Global_BackGround_Color );
  591.  
  592.    Global_Text_Attribute   := ( Global_BackGround_Color AND 7 ) SHL 4 +
  593.                               Global_ForeGround_Color;
  594.  
  595. END    (* Reset_Global_Colors *);
  596.  
  597. (*----------------------------------------------------------------------*)
  598. (*             Set_Border_Color --- Set global border color             *)
  599. (*----------------------------------------------------------------------*)
  600.  
  601. PROCEDURE Set_Border_Color( The_Border_Color : INTEGER );
  602.  
  603. (*----------------------------------------------------------------------*)
  604. (*                                                                      *)
  605. (*     Procedure:  Set_Border_Color                                     *)
  606. (*                                                                      *)
  607. (*     Purpose:    Sets border color                                    *)
  608. (*                                                                      *)
  609. (*     Calling Sequence:                                                *)
  610. (*                                                                      *)
  611. (*        Set_Border_Color( The_Border_Color : INTEGER );               *)
  612. (*                                                                      *)
  613. (*           The_Border_Color --- the border color                      *)
  614. (*                                                                      *)
  615. (*----------------------------------------------------------------------*)
  616.  
  617. VAR
  618.    Regs: Registers;
  619.  
  620. BEGIN  (* Set_Border_Color *)
  621.  
  622.    IF ( ( NOT TimeSharingActive ) AND Write_Screen_Memory AND
  623.         ( Current_Video_Mode <> 7 ) ) THEN
  624.       BEGIN
  625.  
  626.          Regs.Ah := $0B;
  627.          Regs.Bh := 0;
  628.          Regs.Bl := The_Border_Color;
  629.  
  630.          INTR( $10 , Regs );
  631.  
  632.          Global_Border_Color := The_Border_Color;
  633.  
  634.       END;
  635.  
  636. END    (* Set_Border_Color *);
  637.  
  638. (*----------------------------------------------------------------------*)
  639. (*    Change_Attributes --- Changes specified number of attributes      *)
  640. (*----------------------------------------------------------------------*)
  641.  
  642. PROCEDURE Change_Attributes( NAttr: INTEGER;
  643.                              X    : INTEGER;
  644.                              Y    : INTEGER;
  645.                              Color: INTEGER );
  646.  
  647. (*----------------------------------------------------------------------*)
  648. (*                                                                      *)
  649. (*     Procedure:  Change_Attributes                                    *)
  650. (*                                                                      *)
  651. (*     Purpose:    Changes specified number of attributes               *)
  652. (*                                                                      *)
  653. (*     Calling Sequence:                                                *)
  654. (*                                                                      *)
  655. (*        Change_Attributes( NAttr : INTEGER;                           *)
  656. (*                           X     : INTEGER;                           *)
  657. (*                           Y     : INTEGER;                           *)
  658. (*                           Color : INTEGER );                         *)
  659. (*                                                                      *)
  660. (*           NAttr  --- number of attributes to change                  *)
  661. (*           (X,Y)  --- starting column and row position to change      *)
  662. (*           Color  --- new attribute                                   *)
  663. (*                                                                      *)
  664. (*----------------------------------------------------------------------*)
  665.  
  666. BEGIN (* Change_Attributes *)
  667.  
  668. INLINE(
  669.                                   {;}
  670.                                   {;  Check if we're using BIOS.}
  671.                                   {;}
  672.   $F6/$06/>WRITE_SCREEN_MEMORY/$01{         TEST  BYTE [>Write_Screen_Memory],1 ;Direct screen write?}
  673.   /$74/$4F                        {         JZ    Bios                          ;No -- go use BIOS}
  674.                                   {;}
  675.                                   {;  Set up for direct screen write.}
  676.                                   {;  Get row position and column positions, and offset in screen buffer.}
  677.                                   {;}
  678.   /$C4/$3E/>DESQVIEW_SCREEN       {         LES     DI,[>DesqView_Screen]       ;Get base address of screen}
  679.   /$8B/$4E/<Y                     {         MOV     CX,[BP+<Y]                  ;CX = Row}
  680.   /$49                            {         DEC     CX                          ;Row to 0..Max_Screen_Line-1 range}
  681.   /$A1/>MAX_SCREEN_COL            {         MOV     AX,[>Max_Screen_Col]        ;Physical screen width}
  682.   /$F7/$E1                        {         MUL     CX                          ;Row * Max_Screen_Col}
  683.   /$8B/$5E/<X                     {         MOV     BX,[BP+<X]                  ;BX = Column}
  684.   /$4B                            {         DEC     BX                          ;Column to 0..Max_Screen_Col-1 range}
  685.   /$01/$D8                        {         ADD     AX,BX                       ;AX = (Row * Max_Screen_Col) + Col}
  686.   /$D1/$E0                        {         SHL     AX,1                        ;Account for attribute bytes}
  687.   /$89/$FB                        {         MOV     BX,DI                       ;Get base offset of screen}
  688.   /$01/$C3                        {         ADD     BX,AX                       ;Add computed offset}
  689.   /$43                            {         INC     BX                          ;Add 1 to point to attribute}
  690.   /$89/$DF                        {         MOV     DI,BX                       ;Move result into DI}
  691.                                   {;}
  692.   /$8B/$8E/>NATTR                 {         MOV     CX,[BP+>NAttr]              ;CX = # attributes to change}
  693.   /$E3/$79                        {         JCXZ    Exit                        ;If string empty, Exit}
  694.                                   {;}
  695.   /$8A/$26/>WAIT_FOR_RETRACE      {         MOV     AH,[<Wait_For_Retrace]      ;AH = retrace flag}
  696.   /$8A/$46/<COLOR                 {         MOV     AL,[BP+<Color]              ;AL = Attribute}
  697.   /$FC                            {         CLD                                 ;Set direction to forward}
  698.   /$D0/$DC                        {         RCR     AH,1                        ;If we don't wait for retrace, ...}
  699.   /$73/$1A                        {         JNC     Mono                        ; use "Mono" routine}
  700.                                   {;}
  701.                                   {;  Color routine -- wait for retraces.}
  702.                                   {;}
  703.   /$BA/>CRT_STATUS                {         MOV     DX,>CRT_Status              ;Point DX to CGA status port}
  704.   /$89/$C3                        {         MOV     BX,AX                       ;Store video word in BX}
  705.                                   {;}
  706.   /$EC                            {WaitNoH: IN      AL,DX                       ;Get 6845 status}
  707.   /$A8/$01                        {         TEST    AL,1                        ;Wait for horizontal}
  708.   /$75/$FB                        {         JNZ     WaitNoH                     ; retrace to finish}
  709.                                   {;}
  710.   /$FA                            {         CLI                                 ;Turn off interrupts}
  711.   /$EC                            {WaitH:   IN      AL,DX                       ;Get 6845 status again}
  712.   /$A8/$01                        {         TEST    AL,1                        ;Wait for horizontal retrace}
  713.   /$74/$FB                        {         JZ      WaitH                       ; to start}
  714.                                   {;}
  715.   /$89/$D8                        {Store:   MOV     AX,BX                       ;Restore attribute}
  716.   /$AA                            {         STOSB                               ;Store attribute (already in AH)}
  717.   /$FB                            {         STI                                 ;Allow interrupts}
  718.   /$47                            {         INC     DI                          ;Skip character byte}
  719.   /$E2/$EE                        {         LOOP    WaitNoH                     ;Go back and do next attribute}
  720.                                   {;}
  721.   /$E9/$53/$00                    {         JMP     Exit                        ;Quit when done}
  722.                                   {;}
  723.                                   {;  Mono routine (used whenever Wait_For_Retrace is False) **}
  724.                                   {;}
  725.   /$AA                            {Mono:    STOSB                               ;Change attribute}
  726.   /$47                            {         INC     DI                          ;Skip character byte}
  727.   /$E2/$FC                        {         LOOP    Mono                        ;Do next attribute}
  728.                                   {;}
  729.   /$E9/$4C/$00                    {         JMP     Exit                        ;Done}
  730.                                   {;}
  731.                                   {;  Use BIOS to change attributes}
  732.                                   {;}
  733.   /$B4/$03                        {Bios:    MOV     AH,3                        ;Get current cursor position}
  734.   /$30/$FF                        {         XOR     BH,BH                       ;Display page 0}
  735.   /$55                            {         PUSH    BP}
  736.   /$CD/$10                        {         INT     $10}
  737.   /$5D                            {         POP     BP}
  738.                                   {;}
  739.   /$52                            {         PUSH    DX                          ;Save current cursor position}
  740.                                   {;}
  741.   /$8B/$8E/>NATTR                 {         MOV     CX,[BP+>Nattr]              ;Get # attributes to change}
  742.   /$E3/$34                        {         JCXZ    Bios3                       ;Skip this stuff if nothing to do}
  743.                                   {;}
  744.   /$8A/$76/<Y                     {         MOV     DH,[BP+<Y]                  ;Get row}
  745.   /$FE/$CE                        {         DEC     DH                          ;Drop by 1 for 0-origin}
  746.   /$8A/$56/<X                     {         MOV     DL,[BP+<X]                  ;Get column}
  747.   /$FE/$CA                        {         DEC     DL                          ;Drop by 1 for 0-origin}
  748.                                   {;}
  749.   /$51                            {Bios1:   PUSH    CX                          ;Save attributes left to do}
  750.   /$52                            {         PUSH    DX                          ;Save row and column}
  751.   /$30/$FF                        {         XOR     BH,BH                       ;Display page 0}
  752.   /$B4/$02                        {         MOV     AH,2                        ;Set cursor position}
  753.   /$55                            {         PUSH    BP}
  754.   /$CD/$10                        {         INT     $10}
  755.   /$B4/$08                        {         MOV     AH,8                        ;Read character at current position}
  756.   /$CD/$10                        {         INT     $10}
  757.   /$5D                            {         POP     BP}
  758.                                   {;}
  759.   /$B4/$09                        {         MOV     AH,9                        ;Rewrite character with new attrib}
  760.   /$8A/$5E/<COLOR                 {         MOV     BL,[BP+<Color]              ;Get attribute}
  761.   /$B9/$01/$00                    {         MOV     CX,1                        ;Write one character}
  762.   /$55                            {         PUSH    BP}
  763.   /$CD/$10                        {         INT     $10}
  764.   /$5D                            {         POP     BP}
  765.                                   {;}
  766.   /$5A                            {         POP     DX                          ;Restore position}
  767.   /$59                            {         POP     CX                          ;Restore count of attribs left}
  768.                                   {;}
  769.   /$FE/$C2                        {         INC     DL                          ;Point to next column}
  770.   /$3A/$16/>MAX_SCREEN_COL        {         CMP     DL,[>Max_Screen_Col]        ;See if we're past end of line}
  771.   /$72/$04                        {         JB      Bios2}
  772.                                   {;}
  773.   /$FE/$C6                        {         INC     DH                          ;If so, increment row}
  774.   /$30/$D2                        {         XOR     DL,DL                       ;and reset column to 0.}
  775.                                   {;}
  776.   /$E2/$D6                        {Bios2:   LOOP    Bios1                       ;Loop if more attribs to change}
  777.                                   {;}
  778.   /$5A                            {Bios3:   POP     DX                          ;Restore original cursor position}
  779.   /$30/$FF                        {         XOR     BH,BH}
  780.   /$B4/$02                        {         MOV     AH,2}
  781.   /$55                            {         PUSH    BP}
  782.   /$CD/$10                        {         INT     $10}
  783.   /$5D                            {         POP     BP}
  784.                                   {;}
  785.                                   {Exit:}
  786. );
  787.  
  788. END   (* Change_Attributes *);
  789.  
  790. (*----------------------------------------------------------------------*)
  791. (*    Set_Text_Attributes --- Set text attributes for portion of screen *)
  792. (*----------------------------------------------------------------------*)
  793.  
  794. PROCEDURE Set_Text_Attributes( X1, Y1, X2, Y2, FG, BG : INTEGER );
  795.  
  796. (*----------------------------------------------------------------------*)
  797. (*                                                                      *)
  798. (*     Procedure:  Set_Text_Attributes                                  *)
  799. (*                                                                      *)
  800. (*     Purpose:    Sets text attributes for portion of screen           *)
  801. (*                                                                      *)
  802. (*     Calling Sequence:                                                *)
  803. (*                                                                      *)
  804. (*        Set_Text_Attributes( X1, Y2, X2, Y2, FG, BG: INTEGER );       *)
  805. (*                                                                      *)
  806. (*           (X1,Y1);(X2,Y2) --- region to set attributes in            *)
  807. (*           FG --- ForeGround color                                    *)
  808. (*           BG --- BackGround color                                    *)
  809. (*                                                                      *)
  810. (*----------------------------------------------------------------------*)
  811.  
  812. VAR
  813.    Attrib: INTEGER;
  814.    SaveX : INTEGER;
  815.    SaveY : INTEGER;
  816.    I     : INTEGER;
  817.    N     : INTEGER;
  818.  
  819. BEGIN  (* Set_Text_Attributes *)
  820.                                    (* Get # attribs per line to change *)
  821.    N := ( X2 - X1 + 1 );
  822.  
  823.    IF ( N <= 0 ) THEN EXIT;
  824.                                    (* Get new text attribute *)
  825.  
  826.    Attrib := ( BG AND 7 ) SHL 4 + FG;
  827.  
  828.                                    (* Save current position  *)
  829.    SaveX := WhereX;
  830.    SaveY := WhereY;
  831.                                    (* Turn off the cursor      *)
  832.    CursorOff;
  833.                                    (* Freeze screen for DoubleDos *)
  834.  
  835.    IF ( MultiTasker = DoubleDos ) AND ( Write_Screen_Memory ) THEN
  836.       BEGIN
  837.          TurnOffTimeSharing;
  838.          Get_Screen_Address( DesqView_Screen );
  839.       END;
  840.                                    (* Loop over area to change *)
  841.    FOR I := Y1 TO Y2 DO
  842.       Change_Attributes( N, X1, I, Attrib );
  843.  
  844.                                    (* Unfreeze screen in DoubleDos *)
  845.  
  846.    IF Write_Screen_Memory THEN
  847.       IF ( MultiTasker = DoubleDos ) THEN
  848.          TurnOnTimeSharing
  849.                                    (* Synchronize screen for TopView *)
  850.  
  851.       ELSE IF ( MultiTasker = TopView ) THEN
  852.           Sync_Screen( SUCC( ( PRED( Y1 ) * Max_Screen_Col ) SHL 1 ),
  853.                        ( Y2 - Y1 ) * Max_Screen_Col );
  854.  
  855.                                    (* Restore old location *)
  856.    GoToXY( SaveX, SaveY );
  857.                                    (* Turn on the cursor   *)
  858.    CursorOn;
  859.  
  860. END    (* Set_Text_Attributes *);
  861.  
  862. (*----------------------------------------------------------------------*)
  863. (*                 Screen Manipulation Routines                         *)
  864. (*----------------------------------------------------------------------*)
  865. (*                                                                      *)
  866. (*   These routines save and restore screen images in support of the    *)
  867. (*   windowing facility.  Also, the current screen image can be printed *)
  868. (*   and text extracted from the screen memory.                         *)
  869. (*                                                                      *)
  870. (*----------------------------------------------------------------------*)
  871.  
  872. (*----------------------------------------------------------------------*)
  873. (*         ReadCXY --- Read character/attribute from screen             *)
  874. (*----------------------------------------------------------------------*)
  875.  
  876. PROCEDURE ReadCXY( VAR C     (*  : CHAR *);
  877.                        X         : INTEGER;
  878.                        Y         : INTEGER;
  879.                    VAR Color (*  : BYTE *) );
  880.  
  881. (*----------------------------------------------------------------------*)
  882. (*                                                                      *)
  883. (*     Procedure:  ReadCXY                                              *)
  884. (*                                                                      *)
  885. (*     Purpose:    Reads a character from specified row and column      *)
  886. (*                 position on screen.                                  *)
  887. (*                                                                      *)
  888. (*     Calling Sequence:                                                *)
  889. (*                                                                      *)
  890. (*        ReadCXY( VAR C: CHAR; X: INTEGER; Y: INTEGER;                 *)
  891. (*                 VAR Color: INTEGER );                                *)
  892. (*                                                                      *)
  893. (*           C      --- Character picked up                             *)
  894. (*           X      --- Column position to read character               *)
  895. (*           Y      --- Column position to read character               *)
  896. (*           Color  --- Attribute of character                          *)
  897. (*                                                                      *)
  898. (*----------------------------------------------------------------------*)
  899.  
  900. VAR
  901.    SaveXY: INTEGER;
  902.  
  903. BEGIN (* ReadCXY *)
  904.  
  905. INLINE(
  906.                          {;}
  907.   $B4/$03                {          MOV    AH,3              ;Get current cursor position}
  908.   /$B7/$00               {          MOV    BH,0}
  909.   /$CD/$10               {          INT    $10}
  910.                          {;}
  911.   /$89/$96/>SAVEXY       {          MOV    [BP+>SaveXY],DX   ;Save current coordinates}
  912.                          {;}
  913.   /$B4/$02               {          MOV    AH,2              ;Position cursor function}
  914.   /$B7/$00               {          MOV    BH,0}
  915.   /$8A/$76/<Y            {          MOV    DH,[BP+<Y]        ;Get row}
  916.   /$FE/$CE               {          DEC    DH}
  917.   /$8A/$56/<X            {          MOV    DL,[BP+<X]        ;Get column}
  918.   /$FE/$CA               {          DEC    DL}
  919.   /$CD/$10               {          INT    $10               ;Position cursor}
  920.                          {;}
  921.   /$B4/$08               {          MOV    AH,8              ;Get character and attribute}
  922.   /$B7/$00               {          MOV    BH,0}
  923.   /$CD/$10               {          INT    $10}
  924.                          {;}
  925.   /$C4/$7E/<C            {          LES    DI,[BP+<C]        ;Get address of where to store character}
  926.   /$26/$88/$05           {      ES: MOV    [DI],AL           ;and store it}
  927.                          {;}
  928.   /$C4/$7E/<COLOR        {          LES    DI,[BP+<Color]    ;Get address of where to store attribute}
  929.   /$26/$88/$25           {      ES: MOV    [DI],AH           ;and store it}
  930.                          {;}
  931.   /$B4/$02               {          MOV    AH,2              ;Position cursor function}
  932.   /$B7/$00               {          MOV    BH,0}
  933.   /$8B/$96/>SAVEXY       {          MOV    DX,[BP+>SaveXY]   ;Get back previous position}
  934.   /$CD/$10               {          INT    $10               ;Position cursor}
  935.                          {;}
  936. );
  937.  
  938. END   (* ReadCXY *);
  939.  
  940. (*----------------------------------------------------------------------*)
  941. (*           MoveToScreen  ---  Move data to screen memory              *)
  942. (*----------------------------------------------------------------------*)
  943.  
  944. PROCEDURE MoveToScreen( VAR Source, Dest; SLen: INTEGER );
  945.  
  946. (*----------------------------------------------------------------------*)
  947. (*                                                                      *)
  948. (*     Procedure:  MoveToScreen                                         *)
  949. (*                                                                      *)
  950. (*     Purpose:    Moves bytes to screen memory at specified offset     *)
  951. (*                 with retrace locks.                                  *)
  952. (*                                                                      *)
  953. (*     Calling Sequence:                                                *)
  954. (*                                                                      *)
  955. (*        MoveToScreen( VAR Source, Dest; SLen: INTEGER );              *)
  956. (*                                                                      *)
  957. (*           Source --- Data to be moved to screen                      *)
  958. (*           Dest   --- Offset in screen to start storing SData         *)
  959. (*           SLen   --- Number of words to move                         *)
  960. (*                                                                      *)
  961. (*     Calls:   None                                                    *)
  962. (*                                                                      *)
  963. (*----------------------------------------------------------------------*)
  964.  
  965. BEGIN (* MoveToScreen *)
  966.  
  967. INLINE(
  968.   $1E                    {         PUSH  DS                     ;Save DS}
  969.                          {;}
  970.   /$8B/$4E/<SLEN         {         MOV   CX,[BP+<SLen]          ;CX = Length(Source)}
  971.   /$E3/$1E               {         JCXZ  Return                 ;If string empty, Return}
  972.                          {;}
  973.   /$C4/$7E/<DEST         {         LES   DI,[BP+<Dest]          ;ES:DI points to destination}
  974.   /$C5/$76/<SOURCE       {         LDS   SI,[BP+<Source]        ;DS:SI points to source}
  975.   /$FC                   {         CLD                          ;Forward direction}
  976.                          {;}
  977.   /$BA/>CRT_STATUS       {         MOV   DX,>CRT_Status         ;Point DX to CGA status port}
  978.                          {;}
  979.   /$AD                   {GetNext: LODSW                        ;Load next character/attr into AX}
  980.   /$89/$C3               {         MOV   BX,AX                  ;Store video word in BX}
  981.                          {;}
  982.   /$EC                   {WaitNoH: IN    AL,DX                  ;Get 6845 status}
  983.   /$A8/$01               {         TEST  AL,1                   ;Wait for horizontal}
  984.   /$75/$FB               {         JNZ   WaitNoH                ; retrace to finish}
  985.                          {;}
  986.   /$FA                   {         CLI                          ;Turn off interrupts}
  987.   /$EC                   {WaitH:   IN    AL,DX                  ;Get 6845 status again}
  988.   /$A8/$01               {         TEST  AL,1                   ;Wait for horizontal retrace}
  989.   /$74/$FB               {         JZ    WaitH                  ; to start}
  990.                          {;}
  991.   /$89/$D8               {Store:   MOV   AX,BX                  ;Restore attribute}
  992.   /$AB                   {         STOSW                        ; and then to screen}
  993.   /$FB                   {         STI                          ;Allow interrupts}
  994.                          {;}
  995.   /$E2/$EC               {         LOOP  GetNext                ;Get next character}
  996.                          {;}
  997.   /$1F                   {Return:  POP   DS                     ;Restore DS}
  998. );
  999.  
  1000. END   (* MoveToScreen *);
  1001.  
  1002. (*----------------------------------------------------------------------*)
  1003. (*           MoveFromScreen  ---  Move data from screen memory          *)
  1004. (*----------------------------------------------------------------------*)
  1005.  
  1006. PROCEDURE MoveFromScreen( VAR Source, Dest; SLen: INTEGER );
  1007.  
  1008. (*----------------------------------------------------------------------*)
  1009. (*                                                                      *)
  1010. (*     Procedure:  MoveFromScreen                                       *)
  1011. (*                                                                      *)
  1012. (*     Purpose:    Moves bytes from screen memory at specified offset   *)
  1013. (*                 with retrace locks.                                  *)
  1014. (*                                                                      *)
  1015. (*     Calling Sequence:                                                *)
  1016. (*                                                                      *)
  1017. (*        MoveFromScreen( VAR Source, Dest; SLen: INTEGER );            *)
  1018. (*                                                                      *)
  1019. (*           Source --- Offset in screen to start at                    *)
  1020. (*           Dest   --- Receiving data area                             *)
  1021. (*           SLen   --- Number of words to move                         *)
  1022. (*                                                                      *)
  1023. (*     Calls:   None                                                    *)
  1024. (*                                                                      *)
  1025. (*----------------------------------------------------------------------*)
  1026.  
  1027. BEGIN (* MoveFromScreen *)
  1028.  
  1029. INLINE(
  1030.   $1E                    {         PUSH  DS                     ;Save DS}
  1031.                          {;}
  1032.   /$8B/$4E/<SLEN         {         MOV   CX,[BP+<SLen]          ;CX = Length(Source)}
  1033.   /$E3/$1A               {         JCXZ  Return                 ;If string empty, Return}
  1034.   /$C4/$7E/<DEST         {         LES   DI,[BP+<Dest]          ;ES:DI points to destination}
  1035.   /$C5/$76/<SOURCE       {         LDS   SI,[BP+<Source]        ;DS:SI points to source}
  1036.   /$FC                   {         CLD                          ;Forward direction}
  1037.   /$BA/>CRT_STATUS       {         MOV   DX,>CRT_Status         ;Point DX to CGA status port}
  1038.                          {;}
  1039.   /$EC                   {WaitNoH: IN    AL,DX                  ;Get 6845 status}
  1040.   /$A8/$01               {         TEST  AL,1                   ;Wait for horizontal}
  1041.   /$75/$FB               {         JNZ   WaitNoH                ; retrace to finish}
  1042.                          {;}
  1043.   /$FA                   {         CLI                          ;Turn off interrupts}
  1044.   /$EC                   {WaitH:   IN    AL,DX                  ;Get 6845 status again}
  1045.   /$A8/$01               {         TEST  AL,1                   ;Wait for horizontal retrace}
  1046.   /$74/$FB               {         JZ    WaitH                  ; to start}
  1047.                          {;}
  1048.   /$AD                   {         LODSW                        ;Get word from screen}
  1049.   /$FB                   {         STI                          ;Allow interrupts}
  1050.   /$AB                   {         STOSW                        ;Store in receiving data area}
  1051.   /$E2/$F0               {         LOOP  WaitNoH                ;Get next character}
  1052.                          {;}
  1053.   /$1F                   {Return:  POP   DS                     ;Restore DS}
  1054. );
  1055.  
  1056. END   (* MoveFromScreen *);
  1057.