wansi.pas 27 KB

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