video.pp 17 KB

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