vip

VI Plus
git clone https://codeberg.org/night0721/vip
Log | Files | Refs | README | LICENSE

term.c (1674B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <termios.h>
      4 #include <unistd.h>
      5 #include <sys/ioctl.h>
      6 
      7 #include "vip.h"
      8 
      9 extern editor vip;
     10 
     11 void die(const char *s)
     12 {
     13 	write(STDOUT_FILENO, "\x1b[2J", 4);
     14 	write(STDOUT_FILENO, "\x1b[H", 3);
     15 	perror(s);
     16 	exit(1);
     17 }
     18 
     19 void reset_term()
     20 {
     21 	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &vip.termios) == -1) {
     22 		die("tcsetattr");
     23 	}
     24 }
     25 
     26 /*
     27  * Setup terminal
     28  */
     29 void setup_term()
     30 {
     31 	if (tcgetattr(STDIN_FILENO, &vip.termios) == -1) {
     32 		die("tcgetattr");
     33 	}
     34 	atexit(reset_term);
     35 
     36 	struct termios raw = vip.termios;
     37 	/* disbable echo, line output and signals */
     38 	raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
     39 	raw.c_oflag &= ~(OPOST);
     40 	raw.c_cflag |= (CS8);
     41 	raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
     42 	raw.c_cc[VMIN] = 0;
     43 	raw.c_cc[VTIME] = 1;
     44 	if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
     45 		die("tcsetattr");
     46 	}
     47 }
     48 
     49 int get_cursor_position(int *rows, int *cols)
     50 {
     51 	char buf[32];
     52 	unsigned int i = 0;
     53 	if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) {
     54 		return -1;
     55 	}
     56 	while (i < sizeof(buf) - 1) {
     57 		if (read(STDIN_FILENO, &buf[i], 1) != 1) {
     58 			break;
     59 		}
     60 		if (buf[i] == 'R') {
     61 			break;
     62 		}
     63 		i++;
     64 	}
     65 	buf[i] = '\0';
     66 	if (buf[0] != '\x1b' || buf[1] != '[') {
     67 		return -1;
     68 	}
     69 	if (sscanf(&buf[2], "%d;%d", rows, cols) != 2) {
     70 		return -1;
     71 	}
     72 	return 0;
     73 }
     74 
     75 int get_window_size(int *rows, int *cols)
     76 {
     77 	struct winsize ws;
     78 	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
     79 		/* Can't get window size */
     80 		if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12) {
     81 			return -1;
     82 		}
     83 		return get_cursor_position(rows, cols);
     84 	} else {
     85 		*cols = ws.ws_col;
     86 		*rows = ws.ws_row;
     87 		return 0;
     88 	}
     89 }