Mercurial > vim
view src/libvterm/src/vterm.c @ 20462:9ad473b50471 v8.2.0785
patch 8.2.0785: libvterm code lags behind the upstream version
Commit: https://github.com/vim/vim/commit/6fc3b59ee914a0d1710c8b037a0c592e0a7c34d4
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun May 17 22:27:55 2020 +0200
patch 8.2.0785: libvterm code lags behind the upstream version
Problem: Libvterm code lags behind the upstream version.
Solution: Include revisions 734 - 740.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 17 May 2020 22:30:03 +0200 |
parents | c15dd3da4f47 |
children | 6a25d5086e1d |
line wrap: on
line source
#define DEFINE_INLINES // vim: set sw=2 : #include "vterm_internal.h" #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include "utf8.h" /////////////////// // API functions // /////////////////// static void *default_malloc(size_t size, void *allocdata UNUSED) { void *ptr = malloc(size); if(ptr) memset(ptr, 0, size); return ptr; } static void default_free(void *ptr, void *allocdata UNUSED) { free(ptr); } static VTermAllocatorFunctions default_allocator = { &default_malloc, // malloc &default_free // free }; VTerm *vterm_new(int rows, int cols) { return vterm_new_with_allocator(rows, cols, &default_allocator, NULL); } VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata) { // Need to bootstrap using the allocator function directly VTerm *vt = (*funcs->malloc)(sizeof(VTerm), allocdata); if (vt == NULL) return NULL; vt->allocator = funcs; vt->allocdata = allocdata; vt->rows = rows; vt->cols = cols; vt->parser.state = NORMAL; vt->parser.callbacks = NULL; vt->parser.cbdata = NULL; vt->parser.strbuffer_len = 500; // should be able to hold an OSC string vt->parser.strbuffer_cur = 0; vt->parser.strbuffer = vterm_allocator_malloc(vt, vt->parser.strbuffer_len); if (vt->parser.strbuffer == NULL) { vterm_allocator_free(vt, vt); return NULL; } vt->outfunc = NULL; vt->outdata = NULL; vt->outbuffer_len = 200; vt->outbuffer_cur = 0; vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len); if (vt->outbuffer == NULL) { vterm_allocator_free(vt, vt->parser.strbuffer); vterm_allocator_free(vt, vt); return NULL; } vt->tmpbuffer_len = 64; vt->tmpbuffer = vterm_allocator_malloc(vt, vt->tmpbuffer_len); return vt; } void vterm_free(VTerm *vt) { if(vt->screen) vterm_screen_free(vt->screen); if(vt->state) vterm_state_free(vt->state); vterm_allocator_free(vt, vt->parser.strbuffer); vterm_allocator_free(vt, vt->outbuffer); vterm_allocator_free(vt, vt); } INTERNAL void *vterm_allocator_malloc(VTerm *vt, size_t size) { return (*vt->allocator->malloc)(size, vt->allocdata); } /* * Free "ptr" unless it is NULL. */ INTERNAL void vterm_allocator_free(VTerm *vt, void *ptr) { if (ptr) (*vt->allocator->free)(ptr, vt->allocdata); } void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp) { if(rowsp) *rowsp = vt->rows; if(colsp) *colsp = vt->cols; } void vterm_set_size(VTerm *vt, int rows, int cols) { vt->rows = rows; vt->cols = cols; if(vt->parser.callbacks && vt->parser.callbacks->resize) (*vt->parser.callbacks->resize)(rows, cols, vt->parser.cbdata); } int vterm_get_utf8(const VTerm *vt) { return vt->mode.utf8; } void vterm_set_utf8(VTerm *vt, int is_utf8) { vt->mode.utf8 = is_utf8; } void vterm_output_set_callback(VTerm *vt, VTermOutputCallback *func, void *user) { vt->outfunc = func; vt->outdata = user; } INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len) { if(vt->outfunc) { (vt->outfunc)(bytes, len, vt->outdata); return; } if(len > vt->outbuffer_len - vt->outbuffer_cur) { DEBUG_LOG("vterm_push_output_bytes(): buffer overflow; dropping output\n"); return; } memcpy(vt->outbuffer + vt->outbuffer_cur, bytes, len); vt->outbuffer_cur += len; } INTERNAL void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args) { size_t len; #ifndef VSNPRINTF // When vsnprintf() is not available (C90) fall back to vsprintf(). char buffer[1024]; // 1Kbyte is enough for everybody, right? #endif #ifdef VSNPRINTF len = VSNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, format, args); vterm_push_output_bytes(vt, vt->tmpbuffer, len); #else len = vsprintf(buffer, format, args); vterm_push_output_bytes(vt, buffer, len); #endif } INTERNAL void vterm_push_output_sprintf(VTerm *vt, const char *format, ...) { va_list args; va_start(args, format); vterm_push_output_vsprintf(vt, format, args); va_end(args); } INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...) { size_t cur; va_list args; if(ctrl >= 0x80 && !vt->mode.ctrl8bit) cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, ESC_S "%c", ctrl - 0x40); else cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, "%c", ctrl); if(cur >= vt->tmpbuffer_len) return; vterm_push_output_bytes(vt, vt->tmpbuffer, cur); va_start(args, fmt); vterm_push_output_vsprintf(vt, fmt, args); va_end(args); } INTERNAL void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...) { size_t cur; va_list args; cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, vt->mode.ctrl8bit ? "\x90" : ESC_S "P"); // DCS if(cur >= vt->tmpbuffer_len) return; vterm_push_output_bytes(vt, vt->tmpbuffer, cur); va_start(args, fmt); vterm_push_output_vsprintf(vt, fmt, args); va_end(args); cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len, vt->mode.ctrl8bit ? "\x9C" : ESC_S "\\"); // ST if(cur >= vt->tmpbuffer_len) return; vterm_push_output_bytes(vt, vt->tmpbuffer, cur); } size_t vterm_output_get_buffer_size(const VTerm *vt) { return vt->outbuffer_len; } size_t vterm_output_get_buffer_current(const VTerm *vt) { return vt->outbuffer_cur; } size_t vterm_output_get_buffer_remaining(const VTerm *vt) { return vt->outbuffer_len - vt->outbuffer_cur; } size_t vterm_output_read(VTerm *vt, char *buffer, size_t len) { if(len > vt->outbuffer_cur) len = vt->outbuffer_cur; memcpy(buffer, vt->outbuffer, len); if(len < vt->outbuffer_cur) memmove(vt->outbuffer, vt->outbuffer + len, vt->outbuffer_cur - len); vt->outbuffer_cur -= len; return len; } VTermValueType vterm_get_attr_type(VTermAttr attr) { switch(attr) { case VTERM_ATTR_BOLD: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_UNDERLINE: return VTERM_VALUETYPE_INT; case VTERM_ATTR_ITALIC: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_BLINK: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_REVERSE: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_STRIKE: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_FONT: return VTERM_VALUETYPE_INT; case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR; case VTERM_ATTR_BACKGROUND: return VTERM_VALUETYPE_COLOR; case VTERM_N_ATTRS: return 0; } return 0; // UNREACHABLE } VTermValueType vterm_get_prop_type(VTermProp prop) { switch(prop) { case VTERM_PROP_CURSORVISIBLE: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORBLINK: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_ALTSCREEN: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_TITLE: return VTERM_VALUETYPE_STRING; case VTERM_PROP_ICONNAME: return VTERM_VALUETYPE_STRING; case VTERM_PROP_REVERSE: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORSHAPE: return VTERM_VALUETYPE_INT; case VTERM_PROP_MOUSE: return VTERM_VALUETYPE_INT; case VTERM_PROP_CURSORCOLOR: return VTERM_VALUETYPE_STRING; case VTERM_N_PROPS: return 0; } return 0; // UNREACHABLE } void vterm_scroll_rect(VTermRect rect, int downward, int rightward, int (*moverect)(VTermRect src, VTermRect dest, void *user), int (*eraserect)(VTermRect rect, int selective, void *user), void *user) { VTermRect src; VTermRect dest; if(abs(downward) >= rect.end_row - rect.start_row || abs(rightward) >= rect.end_col - rect.start_col) { // Scroll more than area; just erase the lot (*eraserect)(rect, 0, user); return; } if(rightward >= 0) { // rect: [XXX................] // src: [----------------] // dest: [----------------] dest.start_col = rect.start_col; dest.end_col = rect.end_col - rightward; src.start_col = rect.start_col + rightward; src.end_col = rect.end_col; } else { // rect: [................XXX] // src: [----------------] // dest: [----------------] int leftward = -rightward; dest.start_col = rect.start_col + leftward; dest.end_col = rect.end_col; src.start_col = rect.start_col; src.end_col = rect.end_col - leftward; } if(downward >= 0) { dest.start_row = rect.start_row; dest.end_row = rect.end_row - downward; src.start_row = rect.start_row + downward; src.end_row = rect.end_row; } else { int upward = -downward; dest.start_row = rect.start_row + upward; dest.end_row = rect.end_row; src.start_row = rect.start_row; src.end_row = rect.end_row - upward; } if(moverect) (*moverect)(dest, src, user); if(downward > 0) rect.start_row = rect.end_row - downward; else if(downward < 0) rect.end_row = rect.start_row - downward; if(rightward > 0) rect.start_col = rect.end_col - rightward; else if(rightward < 0) rect.end_col = rect.start_col - rightward; (*eraserect)(rect, 0, user); } void vterm_copy_cells(VTermRect dest, VTermRect src, void (*copycell)(VTermPos dest, VTermPos src, void *user), void *user) { int downward = src.start_row - dest.start_row; int rightward = src.start_col - dest.start_col; int init_row, test_row, init_col, test_col; int inc_row, inc_col; VTermPos pos; if(downward < 0) { init_row = dest.end_row - 1; test_row = dest.start_row - 1; inc_row = -1; } else { // downward >= 0 init_row = dest.start_row; test_row = dest.end_row; inc_row = +1; } if(rightward < 0) { init_col = dest.end_col - 1; test_col = dest.start_col - 1; inc_col = -1; } else { // rightward >= 0 init_col = dest.start_col; test_col = dest.end_col; inc_col = +1; } for(pos.row = init_row; pos.row != test_row; pos.row += inc_row) for(pos.col = init_col; pos.col != test_col; pos.col += inc_col) { VTermPos srcpos; srcpos.row = pos.row + downward; srcpos.col = pos.col + rightward; (*copycell)(pos, srcpos, user); } } void vterm_check_version(int major, int minor) { if(major != VTERM_VERSION_MAJOR) { fprintf(stderr, "libvterm major version mismatch; %d (wants) != %d (library)\n", major, VTERM_VERSION_MAJOR); exit(1); } if(minor > VTERM_VERSION_MINOR) { fprintf(stderr, "libvterm minor version mismatch; %d (wants) > %d (library)\n", minor, VTERM_VERSION_MINOR); exit(1); } // Happy }