video.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Video unit for linux
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit Video;
  14. interface
  15. {$i videoh.inc}
  16. implementation
  17. uses
  18. Unix, Strings, TermInfo;
  19. {$i video.inc}
  20. var
  21. LastCursorType : byte;
  22. TtyFd: Longint;
  23. Console: Boolean;
  24. {$ifdef logging}
  25. f: file;
  26. const
  27. logstart: string = '';
  28. nl: char = #10;
  29. logend: string = #10#10;
  30. {$endif logging}
  31. {$ifdef I386}
  32. {$ASMMODE ATT}
  33. {$endif I386}
  34. const
  35. can_delete_term : boolean = false;
  36. ACSIn : string = '';
  37. ACSOut : string = '';
  38. InACS : boolean =false;
  39. function IsACS(var ch,ACSchar : char): boolean;
  40. begin
  41. IsACS:=false;
  42. case ch of
  43. #24, #30: {}
  44. ch:='^';
  45. #25, #31: {}
  46. ch:='v';
  47. #26, #16: {Never introduce a ctrl-Z ... }
  48. ch:='>';
  49. {#27,needed in Escape sequences} #17: {}
  50. ch:='<';
  51. #176, #177, #178: {°±²}
  52. begin
  53. IsACS:=true;
  54. ACSChar:='a';
  55. end;
  56. #180, #181, #182, #185: {´µ¶¹}
  57. begin
  58. IsACS:=true;
  59. ACSChar:='u';
  60. end;
  61. #183, #184, #187, #191: {·¸»¿}
  62. begin
  63. IsACS:=true;
  64. ACSChar:='k';
  65. end;
  66. #188, #189, #190, #217: {¼½¾Ù}
  67. begin
  68. IsACS:=true;
  69. ACSChar:='j';
  70. end;
  71. #192, #200, #211, #212: {ÀÈÓÔ}
  72. begin
  73. IsACS:=true;
  74. ACSChar:='m';
  75. end;
  76. #193, #202, #207, #208: {ÁÊÏÐ}
  77. begin
  78. IsACS:=true;
  79. ACSChar:='v';
  80. end;
  81. #194, #203, #209, #210: {ÂËÑÒ}
  82. begin
  83. IsACS:=true;
  84. ACSChar:='w';
  85. end;
  86. #195, #198, #199, #204: {ÃÆÇÌ}
  87. begin
  88. IsACS:=true;
  89. ACSChar:='t';
  90. end;
  91. #196, #205: {ÄÍ}
  92. begin
  93. IsACS:=true;
  94. ACSChar:='q';
  95. end;
  96. #179, #186: {³º}
  97. begin
  98. IsACS:=true;
  99. ACSChar:='x';
  100. end;
  101. #197, #206, #215, #216: {ÅÎר}
  102. begin
  103. IsACS:=true;
  104. ACSChar:='n';
  105. end;
  106. #201, #213, #214, #218: {ÉÕÖÚ}
  107. begin
  108. IsACS:=true;
  109. ACSChar:='l';
  110. end;
  111. #254: { þ }
  112. begin
  113. ch:='*';
  114. end;
  115. { Shadows for Buttons }
  116. #220: { Ü }
  117. begin
  118. IsACS:=true;
  119. ACSChar:='a';
  120. end;
  121. #223: { ß }
  122. begin
  123. IsACS:=true;
  124. ACSChar:='a';
  125. end;
  126. end;
  127. end;
  128. function SendEscapeSeqNdx(Ndx: Word) : boolean;
  129. var
  130. P,pdelay: PChar;
  131. begin
  132. SendEscapeSeqNdx:=false;
  133. if not assigned(cur_term_Strings) then
  134. exit{RunError(219)};
  135. P:=cur_term_Strings^[Ndx];
  136. if assigned(p) then
  137. begin { Do not transmit the delays }
  138. pdelay:=strpos(p,'$<');
  139. if assigned(pdelay) then
  140. pdelay^:=#0;
  141. fdWrite(TTYFd, P^, StrLen(P));
  142. SendEscapeSeqNdx:=true;
  143. if assigned(pdelay) then
  144. pdelay^:='$';
  145. end;
  146. end;
  147. procedure SendEscapeSeq(const S: String);
  148. begin
  149. fdWrite(TTYFd, S[1], Length(S));
  150. end;
  151. Function IntStr(l:longint):string;
  152. var
  153. s : string;
  154. begin
  155. Str(l,s);
  156. IntStr:=s;
  157. end;
  158. Function XY2Ansi(x,y,ox,oy:longint):String;
  159. {
  160. Returns a string with the escape sequences to go to X,Y on the screen
  161. }
  162. Begin
  163. if y=oy then
  164. begin
  165. if x=ox then
  166. begin
  167. XY2Ansi:='';
  168. exit;
  169. end;
  170. if x=1 then
  171. begin
  172. XY2Ansi:=#13;
  173. exit;
  174. end;
  175. if x>ox then
  176. begin
  177. XY2Ansi:=#27'['+IntStr(x-ox)+'C';
  178. exit;
  179. end
  180. else
  181. begin
  182. XY2Ansi:=#27'['+IntStr(ox-x)+'D';
  183. exit;
  184. end;
  185. end;
  186. if x=ox then
  187. begin
  188. if y>oy then
  189. begin
  190. XY2Ansi:=#27'['+IntStr(y-oy)+'B';
  191. exit;
  192. end
  193. else
  194. begin
  195. XY2Ansi:=#27'['+IntStr(oy-y)+'A';
  196. exit;
  197. end;
  198. end;
  199. if (x=1) and (oy+1=y) then
  200. XY2Ansi:=#13#10
  201. else
  202. XY2Ansi:=#27'['+IntStr(y)+';'+IntStr(x)+'H';
  203. End;
  204. const
  205. AnsiTbl : string[8]='04261537';
  206. Function Attr2Ansi(Attr,OAttr:longint):string;
  207. {
  208. Convert Attr to an Ansi String, the Optimal code is calculate
  209. with use of the old OAttr
  210. }
  211. var
  212. hstr : string[16];
  213. OFg,OBg,Fg,Bg : longint;
  214. procedure AddSep(ch:char);
  215. begin
  216. if length(hstr)>0 then
  217. hstr:=hstr+';';
  218. hstr:=hstr+ch;
  219. end;
  220. begin
  221. if Attr=OAttr then
  222. begin
  223. Attr2Ansi:='';
  224. exit;
  225. end;
  226. Hstr:='';
  227. Fg:=Attr and $f;
  228. Bg:=Attr shr 4;
  229. OFg:=OAttr and $f;
  230. OBg:=OAttr shr 4;
  231. if (OFg<>7) or (Fg=7) or ((OFg>7) and (Fg<8)) or ((OBg>7) and (Bg<8)) then
  232. begin
  233. hstr:='0';
  234. OFg:=7;
  235. OBg:=0;
  236. end;
  237. if (Fg>7) and (OFg<8) then
  238. begin
  239. AddSep('1');
  240. OFg:=OFg or 8;
  241. end;
  242. if (Bg and 8)<>(OBg and 8) then
  243. begin
  244. AddSep('5');
  245. OBg:=OBg or 8;
  246. end;
  247. if (Fg<>OFg) then
  248. begin
  249. AddSep('3');
  250. hstr:=hstr+AnsiTbl[(Fg and 7)+1];
  251. end;
  252. if (Bg<>OBg) then
  253. begin
  254. AddSep('4');
  255. hstr:=hstr+AnsiTbl[(Bg and 7)+1];
  256. end;
  257. if hstr='0' then
  258. hstr:='';
  259. Attr2Ansi:=#27'['+hstr+'m';
  260. end;
  261. procedure UpdateTTY(Force:boolean);
  262. type
  263. tchattr=packed record
  264. {$ifdef ENDIAN_LITTLE}
  265. ch : char;
  266. attr : byte;
  267. {$else}
  268. attr : byte;
  269. ch : char;
  270. {$endif}
  271. end;
  272. var
  273. outbuf : array[0..1023+255] of char;
  274. chattr : tchattr;
  275. skipped : boolean;
  276. outptr,
  277. spaces,
  278. eol,
  279. x,y,
  280. LastX,LastY,
  281. SpaceAttr,
  282. LastAttr : longint;
  283. p,pold : pvideocell;
  284. procedure TransformUsingACS(var st : string);
  285. var
  286. res : string;
  287. i : longint;
  288. ch,ACSch : char;
  289. begin
  290. res:='';
  291. for i:=1 to length(st) do
  292. begin
  293. ch:=st[i];
  294. if IsACS(ch,ACSch) then
  295. begin
  296. if not InACS then
  297. begin
  298. res:=res+ACSIn;
  299. InACS:=true;
  300. end;
  301. res:=res+ACSch;
  302. end
  303. else
  304. begin
  305. if InACS then
  306. begin
  307. res:=res+ACSOut+Attr2Ansi(LastAttr,0);
  308. InACS:=false;
  309. end;
  310. res:=res+ch;
  311. end;
  312. end;
  313. st:=res;
  314. end;
  315. procedure outdata(hstr:string);
  316. begin
  317. while (eol>0) do
  318. begin
  319. hstr:=#13#10+hstr;
  320. dec(eol);
  321. end;
  322. if NoExtendedFrame and (ACSIn<>'') and (ACSOut<>'') then
  323. TransformUsingACS(Hstr);
  324. move(hstr[1],outbuf[outptr],length(hstr));
  325. inc(outptr,length(hstr));
  326. if outptr>=1024 then
  327. begin
  328. {$ifdef logging}
  329. blockwrite(f,logstart[1],length(logstart));
  330. blockwrite(f,nl,1);
  331. blockwrite(f,outptr,sizeof(outptr));
  332. blockwrite(f,nl,1);
  333. blockwrite(f,outbuf,outptr);
  334. blockwrite(f,nl,1);
  335. {$endif logging}
  336. fdWrite(TTYFd,outbuf,outptr);
  337. outptr:=0;
  338. end;
  339. end;
  340. procedure OutClr(c:byte);
  341. begin
  342. if c=LastAttr then
  343. exit;
  344. OutData(Attr2Ansi(c,LastAttr));
  345. LastAttr:=c;
  346. end;
  347. procedure OutSpaces;
  348. begin
  349. if (Spaces=0) then
  350. exit;
  351. OutClr(SpaceAttr);
  352. OutData(Space(Spaces));
  353. LastX:=x;
  354. LastY:=y;
  355. Spaces:=0;
  356. end;
  357. begin
  358. OutPtr:=0;
  359. Eol:=0;
  360. skipped:=true;
  361. p:=PVideoCell(VideoBuf);
  362. pold:=PVideoCell(OldVideoBuf);
  363. { init Attr, X,Y and set autowrap off }
  364. SendEscapeSeq(#27'[m'#27'[?7l'{#27'[H'} );
  365. LastAttr:=7;
  366. LastX:=-1;
  367. LastY:=-1;
  368. for y:=1 to ScreenHeight do
  369. begin
  370. SpaceAttr:=0;
  371. Spaces:=0;
  372. for x:=1 to ScreenWidth do
  373. begin
  374. if (not force) and (p^=pold^) then
  375. begin
  376. if (Spaces>0) then
  377. OutSpaces;
  378. skipped:=true;
  379. end
  380. else
  381. begin
  382. if skipped then
  383. begin
  384. OutData(XY2Ansi(x,y,LastX,LastY));
  385. LastX:=x;
  386. LastY:=y;
  387. skipped:=false;
  388. end;
  389. chattr:=tchattr(p^);
  390. if chattr.ch in [#0,#255] then
  391. chattr.ch:=' ';
  392. if chattr.ch=' ' then
  393. begin
  394. if Spaces=0 then
  395. SpaceAttr:=chattr.Attr;
  396. if (chattr.attr and $f0)=(spaceattr and $f0) then
  397. chattr.Attr:=SpaceAttr
  398. else
  399. begin
  400. OutSpaces;
  401. SpaceAttr:=chattr.Attr;
  402. end;
  403. inc(Spaces);
  404. end
  405. else
  406. begin
  407. if (Spaces>0) then
  408. OutSpaces;
  409. if ord(chattr.ch)<32 then
  410. begin
  411. Chattr.Attr:= $ff xor Chattr.Attr;
  412. ChAttr.ch:= chr(ord(chattr.ch)+ord('A')-1);
  413. end;
  414. if LastAttr<>chattr.Attr then
  415. OutClr(chattr.Attr);
  416. OutData(chattr.ch);
  417. LastX:=x+1;
  418. LastY:=y;
  419. end;
  420. p^:=tvideocell(chattr);
  421. end;
  422. inc(p);
  423. inc(pold);
  424. end;
  425. if (Spaces>0) then
  426. OutSpaces;
  427. if force then
  428. inc(eol)
  429. else
  430. skipped:=true;
  431. end;
  432. eol:=0;
  433. OutData(XY2Ansi(CursorX,CursorY,LastX,LastY));
  434. {$ifdef logging}
  435. blockwrite(f,logstart[1],length(logstart));
  436. blockwrite(f,nl,1);
  437. blockwrite(f,outptr,sizeof(outptr));
  438. blockwrite(f,nl,1);
  439. blockwrite(f,outbuf,outptr);
  440. blockwrite(f,nl,1);
  441. {$endif logging}
  442. fdWrite(TTYFd,outbuf,outptr);
  443. if InACS then
  444. SendEscapeSeqNdx(exit_alt_charset_mode);
  445. {turn autowrap on}
  446. SendEscapeSeq(#27'[?7h');
  447. end;
  448. var
  449. InitialVideoTio, preInitVideoTio, postInitVideoTio: Unix.termios;
  450. inputRaw, outputRaw: boolean;
  451. procedure saveRawSettings(const tio: Unix.termios);
  452. Begin
  453. with tio do
  454. begin
  455. inputRaw :=
  456. ((c_iflag and (IGNBRK or BRKINT or PARMRK or ISTRIP or
  457. INLCR or IGNCR or ICRNL or IXON)) = 0) and
  458. ((c_lflag and (ECHO or ECHONL or ICANON or ISIG or IEXTEN)) = 0);
  459. outPutRaw :=
  460. ((c_oflag and OPOST) = 0) and
  461. ((c_cflag and (CSIZE or PARENB)) = 0) and
  462. ((c_cflag and CS8) <> 0);
  463. end;
  464. end;
  465. procedure restoreRawSettings(tio: Unix.termios);
  466. begin
  467. with tio do
  468. begin
  469. if inputRaw then
  470. begin
  471. c_iflag := c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
  472. INLCR or IGNCR or ICRNL or IXON));
  473. c_lflag := c_lflag and
  474. (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
  475. end;
  476. if outPutRaw then
  477. begin
  478. c_oflag := c_oflag and not(OPOST);
  479. c_cflag := c_cflag and not(CSIZE or PARENB) or CS8;
  480. end;
  481. end;
  482. TCSetAttr(1,TCSANOW,tio);
  483. end;
  484. procedure TargetEntry;
  485. begin
  486. TCGetAttr(1,InitialVideoTio);
  487. end;
  488. procedure TargetExit;
  489. begin
  490. TCSetAttr(1,TCSANOW,InitialVideoTio);
  491. end;
  492. procedure prepareInitVideo;
  493. begin
  494. TCGetAttr(1,preInitVideoTio);
  495. saveRawSettings(preInitVideoTio);
  496. end;
  497. procedure videoInitDone;
  498. begin
  499. TCGetAttr(1,postInitVideoTio);
  500. restoreRawSettings(postInitVideoTio);
  501. end;
  502. procedure prepareDoneVideo;
  503. var
  504. tio: Unix.termios;
  505. begin
  506. TCGetAttr(1,tio);
  507. saveRawSettings(tio);
  508. TCSetAttr(1,TCSANOW,postInitVideoTio);
  509. end;
  510. procedure doneVideoDone;
  511. begin
  512. restoreRawSettings(preInitVideoTio);
  513. end;
  514. procedure SysInitVideo;
  515. const
  516. fontstr : string[3]=#27'(K';
  517. var
  518. ThisTTY: String[30];
  519. FName: String;
  520. WS: packed record
  521. ws_row, ws_col, ws_xpixel, ws_ypixel: Word;
  522. end;
  523. Err: Longint;
  524. prev_term : TerminalCommon_ptr1;
  525. begin
  526. {$ifndef CPUI386}
  527. LowAscii:=false;
  528. {$endif CPUI386}
  529. { check for tty }
  530. ThisTTY:=TTYName(stdinputhandle);
  531. if IsATTY(stdinputhandle) then
  532. begin
  533. { save current terminal characteristics and remove rawness }
  534. prepareInitVideo;
  535. { write code to set a correct font }
  536. fdWrite(stdoutputhandle,fontstr[1],length(fontstr));
  537. { running on a tty, find out whether locally or remotely }
  538. if (Copy(ThisTTY, 1, 8) = '/dev/tty') and
  539. (ThisTTY[9] >= '0') and (ThisTTY[9] <= '9') then
  540. begin
  541. { running on the console }
  542. FName:='/dev/vcsa' + ThisTTY[9];
  543. TTYFd:=fdOpen(FName, Octal(666), Open_RdWr); { open console }
  544. end
  545. else
  546. TTYFd:=-1;
  547. if TTYFd<>-1 then
  548. Console:=true
  549. else
  550. begin
  551. { running on a remote terminal, no error with /dev/vcsa }
  552. Console:=False;
  553. LowAscii:=false;
  554. TTYFd:=stdoutputhandle;
  555. end;
  556. ioctl(stdinputhandle, TIOCGWINSZ, @WS);
  557. if WS.ws_Col=0 then
  558. WS.ws_Col:=80;
  559. if WS.ws_Row=0 then
  560. WS.ws_Row:=25;
  561. ScreenWidth:=WS.ws_Col;
  562. { TDrawBuffer only has FVMaxWidth elements
  563. larger values lead to crashes }
  564. if ScreenWidth> FVMaxWidth then
  565. ScreenWidth:=FVMaxWidth;
  566. ScreenHeight:=WS.ws_Row;
  567. CursorX:=1;
  568. CursorY:=1;
  569. ScreenColor:=True;
  570. { Start with a clear screen }
  571. if not Console then
  572. begin
  573. prev_term:=cur_term;
  574. setupterm(nil, stdoutputhandle, err);
  575. can_delete_term:=assigned(prev_term) and (prev_term<>cur_term);
  576. SendEscapeSeqNdx(cursor_home);
  577. SendEscapeSeqNdx(cursor_normal);
  578. SendEscapeSeqNdx(cursor_visible);
  579. SendEscapeSeqNdx(enter_ca_mode);
  580. SetCursorType(crUnderLine);
  581. end
  582. else if not assigned(cur_term) then
  583. begin
  584. setupterm(nil, stdoutputhandle, err);
  585. can_delete_term:=false;
  586. end;
  587. if assigned(cur_term_Strings) then
  588. begin
  589. ACSIn:=StrPas(cur_term_Strings^[enter_alt_charset_mode]);
  590. ACSOut:=StrPas(cur_term_Strings^[exit_alt_charset_mode]);
  591. if (ACSIn<>'') and (ACSOut<>'') then
  592. SendEscapeSeqNdx(ena_acs);
  593. if pos('$<',ACSIn)>0 then
  594. ACSIn:=Copy(ACSIn,1,Pos('$<',ACSIn)-1);
  595. if pos('$<',ACSOut)>0 then
  596. ACSOut:=Copy(ACSOut,1,Pos('$<',ACSOut)-1);
  597. end
  598. else
  599. begin
  600. ACSIn:='';
  601. ACSOut:='';
  602. end;
  603. {$ifdef logging}
  604. assign(f,'video.log');
  605. rewrite(f,1);
  606. {$endif logging}
  607. { save new terminal characteristics and possible restore rawness }
  608. videoInitDone;
  609. end
  610. else
  611. ErrorCode:=errVioInit; { not a TTY }
  612. end;
  613. procedure SysDoneVideo;
  614. begin
  615. prepareDoneVideo;
  616. if Console then
  617. SetCursorPos(1,1)
  618. else
  619. begin
  620. SendEscapeSeqNdx(exit_ca_mode);
  621. SendEscapeSeqNdx(cursor_home);
  622. SendEscapeSeqNdx(cursor_normal);
  623. SendEscapeSeqNdx(cursor_visible);
  624. SetCursorType(crUnderLine);
  625. SendEscapeSeq(#27'[H');
  626. end;
  627. ACSIn:='';
  628. ACSOut:='';
  629. doneVideoDone;
  630. if can_delete_term then
  631. begin
  632. del_curterm(cur_term);
  633. can_delete_term:=false;
  634. end;
  635. {$ifdef logging}
  636. close(f);
  637. {$endif logging}
  638. end;
  639. procedure SysClearScreen;
  640. begin
  641. if Console then
  642. UpdateScreen(true)
  643. else
  644. begin
  645. SendEscapeSeq(#27'[0m');
  646. SendEscapeSeqNdx(clear_screen);
  647. end;
  648. end;
  649. procedure SysUpdateScreen(Force: Boolean);
  650. var
  651. DoUpdate : boolean;
  652. i : longint;
  653. p1,p2 : plongint;
  654. begin
  655. if not force then
  656. begin
  657. {$ifdef i386}
  658. asm
  659. movl VideoBuf,%esi
  660. movl OldVideoBuf,%edi
  661. movl VideoBufSize,%ecx
  662. shrl $2,%ecx
  663. repe
  664. cmpsl
  665. setne DoUpdate
  666. end;
  667. {$else not i386}
  668. p1:=plongint(VideoBuf);
  669. p2:=plongint(OldVideoBuf);
  670. for i:=0 to VideoBufSize div 2 do
  671. if (p1^<>p2^) then
  672. begin
  673. DoUpdate:=true;
  674. break;
  675. end
  676. else
  677. begin
  678. { Inc does add sizeof(longint) to both pointer values }
  679. inc(p1);
  680. inc(p2);
  681. end;
  682. {$endif not i386}
  683. end
  684. else
  685. DoUpdate:=true;
  686. if not DoUpdate then
  687. exit;
  688. if Console then
  689. begin
  690. fdSeek(TTYFd, 4, Seek_Set);
  691. fdWrite(TTYFd, VideoBuf^,VideoBufSize);
  692. end
  693. else
  694. begin
  695. UpdateTTY(force);
  696. end;
  697. Move(VideoBuf^, OldVideoBuf^, VideoBufSize);
  698. end;
  699. function SysGetCapabilities: Word;
  700. begin
  701. { about cpColor... we should check the terminfo database... }
  702. SysGetCapabilities:=cpUnderLine + cpBlink + cpColor;
  703. end;
  704. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  705. var
  706. Pos : array [1..2] of Byte;
  707. begin
  708. if Console then
  709. begin
  710. fdSeek(TTYFd, 2, Seek_Set);
  711. Pos[1]:=NewCursorX;
  712. Pos[2]:=NewCursorY;
  713. fdWrite(TTYFd, Pos, 2);
  714. end
  715. else
  716. begin
  717. { newcursorx,y is 0 based ! }
  718. SendEscapeSeq(XY2Ansi(NewCursorX+1,NewCursorY+1,0,0));
  719. end;
  720. CursorX:=NewCursorX+1;
  721. CursorY:=NewCursorY+1;
  722. end;
  723. function SysGetCursorType: Word;
  724. begin
  725. SysGetCursorType:=LastCursorType;
  726. end;
  727. procedure SysSetCursorType(NewType: Word);
  728. begin
  729. LastCursorType:=NewType;
  730. case NewType of
  731. crBlock :
  732. Begin
  733. If not SendEscapeSeqNdx(cursor_visible) then
  734. SendEscapeSeq(#27'[?17;0;64c');
  735. End;
  736. crHidden :
  737. Begin
  738. If not SendEscapeSeqNdx(cursor_invisible) then
  739. SendEscapeSeq(#27'[?1c');
  740. End;
  741. else
  742. begin
  743. If not SendEscapeSeqNdx(cursor_normal) then
  744. SendEscapeSeq(#27'[?2c');
  745. end;
  746. end;
  747. end;
  748. Const
  749. SysVideoDriver : TVideoDriver = (
  750. InitDriver : @SysInitVideo;
  751. DoneDriver : @SysDoneVideo;
  752. UpdateScreen : @SysUpdateScreen;
  753. ClearScreen : @SysClearScreen;
  754. SetVideoMode : Nil;
  755. GetVideoModeCount : Nil;
  756. GetVideoModeData : Nil;
  757. SetCursorPos : @SysSetCursorPos;
  758. GetCursorType : @SysGetCursorType;
  759. SetCursorType : @SysSetCursorType;
  760. GetCapabilities : @SysGetCapabilities;
  761. );
  762. initialization
  763. SetVideoDriver(SysVideoDriver);
  764. end.
  765. {
  766. $Log$
  767. Revision 1.13 2003-03-26 12:45:21 armin
  768. * added wrapoff to avoid problems in the ide with some terminal emulators
  769. Revision 1.12 2002/09/07 16:01:28 peter
  770. * old logs removed and tabs fixed
  771. Revision 1.11 2002/07/06 16:50:17 marco
  772. * Fix for corrupt color-attr after some ACS-mode changes. (Pierre, Strassbourg
  773. meeting)
  774. }