tterm.c - neatvi - [fork] simple vi-type editor with UTF-8 support
 (HTM) git clone git://src.adamsgaard.dk/neatvi
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       tterm.c (3557B)
       ---
            1 #include <poll.h>
            2 #include <signal.h>
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 #include <sys/ioctl.h>
            7 #include <termios.h>
            8 #include <unistd.h>
            9 #include "vi.h"
           10 
           11 static struct sbuf *term_sbuf;
           12 static int rows, cols;
           13 static struct termios termios;
           14 
           15 void term_init(void)
           16 {
           17         struct winsize win;
           18         struct termios newtermios;
           19         tcgetattr(0, &termios);
           20         newtermios = termios;
           21         newtermios.c_lflag &= ~(ICANON | ISIG);
           22         newtermios.c_lflag &= ~ECHO;
           23         tcsetattr(0, TCSAFLUSH, &newtermios);
           24         if (getenv("LINES"))
           25                 rows = atoi(getenv("LINES"));
           26         if (getenv("COLUMNS"))
           27                 cols = atoi(getenv("COLUMNS"));
           28         if (!ioctl(0, TIOCGWINSZ, &win)) {
           29                 cols = win.ws_col;
           30                 rows = win.ws_row;
           31         }
           32         cols = cols ? cols : 80;
           33         rows = rows ? rows : 25;
           34         term_str("\33[m");
           35 }
           36 
           37 void term_done(void)
           38 {
           39         term_commit();
           40         tcsetattr(0, 0, &termios);
           41 }
           42 
           43 void term_suspend(void)
           44 {
           45         term_done();
           46         kill(getpid(), SIGSTOP);
           47         term_init();
           48 }
           49 
           50 void term_record(void)
           51 {
           52         if (!term_sbuf)
           53                 term_sbuf = sbuf_make();
           54 }
           55 
           56 void term_commit(void)
           57 {
           58         if (term_sbuf) {
           59                 write(1, sbuf_buf(term_sbuf), sbuf_len(term_sbuf));
           60                 sbuf_free(term_sbuf);
           61                 term_sbuf = NULL;
           62         }
           63 }
           64 
           65 static void term_out(char *s)
           66 {
           67         if (term_sbuf)
           68                 sbuf_str(term_sbuf, s);
           69         else
           70                 write(1, s, strlen(s));
           71 }
           72 
           73 void term_str(char *s)
           74 {
           75         term_out(s);
           76 }
           77 
           78 void term_chr(int ch)
           79 {
           80         char s[4] = {ch};
           81         term_out(s);
           82 }
           83 
           84 void term_kill(void)
           85 {
           86         term_out("\33[K");
           87 }
           88 
           89 void term_room(int n)
           90 {
           91         char cmd[16];
           92         if (n < 0)
           93                 sprintf(cmd, "\33[%dM", -n);
           94         if (n > 0)
           95                 sprintf(cmd, "\33[%dL", n);
           96         if (n)
           97                 term_out(cmd);
           98 }
           99 
          100 void term_pos(int r, int c)
          101 {
          102         char buf[32] = "\r";
          103         if (c < 0)
          104                 c = 0;
          105         if (c >= xcols)
          106                 c = cols - 1;
          107         if (r < 0)
          108                 sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D');
          109         else
          110                 sprintf(buf, "\33[%d;%dH", r + 1, c + 1);
          111         term_out(buf);
          112 }
          113 
          114 int term_rows(void)
          115 {
          116         return rows;
          117 }
          118 
          119 int term_cols(void)
          120 {
          121         return cols;
          122 }
          123 
          124 static char ibuf[4096];                /* input character buffer */
          125 static char icmd[4096];                /* read after the last term_cmd() */
          126 static int ibuf_pos, ibuf_cnt;        /* ibuf[] position and length */
          127 static int icmd_pos;                /* icmd[] position */
          128 
          129 /* read s before reading from the terminal */
          130 void term_push(char *s, int n)
          131 {
          132         n = MIN(n, sizeof(ibuf) - ibuf_cnt);
          133         memcpy(ibuf + ibuf_cnt, s, n);
          134         ibuf_cnt += n;
          135 }
          136 
          137 /* return a static buffer containing inputs read since the last term_cmd() */
          138 char *term_cmd(int *n)
          139 {
          140         *n = icmd_pos;
          141         icmd_pos = 0;
          142         return icmd;
          143 }
          144 
          145 int term_read(void)
          146 {
          147         struct pollfd ufds[1];
          148         int n, c;
          149         if (ibuf_pos >= ibuf_cnt) {
          150                 ufds[0].fd = 0;
          151                 ufds[0].events = POLLIN;
          152                 if (poll(ufds, 1, -1) <= 0)
          153                         return -1;
          154                 /* read a single input character */
          155                 if ((n = read(0, ibuf, 1)) <= 0)
          156                         return -1;
          157                 ibuf_cnt = n;
          158                 ibuf_pos = 0;
          159         }
          160         c = ibuf_pos < ibuf_cnt ? (unsigned char) ibuf[ibuf_pos++] : -1;
          161         if (icmd_pos < sizeof(icmd))
          162                 icmd[icmd_pos++] = c;
          163         return c;
          164 }
          165 
          166 /* return a static string that changes text attributes from old to att */
          167 char *term_att(int att, int old)
          168 {
          169         static char buf[128];
          170         char *s = buf;
          171         int fg = SYN_FG(att);
          172         int bg = SYN_BG(att);
          173         if (att == old)
          174                 return "";
          175         s += sprintf(s, "\33[");
          176         if (att & SYN_BD)
          177                 s += sprintf(s, ";1");
          178         if (att & SYN_IT)
          179                 s += sprintf(s, ";3");
          180         else if (att & SYN_RV)
          181                 s += sprintf(s, ";7");
          182         if (SYN_FGSET(att)) {
          183                 if ((fg & 0xff) < 8)
          184                         s += sprintf(s, ";%d", 30 + (fg & 0xff));
          185                 else
          186                         s += sprintf(s, ";38;5;%d", (fg & 0xff));
          187         }
          188         if (SYN_BGSET(att)) {
          189                 if ((bg & 0xff) < 8)
          190                         s += sprintf(s, ";%d", 40 + (bg & 0xff));
          191                 else
          192                         s += sprintf(s, ";48;5;%d", (bg & 0xff));
          193         }
          194         s += sprintf(s, "m");
          195         return buf;
          196 }