wansi.pas 27 KB

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