@ -23,10 +23,10 @@
# define TNAME "xterm"
# define TNAME "xterm"
/* Arbitrary sizes */
/* Arbitrary sizes */
# define TITLESIZ 256
# define ESC_ TITLE_ SIZ 256
# define ESC SIZ 256
# define ESC _BUF_ SIZ 256
# define ESC ARGSIZ 16
# define ESC _ ARG_ SIZ 16
# define MAX DRAWBUF 1024
# define DRAW_ BUF_SIZ 1024
# define SERRNO strerror(errno)
# define SERRNO strerror(errno)
# define MIN(a, b) ((a) < (b) ? (a) : (b))
# define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -38,21 +38,19 @@
# define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg)
# define ATTRCMP(a, b) ((a).mode != (b).mode || (a).fg != (b).fg || (a).bg != (b).bg)
/* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */
/* Attribute, Cursor, Character state, Terminal mode, Screen draw mode */
enum { ATnone = 0 , ATreverse = 1 , ATunderline = 2 , ATbold = 4 , ATgfx = 8 } ;
enum { ATTR_NULL = 0 , ATTR_REVERSE = 1 , ATTR_UNDERLINE = 2 , ATTR_BOLD = 4 , ATTR_GFX = 8 } ;
enum { CSup , CSdown , CSright , CSleft , CShide , CSdraw , CSsave , CSload } ;
enum { CURSOR_UP , CURSOR_DOWN , CURSOR_LEFT , CURSOR_RIGHT , CURSOR_HIDE , CURSOR_DRAW , CURSOR_SAVE , CURSOR_LOAD } ;
enum { CRset = 1 , CRupdate = 2 } ;
enum { GLYPH_SET = 1 , GLYPH_DIRTY = 2 } ;
enum { TMwrap = 1 , TMinsert = 2 } ;
enum { MODE_WRAP = 1 , MODE_INSERT = 2 , MODE_APPKEYPAD = 4 } ;
enum { ESCin = 1 , ESCcsi = 2 , ESCosc = 4 , ESCtitle = 8 , ESCcharset = 16 } ;
enum { ESC_START = 1 , ESC_CSI = 2 , ESC_OSC = 4 , ESC_TITLE = 8 , ESC_ALTCHARSET = 16 } ;
enum { SCupdate , SCredraw } ;
enum { SCREEN_UPDATE , SCREEN_REDRAW } ;
typedef int Color ;
typedef struct {
typedef struct {
char c ; /* character code */
char c ; /* character code */
char mode ; /* attribute flags */
char mode ; /* attribute flags */
Color fg ; /* foreground */
int fg ; /* foreground */
Color bg ; /* background */
int bg ; /* background */
char state ; /* state flag */
char state ; /* state flag s */
} Glyph ;
} Glyph ;
typedef Glyph * Line ;
typedef Glyph * Line ;
@ -67,10 +65,10 @@ typedef struct {
/* CSI Escape sequence structs */
/* CSI Escape sequence structs */
/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
/* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
typedef struct {
typedef struct {
char buf [ ESC SIZ] ; /* raw string */
char buf [ ESC _BUF_ SIZ] ; /* raw string */
int len ; /* raw string length */
int len ; /* raw string length */
char priv ;
char priv ;
int arg [ ESC ARGSIZ] ;
int arg [ ESC _ ARG_ SIZ] ;
int narg ; /* nb of args */
int narg ; /* nb of args */
char mode ;
char mode ;
} CSIEscape ;
} CSIEscape ;
@ -83,9 +81,9 @@ typedef struct {
TCursor c ; /* cursor */
TCursor c ; /* cursor */
int top ; /* top scroll limit */
int top ; /* top scroll limit */
int bot ; /* bottom scroll limit */
int bot ; /* bottom scroll limit */
int mode ; /* terminal mode */
int mode ; /* terminal mode flags */
int esc ;
int esc ; /* escape state flags */
char title [ TITLESIZ] ;
char title [ ESC_ TITLE_ SIZ] ;
int titlelen ;
int titlelen ;
} Term ;
} Term ;
@ -102,7 +100,7 @@ typedef struct {
typedef struct {
typedef struct {
KeySym k ;
KeySym k ;
char s [ ESC SIZ] ;
char s [ ESC _BUF_ SIZ] ;
} Key ;
} Key ;
# include "config.h"
# include "config.h"
@ -126,8 +124,8 @@ static void csiparse(void);
static void csireset ( void ) ;
static void csireset ( void ) ;
static void tclearregion ( int , int , int , int ) ;
static void tclearregion ( int , int , int , int ) ;
static void tcpos ( int ) ;
static void tcursor ( int ) ;
static void tcursor ( int ) ;
static void tmovecursor ( int ) ;
static void tdeletechar ( int ) ;
static void tdeletechar ( int ) ;
static void tdeleteline ( int ) ;
static void tdeleteline ( int ) ;
static void tinsertblank ( int ) ;
static void tinsertblank ( int ) ;
@ -187,7 +185,7 @@ tdump(void) {
putchar ( ' # ' ) ;
putchar ( ' # ' ) ;
else {
else {
c = term . line [ row ] [ col ] ;
c = term . line [ row ] [ col ] ;
putchar ( c . state & CRset ? c . c : ' . ' ) ;
putchar ( c . state & GLYPH_SET ? c . c : ' . ' ) ;
}
}
}
}
putchar ( ' \n ' ) ;
putchar ( ' \n ' ) ;
@ -218,7 +216,7 @@ xbell(void) { /* visual bell */
XSetForeground ( xw . dis , dc . gc , dc . col [ BellCol ] ) ;
XSetForeground ( xw . dis , dc . gc , dc . col [ BellCol ] ) ;
XFillRectangles ( xw . dis , xw . win , dc . gc , & r , 1 ) ;
XFillRectangles ( xw . dis , xw . win , dc . gc , & r , 1 ) ;
/* usleep(30000); */
/* usleep(30000); */
draw ( SC redraw ) ;
draw ( SC REEN_REDRAW ) ;
}
}
void
void
@ -281,14 +279,11 @@ ttyread(void) {
char buf [ BUFSIZ ] = { 0 } ;
char buf [ BUFSIZ ] = { 0 } ;
int ret ;
int ret ;
switch ( ret = read ( cmdfd , buf , BUFSIZ ) ) {
if ( ( ret = read ( cmdfd , buf , BUFSIZ ) ) < 0 )
case - 1 :
die ( " Couldn't read from shell: %s \n " , SERRNO ) ;
die ( " Couldn't read from shell: %s \n " , SERRNO ) ;
break ;
else
default :
tputs ( buf , ret ) ;
tputs ( buf , ret ) ;
}
}
}
void
void
ttywrite ( const char * s , size_t n ) {
ttywrite ( const char * s , size_t n ) {
@ -308,14 +303,13 @@ ttyresize(int x, int y) {
}
}
void
void
tcpos ( int mode ) {
tcursor ( int mode ) {
static int x = 0 ;
static TCursor c ;
static int y = 0 ;
if ( mode = = C Ssave )
if ( mode = = C URSOR_SAVE )
x = term . c. x , y = term . c . y ;
c = term . c ;
else if ( mode = = C Sload )
else if ( mode = = C URSOR_LOAD )
tmoveto ( x, y ) ;
term . c = c , tmoveto ( c. x, c . y ) ;
}
}
void
void
@ -323,9 +317,9 @@ tnew(int col, int row) { /* screen size */
term . row = row , term . col = col ;
term . row = row , term . col = col ;
term . top = 0 , term . bot = term . row - 1 ;
term . top = 0 , term . bot = term . row - 1 ;
/* mode */
/* mode */
term . mode = TMwrap ;
term . mode = MODE_WRAP ;
/* cursor */
/* cursor */
term . c . attr . mode = AT none ;
term . c . attr . mode = AT TR_NULL ;
term . c . attr . fg = DefaultFG ;
term . c . attr . fg = DefaultFG ;
term . c . attr . bg = DefaultBG ;
term . c . attr . bg = DefaultBG ;
term . c . x = term . c . y = 0 ;
term . c . x = term . c . y = 0 ;
@ -370,7 +364,7 @@ csiparse(void) {
escseq . arg [ escseq . narg ] * = 10 ;
escseq . arg [ escseq . narg ] * = 10 ;
escseq . arg [ escseq . narg ] + = * p + + - ' 0 ' /*, noarg = 0 */ ;
escseq . arg [ escseq . narg ] + = * p + + - ' 0 ' /*, noarg = 0 */ ;
}
}
if ( * p = = ' ; ' & & escseq . narg + 1 < ESC ARGSIZ)
if ( * p = = ' ; ' & & escseq . narg + 1 < ESC _ ARG_ SIZ)
escseq . narg + + , p + + ;
escseq . narg + + , p + + ;
else {
else {
escseq . mode = * p ;
escseq . mode = * p ;
@ -387,27 +381,27 @@ tmoveto(int x, int y) {
}
}
void
void
t cursor( int dir ) {
t move cursor( int dir ) {
int xf = term . c . x , yf = term . c . y ;
int xf = term . c . x , yf = term . c . y ;
switch ( dir ) {
switch ( dir ) {
case C Sup :
case C URSOR_UP :
yf - - ;
yf - - ;
break ;
break ;
case C Sdown :
case C URSOR_DOWN :
yf + + ;
yf + + ;
break ;
break ;
case C Sleft :
case C URSOR_LEFT :
xf - - ;
xf - - ;
if ( term . mode & TMwrap & & xf < 0 ) {
if ( term . mode & MODE_WRAP & & xf < 0 ) {
xf = term . col - 1 , yf - - ;
xf = term . col - 1 , yf - - ;
if ( yf < term . top )
if ( yf < term . top )
yf = term . top , xf = 0 ;
yf = term . top , xf = 0 ;
}
}
break ;
break ;
case C Sright :
case C URSOR_RIGHT :
xf + + ;
xf + + ;
if ( term . mode & TMwrap & & xf > = term . col ) {
if ( term . mode & MODE_WRAP & & xf > = term . col ) {
xf = 0 , yf + + ;
xf = 0 , yf + + ;
if ( yf > term . bot )
if ( yf > term . bot )
yf = term . bot , tscroll ( ) ;
yf = term . bot , tscroll ( ) ;
@ -421,7 +415,7 @@ void
tsetchar ( char c ) {
tsetchar ( char c ) {
term . line [ term . c . y ] [ term . c . x ] = term . c . attr ;
term . line [ term . c . y ] [ term . c . x ] = term . c . attr ;
term . line [ term . c . y ] [ term . c . x ] . c = c ;
term . line [ term . c . y ] [ term . c . x ] . c = c ;
term . line [ term . c . y ] [ term . c . x ] . state | = CRset | CRupdate ;
term . line [ term . c . y ] [ term . c . x ] . state | = GLYPH_SET | GLYPH_DIRTY ;
}
}
void
void
@ -497,8 +491,8 @@ tinsertblankline (int n) {
term . line [ i - n ] = blank ;
term . line [ i - n ] = blank ;
/* blank it */
/* blank it */
memset ( blank , 0 , term . col * sizeof ( Glyph ) ) ;
memset ( blank , 0 , term . col * sizeof ( Glyph ) ) ;
tsetlinestate ( i , CRupdate ) ;
tsetlinestate ( i , GLYPH_DIRTY ) ;
tsetlinestate ( i - n , CRupdate ) ;
tsetlinestate ( i - n , GLYPH_DIRTY ) ;
}
}
}
}
@ -523,8 +517,8 @@ tdeleteline(int n) {
term . line [ i + n ] = blank ;
term . line [ i + n ] = blank ;
/* blank it */
/* blank it */
memset ( blank , 0 , term . col * sizeof ( Glyph ) ) ;
memset ( blank , 0 , term . col * sizeof ( Glyph ) ) ;
tsetlinestate ( i , CRupdate ) ;
tsetlinestate ( i , GLYPH_DIRTY ) ;
tsetlinestate ( i - n , CRupdate ) ;
tsetlinestate ( i - n , GLYPH_DIRTY ) ;
}
}
}
}
@ -535,30 +529,30 @@ tsetattr(int *attr, int l) {
for ( i = 0 ; i < l ; i + + ) {
for ( i = 0 ; i < l ; i + + ) {
switch ( attr [ i ] ) {
switch ( attr [ i ] ) {
case 0 :
case 0 :
term . c . attr . mode & = ~ ( AT reverse | ATunderline | ATbold ) ;
term . c . attr . mode & = ~ ( AT TR_REVERSE | ATTR_UNDERLINE | ATTR_BOLD ) ;
term . c . attr . fg = DefaultFG ;
term . c . attr . fg = DefaultFG ;
term . c . attr . bg = DefaultBG ;
term . c . attr . bg = DefaultBG ;
break ;
break ;
case 1 :
case 1 :
term . c . attr . mode | = AT bold ;
term . c . attr . mode | = AT TR_BOLD ;
break ;
break ;
case 4 :
case 4 :
term . c . attr . mode | = AT underline ;
term . c . attr . mode | = AT TR_UNDERLINE ;
break ;
break ;
case 7 :
case 7 :
term . c . attr . mode | = AT reverse ;
term . c . attr . mode | = AT TR_REVERSE ;
break ;
break ;
case 8 :
case 8 :
term . c . hidden = C Shide ;
term . c . hidden = C URSOR_HIDE ;
break ;
break ;
case 22 :
case 22 :
term . c . attr . mode & = ~ AT bold ;
term . c . attr . mode & = ~ AT TR_BOLD ;
break ;
break ;
case 24 :
case 24 :
term . c . attr . mode & = ~ AT underline ;
term . c . attr . mode & = ~ AT TR_UNDERLINE ;
break ;
break ;
case 27 :
case 27 :
term . c . attr . mode & = ~ AT reverse ;
term . c . attr . mode & = ~ AT TR_REVERSE ;
break ;
break ;
case 39 :
case 39 :
term . c . attr . fg = DefaultFG ;
term . c . attr . fg = DefaultFG ;
@ -593,57 +587,56 @@ tsetscroll(int t, int b) {
void
void
csihandle ( void ) {
csihandle ( void ) {
if ( escseq . priv )
csidump ( ) ;
switch ( escseq . mode ) {
switch ( escseq . mode ) {
unknown :
default :
default :
fprintf ( stderr , " erresc: unknown sequence \n " ) ;
unknown :
printf ( " erresc: unknown sequence -- " ) ;
csidump ( ) ;
csidump ( ) ;
/* die(""); */
/* die(""); */
break ;
break ;
case ' @ ' : /* I nsert <n> blank char */
case ' @ ' : /* I CH -- I nsert <n> blank char */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tinsertblank ( escseq . arg [ 0 ] ) ;
tinsertblank ( escseq . arg [ 0 ] ) ;
break ;
break ;
case ' A ' : /* C ursor <n> Up */
case ' A ' : /* C UU -- C ursor <n> Up */
case ' e ' :
case ' e ' :
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( term . c . x , term . c . y - escseq . arg [ 0 ] ) ;
tmoveto ( term . c . x , term . c . y - escseq . arg [ 0 ] ) ;
break ;
break ;
case ' B ' : /* C ursor <n> Down */
case ' B ' : /* C UD -- C ursor <n> Down */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( term . c . x , term . c . y + escseq . arg [ 0 ] ) ;
tmoveto ( term . c . x , term . c . y + escseq . arg [ 0 ] ) ;
break ;
break ;
case ' C ' : /* C ursor <n> Forward */
case ' C ' : /* C UF -- C ursor <n> Forward */
case ' a ' :
case ' a ' :
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( term . c . x + escseq . arg [ 0 ] , term . c . y ) ;
tmoveto ( term . c . x + escseq . arg [ 0 ] , term . c . y ) ;
break ;
break ;
case ' D ' : /* C ursor <n> Backward */
case ' D ' : /* C UB -- C ursor <n> Backward */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( term . c . x - escseq . arg [ 0 ] , term . c . y ) ;
tmoveto ( term . c . x - escseq . arg [ 0 ] , term . c . y ) ;
break ;
break ;
case ' E ' : /* C ursor <n> Down and first col */
case ' E ' : /* C NL -- C ursor <n> Down and first col */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( 0 , term . c . y + escseq . arg [ 0 ] ) ;
tmoveto ( 0 , term . c . y + escseq . arg [ 0 ] ) ;
break ;
break ;
case ' F ' : /* C ursor <n> Up and first col */
case ' F ' : /* C PL -- C ursor <n> Up and first col */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( 0 , term . c . y - escseq . arg [ 0 ] ) ;
tmoveto ( 0 , term . c . y - escseq . arg [ 0 ] ) ;
break ;
break ;
case ' G ' : /* Move to <col> */
case ' G ' : /* CHA -- Move to <col> */
case ' ` ' :
case ' ` ' : /* XXX: HPA -- same? */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( escseq . arg [ 0 ] - 1 , term . c . y ) ;
tmoveto ( escseq . arg [ 0 ] - 1 , term . c . y ) ;
break ;
break ;
case ' H ' : /* Move to <row> <col> */
case ' H ' : /* CUP -- Move to <row> <col> */
case ' f ' :
case ' f ' : /* XXX: HVP -- same? */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 1 ] , 1 ) ;
DEFAULT ( escseq . arg [ 1 ] , 1 ) ;
tmoveto ( escseq . arg [ 1 ] - 1 , escseq . arg [ 0 ] - 1 ) ;
tmoveto ( escseq . arg [ 1 ] - 1 , escseq . arg [ 0 ] - 1 ) ;
break ;
break ;
case ' J ' : /* Clear screen */
/* XXX: (CSI n I) CHT -- Cursor Forward Tabulation <n> tab stops */
case ' J ' : /* ED -- Clear screen */
switch ( escseq . arg [ 0 ] ) {
switch ( escseq . arg [ 0 ] ) {
case 0 : /* below */
case 0 : /* below */
tclearregion ( term . c . x , term . c . y , term . col - 1 , term . row - 1 ) ;
tclearregion ( term . c . x , term . c . y , term . col - 1 , term . row - 1 ) ;
@ -654,9 +647,12 @@ csihandle(void) {
case 2 : /* all */
case 2 : /* all */
tclearregion ( 0 , 0 , term . col - 1 , term . row - 1 ) ;
tclearregion ( 0 , 0 , term . col - 1 , term . row - 1 ) ;
break ;
break ;
case 3 : /* XXX: erase saved lines (xterm) */
default :
goto unknown ;
}
}
break ;
break ;
case ' K ' : /* Clear line */
case ' K ' : /* EL -- Clear line */
switch ( escseq . arg [ 0 ] ) {
switch ( escseq . arg [ 0 ] ) {
case 0 : /* right */
case 0 : /* right */
tclearregion ( term . c . x , term . c . y , term . col - 1 , term . c . y ) ;
tclearregion ( term . c . x , term . c . y , term . col - 1 , term . c . y ) ;
@ -669,54 +665,77 @@ csihandle(void) {
break ;
break ;
}
}
break ;
break ;
case ' S ' :
case ' S ' : /* XXX: SU -- Scroll <n> line up (faked) */
case ' L ' : /* I nsert <n> blank lines */
case ' L ' : /* I L -- I nsert <n> blank lines */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tinsertblankline ( escseq . arg [ 0 ] ) ;
tinsertblankline ( escseq . arg [ 0 ] ) ;
break ;
break ;
case ' l ' :
case ' l ' : /* RM -- Reset Mode */
if ( escseq . priv ) {
if ( escseq . priv ) {
switch ( escseq . arg [ 0 ] ) {
switch ( escseq . arg [ 0 ] ) {
case 1 :
term . mode & = ~ MODE_APPKEYPAD ;
break ;
case 7 :
case 7 :
term . mode & = ~ TMwrap ;
term . mode & = ~ MODE_WRAP ;
break ;
case 12 : /* att610 -- Stop blinking cursor (IGNORED) */
break ;
break ;
case 25 :
case 25 :
term . c . hidden = 1 ;
term . c . hidden = 1 ;
break ;
break ;
case 1048 : /* XXX: no alt. screen to erase/save */
case 1049 :
tcursor ( CURSOR_LOAD ) ;
tclearregion ( 0 , 0 , term . col - 1 , term . row - 1 ) ;
break ;
default :
goto unknown ;
}
}
}
} else goto unknown ;
break ;
break ;
case ' M ' : /* Delete <n> lines */
case ' M ' : /* D L -- D elete <n> lines */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tdeleteline ( escseq . arg [ 0 ] ) ;
tdeleteline ( escseq . arg [ 0 ] ) ;
break ;
break ;
case ' X ' :
case ' X ' : /* ECH -- Erase <n> char XXX: same? */
case ' P ' : /* D elete <n> char */
case ' P ' : /* D CH -- D elete <n> char */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tdeletechar ( escseq . arg [ 0 ] ) ;
tdeletechar ( escseq . arg [ 0 ] ) ;
break ;
break ;
case ' d ' : /* Move to <row> */
/* XXX: (CSI n Z) CBT -- Cursor Backward Tabulation <n> tab stops */
case ' d ' : /* VPA -- Move to <row> */
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
DEFAULT ( escseq . arg [ 0 ] , 1 ) ;
tmoveto ( term . c . x , escseq . arg [ 0 ] - 1 ) ;
tmoveto ( term . c . x , escseq . arg [ 0 ] - 1 ) ;
break ;
break ;
case ' h ' : /* S et terminal mode */
case ' h ' : /* S M -- S et terminal mode */
if ( escseq . priv )
if ( escseq . priv ) {
switch ( escseq . arg [ 0 ] ) {
switch ( escseq . arg [ 0 ] ) {
case 1 :
term . mode | = MODE_APPKEYPAD ;
break ;
case 7 :
case 7 :
term . mode | = TMwrap ;
term . mode | = MODE_WRAP ;
break ;
case 12 : /* att610 -- Start blinking cursor (IGNORED) */
break ;
break ;
case 25 :
case 25 :
term . c . hidden = 0 ;
term . c . hidden = 0 ;
break ;
break ;
case 1034 :
case 1048 :
/* XXX: Interpret "meta" key, sets eighth bit. */
case 1049 : /* XXX: no alt. screen to erase/save */
tcursor ( CURSOR_SAVE ) ;
tclearregion ( 0 , 0 , term . col - 1 , term . row - 1 ) ;
break ;
break ;
default :
goto unknown ;
}
}
} else goto unknown ;
break ;
break ;
case ' m ' : /* Terminal attribute (color) */
case ' m ' : /* SGR -- Terminal attribute (color) */
tsetattr ( escseq . arg , escseq . narg ) ;
tsetattr ( escseq . arg , escseq . narg ) ;
break ;
break ;
case ' r ' :
case ' r ' : /* DECSTBM -- Set Scrolling Region */
if ( escseq . priv )
if ( escseq . priv )
goto unknown ;
goto unknown ;
else {
else {
@ -725,11 +744,11 @@ csihandle(void) {
tsetscroll ( escseq . arg [ 0 ] - 1 , escseq . arg [ 1 ] - 1 ) ;
tsetscroll ( escseq . arg [ 0 ] - 1 , escseq . arg [ 1 ] - 1 ) ;
}
}
break ;
break ;
case ' s ' : /* Save cursor position */
case ' s ' : /* DECSC -- Save cursor position (ANSI.SYS) */
tc pos( CSsave ) ;
tc ursor( CURSOR_SAVE ) ;
break ;
break ;
case ' u ' : /* Load cursor position */
case ' u ' : /* DECRC -- Restore cursor position (ANSI.SYS) */
tc pos( CSload ) ;
tc ursor( CURSOR_LOAD ) ;
break ;
break ;
}
}
}
}
@ -759,70 +778,82 @@ tputtab(void) {
space - - ;
space - - ;
for ( ; space > 0 ; space - - )
for ( ; space > 0 ; space - - )
t cursor( CSright ) ;
t movecursor( CURSOR_RIGHT ) ;
}
}
void
void
tputc ( char c ) {
tputc ( char c ) {
#if 0
/* dump(c); */
dump ( c ) ;
if ( term . esc & ESC_START ) {
# endif
if ( term . esc & ESC_CSI ) {
if ( term . esc & ESCin ) {
if ( term . esc & ESCcsi ) {
escseq . buf [ escseq . len + + ] = c ;
escseq . buf [ escseq . len + + ] = c ;
if ( BETWEEN ( c , 0x40 , 0x7E ) | | escseq . len > = ESC SIZ) {
if ( BETWEEN ( c , 0x40 , 0x7E ) | | escseq . len > = ESC_BUF_SIZ ) {
term . esc = 0 ;
term . esc = 0 ;
csiparse ( ) , csihandle ( ) ;
csiparse ( ) , csihandle ( ) ;
}
}
} else if ( term . esc & ESC osc ) {
} else if ( term . esc & ESC _OSC ) {
if ( c = = ' ; ' ) {
if ( c = = ' ; ' ) {
term . titlelen = 0 ;
term . titlelen = 0 ;
term . esc = ESC in | ESCtitle ;
term . esc = ESC _START | ESC_TITLE ;
}
}
} else if ( term . esc & ESC title ) {
} else if ( term . esc & ESC _TITLE ) {
if ( c = = ' \a ' | | term . titlelen + 1 > = TITLESIZ) {
if ( c = = ' \a ' | | term . titlelen + 1 > = ESC_ TITLE_ SIZ) {
term . esc = 0 ;
term . esc = 0 ;
term . title [ term . titlelen ] = ' \0 ' ;
term . title [ term . titlelen ] = ' \0 ' ;
XStoreName ( xw . dis , xw . win , term . title ) ;
XStoreName ( xw . dis , xw . win , term . title ) ;
} else {
} else {
term . title [ term . titlelen + + ] = c ;
term . title [ term . titlelen + + ] = c ;
}
}
} else if ( term . esc & ESCcharset ) {
} else if ( term . esc & ESC_ALTCHARSET ) {
printf ( " ESC ( %c \n " , c ) ;
switch ( c ) {
switch ( c ) {
case ' 0 ' : /* Line drawing crap */
case ' 0 ' : /* Line drawing crap */
term . c . attr . mode | = AT gfx ;
term . c . attr . mode | = AT TR_GFX ;
break ;
break ;
case ' B ' : /* Back to regular text */
case ' B ' : /* Back to regular text */
term . c . attr . mode & = ~ AT gfx ;
term . c . attr . mode & = ~ AT TR_GFX ;
break ;
break ;
default :
printf ( " esc unhandled charset: ESC ( %c \n " , c ) ;
}
}
term . esc = 0 ;
term . esc = 0 ;
} else {
} else {
switch ( c ) {
switch ( c ) {
case ' [ ' :
case ' [ ' :
term . esc | = ESC csi ;
term . esc | = ESC _CSI ;
break ;
break ;
case ' ] ' :
case ' ] ' :
term . esc | = ESC osc ;
term . esc | = ESC _OSC ;
break ;
break ;
case ' ( ' :
case ' ( ' :
term . esc | = ESC charset ;
term . esc | = ESC _ALTCHARSET ;
break ;
break ;
case ' A ' :
case ' A ' :
tmoveto ( term . c . x , term . c . y - 1 ) ;
tmoveto ( term . c . x , term . c . y - 1 ) ;
term . esc = 0 ;
break ;
break ;
case ' B ' :
case ' B ' :
tmoveto ( term . c . x , term . c . y + 1 ) ;
tmoveto ( term . c . x , term . c . y + 1 ) ;
term . esc = 0 ;
break ;
break ;
case ' C ' :
case ' C ' :
tmoveto ( term . c . x + 1 , term . c . y ) ;
tmoveto ( term . c . x + 1 , term . c . y ) ;
term . esc = 0 ;
break ;
break ;
case ' D ' :
case ' D ' :
tmoveto ( term . c . x - 1 , term . c . y ) ;
tmoveto ( term . c . x - 1 , term . c . y ) ;
term . esc = 0 ;
break ;
case ' = ' : /* DECPAM */
term . mode | = MODE_APPKEYPAD ;
term . esc = 0 ;
break ;
case ' > ' : /* DECPNM */
term . mode & = ~ MODE_APPKEYPAD ;
term . esc = 0 ;
break ;
break ;
default :
default :
fprintf ( stderr , " erresc: unknown sequence ESC %02X '%c' \n " , c , isprint ( c ) ? c : ' . ' ) ;
fprintf ( stderr , " erresc: unknown sequence ESC %02X '%c' \n " , c , isprint ( c ) ? c : ' . ' ) ;
term . esc = 0 ;
}
}
}
}
} else {
} else {
@ -831,7 +862,7 @@ tputc(char c) {
tputtab ( ) ;
tputtab ( ) ;
break ;
break ;
case ' \b ' :
case ' \b ' :
t cursor( CSleft ) ;
t movecursor( CURSOR_LEFT ) ;
break ;
break ;
case ' \r ' :
case ' \r ' :
tmoveto ( 0 , term . c . y ) ;
tmoveto ( 0 , term . c . y ) ;
@ -844,11 +875,11 @@ tputc(char c) {
break ;
break ;
case ' \033 ' :
case ' \033 ' :
csireset ( ) ;
csireset ( ) ;
term . esc = ESC in ;
term . esc = ESC _START ;
break ;
break ;
default :
default :
tsetchar ( c ) ;
tsetchar ( c ) ;
t cursor( CSright ) ;
t movecursor( CURSOR_RIGHT ) ;
break ;
break ;
}
}
}
}
@ -917,7 +948,7 @@ xscroll(void) {
int dsty = term . top * xw . ch ;
int dsty = term . top * xw . ch ;
int height = ( term . bot - term . top ) * xw . ch ;
int height = ( term . bot - term . top ) * xw . ch ;
xcursor ( C Shide ) ;
xcursor ( C URSOR_HIDE ) ;
XCopyArea ( xw . dis , xw . win , xw . win , dc . gc , 0 , srcy , xw . w , height , 0 , dsty ) ;
XCopyArea ( xw . dis , xw . win , xw . win , dc . gc , 0 , srcy , xw . w , height , 0 , dsty ) ;
xclear ( 0 , term . bot , term . col - 1 , term . bot ) ;
xclear ( 0 , term . bot , term . col - 1 , term . bot ) ;
}
}
@ -950,7 +981,7 @@ xinit(void) {
term . c . attr . fg = DefaultFG ;
term . c . attr . fg = DefaultFG ;
term . c . attr . bg = DefaultBG ;
term . c . attr . bg = DefaultBG ;
term . c . attr . mode = AT none ;
term . c . attr . mode = AT TR_NULL ;
/* windows */
/* windows */
xw . h = term . row * xw . ch ;
xw . h = term . row * xw . ch ;
xw . w = term . col * xw . cw ;
xw . w = term . col * xw . cw ;
@ -982,7 +1013,7 @@ xdraws (char *s, Glyph base, int x, int y, int len) {
int winx = x * xw . cw , winy = y * xw . ch + dc . font - > ascent , width = len * xw . cw ;
int winx = x * xw . cw , winy = y * xw . ch + dc . font - > ascent , width = len * xw . cw ;
int i ;
int i ;
if ( base . mode & AT reverse )
if ( base . mode & AT TR_REVERSE )
xfg = dc . col [ base . bg ] , xbg = dc . col [ base . fg ] ;
xfg = dc . col [ base . bg ] , xbg = dc . col [ base . fg ] ;
else
else
xfg = dc . col [ base . fg ] , xbg = dc . col [ base . bg ] ;
xfg = dc . col [ base . fg ] , xbg = dc . col [ base . bg ] ;
@ -990,15 +1021,13 @@ xdraws (char *s, Glyph base, int x, int y, int len) {
XSetBackground ( xw . dis , dc . gc , xbg ) ;
XSetBackground ( xw . dis , dc . gc , xbg ) ;
XSetForeground ( xw . dis , dc . gc , xfg ) ;
XSetForeground ( xw . dis , dc . gc , xfg ) ;
if ( base . mode & ATgfx ) {
if ( base . mode & ATTR_GFX )
for ( i = 0 ; i < len ; i + + )
for ( i = 0 ; i < len ; i + + )
s [ i ] = gfx [ s [ i ] ] ;
s [ i ] = gfx [ s [ i ] ] ;
}
XDrawImageString ( xw . dis , xw . win , dc . gc , winx , winy , s , len ) ;
XDrawImageString ( xw . dis , xw . win , dc . gc , winx , winy , s , len ) ;
if ( base . mode & AT underline )
if ( base . mode & AT TR_UNDERLINE )
XDrawLine ( xw . dis , xw . win , dc . gc , winx , winy + 1 , winx + width - 1 , winy + 1 ) ;
XDrawLine ( xw . dis , xw . win , dc . gc , winx , winy + 1 , winx + width - 1 , winy + 1 ) ;
}
}
@ -1008,7 +1037,7 @@ xdrawc(int x, int y, Glyph g) {
unsigned long xfg , xbg ;
unsigned long xfg , xbg ;
/* reverse video */
/* reverse video */
if ( g . mode & AT reverse )
if ( g . mode & AT TR_REVERSE )
xfg = dc . col [ g . bg ] , xbg = dc . col [ g . fg ] ;
xfg = dc . col [ g . bg ] , xbg = dc . col [ g . fg ] ;
else
else
xfg = dc . col [ g . fg ] , xbg = dc . col [ g . bg ] ;
xfg = dc . col [ g . fg ] , xbg = dc . col [ g . bg ] ;
@ -1022,20 +1051,20 @@ void
xcursor ( int mode ) {
xcursor ( int mode ) {
static int oldx = 0 ;
static int oldx = 0 ;
static int oldy = 0 ;
static int oldy = 0 ;
Glyph g = { ' ' , AT none , DefaultBG , DefaultCS , 0 } ;
Glyph g = { ' ' , AT TR_NULL , DefaultBG , DefaultCS , 0 } ;
LIMIT ( oldx , 0 , term . col - 1 ) ;
LIMIT ( oldx , 0 , term . col - 1 ) ;
LIMIT ( oldy , 0 , term . row - 1 ) ;
LIMIT ( oldy , 0 , term . row - 1 ) ;
if ( term . line [ term . c . y ] [ term . c . x ] . state & CRset )
if ( term . line [ term . c . y ] [ term . c . x ] . state & GLYPH_SET )
g . c = term . line [ term . c . y ] [ term . c . x ] . c ;
g . c = term . line [ term . c . y ] [ term . c . x ] . c ;
/* remove the old cursor */
/* remove the old cursor */
if ( term . line [ oldy ] [ oldx ] . state & CRset )
if ( term . line [ oldy ] [ oldx ] . state & GLYPH_SET )
xdrawc ( oldx , oldy , term . line [ oldy ] [ oldx ] ) ;
xdrawc ( oldx , oldy , term . line [ oldy ] [ oldx ] ) ;
else
else
xclear ( oldx , oldy , oldx , oldy ) ;
xclear ( oldx , oldy , oldx , oldy ) ;
/* draw the new one */
/* draw the new one */
if ( mode = = C Sdraw ) {
if ( mode = = C URSOR_DRAW ) {
xdrawc ( term . c . x , term . c . y , g ) ;
xdrawc ( term . c . x , term . c . y , g ) ;
oldx = term . c . x , oldy = term . c . y ;
oldx = term . c . x , oldy = term . c . y ;
}
}
@ -1045,14 +1074,14 @@ void
draw ( int redraw_all ) {
draw ( int redraw_all ) {
int i , x , y , ox ;
int i , x , y , ox ;
Glyph base , new ;
Glyph base , new ;
char buf [ MAX DRAWBUF] ;
char buf [ DRAW_ BUF_SIZ ] ;
for ( y = 0 ; y < term . row ; y + + ) {
for ( y = 0 ; y < term . row ; y + + ) {
base = term . line [ y ] [ 0 ] ;
base = term . line [ y ] [ 0 ] ;
i = ox = 0 ;
i = ox = 0 ;
for ( x = 0 ; x < term . col ; x + + ) {
for ( x = 0 ; x < term . col ; x + + ) {
new = term . line [ y ] [ x ] ;
new = term . line [ y ] [ x ] ;
if ( ! ATTRCMP ( base , new ) & & i < MAX DRAWBUF)
if ( ! ATTRCMP ( base , new ) & & i < DRAW_ BUF_SIZ )
buf [ i + + ] = new . c ;
buf [ i + + ] = new . c ;
else {
else {
xdraws ( buf , base , ox , y , i ) ;
xdraws ( buf , base , ox , y , i ) ;
@ -1065,12 +1094,12 @@ draw(int redraw_all) {
xdraws ( buf , base , ox , y , i ) ;
xdraws ( buf , base , ox , y , i ) ;
}
}
if ( ! term . c . hidden )
if ( ! term . c . hidden )
xcursor ( C Sdraw ) ;
xcursor ( C URSOR_DRAW ) ;
}
}
void
void
expose ( XEvent * ev ) {
expose ( XEvent * ev ) {
draw ( SC redraw ) ;
draw ( SC REEN_REDRAW ) ;
}
}
char *
char *
@ -1105,6 +1134,13 @@ kpress(XEvent *ev) {
ttywrite ( buf , len ) ;
ttywrite ( buf , len ) ;
} else
} else
switch ( ksym ) {
switch ( ksym ) {
case XK_Up :
case XK_Down :
case XK_Left :
case XK_Right :
sprintf ( buf , " \033 %c%c " , term . mode & MODE_APPKEYPAD ? ' O ' : ' [ ' , " DACB " [ ksym - XK_Left ] ) ;
ttywrite ( buf , 3 ) ;
break ;
case XK_Insert :
case XK_Insert :
if ( shift )
if ( shift )
/* XXX: paste X clipboard */ ;
/* XXX: paste X clipboard */ ;
@ -1126,7 +1162,7 @@ resize(XEvent *e) {
ttyresize ( col , row ) ;
ttyresize ( col , row ) ;
xw . w = e - > xconfigure . width ;
xw . w = e - > xconfigure . width ;
xw . h = e - > xconfigure . height ;
xw . h = e - > xconfigure . height ;
draw ( SC redraw ) ;
draw ( SC REEN_REDRAW ) ;
}
}
}
}
@ -1151,7 +1187,7 @@ run(void) {
}
}
if ( FD_ISSET ( cmdfd , & rfd ) ) {
if ( FD_ISSET ( cmdfd , & rfd ) ) {
ttyread ( ) ;
ttyread ( ) ;
draw ( SC update ) ;
draw ( SC REEN_UPDATE ) ;
}
}
while ( XPending ( xw . dis ) ) {
while ( XPending ( xw . dis ) ) {
XNextEvent ( xw . dis , & ev ) ;
XNextEvent ( xw . dis , & ev ) ;