video.pp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Video unit for linux
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit video;
  13. {$I-}
  14. {$GOTO on}
  15. {*****************************************************************************}
  16. interface
  17. {*****************************************************************************}
  18. {$i videoh.inc}
  19. type Tencoding=(cp437, {Codepage 437}
  20. cp850, {Codepage 850}
  21. cp852, {Codepage 852}
  22. cp866, {Codepage 866}
  23. koi8r, {KOI8-R codepage}
  24. iso01, {ISO 8859-1}
  25. iso02, {ISO 8859-2}
  26. iso03, {ISO 8859-3}
  27. iso04, {ISO 8859-4}
  28. iso05, {ISO 8859-5}
  29. iso06, {ISO 8859-6}
  30. iso07, {ISO 8859-7}
  31. iso08, {ISO 8859-8}
  32. iso09, {ISO 8859-9}
  33. iso10, {ISO 8859-10}
  34. iso13, {ISO 8859-13}
  35. iso14, {ISO 8859-14}
  36. iso15, {ISO 8859-15}
  37. utf8); {UTF-8}
  38. const {Contains all code pages that can be considered a normal vga font.
  39. Note: KOI8-R has line drawing characters in wrong place. Support
  40. can perhaps be added, for now we'll let it rest.}
  41. vga_codepages=[cp437,cp850,cp852,cp866];
  42. iso_codepages=[iso01,iso02,iso03,iso04,iso05,iso06,iso07,iso08,
  43. iso09,iso10,iso13,iso14,iso15];
  44. var internal_codepage,external_codepage:Tencoding;
  45. {*****************************************************************************}
  46. implementation
  47. {*****************************************************************************}
  48. uses baseunix,termio,strings
  49. {$ifdef linux},linuxvcs{$endif};
  50. {$i video.inc}
  51. {$i convert.inc}
  52. type Tconsole_type=(ttyNetwork
  53. {$ifdef linux},ttyLinux{$endif}
  54. ,ttyFreeBSD
  55. ,ttyNetBSD);
  56. Tconversion=(cv_none,
  57. cv_cp437_to_iso01,
  58. cv_cp850_to_iso01,
  59. cv_linuxlowascii_to_vga,
  60. cv_cp437_to_UTF8);
  61. Ttermcode=(
  62. enter_alt_charset_mode,
  63. exit_alt_charset_mode,
  64. clear_screen,
  65. cursor_home,
  66. cursor_normal,
  67. cursor_visible_underline,
  68. cursor_visible_block,
  69. cursor_invisible,
  70. enter_ca_mode,
  71. exit_ca_mode,
  72. exit_am_mode,
  73. ena_acs
  74. );
  75. Ttermcodes=array[Ttermcode] of Pchar;
  76. Ptermcodes=^Ttermcodes;
  77. const term_codes_ansi:Ttermcodes=
  78. (#$1B#$5B#$31#$31#$6D, {enter_alt_charset_mode}
  79. #$1B#$5B#$31#$30#$6D, {exit_alt_charset_mode}
  80. #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
  81. #$1B#$5B#$48, {cursor_home}
  82. nil, {cursor_normal}
  83. nil, {cursor visible, underline}
  84. nil, {cursor visible, block}
  85. nil, {cursor_invisible}
  86. nil, {enter_ca_mode}
  87. nil, {exit_ca_mode}
  88. nil, {exit_am_mode}
  89. nil); {ena_acs}
  90. term_codes_freebsd:Ttermcodes=
  91. (nil, {enter_alt_charset_mode}
  92. nil, {exit_alt_charset_mode}
  93. #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
  94. #$1B#$5B#$48, {cursor_home}
  95. #$1B#$5B#$3D#$30#$43, {cursor_normal}
  96. #$1B#$5B#$3D#$31#$43, {cursor visible, underline}
  97. #$1B#$5B#$3D#$31#$43, {cursor visible, block}
  98. nil, {cursor_invisible}
  99. nil, {enter_ca_mode}
  100. nil, {exit_ca_mode}
  101. nil, {exit_am_mode}
  102. nil); {ena_acs}
  103. term_codes_linux:Ttermcodes=
  104. (#$1B#$5B#$31#$31#$6D, {enter_alt_charset_mode}
  105. #$1B#$5B#$31#$30#$6D, {exit_alt_charset_mode}
  106. #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
  107. #$1B#$5B#$48, {cursor_home}
  108. #$1B'[?25h'#$1B'[?0c', {cursor_normal}
  109. #$1B'[?0c', {cursor visible, underline}
  110. #$1B'[?17;0;127c', {cursor visible, block}
  111. #$1B'[?1c', {cursor_invisible}
  112. nil, {enter_ca_mode}
  113. nil, {exit_ca_mode}
  114. nil, {exit_am_mode}
  115. nil); {ena_acs}
  116. term_codes_vt100:Ttermcodes=
  117. (#$0E, {enter_alt_charset_mode}
  118. #$0F, {exit_alt_charset_mode}
  119. #$1B#$5B#$48#$1B#$5B#$4A{#$24#$3C#$35#$30#$3E}, {clear_screen}
  120. #$1B#$5B#$48, {cursor_home}
  121. nil, {cursor_normal}
  122. nil, {cursor visible, underline}
  123. nil, {cursor visible, block}
  124. nil, {cursor_invisible}
  125. nil, {enter_ca_mode}
  126. nil, {exit_ca_mode}
  127. #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
  128. #$1B#$28#$42#$1B#$29#$30); {ena_acs}
  129. term_codes_vt220:Ttermcodes=
  130. (#$1B#$28#$30{#$24#$3C#$32#$3E}, {enter_alt_charset_mode}
  131. #$1B#$28#$42{#$24#$3C#$34#$3E}, {exit_alt_charset_mode}
  132. #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
  133. #$1B#$5B#$48, {cursor_home}
  134. nil, {cursor_normal}
  135. nil, {cursor visible, underline}
  136. nil, {cursor visible, block}
  137. nil, {cursor_invisible}
  138. nil, {enter_ca_mode}
  139. nil, {exit_ca_mode}
  140. #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
  141. #$1B#$29#$30); {ena_acs}
  142. term_codes_xterm:Ttermcodes=
  143. (#$0E, {enter_alt_charset_mode}
  144. #$0F, {exit_alt_charset_mode}
  145. #$1B#$5B#$48#$1B#$5B#$32#$4A, {clear_screen}
  146. #$1B#$5B#$48, {cursor_home}
  147. #$1B#$5B#$3F#$31#$32#$6C#$1B#$5B#$3F#$32#$35#$68, {cursor_normal}
  148. #$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, underline}
  149. #$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, block}
  150. #$1B#$5B#$3F#$32#$35#$6C, {cursor_invisible}
  151. #$1B#$5B#$3F#$31#$30#$34#$39#$68, {enter_ca_mode}
  152. #$1B#$5B#$3F#$31#$30#$34#$39#$6C, {exit_ca_mode}
  153. #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
  154. #$1B#$28#$42#$1B#$29#$30); {ena_acs}
  155. term_codes_beos:Ttermcodes=
  156. (nil,//#$0E, {enter_alt_charset_mode}
  157. nil,//#$0F, {exit_alt_charset_mode}
  158. #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
  159. #$1B#$5B#$48, {cursor_home}
  160. #$1B'[?25h',// nil,//#$1B#$5B#$3F#$31#$32#$6C#$1B#$5B#$3F#$32#$35#$68, {cursor_normal}
  161. nil,//#$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, underline}
  162. nil,//#$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, block}
  163. #$1B'[?25l',//nil,//#$1B#$5B#$3F#$32#$35#$6C, {cursor_invisible}
  164. nil,//#$1B#$5B#$3F#$31#$30#$34#$39#$68, {enter_ca_mode}
  165. nil,//#$1B#$5B#$3F#$31#$30#$34#$39#$6C, {exit_ca_mode}
  166. nil,//#$1B#$5B#$3F#$37#$6C, {exit_am_mode}
  167. nil);//#$1B#$28#$42#$1B#$29#$30); {ena_acs}
  168. const terminal_names:array[0..11] of string[7]=(
  169. 'ansi',
  170. 'cons',
  171. 'eterm',
  172. 'gnome',
  173. 'konsole',
  174. 'linux',
  175. 'rxvt',
  176. 'screen',
  177. 'vt100',
  178. 'vt220',
  179. 'xterm',
  180. 'beterm');
  181. terminal_data:array[0..11] of Ptermcodes=(
  182. @term_codes_ansi,
  183. @term_codes_freebsd,
  184. @term_codes_xterm,
  185. @term_codes_xterm,
  186. @term_codes_xterm,
  187. @term_codes_linux,
  188. @term_codes_xterm,
  189. @term_codes_xterm,
  190. @term_codes_vt100,
  191. @term_codes_vt220,
  192. @term_codes_xterm,
  193. @term_codes_beos);
  194. const convert:Tconversion=cv_none;
  195. var
  196. LastCursorType : byte;
  197. {$ifdef linux}
  198. TtyFd: Longint;
  199. {$endif linux}
  200. Console: Tconsole_type;
  201. cur_term_strings:Ptermcodes;
  202. {$ifdef logging}
  203. f: file;
  204. const
  205. logstart: string = '';
  206. nl: char = #10;
  207. logend: string = #10#10;
  208. {$endif logging}
  209. {$ifdef cpui386}
  210. {$ASMMODE ATT}
  211. {$endif cpui386}
  212. const
  213. { can_delete_term : boolean = false;}
  214. ACSIn : string = '';
  215. ACSOut : string = '';
  216. in_ACS : boolean =false;
  217. TerminalSupportsHighIntensityColors: boolean = false;
  218. TerminalSupportsBold: boolean = true;
  219. function convert_vga_to_acs(ch:char):word;
  220. {Ch contains a character in the VGA character set (i.e. codepage 437).
  221. This routine tries to convert some VGA symbols as well as possible to the
  222. xterm alternate character set.
  223. Return type is word to allow expanding to UCS-2 characters in the
  224. future.}
  225. begin
  226. case ch of
  227. #18:
  228. convert_vga_to_acs:=word('|');
  229. #24, #30: {}
  230. convert_vga_to_acs:=word('^');
  231. #25, #31: {}
  232. convert_vga_to_acs:=word('v');
  233. #26, #16: {Never introduce a ctrl-Z ... }
  234. convert_vga_to_acs:=word('>');
  235. {#27,} #17: {}
  236. convert_vga_to_acs:=word('<');
  237. #176, #177, #178: {°±²}
  238. convert_vga_to_acs:=$f800+word('a');
  239. #180, #181, #182, #185: {´µ¶¹}
  240. convert_vga_to_acs:=$f800+word('u');
  241. #183, #184, #187, #191: {·¸»¿}
  242. convert_vga_to_acs:=$f800+word('k');
  243. #188, #189, #190, #217: {¼½¾Ù}
  244. convert_vga_to_acs:=$f800+word('j');
  245. #192, #200, #211, #212: {ÀÈÓÔ}
  246. convert_vga_to_acs:=$f800+word('m');
  247. #193, #202, #207, #208: {ÁÊÏÐ}
  248. convert_vga_to_acs:=$f800+word('v');
  249. #194, #203, #209, #210: {ÂËÑÒ}
  250. convert_vga_to_acs:=$f800+word('w');
  251. #195, #198, #199, #204: {ÃÆÇÌ}
  252. convert_vga_to_acs:=$f800+word('t');
  253. #196, #205: {ÄÍ}
  254. convert_vga_to_acs:=$f800+word('q');
  255. #179, #186: {³º}
  256. convert_vga_to_acs:=$f800+word('x');
  257. #197, #206, #215, #216: {ÅÎר}
  258. convert_vga_to_acs:=$f800+word('n');
  259. #201, #213, #214, #218: {ÉÕÖÚ}
  260. convert_vga_to_acs:=$f800+word('l');
  261. #254: { þ }
  262. convert_vga_to_acs:=word('*');
  263. { Shadows for Buttons }
  264. #220 { Ü },
  265. #223: { ß }
  266. convert_vga_to_acs:=$f800+word('a');
  267. else
  268. convert_vga_to_acs:=word(ch);
  269. end;
  270. end;
  271. procedure SendEscapeSeqNdx(ndx:Ttermcode);
  272. var p:PChar;
  273. begin
  274. { Always true because of vt100 default.
  275. if not assigned(cur_term_Strings) then
  276. exit}{RunError(219)};
  277. p:=cur_term_strings^[ndx];
  278. if p<>nil then
  279. fpwrite(stdoutputhandle,p^,strlen(p));
  280. end;
  281. procedure SendEscapeSeq(const S: String);
  282. begin
  283. fpWrite(stdoutputhandle, S[1], Length(S));
  284. end;
  285. function IntStr(l:longint):string;
  286. begin
  287. Str(l,intstr);
  288. end;
  289. Function XY2Ansi(x,y,ox,oy:longint):String;
  290. {
  291. Returns a string with the escape sequences to go to X,Y on the screen.
  292. Note that x, y, ox, oy are 1-based (i.e. top-left corner of the screen
  293. is (1, 1)), while SetCursorPos parameters and CursorX and CursorY
  294. are 0-based (top-left corner of the screen is (0, 0)).
  295. }
  296. var delta:longint;
  297. direction:char;
  298. movement:string[32];
  299. begin
  300. if ((x=1) and (oy+1=y)) and (console<>ttyfreebsd) then
  301. begin
  302. XY2Ansi:=#13#10;
  303. exit;
  304. end;
  305. direction:='H';
  306. if y=oy then
  307. begin
  308. if x=ox then
  309. begin
  310. XY2Ansi:='';
  311. exit;
  312. end;
  313. if x=1 then
  314. begin
  315. XY2Ansi:=#13;
  316. exit;
  317. end;
  318. delta:=ox-x;
  319. direction:=char(byte('C')+byte(x<=ox));
  320. end;
  321. if x=ox then
  322. begin
  323. delta:=oy-y;
  324. direction:=char(byte('A')+byte(y>oy));
  325. end;
  326. if direction='H' then
  327. movement:=intstr(y)+';'+intstr(x)
  328. else
  329. movement:=intstr(abs(delta));
  330. xy2ansi:=#27'['+movement+direction;
  331. end;
  332. const ansitbl:array[0..7] of char='04261537';
  333. {$ifdef disabled}
  334. Function Attr2Ansi(Attr,OAttr:byte):string;
  335. {
  336. Convert Attr to an Ansi String, the Optimal code is calculate
  337. with use of the old OAttr
  338. }
  339. var
  340. hstr : string[16];
  341. OFg,OBg,Fg,Bg:byte;
  342. procedure AddSep(ch:char);
  343. begin
  344. if length(hstr)>0 then
  345. hstr:=hstr+';';
  346. hstr:=hstr+ch;
  347. end;
  348. begin
  349. if Attr=OAttr then
  350. begin
  351. Attr2Ansi:='';
  352. exit;
  353. end;
  354. Hstr:='';
  355. Fg:=Attr and $f;
  356. Bg:=Attr shr 4;
  357. OFg:=OAttr and $f;
  358. OBg:=OAttr shr 4;
  359. { This resets colours to their defaults, the problem is we don't know what
  360. the default is, i.e. it can either be white on black or back on white or
  361. even something totally different. This causes undesired colour schemes
  362. in the IDE on some terminals.
  363. if (OFg<>7) or (Fg=7) or ((OFg>7) and (Fg<8)) or ((OBg>7) and (Bg<8)) then
  364. begin
  365. hstr:='0';
  366. OFg:=7;
  367. OBg:=0;
  368. end;}
  369. if (Fg>7) and (OFg<8) then
  370. begin
  371. AddSep('1');
  372. OFg:=OFg or 8;
  373. end;
  374. if (Bg and 8)<>(OBg and 8) then
  375. begin
  376. AddSep('5');
  377. OBg:=OBg or 8;
  378. end;
  379. if (Fg<>OFg) then
  380. begin
  381. AddSep('3');
  382. hstr:=hstr+AnsiTbl[fg and 7];
  383. end;
  384. if (Bg<>OBg) then
  385. begin
  386. AddSep('4');
  387. hstr:=hstr+AnsiTbl[bg and 7];
  388. end;
  389. if hstr='0' then
  390. hstr:='';
  391. Attr2Ansi:=#27'['+hstr+'m';
  392. end;
  393. {$endif}
  394. function attr2ansi(attr,oattr:byte):string;
  395. var OFg,OBg,Fg,Bg:byte;
  396. begin
  397. Fg:=Attr and $f;
  398. Bg:=Attr shr 4;
  399. OFg:=OAttr and $f;
  400. OBg:=OAttr shr 4;
  401. attr2ansi:=#27'[';
  402. if TerminalSupportsBold then
  403. if fg and 8<>0 then
  404. begin
  405. {Enable bold if not yet on.}
  406. if ofg and 8=0 then
  407. attr2ansi:=attr2ansi+'1;';
  408. end
  409. else
  410. {Disable bold if on.}
  411. if ofg and 8<>0 then
  412. attr2ansi:=attr2ansi+'22;';
  413. if bg and 8<>0 then
  414. begin
  415. {Enable bold if not yet on.}
  416. if obg and 8=0 then
  417. attr2ansi:=attr2ansi+'5;';
  418. end
  419. else
  420. {Disable bold if on.}
  421. if obg and 8<>0 then
  422. attr2ansi:=attr2ansi+'25;';
  423. if TerminalSupportsHighIntensityColors then
  424. begin
  425. if fg and 15<>ofg and 15 then
  426. if fg and 8<>0 then
  427. attr2ansi:=attr2ansi+'9'+ansitbl[fg and 7]+';'
  428. else
  429. attr2ansi:=attr2ansi+'3'+ansitbl[fg and 7]+';';
  430. end
  431. else
  432. begin
  433. if fg and 7<>ofg and 7 then
  434. attr2ansi:=attr2ansi+'3'+ansitbl[fg and 7]+';';
  435. end;
  436. if bg and 7<>obg and 7 then
  437. attr2ansi:=attr2ansi+'4'+ansitbl[bg and 7]+';';
  438. if attr2ansi[length(attr2ansi)]=';' then
  439. attr2ansi[length(attr2ansi)]:='m'
  440. else
  441. attr2ansi:='';
  442. end;
  443. procedure UpdateTTY(Force:boolean);
  444. type
  445. tchattr=packed record
  446. {$ifdef ENDIAN_LITTLE}
  447. ch : char;
  448. attr : byte;
  449. {$else}
  450. attr : byte;
  451. ch : char;
  452. {$endif}
  453. end;
  454. var
  455. outbuf : array[0..1023+255] of char;
  456. chattr : tchattr;
  457. skipped : boolean;
  458. outptr,
  459. spaces,
  460. eol,
  461. x,y,
  462. LastX,LastY,
  463. SpaceAttr,
  464. LastAttr : longint;
  465. p,pold : pvideocell;
  466. LastLineWidth : Longint;
  467. function transform_cp437_to_iso01(const st:string):string;
  468. var i:byte;
  469. c:char;
  470. converted:word;
  471. begin
  472. transform_cp437_to_iso01:='';
  473. for i:=1 to length(st) do
  474. begin
  475. c:=st[i];
  476. case c of
  477. #0..#31:
  478. converted:=convert_lowascii_to_iso01[c];
  479. #128..#255:
  480. converted:=convert_cp437_to_iso01[c];
  481. else
  482. converted:=byte(c);
  483. end;
  484. if converted and $ff00=$f800 then
  485. begin
  486. if not in_ACS then
  487. begin
  488. transform_cp437_to_iso01:=transform_cp437_to_iso01+ACSIn;
  489. in_ACS:=true;
  490. end;
  491. c:=char(converted and $ff);
  492. end
  493. else
  494. if in_ACS then
  495. begin
  496. transform_cp437_to_iso01:=transform_cp437_to_iso01+ACSOut+
  497. Attr2Ansi(LastAttr,0);
  498. in_ACS:=false;
  499. end;
  500. transform_cp437_to_iso01:=transform_cp437_to_iso01+c;
  501. end;
  502. end;
  503. function transform_cp850_to_iso01(const st:string):string;
  504. var i:byte;
  505. c:char;
  506. converted:word;
  507. begin
  508. transform_cp850_to_iso01:='';
  509. for i:=1 to length(st) do
  510. begin
  511. c:=st[i];
  512. case c of
  513. #0..#31:
  514. converted:=convert_lowascii_to_iso01[c];
  515. #128..#255:
  516. converted:=convert_cp850_to_iso01[c];
  517. else
  518. converted:=byte(c);
  519. end;
  520. if converted and $ff00=$f800 then
  521. begin
  522. if not in_ACS then
  523. begin
  524. transform_cp850_to_iso01:=transform_cp850_to_iso01+ACSIn;
  525. in_ACS:=true;
  526. end;
  527. end
  528. else
  529. if in_ACS then
  530. begin
  531. transform_cp850_to_iso01:=transform_cp850_to_iso01+ACSOut+
  532. Attr2Ansi(LastAttr,0);
  533. in_ACS:=false;
  534. end;
  535. c:=char(converted and $ff);
  536. transform_cp850_to_iso01:=transform_cp850_to_iso01+c;
  537. end;
  538. end;
  539. function transform_linuxlowascii_to_vga(const st:string):string;
  540. var i:byte;
  541. c:char;
  542. converted:word;
  543. begin
  544. transform_linuxlowascii_to_vga:='';
  545. for i:=1 to length(st) do
  546. begin
  547. c:=st[i];
  548. case c of
  549. #0..#31:
  550. converted:=convert_linuxlowascii_to_vga[c];
  551. else
  552. converted:=byte(c);
  553. end;
  554. c:=char(converted and $ff);
  555. transform_linuxlowascii_to_vga:=transform_linuxlowascii_to_vga+c;
  556. end;
  557. end;
  558. function transform_cp437_to_UTF8(const st:string): string;
  559. var i:byte;
  560. c : char;
  561. converted : WideChar;
  562. s : WideString;
  563. begin
  564. transform_cp437_to_UTF8 := '';
  565. for i:=1 to length(st) do
  566. begin
  567. c:=st[i];
  568. case c of
  569. #0..#31:
  570. converted:=convert_lowascii_to_UTF8[c];
  571. #127..#255:
  572. converted:=convert_cp437_to_UTF8[c];
  573. else
  574. begin
  575. converted := #0;
  576. converted := c;
  577. end;
  578. end;
  579. s := s + converted;
  580. end;
  581. transform_cp437_to_UTF8 := Utf8Encode(s);
  582. end;
  583. function transform(const hstr:string):string;
  584. begin
  585. case convert of
  586. cv_linuxlowascii_to_vga:
  587. transform:=transform_linuxlowascii_to_vga(hstr);
  588. cv_cp437_to_iso01:
  589. transform:=transform_cp437_to_iso01(hstr);
  590. cv_cp850_to_iso01:
  591. transform:=transform_cp850_to_iso01(hstr);
  592. cv_cp437_to_UTF8:
  593. transform:=transform_cp437_to_UTF8(hstr);
  594. else
  595. transform:=hstr;
  596. end;
  597. end;
  598. procedure outdata(hstr:string);
  599. begin
  600. If Length(HStr)>0 Then
  601. Begin
  602. while (eol>0) do
  603. begin
  604. hstr:=#13#10+hstr;
  605. dec(eol);
  606. end;
  607. { if (convert=cv_vga_to_acs) and (ACSIn<>'') and (ACSOut<>'') then
  608. transform_using_acs(Hstr);}
  609. move(hstr[1],outbuf[outptr],length(hstr));
  610. inc(outptr,length(hstr));
  611. if outptr>=1024 then
  612. begin
  613. {$ifdef logging}
  614. blockwrite(f,logstart[1],length(logstart));
  615. blockwrite(f,nl,1);
  616. blockwrite(f,outptr,sizeof(outptr));
  617. blockwrite(f,nl,1);
  618. blockwrite(f,outbuf,outptr);
  619. blockwrite(f,nl,1);
  620. {$endif logging}
  621. fpWrite(stdoutputhandle,outbuf,outptr);
  622. outptr:=0;
  623. end;
  624. end;
  625. end;
  626. procedure OutClr(c:byte);
  627. begin
  628. if c=LastAttr then
  629. exit;
  630. OutData(Attr2Ansi(c,LastAttr));
  631. LastAttr:=c;
  632. end;
  633. procedure OutSpaces;
  634. begin
  635. if (Spaces=0) then
  636. exit;
  637. OutClr(SpaceAttr);
  638. OutData(Space(Spaces));
  639. LastX:=x;
  640. LastY:=y;
  641. Spaces:=0;
  642. end;
  643. (*
  644. function GetTermString(ndx:Ttermcode):String;
  645. var
  646. P{,pdelay}: PChar;
  647. begin
  648. GetTermString:='';
  649. if not assigned(cur_term_Strings) then
  650. exit{RunError(219)};
  651. P:=cur_term_Strings^[Ndx];
  652. if assigned(p) then
  653. begin { Do not transmit the delays }
  654. { pdelay:=strpos(p,'$<');
  655. if assigned(pdelay) then
  656. pdelay^:=#0;}
  657. GetTermString:=StrPas(p);
  658. { if assigned(pdelay) then
  659. pdelay^:='$';}
  660. end;
  661. end;
  662. *)
  663. begin
  664. OutPtr:=0;
  665. Eol:=0;
  666. skipped:=true;
  667. p:=PVideoCell(VideoBuf);
  668. pold:=PVideoCell(OldVideoBuf);
  669. { init Attr, X,Y and set autowrap off }
  670. SendEscapeSeq(#27'[0;40;37m'#27'[?7l'{#27'[H'} );
  671. // 1.0.x: SendEscapeSeq(#27'[m'{#27'[H'});
  672. LastAttr:=7;
  673. LastX:=-1;
  674. LastY:=-1;
  675. for y:=1 to ScreenHeight do
  676. begin
  677. SpaceAttr:=0;
  678. Spaces:=0;
  679. LastLineWidth:=ScreenWidth;
  680. If (y=ScreenHeight) And (Console=ttyFreeBSD) {And :am: is on} Then
  681. LastLineWidth:=ScreenWidth-2;
  682. for x:=1 to LastLineWidth do
  683. begin
  684. if (not force) and (p^=pold^) then
  685. begin
  686. if (Spaces>0) then
  687. OutSpaces;
  688. skipped:=true;
  689. end
  690. else
  691. begin
  692. if skipped then
  693. begin
  694. OutData(XY2Ansi(x,y,LastX,LastY));
  695. LastX:=x;
  696. LastY:=y;
  697. skipped:=false;
  698. end;
  699. chattr:=tchattr(p^);
  700. { if chattr.ch in [#0,#255] then
  701. chattr.ch:=' ';}
  702. if chattr.ch=' ' then
  703. begin
  704. if Spaces=0 then
  705. SpaceAttr:=chattr.Attr;
  706. if (chattr.attr and $f0)=(spaceattr and $f0) then
  707. chattr.Attr:=SpaceAttr
  708. else
  709. begin
  710. OutSpaces;
  711. SpaceAttr:=chattr.Attr;
  712. end;
  713. inc(Spaces);
  714. end
  715. else
  716. begin
  717. if (Spaces>0) then
  718. OutSpaces;
  719. { if ord(chattr.ch)<32 then
  720. begin
  721. Chattr.Attr:= $ff xor Chattr.Attr;
  722. ChAttr.ch:=chr(ord(chattr.ch)+ord('A')-1);
  723. end;}
  724. if LastAttr<>chattr.Attr then
  725. OutClr(chattr.Attr);
  726. OutData(transform(chattr.ch));
  727. LastX:=x+1;
  728. LastY:=y;
  729. end;
  730. p^:=tvideocell(chattr);
  731. end;
  732. inc(p);
  733. inc(pold);
  734. end;
  735. if (Spaces>0) then
  736. OutSpaces;
  737. if force then
  738. inc(eol)
  739. else
  740. skipped:=true;
  741. end;
  742. eol:=0;
  743. {if am in capabilities? Then}
  744. if (Console=ttyFreeBSD) and (Plongint(p)^<>plongint(pold)^) Then
  745. begin
  746. OutData(XY2Ansi(ScreenWidth,ScreenHeight,LastX,LastY));
  747. OutData(#8);
  748. {Output last char}
  749. chattr:=tchattr(p[1]);
  750. if LastAttr<>chattr.Attr then
  751. OutClr(chattr.Attr);
  752. OutData(transform(chattr.ch));
  753. inc(LastX);
  754. // OutData(XY2Ansi(ScreenWidth-1,ScreenHeight,LastX,LastY));
  755. // OutData(GetTermString(Insert_character));
  756. OutData(#8+#27+'[1@');
  757. chattr:=tchattr(p^);
  758. if LastAttr<>chattr.Attr then
  759. OutClr(chattr.Attr);
  760. OutData(transform(chattr.ch));
  761. inc(LastX);
  762. end;
  763. OutData(XY2Ansi(CursorX+1,CursorY+1,LastX,LastY));
  764. if in_ACS then
  765. begin
  766. {If the program crashes and the ACS is still enabled, the user's
  767. keyboard will output strange characters. Therefore we disable the
  768. acs after each screen update, so the risk that it happens is greatly
  769. reduced.}
  770. { SendEscapeSeqNdx(exit_alt_charset_mode);}
  771. outdata(acsout);
  772. in_acs:=false;
  773. end;
  774. {$ifdef logging}
  775. blockwrite(f,logstart[1],length(logstart));
  776. blockwrite(f,nl,1);
  777. blockwrite(f,outptr,sizeof(outptr));
  778. blockwrite(f,nl,1);
  779. blockwrite(f,outbuf,outptr);
  780. blockwrite(f,nl,1);
  781. {$endif logging}
  782. fpWrite(stdoutputhandle,outbuf,outptr);
  783. {turn autowrap on}
  784. // SendEscapeSeq(#27'[?7h');
  785. end;
  786. {$ifdef linux}
  787. procedure update_vcsa(force:boolean);
  788. const max_updates=64;
  789. label update,update_all,equal_loop,unequal_loop;
  790. var position,update_count,i:word;
  791. update_positions:array[0..max_updates-1] of word;
  792. update_lengths:array[0..max_updates-1] of word;
  793. begin
  794. if force then
  795. goto update_all;
  796. update_count:=0;
  797. i:=0;
  798. equal_loop:
  799. repeat
  800. if videobuf^[i]<>oldvideobuf^[i] then
  801. goto unequal_loop;
  802. inc(i);
  803. until i>videobufsize div 2;
  804. goto update;
  805. unequal_loop:
  806. if update_count>=max_updates then
  807. goto update_all;
  808. update_positions[update_count]:=i;
  809. update_lengths[update_count]:=0;
  810. inc(update_count);
  811. repeat
  812. if videobuf^[i]=oldvideobuf^[i] then
  813. goto equal_loop;
  814. inc(i);
  815. inc(update_lengths[update_count-1]);
  816. until i>videobufsize div 2;
  817. update:
  818. for i:=1 to update_count do
  819. begin
  820. position:=update_positions[i-1];
  821. fppwrite(ttyfd,videobuf^[position],update_lengths[i-1]*2,4+position*2);
  822. end;
  823. exit;
  824. update_all:
  825. fppwrite(ttyfd,videobuf^,videobufsize,4);
  826. end;
  827. {$endif}
  828. var
  829. preInitVideoTio, postInitVideoTio: termio.termios;
  830. inputRaw, outputRaw: boolean;
  831. procedure saveRawSettings(const tio: termio.termios);
  832. begin
  833. with tio do
  834. begin
  835. inputRaw :=
  836. ((c_iflag and (IGNBRK or BRKINT or PARMRK or ISTRIP or
  837. INLCR or IGNCR or ICRNL or IXON)) = 0) and
  838. ((c_lflag and (ECHO or ECHONL or ICANON or ISIG or IEXTEN)) = 0);
  839. outPutRaw :=
  840. ((c_oflag and OPOST) = 0) and
  841. ((c_cflag and (CSIZE or PARENB)) = 0) and
  842. ((c_cflag and CS8) <> 0);
  843. end;
  844. end;
  845. procedure restoreRawSettings(tio: termio.termios);
  846. begin
  847. with tio do
  848. begin
  849. if inputRaw then
  850. begin
  851. c_iflag := c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
  852. INLCR or IGNCR or ICRNL or IXON));
  853. c_lflag := c_lflag and
  854. (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
  855. c_cc[VMIN]:=1;
  856. c_cc[VTIME]:=0;
  857. end;
  858. if outPutRaw then
  859. begin
  860. c_oflag := c_oflag and not(OPOST);
  861. c_cflag := c_cflag and not(CSIZE or PARENB) or CS8;
  862. end;
  863. end;
  864. TCSetAttr(1,TCSANOW,tio);
  865. end;
  866. function UTF8Enabled: Boolean;
  867. var
  868. lang:string;
  869. begin
  870. {$ifdef BEOS}
  871. UTF8Enabled := true;
  872. exit;
  873. {$endif}
  874. lang:=upcase(fpgetenv('LANG'));
  875. UTF8Enabled := (Pos('.UTF-8', lang) > 0) or (Pos('.UTF8', lang) > 0);
  876. end;
  877. procedure decide_codepages;
  878. var s:string;
  879. begin
  880. if external_codepage in vga_codepages then
  881. begin
  882. {Possible override...}
  883. s:=upcase(fpgetenv('CONSOLEFONT_CP'));
  884. if s='CP437' then
  885. external_codepage:=cp437
  886. else if s='CP850' then
  887. external_codepage:=cp850;
  888. end;
  889. {A non-vcsa Linux console can display most control characters, but not all.}
  890. if {$ifdef linux}(console<>ttyLinux) and{$endif}
  891. (cur_term_strings=@term_codes_linux) then
  892. convert:=cv_linuxlowascii_to_vga;
  893. case external_codepage of
  894. iso01: {West Europe}
  895. begin
  896. internal_codepage:=cp850;
  897. convert:=cv_cp850_to_iso01;
  898. end;
  899. iso02: {East Europe}
  900. internal_codepage:=cp852;
  901. iso05: {Cyrillic}
  902. internal_codepage:=cp866;
  903. utf8:
  904. begin
  905. internal_codepage:=cp437;
  906. convert:=cv_cp437_to_UTF8;
  907. end;
  908. else
  909. if internal_codepage in vga_codepages then
  910. internal_codepage:=external_codepage
  911. else
  912. {We don't know how to convert to the external codepage. Use codepage
  913. 437 in the hope that the actual font has similarity to codepage 437.}
  914. internal_codepage:=cp437;
  915. end;
  916. end;
  917. procedure prepareInitVideo;
  918. begin
  919. TCGetAttr(1,preInitVideoTio);
  920. saveRawSettings(preInitVideoTio);
  921. end;
  922. procedure videoInitDone;
  923. begin
  924. TCGetAttr(1,postInitVideoTio);
  925. restoreRawSettings(postInitVideoTio);
  926. end;
  927. procedure prepareDoneVideo;
  928. var
  929. tio: termio.termios;
  930. begin
  931. TCGetAttr(1,tio);
  932. saveRawSettings(tio);
  933. TCSetAttr(1,TCSANOW,postInitVideoTio);
  934. end;
  935. procedure doneVideoDone;
  936. begin
  937. restoreRawSettings(preInitVideoTio);
  938. end;
  939. procedure SysInitVideo;
  940. var
  941. {$ifdef linux}
  942. FName: String;
  943. {$endif linux}
  944. WS: packed record
  945. ws_row, ws_col, ws_xpixel, ws_ypixel: Word;
  946. end;
  947. { Err: Longint;}
  948. { prev_term : TerminalCommon_ptr1;}
  949. term:string;
  950. i:word;
  951. {$ifdef Linux}
  952. s:string[15];
  953. {$endif}
  954. {$ifdef freebsd}
  955. ThisTTY: String[30];
  956. {$endif}
  957. const font_vga:array[0..11] of char=#15#27'%@'#27'(U'#27'[3h';
  958. font_lat1:array[0..5] of char=#27'%@'#27'(B';
  959. begin
  960. { check for tty }
  961. if (IsATTY(stdinputhandle)=1) then
  962. begin
  963. { save current terminal characteristics and remove rawness }
  964. prepareInitVideo;
  965. {$ifdef linux}
  966. { running on a tty, find out whether locally or remotely }
  967. TTyfd:=-1;
  968. {$endif linux}
  969. Console:=TTyNetwork; {Default: Network or other vtxxx tty}
  970. cur_term_strings:=@term_codes_vt100; {Default: vt100}
  971. external_codepage:=iso01; {Default: ISO-8859-1}
  972. if UTF8Enabled then
  973. external_codepage:=utf8;
  974. {$ifdef linux}
  975. if (vcs_device>=0) and (external_codepage<>utf8) then
  976. begin
  977. str(vcs_device,s);
  978. fname:='/dev/vcsa'+s;
  979. { open console, $1b6=rw-rw-rw- }
  980. ttyfd:=fpopen(fname,$1b6,O_RDWR);
  981. if ttyfd<>-1 then
  982. begin
  983. console:=ttylinux;
  984. external_codepage:=cp437; {VCSA defaults to codepage 437.}
  985. end
  986. else
  987. if try_grab_vcsa then
  988. begin
  989. ttyfd:=fpopen(fname,$1b6,O_RDWR);
  990. if ttyfd<>-1 then
  991. begin
  992. console:=ttylinux;
  993. external_codepage:=cp437; {VCSA defaults to codepage 437.}
  994. end;
  995. end;
  996. end;
  997. {$endif}
  998. {$ifdef freebsd}
  999. ThisTTY:=TTYName(stdinputhandle);
  1000. if copy(ThisTTY, 1, 9) = '/dev/ttyv' then {FreeBSD has these}
  1001. begin
  1002. { check for (Free?)BSD native}
  1003. if (ThisTTY[10]>='0') and (ThisTTY[10]<='9') Then
  1004. Console:=ttyFreeBSD; {TTYFd ?}
  1005. end;
  1006. {$endif}
  1007. term:=fpgetenv('TERM');
  1008. for i:=low(terminal_names) to high(terminal_names) do
  1009. if copy(term,1,length(terminal_names[i]))=terminal_names[i] then
  1010. cur_term_strings:=terminal_data[i];
  1011. if cur_term_strings=@term_codes_xterm then
  1012. begin
  1013. {$ifdef haiku}
  1014. TerminalSupportsBold := true;
  1015. TerminalSupportsHighIntensityColors := false;
  1016. {$else}
  1017. TerminalSupportsBold := false;
  1018. TerminalSupportsHighIntensityColors := true;
  1019. {$endif}
  1020. end
  1021. else
  1022. begin
  1023. TerminalSupportsBold := true;
  1024. TerminalSupportsHighIntensityColors := false;
  1025. end;
  1026. if cur_term_strings=@term_codes_beos then
  1027. begin
  1028. TerminalSupportsBold := false;
  1029. TerminalSupportsHighIntensityColors := false;
  1030. end;
  1031. if cur_term_strings=@term_codes_freebsd then
  1032. console:=ttyFreeBSD;
  1033. {$ifdef linux}
  1034. if (console<>ttylinux) then
  1035. begin
  1036. {$endif}
  1037. if cur_term_strings=@term_codes_linux then
  1038. begin
  1039. if external_codepage<>utf8 then
  1040. begin
  1041. {Enable the VGA character set (codepage 437,850,....)}
  1042. fpwrite(stdoutputhandle,font_vga,sizeof(font_vga));
  1043. external_codepage:=cp437; {Now default to codepage 437.}
  1044. end;
  1045. end
  1046. else
  1047. begin
  1048. if external_codepage<>utf8 then
  1049. begin
  1050. {No VGA font :( }
  1051. fpwrite(stdoutputhandle,font_lat1,sizeof(font_lat1));
  1052. end;
  1053. { running on a remote terminal, no error with /dev/vcsa }
  1054. end;
  1055. {$ifdef linux}
  1056. end;
  1057. {$endif}
  1058. fpioctl(stdinputhandle, TIOCGWINSZ, @WS);
  1059. if WS.ws_Col=0 then
  1060. WS.ws_Col:=80;
  1061. if WS.ws_Row=0 then
  1062. WS.ws_Row:=25;
  1063. ScreenWidth:=WS.ws_Col;
  1064. { TDrawBuffer only has FVMaxWidth elements
  1065. larger values lead to crashes }
  1066. if ScreenWidth> FVMaxWidth then
  1067. ScreenWidth:=FVMaxWidth;
  1068. ScreenHeight:=WS.ws_Row;
  1069. CursorX:=0;
  1070. CursorY:=0;
  1071. LastCursorType:=$ff;
  1072. ScreenColor:=True;
  1073. { Start with a clear screen }
  1074. {$ifdef linux}
  1075. if Console<>ttylinux then
  1076. begin
  1077. {$endif}
  1078. SendEscapeSeqNdx(cursor_home);
  1079. SendEscapeSeqNdx(cursor_normal);
  1080. SendEscapeSeqNdx(cursor_visible_underline);
  1081. SendEscapeSeqNdx(enter_ca_mode);
  1082. SetCursorType(crUnderLine);
  1083. If Console=ttyFreeBSD Then
  1084. SendEscapeSeqNdx(exit_am_mode);
  1085. {$ifdef linux}
  1086. end;
  1087. {$endif}
  1088. { Always true because of vt100 default...
  1089. if assigned(cur_term_Strings) then
  1090. begin}
  1091. ACSIn:=StrPas(cur_term_strings^[enter_alt_charset_mode]);
  1092. ACSOut:=StrPas(cur_term_strings^[exit_alt_charset_mode]);
  1093. if (ACSIn<>'') and (ACSOut<>'') then
  1094. SendEscapeSeqNdx(ena_acs);
  1095. (* If fpGetEnv('TERM')='xterm' then
  1096. convert:=cv_vga_to_acs; {use of acs for xterm is ok}*)
  1097. { end
  1098. else
  1099. begin
  1100. ACSIn:='';
  1101. ACSOut:='';
  1102. end;}
  1103. {$ifdef logging}
  1104. assign(f,'video.log');
  1105. rewrite(f,1);
  1106. {$endif logging}
  1107. { save new terminal characteristics and possible restore rawness }
  1108. videoInitDone;
  1109. decide_codepages;
  1110. end
  1111. else
  1112. ErrorCode:=errVioInit; { not a TTY }
  1113. end;
  1114. procedure SysDoneVideo;
  1115. var font_custom:array[0..2] of char=#27'(K';
  1116. begin
  1117. prepareDoneVideo;
  1118. SetCursorType(crUnderLine);
  1119. {$ifdef linux}
  1120. if Console=ttylinux then
  1121. SetCursorPos(0,0)
  1122. else
  1123. begin
  1124. {$endif}
  1125. SendEscapeSeqNdx(exit_ca_mode);
  1126. SendEscapeSeqNdx(cursor_home);
  1127. SendEscapeSeqNdx(cursor_normal);
  1128. SendEscapeSeqNdx(cursor_visible_underline);
  1129. SendEscapeSeq(#27'[H');
  1130. if cur_term_strings=@term_codes_linux then
  1131. begin
  1132. {Executed in case ttylinux is false (i.e. no vcsa), but
  1133. TERM=linux.}
  1134. { if we're in utf8 mode, we didn't change the font, so
  1135. no need to restore anything }
  1136. if external_codepage<>utf8 then
  1137. begin
  1138. {Enable the character set set through setfont}
  1139. fpwrite(stdoutputhandle,font_custom,3);
  1140. end;
  1141. end;
  1142. {$ifdef linux}
  1143. end;
  1144. {$endif}
  1145. ACSIn:='';
  1146. ACSOut:='';
  1147. doneVideoDone;
  1148. {$ifdef logging}
  1149. close(f);
  1150. {$endif logging}
  1151. end;
  1152. procedure SysClearScreen;
  1153. begin
  1154. {$ifdef linux}
  1155. if Console=ttylinux then
  1156. UpdateScreen(true)
  1157. else
  1158. begin
  1159. {$endif}
  1160. SendEscapeSeq(#27'[0m');
  1161. SendEscapeSeqNdx(clear_screen);
  1162. {$ifdef linux}
  1163. end;
  1164. {$endif}
  1165. end;
  1166. procedure SysUpdateScreen(Force: Boolean);
  1167. begin
  1168. {$ifdef linux}
  1169. if console=ttylinux then
  1170. update_vcsa(force)
  1171. else
  1172. {$endif}
  1173. updateTTY(force);
  1174. move(VideoBuf^,OldVideoBuf^,VideoBufSize);
  1175. end;
  1176. function SysGetCapabilities: Word;
  1177. begin
  1178. { about cpColor... we should check the terminfo database... }
  1179. SysGetCapabilities:=cpUnderLine + cpBlink + cpColor;
  1180. end;
  1181. procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
  1182. {$ifdef linux}
  1183. var
  1184. Pos : array [1..2] of Byte;
  1185. {$endif linux}
  1186. begin
  1187. if (CursorX=NewCursorX) and (CursorY=NewCursorY) then
  1188. exit;
  1189. {$ifdef linux}
  1190. if Console=ttylinux then
  1191. begin
  1192. Pos[1]:=NewCursorX;
  1193. Pos[2]:=NewCursorY;
  1194. fppwrite(ttyfd,pos,2,2);
  1195. end
  1196. else
  1197. {$endif}
  1198. { newcursorx,y and CursorX,Y are 0 based ! }
  1199. SendEscapeSeq(XY2Ansi(NewCursorX+1,NewCursorY+1,CursorX+1,CursorY+1));
  1200. CursorX:=NewCursorX;
  1201. CursorY:=NewCursorY;
  1202. end;
  1203. function SysGetCursorType: Word;
  1204. begin
  1205. SysGetCursorType:=LastCursorType;
  1206. end;
  1207. procedure SysSetCursorType(NewType: Word);
  1208. begin
  1209. If LastCursorType=NewType then
  1210. exit;
  1211. LastCursorType:=NewType;
  1212. case NewType of
  1213. crBlock:
  1214. SendEscapeSeqNdx(cursor_visible_block);
  1215. crHidden:
  1216. SendEscapeSeqNdx(cursor_invisible);
  1217. else
  1218. SendEscapeSeqNdx(cursor_normal);
  1219. end;
  1220. end;
  1221. function SysSetVideoMode(const mode:Tvideomode):boolean;
  1222. var winsize:Twinsize;
  1223. begin
  1224. {Due to xterm resize this procedure might get called with the new xterm
  1225. size. Approve the video mode change if the new size equals that of
  1226. the terminal window size.}
  1227. SysSetVideoMode:=false;
  1228. fpioctl(stdinputhandle,TIOCGWINSZ,@winsize);
  1229. if (mode.row=winsize.ws_row) and
  1230. (mode.col=winsize.ws_col) then
  1231. begin
  1232. screenwidth:=mode.col;
  1233. screenheight:=mode.row;
  1234. screencolor:=true;
  1235. SysSetVideoMode:=true;
  1236. end;
  1237. end;
  1238. Const
  1239. SysVideoDriver : TVideoDriver = (
  1240. InitDriver : @SysInitVideo;
  1241. DoneDriver : @SysDoneVideo;
  1242. UpdateScreen : @SysUpdateScreen;
  1243. ClearScreen : @SysClearScreen;
  1244. SetVideoMode : @SysSetVideoMode;
  1245. GetVideoModeCount : Nil;
  1246. GetVideoModeData : Nil;
  1247. SetCursorPos : @SysSetCursorPos;
  1248. GetCursorType : @SysGetCursorType;
  1249. SetCursorType : @SysSetCursorType;
  1250. GetCapabilities : @SysGetCapabilities;
  1251. );
  1252. initialization
  1253. SetVideoDriver(SysVideoDriver);
  1254. end.