1dae0a4e0SAdrien Destugues - PulkoMandy#include "vterm_internal.h"
2dae0a4e0SAdrien Destugues - PulkoMandy
3dae0a4e0SAdrien Destugues - PulkoMandy#include <stdio.h>
4dae0a4e0SAdrien Destugues - PulkoMandy#include <string.h>
5dae0a4e0SAdrien Destugues - PulkoMandy
6dae0a4e0SAdrien Destugues - PulkoMandy#define strneq(a,b,n) (strncmp(a,b,n)==0)
7dae0a4e0SAdrien Destugues - PulkoMandy
8dae0a4e0SAdrien Destugues - PulkoMandy#include "utf8.h"
9dae0a4e0SAdrien Destugues - PulkoMandy
101ec25517SAdrien Destugues#if defined(DEBUG) && DEBUG > 1
11dae0a4e0SAdrien Destugues - PulkoMandy# define DEBUG_GLYPH_COMBINE
12dae0a4e0SAdrien Destugues - PulkoMandy#endif
13dae0a4e0SAdrien Destugues - PulkoMandy
141ec25517SAdrien Destugues#define MOUSE_WANT_CLICK 0x01
151ec25517SAdrien Destugues#define MOUSE_WANT_DRAG  0x02
161ec25517SAdrien Destugues#define MOUSE_WANT_MOVE  0x04
17dae0a4e0SAdrien Destugues - PulkoMandy
18dae0a4e0SAdrien Destugues - PulkoMandy/* Some convenient wrappers to make callback functions easier */
19dae0a4e0SAdrien Destugues - PulkoMandy
20dae0a4e0SAdrien Destugues - PulkoMandystatic void putglyph(VTermState *state, const uint32_t chars[], int width, VTermPos pos)
21dae0a4e0SAdrien Destugues - PulkoMandy{
221ec25517SAdrien Destugues  VTermGlyphInfo info = {
231ec25517SAdrien Destugues    .chars = chars,
241ec25517SAdrien Destugues    .width = width,
251ec25517SAdrien Destugues    .protected_cell = state->protected_cell,
261ec25517SAdrien Destugues    .dwl = state->lineinfo[pos.row].doublewidth,
271ec25517SAdrien Destugues    .dhl = state->lineinfo[pos.row].doubleheight,
281ec25517SAdrien Destugues  };
291ec25517SAdrien Destugues
30dae0a4e0SAdrien Destugues - PulkoMandy  if(state->callbacks && state->callbacks->putglyph)
311ec25517SAdrien Destugues    if((*state->callbacks->putglyph)(&info, pos, state->cbdata))
32dae0a4e0SAdrien Destugues - PulkoMandy      return;
33dae0a4e0SAdrien Destugues - PulkoMandy
34dae0a4e0SAdrien Destugues - PulkoMandy  fprintf(stderr, "libvterm: Unhandled putglyph U+%04x at (%d,%d)\n", chars[0], pos.col, pos.row);
35dae0a4e0SAdrien Destugues - PulkoMandy}
36dae0a4e0SAdrien Destugues - PulkoMandy
37dae0a4e0SAdrien Destugues - PulkoMandystatic void updatecursor(VTermState *state, VTermPos *oldpos, int cancel_phantom)
38dae0a4e0SAdrien Destugues - PulkoMandy{
39dae0a4e0SAdrien Destugues - PulkoMandy  if(state->pos.col == oldpos->col && state->pos.row == oldpos->row)
40dae0a4e0SAdrien Destugues - PulkoMandy    return;
41dae0a4e0SAdrien Destugues - PulkoMandy
42dae0a4e0SAdrien Destugues - PulkoMandy  if(cancel_phantom)
43dae0a4e0SAdrien Destugues - PulkoMandy    state->at_phantom = 0;
44dae0a4e0SAdrien Destugues - PulkoMandy
45dae0a4e0SAdrien Destugues - PulkoMandy  if(state->callbacks && state->callbacks->movecursor)
46dae0a4e0SAdrien Destugues - PulkoMandy    if((*state->callbacks->movecursor)(state->pos, *oldpos, state->mode.cursor_visible, state->cbdata))
47dae0a4e0SAdrien Destugues - PulkoMandy      return;
48dae0a4e0SAdrien Destugues - PulkoMandy}
49dae0a4e0SAdrien Destugues - PulkoMandy
501ec25517SAdrien Destuguesstatic void erase(VTermState *state, VTermRect rect, int selective)
51dae0a4e0SAdrien Destugues - PulkoMandy{
52dae0a4e0SAdrien Destugues - PulkoMandy  if(state->callbacks && state->callbacks->erase)
531ec25517SAdrien Destugues    if((*state->callbacks->erase)(rect, selective, state->cbdata))
54dae0a4e0SAdrien Destugues - PulkoMandy      return;
55dae0a4e0SAdrien Destugues - PulkoMandy}
56dae0a4e0SAdrien Destugues - PulkoMandy
57dae0a4e0SAdrien Destugues - PulkoMandystatic VTermState *vterm_state_new(VTerm *vt)
58dae0a4e0SAdrien Destugues - PulkoMandy{
59dae0a4e0SAdrien Destugues - PulkoMandy  VTermState *state = vterm_allocator_malloc(vt, sizeof(VTermState));
60dae0a4e0SAdrien Destugues - PulkoMandy
61dae0a4e0SAdrien Destugues - PulkoMandy  state->vt = vt;
62dae0a4e0SAdrien Destugues - PulkoMandy
63dae0a4e0SAdrien Destugues - PulkoMandy  state->rows = vt->rows;
64dae0a4e0SAdrien Destugues - PulkoMandy  state->cols = vt->cols;
65dae0a4e0SAdrien Destugues - PulkoMandy
661ec25517SAdrien Destugues  vterm_state_newpen(state);
67dae0a4e0SAdrien Destugues - PulkoMandy
68dae0a4e0SAdrien Destugues - PulkoMandy  state->bold_is_highbright = 0;
69dae0a4e0SAdrien Destugues - PulkoMandy
70dae0a4e0SAdrien Destugues - PulkoMandy  return state;
71dae0a4e0SAdrien Destugues - PulkoMandy}
72dae0a4e0SAdrien Destugues - PulkoMandy
731ec25517SAdrien DestuguesINTERNAL void vterm_state_free(VTermState *state)
74dae0a4e0SAdrien Destugues - PulkoMandy{
751ec25517SAdrien Destugues  vterm_allocator_free(state->vt, state->tabstops);
761ec25517SAdrien Destugues  vterm_allocator_free(state->vt, state->lineinfo);
77dae0a4e0SAdrien Destugues - PulkoMandy  vterm_allocator_free(state->vt, state->combine_chars);
78dae0a4e0SAdrien Destugues - PulkoMandy  vterm_allocator_free(state->vt, state);
79dae0a4e0SAdrien Destugues - PulkoMandy}
80dae0a4e0SAdrien Destugues - PulkoMandy
81dae0a4e0SAdrien Destugues - PulkoMandystatic void scroll(VTermState *state, VTermRect rect, int downward, int rightward)
82dae0a4e0SAdrien Destugues - PulkoMandy{
83dae0a4e0SAdrien Destugues - PulkoMandy  if(!downward && !rightward)
84dae0a4e0SAdrien Destugues - PulkoMandy    return;
85dae0a4e0SAdrien Destugues - PulkoMandy
861ec25517SAdrien Destugues  // Update lineinfo if full line
871ec25517SAdrien Destugues  if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
881ec25517SAdrien Destugues    int height = rect.end_row - rect.start_row - abs(downward);
891ec25517SAdrien Destugues
901ec25517SAdrien Destugues    if(downward > 0)
911ec25517SAdrien Destugues      memmove(state->lineinfo + rect.start_row,
921ec25517SAdrien Destugues              state->lineinfo + rect.start_row + downward,
931ec25517SAdrien Destugues              height * sizeof(state->lineinfo[0]));
941ec25517SAdrien Destugues    else
951ec25517SAdrien Destugues      memmove(state->lineinfo + rect.start_row - downward,
961ec25517SAdrien Destugues              state->lineinfo + rect.start_row,
971ec25517SAdrien Destugues              height * sizeof(state->lineinfo[0]));
981ec25517SAdrien Destugues  }
991ec25517SAdrien Destugues
100dae0a4e0SAdrien Destugues - PulkoMandy  if(state->callbacks && state->callbacks->scrollrect)
101dae0a4e0SAdrien Destugues - PulkoMandy    if((*state->callbacks->scrollrect)(rect, downward, rightward, state->cbdata))
102dae0a4e0SAdrien Destugues - PulkoMandy      return;
103dae0a4e0SAdrien Destugues - PulkoMandy
104dae0a4e0SAdrien Destugues - PulkoMandy  if(state->callbacks)
105dae0a4e0SAdrien Destugues - PulkoMandy    vterm_scroll_rect(rect, downward, rightward,
106dae0a4e0SAdrien Destugues - PulkoMandy        state->callbacks->moverect, state->callbacks->erase, state->cbdata);
107dae0a4e0SAdrien Destugues - PulkoMandy}
108dae0a4e0SAdrien Destugues - PulkoMandy
109dae0a4e0SAdrien Destugues - PulkoMandystatic void linefeed(VTermState *state)
110dae0a4e0SAdrien Destugues - PulkoMandy{
1111ec25517SAdrien Destugues  if(state->pos.row == SCROLLREGION_BOTTOM(state) - 1) {
112dae0a4e0SAdrien Destugues - PulkoMandy    VTermRect rect = {
1131ec25517SAdrien Destugues      .start_row = state->scrollregion_top,
1141ec25517SAdrien Destugues      .end_row   = SCROLLREGION_BOTTOM(state),
1151ec25517SAdrien Destugues      .start_col = SCROLLREGION_LEFT(state),
1161ec25517SAdrien Destugues      .end_col   = SCROLLREGION_RIGHT(state),
117dae0a4e0SAdrien Destugues - PulkoMandy    };
118dae0a4e0SAdrien Destugues - PulkoMandy
119dae0a4e0SAdrien Destugues - PulkoMandy    scroll(state, rect, 1, 0);
120dae0a4e0SAdrien Destugues - PulkoMandy  }
121dae0a4e0SAdrien Destugues - PulkoMandy  else if(state->pos.row < state->rows-1)
122dae0a4e0SAdrien Destugues - PulkoMandy    state->pos.row++;
123dae0a4e0SAdrien Destugues - PulkoMandy}
124dae0a4e0SAdrien Destugues - PulkoMandy
125dae0a4e0SAdrien Destugues - PulkoMandystatic void grow_combine_buffer(VTermState *state)
126dae0a4e0SAdrien Destugues - PulkoMandy{
127dae0a4e0SAdrien Destugues - PulkoMandy  size_t    new_size = state->combine_chars_size * 2;
128dae0a4e0SAdrien Destugues - PulkoMandy  uint32_t *new_chars = vterm_allocator_malloc(state->vt, new_size * sizeof(new_chars[0]));
129dae0a4e0SAdrien Destugues - PulkoMandy
130dae0a4e0SAdrien Destugues - PulkoMandy  memcpy(new_chars, state->combine_chars, state->combine_chars_size * sizeof(new_chars[0]));
131dae0a4e0SAdrien Destugues - PulkoMandy
132dae0a4e0SAdrien Destugues - PulkoMandy  vterm_allocator_free(state->vt, state->combine_chars);
1331ec25517SAdrien Destugues
134dae0a4e0SAdrien Destugues - PulkoMandy  state->combine_chars = new_chars;
1351ec25517SAdrien Destugues  state->combine_chars_size = new_size;
136dae0a4e0SAdrien Destugues - PulkoMandy}
137dae0a4e0SAdrien Destugues - PulkoMandy
138dae0a4e0SAdrien Destugues - PulkoMandystatic void set_col_tabstop(VTermState *state, int col)
139dae0a4e0SAdrien Destugues - PulkoMandy{
140dae0a4e0SAdrien Destugues - PulkoMandy  unsigned char mask = 1 << (col & 7);
141dae0a4e0SAdrien Destugues - PulkoMandy  state->tabstops[col >> 3] |= mask;
142dae0a4e0SAdrien Destugues - PulkoMandy}
143dae0a4e0SAdrien Destugues - PulkoMandy
144dae0a4e0SAdrien Destugues - PulkoMandystatic void clear_col_tabstop(VTermState *state, int col)
145dae0a4e0SAdrien Destugues - PulkoMandy{
146dae0a4e0SAdrien Destugues - PulkoMandy  unsigned char mask = 1 << (col & 7);
147dae0a4e0SAdrien Destugues - PulkoMandy  state->tabstops[col >> 3] &= ~mask;
148dae0a4e0SAdrien Destugues - PulkoMandy}
149dae0a4e0SAdrien Destugues - PulkoMandy
150dae0a4e0SAdrien Destugues - PulkoMandystatic int is_col_tabstop(VTermState *state, int col)
151dae0a4e0SAdrien Destugues - PulkoMandy{
152dae0a4e0SAdrien Destugues - PulkoMandy  unsigned char mask = 1 << (col & 7);
153dae0a4e0SAdrien Destugues - PulkoMandy  return state->tabstops[col >> 3] & mask;
154dae0a4e0SAdrien Destugues - PulkoMandy}
155dae0a4e0SAdrien Destugues - PulkoMandy
156dae0a4e0SAdrien Destugues - PulkoMandystatic void tab(VTermState *state, int count, int direction)
157dae0a4e0SAdrien Destugues - PulkoMandy{
158dae0a4e0SAdrien Destugues - PulkoMandy  while(count--)
1591ec25517SAdrien Destugues    while(state->pos.col >= 0 && state->pos.col < THISROWWIDTH(state)-1) {
160dae0a4e0SAdrien Destugues - PulkoMandy      state->pos.col += direction;
161dae0a4e0SAdrien Destugues - PulkoMandy
162dae0a4e0SAdrien Destugues - PulkoMandy      if(is_col_tabstop(state, state->pos.col))
163dae0a4e0SAdrien Destugues - PulkoMandy        break;
164dae0a4e0SAdrien Destugues - PulkoMandy    }
165dae0a4e0SAdrien Destugues - PulkoMandy}
166dae0a4e0SAdrien Destugues - PulkoMandy
1671ec25517SAdrien Destugues#define NO_FORCE 0
1681ec25517SAdrien Destugues#define FORCE    1
1691ec25517SAdrien Destugues
1701ec25517SAdrien Destugues#define DWL_OFF 0
1711ec25517SAdrien Destugues#define DWL_ON  1
1721ec25517SAdrien Destugues
1731ec25517SAdrien Destugues#define DHL_OFF    0
1741ec25517SAdrien Destugues#define DHL_TOP    1
1751ec25517SAdrien Destugues#define DHL_BOTTOM 2
1761ec25517SAdrien Destugues
1771ec25517SAdrien Destuguesstatic void set_lineinfo(VTermState *state, int row, int force, int dwl, int dhl)
1781ec25517SAdrien Destugues{
1791ec25517SAdrien Destugues  VTermLineInfo info = state->lineinfo[row];
1801ec25517SAdrien Destugues
1811ec25517SAdrien Destugues  if(dwl == DWL_OFF)
1821ec25517SAdrien Destugues    info.doublewidth = DWL_OFF;
1831ec25517SAdrien Destugues  else if(dwl == DWL_ON)
1841ec25517SAdrien Destugues    info.doublewidth = DWL_ON;
1851ec25517SAdrien Destugues  // else -1 to ignore
1861ec25517SAdrien Destugues
1871ec25517SAdrien Destugues  if(dhl == DHL_OFF)
1881ec25517SAdrien Destugues    info.doubleheight = DHL_OFF;
1891ec25517SAdrien Destugues  else if(dhl == DHL_TOP)
1901ec25517SAdrien Destugues    info.doubleheight = DHL_TOP;
1911ec25517SAdrien Destugues  else if(dhl == DHL_BOTTOM)
1921ec25517SAdrien Destugues    info.doubleheight = DHL_BOTTOM;
1931ec25517SAdrien Destugues
1941ec25517SAdrien Destugues  if((state->callbacks &&
1951ec25517SAdrien Destugues      state->callbacks->setlineinfo &&
1961ec25517SAdrien Destugues      (*state->callbacks->setlineinfo)(row, &info, state->lineinfo + row, state->cbdata))
1971ec25517SAdrien Destugues      || force)
1981ec25517SAdrien Destugues    state->lineinfo[row] = info;
1991ec25517SAdrien Destugues}
2001ec25517SAdrien Destugues
201dae0a4e0SAdrien Destugues - PulkoMandystatic int on_text(const char bytes[], size_t len, void *user)
202dae0a4e0SAdrien Destugues - PulkoMandy{
203dae0a4e0SAdrien Destugues - PulkoMandy  VTermState *state = user;
204dae0a4e0SAdrien Destugues - PulkoMandy
205dae0a4e0SAdrien Destugues - PulkoMandy  VTermPos oldpos = state->pos;
206dae0a4e0SAdrien Destugues - PulkoMandy
207dae0a4e0SAdrien Destugues - PulkoMandy  // We'll have at most len codepoints
208dae0a4e0SAdrien Destugues - PulkoMandy  uint32_t codepoints[len];
209dae0a4e0SAdrien Destugues - PulkoMandy  int npoints = 0;
210dae0a4e0SAdrien Destugues - PulkoMandy  size_t eaten = 0;
2116a545a8eSAdrien Destugues  int i = 0;
212dae0a4e0SAdrien Destugues - PulkoMandy
213dae0a4e0SAdrien Destugues - PulkoMandy  VTermEncodingInstance *encoding =
2141ec25517SAdrien Destugues    state->gsingle_set     ? &state->encoding[state->gsingle_set] :
215dae0a4e0SAdrien Destugues - PulkoMandy    !(bytes[eaten] & 0x80) ? &state->encoding[state->gl_set] :
2161ec25517SAdrien Destugues    state->vt->mode.utf8   ? &state->encoding_utf8 :
217dae0a4e0SAdrien Destugues - PulkoMandy                             &state->encoding[state->gr_set];
218dae0a4e0SAdrien Destugues - PulkoMandy
219dae0a4e0SAdrien Destugues - PulkoMandy  (*encoding->enc->decode)(encoding->enc, encoding->data,
2201ec25517SAdrien Destugues      codepoints, &npoints, state->gsingle_set ? 1 : len,
2211ec25517SAdrien Destugues      bytes, &eaten, len);
2221ec25517SAdrien Destugues
2231ec25517SAdrien Destugues  if(state->gsingle_set && npoints)
2241ec25517SAdrien Destugues    state->gsingle_set = 0;
2251ec25517SAdrien Destugues
226dae0a4e0SAdrien Destugues - PulkoMandy  /* This is a combining char. that needs to be merged with the previous
227dae0a4e0SAdrien Destugues - PulkoMandy   * glyph output */
228dae0a4e0SAdrien Destugues - PulkoMandy  if(vterm_unicode_is_combining(codepoints[i])) {
229dae0a4e0SAdrien Destugues - PulkoMandy    /* See if the cursor has moved since */
230dae0a4e0SAdrien Destugues - PulkoMandy    if(state->pos.row == state->combine_pos.row && state->pos.col == state->combine_pos.col + state->combine_width) {
231f3814567SAdrien Destugues      unsigned saved_i = 0;
232dae0a4e0SAdrien Destugues - PulkoMandy#ifdef DEBUG_GLYPH_COMBINE
233dae0a4e0SAdrien Destugues - PulkoMandy      int printpos;
234dae0a4e0SAdrien Destugues - PulkoMandy      printf("DEBUG: COMBINING SPLIT GLYPH of chars {");
235dae0a4e0SAdrien Destugues - PulkoMandy      for(printpos = 0; state->combine_chars[printpos]; printpos++)
236dae0a4e0SAdrien Destugues - PulkoMandy        printf("U+%04x ", state->combine_chars[printpos]);
237dae0a4e0SAdrien Destugues - PulkoMandy      printf("} + {");
238dae0a4e0SAdrien Destugues - PulkoMandy#endif
239dae0a4e0SAdrien Destugues - PulkoMandy
240dae0a4e0SAdrien Destugues - PulkoMandy      /* Find where we need to append these combining chars */
241dae0a4e0SAdrien Destugues - PulkoMandy      while(state->combine_chars[saved_i])
242dae0a4e0SAdrien Destugues - PulkoMandy        saved_i++;
243dae0a4e0SAdrien Destugues - PulkoMandy
244dae0a4e0SAdrien Destugues - PulkoMandy      /* Add extra ones */
245dae0a4e0SAdrien Destugues - PulkoMandy      while(i < npoints && vterm_unicode_is_combining(codepoints[i])) {
246dae0a4e0SAdrien Destugues - PulkoMandy        if(saved_i >= state->combine_chars_size)
247dae0a4e0SAdrien Destugues - PulkoMandy          grow_combine_buffer(state);
248dae0a4e0SAdrien Destugues - PulkoMandy        state->combine_chars[saved_i++] = codepoints[i++];
249dae0a4e0SAdrien Destugues - PulkoMandy      }
250dae0a4e0SAdrien Destugues - PulkoMandy      if(saved_i >= state->combine_chars_size)
251dae0a4e0SAdrien Destugues - PulkoMandy        grow_combine_buffer(state);
252dae0a4e0SAdrien Destugues - PulkoMandy      state->combine_chars[saved_i] = 0;
253dae0a4e0SAdrien Destugues - PulkoMandy
254dae0a4e0SAdrien Destugues - PulkoMandy#ifdef DEBUG_GLYPH_COMBINE
255dae0a4e0SAdrien Destugues - PulkoMandy      for(; state->combine_chars[printpos]; printpos++)
256dae0a4e0SAdrien Destugues - PulkoMandy        printf("U+%04x ", state->combine_chars[printpos]);
257dae0a4e0SAdrien Destugues - PulkoMandy      printf("}\n");
258dae0a4e0SAdrien Destugues - PulkoMandy#endif
259dae0a4e0SAdrien Destugues - PulkoMandy
260dae0a4e0SAdrien Destugues - PulkoMandy      /* Now render it */
261dae0a4e0SAdrien Destugues - PulkoMandy      putglyph(state, state->combine_chars, state->combine_width, state->combine_pos);
262dae0a4e0SAdrien Destugues - PulkoMandy    }
263dae0a4e0SAdrien Destugues - PulkoMandy    else {
264dae0a4e0SAdrien Destugues - PulkoMandy      fprintf(stderr, "libvterm: TODO: Skip over split char+combining\n");
265dae0a4e0SAdrien Destugues - PulkoMandy    }
266dae0a4e0SAdrien Destugues - PulkoMandy  }
267dae0a4e0SAdrien Destugues - PulkoMandy
268dae0a4e0SAdrien Destugues - PulkoMandy  for(; i < npoints; i++) {
269dae0a4e0SAdrien Destugues - PulkoMandy    // Try to find combining characters following this
270dae0a4e0SAdrien Destugues - PulkoMandy    int glyph_starts = i;
271dae0a4e0SAdrien Destugues - PulkoMandy    int glyph_ends;
2726a545a8eSAdrien Destugues    int width = 0;
2736a545a8eSAdrien Destugues	uint32_t* chars;
2746a545a8eSAdrien Destugues
275dae0a4e0SAdrien Destugues - PulkoMandy    for(glyph_ends = i + 1; glyph_ends < npoints; glyph_ends++)
276dae0a4e0SAdrien Destugues - PulkoMandy      if(!vterm_unicode_is_combining(codepoints[glyph_ends]))
277dae0a4e0SAdrien Destugues - PulkoMandy        break;
278dae0a4e0SAdrien Destugues - PulkoMandy
2796a545a8eSAdrien Destugues    chars = alloca(glyph_ends - glyph_starts + 1);
280dae0a4e0SAdrien Destugues - PulkoMandy
281dae0a4e0SAdrien Destugues - PulkoMandy    for( ; i < glyph_ends; i++) {
282dae0a4e0SAdrien Destugues - PulkoMandy      chars[i - glyph_starts] = codepoints[i];
283dae0a4e0SAdrien Destugues - PulkoMandy      width += vterm_unicode_width(codepoints[i]);
284dae0a4e0SAdrien Destugues - PulkoMandy    }
285dae0a4e0SAdrien Destugues - PulkoMandy
286dae0a4e0SAdrien Destugues - PulkoMandy    chars[glyph_ends - glyph_starts] = 0;
287dae0a4e0SAdrien Destugues - PulkoMandy    i--;
288dae0a4e0SAdrien Destugues - PulkoMandy
289dae0a4e0SAdrien Destugues - PulkoMandy#ifdef DEBUG_GLYPH_COMBINE
290f3814567SAdrien Destugues	{
291dae0a4e0SAdrien Destugues - PulkoMandy    int printpos;
292dae0a4e0SAdrien Destugues - PulkoMandy    printf("DEBUG: COMBINED GLYPH of %d chars {", glyph_ends - glyph_starts);
293dae0a4e0SAdrien Destugues - PulkoMandy    for(printpos = 0; printpos < glyph_ends - glyph_starts; printpos++)
294dae0a4e0SAdrien Destugues - PulkoMandy      printf("U+%04x ", chars[printpos]);
295dae0a4e0SAdrien Destugues - PulkoMandy    printf("}, onscreen width %d\n", width);
296f3814567SAdrien Destugues	}
297dae0a4e0SAdrien Destugues - PulkoMandy#endif
298dae0a4e0SAdrien Destugues - PulkoMandy
2991ec25517SAdrien Destugues    if(state->at_phantom || state->pos.col + width > THISROWWIDTH(state)) {
300dae0a4e0SAdrien Destugues - PulkoMandy      linefeed(state);
301dae0a4e0SAdrien Destugues - PulkoMandy      state->pos.col = 0;
302dae0a4e0SAdrien Destugues - PulkoMandy      state->at_phantom = 0;
303dae0a4e0SAdrien Destugues - PulkoMandy    }
304dae0a4e0SAdrien Destugues - PulkoMandy
305dae0a4e0SAdrien Destugues - PulkoMandy    if(state->mode.insert) {
306dae0a4e0SAdrien Destugues - PulkoMandy      /* TODO: This will be a little inefficient for large bodies of text, as
307dae0a4e0SAdrien Destugues - PulkoMandy       * it'll have to 'ICH' effectively before every glyph. We should scan
308dae0a4e0SAdrien Destugues - PulkoMandy       * ahead and ICH as many times as required
309dae0a4e0SAdrien Destugues - PulkoMandy       */
310dae0a4e0SAdrien Destugues - PulkoMandy      VTermRect rect = {
311dae0a4e0SAdrien Destugues - PulkoMandy        .start_row = state->pos.row,
312dae0a4e0SAdrien Destugues - PulkoMandy        .end_row   = state->pos.row + 1,
313dae0a4e0SAdrien Destugues - PulkoMandy        .start_col = state->pos.col,
3141ec25517SAdrien Destugues        .end_col   = THISROWWIDTH(state),
315dae0a4e0SAdrien Destugues - PulkoMandy      };
316dae0a4e0SAdrien Destugues - PulkoMandy      scroll(state, rect, 0, -1);
317dae0a4e0SAdrien Destugues - PulkoMandy    }
3181ec25517SAdrien Destugues
319dae0a4e0SAdrien Destugues - PulkoMandy    putglyph(state, chars, width, state->pos);
320dae0a4e0SAdrien Destugues - PulkoMandy
321dae0a4e0SAdrien Destugues - PulkoMandy    if(i == npoints - 1) {
322dae0a4e0SAdrien Destugues - PulkoMandy      /* End of the buffer. Save the chars in case we have to combine with
323dae0a4e0SAdrien Destugues - PulkoMandy       * more on the next call */
3246a545a8eSAdrien Destugues      unsigned save_i;
325dae0a4e0SAdrien Destugues - PulkoMandy      for(save_i = 0; chars[save_i]; save_i++) {
326dae0a4e0SAdrien Destugues - PulkoMandy        if(save_i >= state->combine_chars_size)
327dae0a4e0SAdrien Destugues - PulkoMandy          grow_combine_buffer(state);
328dae0a4e0SAdrien Destugues - PulkoMandy        state->combine_chars[save_i] = chars[save_i];
329dae0a4e0SAdrien Destugues - PulkoMandy      }
330dae0a4e0SAdrien Destugues - PulkoMandy      if(save_i >= state->combine_chars_size)
331dae0a4e0SAdrien Destugues - PulkoMandy        grow_combine_buffer(state);
332dae0a4e0SAdrien Destugues - PulkoMandy      state->combine_chars[save_i] = 0;
333dae0a4e0SAdrien Destugues - PulkoMandy      state->combine_width = width;
334dae0a4e0SAdrien Destugues - PulkoMandy      state->combine_pos = state->pos;
335dae0a4e0SAdrien Destugues - PulkoMandy    }
336dae0a4e0SAdrien Destugues - PulkoMandy
3371ec25517SAdrien Destugues    if(state->pos.col + width >= THISROWWIDTH(state)) {
338dae0a4e0SAdrien Destugues - PulkoMandy      if(state->mode.autowrap)
339dae0a4e0SAdrien Destugues - PulkoMandy        state->at_phantom = 1;
340dae0a4e0SAdrien Destugues - PulkoMandy    }
341dae0a4e0SAdrien Destugues - PulkoMandy    else {
342dae0a4e0SAdrien Destugues - PulkoMandy      state->pos.col += width;
343dae0a4e0SAdrien Destugues - PulkoMandy    }
344dae0a4e0SAdrien Destugues - PulkoMandy  }
345dae0a4e0SAdrien Destugues - PulkoMandy
346dae0a4e0SAdrien Destugues - PulkoMandy  updatecursor(state, &oldpos, 0);
347dae0a4e0SAdrien Destugues - PulkoMandy
348dae0a4e0SAdrien Destugues - PulkoMandy  return eaten;
349dae0a4e0SAdrien Destugues - PulkoMandy}
350dae0a4e0SAdrien Destugues - PulkoMandy
351dae0a4e0SAdrien Destugues - PulkoMandystatic int on_control(unsigned char control, void *user)
352dae0a4e0SAdrien Destugues - PulkoMandy{
353dae0a4e0SAdrien Destugues - PulkoMandy  VTermState *state = user;
354dae0a4e0SAdrien Destugues - PulkoMandy
355dae0a4e0SAdrien Destugues - PulkoMandy  VTermPos oldpos = state->pos;
356dae0a4e0SAdrien Destugues - PulkoMandy
357dae0a4e0SAdrien Destugues - PulkoMandy  switch(control) {
358dae0a4e0SAdrien Destugues - PulkoMandy  case 0x07: // BEL - ECMA-48 8.3.3
359dae0a4e0SAdrien Destugues - PulkoMandy    if(state->callbacks && state->callbacks->bell)
360dae0a4e0SAdrien Destugues - PulkoMandy      (*state->callbacks->bell)(state->cbdata);
361dae0a4e0SAdrien Destugues - PulkoMandy    break;
362dae0a4e0SAdrien Destugues - PulkoMandy
363dae0a4e0SAdrien Destugues - PulkoMandy  case 0x08: // BS - ECMA-48 8.3.5
364dae0a4e0SAdrien Destugues - PulkoMandy    if(state->pos.col > 0)
365dae0a4e0SAdrien Destugues - PulkoMandy      state->pos.col--;
366dae0a4e0SAdrien Destugues - PulkoMandy    break;
367dae0a4e0SAdrien Destugues - PulkoMandy
368dae0a4e0SAdrien Destugues - PulkoMandy  case 0x09: // HT - ECMA-48 8.3.60
369dae0a4e0SAdrien Destugues - PulkoMandy    tab(state, 1, +1);
370dae0a4e0SAdrien Destugues - PulkoMandy    break;
371dae0a4e0SAdrien Destugues - PulkoMandy
372dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0a: // LF - ECMA-48 8.3.74
373dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0b: // VT
374dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0c: // FF
375dae0a4e0SAdrien Destugues - PulkoMandy    linefeed(state);
376dae0a4e0SAdrien Destugues - PulkoMandy    if(state->mode.newline)
377dae0a4e0SAdrien Destugues - PulkoMandy      state->pos.col = 0;
378dae0a4e0SAdrien Destugues - PulkoMandy    break;
379dae0a4e0SAdrien Destugues - PulkoMandy
380dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0d: // CR - ECMA-48 8.3.15
381dae0a4e0SAdrien Destugues - PulkoMandy    state->pos.col = 0;
382dae0a4e0SAdrien Destugues - PulkoMandy    break;
383dae0a4e0SAdrien Destugues - PulkoMandy
384dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0e: // LS1 - ECMA-48 8.3.76
385dae0a4e0SAdrien Destugues - PulkoMandy    state->gl_set = 1;
386dae0a4e0SAdrien Destugues - PulkoMandy    break;
387dae0a4e0SAdrien Destugues - PulkoMandy
388dae0a4e0SAdrien Destugues - PulkoMandy  case 0x0f: // LS0 - ECMA-48 8.3.75
389dae0a4e0SAdrien Destugues - PulkoMandy    state->gl_set = 0;
390dae0a4e0SAdrien Destugues - PulkoMandy    break;
391dae0a4e0SAdrien Destugues - PulkoMandy
392dae0a4e0SAdrien Destugues - PulkoMandy  case 0x84: // IND - DEPRECATED but implemented for completeness
393dae0a4e0SAdrien Destugues - PulkoMandy    linefeed(state);
394dae0a4e0SAdrien Destugues - PulkoMandy    break;
395dae0a4e0SAdrien Destugues - PulkoMandy
396dae0a4e0SAdrien Destugues - PulkoMandy  case 0x85: // NEL - ECMA-48 8.3.86
397dae0a4e0SAdrien Destugues - PulkoMandy    linefeed(state);
398dae0a4e0SAdrien Destugues - PulkoMandy    state->pos.col = 0;
399dae0a4e0SAdrien Destugues - PulkoMandy    break;
400dae0a4e0SAdrien Destugues - PulkoMandy
401dae0a4e0SAdrien Destugues - PulkoMandy  case 0x88: // HTS - ECMA-48 8.3.62
402dae0a4e0SAdrien Destugues - PulkoMandy    set_col_tabstop(state, state->pos.col);
403dae0a4e0SAdrien Destugues - PulkoMandy    break;
404dae0a4e0SAdrien Destugues - PulkoMandy
405dae0a4e0SAdrien Destugues - PulkoMandy  case 0x8d: // RI - ECMA-48 8.3.104
4061ec25517SAdrien Destugues    if(state->pos.row == state->scrollregion_top) {
407dae0a4e0SAdrien Destugues - PulkoMandy      VTermRect rect = {
4081ec25517SAdrien Destugues        .start_row = state->scrollregion_top,
4091ec25517SAdrien Destugues        .end_row   = SCROLLREGION_BOTTOM(state),
4101ec25517SAdrien Destugues        .start_col = SCROLLREGION_LEFT(state),
4111ec25517SAdrien Destugues        .end_col   = SCROLLREGION_RIGHT(state),
412dae0a4e0SAdrien Destugues - PulkoMandy      };
413dae0a4e0SAdrien Destugues - PulkoMandy
414dae0a4e0SAdrien Destugues - PulkoMandy      scroll(state, rect, -1, 0);
415dae0a4e0SAdrien Destugues - PulkoMandy    }
416dae0a4e0SAdrien Destugues - PulkoMandy    else if(state->pos.row > 0)
417dae0a4e0SAdrien Destugues - PulkoMandy        state->pos.row--;
418dae0a4e0SAdrien Destugues - PulkoMandy    break;
419dae0a4e0SAdrien Destugues - PulkoMandy
4201ec25517SAdrien Destugues  case 0x8e: // SS2 - ECMA-48 8.3.141
4211ec25517SAdrien Destugues    state->gsingle_set = 2;
4221ec25517SAdrien Destugues    break;
4231ec25517SAdrien Destugues
4241ec25517SAdrien Destugues  case 0x8f: // SS3 - ECMA-48 8.3.142
4251ec25517SAdrien Destugues    state->gsingle_set = 3;
4261ec25517SAdrien Destugues    break;
4271ec25517SAdrien Destugues
428dae0a4e0SAdrien Destugues - PulkoMandy  default:
429dae0a4e0SAdrien Destugues - PulkoMandy    return 0;
430dae0a4e0SAdrien Destugues - PulkoMandy  }
431dae0a4e0SAdrien Destugues - PulkoMandy
432dae0a4e0SAdrien Destugues - PulkoMandy  updatecursor(state, &oldpos, 1);
433dae0a4e0SAdrien Destugues - PulkoMandy
434dae0a4e0SAdrien Destugues - PulkoMandy  return 1;
435dae0a4e0SAdrien Destugues - PulkoMandy}
436dae0a4e0SAdrien Destugues - PulkoMandy
437dae0a4e0SAdrien Destugues - PulkoMandystatic void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row)
438dae0a4e0SAdrien Destugues - PulkoMandy{
439dae0a4e0SAdrien Destugues - PulkoMandy  modifiers <<= 2;
440dae0a4e0SAdrien Destugues - PulkoMandy
441dae0a4e0SAdrien Destugues - PulkoMandy  switch(state->mouse_protocol) {
442dae0a4e0SAdrien Destugues - PulkoMandy  case MOUSE_X10:
443dae0a4e0SAdrien Destugues - PulkoMandy    if(col + 0x21 > 0xff)
444dae0a4e0SAdrien Destugues - PulkoMandy      col = 0xff - 0x21;
445dae0a4e0SAdrien Destugues - PulkoMandy    if(row + 0x21 > 0xff)
446dae0a4e0SAdrien Destugues - PulkoMandy      row = 0xff - 0x21;
447dae0a4e0SAdrien Destugues - PulkoMandy
448dae0a4e0SAdrien Destugues - PulkoMandy    if(!pressed)
449dae0a4e0SAdrien Destugues - PulkoMandy      code = 3;
450dae0a4e0SAdrien Destugues - PulkoMandy
4511ec25517SAdrien Destugues    vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c",
452dae0a4e0SAdrien Destugues - PulkoMandy        (code | modifiers) + 0x20, col + 0x21, row + 0x21);
453dae0a4e0SAdrien Destugues - PulkoMandy    break;
454dae0a4e0SAdrien Destugues - PulkoMandy
455dae0a4e0SAdrien Destugues - PulkoMandy  case MOUSE_UTF8:
456dae0a4e0SAdrien Destugues - PulkoMandy    {
457dae0a4e0SAdrien Destugues - PulkoMandy      char utf8[18]; size_t len = 0;
458dae0a4e0SAdrien Destugues - PulkoMandy
459dae0a4e0SAdrien Destugues - PulkoMandy      if(!pressed)
460dae0a4e0SAdrien Destugues - PulkoMandy        code = 3;
461dae0a4e0SAdrien Destugues - PulkoMandy
462dae0a4e0SAdrien Destugues - PulkoMandy      len += fill_utf8((code | modifiers) + 0x20, utf8 + len);
463dae0a4e0SAdrien Destugues - PulkoMandy      len += fill_utf8(col + 0x21, utf8 + len);
464dae0a4e0SAdrien Destugues - PulkoMandy      len += fill_utf8(row + 0x21, utf8 + len);
4651ec25517SAdrien Destugues      utf8[len] = 0;
466dae0a4e0SAdrien Destugues - PulkoMandy
4671ec25517SAdrien Destugues      vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8);
468dae0a4e0SAdrien Destugues - PulkoMandy    }
469dae0a4e0SAdrien Destugues - PulkoMandy    break;
470dae0a4e0SAdrien Destugues - PulkoMandy
471dae0a4e0SAdrien Destugues - PulkoMandy  case MOUSE_SGR:
4721ec25517SAdrien Destugues    vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c",
473dae0a4e0SAdrien Destugues - PulkoMandy        code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm');
474dae0a4e0SAdrien Destugues - PulkoMandy    break;
475dae0a4e0SAdrien Destugues - PulkoMandy
476dae0a4e0SAdrien Destugues - PulkoMandy  case MOUSE_RXVT:
477dae0a4e0SAdrien Destugues - PulkoMandy    if(!pressed)
478dae0a4e0SAdrien Destugues - PulkoMandy      code = 3;
479dae0a4e0SAdrien Destugues - PulkoMandy
4801ec25517SAdrien Destugues    vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM",
481dae0a4e0SAdrien Destugues - PulkoMandy        code | modifiers, col + 1, row + 1);
482dae0a4e0SAdrien Destugues - PulkoMandy    break;
483dae0a4e0SAdrien Destugues - PulkoMandy  }
484dae0a4e0SAdrien Destugues - PulkoMandy}
485dae0a4e0SAdrien Destugues - PulkoMandy
486dae0a4e0SAdrien Destugues - PulkoMandystatic void mousefunc(int col, int row, int button, int pressed, int modifiers, void *data)
487dae0a4e0SAdrien Destugues - PulkoMandy{
488dae0a4e0SAdrien Destugues - PulkoMandy  VTermState *state = data;
489dae0a4e0SAdrien Destugues - PulkoMandy
490dae0a4e0SAdrien Destugues - PulkoMandy  int old_col     = state->mouse_col;
491dae0a4e0SAdrien Destugues - PulkoMandy  int old_row     = state->mouse_row;
492dae0a4e0SAdrien Destugues - PulkoMandy  int old_buttons = state->mouse_buttons;
493dae0a4e0SAdrien Destugues - PulkoMandy
494dae0a4e0SAdrien Destugues - PulkoMandy  state->mouse_col = col;
495dae0a4e0SAdrien Destugues - PulkoMandy  state->mouse_row = row;
496dae0a4e0SAdrien Destugues - PulkoMandy
497dae0a4e0SAdrien Destugues - PulkoMandy  if(button > 0 && button <= 3) {
498dae0a4e0SAdrien Destugues - PulkoMandy    if(pressed)
499dae0a4e0SAdrien Destugues - PulkoMandy      state->mouse_buttons |= (1 << (button-1));
500dae0a4e0SAdrien Destugues - PulkoMandy    else
501dae0a4e0SAdrien Destugues - PulkoMandy      state->mouse_buttons &= ~(1 << (button-1));
502dae0a4e0SAdrien Destugues - PulkoMandy  }
503dae0a4e0SAdrien Destugues - PulkoMandy
504dae0a4e0SAdrien Destugues - PulkoMandy  modifiers &= 0x7;
505dae0a4e0SAdrien Destugues - PulkoMandy
506dae0a4e0SAdrien Destugues - PulkoMandy
507dae0a4e0SAdrien Destugues - PulkoMandy  /* Most of the time we don't get button releases from 4/5 */
508dae0a4e0SAdrien Destugues - PulkoMandy  if(state->mouse_buttons != old_buttons || button >= 4) {
509dae0a4e0SAdrien Destugues - PulkoMandy    if(button < 4) {
510dae0a4e0SAdrien Destugues - PulkoMandy      output_mouse(state, button-1, pressed, modifiers, col, row);
511dae0a4e0SAdrien Destugues - PulkoMandy    }
512dae0a4e0SAdrien Destugues - PulkoMandy    else if(button < 6) {
513dae0a4e0SAdrien Destugues - PulkoMandy      output_mouse(state, button-4 + 0x40, pressed, modifiers, col, row);
514dae0a4e0SAdrien Destugues - PulkoMandy    }
515dae0a4e0SAdrien Destugues - PulkoMandy  }
516dae0a4e0SAdrien Destugues - PulkoMandy  else if(col != old_col || row != old_row) {
517dae0a4e0SAdrien Destugues - PulkoMandy    if((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) ||
518dae0a4e0SAdrien Destugues - PulkoMandy       (state->mouse_flags & MOUSE_WANT_MOVE)) {
519dae0a4e0SAdrien Destugues - PulkoMandy      int button = state->mouse_buttons & 0x01 ? 1 :
520dae0a4e0SAdrien Destugues - PulkoMandy                   state->mouse_buttons & 0x02 ? 2 :
521dae0a4e0SAdrien Destugues - PulkoMandy                   state->mouse_buttons & 0x04 ? 3 : 4;
522dae0a4e0SAdrien Destugues - PulkoMandy      output_mouse(state, button-1 + 0x20, 1, modifiers, col, row);
523dae0a4e0SAdrien Destugues - PulkoMandy    }
524dae0a4e0SAdrien Destugues - PulkoMandy  }
525dae0a4e0SAdrien Destugues - PulkoMandy}
526dae0a4e0SAdrien Destugues - PulkoMandy
527dae0a4e0SAdrien Destugues - PulkoMandystatic int settermprop_bool(VTermState *state, VTermProp prop, int v)
528dae0a4e0SAdrien Destugues - PulkoMandy{
5291ec25517SAdrien Destugues  VTermValue val = { .boolean = v };
5301ec25517SAdrien Destugues  return vterm_state_set_termprop(state, prop, &val);
531dae0a4e0SAdrien Destugues - PulkoMandy}
532dae0a4e0SAdrien Destugues - PulkoMandy
533dae0a4e0SAdrien Destugues - PulkoMandystatic int settermprop_int(VTermState *state, VTermProp prop, int v)
534dae0a4e0SAdrien Destugues - PulkoMandy{
5351ec25517SAdrien Destugues  VTermValue val = { .number = v };
5361ec25517SAdrien Destugues  return vterm_state_set_termprop(state, prop, &val);
537dae0a4e0SAdrien Destugues - PulkoMandy}
538dae0a4e0SAdrien Destugues - PulkoMandy
539dae0a4e0SAdrien Destugues - PulkoMandystatic int settermprop_string(VTermState *state, VTermProp prop, const char *str, size_t len)
540dae0a4e0SAdrien Destugues - PulkoMandy{
541dae0a4e0SAdrien Destugues - PulkoMandy  char strvalue[len+1];
5426a545a8eSAdrien Destugues  VTermValue val = { .string = strvalue };
5436a545a8eSAdrien Destugues
544dae0a4e0SAdrien Destugues - PulkoMandy  strncpy(strvalue, str, len);
545dae0a4e0SAdrien Destugues - PulkoMandy  strvalue[len] = 0;
546dae0a4e0SAdrien Destugues - PulkoMandy
5471ec25517SAdrien Destugues  return vterm_state_set_termprop(state, prop, &val);
548dae0a4e0SAdrien Destugues - PulkoMandy}
549dae0a4e0SAdrien Destugues - PulkoMandy
550dae0a4e0SAdrien Destugues - PulkoMandystatic void savecursor(VTermState *state, int save)
551dae0a4e0SAdrien Destugues - PulkoMandy{
552dae0a4e0SAdrien Destugues - PulkoMandy  if(save) {
553dae0a4e0SAdrien Destugues - PulkoMandy    state->saved.pos = state->pos;
554dae0a4e0SAdrien Destugues - PulkoMandy    state->saved.mode.cursor_visible = state->mode.cursor_visible;
555dae0a4e0SAdrien Destugues - PulkoMandy    state->saved.mode.cursor_blink   = state->mode.cursor_blink;
556dae0a4e0SAdrien Destugues - PulkoMandy    state->saved.mode.cursor_shape   = state->mode.cursor_shape;
557dae0a4e0SAdrien Destugues - PulkoMandy
558dae0a4e0SAdrien Destugues - PulkoMandy    vterm_state_savepen(state, 1);
559dae0a4e0SAdrien Destugues - PulkoMandy  }
560dae0a4e0SAdrien Destugues - PulkoMandy  else {
561dae0a4e0SAdrien Destugues - PulkoMandy    VTermPos oldpos = state->pos;
562dae0a4e0SAdrien Destugues - PulkoMandy
563dae0a4e0SAdrien Destugues - PulkoMandy    state->pos = state->saved.pos;
564dae0a4e0SAdrien Destugues - PulkoMandy
5651ec25517SAdrien Destugues    settermprop_bool(state, VTERM_PROP_CURSORVISIBLE, state->saved.mode.cursor_visible);
5661ec25517SAdrien Destugues    settermprop_bool(state, VTERM_PROP_CURSORBLINK,   state->saved.mode.cursor_blink);
5671ec25517SAdrien Destugues    settermprop_int (state, VTERM_PROP_CURSORSHAPE,   state->saved.mode.cursor_shape);
568dae0a4e0SAdrien Destugues - PulkoMandy
569dae0a4e0SAdrien Destugues - PulkoMandy    vterm_state_savepen(state, 0);
570dae0a4e0SAdrien Destugues - PulkoMandy
571dae0a4e0SAdrien Destugues - PulkoMandy    updatecursor(state, &oldpos, 1);
572dae0a4e0SAdrien Destugues - PulkoMandy  }
573dae0a4e0SAdrien Destugues - PulkoMandy}
574dae0a4e0SAdrien Destugues - PulkoMandy
575dae0a4e0SAdrien Destugues - PulkoMandystatic int on_escape(const char *bytes, size_t len, void *user)
576dae0a4e0SAdrien Destugues - PulkoMandy{
577dae0a4e0SAdrien Destugues - PulkoMandy  VTermState *state = user;
578dae0a4e0SAdrien Destugues - PulkoMandy
579dae0a4e0SAdrien Destugues - PulkoMandy  /* Easier to decode this from the first byte, even though the final
580dae0a4e0SAdrien Destugues - PulkoMandy   * byte terminates it
581dae0a4e0SAdrien Destugues - PulkoMandy   */
582dae0a4e0SAdrien Destugues - PulkoMandy  switch(bytes[0]) {
5831ec25517SAdrien Destugues  case ' ':
5841ec25517SAdrien Destugues    if(len != 2)
5851ec25517SAdrien Destugues      return 0;
5861ec25517SAdrien Destugues
5871ec25517SAdrien Destugues    switch(bytes[1]) {
5881ec25517SAdrien Destugues      case 'F': // S7C1T
5891ec25517SAdrien Destugues        state->vt->mode.ctrl8bit = 0;
5901ec25517SAdrien Destugues        break;
5911ec25517SAdrien Destugues
5921ec25517SAdrien Destugues      case 'G': // S8C1T
5931ec25517SAdrien Destugues        state->vt->mode.ctrl8bit = 1;
5941ec25517SAdrien Destugues        break;
5951ec25517SAdrien Destugues
5961ec25517SAdrien Destugues      default:
5971ec25517SAdrien Destugues        return 0;
5981ec25517SAdrien Destugues    }
5991ec25517SAdrien Destugues    return 2;
6001ec25517SAdrien Destugues
601dae0a4e0SAdrien Destugues - PulkoMandy  case '#':
602dae0a4e0SAdrien Destugues - PulkoMandy    if(len != 2)
603dae0a4e0SAdrien Destugues - PulkoMandy      return 0;
604dae0a4e0SAdrien Destugues - PulkoMandy
605dae0a4e0SAdrien Destugues - PulkoMandy    switch(bytes[1]) {
6061ec25517SAdrien Destugues      case '3': // DECDHL top
6071ec25517SAdrien Destugues        if(state->mode.leftrightmargin)
6081ec25517SAdrien Destugues          break;
6091ec25517SAdrien Destugues        set_lineinfo(state, state->pos.row, NO_FORCE, DWL_ON, DHL_TOP);
6101ec25517SAdrien Destugues        break;
6111ec25517SAdrien Destugues
6121ec25517SAdrien Destugues      case '4': // DECDHL bottom
6131ec25517SAdrien Destugues        if(state->mode.leftrightmargin)
6141ec25517SAdrien Destugues          break;
6151ec25517SAdrien Destugues        set_lineinfo(state, state->pos.row, NO_FORCE, DWL_ON, DHL_BOTTOM);
6161ec25517SAdrien Destugues        break;
6171ec25517SAdrien Destugues
6181ec25517SAdrien Destugues      case '5': // DECSWL
6191ec25517SAdrien Destugues        if(state->mode.leftrightmargin)
6201ec25517SAdrien Destugues          break;
6211ec25517SAdrien Destugues        set_lineinfo(state, state->pos.row, NO_FORCE, DWL_OFF, DHL_OFF);
6221ec25517SAdrien Destugues        break;
6231ec25517SAdrien Destugues
6241ec25517SAdrien Destugues      case '6': // DECDWL
6251ec25517SAdrien Destugues        if(state->mode.leftrightmargin)
6261ec25517SAdrien Destugues          break;
6271ec25517SAdrien Destugues        set_lineinfo(state, state->pos.row, NO_FORCE, DWL_ON, DHL_OFF);
6281ec25517SAdrien Destugues        break;
6291ec25517SAdrien Destugues
630dae0a4e0SAdrien Destugues - PulkoMandy      case '8': // DECALN
631dae0a4e0SAdrien Destugues - PulkoMandy      {
632dae0a4e0SAdrien Destugues - PulkoMandy        VTermPos pos;
633dae0a4e0SAdrien Destugues - PulkoMandy        uint32_t E[] = { 'E', 0 };
634dae0a4e0SAdrien Destugues - PulkoMandy        for(pos.row = 0; pos.row < state->rows; pos.row++)
6351ec25517SAdrien Destugues          for(pos.col = 0; pos.col < ROWWIDTH(state, pos.row); pos.col++)
636dae0a4e0SAdrien Destugues - PulkoMandy            putglyph(state, E, 1, pos);
637dae0a4e0SAdrien Destugues - PulkoMandy        break;
638dae0a4e0SAdrien Destugues - PulkoMandy      }
639dae0a4e0SAdrien Destugues - PulkoMandy
640dae0a4e0SAdrien Destugues - PulkoMandy      default:
641dae0a4e0SAdrien Destugues - PulkoMandy        return 0;
642dae0a4e0SAdrien Destugues - PulkoMandy    }
643dae0a4e0SAdrien Destugues - PulkoMandy    return 2;
644dae0a4e0SAdrien Destugues - PulkoMandy
645dae0a4e0SAdrien Destugues - PulkoMandy  case '(': case ')': case '*': case '+': // SCS
646dae0a4e0SAdrien Destugues - PulkoMandy    if(len != 2)
647dae0a4e0SAdrien Destugues - PulkoMandy      return 0;
648dae0a4e0SAdrien Destugues - PulkoMandy
649dae0a4e0SAdrien Destugues - PulkoMandy    {
650dae0a4e0SAdrien Destugues - PulkoMandy      int setnum = bytes[0] - 0x28;
651dae0a4e0SAdrien Destugues - PulkoMandy      VTermEncoding *newenc = vterm_lookup_encoding(ENC_SINGLE_94, bytes[1]);
652dae0a4e0SAdrien Destugues - PulkoMandy
653dae0a4e0SAdrien Destugues - PulkoMandy      if(newenc) {
654dae0a4e0SAdrien Destugues - PulkoMandy        state->encoding[setnum].enc = newenc;
655dae0a4e0SAdrien Destugues - PulkoMandy
656dae0a4e0SAdrien Destugues - PulkoMandy        if(newenc->init)
657dae0a4e0SAdrien Destugues - PulkoMandy          (*newenc->init)(newenc, state->encoding[setnum].data);
658dae0a4e0SAdrien Destugues - PulkoMandy      }
659dae0a4e0SAdrien Destugues - PulkoMandy    }
660dae0a4e0SAdrien Destugues - PulkoMandy
661dae0a4e0SAdrien Destugues - PulkoMandy    return 2;
662dae0a4e0SAdrien Destugues - PulkoMandy
663dae0a4e0SAdrien Destugues - PulkoMandy  case '7': // DECSC
664dae0a4e0SAdrien Destugues - PulkoMandy    savecursor(state, 1);
665dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
666dae0a4e0SAdrien Destugues - PulkoMandy
667dae0a4e0SAdrien Destugues - PulkoMandy  case '8': // DECRC
668dae0a4e0SAdrien Destugues - PulkoMandy    savecursor(state, 0);
669dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
670dae0a4e0SAdrien Destugues - PulkoMandy
6711ec25517SAdrien Destugues  case '<': // Ignored by VT100. Used in VT52 mode to switch up to VT100
6721ec25517SAdrien Destugues    return 1;
6731ec25517SAdrien Destugues
674dae0a4e0SAdrien Destugues - PulkoMandy  case '=': // DECKPAM
675dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.keypad = 1;
676dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
677dae0a4e0SAdrien Destugues - PulkoMandy
678dae0a4e0SAdrien Destugues - PulkoMandy  case '>': // DECKPNM
679dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.keypad = 0;
680dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
681dae0a4e0SAdrien Destugues - PulkoMandy
682dae0a4e0SAdrien Destugues - PulkoMandy  case 'c': // RIS - ECMA-48 8.3.105
683dae0a4e0SAdrien Destugues - PulkoMandy  {
684dae0a4e0SAdrien Destugues - PulkoMandy    VTermPos oldpos = state->pos;
685dae0a4e0SAdrien Destugues - PulkoMandy    vterm_state_reset(state, 1);
686dae0a4e0SAdrien Destugues - PulkoMandy    if(state->callbacks && state->callbacks->movecursor)
687dae0a4e0SAdrien Destugues - PulkoMandy      (*state->callbacks->movecursor)(state->pos, oldpos, state->mode.cursor_visible, state->cbdata);
688dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
689dae0a4e0SAdrien Destugues - PulkoMandy  }
690dae0a4e0SAdrien Destugues - PulkoMandy
691dae0a4e0SAdrien Destugues - PulkoMandy  case 'n': // LS2 - ECMA-48 8.3.78
692dae0a4e0SAdrien Destugues - PulkoMandy    state->gl_set = 2;
693dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
694dae0a4e0SAdrien Destugues - PulkoMandy
695dae0a4e0SAdrien Destugues - PulkoMandy  case 'o': // LS3 - ECMA-48 8.3.80
696dae0a4e0SAdrien Destugues - PulkoMandy    state->gl_set = 3;
697dae0a4e0SAdrien Destugues - PulkoMandy    return 1;
698dae0a4e0SAdrien Destugues - PulkoMandy
6991ec25517SAdrien Destugues  case '~': // LS1R - ECMA-48 8.3.77
7001ec25517SAdrien Destugues    state->gr_set = 1;
7011ec25517SAdrien Destugues    return 1;
7021ec25517SAdrien Destugues
7031ec25517SAdrien Destugues  case '}': // LS2R - ECMA-48 8.3.79
7041ec25517SAdrien Destugues    state->gr_set = 2;
7051ec25517SAdrien Destugues    return 1;
7061ec25517SAdrien Destugues
7071ec25517SAdrien Destugues  case '|': // LS3R - ECMA-48 8.3.81
7081ec25517SAdrien Destugues    state->gr_set = 3;
7091ec25517SAdrien Destugues    return 1;
7101ec25517SAdrien Destugues
711dae0a4e0SAdrien Destugues - PulkoMandy  default:
712dae0a4e0SAdrien Destugues - PulkoMandy    return 0;
713dae0a4e0SAdrien Destugues - PulkoMandy  }
714dae0a4e0SAdrien Destugues - PulkoMandy}
715dae0a4e0SAdrien Destugues - PulkoMandy
716dae0a4e0SAdrien Destugues - PulkoMandystatic void set_mode(VTermState *state, int num, int val)
717dae0a4e0SAdrien Destugues - PulkoMandy{
718dae0a4e0SAdrien Destugues - PulkoMandy  switch(num) {
719dae0a4e0SAdrien Destugues - PulkoMandy  case 4: // IRM - ECMA-48 7.2.10
720dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.insert = val;
721dae0a4e0SAdrien Destugues - PulkoMandy    break;
722dae0a4e0SAdrien Destugues - PulkoMandy
723dae0a4e0SAdrien Destugues - PulkoMandy  case 20: // LNM - ANSI X3.4-1977
724dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.newline = val;
725dae0a4e0SAdrien Destugues - PulkoMandy    break;
726dae0a4e0SAdrien Destugues - PulkoMandy
727dae0a4e0SAdrien Destugues - PulkoMandy  default:
728dae0a4e0SAdrien Destugues - PulkoMandy    fprintf(stderr, "libvterm: Unknown mode %d\n", num);
729dae0a4e0SAdrien Destugues - PulkoMandy    return;
730dae0a4e0SAdrien Destugues - PulkoMandy  }
731dae0a4e0SAdrien Destugues - PulkoMandy}
732dae0a4e0SAdrien Destugues - PulkoMandy
733dae0a4e0SAdrien Destugues - PulkoMandystatic void set_dec_mode(VTermState *state, int num, int val)
734dae0a4e0SAdrien Destugues - PulkoMandy{
735dae0a4e0SAdrien Destugues - PulkoMandy  switch(num) {
736dae0a4e0SAdrien Destugues - PulkoMandy  case 1:
737dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.cursor = val;
738dae0a4e0SAdrien Destugues - PulkoMandy    break;
739dae0a4e0SAdrien Destugues - PulkoMandy
7401ec25517SAdrien Destugues  case 5: // DECSCNM - screen mode
741dae0a4e0SAdrien Destugues - PulkoMandy    settermprop_bool(state, VTERM_PROP_REVERSE, val);
742dae0a4e0SAdrien Destugues - PulkoMandy    break;
743dae0a4e0SAdrien Destugues - PulkoMandy
744dae0a4e0SAdrien Destugues - PulkoMandy  case 6: // DECOM - origin mode
745dae0a4e0SAdrien Destugues - PulkoMandy    {
746dae0a4e0SAdrien Destugues - PulkoMandy      VTermPos oldpos = state->pos;
747dae0a4e0SAdrien Destugues - PulkoMandy      state->mode.origin = val;
7481ec25517SAdrien Destugues      state->pos.row = state->mode.origin ? state->scrollregion_top : 0;
7491ec25517SAdrien Destugues      state->pos.col = state->mode.origin ? SCROLLREGION_LEFT(state) : 0;
750dae0a4e0SAdrien Destugues - PulkoMandy      updatecursor(state, &oldpos, 1);
751dae0a4e0SAdrien Destugues - PulkoMandy    }
752dae0a4e0SAdrien Destugues - PulkoMandy    break;
753dae0a4e0SAdrien Destugues - PulkoMandy
754dae0a4e0SAdrien Destugues - PulkoMandy  case 7:
755dae0a4e0SAdrien Destugues - PulkoMandy    state->mode.autowrap = val;
756dae0a4e0SAdrien Destugues - PulkoMandy    break;
757dae0a4e0SAdrien Destugues - PulkoMandy
758