wansi.pas 27 KB

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