Home
       tterm.c - iomenu - interactive terminal-based selection menu
  HTML git clone git://bitreich.org/iomenu git://hg6vgqziawt5s4dj.onion/iomenu
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       tterm.c (1800B)
       ---
            1 #include "term.h"
            2 
            3 #include <ctype.h>
            4 #include <stdint.h>
            5 #include <stdio.h>
            6 #include <string.h>
            7 #include <sys/ioctl.h>
            8 #include <termios.h>
            9 
           10 #include "compat.h"
           11 #include "utf8.h"
           12 
           13 struct term term = {0};
           14 
           15 static int
           16 term_codepoint_width(uint32_t codepoint, int pos)
           17 {
           18         if (codepoint == '\t')
           19                 return 8 - pos % 8;
           20         return wcwidth(codepoint);
           21 }
           22 
           23 int
           24 term_at_width(char const *s, int width, int pos)
           25 {
           26         char const *beg = s;
           27 
           28         for (uint32_t state = 0, codepoint; *s != '\0'; s++) {
           29                 if (utf8_decode(&state, &codepoint, *s) == UTF8_ACCEPT) {
           30                         pos += term_codepoint_width(codepoint, pos);
           31                         if (pos > width)
           32                                 break;
           33                 }
           34         }
           35         return s - beg;
           36 }
           37 
           38 int
           39 term_raw_on(int fd)
           40 {
           41         struct termios new_termios = {0};
           42         char *seq = "\x1b[s\x1b[?1049h\x1b[H";
           43         ssize_t len = strlen(seq);
           44 
           45         if (write(fd, seq, len) < len)
           46                 return -1;
           47 
           48         if (tcgetattr(fd, &term.old_termios) < 0)
           49                 return -1;
           50         memcpy(&new_termios, &term.old_termios, sizeof new_termios);
           51 
           52         new_termios.c_lflag &= ~(ICANON | ECHO | IEXTEN | IGNBRK | ISIG);
           53         if (tcsetattr(fd, TCSANOW, &new_termios) == -1)
           54                 return -1;
           55         return 0;
           56 }
           57 
           58 int
           59 term_raw_off(int fd)
           60 {
           61         char *seq = "\x1b[2J\x1b[u\033[?1049l";
           62         ssize_t len = strlen(seq);
           63 
           64         if (tcsetattr(fd, TCSANOW, &term.old_termios) < 0)
           65                 return -1;
           66         if (write(fd, seq, len) < len)
           67                 return -1;
           68         return 0;
           69 }
           70 
           71 int
           72 term_get_key(FILE *fp)
           73 {
           74         int key, num;
           75 
           76         key = fgetc(fp);
           77 top:
           78         switch (key) {
           79         case EOF:
           80                 return -1;
           81         case TERM_KEY_ALT('['):
           82                 key = getc(fp);
           83                 if (key == EOF)
           84                         return -1;
           85 
           86                 for (num = 0; isdigit(key);) {
           87                         num *= 10;
           88                         num += key - '0';
           89 
           90                         key = fgetc(fp);
           91                         if (key == EOF)
           92                                 return -1;
           93                 }
           94 
           95                 key = TERM_KEY_CSI(key, num);
           96 
           97                 goto top;
           98         case TERM_KEY_ESC:
           99                 key = getc(fp);
          100                 if (key == EOF)
          101                         return -1;
          102                 key = TERM_KEY_ALT(key);
          103                 goto top;
          104         default:
          105                 return key;
          106         }
          107 }