about summary refs log tree commit diff stats
path: root/cpp/termbox/termbox.c
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-05 21:17:24 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-05 21:17:24 -0700
commitb96af395b9af2ff9df94b3e82213171f30827c8d (patch)
tree17c8c12648ccc25625e2534ec8d74fbe8f1542cc /cpp/termbox/termbox.c
parent2e3b597fe85b654e82b891c22d50754fa5a26156 (diff)
downloadmu-b96af395b9af2ff9df94b3e82213171f30827c8d.tar.gz
1276 - make C++ version the default
I've tried to update the Readme, but there are at least a couple of issues.
Diffstat (limited to 'cpp/termbox/termbox.c')
-rw-r--r--cpp/termbox/termbox.c562
1 files changed, 0 insertions, 562 deletions
diff --git a/cpp/termbox/termbox.c b/cpp/termbox/termbox.c
deleted file mode 100644
index 13ef1359..00000000
--- a/cpp/termbox/termbox.c
+++ /dev/null
@@ -1,562 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <termios.h>
-#include <unistd.h>
-#include <wchar.h>
-
-#include "termbox.h"
-
-#include "bytebuffer.inl"
-#include "output.inl"
-#include "input.inl"
-
-struct cellbuf {
-  int width;
-  int height;
-  struct tb_cell *cells;
-};
-
-#define CELL(buf, x, y) (buf)->cells[(y) * (buf)->width + (x)]
-#define IS_CURSOR_HIDDEN(cx, cy) (cx == -1 || cy == -1)
-#define LAST_COORD_INIT -1
-
-static struct termios orig_tios;
-
-static struct cellbuf back_buffer;
-static struct cellbuf front_buffer;
-static struct bytebuffer output_buffer;
-static struct bytebuffer input_buffer;
-
-static int termw = -1;
-static int termh = -1;
-
-static int inout;
-static int winch_fds[2];
-
-static int lastx = LAST_COORD_INIT;
-static int lasty = LAST_COORD_INIT;
-static int cursor_x = -1;
-static int cursor_y = -1;
-
-static uint16_t background = TB_DEFAULT;
-static uint16_t foreground = TB_DEFAULT;
-
-static void write_cursor(int x, int y);
-static void write_sgr_fg(uint16_t fg);
-static void write_sgr_bg(uint16_t bg);
-static void write_sgr(uint16_t fg, uint16_t bg);
-
-static void cellbuf_init(struct cellbuf *buf, int width, int height);
-static void cellbuf_resize(struct cellbuf *buf, int width, int height);
-static void cellbuf_clear(struct cellbuf *buf);
-static void cellbuf_free(struct cellbuf *buf);
-
-static void update_size(void);
-static void update_term_size(void);
-static void send_attr(uint16_t fg, uint16_t bg);
-static void send_char(int x, int y, uint32_t c);
-static void send_clear(void);
-static void sigwinch_handler(int xxx);
-static int wait_fill_event(struct tb_event *event, struct timeval *timeout);
-
-/* may happen in a different thread */
-static volatile int buffer_size_change_request;
-
-/* -------------------------------------------------------- */
-
-int tb_init(void)
-{
-  inout = open("/dev/tty", O_RDWR);
-  if (inout == -1) {
-    return TB_EFAILED_TO_OPEN_TTY;
-  }
-
-  if (init_term() < 0) {
-    close(inout);
-    return TB_EUNSUPPORTED_TERMINAL;
-  }
-
-  if (pipe(winch_fds) < 0) {
-    close(inout);
-    return TB_EPIPE_TRAP_ERROR;
-  }
-
-  struct sigaction sa;
-  memset(&sa, 0, sizeof(sa));
-  sa.sa_handler = sigwinch_handler;
-  sa.sa_flags = 0;
-  sigaction(SIGWINCH, &sa, 0);
-
-  tcgetattr(inout, &orig_tios);
-
-  struct termios tios;
-  memcpy(&tios, &orig_tios, sizeof(tios));
-
-  tios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
-                           | INLCR | IGNCR | ICRNL | IXON);
-  tios.c_oflag &= ~OPOST;
-  tios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
-  tios.c_cflag &= ~(CSIZE | PARENB);
-  tios.c_cflag |= CS8;
-  tios.c_cc[VMIN] = 0;
-  tios.c_cc[VTIME] = 0;
-  tcsetattr(inout, TCSAFLUSH, &tios);
-
-  bytebuffer_init(&input_buffer, 128);
-  bytebuffer_init(&output_buffer, 32 * 1024);
-
-  bytebuffer_puts(&output_buffer, funcs[T_ENTER_CA]);
-  bytebuffer_puts(&output_buffer, funcs[T_ENTER_KEYPAD]);
-  bytebuffer_puts(&output_buffer, funcs[T_HIDE_CURSOR]);
-  send_clear();
-
-  update_term_size();
-  cellbuf_init(&back_buffer, termw, termh);
-  cellbuf_init(&front_buffer, termw, termh);
-  cellbuf_clear(&back_buffer);
-  cellbuf_clear(&front_buffer);
-
-  return 0;
-}
-
-void tb_shutdown(void)
-{
-  if (termw == -1) {
-    fputs("tb_shutdown() should not be called twice.", stderr);
-    abort();
-  }
-
-  bytebuffer_puts(&output_buffer, funcs[T_SHOW_CURSOR]);
-  bytebuffer_puts(&output_buffer, funcs[T_SGR0]);
-  bytebuffer_puts(&output_buffer, funcs[T_CLEAR_SCREEN]);
-  bytebuffer_puts(&output_buffer, funcs[T_EXIT_CA]);
-  bytebuffer_puts(&output_buffer, funcs[T_EXIT_KEYPAD]);
-  bytebuffer_puts(&output_buffer, funcs[T_EXIT_MOUSE]);
-  bytebuffer_flush(&output_buffer, inout);
-  tcsetattr(inout, TCSAFLUSH, &orig_tios);
-
-  shutdown_term();
-  close(inout);
-  close(winch_fds[0]);
-  close(winch_fds[1]);
-
-  cellbuf_free(&back_buffer);
-  cellbuf_free(&front_buffer);
-  bytebuffer_free(&output_buffer);
-  bytebuffer_free(&input_buffer);
-  termw = termh = -1;
-}
-
-void tb_present(void)
-{
-  int x,y,w,i;
-  struct tb_cell *back, *front;
-
-  /* invalidate cursor position */
-  lastx = LAST_COORD_INIT;
-  lasty = LAST_COORD_INIT;
-
-  if (buffer_size_change_request) {
-    update_size();
-    buffer_size_change_request = 0;
-  }
-
-  for (y = 0; y < front_buffer.height; ++y) {
-    for (x = 0; x < front_buffer.width; ) {
-      back = &CELL(&back_buffer, x, y);
-      front = &CELL(&front_buffer, x, y);
-      w = wcwidth(back->ch);
-      if (w < 1) w = 1;
-      if (memcmp(back, front, sizeof(struct tb_cell)) == 0) {
-        x += w;
-        continue;
-      }
-      memcpy(front, back, sizeof(struct tb_cell));
-      send_attr(back->fg, back->bg);
-      if (w > 1 && x >= front_buffer.width - (w - 1)) {
-        // Not enough room for wide ch, so send spaces
-        for (i = x; i < front_buffer.width; ++i) {
-          send_char(i, y, ' ');
-        }
-      } else {
-        send_char(x, y, back->ch);
-        for (i = 1; i < w; ++i) {
-          front = &CELL(&front_buffer, x + i, y);
-          front->ch = 0;
-          front->fg = back->fg;
-          front->bg = back->bg;
-        }
-      }
-      x += w;
-    }
-  }
-  if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
-    write_cursor(cursor_x, cursor_y);
-  bytebuffer_flush(&output_buffer, inout);
-}
-
-void tb_set_cursor(int cx, int cy)
-{
-  if (IS_CURSOR_HIDDEN(cursor_x, cursor_y) && !IS_CURSOR_HIDDEN(cx, cy))
-    bytebuffer_puts(&output_buffer, funcs[T_SHOW_CURSOR]);
-
-  if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y) && IS_CURSOR_HIDDEN(cx, cy))
-    bytebuffer_puts(&output_buffer, funcs[T_HIDE_CURSOR]);
-
-  cursor_x = cx;
-  cursor_y = cy;
-  if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
-    write_cursor(cursor_x, cursor_y);
-}
-
-void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
-{
-  if ((unsigned)x >= (unsigned)back_buffer.width)
-    return;
-  if ((unsigned)y >= (unsigned)back_buffer.height)
-    return;
-  struct tb_cell c = {ch, fg, bg};
-  CELL(&back_buffer, x, y) = c;
-}
-
-struct tb_cell *tb_cell_buffer()
-{
-  return back_buffer.cells;
-}
-
-int tb_poll_event(struct tb_event *event)
-{
-  return wait_fill_event(event, 0);
-}
-
-int tb_peek_event(struct tb_event *event, int timeout)
-{
-  struct timeval tv;
-  tv.tv_sec = timeout / 1000;
-  tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
-  return wait_fill_event(event, &tv);
-}
-
-int tb_width(void)
-{
-  return termw;
-}
-
-int tb_height(void)
-{
-  return termh;
-}
-
-void tb_clear(void)
-{
-  if (buffer_size_change_request) {
-    update_size();
-    buffer_size_change_request = 0;
-  }
-  cellbuf_clear(&back_buffer);
-}
-
-void tb_set_clear_attributes(uint16_t fg, uint16_t bg)
-{
-  foreground = fg;
-  background = bg;
-}
-
-/* -------------------------------------------------------- */
-
-static int convertnum(uint32_t num, char* buf) {
-  int i, l = 0;
-  int ch;
-  do {
-    buf[l++] = '0' + (num % 10);
-    num /= 10;
-  } while (num);
-  for(i = 0; i < l / 2; i++) {
-    ch = buf[i];
-    buf[i] = buf[l - 1 - i];
-    buf[l - 1 - i] = ch;
-  }
-  return l;
-}
-
-#define WRITE_LITERAL(X) bytebuffer_append(&output_buffer, (X), sizeof(X)-1)
-#define WRITE_INT(X) bytebuffer_append(&output_buffer, buf, convertnum((X), buf))
-
-static void write_cursor(int x, int y) {
-  char buf[32];
-  WRITE_LITERAL("\033[");
-  WRITE_INT(y+1);
-  WRITE_LITERAL(";");
-  WRITE_INT(x+1);
-  WRITE_LITERAL("H");
-}
-
-static void write_sgr_fg(uint16_t fg) {
-  char buf[32];
-  WRITE_LITERAL("\033[3");
-  WRITE_INT(fg-1);
-  WRITE_LITERAL("m");
-}
-
-static void write_sgr_bg(uint16_t bg) {
-  char buf[32];
-  WRITE_LITERAL("\033[4");
-  WRITE_INT(bg-1);
-  WRITE_LITERAL("m");
-}
-
-static void write_sgr(uint16_t fg, uint16_t bg) {
-  char buf[32];
-  WRITE_LITERAL("\033[3");
-  WRITE_INT(fg-1);
-  WRITE_LITERAL(";4");
-  WRITE_INT(bg-1);
-  WRITE_LITERAL("m");
-}
-
-static void cellbuf_init(struct cellbuf *buf, int width, int height)
-{
-  buf->cells = (struct tb_cell*)malloc(sizeof(struct tb_cell) * width * height);
-  assert(buf->cells);
-  buf->width = width;
-  buf->height = height;
-}
-
-static void cellbuf_resize(struct cellbuf *buf, int width, int height)
-{
-  if (buf->width == width && buf->height == height)
-    return;
-
-  int oldw = buf->width;
-  int oldh = buf->height;
-  struct tb_cell *oldcells = buf->cells;
-
-  cellbuf_init(buf, width, height);
-  cellbuf_clear(buf);
-
-  int minw = (width < oldw) ? width : oldw;
-  int minh = (height < oldh) ? height : oldh;
-  int i;
-
-  for (i = 0; i < minh; ++i) {
-    struct tb_cell *csrc = oldcells + (i * oldw);
-    struct tb_cell *cdst = buf->cells + (i * width);
-    memcpy(cdst, csrc, sizeof(struct tb_cell) * minw);
-  }
-
-  free(oldcells);
-}
-
-static void cellbuf_clear(struct cellbuf *buf)
-{
-  int i;
-  int ncells = buf->width * buf->height;
-
-  for (i = 0; i < ncells; ++i) {
-    buf->cells[i].ch = ' ';
-    buf->cells[i].fg = foreground;
-    buf->cells[i].bg = background;
-  }
-}
-
-static void cellbuf_free(struct cellbuf *buf)
-{
-  free(buf->cells);
-}
-
-static void get_term_size(int *w, int *h)
-{
-  struct winsize sz;
-  memset(&sz, 0, sizeof(sz));
-
-  ioctl(inout, TIOCGWINSZ, &sz);
-
-  if (w) *w = sz.ws_col;
-  if (h) *h = sz.ws_row;
-}
-
-static void update_term_size(void)
-{
-  struct winsize sz;
-  memset(&sz, 0, sizeof(sz));
-
-  ioctl(inout, TIOCGWINSZ, &sz);
-
-  termw = sz.ws_col;
-  termh = sz.ws_row;
-}
-
-static void send_attr(uint16_t fg, uint16_t bg)
-{
-#define LAST_ATTR_INIT 0xFFFF
-  static uint16_t lastfg = LAST_ATTR_INIT, lastbg = LAST_ATTR_INIT;
-  if (fg != lastfg || bg != lastbg) {
-    bytebuffer_puts(&output_buffer, funcs[T_SGR0]);
-
-    uint16_t fgcol = fg & 0x0F;
-    uint16_t bgcol = bg & 0x0F;
-
-    if (fg & TB_BOLD)
-      bytebuffer_puts(&output_buffer, funcs[T_BOLD]);
-    if (bg & TB_BOLD)
-      bytebuffer_puts(&output_buffer, funcs[T_BLINK]);
-    if (fg & TB_UNDERLINE)
-      bytebuffer_puts(&output_buffer, funcs[T_UNDERLINE]);
-    if ((fg & TB_REVERSE) || (bg & TB_REVERSE))
-      bytebuffer_puts(&output_buffer, funcs[T_REVERSE]);
-
-    if (fgcol != TB_DEFAULT) {
-      if (bgcol != TB_DEFAULT)
-        write_sgr(fgcol, bgcol);
-      else
-        write_sgr_fg(fgcol);
-    } else if (bgcol != TB_DEFAULT) {
-      write_sgr_bg(bgcol);
-    }
-
-    lastfg = fg;
-    lastbg = bg;
-  }
-}
-
-static void send_char(int x, int y, uint32_t c)
-{
-  char buf[7];
-  int bw = tb_utf8_unicode_to_char(buf, c);
-  buf[bw] = '\0';
-  if (x-1 != lastx || y != lasty)
-    write_cursor(x, y);
-  lastx = x; lasty = y;
-  if(!c) buf[0] = ' '; // replace 0 with whitespace
-  bytebuffer_puts(&output_buffer, buf);
-}
-
-static void send_clear(void)
-{
-  send_attr(foreground, background);
-  bytebuffer_puts(&output_buffer, funcs[T_CLEAR_SCREEN]);
-  if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
-    write_cursor(cursor_x, cursor_y);
-  bytebuffer_flush(&output_buffer, inout);
-
-  /* we need to invalidate cursor position too and these two vars are
-   * used only for simple cursor positioning optimization, cursor
-   * actually may be in the correct place, but we simply discard
-   * optimization once and it gives us simple solution for the case when
-   * cursor moved */
-  lastx = LAST_COORD_INIT;
-  lasty = LAST_COORD_INIT;
-}
-
-static void sigwinch_handler(int xxx)
-{
-  (void) xxx;
-  const int zzz = 1;
-  int yyy = write(winch_fds[1], &zzz, sizeof(int));
-  (void) yyy;
-}
-
-static void update_size(void)
-{
-  update_term_size();
-  cellbuf_resize(&back_buffer, termw, termh);
-  cellbuf_resize(&front_buffer, termw, termh);
-  cellbuf_clear(&front_buffer);
-  send_clear();
-}
-
-static int read_up_to(int n) {
-  assert(n > 0);
-  const int prevlen = input_buffer.len;
-  bytebuffer_resize(&input_buffer, prevlen + n);
-
-  int read_n = 0;
-  while (read_n <= n) {
-    ssize_t r = 0;
-    if (read_n < n) {
-      r = read(inout, input_buffer.buf + prevlen + read_n, n - read_n);
-    }
-#ifdef __CYGWIN__
-    // While linux man for tty says when VMIN == 0 && VTIME == 0, read
-    // should return 0 when there is nothing to read, cygwin's read returns
-    // -1. Not sure why and if it's correct to ignore it, but let's pretend
-    // it's zero.
-    if (r < 0) r = 0;
-#endif
-    if (r < 0) {
-      // EAGAIN / EWOULDBLOCK shouldn't occur here
-      assert(errno != EAGAIN && errno != EWOULDBLOCK);
-      return -1;
-    } else if (r > 0) {
-      read_n += r;
-    } else {
-      bytebuffer_resize(&input_buffer, prevlen + read_n);
-      return read_n;
-    }
-  }
-  assert(!"unreachable");
-  return 0;
-}
-
-static int wait_fill_event(struct tb_event *event, struct timeval *timeout)
-{
-  // ;-)
-#define ENOUGH_DATA_FOR_PARSING 64
-  fd_set events;
-  memset(event, 0, sizeof(struct tb_event));
-
-  // try to extract event from input buffer, return on success
-  event->type = TB_EVENT_KEY;
-  if (extract_event(event, &input_buffer))
-    return event->type;
-
-  // it looks like input buffer is incomplete, let's try the short path,
-  // but first make sure there is enough space
-  int n = read_up_to(ENOUGH_DATA_FOR_PARSING);
-  if (n < 0)
-    return -1;
-  if (n > 0 && extract_event(event, &input_buffer))
-    return event->type;
-
-  // n == 0, or not enough data, let's go to select
-  while (1) {
-    FD_ZERO(&events);
-    FD_SET(inout, &events);
-    FD_SET(winch_fds[0], &events);
-    int maxfd = (winch_fds[0] > inout) ? winch_fds[0] : inout;
-    int result = select(maxfd+1, &events, 0, 0, timeout);
-    if (!result)
-      return 0;
-
-    if (FD_ISSET(inout, &events)) {
-      event->type = TB_EVENT_KEY;
-      n = read_up_to(ENOUGH_DATA_FOR_PARSING);
-      if (n < 0)
-        return -1;
-
-      if (n == 0)
-        continue;
-
-      if (extract_event(event, &input_buffer))
-        return event->type;
-    }
-    if (FD_ISSET(winch_fds[0], &events)) {
-      event->type = TB_EVENT_RESIZE;
-      int zzz = 0;
-      int yyy = read(winch_fds[0], &zzz, sizeof(int));
-      (void) yyy;
-      buffer_size_change_request = 1;
-      get_term_size(&event->w, &event->h);
-      return TB_EVENT_RESIZE;
-    }
-  }
-}