wansi.pas 26 KB

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