2
0

wansi.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1996-2000 by Berczi Gabor
  5. ANSI support
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {.$DEFINE DEBUG}
  13. unit WANSI;
  14. interface
  15. uses Objects,Drivers,Crt,Dos,Views,App;
  16. const
  17. ANSIMaxParamLen = 30; { max ANSI escape sequence length }
  18. ANSICurPosStackSize = 20; { max number of cursor positions stored at the same time }
  19. Esc = #27;
  20. MaxVideoLine = 65520 div (2*MaxViewWidth); { maximum number of lines that fit in 64K }
  21. { BoundCheck constants }
  22. bc_MinX = 1;
  23. bc_MinY = 2;
  24. bc_MaxX = 4;
  25. bc_MaxY = 8;
  26. bc_X = bc_MinX or bc_MaxX;
  27. bc_Y = bc_MinY or bc_MaxY;
  28. bc_Min = bc_MinX or bc_MinY;
  29. bc_Max = bc_MaxX or bc_MaxY;
  30. bc_All = bc_X or bc_Y;
  31. type
  32. TANSIParam = string[ANSIMaxParamLen];
  33. PHookProc = ^THookProc;
  34. THookProc = procedure (S: string);
  35. PConsoleObject = ^TConsoleObject;
  36. TConsoleObject = object(TObject)
  37. CurPos : TPoint;
  38. Size : TPoint;
  39. TextAttr : byte;
  40. BoldOn : boolean;
  41. BlinkOn : boolean;
  42. BoundChecks: byte;
  43. LineWrapping: boolean;
  44. ReplyHook : PHookProc;
  45. KeyHook : PHookProc;
  46. WriteHook : PHookProc;
  47. constructor Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  48. procedure Home; virtual;
  49. procedure ClrScr; virtual;
  50. procedure FillScreen(B: byte); virtual;
  51. procedure ClrEol; virtual;
  52. procedure GotoXY(X,Y: integer); virtual;
  53. procedure Write(S: string); virtual;
  54. procedure WriteLn(S: string); virtual;
  55. procedure WriteChar(C: char); virtual;
  56. procedure DelLine(LineCount: integer); virtual;
  57. procedure InsLine(LineCount: integer); virtual;
  58. procedure HighVideo; virtual;
  59. procedure BlinkVideo; virtual;
  60. procedure NoBlinkVideo; virtual;
  61. procedure NormVideo; virtual;
  62. procedure LowVideo; virtual;
  63. procedure TextBackground(Color: byte); virtual;
  64. procedure TextColor(Color: byte); virtual;
  65. function WhereX: integer; virtual;
  66. function WhereY: integer; virtual;
  67. procedure CursorOn; virtual;
  68. procedure CursorOff; virtual;
  69. procedure UpdateCursor; virtual;
  70. { --- Hook procedures --- }
  71. procedure Reply(S: string); virtual;
  72. procedure PutKey(S: string); virtual;
  73. destructor Done; virtual;
  74. private
  75. procedure ProcessChar(C: char); virtual;
  76. end;
  77. PANSIConsole = ^TANSIConsole;
  78. TANSIConsole = object(TConsoleObject)
  79. ANSIParam : TANSIParam;
  80. ANSILevel : byte;
  81. ANSICurPosStack : array[1..ANSICurPosStackSize] of TPoint;
  82. ANSICurPosStackPtr : byte;
  83. constructor Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  84. procedure ProcessChar(C: char); virtual;
  85. function GetANSIParam: integer; virtual;
  86. { --- ANSI functions --- }
  87. procedure PushCurPos; virtual;
  88. procedure PopCurPos; virtual;
  89. procedure CursorUp(LineCount: integer); virtual;
  90. procedure CursorDown(LineCount: integer); virtual;
  91. procedure CursorForward(CharCount: integer); virtual;
  92. procedure CursorBack(CharCount: integer); virtual;
  93. procedure SetAttr(Color: integer); virtual;
  94. end;
  95. PCrtConsole = ^TCrtConsole;
  96. TCrtConsole = object(TANSIConsole)
  97. constructor Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  98. procedure CursorOn; virtual;
  99. procedure CursorOff; virtual;
  100. procedure ClrScr; virtual;
  101. procedure ClrEol; virtual;
  102. procedure WriteChar(C: char); virtual;
  103. procedure DelLine(LineCount: integer); virtual;
  104. procedure InsLine(LineCount: integer); virtual;
  105. procedure UpdateCursor; virtual;
  106. procedure TextBackground(Color: byte); virtual;
  107. procedure TextColor(Color: byte); virtual;
  108. end;
  109. PANSIView = ^TANSIView;
  110. PANSIViewConsole = ^TANSIViewConsole;
  111. TANSIViewConsole = object(TANSIConsole)
  112. Owner : PANSIView;
  113. constructor Init(AOwner: PANSIView);
  114. procedure CursorOn; virtual;
  115. procedure CursorOff; virtual;
  116. procedure ClrScr; virtual;
  117. procedure ClrEol; virtual;
  118. procedure WriteChar(C: char); virtual;
  119. procedure DelLine(LineCount: integer); virtual;
  120. procedure InsLine(LineCount: integer); virtual;
  121. procedure UpdateCursor; virtual;
  122. procedure GotoXY(X,Y: integer); virtual;
  123. end;
  124. TVideoBuf = array[0..MaxViewWidth*MaxVideoLine] of word;
  125. TANSIView = object(TScroller)
  126. Console : PANSIViewConsole;
  127. Buffer : TVideoBuf;
  128. LockCount : word;
  129. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar:PScrollBar);
  130. function LoadFile(const FileName: string): boolean;
  131. procedure Draw; virtual;
  132. destructor Done; virtual;
  133. procedure Write(S: string); virtual;
  134. procedure WriteLn(S: string); virtual;
  135. procedure Lock; virtual;
  136. procedure UnLock; virtual;
  137. procedure ChangeBounds(var Bounds: TRect); virtual;
  138. procedure HandleEvent(var Event: TEvent); virtual;
  139. private
  140. end;
  141. PANSIBackground = ^TANSIBackground;
  142. PANSIBackgroundConsole = ^TANSIBackgroundConsole;
  143. TANSIBackgroundConsole = object(TANSIConsole)
  144. Owner : PANSIBackground;
  145. constructor Init(AOwner: PANSIBackground);
  146. procedure CursorOn; virtual;
  147. procedure CursorOff; virtual;
  148. procedure ClrScr; virtual;
  149. procedure ClrEol; virtual;
  150. procedure WriteChar(C: char); virtual;
  151. procedure DelLine(LineCount: integer); virtual;
  152. procedure InsLine(LineCount: integer); virtual;
  153. procedure UpdateCursor; virtual;
  154. procedure GotoXY(X,Y: integer); virtual;
  155. end;
  156. TANSIBackground = object(TBackground)
  157. Console : PANSIBackgroundConsole;
  158. Buffer : TVideoBuf;
  159. LockCount : word;
  160. constructor Init(var Bounds: TRect);
  161. function LoadFile(const FileName: string): boolean;
  162. procedure Draw; virtual;
  163. destructor Done; virtual;
  164. procedure Write(S: string); virtual;
  165. procedure WriteLn(S: string); virtual;
  166. procedure Lock; virtual;
  167. procedure UnLock; virtual;
  168. procedure ChangeBounds(var Bounds: TRect); virtual;
  169. procedure HandleEvent(var Event: TEvent); virtual;
  170. private
  171. end;
  172. implementation
  173. uses WUtils;
  174. constructor TConsoleObject.Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  175. begin
  176. inherited Init;
  177. ReplyHook:=AReplyHook; KeyHook:=AKeyHook; WriteHook:=AWriteHook;
  178. BoundChecks:=bc_All; LineWrapping:=true;
  179. TextColor(LightGray); TextBackground(Black);
  180. NormVideo;
  181. ClrScr;
  182. end;
  183. procedure TConsoleObject.Home;
  184. begin
  185. GotoXY(1,1);
  186. end;
  187. procedure TConsoleObject.ClrScr;
  188. begin
  189. Abstract;
  190. end;
  191. procedure TConsoleObject.FillScreen(B: byte);
  192. var X,Y: integer;
  193. S : string;
  194. begin
  195. GotoXY(1,1);
  196. for Y:=1 to Size.Y do
  197. begin
  198. S:='';
  199. for X:=1 to Size.X do S:=S+chr(B);
  200. WriteLn(S);
  201. end;
  202. end;
  203. procedure TConsoleObject.ClrEol;
  204. begin
  205. Abstract;
  206. end;
  207. procedure TConsoleObject.GotoXY(X,Y: integer);
  208. begin
  209. if (BoundChecks and bc_MinX)<>0 then X:=Max(X,1);
  210. if (BoundChecks and bc_MaxX)<>0 then
  211. if LineWrapping then while (X>Size.X) and (Size.X<>0)
  212. do begin
  213. Inc(Y);
  214. X:=X-Size.X;
  215. end
  216. else X:=Min(X,Size.X);
  217. if (BoundChecks and bc_MinY)<>0 then Y:=Max(Y,1);
  218. if (BoundChecks and bc_MaxY)<>0 then Y:=Min(Y,Size.Y);
  219. CurPos.X:=X; CurPos.Y:=Y;
  220. UpdateCursor;
  221. end;
  222. procedure TConsoleObject.ProcessChar(C: char);
  223. begin
  224. WriteChar(C);
  225. end;
  226. procedure TConsoleObject.WriteChar(C: char);
  227. begin
  228. Abstract;
  229. end;
  230. procedure TConsoleObject.Write(S: string); {assembler;
  231. asm
  232. push ds
  233. lds si, S
  234. lodsb
  235. xor ah, ah
  236. mov cx, ax
  237. @loop:
  238. or cx, cx
  239. je @exitloop
  240. lodsb
  241. pop ds
  242. push ax
  243. call ProcessChar
  244. push ds
  245. dec cx
  246. jmp @loop
  247. @exitloop:
  248. pop ds
  249. end;}
  250. var Len: byte;
  251. I : byte;
  252. begin
  253. Len:=length(S);
  254. for I:=1 to Len do ProcessChar(S[I]);
  255. end;
  256. procedure TConsoleObject.WriteLn(S: string);
  257. begin
  258. Write(S+#10);
  259. end;
  260. procedure TConsoleObject.DelLine(LineCount: integer);
  261. begin
  262. Abstract;
  263. end;
  264. procedure TConsoleObject.InsLine(LineCount: integer);
  265. begin
  266. Abstract;
  267. end;
  268. procedure TConsoleObject.NormVideo;
  269. begin
  270. BoldOn:=false; BlinkOn:=false;
  271. TextColor(LightGray);
  272. TextBackground(Black);
  273. end;
  274. procedure TConsoleObject.BlinkVideo;
  275. begin
  276. BlinkOn:=true;
  277. TextBackground(TextAttr shr 4);
  278. end;
  279. procedure TConsoleObject.NoBlinkVideo;
  280. begin
  281. BlinkOn:=false;
  282. TextBackground(TextAttr shr 4);
  283. end;
  284. procedure TConsoleObject.HighVideo;
  285. begin
  286. BoldOn:=true;
  287. TextColor(TextAttr);
  288. end;
  289. procedure TConsoleObject.LowVideo;
  290. begin
  291. BoldOn:=false;
  292. TextColor(TextAttr);
  293. end;
  294. procedure TConsoleObject.TextBackground(Color: byte);
  295. begin
  296. if BlinkOn=false then TextAttr:=TextAttr and $7f;
  297. TextAttr:=(TextAttr and $0f) or (Color shl 4) or byte(BlinkOn)*$80;
  298. end;
  299. procedure TConsoleObject.TextColor(Color: byte);
  300. begin
  301. if BoldOn=false then TextAttr:=TextAttr and not $08;
  302. TextAttr:=((TextAttr and $f0) or (Color and $0f) or byte(BoldOn)*$08);
  303. end;
  304. function TConsoleObject.WhereX: integer;
  305. begin
  306. WhereX:=CurPos.X;
  307. end;
  308. function TConsoleObject.WhereY: integer;
  309. begin
  310. WhereY:=CurPos.Y;
  311. end;
  312. procedure TConsoleObject.CursorOn;
  313. begin
  314. Abstract;
  315. end;
  316. procedure TConsoleObject.CursorOff;
  317. begin
  318. Abstract;
  319. end;
  320. procedure TConsoleObject.UpdateCursor;
  321. begin
  322. Abstract;
  323. end;
  324. procedure TConsoleObject.Reply(S: string);
  325. begin
  326. if ReplyHook<>nil then ReplyHook^(S);
  327. end;
  328. procedure TConsoleObject.PutKey(S: string);
  329. begin
  330. if KeyHook<>nil then KeyHook^(S);
  331. end;
  332. destructor TConsoleObject.Done;
  333. begin
  334. inherited Done;
  335. end;
  336. constructor TCrtConsole.Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  337. begin
  338. inherited Init(AReplyHook, AKeyHook, AWriteHook);
  339. Size.X:=Lo(Crt.WindMax); Size.Y:=Hi(Crt.WindMax);
  340. end;
  341. procedure TCrtConsole.CursorOn;
  342. begin
  343. end;
  344. procedure TCrtConsole.CursorOff;
  345. begin
  346. end;
  347. procedure TCrtConsole.ClrScr;
  348. begin
  349. Crt.ClrScr;
  350. GotoXY(Crt.WhereX,Crt.WhereY);
  351. end;
  352. procedure TCrtConsole.ClrEol;
  353. begin
  354. Crt.ClrEol;
  355. GotoXY(Crt.WhereX,Crt.WhereY);
  356. end;
  357. procedure TCrtConsole.WriteChar(C: char);
  358. {var OK: boolean;}
  359. begin
  360. { OK:=((C>=#32) and (WhereX<Size.X)) or (C<#32);
  361. if OK then
  362. begin}
  363. System.Write(C);
  364. GotoXY(Crt.WhereX,Crt.WhereY);
  365. { end
  366. else Inc(CurPos.X);}
  367. end;
  368. procedure TCrtConsole.DelLine(LineCount: integer);
  369. var I: integer;
  370. begin
  371. for I:=1 to LineCount do Crt.DelLine;
  372. end;
  373. procedure TCrtConsole.InsLine(LineCount: integer);
  374. var I: integer;
  375. begin
  376. for I:=1 to LineCount do Crt.InsLine;
  377. end;
  378. procedure TCrtConsole.UpdateCursor;
  379. begin
  380. Crt.GotoXY(CurPos.X,CurPos.Y);
  381. end;
  382. procedure TCrtConsole.TextBackground(Color: byte);
  383. begin
  384. inherited TextBackground(Color);
  385. Crt.TextAttr:=TextAttr;
  386. end;
  387. procedure TCrtConsole.TextColor(Color: byte);
  388. begin
  389. inherited TextColor(Color);
  390. Crt.TextAttr:=TextAttr;
  391. end;
  392. constructor TANSIConsole.Init(AReplyHook, AKeyHook, AWriteHook: PHookProc);
  393. begin
  394. inherited Init(AReplyHook, AKeyHook, AWriteHook);
  395. BoundChecks:=bc_MaxX;
  396. ANSIParam:=''; ANSILevel:=0; ANSICurPosStackPtr:=0;
  397. end;
  398. procedure TANSIConsole.ProcessChar(C: char);
  399. var SkipThis : boolean;
  400. ANSIDone : boolean;
  401. X,Y,Z : integer;
  402. begin
  403. SkipThis:=false;
  404. if C=Esc then begin ANSILevel:=1; SkipThis:=true; end else
  405. if (ANSILevel=1) then
  406. begin
  407. ANSILevel:=0;
  408. case C of
  409. '[' : begin ANSILevel:=2; SkipThis:=true; end;
  410. end;
  411. end;
  412. if SkipThis=false then
  413. if (ANSILevel=2)
  414. then begin
  415. ANSIDone:=true;
  416. case C of
  417. 'H','f' : if ANSIParam='' then GotoXY(1,1) else
  418. begin
  419. X:=WhereX; Y:=WhereY;
  420. Z:=Pos(';',ANSIParam);
  421. if Z=0
  422. then Y:=GetANSIParam
  423. else if Z=1 then X:=GetANSIParam
  424. else begin Y:=GetANSIParam; X:=GetANSIParam; end;
  425. GotoXY(X,Y);
  426. end;
  427. 'A' : if ANSIParam='' then CursorUp(1)
  428. else CursorUp(GetANSIParam);
  429. 'B' : if ANSIParam='' then CursorDown(1)
  430. else CursorDown(GetANSIParam);
  431. 'C' : if ANSIParam='' then CursorForward(1)
  432. else CursorForward(GetANSIParam);
  433. 'D' : if ANSIParam='' then CursorBack(1)
  434. else CursorBack(GetANSIParam);
  435. 's' : if ANSIParam='' then PushCurPos;
  436. 'u' : if ANSIParam='' then PopCurPos;
  437. 'J' : if ANSIParam='2' then begin ANSIParam:=''; ClrScr; end
  438. else FillScreen(GetANSIParam);
  439. 'K' : if ANSIParam='' then ClrEol;
  440. 'L' : if ANSIParam='' then InsLine(1)
  441. else InsLine(GetANSIParam);
  442. 'M' : if ANSIParam='' then DelLine(1)
  443. else DelLine(GetANSIParam);
  444. 'm' : while ANSIParam<>'' do SetAttr(GetANSIParam);
  445. else begin ANSIParam:=ANSIParam+C; ANSIDone:=false; end;
  446. end;
  447. if ANSIDone then
  448. begin
  449. {$IFDEF DEBUG}
  450. if ANSIParam<>'' then RunError(240);
  451. {$ENDIF}
  452. ANSIParam:=''; ANSILevel:=0;
  453. end;
  454. end
  455. else begin
  456. WriteChar(C);
  457. if C=#10 then WriteChar(#13);
  458. end;
  459. end;
  460. function TANSIConsole.GetANSIParam: integer;
  461. var P: byte;
  462. I,C: integer;
  463. begin
  464. P:=Pos(';',ANSIParam);
  465. if P=0 then P:=length(ANSIParam)+1;
  466. Val(copy(ANSIParam,1,P-1),I,C);
  467. if C<>0 then I:=0;
  468. Delete(ANSIParam,1,P);
  469. GetANSIParam:=I;
  470. end;
  471. procedure TANSIConsole.CursorUp(LineCount: integer);
  472. begin
  473. GotoXY(WhereX,WhereY-LineCount);
  474. end;
  475. procedure TANSIConsole.CursorDown(LineCount: integer);
  476. begin
  477. GotoXY(WhereX,WhereY+LineCount);
  478. end;
  479. procedure TANSIConsole.CursorForward(CharCount: integer);
  480. var X, Y: integer;
  481. begin
  482. X:=WhereX; Y:=WhereY;
  483. X:=X+CharCount;
  484. while (X>Size.X) do
  485. begin Inc(Y); Dec(X,Size.X); end;
  486. GotoXY(X,Y);
  487. end;
  488. procedure TANSIConsole.CursorBack(CharCount: integer);
  489. var X, Y: integer;
  490. begin
  491. X:=WhereX; Y:=WhereY;
  492. X:=X-CharCount;
  493. while (X<1) do begin Dec(Y); Inc(X,Size.X); end;
  494. GotoXY(X,Y);
  495. end;
  496. procedure TANSIConsole.PushCurPos;
  497. begin
  498. if ANSICurPosStackPtr=ANSICurPosStackSize then Exit;
  499. Inc(ANSICurPosStackPtr);
  500. ANSICurPosStack[ANSICurPosStackPtr].X:=WhereX;
  501. ANSICurPosStack[ANSICurPosStackPtr].Y:=WhereY;
  502. end;
  503. procedure TANSIConsole.PopCurPos;
  504. begin
  505. if ANSICurPosStackPtr=0 then Exit;
  506. GotoXY(ANSICurPosStack[ANSICurPosStackPtr].X,ANSICurPosStack[ANSICurPosStackPtr].Y);
  507. Dec(ANSICurPosStackPtr);
  508. end;
  509. procedure TANSIConsole.SetAttr(Color: integer);
  510. const ColorTab : array[0..7] of byte =
  511. (Black,Red,Green,Brown,Blue,Magenta,Cyan,LightGray);
  512. begin
  513. case Color of
  514. 0 : NormVideo;
  515. 1 : HighVideo;
  516. 5 : BlinkVideo;
  517. 7,27 : TextAttr:=(TextAttr shl 4) or (TextAttr shr 4);
  518. 8 : TextColor(TextAttr shr 4);
  519. 21,22 : LowVideo;
  520. 25 : NoBlinkVideo;
  521. 30..37 : TextColor(ColorTab[Color-30]);
  522. 40..47 : TextBackground(ColorTab[Color-40]);
  523. (* else {$IFDEF DEBUG}begin system.writeln('Unknown attr : ',Color); Halt; end{$ENDIF};*)
  524. end;
  525. end;
  526. constructor TANSIViewConsole.Init(AOwner: PANSIView);
  527. begin
  528. if AOwner=nil then Fail;
  529. inherited Init(nil,nil,nil);
  530. Owner:=AOwner;
  531. Size:=Owner^.Size;
  532. end;
  533. procedure TANSIViewConsole.CursorOn;
  534. begin
  535. Owner^.ShowCursor;
  536. end;
  537. procedure TANSIViewConsole.CursorOff;
  538. begin
  539. Owner^.HideCursor;
  540. end;
  541. procedure TANSIViewConsole.ClrScr;
  542. var X,Y: word;
  543. Pos: longint;
  544. begin
  545. GotoXY(1,1);
  546. if Owner<>nil then
  547. for X:=0 to MaxViewWidth-1 do for Y:=0 to Size.Y-1 do
  548. begin
  549. Pos:=(Owner^.Delta.Y*MaxViewWidth)+X+Y*MaxViewWidth;
  550. Owner^.Buffer[Pos]:=32+256*word(TextAttr);
  551. end;
  552. end;
  553. procedure TANSIViewConsole.ClrEol;
  554. var X,Y: word;
  555. Pos: longint;
  556. begin
  557. if Owner<>nil then
  558. begin
  559. Y:=CurPos.Y;
  560. for X:=CurPos.X to MaxViewWidth-1 do
  561. begin
  562. Pos:=(Owner^.Delta.Y*MaxViewWidth)+X+Y*MaxViewWidth;
  563. Owner^.Buffer[Pos]:=32+256*word(TextAttr);
  564. end;
  565. end;
  566. end;
  567. procedure TANSIViewConsole.WriteChar(C: char);
  568. var Pos: longint;
  569. begin
  570. case C of
  571. #8 : begin
  572. CursorBack(1);
  573. Pos:=(CurPos.Y-1)*MaxViewWidth+(WhereX-1);
  574. Owner^.Buffer[Pos]:=ord(' ')+256*word(TextAttr);
  575. end;
  576. #0..#7,#9,
  577. #11..#12,
  578. #14..#31,
  579. #32..#255
  580. : begin
  581. Pos:=(CurPos.Y-1)*MaxViewWidth+(WhereX-1);
  582. Owner^.Buffer[Pos]:=ord(C)+256*word(TextAttr);
  583. GotoXY(WhereX+1,WhereY);
  584. end;
  585. #10 :
  586. GotoXY(WhereX,WhereY+1);
  587. #13 :
  588. GotoXY(1,WhereY);
  589. else {$IFDEF DEBUG}RunError(241){$ENDIF};
  590. end;
  591. end;
  592. procedure TANSIViewConsole.DelLine(LineCount: integer);
  593. begin
  594. Abstract;
  595. end;
  596. procedure TANSIViewConsole.InsLine(LineCount: integer);
  597. begin
  598. Abstract;
  599. end;
  600. procedure TANSIViewConsole.UpdateCursor;
  601. begin
  602. if Owner<>nil then
  603. if Owner^.LockCount=0 then Owner^.SetCursor(WhereX-1,WhereY-1);
  604. end;
  605. procedure TANSIViewConsole.GotoXY(X,Y: integer);
  606. var W: word;
  607. begin
  608. if Owner<>nil then
  609. while Y>MaxVideoLine do
  610. begin
  611. Move(Owner^.Buffer[MaxViewWidth],Owner^.Buffer,SizeOf(Owner^.Buffer)-(MaxViewWidth*2));
  612. W:=(MaxViewWidth*MaxVideoLine)-1-(MaxViewWidth);
  613. FillChar(Owner^.Buffer[W],MaxViewWidth*2,0);
  614. Dec(Y);
  615. end;
  616. inherited GotoXY(X,Y);
  617. end;
  618. constructor TANSIView.Init(var Bounds: TRect; AHScrollBar, AVScrollBar:
  619. PScrollBar);
  620. begin
  621. inherited Init(Bounds,AHScrollBar,AVScrollBar);
  622. LockCount:=0; Options:=Options or ofTopSelect;
  623. GrowMode:=gfGrowHiX or gfGrowHiY;
  624. SetLimit({MaxViewWidth}80,MaxVideoLine);
  625. New(Console, Init(@Self));
  626. Console^.Size.X:=80; Console^.Size.Y:=25;
  627. Console^.ClrScr;
  628. Console^.CursorOn;
  629. end;
  630. function TANSIView.LoadFile(const FileName: string): boolean;
  631. var S: PBufStream;
  632. OK: boolean;
  633. B: array[0..1023] of char;
  634. I,FragSize: integer;
  635. begin
  636. {$I-}
  637. New(S, Init(FileName, stOpenRead, 4096));
  638. OK:=Assigned(S);
  639. while OK and (S^.Status=stOK) do
  640. begin
  641. FragSize:=Min(Sizeof(B),S^.GetSize-S^.GetPos);
  642. if FragSize=0 then Break;
  643. S^.Read(B,FragSize);
  644. OK:=(S^.Status=stOK);
  645. if OK then
  646. for I:=0 to FragSize-1 do
  647. self.Write(B[I]);
  648. end;
  649. if Assigned(S) then Dispose(S, Done); S:=nil;
  650. {$I+}
  651. LoadFile:=OK;
  652. end;
  653. procedure TANSIView.Draw;
  654. var I: integer;
  655. Pos: longint;
  656. X,Y: integer;
  657. begin
  658. if LockCount<>0 then Exit;
  659. for I:=0 to Size.Y-1 do
  660. begin
  661. Pos:=Delta.X+(Delta.Y+I)*MaxViewWidth;
  662. WriteLine(0,I,Size.X,1,Buffer[Pos]);
  663. end;
  664. if Console=nil then Exit;
  665. X:=Console^.WhereX-Delta.X; Y:=Console^.WhereY-Delta.Y;
  666. if (X<0) or (Y<0) or (X>Size.X-1) or (Y>Size.X-1)
  667. then HideCursor
  668. else begin
  669. ShowCursor;
  670. SetCursor(X-1,Y-1);
  671. end;
  672. end;
  673. procedure TANSIView.Write(S: string);
  674. begin
  675. Console^.Write(S);
  676. DrawView;
  677. end;
  678. procedure TANSIView.WriteLn(S: string);
  679. begin
  680. Console^.WriteLn(S);
  681. DrawView;
  682. end;
  683. procedure TANSIView.Lock;
  684. begin
  685. Inc(LockCount);
  686. end;
  687. procedure TANSIView.UnLock;
  688. begin
  689. Dec(LockCount);
  690. if LockCount=0 then DrawView;
  691. end;
  692. procedure TANSIView.ChangeBounds(var Bounds: TRect);
  693. begin
  694. inherited ChangeBounds(Bounds);
  695. { Console^.Size.X:=Size.X; Console^.Size.Y:=Size.Y;}
  696. end;
  697. procedure TANSIView.HandleEvent(var Event: TEvent);
  698. begin
  699. inherited HandleEvent(Event);
  700. { if Event.What=evKeyDown then
  701. begin
  702. if VScrollBar<>nil then VScrollBar^.HandleEvent(Event);
  703. if HScrollBar<>nil then HScrollBar^.HandleEvent(Event);
  704. end;}
  705. end;
  706. destructor TANSIView.Done;
  707. begin
  708. Dispose(Console, Done);
  709. inherited Done;
  710. end;
  711. constructor TANSIBackgroundConsole.Init(AOwner: PANSIBackground);
  712. begin
  713. if AOwner=nil then Fail;
  714. inherited Init(nil,nil,nil);
  715. Owner:=AOwner;
  716. Size:=Owner^.Size;
  717. end;
  718. procedure TANSIBackgroundConsole.CursorOn;
  719. begin
  720. Owner^.ShowCursor;
  721. end;
  722. procedure TANSIBackgroundConsole.CursorOff;
  723. begin
  724. Owner^.HideCursor;
  725. end;
  726. procedure TANSIBackgroundConsole.ClrScr;
  727. var X,Y: word;
  728. Pos: longint;
  729. begin
  730. GotoXY(1,1);
  731. if Owner<>nil then
  732. for X:=0 to MaxViewWidth-1 do
  733. for Y:=0 to Size.Y-1 do
  734. begin
  735. Pos:=X+Y*MaxViewWidth;
  736. Owner^.Buffer[Pos]:=32+256*word(TextAttr);
  737. end;
  738. end;
  739. procedure TANSIBackgroundConsole.ClrEol;
  740. var X,Y: word;
  741. Pos: longint;
  742. begin
  743. if Owner<>nil then
  744. begin
  745. Y:=CurPos.Y;
  746. for X:=CurPos.X to MaxViewWidth-1 do
  747. begin
  748. Pos:=X+Y*MaxViewWidth;
  749. Owner^.Buffer[Pos]:=32+256*word(TextAttr);
  750. end;
  751. end;
  752. end;
  753. procedure TANSIBackgroundConsole.WriteChar(C: char);
  754. var Pos: longint;
  755. begin
  756. case C of
  757. #8 : begin
  758. CursorBack(1);
  759. Pos:=(CurPos.Y-1)*MaxViewWidth+(WhereX-1);
  760. Owner^.Buffer[Pos]:=ord(' ')+256*word(TextAttr);
  761. end;
  762. #0..#7,#9,
  763. #11..#12,
  764. #14..#31,
  765. #32..#255
  766. : begin
  767. Pos:=(CurPos.Y-1)*MaxViewWidth+(WhereX-1);
  768. Owner^.Buffer[Pos]:=ord(C)+256*word(TextAttr);
  769. GotoXY(WhereX+1,WhereY);
  770. end;
  771. #10 :
  772. GotoXY(WhereX,WhereY+1);
  773. #13 :
  774. GotoXY(1,WhereY);
  775. else {$IFDEF DEBUG}RunError(241){$ENDIF};
  776. end;
  777. end;
  778. procedure TANSIBackgroundConsole.DelLine(LineCount: integer);
  779. begin
  780. Abstract;
  781. end;
  782. procedure TANSIBackgroundConsole.InsLine(LineCount: integer);
  783. begin
  784. Abstract;
  785. end;
  786. procedure TANSIBackgroundConsole.UpdateCursor;
  787. begin
  788. if Owner<>nil then
  789. if Owner^.LockCount=0 then Owner^.SetCursor(WhereX-1,WhereY-1);
  790. end;
  791. procedure TANSIBackgroundConsole.GotoXY(X,Y: integer);
  792. var W: word;
  793. begin
  794. if Owner<>nil then
  795. while Y>MaxVideoLine do
  796. begin
  797. Move(Owner^.Buffer[MaxViewWidth],Owner^.Buffer,SizeOf(Owner^.Buffer)-(MaxViewWidth*2));
  798. W:=(MaxViewWidth*MaxVideoLine)-1-(MaxViewWidth);
  799. FillChar(Owner^.Buffer[W],MaxViewWidth*2,0);
  800. Dec(Y);
  801. end;
  802. inherited GotoXY(X,Y);
  803. end;
  804. constructor TANSIBackground.Init(var Bounds: TRect);
  805. begin
  806. inherited Init(Bounds,' ');
  807. LockCount:=0;
  808. GrowMode:=gfGrowHiX or gfGrowHiY;
  809. New(Console, Init(@Self));
  810. Console^.Size.X:=132; Console^.Size.Y:=50;
  811. Console^.ClrScr;
  812. Console^.CursorOn;
  813. end;
  814. function TANSIBackground.LoadFile(const FileName: string): boolean;
  815. var S: PBufStream;
  816. OK: boolean;
  817. B: array[0..1023] of char;
  818. I,FragSize: integer;
  819. begin
  820. {$I-}
  821. New(S, Init(FileName, stOpenRead, 4096));
  822. OK:=Assigned(S);
  823. while OK and (S^.Status=stOK) do
  824. begin
  825. FragSize:=Min(Sizeof(B),S^.GetSize-S^.GetPos);
  826. if FragSize=0 then Break;
  827. S^.Read(B,FragSize);
  828. OK:=(S^.Status=stOK);
  829. if OK then
  830. for I:=0 to FragSize-1 do
  831. self.Write(B[I]);
  832. end;
  833. if Assigned(S) then Dispose(S, Done); S:=nil;
  834. {$I+}
  835. LoadFile:=OK;
  836. end;
  837. procedure TANSIBackground.Draw;
  838. var I: integer;
  839. Pos: longint;
  840. X,Y: integer;
  841. begin
  842. if LockCount<>0 then Exit;
  843. for I:=0 to Size.Y-1 do
  844. begin
  845. Pos:=I*MaxViewWidth;
  846. WriteLine(0,I,Size.X,1,Buffer[Pos]);
  847. end;
  848. if Console=nil then Exit;
  849. X:=Console^.WhereX; Y:=Console^.WhereY;
  850. if (X<0) or (Y<0) or (X>Size.X-1) or (Y>Size.X-1)
  851. then HideCursor
  852. else begin
  853. ShowCursor;
  854. SetCursor(X-1,Y-1);
  855. end;
  856. end;
  857. procedure TANSIBackground.Write(S: string);
  858. begin
  859. Console^.Write(S);
  860. DrawView;
  861. end;
  862. procedure TANSIBackground.WriteLn(S: string);
  863. begin
  864. Console^.WriteLn(S);
  865. DrawView;
  866. end;
  867. procedure TANSIBackground.Lock;
  868. begin
  869. Inc(LockCount);
  870. end;
  871. procedure TANSIBackground.UnLock;
  872. begin
  873. Dec(LockCount);
  874. if LockCount=0 then DrawView;
  875. end;
  876. procedure TANSIBackground.ChangeBounds(var Bounds: TRect);
  877. begin
  878. inherited ChangeBounds(Bounds);
  879. { Console^.Size.X:=Size.X; Console^.Size.Y:=Size.Y;}
  880. end;
  881. procedure TANSIBackground.HandleEvent(var Event: TEvent);
  882. begin
  883. inherited HandleEvent(Event);
  884. { if Event.What=evKeyDown then
  885. begin
  886. if VScrollBar<>nil then VScrollBar^.HandleEvent(Event);
  887. if HScrollBar<>nil then HScrollBar^.HandleEvent(Event);
  888. end;}
  889. end;
  890. destructor TANSIBackground.Done;
  891. begin
  892. Dispose(Console, Done);
  893. inherited Done;
  894. end;
  895. END.
  896. {
  897. $Log $
  898. }