12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897 |
- /*
- Copyright (C) 2004, 2005, 2006 John E. Davis
- This file is part of the S-Lang Library.
- The S-Lang Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
- The S-Lang Library 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. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA.
- */
- #include "slinclud.h"
- #include <time.h>
- #include <ctype.h>
- #if !defined(VMS) || (__VMS_VER >= 70000000)
- # include <sys/time.h>
- # ifdef __QNX__
- # include <sys/select.h>
- # endif
- # include <sys/types.h>
- #endif
- #ifdef __BEOS__
- /* Prototype for select */
- # include <net/socket.h>
- #endif
- #ifdef HAVE_TERMIOS_H
- # include <termios.h>
- #endif
- #ifdef VMS
- # include <unixlib.h>
- # include <unixio.h>
- # include <dvidef.h>
- # include <descrip.h>
- # include <lib$routines.h>
- # include <starlet.h>
- #else
- # if !defined(sun)
- # include <sys/ioctl.h>
- # endif
- #endif
- #ifdef SYSV
- # include <sys/termio.h>
- # include <sys/stream.h>
- # include <sys/ptem.h>
- # include <sys/tty.h>
- #endif
- #if defined (_AIX) && !defined (FD_SET)
- # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
- #endif
- #include <errno.h>
- #if defined(__DECC) && defined(VMS)
- /* These get prototypes for write an sleep */
- # include <unixio.h>
- #endif
- #include <signal.h>
- #include "slang.h"
- #include "_slang.h"
- /* Colors: These definitions are used for the display. However, the
- * application only uses object handles which get mapped to this
- * internal representation. The mapping is performed by the Color_Map
- * structure below. */
- #define CHAR_MASK 0x000000FF
- #define FG_MASK 0x0000FF00
- #define BG_MASK 0x00FF0000
- #define ATTR_MASK 0x1F000000
- #define BGALL_MASK 0x0FFF0000
- /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
- * not include this attribute.
- */
- #define GET_FG(fgbg) (((fgbg) & FG_MASK) >> 8)
- #define GET_BG(fgbg) (((fgbg) & BG_MASK) >> 16)
- #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
- int SLtt_Screen_Cols = 80;
- int SLtt_Screen_Rows = 24;
- int SLtt_Term_Cannot_Insert;
- int SLtt_Term_Cannot_Scroll;
- int SLtt_Use_Ansi_Colors;
- int SLtt_Blink_Mode = 0;
- int SLtt_Use_Blink_For_ACS = 0;
- int SLtt_Newline_Ok = 0;
- int SLtt_Has_Alt_Charset = 0;
- int SLtt_Force_Keypad_Init = 0;
- /* static int UTF8_Mode = -1; */
- void (*_pSLtt_color_changed_hook)(void);
- #if SLTT_HAS_NON_BCE_SUPPORT
- static int Bce_Color_Offset = 0;
- #endif
- static int Can_Background_Color_Erase = 1;
- /* -1 means unknown */
- int SLtt_Has_Status_Line = -1; /* hs */
- int SLang_TT_Write_FD = -1;
- static int Automatic_Margins;
- /* static int No_Move_In_Standout; */
- static int Worthless_Highlight;
- #define HP_GLITCH_CODE
- #ifdef HP_GLITCH_CODE
- /* This glitch is exclusive to HP term. Basically it means that to clear
- * attributes, one has to erase to the end of the line.
- */
- static int Has_HP_Glitch;
- #endif
- static char *Reset_Color_String;
- static int Is_Color_Terminal = 0;
- static int Linux_Console;
- static int QANSI_Console;
- static int Mouse_Mode = -1;
- /* The following comment is nolonger valid, but is here in case there are
- * some apps that use SLtt_Use_Blink_For_ACS and still need porting to v2.
- * -------
- * It is crucial that JMAX_COLORS must be less than 128 since the high bit
- * is used to indicate a character from the ACS (alt char set). The exception
- * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
- * the highbit is set, we interpret that as a blink character. This is
- * exploited by DOSemu.
- */
- #define JMAX_COLORS 512
- #define JNORMAL_COLOR 0
- typedef struct
- {
- SLtt_Char_Type fgbg;
- SLtt_Char_Type mono;
- }
- Brush_Info_Type;
- static Brush_Info_Type Brush_Table[JMAX_COLORS];
- /* 0 if least significant bit is blue, not red */
- /* static int Is_Fg_BGR = 0; */
- static int Is_Bg_BGR = 0;
- #define COLOR_ARG(color, is_bgr) ((is_bgr) ? RGB_to_BGR[(color)&0x7] : (color))
- static SLCONST int RGB_to_BGR[] =
- {
- 0, 4, 2, 6, 1, 5, 3, 7
- };
- static char *Color_Fg_Str = "\033[3%dm";
- static char *Color_Bg_Str = "\033[4%dm";
- static char *Default_Color_Fg_Str = "\033[39m";
- static char *Default_Color_Bg_Str = "\033[49m";
- static int Max_Terminfo_Colors = 8; /* termcap Co */
- char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
- /* 1 if terminal lacks the ability to go into insert mode or into delete
- mode. Currently controlled by S-Lang but later perhaps termcap. */
- static char *UnderLine_Vid_Str;
- static char *Blink_Vid_Str;
- static char *Bold_Vid_Str;
- static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
- static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
- static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
- static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
- static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
- static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
- static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
- static char *Del_Bol_Str; /* = "\033[1K"; */ /* cb */
- static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
- static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
- static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
- static char *Rev_Scroll_Str;
- static char *Curs_Up_Str;
- static char *Curs_F_Str; /* RI termcap string */
- static char *Cursor_Visible_Str; /* ve termcap string */
- static char *Cursor_Invisible_Str; /* vi termcap string */
- #if 0
- static char *Start_Mouse_Rpt_Str; /* Start mouse reporting mode */
- static char *End_Mouse_Rpt_Str; /* End mouse reporting mode */
- #endif
- static char *Start_Alt_Chars_Str; /* as */
- static char *End_Alt_Chars_Str; /* ae */
- static char *Enable_Alt_Char_Set; /* eA */
- static char *Term_Init_Str;
- static char *Keypad_Init_Str;
- static char *Term_Reset_Str;
- static char *Keypad_Reset_Str;
- /* status line functions */
- static char *Disable_Status_line_Str; /* ds */
- static char *Return_From_Status_Line_Str; /* fs */
- static char *Goto_Status_Line_Str; /* ts */
- static int Num_Status_Line_Columns; /* ws */
- /* static int Status_Line_Esc_Ok; */ /* es */
- /* static int Len_Curs_F_Str = 5; */
- /* cm string has %i%d since termcap numbers columns from 0 */
- /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
- static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
- /* scrolling region */
- static int Scroll_r1 = 0, Scroll_r2 = 23;
- static int Cursor_r, Cursor_c; /* 0 based */
- /* current attributes --- initialized to impossible value */
- static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
- static int Cursor_Set; /* 1 if cursor position known, 0
- * if not. -1 if only row is known
- */
- #define MAX_OUTPUT_BUFFER_SIZE 4096
- static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
- static unsigned char *Output_Bufferp = Output_Buffer;
- unsigned long SLtt_Num_Chars_Output;
- int _pSLusleep (unsigned long usecs)
- {
- #if !defined(VMS) || (__VMS_VER >= 70000000)
- struct timeval tv;
- tv.tv_sec = usecs / 1000000;
- tv.tv_usec = usecs % 1000000;
- return select(0, NULL, NULL, NULL, &tv);
- #else
- return 0;
- #endif
- }
- int SLtt_flush_output (void)
- {
- int nwrite = 0;
- unsigned int total;
- int n = (int) (Output_Bufferp - Output_Buffer);
- SLtt_Num_Chars_Output += n;
- total = 0;
- while (n > 0)
- {
- nwrite = write (SLang_TT_Write_FD, (char *) Output_Buffer + total, n);
- if (nwrite == -1)
- {
- nwrite = 0;
- #ifdef EAGAIN
- if (errno == EAGAIN)
- {
- _pSLusleep (100000); /* 1/10 sec */
- continue;
- }
- #endif
- #ifdef EWOULDBLOCK
- if (errno == EWOULDBLOCK)
- {
- _pSLusleep (100000);
- continue;
- }
- #endif
- #ifdef EINTR
- if (errno == EINTR) continue;
- #endif
- break;
- }
- n -= nwrite;
- total += nwrite;
- }
- Output_Bufferp = Output_Buffer;
- return n;
- }
- int SLtt_Baud_Rate;
- static void tt_write(char *str, unsigned int n)
- {
- static unsigned long last_time;
- static int total;
- unsigned long now;
- unsigned int ndiff;
- if ((str == NULL) || (n == 0)) return;
- total += n;
- while (1)
- {
- ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
- if (ndiff < n)
- {
- SLMEMCPY ((char *) Output_Bufferp, str, ndiff);
- Output_Bufferp += ndiff;
- SLtt_flush_output ();
- n -= ndiff;
- str += ndiff;
- }
- else
- {
- SLMEMCPY ((char *) Output_Bufferp, str, n);
- Output_Bufferp += n;
- break;
- }
- }
- if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
- && (10 * total > SLtt_Baud_Rate))
- {
- total = 0;
- if ((now = (unsigned long) time(NULL)) - last_time <= 1)
- {
- SLtt_flush_output ();
- sleep((unsigned) 1);
- }
- last_time = now;
- }
- }
- static void tt_write_string (char *str)
- {
- if (str != NULL) tt_write(str, strlen(str));
- }
- void SLtt_write_string (char *str)
- {
- tt_write_string (str);
- Cursor_Set = 0;
- }
- void SLtt_putchar (char ch)
- {
- SLtt_normal_video ();
- if (Cursor_Set == 1)
- {
- if (ch >= ' ') Cursor_c++;
- else if (ch == '\b') Cursor_c--;
- else if (ch == '\r') Cursor_c = 0;
- else Cursor_Set = 0;
- if ((Cursor_c + 1 == SLtt_Screen_Cols)
- && Automatic_Margins) Cursor_Set = 0;
- }
- if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
- {
- *Output_Bufferp++ = (unsigned char) ch;
- }
- else tt_write (&ch, 1);
- }
- static unsigned int tt_sprintf(char *buf, unsigned int buflen, char *fmt, int x, int y)
- {
- char *fmt_max;
- unsigned char *b, *bmax, ch;
- int offset;
- int z, z1, parse_level;
- int zero_pad;
- int field_width;
- int variables [26];
- int stack [64];
- unsigned int stack_len;
- int parms [10];
- #define STACK_POP (stack_len ? stack[--stack_len] : 0)
- if (fmt == NULL)
- {
- *buf = 0;
- return 0;
- }
- stack [0] = y; /* pushed for termcap */
- stack [1] = x;
- stack_len = 2;
- parms [1] = x; /* p1 */
- parms [2] = y; /* p2 */
- offset = 0;
- zero_pad = 0;
- field_width = 0;
- b = (unsigned char *) buf;
- bmax = b + buflen;
- fmt_max = fmt + strlen (fmt);
- while ((fmt < fmt_max) && (b < bmax))
- {
- ch = *fmt++;
- if (ch != '%')
- {
- *b++ = ch;
- continue;
- }
- if (fmt == fmt_max) break;
- ch = *fmt++;
- switch (ch)
- {
- default:
- *b++ = ch;
- break;
- case 'p':
- if (fmt == fmt_max) break;
- ch = *fmt++;
- if ((ch >= '0') && (ch <= '9'))
- stack [stack_len++] = parms [ch - '0'];
- break;
- case '\'': /* 'x' */
- if (fmt == fmt_max) break;
- stack [stack_len++] = *fmt++;
- if (fmt < fmt_max) fmt++; /* skip ' */
- break;
- case '{': /* literal constant, e.g. {30} */
- z = 0;
- while ((fmt < fmt_max) && ((ch = *fmt) <= '9') && (ch >= '0'))
- {
- z = z * 10 + (ch - '0');
- fmt++;
- }
- stack [stack_len++] = z;
- if ((ch == '}') && (fmt < fmt_max)) fmt++;
- break;
- case '0':
- if (fmt == fmt_max) break;
- ch = *fmt;
- if ((ch != '2') && (ch != '3'))
- break;
- zero_pad = 1;
- fmt++;
- /* drop */
- case '2':
- case '3':
- if (fmt == fmt_max) break;
- if (*fmt == 'x')
- {
- char x_fmt_buf [4];
- char *x_fmt_buf_ptr;
- x_fmt_buf_ptr = x_fmt_buf;
- if (zero_pad) *x_fmt_buf_ptr++ = '0';
- *x_fmt_buf_ptr++ = ch;
- *x_fmt_buf_ptr++ = 'X';
- *x_fmt_buf_ptr = 0;
- z = STACK_POP;
- z += offset;
- sprintf ((char *)b, x_fmt_buf, z);
- b += strlen ((char *)b);
- zero_pad = 0;
- break;
- }
- field_width = (ch - '0');
- /* drop */
- case 'd':
- z = STACK_POP;
- z += offset;
- if (z >= 100)
- {
- *b++ = z / 100 + '0';
- z = z % 100;
- zero_pad = 1;
- field_width = 2;
- }
- else if (zero_pad && (field_width == 3))
- *b++ = '0';
- if (b == bmax) break;
- if (z >= 10)
- {
- *b++ = z / 10 + '0';
- z = z % 10;
- }
- else if (zero_pad && (field_width >= 2))
- *b++ = '0';
- if (b == bmax) break;
- *b++ = z + '0';
- field_width = zero_pad = 0;
- break;
- case 'x':
- z = STACK_POP;
- z += offset;
- if (b + 16 >= bmax)
- break;
- sprintf ((char *) b, "%X", z);
- b += strlen ((char *)b);
- break;
- case 'i':
- offset = 1;
- break;
- case '+':
- /* Handling this depends upon whether or not we are parsing
- * terminfo. Terminfo requires the stack so use it as an
- * indicator.
- */
- if (stack_len > 2)
- {
- z = STACK_POP;
- stack [stack_len - 1] += z;
- }
- else if (fmt < fmt_max)
- {
- ch = *fmt++;
- if ((unsigned char) ch == 128) ch = 0;
- ch = ch + (unsigned char) STACK_POP;
- if (ch == '\n') ch++;
- *b++ = ch;
- }
- break;
- /* Binary operators */
- case '-':
- case '*':
- case '/':
- case 'm':
- case '&':
- case '|':
- case '^':
- case '=':
- case '>':
- case '<':
- case 'A':
- case 'O':
- z1 = STACK_POP;
- z = STACK_POP;
- switch (ch)
- {
- case '-': z = (z - z1); break;
- case '*': z = (z * z1); break;
- case '/': z = (z / z1); break;
- case 'm': z = (z % z1); break;
- case '&': z = (z & z1); break;
- case '|': z = (z | z1); break;
- case '^': z = (z ^ z1); break;
- case '=': z = (z == z1); break;
- case '>': z = (z > z1); break;
- case '<': z = (z < z1); break;
- case 'A': z = (z && z1); break;
- case 'O': z = (z || z1); break;
- }
- stack [stack_len++] = z;
- break;
- /* unary */
- case '!':
- z = STACK_POP;
- stack [stack_len++] = !z;
- break;
- case '~':
- z = STACK_POP;
- stack [stack_len++] = ~z;
- break;
- case 'r': /* termcap -- swap parameters */
- z = stack [0];
- stack [0] = stack [1];
- stack [1] = z;
- break;
- case '.': /* termcap */
- case 'c':
- ch = (unsigned char) STACK_POP;
- if (ch == '\n') ch++;
- *b++ = ch;
- break;
- case 'g':
- if (fmt == fmt_max) break;
- ch = *fmt++;
- if ((ch >= 'a') && (ch <= 'z'))
- stack [stack_len++] = variables [ch - 'a'];
- break;
- case 'P':
- if (fmt == fmt_max) break;
- ch = *fmt++;
- if ((ch >= 'a') && (ch <= 'z'))
- variables [ch - 'a'] = STACK_POP;
- break;
- /* If then else parsing. Actually, this is rather easy. The
- * key is to notice that 'then' does all the work. 'if' simply
- * there to indicate the start of a test and endif indicates
- * the end of tests. If 'else' is seen, then skip to
- * endif.
- */
- case '?': /* if */
- case ';': /* endif */
- break;
- case 't': /* then */
- z = STACK_POP;
- if (z != 0)
- break; /* good. Continue parsing. */
- /* z == 0 and test has failed. So, skip past this entire if
- * expression to the matching else or matching endif.
- */
- /* drop */
- case 'e': /* else */
- parse_level = 0;
- while (fmt < fmt_max)
- {
- unsigned char ch1;
- ch1 = *fmt++;
- if ((ch1 != '%') || (fmt == fmt_max))
- continue;
- ch1 = *fmt++;
- if (ch1 == '?') parse_level++; /* new if */
- else if (ch1 == 'e')
- {
- if ((ch != 'e') && (parse_level == 0))
- break;
- }
- else if (ch1 == ';')
- {
- if (parse_level == 0)
- break;
- parse_level--;
- }
- }
- break;
- }
- }
- if (b >= bmax)
- b = bmax - 1;
- *b = 0;
- return (unsigned int) (b - (unsigned char *) buf);
- }
- static void tt_printf(char *fmt, int x, int y)
- {
- char buf[1024];
- unsigned int n;
- if (fmt == NULL) return;
- n = tt_sprintf(buf, sizeof (buf), fmt, x, y);
- tt_write(buf, n);
- }
- void SLtt_set_scroll_region (int r1, int r2)
- {
- Scroll_r1 = r1;
- Scroll_r2 = r2;
- tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
- Cursor_Set = 0;
- }
- void SLtt_reset_scroll_region (void)
- {
- SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
- }
- int SLtt_set_cursor_visibility (int show)
- {
- if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
- return -1;
- tt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
- return 0;
- }
- /* the goto_rc function moves to row relative to scrolling region */
- void SLtt_goto_rc(int r, int c)
- {
- char *s = NULL;
- int n;
- char buf[6];
- if ((c < 0) || (r < 0))
- {
- Cursor_Set = 0;
- return;
- }
- /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
- r += Scroll_r1;
- if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
- {
- n = r - Cursor_r;
- if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
- && (Curs_Up_Str != NULL))
- {
- s = Curs_Up_Str;
- }
- else if ((n >= 0) && (n <= 4))
- {
- if ((n == 0) && (Cursor_Set == 1)
- && ((c > 1) || (c == Cursor_c)))
- {
- if (Cursor_c == c) return;
- if (Cursor_c == c + 1)
- {
- /* cursor movement optimizations, like backspace
- doesn't work as needed on qansi-m consoles when
- current table is not a G0, so we'll disable it. */
- if (!QANSI_Console)
- {
- s = buf;
- *s++ = '\b'; *s = 0;
- s = buf;
- }
- else
- {
- /* do the generic cursor positioning,
- without an optimization */
- s = NULL;
- }
- }
- }
- else if ((c == 0) && (!QANSI_Console)) /* the same things
- for the qansi-m console limitation */
- {
- s = buf;
- if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
- while (n--) *s++ = '\n';
- #ifdef VMS
- /* Need to add this after \n to start a new record. Sheesh. */
- *s++ = '\r';
- #endif
- *s = 0;
- s = buf;
- }
- /* Will fail on VMS */
- #ifndef VMS
- else if ((SLtt_Newline_Ok && (Cursor_Set == 1) &&
- (Cursor_c >= c) && (c + 3 > Cursor_c)) &&
- (!QANSI_Console))
- {
- s = buf;
- while (n--) *s++ = '\n';
- n = Cursor_c - c;
- while (n--) *s++ = '\b';
- *s = 0;
- s = buf;
- }
- #endif
- }
- }
- if (s != NULL) tt_write_string(s);
- else tt_printf(Curs_Pos_Str, r, c);
- Cursor_c = c; Cursor_r = r;
- Cursor_Set = 1;
- }
- void SLtt_begin_insert (void)
- {
- tt_write_string(Ins_Mode_Str);
- }
- void SLtt_end_insert (void)
- {
- tt_write_string(Eins_Mode_Str);
- }
- void SLtt_delete_char (void)
- {
- SLtt_normal_video ();
- tt_write_string(Del_Char_Str);
- }
- void SLtt_erase_line (void)
- {
- tt_write ("\r", 1);
- Cursor_Set = 1; Cursor_c = 0;
- SLtt_del_eol();
- /* Put the cursor back at the beginning of the line */
- tt_write ("\r", 1);
- Cursor_Set = 1; Cursor_c = 0;
- }
- /* It appears that the Linux console, and most likely others do not
- * like scrolling regions that consist of one line. So I have to
- * resort to this stupidity to make up for that stupidity.
- */
- static void delete_line_in_scroll_region (void)
- {
- SLtt_goto_rc (Cursor_r - Scroll_r1, 0);
- SLtt_del_eol ();
- }
- void SLtt_delete_nlines (int nn)
- {
- int r1, curs;
- unsigned int n;
- if (nn <= 0) return;
- n = (unsigned int) nn;
- SLtt_normal_video ();
- if (Scroll_r1 == Scroll_r2)
- {
- delete_line_in_scroll_region ();
- return;
- }
- if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str, n, 0);
- else
- /* get a new terminal */
- {
- char buf[80];
- unsigned int dn = n;
- if (dn > sizeof (buf))
- dn = sizeof (buf);
- SLMEMSET (buf, '\n', dn);
- while (n > dn)
- {
- tt_write (buf, dn);
- n -= dn;
- }
- tt_write (buf, n);
- r1 = Scroll_r1;
- curs = Cursor_r;
- SLtt_set_scroll_region(curs, Scroll_r2);
- SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
- SLMEMSET(buf, '\n', (unsigned int) n);
- tt_write(buf, (unsigned int) n);
- /* while (n--) tt_putchar('\n'); */
- SLtt_set_scroll_region(r1, Scroll_r2);
- SLtt_goto_rc(curs, 0);
- }
- }
- void SLtt_cls (void)
- {
- /* If the terminal is a color terminal but the user wants black and
- * white, then make sure that the colors are reset. This appears to be
- * necessary.
- */
- if ((SLtt_Use_Ansi_Colors == 0) && Is_Color_Terminal)
- {
- if (Reset_Color_String != NULL)
- tt_write_string (Reset_Color_String);
- else
- tt_write ("\033[0m\033[m", 7);
- }
- SLtt_normal_video();
- SLtt_reset_scroll_region ();
- tt_write_string(Cls_Str);
- }
- void SLtt_reverse_index (int n)
- {
- if (!n) return;
- SLtt_normal_video();
- if (Scroll_r1 == Scroll_r2)
- {
- delete_line_in_scroll_region ();
- return;
- }
- if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
- else
- {
- while(n--) tt_write_string(Rev_Scroll_Str);
- }
- }
- int SLtt_Ignore_Beep = 1;
- static char *Visible_Bell_Str;
- void SLtt_beep (void)
- {
- if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
- if (SLtt_Ignore_Beep & 0x2)
- {
- if (Visible_Bell_Str != NULL) tt_write_string (Visible_Bell_Str);
- #ifdef __linux__
- else if (Linux_Console)
- {
- tt_write ("\033[?5h", 5);
- SLtt_flush_output ();
- _pSLusleep (50000);
- tt_write ("\033[?5l", 5);
- }
- #endif
- }
- SLtt_flush_output ();
- }
- static void write_string_with_care (char *);
- static void del_eol (void)
- {
- #if 0
- int c;
- #endif
- if ((Del_Eol_Str != NULL)
- && (Can_Background_Color_Erase || ((Current_Fgbg & ~0xFF) == 0)))
- {
- tt_write_string(Del_Eol_Str);
- return;
- }
- #if 0
- c = Cursor_c;
-
- /* Avoid writing to the lower right corner. If the terminal does not
- * have Del_Eol_Str, then it probably does not have what it takes to play
- * games with insert-mode to "push" the desired character into that corner.
- */
- if (Cursor_r + 1 < SLtt_Screen_Rows)
- c++;
- while (c < SLtt_Screen_Cols)
- {
- tt_write (" ", 1);
- c++;
- }
- Cursor_c = (SLtt_Screen_Cols-1);
- #else
- while (Cursor_c < SLtt_Screen_Cols)
- {
- write_string_with_care (" ");
- Cursor_c++;
- }
- Cursor_c = SLtt_Screen_Cols - 1;
- Cursor_Set = 0;
- #endif
- }
- void SLtt_del_eol (void)
- {
- if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
- del_eol ();
- }
- typedef SLCONST struct
- {
- char *name;
- SLtt_Char_Type color;
- }
- Color_Def_Type;
- #define MAX_COLOR_NAMES 17
- static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
- {
- {"black", SLSMG_COLOR_BLACK},
- {"red", SLSMG_COLOR_RED},
- {"green", SLSMG_COLOR_GREEN},
- {"brown", SLSMG_COLOR_BROWN},
- {"blue", SLSMG_COLOR_BLUE},
- {"magenta", SLSMG_COLOR_MAGENTA},
- {"cyan", SLSMG_COLOR_CYAN},
- {"lightgray", SLSMG_COLOR_LGRAY},
- {"gray", SLSMG_COLOR_GRAY},
- {"brightred", SLSMG_COLOR_BRIGHT_RED},
- {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
- {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
- {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
- {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
- {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
- {"white", SLSMG_COLOR_BRIGHT_WHITE},
- #define SLSMG_COLOR_DEFAULT 0xFF
- {"default", SLSMG_COLOR_DEFAULT}
- };
- static int Brushes_Initialized = 0;
- static int initialize_brushes (void)
- {
- int fg, bg;
- Brush_Info_Type *b, *bmax;
- b = Brush_Table;
- bmax = b + JMAX_COLORS;
- bg = 0;
- while (b < bmax)
- {
- fg = 7;
- while (b < bmax)
- {
- if (fg != bg)
- {
- b->fgbg = MAKE_COLOR(fg,bg);
- b->mono = SLTT_REV_MASK;
- b++;
- }
- if (fg == 0)
- break;
- fg--;
- }
- bg++;
- if (bg == 8)
- bg = 0;
- }
- Brush_Table[0].mono = 0;
- Brushes_Initialized = 1;
- return 0;
- }
-
-
- static Brush_Info_Type *get_brush_info (unsigned int color)
- {
- if (Brushes_Initialized == 0)
- initialize_brushes ();
- color &= SLSMG_COLOR_MASK;
- if (color >= JMAX_COLORS)
- color = 0;
- return Brush_Table + color;
- }
- static SLtt_Char_Type get_brush_attr (unsigned int color)
- {
- Brush_Info_Type *b;
-
- if (NULL == (b = get_brush_info (color)))
- return (SLtt_Char_Type)-1;
-
- if (SLtt_Use_Ansi_Colors)
- return b->fgbg;
-
- return b->mono;
- }
- static SLtt_Char_Type get_brush_fgbg (unsigned int color)
- {
- return get_brush_info(color)->fgbg;
- }
- int SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
- {
- Brush_Info_Type *b;
- (void) what;
- if (NULL == (b = get_brush_info (obj)))
- return -1;
-
- b->mono = mask & ATTR_MASK;
- return 0;
- }
- static char *check_color_for_digit_form (char *color)
- {
- unsigned int i, ich;
- unsigned char *s = (unsigned char *) color;
- i = 0;
- while ((ich = (unsigned int) *s) != 0)
- {
- if ((ich < '0') || (ich > '9'))
- return color;
- i = i * 10 + (ich - '0');
- s++;
- }
- if (i < MAX_COLOR_NAMES)
- color = Color_Defs[i].name;
- return color;
- }
- static int get_default_colors (char **fgp, char **bgp)
- {
- static char fg_buf[16], bg_buf[16], *bg, *fg;
- static int already_parsed;
- char *p, *pmax;
- if (already_parsed == -1)
- return -1;
- if (already_parsed)
- {
- *fgp = fg;
- *bgp = bg;
- return 0;
- }
- already_parsed = -1;
- bg = getenv ("COLORFGBG");
- if (bg == NULL)
- {
- bg = getenv ("DEFAULT_COLORS");
- if (bg == NULL)
- return -1;
- }
- p = fg_buf;
- pmax = p + (sizeof (fg_buf) - 1);
- while ((*bg != 0) && (*bg != ';'))
- {
- if (p < pmax) *p++ = *bg;
- bg++;
- }
- *p = 0;
- if (*bg) bg++;
- p = bg_buf;
- pmax = p + (sizeof (bg_buf) - 1);
- /* Mark suggested allowing for extra application specific stuff following
- * the background color. That is what the check for the semi-colon is for.
- */
- while ((*bg != 0) && (*bg != ';'))
- {
- if (p < pmax) *p++ = *bg;
- bg++;
- }
- *p = 0;
- if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
- {
- *fgp = *bgp = fg = bg = "default";
- }
- else
- {
- *fgp = fg = check_color_for_digit_form (fg_buf);
- *bgp = bg = check_color_for_digit_form (bg_buf);
- }
- already_parsed = 1;
- return 0;
- }
- static int Color_0_Modified = 0;
- int SLtt_set_color_object (int obj, SLtt_Char_Type attr)
- {
- Brush_Info_Type *b;
-
- if (NULL == (b = get_brush_info (obj)))
- return -1;
- b->fgbg = attr;
- if (obj == 0) Color_0_Modified = 1;
- if (_pSLtt_color_changed_hook != NULL)
- (*_pSLtt_color_changed_hook)();
-
- return 0;
- }
- SLtt_Char_Type SLtt_get_color_object (int obj)
- {
- return get_brush_fgbg (obj);
- }
- int SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
- {
- Brush_Info_Type *b;
-
- if (NULL == (b = get_brush_info (obj)))
- return -1;
- b->fgbg |= (attr & ATTR_MASK);
- if (obj == 0) Color_0_Modified = 1;
- if (_pSLtt_color_changed_hook != NULL)
- (*_pSLtt_color_changed_hook)();
-
- return 0;
- }
- static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
- {
- SLtt_Char_Type attr;
- if (Max_Terminfo_Colors != 8)
- {
- if (f != SLSMG_COLOR_DEFAULT) f %= Max_Terminfo_Colors;
- if (b != SLSMG_COLOR_DEFAULT) b %= Max_Terminfo_Colors;
- return ((f << 8) | (b << 16));
- }
- /* Otherwise we have 8 ansi colors. Try to get bright versions
- * by using the BOLD and BLINK attributes.
- */
- attr = 0;
- /* Note: If f represents default, it will have the value 0xFF */
- if (f != SLSMG_COLOR_DEFAULT)
- {
- if (f & 0x8) attr = SLTT_BOLD_MASK;
- f &= 0x7;
- }
- if (b != SLSMG_COLOR_DEFAULT)
- {
- if (b & 0x8) attr |= SLTT_BLINK_MASK;
- b &= 0x7;
- }
- return ((f << 8) | (b << 16) | attr);
- }
- /* This looks for colors with name form 'colorN'. If color is of this
- * form, N is passed back via parameter list.
- */
- static int parse_color_digit_name (char *color, SLtt_Char_Type *f)
- {
- unsigned int i;
- unsigned char ch;
- if (strncmp (color, "color", 5))
- return -1;
- color += 5;
- if (*color == 0)
- return -1;
- i = 0;
- while (1)
- {
- unsigned int j;
- ch = (unsigned char) *color++;
- if (ch == 0)
- break;
- if ((ch > '9') || (ch < '0'))
- return -1;
-
- if (i > 0xFFFFFFFFU / 10)
- return -1;
- j = (i *= 10);
- i += (ch - '0');
- if (i < j)
- return -1;
- }
- *f = (SLtt_Char_Type) i;
- return 0;
- }
- static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
- {
- SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
- char *dfg, *dbg;
- unsigned int i;
- if ((fg != NULL) && (*fg == 0)) fg = NULL;
- if ((bg != NULL) && (*bg == 0)) bg = NULL;
- if ((fg == NULL) || (bg == NULL))
- {
- if (-1 == get_default_colors (&dfg, &dbg))
- return -1;
- if (fg == NULL) fg = dfg;
- if (bg == NULL) bg = dbg;
- }
- if (-1 == parse_color_digit_name (fg, &f))
- {
- for (i = 0; i < MAX_COLOR_NAMES; i++)
- {
- if (strcmp(fg, Color_Defs[i].name)) continue;
- f = Color_Defs[i].color;
- break;
- }
- }
- if (-1 == parse_color_digit_name (bg, &b))
- {
- for (i = 0; i < MAX_COLOR_NAMES; i++)
- {
- if (strcmp(bg, Color_Defs[i].name)) continue;
- b = Color_Defs[i].color;
- break;
- }
- }
- if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
- return -1;
- *fgbg = fb_to_fgbg (f, b);
- return 0;
- }
- int SLtt_set_color (int obj, char *what, char *fg, char *bg)
- {
- SLtt_Char_Type fgbg;
- (void) what;
-
- if (-1 == make_color_fgbg (fg, bg, &fgbg))
- return -1;
- return SLtt_set_color_object (obj, fgbg);
- }
- int SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
- {
- return SLtt_set_color_object (obj, fb_to_fgbg (f, b));
- }
- void SLtt_set_alt_char_set (int i)
- {
- static int last_i;
- if (SLtt_Has_Alt_Charset == 0) return;
- i = (i != 0);
- if (i == last_i) return;
- tt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
- last_i = i;
- }
- static void write_attributes (SLtt_Char_Type fgbg)
- {
- int bg0, fg0;
- int unknown_attributes;
- if (Worthless_Highlight) return;
- if (fgbg == Current_Fgbg) return;
- unknown_attributes = 0;
- /* Before spitting out colors, fix attributes */
- if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
- {
- if (Current_Fgbg & ATTR_MASK)
- {
- tt_write_string(Norm_Vid_Str);
- /* In case normal video turns off ALL attributes: */
- if (fgbg & SLTT_ALTC_MASK)
- Current_Fgbg &= ~SLTT_ALTC_MASK;
- SLtt_set_alt_char_set (0);
- }
- if ((fgbg & SLTT_ALTC_MASK)
- != (Current_Fgbg & SLTT_ALTC_MASK))
- {
- SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
- }
- if (fgbg & SLTT_ULINE_MASK) tt_write_string (UnderLine_Vid_Str);
- if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
- if (fgbg & SLTT_REV_MASK) tt_write_string (Rev_Vid_Str);
- if (fgbg & SLTT_BLINK_MASK)
- {
- /* Someday Linux will have a blink mode that set high intensity
- * background. Lets be prepared.
- */
- if (SLtt_Blink_Mode) tt_write_string (Blink_Vid_Str);
- }
- unknown_attributes = 1;
- }
- if (SLtt_Use_Ansi_Colors)
- {
- fg0 = (int) GET_FG(fgbg);
- bg0 = (int) GET_BG(fgbg);
- if (unknown_attributes
- || (fg0 != (int)GET_FG(Current_Fgbg)))
- {
- if (fg0 == SLSMG_COLOR_DEFAULT)
- tt_write_string (Default_Color_Fg_Str);
- else
- tt_printf (Color_Fg_Str, COLOR_ARG(fg0, Is_Bg_BGR), 0);
- }
- if (unknown_attributes
- || (bg0 != (int)GET_BG(Current_Fgbg)))
- {
- if (bg0 == SLSMG_COLOR_DEFAULT)
- tt_write_string (Default_Color_Bg_Str);
- else
- tt_printf (Color_Bg_Str, COLOR_ARG(bg0, Is_Bg_BGR), 0);
- }
- }
- Current_Fgbg = fgbg;
- }
- static int Video_Initialized;
- void SLtt_reverse_video (int color)
- {
- SLtt_Char_Type fgbg;
- if (Worthless_Highlight) return;
- if (Video_Initialized == 0)
- {
- if (color == JNORMAL_COLOR)
- {
- tt_write_string (Norm_Vid_Str);
- }
- else tt_write_string (Rev_Vid_Str);
- Current_Fgbg = 0xFFFFFFFFU;
- return;
- }
- fgbg = get_brush_attr (color);
- if (fgbg == Current_Fgbg) return;
- write_attributes (fgbg);
- }
- void SLtt_normal_video (void)
- {
- SLtt_reverse_video(JNORMAL_COLOR);
- }
- void SLtt_narrow_width (void)
- {
- tt_write ("\033[?3l", 5);
- }
- void SLtt_wide_width (void)
- {
- tt_write ("\033[?3h", 5);
- }
- /* Highest bit represents the character set. */
- #define COLOR_OF(a) ((a)->color & SLSMG_COLOR_MASK)
- static int bce_color_eqs (SLsmg_Char_Type *a, SLsmg_Char_Type *b)
- {
- SLsmg_Color_Type ca, cb;
- Brush_Info_Type *ba, *bb;
- ca = COLOR_OF(a);
- cb = COLOR_OF(b);
- if (ca == cb)
- return 1;
- ba = get_brush_info (ca);
- bb = get_brush_info (cb);
-
- if (SLtt_Use_Ansi_Colors == 0)
- return ba->mono == bb->mono;
- if (Bce_Color_Offset == 0)
- return ba->fgbg == bb->fgbg;
- /* If either are color 0, then we do not know what that means since the
- * terminal does not support BCE */
- if ((ca == 0) || (cb == 0))
- return 0;
-
- return get_brush_fgbg (ca-1) == get_brush_fgbg(cb-1);
- }
- /* The whole point of this routine is to prevent writing to the last column
- * and last row on terminals with automatic margins.
- */
- static void write_string_with_care (char *str)
- {
- unsigned int len;
- if (str == NULL) return;
- len = strlen (str);
- if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
- {
- if (_pSLtt_UTF8_Mode == 0)
- {
- if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
- {
- /* For now, just do not write there. Later, something more
- * sophisticated will be implemented.
- */
- if (SLtt_Screen_Cols > Cursor_c)
- len = SLtt_Screen_Cols - Cursor_c - 1;
- else
- len = 0;
- }
- }
- else
- {
- unsigned int nchars = SLutf8_strlen((SLuchar_Type *)str, 1);
- if (nchars + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
- {
- if (SLtt_Screen_Cols > Cursor_c)
- {
- char *p;
- nchars = SLtt_Screen_Cols - Cursor_c - 1;
- p = (char *)SLutf8_skip_chars((SLuchar_Type *) str, (SLuchar_Type *)(str + len), nchars, NULL, 1);
- len = p - str;
- }
- else
- len = 0;
- }
- }
- }
- tt_write (str, len);
- }
- static void send_attr_str (SLsmg_Char_Type *s, SLsmg_Char_Type *smax)
- {
- unsigned char out[1+SLUTF8_MAX_MBLEN*SLSMG_MAX_CHARS_PER_CELL*SLTT_MAX_SCREEN_COLS];
- unsigned char *p, *pmax;
- register SLtt_Char_Type attr;
- SLsmg_Color_Type color, last_color = (SLsmg_Color_Type)-1;
- int dcursor_c;
- p = out;
- pmax = p + (sizeof (out)-1);
- dcursor_c = 0;
- while (s < smax)
- {
- SLwchar_Type wch;
- unsigned int nchars;
- if (0 == (nchars = s->nchars))
- {
- /* 2nd element of a char that occupies two columns */
- s++;
- if (_pSLtt_UTF8_Mode == 0)
- *p++ = ' ';
- dcursor_c++;
- continue;
- }
- color = s->color;
- #if SLTT_HAS_NON_BCE_SUPPORT
- if (Bce_Color_Offset
- && (color >= Bce_Color_Offset))
- color -= Bce_Color_Offset;
- #endif
- wch = s->wchars[0];
- if (color != last_color)
- {
- attr = get_brush_attr (color);
- if (color & SLSMG_ACS_MASK) /* alternate char set */
- {
- if (SLtt_Use_Blink_For_ACS)
- {
- if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
- }
- else attr |= SLTT_ALTC_MASK;
- }
- if (attr != Current_Fgbg)
- {
- if ((wch != ' ')
- || (nchars > 1)
- /* it is a space so only consider it different if it
- * has different attributes.
- */
- || (attr != Current_Fgbg)
- )
- {
- if (p != out)
- {
- *p = 0;
- write_string_with_care ((char *) out);
- p = out;
- Cursor_c += dcursor_c;
- dcursor_c = 0;
- }
- write_attributes (attr);
- last_color = color;
- }
- }
- }
-
- if ((wch < 0x80) && (nchars == 1))
- *p++ = (unsigned char) wch;
- else if (_pSLtt_UTF8_Mode == 0)
- {
- if (wch > 255)
- wch = '?';
- else if (wch < (SLwchar_Type)SLsmg_Display_Eight_Bit)
- wch = '?';
- *p++ = (unsigned char) wch;
- }
- else
- {
- unsigned int i;
- for (i = 0; i < nchars; i++)
- {
- if (NULL == (p = SLutf8_encode (s->wchars[i], p, pmax-p)))
- {
- fprintf (stderr, "*** send_attr_str: buffer too small\n");
- return;
- }
- }
- }
- dcursor_c++;
- s++;
- }
- *p = 0;
- if (p != out) write_string_with_care ((char *) out);
- Cursor_c += dcursor_c;
- }
- static void forward_cursor (unsigned int n, int row)
- {
- char buf [1024];
- /* if (Current_Fgbg & ~0xFF) */
- /* { */
- /* unsigned int num = 0; */
- /* while (num < n) */
- /* { */
- /* write_string_with_care (" "); */
- /* num++; */
- /* } */
- /* Cursor_c += n; */
- /* return; */
- /* } */
-
-
- if (n <= 4)
- {
- SLtt_normal_video ();
- #if 0
- if (n >= sizeof (buf))
- n = sizeof (buf) - 1;
- #endif
- SLMEMSET (buf, ' ', n);
- buf[n] = 0;
- write_string_with_care (buf);
- Cursor_c += n;
- }
- else if (Curs_F_Str != NULL)
- {
- Cursor_c += n;
- n = tt_sprintf(buf, sizeof (buf), Curs_F_Str, (int) n, 0);
- tt_write(buf, n);
- }
- else SLtt_goto_rc (row, (int) (Cursor_c + n));
- }
- /* FIXME!! If the terminal does not support color, then this route has
- * problems of color object 0 has been assigned some monochrome attribute
- * such as reverse video. In such a case, space_char=' ' is not a simple
- * space character as is assumed below.
- */
- #define COLOR_EQS(a,b) ((COLOR_OF(a)==COLOR_OF(b)) || bce_color_eqs (a,b))
- #define CHARSET(a) ((a)->color&SLSMG_ACS_MASK)
- #define CHAR_EQS(a, b) (((a)->nchars==(b)->nchars) \
- && (((a)->nchars == 0) \
- || ((((a)->wchars[0]==(b)->wchars[0]) \
- && (0 == memcmp((a)->wchars, (b)->wchars, (a)->nchars*sizeof(SLwchar_Type)))) \
- && (COLOR_EQS(a,b)) \
- && (CHARSET(a)==CHARSET(b)))))
- #define CHAR_EQS_SPACE(a) (((a)->wchars[0]==' ') && ((a)->color==0) && ((a)->nchars==1))
- void SLtt_smart_puts(SLsmg_Char_Type *neww, SLsmg_Char_Type *oldd, int len, int row)
- {
- register SLsmg_Char_Type *p, *q, *qmax, *pmax, *buf;
- SLsmg_Char_Type buffer[SLTT_MAX_SCREEN_COLS+1];
- unsigned int n_spaces;
- SLsmg_Char_Type *space_match, *last_buffered_match;
- #ifdef HP_GLITCH_CODE
- int handle_hp_glitch = 0;
- #endif
- SLsmg_Char_Type *space_char;
- SLsmg_Char_Type space_char_buf;
- #define SLTT_USE_INSERT_HACK 1
- #if SLTT_USE_INSERT_HACK
- SLsmg_Char_Type *insert_hack_prev = NULL;
- SLsmg_Char_Type *insert_hack_char = NULL;
- if ((row + 1 == SLtt_Screen_Rows)
- && (len == SLtt_Screen_Cols)
- && (len > 1)
- && (SLtt_Term_Cannot_Insert == 0)
- && Automatic_Margins)
- {
- SLsmg_Char_Type *a, *b;
- insert_hack_char = &neww[len-1];
- a = oldd+(len-1);
- b = neww+(len-1);
-
- if (CHAR_EQS(a,b))
- insert_hack_char = NULL;
- else
- insert_hack_prev = &neww[len-2];
- }
- #endif
-
- memset ((char *) &space_char_buf, 0, sizeof (SLsmg_Char_Type));
- space_char = &space_char_buf;
- space_char->nchars = 1;
- space_char->wchars[0] = ' ';
- if (len > SLTT_MAX_SCREEN_COLS)
- len = SLTT_MAX_SCREEN_COLS;
- q = oldd; p = neww;
- qmax = oldd + len;
- pmax = p + len;
- /* Find out where to begin --- while they match, we are ok */
- while (1)
- {
- if (q == qmax) return;
- #if SLANG_HAS_KANJI_SUPPORT
- if (*p & 0x80)
- { /* new is kanji */
- if ((*q & 0x80) && ((q + 1) < qmax))
- { /* old is also kanji */
- if (((0xFF & *q) != (0xFF & *p))
- || ((0xFF & q[1]) != (0xFF & p[1])))
- break; /* both kanji, but not match */
- else
- { /* kanji match ! */
- if (!COLOR_EQS(*q, *p)) break;
- q++; p++;
- if (!COLOR_EQS(*q, *p)) break;
- /* really match! */
- q++; p++;
- continue;
- }
- }
- else break; /* old is not kanji */
- }
- else
- { /* new is not kanji */
- if (*q & 0x80) break; /* old is kanji */
- }
- #endif
- if (!CHAR_EQS(q, p)) break;
- q++; p++;
- }
- #ifdef HP_GLITCH_CODE
- if (Has_HP_Glitch)
- {
- SLsmg_Char_Type *qq = q;
- SLtt_goto_rc (row, (int) (p - neww));
- while (qq < qmax)
- {
- if (qq->color)
- {
- SLtt_normal_video ();
- SLtt_del_eol ();
- qmax = q;
- handle_hp_glitch = 1;
- break;
- }
- qq++;
- }
- }
- #endif
- /* Find where the last non-blank character on old/new screen is */
- if (CHAR_EQS_SPACE(pmax-1))
- {
- /* If we get here, then we can erase to the end of the line to create
- * the final space. However, this will only work _if_ erasing will
- * get us the correct color. If the terminal supports BCE, then this
- * is easy. If it does not, then we can only perform this operation
- * if the color is known via something like COLORFGBG. For now,
- * I just will not perform the optimization for such terminals.
- */
- if ((Can_Background_Color_Erase)
- && SLtt_Use_Ansi_Colors)
- space_char = pmax - 1;
- while (pmax > p)
- {
- pmax--;
- if (!CHAR_EQS(pmax, space_char))
- {
- pmax++;
- break;
- }
- }
- }
- while (qmax > q)
- {
- qmax--;
- if (!CHAR_EQS(qmax, space_char))
- {
- qmax++;
- break;
- }
- }
- last_buffered_match = buf = buffer; /* buffer is empty */
- #ifdef HP_GLITCH_CODE
- if (handle_hp_glitch)
- {
- while (p < pmax)
- {
- *buf++ = *p++;
- }
- }
- #endif
- #ifdef HP_GLITCH_CODE
- if (Has_HP_Glitch == 0)
- {
- #endif
- /* Try use use erase to bol if possible */
- if ((Del_Bol_Str != NULL) && (CHAR_EQS_SPACE(neww)))
- {
- SLsmg_Char_Type *p1;
- SLsmg_Color_Type blank_color = 0;
- p1 = neww;
- if ((Can_Background_Color_Erase)
- && SLtt_Use_Ansi_Colors)
- {
- SLsmg_Char_Type *blank = p1;
- blank_color = COLOR_OF(blank);
- while ((p1 < pmax) && (CHAR_EQS (p1, blank)))
- p1++;
- }
- else
- {
- /* black+white attributes do not support bce */
- while ((p1 < pmax) && (CHAR_EQS_SPACE (p1)))
- p1++;
- }
-
- /* Is this optimization worth it? Assume Del_Bol_Str is ESC [ 1 K
- * It costs 4 chars + the space needed to properly position the
- * cursor, e.g., ESC [ 10;10H. So, it costs at least 13 characters.
- */
- if ((p1 > neww + 13)
- && (p1 >= p)
- /* Avoid erasing from the end of the line */
- && ((p1 != pmax) || (pmax < neww + len)))
- {
- int ofs = (int) (p1 - neww);
- q = oldd + ofs;
- p = p1;
- SLtt_goto_rc (row, ofs - 1);
- SLtt_reverse_video (blank_color);
- tt_write_string (Del_Bol_Str);
- tt_write (" ", 1);
- Cursor_c += 1;
- }
- else
- SLtt_goto_rc (row, (int) (p - neww));
- }
- else
- SLtt_goto_rc (row, (int) (p - neww));
- #ifdef HP_GLITCH_CODE
- }
- #endif
-
-
- /* loop using overwrite then skip algorithm until done */
- while (1)
- {
- /* while they do not match and we do not hit a space, buffer them up */
- n_spaces = 0;
- while (p < pmax)
- {
- if (CHAR_EQS_SPACE(q) && CHAR_EQS_SPACE(p))
- {
- /* If *q is not a space, we would have to overwrite it.
- * However, if *q is a space, then while *p is also one,
- * we only need to skip over the blank field.
- */
- space_match = p;
- p++; q++;
- while ((p < pmax)
- && CHAR_EQS_SPACE(q)
- && CHAR_EQS_SPACE(p))
- {
- p++;
- q++;
- }
- n_spaces = (unsigned int) (p - space_match);
- break;
- }
- #if SLANG_HAS_KANJI_SUPPORT
- if ((*p & 0x80) && ((p + 1) < pmax))
- { /* new is kanji */
- if (*q & 0x80)
- { /* old is also kanji */
- if (((0xFF & *q) != (0xFF & *p))
- || ((0xFF & q[1]) != (0xFF & p[1])))
- {
- /* both kanji, but not match */
- *buf++ = *p++;
- *buf++ = *p++;
- q += 2;
- continue;
- }
- else
- { /* kanji match ? */
- if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
- {
- /* code is match, but color is diff */
- *buf++ = *p++;
- *buf++ = *p++;
- q += 2;
- continue;
- }
- /* really match ! */
- break;
- }
- }
- else
- { /* old is not kanji */
- *buf++ = *p++;
- *buf++ = *p++;
- q += 2;
- continue;
- }
- }
- else
- { /* new is not kanji */
- if (*q & 0x80)
- { /* old is kanji */
- *buf++ = *p++;
- q++;
- continue;
- }
- }
- #endif
- if (CHAR_EQS(q, p))
- {
- /* Could be the second half of a double width character */
- if (p->nchars || q->nchars)
- break;
- }
- *buf++ = *p++;
- q++;
- }
- /* At this point, the buffer contains characters that do not match */
- if (buf != buffer) send_attr_str (buffer, buf);
- buf = buffer;
- if (n_spaces
- && ((p < pmax) /* erase to eol will achieve this effect*/
- || (!CHAR_EQS_SPACE(space_char))))/* unless space_char is not a simple space */
- {
- forward_cursor (n_spaces, row);
- }
- /* Now we overwrote what we could and cursor is placed at position
- * of a possible match of new and old. If this is the case, skip
- * some more.
- */
-
- /* Note that from here on, the buffer will contain matched characters */
- #if !SLANG_HAS_KANJI_SUPPORT
- while ((p < pmax) && CHAR_EQS(p, q))
- {
- *buf++ = *p++;
- q++;
- }
- #else
- /* Kanji */
- while (p < pmax)
- {
- if ((*p & 0x80) && ((p + 1) < pmax))
- { /* new is kanji */
- if (*q & 0x80)
- { /* old is also kanji */
- if (((0xFF & *q) == (0xFF & *p))
- && ((0xFF & q[1]) == (0xFF & p[1])))
- {
- /* kanji match ? */
- if (!COLOR_EQS(*q, *p)
- || !COLOR_EQS(q[1], p[1]))
- break;
- *buf++ = *p++;
- q++;
- if (p >= pmax)
- {
- *buf++ = 32;
- p++;
- break;
- }
- else
- {
- *buf++ = *p++;
- q++;
- continue;
- }
- }
- else break; /* both kanji, but not match */
- }
- else break; /* old is not kanji */
- }
- else
- { /* new is not kanji */
- if (*q & 0x80) break; /* old is kanji */
- if (!CHAR_EQS(*q, *p)) break;
- *buf++ = *p++;
- q++;
- }
- }
- #endif
- last_buffered_match = buf;
- if (p >= pmax) break;
- /* jump to new position is it is greater than 5 otherwise
- * let it sit in the buffer and output it later.
- */
- if ((int) (buf - buffer) >= 5)
- {
- forward_cursor ((unsigned int) (buf - buffer), row);
- last_buffered_match = buf = buffer;
- }
- }
- /* At this point we have reached the end of the new string with the
- * exception of space_chars hanging off the end of it, but we may not have
- * reached the end of the old string if they did not match.
- */
-
- /* Here the buffer will consist only of characters that have matched */
- if (buf != buffer)
- {
- if (q < qmax)
- {
- if ((buf == last_buffered_match)
- && ((int) (buf - buffer) >= 5))
- {
- forward_cursor ((unsigned int) (buf - buffer), row);
- }
- else
- {
- send_attr_str (buffer, buf);
- }
- }
- }
- if (q < qmax)
- {
- SLtt_reverse_video (COLOR_OF(space_char));
- del_eol ();
- }
-
- #if SLTT_USE_INSERT_HACK
- else if (insert_hack_char != NULL)
- {
- SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
- send_attr_str (insert_hack_char, insert_hack_char+1);
- SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
- SLtt_begin_insert ();
- send_attr_str (insert_hack_prev, insert_hack_prev+1);
- SLtt_end_insert ();
- }
- #endif
- if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
- }
- static void get_color_info (void)
- {
- char *fg, *bg;
- /* Allow easy mechanism to override inadequate termcap/terminfo files. */
- if (SLtt_Use_Ansi_Colors == 0)
- SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
- if (SLtt_Use_Ansi_Colors)
- Is_Color_Terminal = 1;
- #if SLTT_HAS_NON_BCE_SUPPORT
- if (Can_Background_Color_Erase == 0)
- Can_Background_Color_Erase = (NULL != getenv ("COLORTERM_BCE"));
- #endif
- if (-1 == get_default_colors (&fg, &bg))
- return;
- /* Check to see if application has already set them. */
- if (Color_0_Modified)
- return;
- SLtt_set_color (0, NULL, fg, bg);
- SLtt_set_color (1, NULL, bg, fg);
- }
- /* termcap stuff */
- #ifdef __unix__
- static int Termcap_Initalized = 0;
- /* #define USE_TERMCAP 1 */
- #ifdef USE_TERMCAP
- /* Termcap based system */
- static char Termcap_Buf[4096];
- /* static char Termcap_String_Buf[4096]; */
- /* static char *Termcap_String_Ptr; */
- extern char *tgetstr(char *, char **);
- extern int tgetent(char *, char *);
- extern int tgetnum(char *);
- extern int tgetflag(char *);
- #else
- /* Terminfo */
- static SLterminfo_Type *Terminfo;
- #endif
- #define TGETFLAG(x) (SLtt_tgetflag(x) > 0)
- static char *fixup_tgetstr (char *what)
- {
- register char *w, *w1;
- char *wsave;
-
- if (what == NULL)
- return NULL;
- /* Check for AIX brain-damage */
- if (*what == '@')
- return NULL;
- /* lose pad info --- with today's technology, term is a loser if
- it is really needed */
- while ((*what == '.') ||
- ((*what >= '0') && (*what <= '9'))) what++;
- if (*what == '*') what++;
-
- /* lose terminfo padding--- looks like $<...> */
- w = what;
- while (*w) if ((*w++ == '$') && (*w == '<'))
- {
- w1 = w - 1;
- while (*w && (*w != '>')) w++;
- if (*w == 0) break;
- w++;
- wsave = w1;
- while ((*w1++ = *w++) != 0);
- w = wsave;
- }
- if (*what == 0) what = NULL;
- return what;
- }
- char *SLtt_tgetstr (char *cap)
- {
- char *s;
- #ifdef USE_TERMCAP
- char area_buf[4096];
- char *area;
- #endif
- if (Termcap_Initalized == 0)
- return NULL;
-
- #ifdef USE_TERMCAP
- /* tmp_area = &Termcap_String_Buf; */
- area = area_buf;
- s = tgetstr (cap, &area);
- if (area > area_buf + sizeof(area_buf))
- {
- SLang_exit_error ("\
- The termcap tgetstr appears to have overflowed a buffer.\n\
- The integrity of this program has been violated.\n");
- }
- #else
- s = _pSLtt_tigetstr (Terminfo, cap);
- #endif
- /* Do not strip pad info for alternate character set. I need to make
- * this more general.
- */
- /* FIXME: Priority=low; */
- if (0 == strcmp (cap, "ac"))
- return s;
- s = fixup_tgetstr (s);
- #ifdef USE_TERMCAP
- if ((s >= area_buf) && (s < area_buf + sizeof(area_buf)))
- {
- /* It looks like tgetstr placed the object in the buffer and
- * returned a pointer to that buffer. So, we have to make a
- * copy of it.
- *
- * Yes, this introduces a leak...
- */
- s = SLmake_string (s);
- }
- #endif
- return s;
- }
- int SLtt_tgetnum (char *s)
- {
- if (Termcap_Initalized == 0)
- return -1;
- #ifdef USE_TERMCAP
- return tgetnum (s);
- #else
- return _pSLtt_tigetnum (Terminfo, s);
- #endif
- }
- int SLtt_tgetflag (char *s)
- {
- if (Termcap_Initalized == 0)
- return -1;
- #ifdef USE_TERMCAP
- return tgetflag (s);
- #else
- return _pSLtt_tigetflag (Terminfo, s);
- #endif
- }
- #if 0
- int SLtt_tgetent(char *term)
- {
- return SLtt_initialize(term) == 0;
- }
- int SLtt_tputs(char *str, int affcnt, int (*p)(int))
- {
- while (*str) (*p)(*str++);
- return 0;
- }
- char *SLtt_tgoto(char *cap, int col, int row)
- {
- static char buf[64];
- /* beware of overflows. 2^64 is 20 bytes printed */
- if (strlen(cap) > 23)
- strcpy(buf, "capability too long");
- else
- tt_sprintf(buf, cap, row, col);
- return buf;
- }
- #endif
- static int Vt100_Like = 0;
- void SLtt_get_terminfo (void)
- {
- char *term;
- int status;
- term = getenv ("TERM");
- if (term == NULL)
- SLang_exit_error("TERM environment variable needs set.");
- if (0 == (status = SLtt_initialize (term)))
- return;
- if (status == -1)
- {
- SLang_exit_error ("Unknown terminal: %s\n\
- Check the TERM environment variable.\n\
- Also make sure that the terminal is defined in the terminfo database.\n\
- Alternatively, set the TERMCAP environment variable to the desired\n\
- termcap entry.",
- term);
- }
- if (status == -2)
- {
- SLang_exit_error ("\
- Your terminal lacks the ability to clear the screen or position the cursor.\n");
- }
- }
- /* Returns 0 if all goes well, -1 if terminal capabilities cannot be deduced,
- * or -2 if terminal cannot position the cursor.
- */
- int SLtt_initialize (char *term)
- {
- char *t, ch;
- int is_xterm;
- int almost_vtxxx;
- if (_pSLtt_UTF8_Mode == -1)
- _pSLtt_UTF8_Mode = _pSLutf8_mode;
- if (SLang_TT_Write_FD == -1)
- {
- /* Apparantly, this cannot fail according to the man pages. */
- SLang_TT_Write_FD = fileno (stdout);
- }
-
- if (term == NULL)
- {
- term = getenv ("TERM");
- if (term == NULL)
- return -1;
- }
- if (_pSLsecure_issetugid ()
- && ((term[0] == '.') || (NULL != strchr(term, '/'))))
- return -1;
-
- Linux_Console = (!strncmp (term, "linux", 5)
- # ifdef linux
- || !strncmp(term, "con", 3)
- # endif
- );
- QANSI_Console = !strncmp (term, "qansi-m", 7);
- t = term;
- if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
- && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
- is_xterm = ((0 == strncmp (term, "xterm", 5))
- || (0 == strncmp (term, "rxvt", 4))
- || (0 == strncmp (term, "Eterm", 5)));
- almost_vtxxx = (Vt100_Like
- || Linux_Console
- || is_xterm
- || !strcmp (term, "screen"));
- # ifndef USE_TERMCAP
- if (NULL == (Terminfo = _pSLtt_tigetent (term)))
- {
- if (almost_vtxxx) /* Special cases. */
- {
- int vt102 = 1;
- if (!strcmp (term, "vt100")) vt102 = 0;
- get_color_info ();
- SLtt_set_term_vtxxx (&vt102);
- (void) SLtt_get_screen_size ();
- return 0;
- }
- return -1;
- }
- # else /* USE_TERMCAP */
- if (1 != tgetent(Termcap_Buf, term))
- return -1;
- /* Termcap_String_Ptr = Termcap_String_Buf; */
- # endif /* NOT USE_TERMCAP */
- Termcap_Initalized = 1;
- Cls_Str = SLtt_tgetstr ("cl");
- Curs_Pos_Str = SLtt_tgetstr ("cm");
- if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
- || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
- || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
- SLtt_Term_Cannot_Insert = 1;
- Visible_Bell_Str = SLtt_tgetstr ("vb");
- Curs_Up_Str = SLtt_tgetstr ("up");
- Rev_Scroll_Str = SLtt_tgetstr("sr");
- Del_N_Lines_Str = SLtt_tgetstr("DL");
- Add_N_Lines_Str = SLtt_tgetstr("AL");
- /* Actually these are used to initialize terminals that use cursor
- * addressing. Hard to believe.
- */
- Term_Init_Str = SLtt_tgetstr ("ti");
- Term_Reset_Str = SLtt_tgetstr ("te");
- /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
- * which I do not want. This is mainly for HP terminals.
- */
- if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
- {
- Keypad_Init_Str = SLtt_tgetstr ("ks");
- Keypad_Reset_Str = SLtt_tgetstr ("ke");
- }
- /* Make up for defective termcap/terminfo databases */
- if ((Vt100_Like && (term[2] != '1'))
- || Linux_Console
- || is_xterm
- )
- {
- if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
- if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
- }
- Scroll_R_Str = SLtt_tgetstr("cs");
- SLtt_get_screen_size ();
- if ((Scroll_R_Str == NULL)
- || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
- && (NULL == Rev_Scroll_Str)))
- {
- if (is_xterm
- || Linux_Console
- )
- {
- /* Defective termcap mode!!!! */
- SLtt_set_term_vtxxx (NULL);
- }
- else SLtt_Term_Cannot_Scroll = 1;
- }
- Del_Eol_Str = SLtt_tgetstr("ce");
- Del_Bol_Str = SLtt_tgetstr("cb");
- if (is_xterm && (Del_Bol_Str == NULL))
- Del_Bol_Str = "\033[1K";
- if (is_xterm && (Del_Eol_Str == NULL))
- Del_Eol_Str = "\033[K";
- Rev_Vid_Str = SLtt_tgetstr("mr");
- if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
- Bold_Vid_Str = SLtt_tgetstr("md");
- /* Although xterm cannot blink, it does display the blinking characters
- * as bold ones. Some Rxvt will display the background as high intensity.
- */
- if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
- && is_xterm)
- Blink_Vid_Str = "\033[5m";
- UnderLine_Vid_Str = SLtt_tgetstr("us");
- Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
- End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
- Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
- SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
- if (NULL == SLtt_Graphics_Char_Pairs)
- {
- /* make up for defective termcap/terminfo */
- if (Vt100_Like)
- {
- Start_Alt_Chars_Str = "\016";
- End_Alt_Chars_Str = "\017";
- Enable_Alt_Char_Set = "\033)0";
- }
- }
- /* aixterm added by willi */
- if (is_xterm || !strncmp (term, "aixterm", 7))
- {
- #if 0
- Start_Alt_Chars_Str = "\016";
- End_Alt_Chars_Str = "\017";
- Enable_Alt_Char_Set = "\033(B\033)0";
- #else
- Start_Alt_Chars_Str = "\033(0";
- End_Alt_Chars_Str = "\033(B";
- Enable_Alt_Char_Set = "";
- #endif
- }
- if ((SLtt_Graphics_Char_Pairs == NULL) &&
- ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
- {
- SLtt_Has_Alt_Charset = 0;
- Enable_Alt_Char_Set = NULL;
- }
- else SLtt_Has_Alt_Charset = 1;
- #ifdef AMIGA
- Enable_Alt_Char_Set = Start_Alt_Chars_Str = End_Alt_Chars_Str = NULL;
- #endif
- /* status line capabilities */
- if ((SLtt_Has_Status_Line == -1)
- && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
- {
- Disable_Status_line_Str = SLtt_tgetstr ("ds");
- Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
- Goto_Status_Line_Str = SLtt_tgetstr ("ts");
- /* Status_Line_Esc_Ok = TGETFLAG("es"); */
- Num_Status_Line_Columns = SLtt_tgetnum ("ws");
- if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
- }
- if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
- {
- Norm_Vid_Str = SLtt_tgetstr("se");
- }
- Cursor_Invisible_Str = SLtt_tgetstr("vi");
- Cursor_Visible_Str = SLtt_tgetstr("ve");
- Curs_F_Str = SLtt_tgetstr("RI");
- # if 0
- if (NULL != Curs_F_Str)
- {
- Len_Curs_F_Str = strlen(Curs_F_Str);
- }
- else Len_Curs_F_Str = strlen(Curs_Pos_Str);
- # endif
- Automatic_Margins = TGETFLAG ("am");
- /* No_Move_In_Standout = !TGETFLAG ("ms"); */
- # ifdef HP_GLITCH_CODE
- Has_HP_Glitch = TGETFLAG ("xs");
- # else
- Worthless_Highlight = TGETFLAG ("xs");
- # endif
- if (Worthless_Highlight == 0)
- { /* Magic cookie glitch */
- Worthless_Highlight = (SLtt_tgetnum ("sg") > 0);
- }
- if (Worthless_Highlight)
- SLtt_Has_Alt_Charset = 0;
- Reset_Color_String = SLtt_tgetstr ("op");
-
- /* Apparantly the difference between "AF" and "Sf" is that AF uses RGB,
- * but Sf uses BGR.
- */
- Color_Fg_Str = SLtt_tgetstr ("AF"); /* ANSI setaf */
- if (Color_Fg_Str == NULL)
- {
- Color_Fg_Str = SLtt_tgetstr ("Sf"); /* setf */
- /* Is_Fg_BGR = (Color_Fg_Str != NULL); */
- }
- Color_Bg_Str = SLtt_tgetstr ("AB"); /* ANSI setbf */
- if (Color_Bg_Str == NULL)
- {
- Color_Bg_Str = SLtt_tgetstr ("Sb"); /* setb */
- /* Is_Fg_BGR = (Color_Bg_Str != NULL); */
- }
- if ((Max_Terminfo_Colors = SLtt_tgetnum ("Co")) < 0)
- Max_Terminfo_Colors = 8;
- if ((Color_Bg_Str != NULL) && (Color_Fg_Str != NULL))
- SLtt_Use_Ansi_Colors = 1;
- else
- {
- #if 0
- Color_Fg_Str = "%?%p1%{7}%>%t\033[1;3%p1%{8}%m%dm%e\033[3%p1%dm%;";
- Color_Bg_Str = "%?%p1%{7}%>%t\033[5;4%p1%{8}%m%dm%e\033[4%p1%dm%;";
- Max_Terminfo_Colors = 16;
- #else
- Color_Fg_Str = "\033[3%dm";
- Color_Bg_Str = "\033[4%dm";
- Max_Terminfo_Colors = 8;
- #endif
- }
- #if SLTT_HAS_NON_BCE_SUPPORT
- Can_Background_Color_Erase = TGETFLAG ("ut"); /* bce */
- /* Modern xterms have the BCE capability as well as the linux console */
- if (Can_Background_Color_Erase == 0)
- {
- Can_Background_Color_Erase = (Linux_Console
- # if SLTT_XTERM_ALWAYS_BCE
- || is_xterm
- # endif
- );
- }
- #endif
- get_color_info ();
-
- if ((Cls_Str == NULL)
- || (Curs_Pos_Str == NULL))
- return -2;
- return 0;
- }
- #endif
- /* Unix */
- /* specific to vtxxx only */
- void SLtt_enable_cursor_keys (void)
- {
- #ifdef __unix__
- if (Vt100_Like)
- #endif
- tt_write_string("\033=\033[?1l");
- }
- #ifdef VMS
- int SLtt_initialize (char *term)
- {
- SLtt_get_terminfo ();
- return 0;
- }
- void SLtt_get_terminfo ()
- {
- int zero = 0;
- /* Apparantly, this cannot fail according to the man pages. */
- if (SLang_TT_Write_FD == -1)
- SLang_TT_Write_FD = fileno (stdout);
-
- Can_Background_Color_Erase = 0;
- Color_Fg_Str = "\033[3%dm";
- Color_Bg_Str = "\033[4%dm";
- Max_Terminfo_Colors = 8;
- get_color_info ();
- SLtt_set_term_vtxxx(&zero);
- Start_Alt_Chars_Str = "\016";
- End_Alt_Chars_Str = "\017";
- SLtt_Has_Alt_Charset = 1;
- SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
- Enable_Alt_Char_Set = "\033(B\033)0";
- SLtt_get_screen_size ();
- }
- #endif
- /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
- * is non-zero, set terminal appropriate for a only vt100
- * (no add line capability). */
- void SLtt_set_term_vtxxx(int *vt100)
- {
- Norm_Vid_Str = "\033[m";
- Scroll_R_Str = "\033[%i%d;%dr";
- Cls_Str = "\033[2J\033[H";
- Rev_Vid_Str = "\033[7m";
- Bold_Vid_Str = "\033[1m";
- Blink_Vid_Str = "\033[5m";
- UnderLine_Vid_Str = "\033[4m";
- Del_Eol_Str = "\033[K";
- Del_Bol_Str = "\033[1K";
- Rev_Scroll_Str = "\033M";
- Curs_F_Str = "\033[%dC";
- /* Len_Curs_F_Str = 5; */
- Curs_Pos_Str = "\033[%i%d;%dH";
- if ((vt100 == NULL) || (*vt100 == 0))
- {
- Ins_Mode_Str = "\033[4h";
- Eins_Mode_Str = "\033[4l";
- Del_Char_Str = "\033[P";
- Del_N_Lines_Str = "\033[%dM";
- Add_N_Lines_Str = "\033[%dL";
- SLtt_Term_Cannot_Insert = 0;
- }
- else
- {
- Del_N_Lines_Str = NULL;
- Add_N_Lines_Str = NULL;
- SLtt_Term_Cannot_Insert = 1;
- }
- SLtt_Term_Cannot_Scroll = 0;
- /* No_Move_In_Standout = 0; */
- }
- int SLtt_init_video (void)
- {
- /* send_string_to_term("\033[?6h"); */
- /* relative origin mode */
- tt_write_string (Term_Init_Str);
- tt_write_string (Keypad_Init_Str);
- SLtt_reset_scroll_region();
- SLtt_end_insert();
- tt_write_string (Enable_Alt_Char_Set);
- Video_Initialized = 1;
- return 0;
- }
- int SLtt_reset_video (void)
- {
- SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
- Cursor_Set = 0;
- SLtt_normal_video (); /* MSKermit requires this */
- tt_write_string(Norm_Vid_Str);
- Current_Fgbg = 0xFFFFFFFFU;
- SLtt_set_alt_char_set (0);
- if (SLtt_Use_Ansi_Colors)
- {
- if (Reset_Color_String == NULL)
- {
- SLtt_Char_Type attr;
- if (-1 != make_color_fgbg (NULL, NULL, &attr))
- write_attributes (attr);
- else tt_write_string ("\033[0m\033[m");
- }
- else tt_write_string (Reset_Color_String);
- Current_Fgbg = 0xFFFFFFFFU;
- }
- SLtt_erase_line ();
- tt_write_string (Keypad_Reset_Str);
- tt_write_string (Term_Reset_Str);
- if (Mouse_Mode == 1)
- SLtt_set_mouse_mode (0, 1);
- SLtt_flush_output ();
- Video_Initialized = 0;
- return 0;
- }
- void SLtt_bold_video (void)
- {
- tt_write_string (Bold_Vid_Str);
- }
- int SLtt_set_mouse_mode (int mode, int force)
- {
- char *term;
- if (force == 0)
- {
- if (NULL == (term = (char *) getenv("TERM"))) return -1;
- if (strncmp ("xterm", term, 5))
- return -1;
- }
- Mouse_Mode = (mode != 0);
- if (mode)
- tt_write_string ("\033[?9h");
- else
- tt_write_string ("\033[?9l");
- return 0;
- }
- void SLtt_disable_status_line (void)
- {
- if (SLtt_Has_Status_Line > 0)
- {
- tt_write_string (Disable_Status_line_Str);
- SLtt_flush_output ();
- }
- }
- int SLtt_write_to_status_line (char *s, int col)
- {
- if ((SLtt_Has_Status_Line <= 0)
- || (Goto_Status_Line_Str == NULL)
- || (Return_From_Status_Line_Str == NULL))
- return -1;
- tt_printf (Goto_Status_Line_Str, col, 0);
- tt_write_string (s);
- tt_write_string (Return_From_Status_Line_Str);
- return 0;
- }
- void SLtt_get_screen_size (void)
- {
- #ifdef VMS
- int status, code;
- unsigned short chan;
- $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
- #endif
- int r = 0, c = 0;
- #ifdef TIOCGWINSZ
- struct winsize wind_struct;
- do
- {
- if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
- || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
- || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
- {
- c = (int) wind_struct.ws_col;
- r = (int) wind_struct.ws_row;
- break;
- }
- }
- while (errno == EINTR);
- #endif
- #ifdef VMS
- status = sys$assign(&dev_dsc,&chan,0,0,0);
- if (status & 1)
- {
- code = DVI$_DEVBUFSIZ;
- status = lib$getdvi(&code, &chan,0, &c, 0,0);
- if (!(status & 1))
- c = 80;
- code = DVI$_TT_PAGE;
- status = lib$getdvi(&code, &chan,0, &r, 0,0);
- if (!(status & 1))
- r = 24;
- sys$dassgn(chan);
- }
- #endif
- if (r <= 0)
- {
- char *s = getenv ("LINES");
- if (s != NULL) r = atoi (s);
- }
- if (c <= 0)
- {
- char *s = getenv ("COLUMNS");
- if (s != NULL) c = atoi (s);
- }
- if ((r <= 0) || (r > SLTT_MAX_SCREEN_ROWS)) r = 24;
- if ((c <= 0) || (c > SLTT_MAX_SCREEN_COLS)) c = 80;
- SLtt_Screen_Rows = r;
- SLtt_Screen_Cols = c;
- }
- #if SLTT_HAS_NON_BCE_SUPPORT
- int _pSLtt_get_bce_color_offset (void)
- {
- if ((SLtt_Use_Ansi_Colors == 0)
- || Can_Background_Color_Erase
- || SLtt_Use_Blink_For_ACS) /* in this case, we cannot lose a color */
- Bce_Color_Offset = 0;
- else
- {
- SLtt_Char_Type fgbg = get_brush_fgbg (0);
- if (GET_BG(fgbg) == SLSMG_COLOR_DEFAULT)
- Bce_Color_Offset = 0;
- else
- Bce_Color_Offset = 1;
- }
-
- return Bce_Color_Offset;
- }
- #endif
- int SLtt_utf8_enable (int mode)
- {
- if (mode == -1)
- mode = _pSLutf8_mode;
- return _pSLtt_UTF8_Mode = mode;
- }
- int SLtt_is_utf8_mode (void)
- {
- int mode = _pSLtt_UTF8_Mode;
- if (mode == -1)
- mode = _pSLutf8_mode;
- return mode;
- }
|