video.pp 40 KB

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