home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / lxlt121s.zip / lxLite_src / common / Crt.pas < prev    next >
Pascal/Delphi Source File  |  1997-04-25  |  18KB  |  658 lines

  1. {█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█}
  2. {█                                                       █}
  3. {█      Virtual Pascal Runtime Library.  Version 1.0.    █}
  4. {█      CRT Interface unit for OS/2                      █}
  5. {█      ─────────────────────────────────────────────────█}
  6. {█      Copyright (C) 1995 B&M&T Corporation             █}
  7. {█      ─────────────────────────────────────────────────█}
  8. {█      Written by Vitaly Miryanov                       █}
  9. {█                                                       █}
  10. {▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀}
  11.  
  12. {$S-,R-,Q-,I-,Cdecl-,OrgName-,AlignRec-}
  13.  
  14. unit Crt;
  15.  
  16. interface
  17.  
  18. uses Use32;
  19.  
  20. const
  21.  
  22. { CRT modes }
  23.  
  24.   BW40          = 0;            { 40x25 B/W on Color Adapter   }
  25.   CO40          = 1;            { 40x25 Color on Color Adapter }
  26.   BW80          = 2;            { 80x25 B/W on Color Adapter   }
  27.   CO80          = 3;            { 80x25 Color on Color Adapter }
  28.   Mono          = 7;            { 80x25 on Monochrome Adapter  }
  29.   Font8x8       = 256;          { Add-in for 8x8 font          }
  30.  
  31. { Foreground and background color constants }
  32.  
  33.   Black         = 0;
  34.   Blue          = 1;
  35.   Green         = 2;
  36.   Cyan          = 3;
  37.   Red           = 4;
  38.   Magenta       = 5;
  39.   Brown         = 6;
  40.   LightGray     = 7;
  41.  
  42. { Foreground color constants }
  43.  
  44.   DarkGray      = 8;
  45.   LightBlue     = 9;
  46.   LightGreen    = 10;
  47.   LightCyan     = 11;
  48.   LightRed      = 12;
  49.   LightMagenta  = 13;
  50.   Yellow        = 14;
  51.   White         = 15;
  52.  
  53. { Add-in for blinking }
  54.  
  55.   Blink         = 128;
  56.  
  57. { Interface variables }
  58.  
  59. const
  60.   CheckBreak: Boolean = True;   { Enable Ctrl-Break      }
  61.   CheckEOF: Boolean = False;    { Allow Ctrl-Z for EOF?  }
  62.   TextAttr: Byte = LightGray;   { Current text attribute }
  63.   RedirOutput: boolean = False; {True if stdOut is redirected}
  64.   RedirInput: boolean = False;  {True if stdIn is redirected}
  65.  
  66. var
  67.   LastMode: Word;               { Current text mode }
  68.   WindMin: Word;                { Window upper left coordinates }
  69.   WindMax: Word;                { Window lower right coordinates }
  70.   StdIn,                        { Old standard input }
  71.   StdOut: Text;                 { and output streams }
  72.  
  73. { The following interface variables are not used (for compatibility only) }
  74.  
  75. const
  76.   DirectVideo: Boolean = False; { Enable direct video addressing }
  77.   CheckSnow: Boolean = True;    { Enable snow filtering }
  78.  
  79. { Interface procedures }
  80.  
  81. procedure AssignCrt(var F: Text);
  82. function KeyPressed: Boolean;
  83. function ReadKey: Char;
  84. procedure TextMode(Mode: Integer);
  85. procedure Window(X1,Y1,X2,Y2: Byte);
  86. procedure GotoXY(X,Y: Byte);
  87. function WhereX: Byte;
  88. function WhereY: Byte;
  89. procedure ClrScr;
  90. procedure ClrEol;
  91. procedure InsLine;
  92. procedure DelLine;
  93. procedure TextColor(Color: Byte);
  94. procedure TextBackground(Color: Byte);
  95. procedure LowVideo;
  96. procedure HighVideo;
  97. procedure NormVideo;
  98. procedure Delay(MS: Longint);
  99.  
  100. { The following procedures are not implemented
  101.  
  102. procedure Sound(Hz: Word);
  103. procedure NoSound;
  104.  
  105. use new procedure PlaySound instead
  106.  
  107. }
  108.  
  109. procedure PlaySound(Freq,Duration: Longint);
  110.  
  111. implementation
  112.  
  113. uses Dos, Os2Def, Os2Base;
  114.  
  115. { Private variables }
  116.  
  117. var
  118.   VioMode: VioModeInfo;
  119.   NormAttr: Byte;
  120.   DelayCount: Longint;
  121.   PrevXcptProc: Pointer;
  122.  
  123. const
  124.   ScanCode: Byte = 0;
  125.  
  126. { Determines if a key has been pressed on the keyboard and returns True }
  127. { if a key has been pressed                                             }
  128.  
  129. function KeyPressed: Boolean;
  130. var
  131.   Key: KbdKeyInfo;
  132. begin
  133.   KbdPeek(Key,0);
  134.   KeyPressed := (ScanCode <> 0) or ((Key.fbStatus and kbdtrf_Final_Char_In) <> 0);
  135. end;
  136.  
  137. { Reads a character from the keyboard and returns a character or an     }
  138. { extended scan code.                                                   }
  139.  
  140. function ReadKey: Char;
  141. var
  142.   Key: KbdKeyInfo;
  143. begin
  144.  if RedirInput
  145.   then Read(Input, Key.chChar)
  146.   else begin
  147.         If ScanCode <> 0
  148.          then begin
  149.                Key.chChar := Chr(ScanCode);
  150.                ScanCode := 0;
  151.               end
  152.          else begin
  153.                KbdCharIn(Key,io_Wait,0);
  154.                case Key.chChar of
  155.                 #0:
  156.                  ScanCode := Key.chScan;
  157.                 #$E0:           {   Up, Dn, Left Rt Ins Del Home End PgUp PgDn C-Home C-End C-PgUp C-PgDn C-Left C-Right C-Up C-Dn }
  158.                  if Key.chScan in [$48,$50,$4B,$4D,$52,$53,$47, $4F,$49, $51, $77,   $75,  $84,   $76,   $73,   $74,    $8D, $91]
  159.                   then begin
  160.                         ScanCode := Key.chScan;
  161.                         Key.chChar := #0;
  162.                        end;
  163.                end;
  164.               end;
  165.        end;
  166.  ReadKey := Key.chChar;
  167. end;
  168.  
  169. { Reads normal character attribute }
  170.  
  171. procedure ReadNormAttr;
  172. var
  173.   Cell,Size: SmallWord;
  174. begin
  175.   Size := 2;
  176.   VioReadCellStr(Cell, Size, WhereY-1, WhereX-1, 0);
  177.   NormAttr := Hi(Cell) and $7F;
  178.   NormVideo;
  179. end;
  180.  
  181. { Setups window coordinates }
  182.  
  183. procedure SetWindowPos;
  184. begin
  185.   WindMin := 0;
  186.   WindMax := VioMode.Col - 1 + (VioMode.Row - 1) shl 8;
  187. end;
  188.  
  189. { Stores current video mode in LastMode }
  190.  
  191. procedure GetLastMode;
  192. begin
  193.   VioMode.cb := SizeOf(VioMode);
  194.   VioGetMode(VioMode, 0);
  195.   with VioMode do
  196.   begin
  197.     if Col = 40 then LastMode := BW40 else LastMode := BW80;
  198.     if (fbType and vgmt_DisableBurst) = 0 then
  199.       if LastMode = BW40 then LastMode := CO40 else LastMode := CO80;
  200.     if Color = 0 then LastMode := Mono;
  201.     if Row > 25 then Inc(LastMode,Font8x8);
  202.   end;
  203. end;
  204.  
  205. { Selects a specific text mode. The valid text modes are:               }
  206. {   BW40: 40x25 Black and white                                         }
  207. {   CO40  40x25 Color                                                   }
  208. {   BW80  80x25 Black and white                                         }
  209. {   CO80  80x25 Color                                                   }
  210. {   Mono  80x25 Black and white                                         }
  211. {   Font8x8 (Add-in) 43-/50-line mode                                   }
  212.  
  213. procedure TextMode(Mode: Integer);
  214. var BiosMode: Byte; Cell: SmallWord; VideoConfig: VioConfigInfo;
  215. begin
  216.   GetLastMode;
  217.   TextAttr := LightGray;
  218.   BiosMode := Lo(Mode);
  219.   VideoConfig.cb := SizeOf(VideoConfig);
  220.   VioGetConfig(0, VideoConfig, 0);
  221.   with VioMode do
  222.   begin
  223.     cb := SizeOf(VioMode);
  224.     fbType := vgmt_Other;
  225.     Color := colors_16;         { Color }
  226.     Row := 25;                  { 80x25 }
  227.     Col := 80;
  228.     VRes := 400;
  229.     HRes := 720;
  230.     case BiosMode of            { 40x25 }
  231.       BW40,CO40:
  232.         begin
  233.           Col := 40; HRes := 360;
  234.         end;
  235.     end;
  236.     if (Mode and Font8x8) <> 0 then
  237.     case VideoConfig.Adapter of { 80x43 }
  238.       display_Monochrome..display_CGA: ;
  239.       display_EGA:
  240.         begin
  241.           Row := 43; VRes := 350; HRes := 640;
  242.         end;
  243.       else                      { 80x50 }
  244.         begin
  245.           Row := 50; VRes := 400; HRes := 720;
  246.         end;
  247.     end;
  248.     case BiosMode of            { Black and white }
  249.       BW40,BW80: fbType := vgmt_Other + vgmt_DisableBurst;
  250.       Mono:
  251.         begin                   { Monochrome }
  252.           HRes := 720; VRes := 350; Color := 0; fbType := 0;
  253.         end;
  254.     end;
  255.   end;
  256.   VioSetMode(VioMode, 0);
  257.   VioGetMode(VioMode, 0);
  258.   NormVideo;
  259.   SetWindowPos;
  260.   Cell := Ord(' ') + TextAttr shl 8;    { Clear entire screen }
  261.   VioScrollUp(0,0,65535,65535,65535,Cell,0);
  262. end;
  263.  
  264. { Defines a text window on the screen.                                  }
  265.  
  266. procedure Window(X1,Y1,X2,Y2: Byte);
  267. begin
  268.   if (X1 <= X2) and (Y1 <= Y2) then
  269.   begin
  270.     Dec(X1);
  271.     Dec(Y1);
  272.     if (X1 >= 0) and (Y1 >= 0) then
  273.     begin
  274.       Dec(X2);
  275.       Dec(Y2);
  276.       if (X2 < VioMode.Col) and (Y2 < VioMode.Row) then
  277.       begin
  278.         WindMin := X1 + Y1 shl 8;
  279.         WindMax := X2 + Y2 shl 8;
  280.         GotoXY(1,1);
  281.       end;
  282.     end;
  283.   end;
  284. end;
  285.  
  286. { Moves the cursor to the given coordinates within the screen.          }
  287.  
  288. procedure GotoXY(X,Y: Byte);
  289. var
  290.   X1,Y1: Word;
  291. begin
  292.   if (X > 0) and (Y > 0) then
  293.   begin
  294.     X1 := X - 1 + Lo(WindMin);
  295.     Y1 := Y - 1 + Hi(WindMin);
  296.     if (X1 <= Lo(WindMax)) and (Y1 <= Hi(WindMax)) then VioSetCurPos(Y1,X1,0);
  297.   end;
  298. end;
  299.  
  300. { Returns the X coordinate of the current cursor location.              }
  301.  
  302. function WhereX: Byte;
  303. var
  304.   X,Y: SmallWord;
  305. begin
  306.   VioGetCurPos(Y,X,0);
  307.   WhereX := X - Lo(WindMin) + 1;
  308. end;
  309.  
  310. { Returns the Y coordinate of the current cursor location.              }
  311.  
  312. function WhereY: Byte;
  313. var
  314.   X,Y: SmallWord;
  315. begin
  316.   VioGetCurPos(Y,X,0);
  317.   WhereY := Y - Hi(WindMin) + 1;
  318. end;
  319.  
  320. { Clears the screen and returns the cursor to the upper-left corner.    }
  321.  
  322. procedure ClrScr;
  323. var
  324.   Cell: SmallWord;
  325. begin
  326.   Cell := Ord(' ') + TextAttr shl 8;
  327.   VioScrollUp(Hi(WindMin),Lo(WindMin),Hi(WindMax),Lo(WindMax),Hi(WindMax)-Hi(WindMin)+1,Cell,0);
  328.   GotoXY(1,1);
  329. end;
  330.  
  331. { Clears all characters from the cursor position to the end of the line }
  332. { without moving the cursor.                                            }
  333.  
  334. procedure ClrEol;
  335. var
  336.   Cell,X,Y: SmallWord;
  337. begin
  338.   Cell := Ord(' ') + TextAttr shl 8;
  339.   VioGetCurPos(Y,X,0);
  340.   VioScrollUp(Y,X,Y,Lo(WindMax),1,Cell,0);
  341. end;
  342.  
  343. { Inserts an empty line at the cursor position.                         }
  344.  
  345. procedure InsLine;
  346. var
  347.   Cell,X,Y: SmallWord;
  348. begin
  349.   Cell := Ord(' ') + TextAttr shl 8;
  350.   VioGetCurPos(Y,X,0);
  351.   VioScrollDn(Y,Lo(WindMin),Hi(WindMax),Lo(WindMax),1,Cell,0);
  352. end;
  353.  
  354. { Deletes the line containing the cursor.                               }
  355.  
  356. procedure DelLine;
  357. var
  358.   Cell,X,Y: SmallWord;
  359. begin
  360.   Cell := Ord(' ') + TextAttr shl 8;
  361.   VioGetCurPos(Y,X,0);
  362.   VioScrollUp(Y,Lo(WindMin),Hi(WindMax),Lo(WindMax),1,Cell,0);
  363. end;
  364.  
  365. { Selects the foreground character color.                               }
  366.  
  367. procedure TextColor(Color: Byte);
  368. begin
  369.   if Color > White then Color := (Color and $0F) or $80;
  370.   TextAttr := (TextAttr and $70) or Color;
  371. end;
  372.  
  373. { Selects the background color.                                         }
  374.  
  375. procedure TextBackground(Color: Byte);
  376. begin
  377.   TextAttr := (TextAttr and $8F) or ((Color and $07) shl 4);
  378. end;
  379.  
  380. { Selects low intensity characters.                                     }
  381.  
  382. procedure LowVideo;
  383. begin
  384.   TextAttr := TextAttr and $F7;
  385. end;
  386.  
  387. { Selects normal intensity characters.                                  }
  388.  
  389. procedure NormVideo;
  390. begin
  391.   TextAttr := NormAttr;
  392. end;
  393.  
  394. { Selects high-intensity characters.                                    }
  395.  
  396. procedure HighVideo;
  397. begin
  398.   TextAttr := TextAttr or $08;
  399. end;
  400.  
  401. { Waits for next timer tick or delays 1ms }
  402.  
  403. function DelayLoop(Count: Longint; var StartValue: ULong): Longint;
  404. var
  405.   Value: ULong;
  406. begin
  407.   repeat
  408.     DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,Value,SizeOf(Value));
  409.     Dec(Count);
  410.   until (Value <> StartValue) or (Count = -1);
  411.   StartValue := Value;
  412.   DelayLoop := Count;
  413. end;
  414.  
  415. { Delays a specified number of milliseconds. DosSleep is too inexact on }
  416. { small time intervals. More over, the least time interval for DosSleep }
  417. { is 1 timer tick (usually 31ms). That is why for small time intervals  }
  418. { special delay routine is used. Unfortunately, even this routine cannot}
  419. { be exact in the multitasking environment.                             }
  420.  
  421. procedure Delay(MS: Longint);
  422. var
  423.   StartValue,Value: ULong;
  424.   Count: Longint;
  425. begin
  426.   if MS >= 31 then DosSleep(MS)
  427.  else
  428.   begin
  429.     DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,StartValue,SizeOf(StartValue));
  430.     Value := StartValue;
  431.     Count := MS;
  432.     repeat
  433.       DelayLoop(DelayCount,Value);
  434.       Dec(Count)
  435.     until (Value-StartValue >= MS) or (Count <= 0);
  436.   end;
  437. end;
  438.  
  439. { Calculates 1ms delay count for DelayLoop routine. }
  440. { CalcDelayCount is called once at startup.         }
  441.  
  442. procedure CalcDelayCount;
  443. var
  444.   Interval,StartValue,Value: ULong;
  445. begin
  446.   DosQuerySysInfo(qsv_Timer_Interval,qsv_Timer_Interval,Interval,SizeOf(Interval));
  447.   DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,StartValue,SizeOf(StartValue));
  448.   repeat
  449.     DosQuerySysInfo(qsv_Ms_Count,qsv_Ms_Count,Value,SizeOf(Value));
  450.   until Value <> StartValue;
  451.   DelayCount := -DelayLoop(-1,Value) div Interval * 10;
  452.   if DelayCount = 0 then Inc(DelayCount);
  453. end;
  454.  
  455. { Plays sound of a specified frequency and duration.                    }
  456.  
  457. procedure PlaySound(Freq,Duration: Longint);
  458. begin
  459.   DosBeep(Freq,Duration);
  460. end;
  461.  
  462. { Do line feed operation }
  463.  
  464. procedure LineFeed;
  465. var
  466.   Cell: SmallWord;
  467. begin
  468.   Cell := Ord(' ') + TextAttr shl 8;
  469.   VioScrollUp(Hi(WindMin),Lo(WindMin),Hi(WindMax),Lo(WindMax),1,Cell,0);
  470. end;
  471.  
  472. { Outputs packed string to the CRT device }
  473.  
  474. procedure WritePackedString(S: PChar; Len: Longint);
  475. var X,Y,cX,cY : SmallWord;
  476.     i,sP,sL   : Longint;
  477.     C         : Char;
  478. begin
  479.  VioGetCurPos(Y,X,0);
  480.  i := 0;
  481.  While i < Len do
  482.   begin
  483.    sP := i; sL := 0;
  484.    cX := X; cY := Y;
  485.    repeat
  486.     C := S[i]; Inc(i);
  487.     if C in [^J,^M,^H,^G] then break;
  488.     Inc(sL); Inc(X);
  489.    until (i >= pred(Len)) or (X > Lo(WindMax));
  490.    if sL <> 0 then VioWrtCharStrAtt(@S[sP], sL, cY, cX, TextAttr, 0);
  491.    case C of
  492.     ^J : if Y >= Hi(WindMax) then LineFeed else Inc(Y); { Line Feed       }
  493.     ^M : X := Lo(WindMin);                              { Carriage return }
  494.     ^H : if X > Lo(WindMin) then Dec(X);                { Backspace       }
  495.     ^G : begin                                          { Bell            }
  496.           if (X <> cX) or (Y <> cY) then VioSetCurPos(Y,X,0);
  497.           cX := X; cY := Y;
  498.           VioWrtTTY(@C,1,0);
  499.          end;
  500.    end;
  501.    if X > Lo(WindMax)
  502.     then begin
  503.           X := Lo(WindMin);
  504.           Inc(Y);
  505.          end;
  506.    if Y > Hi(WindMax)
  507.     then begin
  508.           LineFeed;
  509.           Y := Hi(WindMax);
  510.          end;
  511.    if (X <> cX) or (Y <> cY) then VioSetCurPos(Y,X,0);
  512.   end;
  513. end;
  514.  
  515. { CRT text file I/O functions }
  516.  
  517. function CrtRead(var F: Text): Longint;
  518. var
  519.   CurPos : Longint;
  520.   C      : Char;
  521. begin
  522.   with TextRec(F) do
  523.   begin
  524.     CurPos := 0;
  525.     repeat
  526.       ScanCode := 0;
  527.       C := ReadKey;
  528.       case C of
  529.         ^H:                     { Backspace }
  530.           if CurPos > 0 then
  531.           begin
  532.             WritePackedString(^H' '^H, 3);
  533.             Dec(CurPos);
  534.           end;
  535.         #27:                    { Escape }
  536.           while CurPos > 0 do
  537.           begin
  538.             WritePackedString(^H' '^H, 3);
  539.             Dec(CurPos);
  540.           end;
  541.         ' '..#255:
  542.           if CurPos < BufSize - 2 then
  543.           begin
  544.             BufPtr^[CurPos] := C;
  545.             Inc(CurPos);
  546.             WritePackedString(@C,1);
  547.           end;
  548.       end; { case }
  549.     until (C = ^M) or (CheckEOF and (C = ^Z));
  550.     BufPtr^[CurPos] := C;
  551.     Inc(CurPos);
  552.     if C = ^M then              { Carriage Return }
  553.     begin
  554.       BufPtr^[CurPos] := ^J;    { Line Feed }
  555.       Inc(CurPos);
  556.       WritePackedString(^M^J,2);
  557.     end;
  558.     BufPos := 0;
  559.     BufEnd := CurPos;
  560.   end;
  561.   CrtRead := 0;                 { I/O result = 0: success }
  562. end;
  563.  
  564. function CrtWrite(var F: Text): Longint;
  565. begin
  566.   with TextRec(F) do
  567.   begin
  568.     WritePackedString(PChar(BufPtr),BufPos);
  569.     BufPos := 0;
  570.   end;
  571.   CrtWrite := 0;                { I/O result = 0: success }
  572. end;
  573.  
  574. function CrtReturn(var F: Text): Longint;
  575. begin
  576.   CrtReturn := 0;               { I/O result = 0: success }
  577. end;
  578.  
  579. function CrtOpen(var F: Text): Longint;
  580. begin
  581.   with TextRec(F) do
  582.   begin
  583.     CloseFunc := @CrtReturn;
  584.     if Mode = fmInput then
  585.     begin
  586.       InOutFunc := @CrtRead;
  587.       FlushFunc := @CrtReturn;
  588.     end
  589.    else
  590.     begin
  591.       Mode := fmOutput;
  592.       InOutFunc := @CrtWrite;
  593.       FlushFunc := @CrtWrite;
  594.     end;
  595.   end;
  596.   CrtOpen := 0;                 { I/O result = 0: success }
  597. end;
  598.  
  599. { Associates a text file with CRT device.                               }
  600.  
  601. procedure AssignCrt(var F: Text);
  602. begin
  603.   with TextRec(F) do
  604.   begin
  605.     Handle := $FFFFFFFF;
  606.     Mode := fmClosed;
  607.     BufSize := SizeOf(Buffer);
  608.     BufPtr := @Buffer;
  609.     OpenFunc := @CrtOpen;
  610.     Name[0] := #0;
  611.   end;
  612. end;
  613.  
  614. { Signal Handler }
  615.  
  616. function CtrlBreakHandler(Report:       PExceptionReportRecord;
  617.                           Registration: PExceptionRegistrationRecord;
  618.                           Context:      PContextRecord;
  619.                           P:            Pointer): ULong; cdecl;
  620. begin
  621.   if not CheckBreak and (Report^.ExceptionNum = xcpt_Signal)
  622.     then CtrlBreakHandler := xcpt_Continue_Execution
  623.     else CtrlBreakHandler := xcpt_Continue_Search;
  624. end;
  625.  
  626. Procedure AssignConToCrt;
  627. var hType,hAttr : Longint;
  628. begin
  629.  Move(Input, StdIn, sizeOf(StdIn));
  630.  Move(Output, StdOut, sizeOf(StdOut));
  631.  DosQueryHType(0, hType, hAttr);
  632.  if (hType and 3 = 1) and (hAttr and 1 <> 0)
  633.   then begin
  634.         AssignCrt(Input);
  635.         Reset(Input);
  636.        end
  637.   else RedirInput := True;
  638.  DosQueryHType(1, hType, hAttr);
  639.  if (hType and 3 = 1) and (hAttr and 2 <> 0)
  640.   then begin
  641.         AssignCrt(Output);
  642.         ReWrite(Output);
  643.        end
  644.   else RedirOutput := True;
  645. end;
  646.  
  647. begin
  648.  GetLastMode;
  649.  if (VioMode.fbType and vgmt_Graphics) <> 0 then TextMode(CO80);
  650.  ReadNormAttr;
  651.  SetWindowPos;
  652.  AssignConToCrt;
  653.  CalcDelayCount;
  654.  PrevXcptProc := XcptProc;
  655.  XcptProc := @CtrlBreakHandler;
  656. end.
  657.  
  658.