| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Florian Klaempfl
- member of the Free Pascal development team
- Video unit for linux
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$IFNDEF FPC_DOTTEDUNITS}
- unit video;
- {$ENDIF FPC_DOTTEDUNITS}
- {$I-}
- {$GOTO on}
- {*****************************************************************************}
- interface
- {*****************************************************************************}
- {$i videoh.inc}
- {*****************************************************************************}
- implementation
- {*****************************************************************************}
- {$IFDEF FPC_DOTTEDUNITS}
- uses UnixApi.Base,UnixApi.TermIO,System.Strings,System.Console.Unixkvmbase,System.Unicode.Graphemebreakproperty,System.Unicode.Eastasianwidth
- ,System.CharSet
- {$ifdef Linux},LinuxApi.Vcs{$endif};
- {$ELSE FPC_DOTTEDUNITS}
- uses baseunix,termio,strings,unixkvmbase,graphemebreakproperty,eastasianwidth
- ,charset
- {$ifdef linux},linuxvcs{$endif};
- {$ENDIF FPC_DOTTEDUNITS}
- const
- CP_ISO01 = 28591; {ISO 8859-1}
- CP_ISO02 = 28592; {ISO 8859-2}
- CP_ISO05 = 28595; {ISO 8859-5}
- var external_codepage:TSystemCodePage;
- {$i video.inc}
- type Tconsole_type=(ttyNetwork
- {$ifdef linux},ttyLinux{$endif}
- ,ttyFreeBSD
- ,ttyNetBSD);
- Ttermcode=(
- enter_alt_charset_mode,
- exit_alt_charset_mode,
- clear_screen,
- cursor_home,
- cursor_normal,
- cursor_visible_underline,
- cursor_visible_block,
- cursor_invisible,
- enter_ca_mode,
- exit_ca_mode,
- exit_am_mode,
- ena_acs
- );
- Ttermcodes=array[Ttermcode] of PAnsiChar;
- Ptermcodes=^Ttermcodes;
- const term_codes_ansi:Ttermcodes=
- (#$1B#$5B#$31#$31#$6D, {enter_alt_charset_mode}
- #$1B#$5B#$31#$30#$6D, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- nil, {cursor_normal}
- nil, {cursor visible, underline}
- nil, {cursor visible, block}
- nil, {cursor_invisible}
- nil, {enter_ca_mode}
- nil, {exit_ca_mode}
- nil, {exit_am_mode}
- nil); {ena_acs}
- term_codes_freebsd:Ttermcodes=
- (nil, {enter_alt_charset_mode}
- nil, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- #$1B#$5B#$3D#$30#$43, {cursor_normal}
- #$1B#$5B#$3D#$31#$43, {cursor visible, underline}
- #$1B#$5B#$3D#$31#$43, {cursor visible, block}
- nil, {cursor_invisible}
- nil, {enter_ca_mode}
- nil, {exit_ca_mode}
- nil, {exit_am_mode}
- nil); {ena_acs}
- term_codes_linux:Ttermcodes=
- (#$1B#$5B#$31#$31#$6D, {enter_alt_charset_mode}
- #$1B#$5B#$31#$30#$6D, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- #$1B'[?25h'#$1B'[?0c', {cursor_normal}
- #$1B'[?0c', {cursor visible, underline}
- #$1B'[?6c', {cursor visible, block}
- #$1B'[?1c', {cursor_invisible}
- nil, {enter_ca_mode}
- nil, {exit_ca_mode}
- nil, {exit_am_mode}
- nil); {ena_acs}
- term_codes_vt100:Ttermcodes=
- (#$0E, {enter_alt_charset_mode}
- #$0F, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A{#$24#$3C#$35#$30#$3E}, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- nil, {cursor_normal}
- nil, {cursor visible, underline}
- nil, {cursor visible, block}
- nil, {cursor_invisible}
- nil, {enter_ca_mode}
- nil, {exit_ca_mode}
- #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
- #$1B#$28#$42#$1B#$29#$30); {ena_acs}
- term_codes_vt220:Ttermcodes=
- (#$1B#$28#$30{#$24#$3C#$32#$3E}, {enter_alt_charset_mode}
- #$1B#$28#$42{#$24#$3C#$34#$3E}, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- nil, {cursor_normal}
- nil, {cursor visible, underline}
- nil, {cursor visible, block}
- nil, {cursor_invisible}
- nil, {enter_ca_mode}
- nil, {exit_ca_mode}
- #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
- #$1B#$29#$30); {ena_acs}
- term_codes_xterm:Ttermcodes=
- (#$0E, {enter_alt_charset_mode}
- #$0F, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$32#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- #$1B#$5B#$3F#$31#$32#$6C#$1B#$5B#$3F#$32#$35#$68, {cursor_normal}
- #27'[?25h'#27'[4 q', {cursor visible, underline}
- #27'[?25h'#27'[2 q', {cursor visible, block}
- #$1B#$5B#$3F#$32#$35#$6C, {cursor_invisible}
- #$1B#$5B#$3F#$31#$30#$34#$39#$68, {enter_ca_mode}
- #$1B#$5B#$3F#$31#$30#$34#$39#$6C, {exit_ca_mode}
- #$1B#$5B#$3F#$37#$6C, {exit_am_mode}
- #$1B#$28#$42#$1B#$29#$30); {ena_acs}
- term_codes_beos:Ttermcodes=
- (nil,//#$0E, {enter_alt_charset_mode}
- nil,//#$0F, {exit_alt_charset_mode}
- #$1B#$5B#$48#$1B#$5B#$4A, {clear_screen}
- #$1B#$5B#$48, {cursor_home}
- #$1B'[?25h',// nil,//#$1B#$5B#$3F#$31#$32#$6C#$1B#$5B#$3F#$32#$35#$68, {cursor_normal}
- nil,//#$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, underline}
- nil,//#$1B#$5B#$3F#$31#$32#$3B#$32#$35#$68, {cursor visible, block}
- #$1B'[?25l',//nil,//#$1B#$5B#$3F#$32#$35#$6C, {cursor_invisible}
- nil,//#$1B#$5B#$3F#$31#$30#$34#$39#$68, {enter_ca_mode}
- nil,//#$1B#$5B#$3F#$31#$30#$34#$39#$6C, {exit_ca_mode}
- nil,//#$1B#$5B#$3F#$37#$6C, {exit_am_mode}
- nil);//#$1B#$28#$42#$1B#$29#$30); {ena_acs}
- const terminal_names:array[0..11] of string[7]=(
- 'ansi',
- 'cons',
- 'eterm',
- 'gnome',
- 'konsole',
- 'linux',
- 'rxvt',
- 'screen',
- 'vt100',
- 'vt220',
- 'xterm',
- 'beterm');
- terminal_data:array[0..11] of Ptermcodes=(
- @term_codes_ansi,
- @term_codes_freebsd,
- @term_codes_xterm,
- @term_codes_xterm,
- @term_codes_xterm,
- @term_codes_linux,
- @term_codes_xterm,
- @term_codes_xterm,
- @term_codes_vt100,
- @term_codes_vt220,
- @term_codes_xterm,
- @term_codes_beos);
- var
- LastCursorType : byte;
- {$ifdef linux}
- TtyFd: Longint;
- {$endif linux}
- Console: Tconsole_type;
- cur_term_strings:Ptermcodes;
- {$ifdef logging}
- f: file;
- const
- logstart: shortstring = '';
- nl: AnsiChar = #10;
- logend: shortstring = #10#10;
- {$endif logging}
- {$ifdef cpui386}
- {$ASMMODE ATT}
- {$endif cpui386}
- const
- { can_delete_term : boolean = false;}
- ACSIn : shortstring = '';
- ACSOut : shortstring = '';
- in_ACS : boolean =false;
- TerminalSupportsHighIntensityColors: boolean = false;
- TerminalSupportsBold: boolean = true;
- {Contains all code pages that can be considered a normal vga font.
- Note: KOI8-R has line drawing characters in wrong place. Support
- can perhaps be added, for now we'll let it rest.}
- function is_vga_code_page(CP: TSystemCodePage): Boolean;
- begin
- case CP of
- 437,850,852,866:
- result:=true;
- else
- result:=false;
- end;
- end;
- function Unicode2DecSpecialGraphics(Ch: WideChar): AnsiChar;
- begin
- case Ch of
- #$25C6:
- Result := #$60;
- #$2592,#$2591,#$2593,#$2584,#$2580:
- Result := #$61;
- #$2409:
- Result := #$62;
- #$240C:
- Result := #$63;
- #$240D:
- Result := #$64;
- #$240A:
- Result := #$65;
- #$00B0:
- Result := #$66;
- #$00B1:
- Result := #$67;
- #$2424:
- Result := #$68;
- #$240B:
- Result := #$69;
- #$2518,#$255B,#$255C,#$255D:
- Result := #$6A;
- #$2510,#$2556,#$2555,#$2557:
- Result := #$6B;
- #$250C,#$2553,#$2552,#$2554:
- Result := #$6C;
- #$2514,#$2558,#$2559,#$255A:
- Result := #$6D;
- #$253C,#$256C,#$256B,#$256A:
- Result := #$6E;
- #$23BA:
- Result := #$6F;
- #$23BB:
- Result := #$70;
- #$2500,#$2550:
- Result := #$71;
- #$23BC:
- Result := #$72;
- #$23BD:
- Result := #$73;
- #$251C,#$255E,#$255F,#$2560:
- Result := #$74;
- #$2524,#$2561,#$2562,#$2563:
- Result := #$75;
- #$2534,#$2569,#$2567,#$2568:
- Result := #$76;
- #$252C,#$2566,#$2564,#$2565:
- Result := #$77;
- #$2502,#$2551:
- Result := #$78;
- #$2264:
- Result := #$79;
- #$2265:
- Result := #$7A;
- #$03A0:
- Result := #$7B;
- #$2260:
- Result := #$7C;
- #$00A3:
- Result := #$7D;
- #$00B7:
- Result := #$7E;
- else
- Result := #0;
- end;
- end;
- function convert_vga_to_acs(ch:AnsiChar):word;
- {Ch contains a character in the VGA character set (i.e. codepage 437).
- This routine tries to convert some VGA symbols as well as possible to the
- xterm alternate character set.
- Return type is word to allow expanding to UCS-2 characters in the
- future.}
- begin
- case ch of
- #18:
- convert_vga_to_acs:=word('|');
- #24, #30: {↑▲}
- convert_vga_to_acs:=word('^');
- #25, #31: {↓▼}
- convert_vga_to_acs:=word('v');
- #26, #16: {Never introduce a ctrl-Z ... →►}
- convert_vga_to_acs:=word('>');
- {#27,} #17: {←◄}
- convert_vga_to_acs:=word('<');
- #176, #177, #178: {░▒▓}
- convert_vga_to_acs:=$f800+word('a');
- #180, #181, #182, #185: {┤╡╢╣}
- convert_vga_to_acs:=$f800+word('u');
- #183, #184, #187, #191: {╖╕╗┐}
- convert_vga_to_acs:=$f800+word('k');
- #188, #189, #190, #217: {╝╜╛┘}
- convert_vga_to_acs:=$f800+word('j');
- #192, #200, #211, #212: {└╚╙╘}
- convert_vga_to_acs:=$f800+word('m');
- #193, #202, #207, #208: {┴╩╧╨}
- convert_vga_to_acs:=$f800+word('v');
- #194, #203, #209, #210: {┬╦╤╥}
- convert_vga_to_acs:=$f800+word('w');
- #195, #198, #199, #204: {├╞╟╠}
- convert_vga_to_acs:=$f800+word('t');
- #196, #205: {─═}
- convert_vga_to_acs:=$f800+word('q');
- #179, #186: {│║}
- convert_vga_to_acs:=$f800+word('x');
- #197, #206, #215, #216: {┼╬╫╪}
- convert_vga_to_acs:=$f800+word('n');
- #201, #213, #214, #218: {╔╒╓┌}
- convert_vga_to_acs:=$f800+word('l');
- #254: { ■ }
- convert_vga_to_acs:=word('*');
- { Shadows for Buttons }
- #220 { ▄ },
- #223: { ▀ }
- convert_vga_to_acs:=$f800+word('a');
- else
- convert_vga_to_acs:=word(ch);
- end;
- end;
- procedure SendEscapeSeqNdx(ndx:Ttermcode);
- var p:PAnsiChar;
- begin
- { Always true because of vt100 default.
- if not assigned(cur_term_Strings) then
- exit}{RunError(219)};
- p:=cur_term_strings^[ndx];
- if p<>nil then
- fpwrite(stdoutputhandle,p^,strlen(p));
- end;
- procedure SendEscapeSeq(const S: shortstring);
- begin
- fpWrite(stdoutputhandle, S[1], Length(S));
- end;
- function IntStr(l:longint):shortstring;
- begin
- Str(l,intstr);
- end;
- Function XY2Ansi(x,y,ox,oy:longint):shortstring;
- {
- Returns a string with the escape sequences to go to X,Y on the screen.
- Note that x, y, ox, oy are 1-based (i.e. top-left corner of the screen
- is (1, 1)), while SetCursorPos parameters and CursorX and CursorY
- are 0-based (top-left corner of the screen is (0, 0)).
- }
- var delta:longint;
- direction:AnsiChar;
- movement:string[32];
- begin
- if ((x=1) and (oy+1=y)) and (console<>ttyfreebsd) then
- begin
- XY2Ansi:=#13#10;
- exit;
- end;
- direction:='H';
- if y=oy then
- begin
- if x=ox then
- begin
- XY2Ansi:='';
- exit;
- end;
- if x=1 then
- begin
- XY2Ansi:=#13;
- exit;
- end;
- delta:=ox-x;
- direction:=AnsiChar(byte('C')+byte(x<=ox));
- end;
- if x=ox then
- begin
- delta:=oy-y;
- direction:=AnsiChar(byte('A')+byte(y>oy));
- end;
- if direction='H' then
- movement:=intstr(y)+';'+intstr(x)
- else
- movement:=intstr(abs(delta));
- xy2ansi:=#27'['+movement+direction;
- end;
- const ansitbl:array[0..7] of AnsiChar='04261537';
- function attr2ansi(Fg,Bg:byte;Attr:TEnhancedVideoAttributes;OFg,OBg:byte;OAttr:TEnhancedVideoAttributes):shortstring;
- const
- AttrOnOffStr: array [TEnhancedVideoAttribute, Boolean] of shortstring = (
- ('22;','1;'),
- ('22;','2;'),
- ('23;','3;'),
- ('24;','4;'),
- ('25;','5;'),
- ('25;','6;'),
- ('27;','7;'),
- ('28;','8;'),
- ('29;','9;'),
- ('24;','21;'));
- var
- tmpS: shortstring;
- A: TEnhancedVideoAttribute;
- begin
- attr2ansi:=#27'[';
- if Attr<>OAttr then
- begin
- { turn off old attributes first }
- for A := Low(TEnhancedVideoAttribute) to High(TEnhancedVideoAttribute) do
- if (not (A in Attr)) and (A in OAttr) then
- attr2ansi:=attr2ansi+AttrOnOffStr[A,False];
- { then, turn on new attributes }
- for A := Low(TEnhancedVideoAttribute) to High(TEnhancedVideoAttribute) do
- if (A in Attr) and (not (A in OAttr)) then
- attr2ansi:=attr2ansi+AttrOnOffStr[A,True];
- end;
- if (Fg > 15) or (Bg > 15) then
- begin
- if Fg<>OFg then
- begin
- if TerminalSupportsBold and (ofg and 8<>0) then
- attr2ansi:=attr2ansi+'22;';
- Str(Fg,tmpS);
- attr2ansi:=attr2ansi+'38;5;'+tmpS+';';
- end;
- if Bg<>OBg then
- begin
- Str(Bg,tmpS);
- attr2ansi:=attr2ansi+'48;5;'+tmpS+';';
- end;
- end
- else
- begin
- if TerminalSupportsBold then
- if fg and 8<>0 then
- begin
- {Enable bold if not yet on.}
- if ofg and 8=0 then
- attr2ansi:=attr2ansi+'1;';
- end
- else
- {Disable bold if on.}
- if ofg and 8<>0 then
- attr2ansi:=attr2ansi+'22;';
- if bg and 8<>0 then
- begin
- {Enable bold if not yet on.}
- if obg and 8=0 then
- attr2ansi:=attr2ansi+'5;';
- end
- else
- {Disable bold if on.}
- if obg and 8<>0 then
- attr2ansi:=attr2ansi+'25;';
- if TerminalSupportsHighIntensityColors then
- begin
- if fg and 15<>ofg and 15 then
- if fg and 8<>0 then
- attr2ansi:=attr2ansi+'9'+ansitbl[fg and 7]+';'
- else
- attr2ansi:=attr2ansi+'3'+ansitbl[fg and 7]+';';
- end
- else
- begin
- if fg and 7<>ofg and 7 then
- attr2ansi:=attr2ansi+'3'+ansitbl[fg and 7]+';';
- end;
- if bg and 7<>obg and 7 then
- attr2ansi:=attr2ansi+'4'+ansitbl[bg and 7]+';';
- end;
- if attr2ansi[length(attr2ansi)]=';' then
- attr2ansi[length(attr2ansi)]:='m'
- else
- attr2ansi:='';
- end;
- procedure UpdateTTY(Force:boolean);
- var
- outbuf : array[0..1023+255] of AnsiChar;
- chattr : tenhancedvideocell;
- skipped : boolean;
- outptr,
- spaces,
- eol,
- x,y,
- LastX,LastY : longint;
- SpaceFg, SpaceBg : byte;
- SpaceAttr: TEnhancedVideoAttributes;
- LastFg, LastBg : byte;
- LastAttr: TEnhancedVideoAttributes;
- LastLineWidth : Longint;
- p,pold : penhancedvideocell;
- LastCharWasDoubleWidth: Boolean;
- CurCharWidth: Integer;
- function transform(const hstr:UnicodeString):RawByteString;
- var
- DecSpecialGraphicsCharacter: AnsiChar;
- begin
- if external_codepage=CP_UTF8 then
- result:=Utf8Encode(hstr)
- else
- begin
- DecSpecialGraphicsCharacter:=#0;
- if (Length(hstr)=1) and (ACSIn<>'') and (ACSOut<>'') then
- DecSpecialGraphicsCharacter:=Unicode2DecSpecialGraphics(hstr[1]);
- if DecSpecialGraphicsCharacter<>#0 then
- begin
- result:=ACSIn+DecSpecialGraphicsCharacter+ACSOut;
- SetCodePage(result,external_codepage,False);
- end
- else
- begin
- result:=Utf8Encode(hstr);
- SetCodePage(result,external_codepage,True);
- if (result='?') and (hstr<>'?') then
- begin
- { Character is missing in the external codepage. }
- { Try some replacements. }
- if Length(hstr)=1 then
- begin
- case hstr[1] of
- #$2195:
- result:='|';
- #$2191,#$25B2:
- result:='^';
- #$2193,#$25BC:
- result:='v';
- #$2192,#$25BA:
- result:='>';
- #$2190,#$25C4:
- result:='<';
- #$25A0:
- result:='*';
- end;
- SetCodePage(result,external_codepage,False);
- end;
- end;
- end;
- end;
- end;
- procedure outdata(hstr:rawbytestring);
- begin
- If Length(HStr)>0 Then
- Begin
- while (eol>0) do
- begin
- outbuf[outptr]:=#13;
- outbuf[outptr+1]:=#10;
- inc(outptr,2);
- dec(eol);
- end;
- { if (convert=cv_vga_to_acs) and (ACSIn<>'') and (ACSOut<>'') then
- transform_using_acs(Hstr);}
- move(hstr[1],outbuf[outptr],length(hstr));
- inc(outptr,length(hstr));
- if outptr>=1024 then
- begin
- {$ifdef logging}
- blockwrite(f,logstart[1],length(logstart));
- blockwrite(f,nl,1);
- blockwrite(f,outptr,sizeof(outptr));
- blockwrite(f,nl,1);
- blockwrite(f,outbuf,outptr);
- blockwrite(f,nl,1);
- {$endif logging}
- fpWrite(stdoutputhandle,outbuf,outptr);
- outptr:=0;
- end;
- end;
- end;
- procedure OutClr(Fg,Bg:byte;Attr:TEnhancedVideoAttributes);
- begin
- if (Fg=LastFg) and (Bg=LastBg) and (Attr=LastAttr) then
- exit;
- OutData(Attr2Ansi(Fg,Bg,Attr,LastFg,LastBg,LastAttr));
- LastFg:=Fg;
- LastBg:=Bg;
- LastAttr:=Attr;
- end;
- procedure OutSpaces;
- var SpaceLen : longint;
- begin
- if (Spaces=0) then
- exit;
- OutClr(SpaceFg,SpaceBg,SpaceAttr);
- repeat
- SpaceLen:=Spaces;
- if SpaceLen > 200 then SpaceLen:=200; {have to fit in ShortString}
- OutData(Space(SpaceLen));
- Spaces:=Spaces-SpaceLen;
- until Spaces = 0;
- LastX:=x;
- LastY:=y;
- Spaces:=0;
- end;
- (*
- function GetTermString(ndx:Ttermcode):shortstring;
- var
- P{,pdelay}: PAnsiChar;
- begin
- GetTermString:='';
- if not assigned(cur_term_Strings) then
- exit{RunError(219)};
- P:=cur_term_Strings^[Ndx];
- if assigned(p) then
- begin { Do not transmit the delays }
- { pdelay:=strpos(p,'$<');
- if assigned(pdelay) then
- pdelay^:=#0;}
- GetTermString:=StrPas(p);
- { if assigned(pdelay) then
- pdelay^:='$';}
- end;
- end;
- *)
- begin
- OutPtr:=0;
- Eol:=0;
- skipped:=true;
- p:=PEnhancedVideoCell(@EnhancedVideoBuf[0]);
- pold:=PEnhancedVideoCell(@OldEnhancedVideoBuf[0]);
- { init Attr, X,Y and set autowrap off }
- SendEscapeSeq(#27'[0;40;37m'#27'[?7l'{#27'[H'} );
- // 1.0.x: SendEscapeSeq(#27'[m'{#27'[H'});
- LastFg:=7;
- LastBg:=0;
- LastAttr:=[];
- LastX:=-1;
- LastY:=-1;
- for y:=1 to ScreenHeight do
- begin
- SpaceFg:=0;
- SpaceBg:=0;
- SpaceAttr:=[];
- Spaces:=0;
- LastLineWidth:=ScreenWidth;
- If (y=ScreenHeight) And (Console=ttyFreeBSD) {And :am: is on} Then
- LastLineWidth:=ScreenWidth-2;
- LastCharWasDoubleWidth:=False;
- for x:=1 to LastLineWidth do
- begin
- if LastCharWasDoubleWidth then
- LastCharWasDoubleWidth:=false
- else
- begin
- CurCharWidth := ExtendedGraphemeClusterDisplayWidth(p^.ExtendedGraphemeCluster);
- if (not force) and (p^=pold^) and
- ((CurCharWidth <= 1) or (x=LastLineWidth) or (p[1]=pold[1])) then
- begin
- if (Spaces>0) then
- OutSpaces;
- skipped:=true;
- if CurCharWidth = 2 then
- LastCharWasDoubleWidth:=true;
- end
- else
- begin
- if skipped then
- begin
- OutData(XY2Ansi(x,y,LastX,LastY));
- LastX:=x;
- LastY:=y;
- skipped:=false;
- end;
- chattr:=p^;
- { if chattr.ch in [#0,#255] then
- chattr.ch:=' ';}
- if chattr.ExtendedGraphemeCluster=' ' then
- begin
- if Spaces=0 then
- begin
- SpaceFg:=chattr.ForegroundColor;
- SpaceBg:=chattr.BackgroundColor;
- SpaceAttr:=chattr.EnhancedVideoAttributes;
- end;
- if (chattr.BackgroundColor=SpaceBg) and (chattr.EnhancedVideoAttributes=SpaceAttr) then
- chattr.ForegroundColor:=SpaceFg
- else
- begin
- OutSpaces;
- SpaceFg:=chattr.ForegroundColor;
- SpaceBg:=chattr.BackgroundColor;
- SpaceAttr:=chattr.EnhancedVideoAttributes;
- end;
- inc(Spaces);
- end
- else
- begin
- if (Spaces>0) then
- OutSpaces;
- { if ord(chattr.ch)<32 then
- begin
- Chattr.Attr:= $ff xor Chattr.Attr;
- ChAttr.ch:=chr(ord(chattr.ch)+ord('A')-1);
- end;}
- if (LastFg<>chattr.ForegroundColor) or (LastBg<>chattr.BackgroundColor) or (LastAttr<>chattr.EnhancedVideoAttributes) then
- OutClr(chattr.ForegroundColor,chattr.BackgroundColor,chattr.EnhancedVideoAttributes);
- OutData(transform(chattr.ExtendedGraphemeCluster));
- if CurCharWidth=2 then
- begin
- LastX:=x+2;
- LastCharWasDoubleWidth:=True;
- end
- else
- begin
- LastX:=x+1;
- LastCharWasDoubleWidth:=False;
- end;
- LastY:=y;
- end;
- //p^:=chattr;
- end;
- end;
- inc(p);
- inc(pold);
- end;
- if (Spaces>0) then
- OutSpaces;
- if force then
- inc(eol)
- else
- skipped:=true;
- end;
- eol:=0;
- {if am in capabilities? Then}
- if (Console=ttyFreeBSD) and (p^<>pold^) Then
- begin
- OutData(XY2Ansi(ScreenWidth,ScreenHeight,LastX,LastY));
- OutData(#8);
- {Output last AnsiChar}
- chattr:=p[1];
- if (LastFg<>chattr.ForegroundColor) or (LastBg<>chattr.BackgroundColor) or (LastAttr<>chattr.EnhancedVideoAttributes) then
- OutClr(chattr.ForegroundColor,chattr.BackgroundColor,chattr.EnhancedVideoAttributes);
- OutData(transform(chattr.ExtendedGraphemeCluster));
- inc(LastX);
- // OutData(XY2Ansi(ScreenWidth-1,ScreenHeight,LastX,LastY));
- // OutData(GetTermString(Insert_character));
- OutData(#8+#27+'[1@');
- chattr:=p^;
- if (LastFg<>chattr.ForegroundColor) or (LastBg<>chattr.BackgroundColor) or (LastAttr<>chattr.EnhancedVideoAttributes) then
- OutClr(chattr.ForegroundColor,chattr.BackgroundColor,chattr.EnhancedVideoAttributes);
- OutData(transform(chattr.ExtendedGraphemeCluster));
- inc(LastX);
- end;
- OutData(XY2Ansi(CursorX+1,CursorY+1,LastX,LastY));
- if in_ACS then
- begin
- {If the program crashes and the ACS is still enabled, the user's
- keyboard will output strange characters. Therefore we disable the
- acs after each screen update, so the risk that it happens is greatly
- reduced.}
- { SendEscapeSeqNdx(exit_alt_charset_mode);}
- outdata(acsout);
- in_acs:=false;
- end;
- {$ifdef logging}
- blockwrite(f,logstart[1],length(logstart));
- blockwrite(f,nl,1);
- blockwrite(f,outptr,sizeof(outptr));
- blockwrite(f,nl,1);
- blockwrite(f,outbuf,outptr);
- blockwrite(f,nl,1);
- {$endif logging}
- fpWrite(stdoutputhandle,outbuf,outptr);
- {turn autowrap on}
- // SendEscapeSeq(#27'[?7h');
- end;
- {$ifdef linux}
- procedure update_vcsa(force:boolean);
- const max_updates=64;
- label update,update_all,equal_loop,unequal_loop;
- var position,update_count,i:word;
- update_positions:array[0..max_updates-1] of word;
- update_lengths:array[0..max_updates-1] of word;
- begin
- if force then
- goto update_all;
- update_count:=0;
- i:=0;
- equal_loop:
- repeat
- if videobuf^[i]<>oldvideobuf^[i] then
- goto unequal_loop;
- inc(i);
- until i>videobufsize div 2;
- goto update;
- unequal_loop:
- if update_count>=max_updates then
- goto update_all;
- update_positions[update_count]:=i;
- update_lengths[update_count]:=0;
- inc(update_count);
- repeat
- if videobuf^[i]=oldvideobuf^[i] then
- goto equal_loop;
- inc(i);
- inc(update_lengths[update_count-1]);
- until i>videobufsize div 2;
- update:
- for i:=1 to update_count do
- begin
- position:=update_positions[i-1];
- fppwrite(ttyfd,videobuf^[position],update_lengths[i-1]*2,4+position*2);
- end;
- exit;
- update_all:
- fppwrite(ttyfd,videobuf^,videobufsize,4);
- end;
- {$endif}
- var
- preInitVideoTio, postInitVideoTio: {$IFDEF FPC_DOTTEDUNITS}UnixApi.{$ENDIF}TermIo.termios;
- inputRaw, outputRaw: boolean;
- procedure saveRawSettings(const tio: {$IFDEF FPC_DOTTEDUNITS}UnixApi.{$ENDIF}TermIo.termios);
- begin
- with tio do
- begin
- inputRaw :=
- ((c_iflag and (IGNBRK or BRKINT or PARMRK or ISTRIP or
- INLCR or IGNCR or ICRNL or IXON)) = 0) and
- ((c_lflag and (ECHO or ECHONL or ICANON or ISIG or IEXTEN)) = 0);
- outPutRaw :=
- ((c_oflag and OPOST) = 0) and
- ((c_cflag and (CSIZE or PARENB)) = 0) and
- ((c_cflag and CS8) <> 0);
- end;
- end;
- procedure restoreRawSettings(tio: {$IFDEF FPC_DOTTEDUNITS}UnixApi.{$ENDIF}TermIo.termios);
- begin
- with tio do
- begin
- if inputRaw then
- begin
- c_iflag := c_iflag and (not (IGNBRK or BRKINT or PARMRK or ISTRIP or
- INLCR or IGNCR or ICRNL or IXON));
- c_lflag := c_lflag and
- (not (ECHO or ECHONL or ICANON or ISIG or IEXTEN));
- c_cc[VMIN]:=1;
- c_cc[VTIME]:=0;
- end;
- if outPutRaw then
- begin
- c_oflag := c_oflag and not(OPOST);
- c_cflag := c_cflag and not(CSIZE or PARENB) or CS8;
- end;
- end;
- TCSetAttr(1,TCSANOW,tio);
- end;
- function DeduceOemCodePageFromLocale: TSystemCodePage;
- var
- lc: PAnsiChar;
- lc_str: AnsiString;
- function IsLocaleMatches(const current, wanted: AnsiString): boolean;
- var
- wanted_len: integer;
- begin
- wanted_len := length(wanted);
- if length(current) < wanted_len then
- begin
- IsLocaleMatches:=false;
- exit;
- end;
- if StrLComp(PAnsiChar(current), PAnsiChar(wanted), wanted_len) <> 0 then
- begin
- IsLocaleMatches:=false;
- exit;
- end;
- if length(current) = wanted_len then
- IsLocaleMatches:=true
- else
- IsLocaleMatches:=(current[wanted_len + 1] = '.');
- end;
- begin
- DeduceOemCodePageFromLocale := 437;
- lc := fpgetenv('LANG');
- if lc = nil then
- exit;
- lc_str := lc;
- if IsLocaleMatches(lc_str, 'af_ZA') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'ar_SA') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_LB') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_EG') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_DZ') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_BH') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_IQ') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_JO') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_KW') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_LY') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_MA') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_OM') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_QA') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_SY') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_TN') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_AE') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ar_YE') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'ast_ES') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'az_AZ') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'be_BY') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'bg_BG') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'br_FR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'ca_ES') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'zh_CN') then DeduceOemCodePageFromLocale := 936
- else if IsLocaleMatches(lc_str, 'zh_TW') then DeduceOemCodePageFromLocale := 950
- else if IsLocaleMatches(lc_str, 'kw_GB') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'cs_CZ') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'cy_GB') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'da_DK') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'de_AT') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'de_LI') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'de_LU') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'de_CH') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'de_DE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'el_GR') then DeduceOemCodePageFromLocale := 737
- else if IsLocaleMatches(lc_str, 'en_AU') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_CA') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_GB') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_IE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_JM') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_BZ') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_PH') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'en_ZA') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'en_TT') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'en_US') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'en_ZW') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'en_NZ') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_PA') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_BO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_CR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_DO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_SV') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_EC') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_GT') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_HN') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_NI') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_CL') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_MX') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_ES') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_CO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_PE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_AR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_PR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_VE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_UY') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'es_PY') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'et_EE') then DeduceOemCodePageFromLocale := 775
- else if IsLocaleMatches(lc_str, 'eu_ES') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fa_IR') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'fi_FI') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fo_FO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_FR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_BE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_CA') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_LU') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_MC') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'fr_CH') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'ga_IE') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'gd_GB') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'gv_IM') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'gl_ES') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'he_IL') then DeduceOemCodePageFromLocale := 862
- else if IsLocaleMatches(lc_str, 'hr_HR') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'hu_HU') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'id_ID') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'is_IS') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'it_IT') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'it_CH') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'iv_IV') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'ja_JP') then DeduceOemCodePageFromLocale := 932
- else if IsLocaleMatches(lc_str, 'kk_KZ') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'ko_KR') then DeduceOemCodePageFromLocale := 949
- else if IsLocaleMatches(lc_str, 'ky_KG') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'lt_LT') then DeduceOemCodePageFromLocale := 775
- else if IsLocaleMatches(lc_str, 'lv_LV') then DeduceOemCodePageFromLocale := 775
- else if IsLocaleMatches(lc_str, 'mk_MK') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'mn_MN') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'ms_BN') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'ms_MY') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'nl_BE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'nl_NL') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'nl_SR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'nn_NO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'nb_NO') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'pl_PL') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'pt_BR') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'pt_PT') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'rm_CH') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'ro_RO') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'ru_RU') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'sk_SK') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'sl_SI') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'sq_AL') then DeduceOemCodePageFromLocale := 852
- else if IsLocaleMatches(lc_str, 'sr_RS') then DeduceOemCodePageFromLocale := 855
- else if IsLocaleMatches(lc_str, 'sv_SE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'sv_FI') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'sw_KE') then DeduceOemCodePageFromLocale := 437
- else if IsLocaleMatches(lc_str, 'th_TH') then DeduceOemCodePageFromLocale := 874
- else if IsLocaleMatches(lc_str, 'tr_TR') then DeduceOemCodePageFromLocale := 857
- else if IsLocaleMatches(lc_str, 'tt_RU') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'uk_UA') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'ur_PK') then DeduceOemCodePageFromLocale := 720
- else if IsLocaleMatches(lc_str, 'uz_UZ') then DeduceOemCodePageFromLocale := 866
- else if IsLocaleMatches(lc_str, 'vi_VN') then DeduceOemCodePageFromLocale := 1258
- else if IsLocaleMatches(lc_str, 'wa_BE') then DeduceOemCodePageFromLocale := 850
- else if IsLocaleMatches(lc_str, 'zh_HK') then DeduceOemCodePageFromLocale := 950
- else if IsLocaleMatches(lc_str, 'zh_SG') then DeduceOemCodePageFromLocale := 936
- else if IsLocaleMatches(lc_str, 'zh_MO') then DeduceOemCodePageFromLocale := 950;
- end;
- procedure decide_codepages;
- var s:shortstring;
- begin
- if is_vga_code_page(external_codepage) then
- begin
- {Possible override...}
- s:=upcase(fpgetenv('CONSOLEFONT_CP'));
- if s='CP437' then
- external_codepage:=437
- else if s='CP850' then
- external_codepage:=850;
- end;
- {A non-vcsa Linux console can display most control characters, but not all.}
- case external_codepage of
- CP_ISO01: {West Europe}
- CurrentLegacy2EnhancedTranslationCodePage:=850;
- CP_ISO02: {East Europe}
- CurrentLegacy2EnhancedTranslationCodePage:=852;
- CP_ISO05: {Cyrillic}
- CurrentLegacy2EnhancedTranslationCodePage:=866;
- CP_UTF8:
- CurrentLegacy2EnhancedTranslationCodePage:=DeduceOemCodePageFromLocale;
- else
- if is_vga_code_page(external_codepage) then
- CurrentLegacy2EnhancedTranslationCodePage:=external_codepage
- else
- {We don't know how to convert to the external codepage. Use codepage
- 437 in the hope that the actual font has similarity to codepage 437.}
- CurrentLegacy2EnhancedTranslationCodePage:=437;
- end;
- end;
- procedure prepareInitVideo;
- begin
- TCGetAttr(1,preInitVideoTio);
- saveRawSettings(preInitVideoTio);
- end;
- procedure videoInitDone;
- begin
- TCGetAttr(1,postInitVideoTio);
- restoreRawSettings(postInitVideoTio);
- end;
- procedure prepareDoneVideo;
- var
- tio: {$IFDEF FPC_DOTTEDUNITS}UnixApi.{$ENDIF}TermIo.termios;
- begin
- TCGetAttr(1,tio);
- saveRawSettings(tio);
- TCSetAttr(1,TCSANOW,postInitVideoTio);
- end;
- procedure doneVideoDone;
- begin
- restoreRawSettings(preInitVideoTio);
- end;
- procedure SysInitVideo;
- var
- {$ifdef linux}
- FName: shortstring;
- {$endif linux}
- WS: packed record
- ws_row, ws_col, ws_xpixel, ws_ypixel: Word;
- end;
- { Err: Longint;}
- { prev_term : TerminalCommon_ptr1;}
- term:shortstring;
- i:word;
- {$ifdef Linux}
- s:string[15];
- {$endif}
- {$ifdef freebsd}
- ThisTTY: String[30];
- {$endif}
- envInput: string;
- const font_vga:array[0..11] of AnsiChar=#15#27'%@'#27'(U'#27'[3h';
- font_lat1:array[0..5] of AnsiChar=#27'%@'#27'(B';
- begin
- { check for tty }
- if (IsATTY(stdinputhandle)=1) then
- begin
- { save current terminal characteristics and remove rawness }
- prepareInitVideo;
- {$ifdef linux}
- { running on a tty, find out whether locally or remotely }
- TTyfd:=-1;
- {$endif linux}
- Console:=TTyNetwork; {Default: Network or other vtxxx tty}
- cur_term_strings:=@term_codes_vt100; {Default: vt100}
- external_codepage:=CP_ISO01; {Default: ISO-8859-1}
- if UTF8Enabled then
- external_codepage:=CP_UTF8;
- {$ifdef linux}
- if (vcs_device>=0) and (external_codepage<>CP_UTF8) then
- begin
- str(vcs_device,s);
- fname:='/dev/vcsa'+s;
- { open console, $1b6=rw-rw-rw- }
- ttyfd:=fpopen(fname,$1b6,O_RDWR);
- if ttyfd<>-1 then
- begin
- console:=ttylinux;
- external_codepage:=437; {VCSA defaults to codepage 437.}
- end
- else
- if try_grab_vcsa then
- begin
- ttyfd:=fpopen(fname,$1b6,O_RDWR);
- if ttyfd<>-1 then
- begin
- console:=ttylinux;
- external_codepage:=437; {VCSA defaults to codepage 437.}
- end;
- end;
- end;
- {$endif}
- {$ifdef freebsd}
- ThisTTY:=TTYName(stdinputhandle);
- if copy(ThisTTY, 1, 9) = '/dev/ttyv' then {FreeBSD has these}
- begin
- { check for (Free?)BSD native}
- if (ThisTTY[10]>='0') and (ThisTTY[10]<='9') Then
- Console:=ttyFreeBSD; {TTYFd ?}
- end;
- {$endif}
- term:=fpgetenv('TERM');
- for i:=low(terminal_names) to high(terminal_names) do
- if copy(term,1,length(terminal_names[i]))=terminal_names[i] then
- cur_term_strings:=terminal_data[i];
- if cur_term_strings=@term_codes_xterm then
- begin
- {$ifdef haiku}
- TerminalSupportsBold := true;
- TerminalSupportsHighIntensityColors := false;
- {$else}
- TerminalSupportsBold := false;
- TerminalSupportsHighIntensityColors := true;
- {$endif}
- end
- else
- begin
- TerminalSupportsBold := true;
- TerminalSupportsHighIntensityColors := false;
- end;
- if cur_term_strings=@term_codes_beos then
- begin
- TerminalSupportsBold := false;
- TerminalSupportsHighIntensityColors := false;
- end;
- if cur_term_strings=@term_codes_freebsd then
- console:=ttyFreeBSD;
- {$ifdef linux}
- if (console<>ttylinux) then
- begin
- {$endif}
- if cur_term_strings=@term_codes_linux then
- begin
- if external_codepage<>CP_UTF8 then
- begin
- {Enable the VGA character set (codepage 437,850,....)}
- fpwrite(stdoutputhandle,font_vga,sizeof(font_vga));
- external_codepage:=437; {Now default to codepage 437.}
- end;
- end
- else
- begin
- if external_codepage<>CP_UTF8 then
- begin
- {No VGA font :( }
- fpwrite(stdoutputhandle,font_lat1,sizeof(font_lat1));
- end;
- { running on a remote terminal, no error with /dev/vcsa }
- end;
- {$ifdef linux}
- end;
- {$endif}
- fpioctl(stdinputhandle, TIOCGWINSZ, @WS);
- if WS.ws_Col=0 then
- WS.ws_Col:=80;
- if WS.ws_Row=0 then
- WS.ws_Row:=25;
- ScreenWidth:=WS.ws_Col;
- { TDrawBuffer only has FVMaxWidth elements
- larger values lead to crashes }
- if ScreenWidth> FVMaxWidth then
- ScreenWidth:=FVMaxWidth;
- ScreenHeight:=WS.ws_Row;
- CursorX:=0;
- CursorY:=0;
- LastCursorType:=$ff;
- ScreenColor:=True;
- { Start with a clear screen }
- {$ifdef linux}
- if Console<>ttylinux then
- begin
- {$endif}
- SendEscapeSeqNdx(enter_ca_mode);
- SendEscapeSeqNdx(cursor_home);
- SendEscapeSeqNdx(cursor_normal);
- SendEscapeSeqNdx(cursor_visible_underline);
- SetCursorType(crUnderLine);
- If Console=ttyFreeBSD Then
- SendEscapeSeqNdx(exit_am_mode);
- {$ifdef linux}
- end;
- {$endif}
- { Always true because of vt100 default...
- if assigned(cur_term_Strings) then
- begin}
- ACSIn:=StrPas(cur_term_strings^[enter_alt_charset_mode]);
- ACSOut:=StrPas(cur_term_strings^[exit_alt_charset_mode]);
- if (ACSIn<>'') and (ACSOut<>'') then
- SendEscapeSeqNdx(ena_acs);
- (* If fpGetEnv('TERM')='xterm' then
- convert:=cv_vga_to_acs; {use of acs for xterm is ok}*)
- { end
- else
- begin
- ACSIn:='';
- ACSOut:='';
- end;}
- {$ifdef logging}
- assign(f,'video.log');
- rewrite(f,1);
- {$endif logging}
- { save new terminal characteristics and possible restore rawness }
- videoInitDone;
- decide_codepages;
- envInput := LowerCase(fpgetenv('TV_INPUT'));
- if (envInput = '') or (envInput = 'kitty') then
- SendEscapeSeq(#27'[>31u');{Entering alternativ screen we have to set up kitty keys}
- end
- else
- ErrorCode:=errVioInit; { not a TTY }
- end;
- procedure SysDoneVideo;
- var font_custom:array[0..2] of AnsiChar=#27'(K';
- begin
- SendEscapeSeq(#27'[<u'); { kitty keys disable }
- prepareDoneVideo;
- SetCursorType(crUnderLine);
- {$ifdef linux}
- if Console=ttylinux then
- SetCursorPos(0,0)
- else
- begin
- {$endif}
- SendEscapeSeqNdx(cursor_home);
- SendEscapeSeqNdx(cursor_normal);
- SendEscapeSeqNdx(cursor_visible_underline);
- SendEscapeSeq(#27'[H');
- SendEscapeSeqNdx(exit_ca_mode);
- if cur_term_strings=@term_codes_linux then
- begin
- {Executed in case ttylinux is false (i.e. no vcsa), but
- TERM=linux.}
- { if we're in utf8 mode, we didn't change the font, so
- no need to restore anything }
- if external_codepage<>CP_UTF8 then
- begin
- {Enable the character set set through setfont}
- fpwrite(stdoutputhandle,font_custom,3);
- end;
- end;
- {$ifdef linux}
- end;
- {$endif}
- ACSIn:='';
- ACSOut:='';
- doneVideoDone;
- {$ifdef logging}
- close(f);
- {$endif logging}
- end;
- procedure SysClearScreen;
- begin
- {$ifdef linux}
- if Console=ttylinux then
- UpdateScreen(true)
- else
- begin
- {$endif}
- SendEscapeSeq(#27'[0m');
- SendEscapeSeqNdx(clear_screen);
- {$ifdef linux}
- end;
- {$endif}
- end;
- procedure SysUpdateScreen(Force: Boolean);
- var
- I: Integer;
- begin
- {$ifdef linux}
- if console=ttylinux then
- update_vcsa(force)
- else
- {$endif}
- updateTTY(force);
- if VideoInitialized then
- begin
- move(VideoBuf^,OldVideoBuf^,VideoBufSize);
- end else
- begin
- for I := Low(EnhancedVideoBuf) to High(EnhancedVideoBuf) do
- OldEnhancedVideoBuf[I] := EnhancedVideoBuf[I];
- end;
- end;
- function SysGetCapabilities: Word;
- begin
- { about cpColor... we should check the terminfo database... }
- SysGetCapabilities:=cpUnderLine + cpBlink + cpColor;
- end;
- procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
- {$ifdef linux}
- var
- Pos : array [1..2] of Byte;
- {$endif linux}
- begin
- if (CursorX=NewCursorX) and (CursorY=NewCursorY) then
- exit;
- {$ifdef linux}
- if Console=ttylinux then
- begin
- Pos[1]:=NewCursorX;
- Pos[2]:=NewCursorY;
- fppwrite(ttyfd,pos,2,2);
- end
- else
- {$endif}
- { newcursorx,y and CursorX,Y are 0 based ! }
- SendEscapeSeq(XY2Ansi(NewCursorX+1,NewCursorY+1,CursorX+1,CursorY+1));
- CursorX:=NewCursorX;
- CursorY:=NewCursorY;
- end;
- function SysGetCursorType: Word;
- begin
- SysGetCursorType:=LastCursorType;
- end;
- procedure SysSetCursorType(NewType: Word);
- begin
- If LastCursorType=NewType then
- exit;
- LastCursorType:=NewType;
- case NewType of
- crBlock:
- SendEscapeSeqNdx(cursor_visible_block);
- crUnderLine:
- SendEscapeSeqNdx(cursor_visible_underline);
- crHidden:
- SendEscapeSeqNdx(cursor_invisible);
- else
- SendEscapeSeqNdx(cursor_normal);
- end;
- end;
- function SysSetVideoMode(const mode:Tvideomode):boolean;
- var winsize:Twinsize;
- begin
- {Due to xterm resize this procedure might get called with the new xterm
- size. Approve the video mode change if the new size equals that of
- the terminal window size.}
- SysSetVideoMode:=false;
- fpioctl(stdinputhandle,TIOCGWINSZ,@winsize);
- if (mode.row=winsize.ws_row) and
- (mode.col=winsize.ws_col) then
- begin
- screenwidth:=mode.col;
- screenheight:=mode.row;
- screencolor:=true;
- SysSetVideoMode:=true;
- end;
- end;
- Const
- SysVideoDriver : TVideoDriver = (
- InitDriver : nil;
- InitEnhancedDriver: @SysInitVideo;
- DoneDriver : @SysDoneVideo;
- UpdateScreen : @SysUpdateScreen;
- UpdateScreenArea : Nil;
- ClearScreen : @SysClearScreen;
- SetVideoMode : @SysSetVideoMode;
- GetVideoModeCount : Nil;
- GetVideoModeData : Nil;
- SetCursorPos : @SysSetCursorPos;
- GetCursorType : @SysGetCursorType;
- SetCursorType : @SysSetCursorType;
- GetCapabilities : @SysGetCapabilities;
- GetActiveCodePage : Nil;
- ActivateCodePage : Nil;
- GetSupportedCodePageCount : Nil;
- GetSupportedCodePage : Nil;
- );
- initialization
- SetVideoDriver(SysVideoDriver);
- end.
|