X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=st.c;h=12e1e1f1e5ca4b799d3655f3e24094e9c675c0cb;hb=297c886b72f4e9093973aaa14b66d392f6196634;hp=84f9abb071d87c0f664daf445d3c01d7ccb7639a;hpb=c5c2365ab7c7ac2671b6e7d31cc9b0d41636393c;p=st.git diff --git a/st.c b/st.c index 84f9abb..12e1e1f 100644 --- a/st.c +++ b/st.c @@ -137,6 +137,16 @@ enum term_mode { |MODE_MOUSEMANY, }; +enum charset { + CS_GRAPHIC0, + CS_GRAPHIC1, + CS_UK, + CS_USA, + CS_MULTI, + CS_GER, + CS_FIN +}; + enum escape_state { ESC_START = 1, ESC_CSI = 2, @@ -216,6 +226,9 @@ typedef struct { int bot; /* bottom scroll limit */ int mode; /* terminal mode flags */ int esc; /* escape state flags */ + char trantbl[4]; /* charset table translation */ + int charset; /* current charset */ + int icharset; /* selected charset for sequence */ bool numlock; /* lock numbers in keyboard */ bool *tabs; } Term; @@ -243,15 +256,15 @@ typedef struct { } XWindow; typedef struct { - int b; + uint b; uint mask; - char s[ESC_BUF_SIZ]; + char *s; } Mousekey; typedef struct { KeySym k; uint mask; - char s[ESC_BUF_SIZ]; + char *s; /* three valued logic variables: 0 indifferent, 1 on, -1 off */ signed char appkey; /* application keypad */ signed char appcursor; /* application cursor */ @@ -367,10 +380,13 @@ static void tsetmode(bool, bool, int *, int); static void tfulldirt(void); static void techo(char *, int); static long tdefcolor(int *, int *, int); +static void tselcs(void); +static void tdeftran(char); static inline bool match(uint, uint); static void ttynew(void); static void ttyread(void); static void ttyresize(void); +static void ttysend(char *, size_t); static void ttywrite(const char *, size_t); static void xdraws(char *, Glyph, int, int, int, int); @@ -878,9 +894,7 @@ bpress(XEvent *e) { for(mk = mshortcuts; mk < mshortcuts + LEN(mshortcuts); mk++) { if(e->xbutton.button == mk->b && match(mk->mask, e->xbutton.state)) { - ttywrite(mk->s, strlen(mk->s)); - if(IS_SET(MODE_ECHO)) - techo(mk->s, strlen(mk->s)); + ttysend(mk->s, strlen(mk->s)); return; } } @@ -1016,7 +1030,7 @@ selnotify(XEvent *e) { if(IS_SET(MODE_BRCKTPASTE)) ttywrite("\033[200~", 6); - ttywrite((const char *)data, nitems * format / 8); + ttysend((char *)data, nitems * format / 8); if(IS_SET(MODE_BRCKTPASTE)) ttywrite("\033[201~", 6); XFree(data); @@ -1285,6 +1299,13 @@ ttywrite(const char *s, size_t n) { } void +ttysend(char *s, size_t n) { + ttywrite(s, n); + if(IS_SET(MODE_ECHO)) + techo(s, n); +} + +void ttyresize(void) { struct winsize w; @@ -1369,6 +1390,8 @@ treset(void) { term.top = 0; term.bot = term.row - 1; term.mode = MODE_WRAP; + memset(term.trantbl, sizeof(term.trantbl), CS_USA); + term.charset = 0; tclearregion(0, 0, term.col-1, term.row-1); tmoveto(0, 0); @@ -2260,6 +2283,33 @@ techo(char *buf, int len) { } void +tdeftran(char ascii) { + char c, (*bp)[2]; + static char tbl[][2] = { + {'0', CS_GRAPHIC0}, {'1', CS_GRAPHIC1}, {'A', CS_UK}, + {'B', CS_USA}, {'<', CS_MULTI}, {'K', CS_GER}, + {'5', CS_FIN}, {'C', CS_FIN}, + {0, 0} + }; + + for (bp = &tbl[0]; (c = (*bp)[0]) && c != ascii; ++bp) + /* nothing */; + + if (c == 0) + fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); + else + term.trantbl[term.icharset] = (*bp)[1]; +} + +void +tselcs(void) { + if (term.trantbl[term.charset] == CS_GRAPHIC0) + term.c.attr.mode |= ATTR_GFX; + else + term.c.attr.mode &= ~ATTR_GFX; +} + +void tputc(char *c, int len) { uchar ascii = *c; bool control = ascii < '\x20' || ascii == 0177; @@ -2351,13 +2401,12 @@ tputc(char *c, int len) { term.esc = ESC_START; return; case '\016': /* SO */ + term.charset = 0; + tselcs(); + return; case '\017': /* SI */ - /* - * Different charsets are hard to handle. Applications - * should use the right alt charset escapes for the - * only reason they still exist: line drawing. The - * rest is incompatible history st should not support. - */ + term.charset = 1; + tselcs(); return; case '\032': /* SUB */ case '\030': /* CAN */ @@ -2385,22 +2434,8 @@ tputc(char *c, int len) { if(ascii == '\\') strhandle(); } else if(term.esc & ESC_ALTCHARSET) { - switch(ascii) { - case '0': /* Line drawing set */ - term.c.attr.mode |= ATTR_GFX; - break; - case 'B': /* USASCII */ - term.c.attr.mode &= ~ATTR_GFX; - break; - case 'A': /* UK (IGNORED) */ - case '<': /* multinational charset (IGNORED) */ - case '5': /* Finnish (IGNORED) */ - case 'C': /* Finnish (IGNORED) */ - case 'K': /* German (IGNORED) */ - break; - default: - fprintf(stderr, "esc unhandled charset: ESC ( %c\n", ascii); - } + tdeftran(ascii); + tselcs(); term.esc = 0; } else if(term.esc & ESC_TEST) { if(ascii == '8') { /* DEC screen alignment test. */ @@ -2431,13 +2466,12 @@ tputc(char *c, int len) { term.esc |= ESC_STR; break; case '(': /* set primary charset G0 */ + case ')': /* set secondary charset G1 */ + case '*': /* set tertiary charset G2 */ + case '+': /* set quaternary charset G3 */ + term.icharset = ascii - '('; term.esc |= ESC_ALTCHARSET; break; - case ')': /* set secondary charset G1 (IGNORED) */ - case '*': /* set tertiary charset G2 (IGNORED) */ - case '+': /* set quaternary charset G3 (IGNORED) */ - term.esc = 0; - break; case 'D': /* IND -- Linefeed */ if(term.c.y == term.bot) { tscrollup(term.top, 1); @@ -3535,8 +3569,8 @@ void kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; KeySym ksym; - char xstr[31], buf[32], *customkey, *cp = buf; - int len, ret; + char buf[32], *customkey; + int len; long c; Status status; Shortcut *bp; @@ -3544,8 +3578,7 @@ kpress(XEvent *ev) { if(IS_SET(MODE_KBDLOCK)) return; - len = XmbLookupString(xw.xic, e, xstr, sizeof(xstr), &ksym, &status); - e->state &= ~Mod2Mask; + len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); /* 1. shortcuts */ for(bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if(ksym == bp->keysym && match(bp->mod, e->state)) { @@ -3556,33 +3589,26 @@ kpress(XEvent *ev) { /* 2. custom keys from config.h */ if((customkey = kmap(ksym, e->state))) { - len = strlen(customkey); - memcpy(buf, customkey, len); - /* 3. hardcoded (overrides X lookup) */ - } else { - if(len == 0) - return; + ttysend(customkey, strlen(customkey)); + return; + } - if(len == 1 && e->state & Mod1Mask) { - if(IS_SET(MODE_8BIT)) { - if(*xstr < 0177) { - c = *xstr | 0x80; - ret = utf8encode(&c, cp); - cp += ret; - len = 0; - } - } else { - *cp++ = '\033'; + /* 3. composed string from input method */ + if(len == 0) + return; + if(len == 1 && e->state & Mod1Mask) { + if(IS_SET(MODE_8BIT)) { + if(*buf < 0177) { + c = *buf | 0x80; + len = utf8encode(&c, buf); } + } else { + buf[1] = buf[0]; + buf[0] = '\033'; + len = 2; } - - memcpy(cp, xstr, len); - len = cp - buf + len; } - - ttywrite(buf, len); - if(IS_SET(MODE_ECHO)) - techo(buf, len); + ttysend(buf, len); }