neatvi

[fork] simple vi-type editor with UTF-8 support
git clone git://src.adamsgaard.dk/neatvi # fast
git clone https://src.adamsgaard.dk/neatvi.git # slow
Log | Files | Refs | README Back to index

term.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 }