Fixing (potentially) a buffer underflow in key_press_cb
Basically the inputs are goofy
This commit is contained in:
parent
9215edb1c1
commit
0437af53c3
65
cowterm.c
65
cowterm.c
@ -304,6 +304,10 @@ static void draw_char(Display *display, Drawable d, int x, int y) {
|
|||||||
if (x < 0 || x >= term_cols || y < 0 || y >= term_rows)
|
if (x < 0 || x >= term_cols || y < 0 || y >= term_rows)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
char c = terminal_buffer[y][x];
|
||||||
|
if (c < 32 || c > 126) // Only allow printable ASCII characters
|
||||||
|
return;
|
||||||
|
|
||||||
unsigned long fg = color_buffer[y][x];
|
unsigned long fg = color_buffer[y][x];
|
||||||
unsigned long bg = bg_color_buffer[y][x];
|
unsigned long bg = bg_color_buffer[y][x];
|
||||||
int attr = attr_buffer[y][x];
|
int attr = attr_buffer[y][x];
|
||||||
@ -328,7 +332,7 @@ static void draw_char(Display *display, Drawable d, int x, int y) {
|
|||||||
|
|
||||||
XSetForeground(display, gc, fg);
|
XSetForeground(display, gc, fg);
|
||||||
|
|
||||||
char c[2] = {terminal_buffer[y][x], '\0'};
|
char str[2] = {c, '\0'};
|
||||||
XFontStruct *font = regular_font;
|
XFontStruct *font = regular_font;
|
||||||
|
|
||||||
if (attr & ATTR_BOLD)
|
if (attr & ATTR_BOLD)
|
||||||
@ -337,7 +341,8 @@ static void draw_char(Display *display, Drawable d, int x, int y) {
|
|||||||
font = italic_font;
|
font = italic_font;
|
||||||
|
|
||||||
XSetFont(display, gc, font->fid);
|
XSetFont(display, gc, font->fid);
|
||||||
XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 4, c, 1);
|
XDrawString(display, d, gc, x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 4, str,
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_terminal(Display *display, Window window) {
|
static void draw_terminal(Display *display, Window window) {
|
||||||
@ -785,6 +790,46 @@ static void parse_ansi_code(const char *buf, int *idx, int max_len,
|
|||||||
|
|
||||||
switch (buf[*idx]) {
|
switch (buf[*idx]) {
|
||||||
case 'H': // Set cursor position
|
case 'H': // Set cursor position
|
||||||
|
if (param_idx >= 2) {
|
||||||
|
cursor_y = params[0] - 1 < 0 ? 0
|
||||||
|
: params[0] - 1 >= term_rows ? term_rows - 1
|
||||||
|
: params[0] - 1;
|
||||||
|
cursor_x = params[1] - 1 < 0 ? 0
|
||||||
|
: params[1] - 1 >= term_cols ? term_cols - 1
|
||||||
|
: params[1] - 1;
|
||||||
|
} else {
|
||||||
|
cursor_x = cursor_y = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's': // Save cursor position
|
||||||
|
if (param_idx == 0) {
|
||||||
|
saved_cursor_x = cursor_x;
|
||||||
|
saved_cursor_y = cursor_y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u': // Restore cursor position
|
||||||
|
if (param_idx == 0) {
|
||||||
|
cursor_x = saved_cursor_x;
|
||||||
|
cursor_y = saved_cursor_y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'h': // Set mode
|
||||||
|
case 'l': // Reset mode
|
||||||
|
if (param_idx >= 1) {
|
||||||
|
switch (params[0]) {
|
||||||
|
case 25: // Show/hide cursor
|
||||||
|
cursor_visible = (buf[*idx] == 'h');
|
||||||
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
|
case 12: // Start/stop blinking cursor
|
||||||
|
cursor_visible = 1;
|
||||||
|
needs_refresh = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'f': // Alternative set cursor position
|
case 'f': // Alternative set cursor position
|
||||||
if (param_idx >= 2) {
|
if (param_idx >= 2) {
|
||||||
cursor_y = params[0] - 1 < 0 ? 0
|
cursor_y = params[0] - 1 < 0 ? 0
|
||||||
@ -1062,8 +1107,11 @@ static void key_press_cb(XKeyEvent *event, void *data) {
|
|||||||
write(*master, "\025", 1);
|
write(*master, "\025", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char ctrl_char = '@' + (keysym & 0x1f);
|
if ((keysym & 0x1f) >= '@' && (keysym & 0x1f) <= '_') {
|
||||||
write(*master, &ctrl_char, 1);
|
char ctrl_char = '@' + (keysym & 0x1f);
|
||||||
|
write(*master, &ctrl_char, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,10 +1119,6 @@ static void key_press_cb(XKeyEvent *event, void *data) {
|
|||||||
write(*master, "\r", 1); // Shell handles return
|
write(*master, "\r", 1); // Shell handles return
|
||||||
} else if (keysym == XK_BackSpace) {
|
} else if (keysym == XK_BackSpace) {
|
||||||
write(*master, "\177", 1); // Shell handles backspace
|
write(*master, "\177", 1); // Shell handles backspace
|
||||||
} else if (cursor_y > 0) {
|
|
||||||
char seq[8];
|
|
||||||
snprintf(seq, sizeof(seq), "\033[A\033[%dC", term_cols);
|
|
||||||
write(*master, seq, strlen(seq));
|
|
||||||
} else if (keysym == XK_Left) {
|
} else if (keysym == XK_Left) {
|
||||||
if (cursor_x > 0) {
|
if (cursor_x > 0) {
|
||||||
write(*master, "\033[D", 3);
|
write(*master, "\033[D", 3);
|
||||||
@ -1098,6 +1142,8 @@ static void key_press_cb(XKeyEvent *event, void *data) {
|
|||||||
} else if (keysym == XK_Tab) {
|
} else if (keysym == XK_Tab) {
|
||||||
write(*master, "\t", 1); // Shell handles autocomplete
|
write(*master, "\t", 1); // Shell handles autocomplete
|
||||||
} else if (len > 0) {
|
} else if (len > 0) {
|
||||||
|
if (len > (int)sizeof(buf))
|
||||||
|
len = sizeof(buf);
|
||||||
write(*master, buf, len);
|
write(*master, buf, len);
|
||||||
if (cursor_x >= term_cols - 1) {
|
if (cursor_x >= term_cols - 1) {
|
||||||
write(*master, "\r\n", 2);
|
write(*master, "\r\n", 2);
|
||||||
@ -1236,8 +1282,9 @@ int main(void) {
|
|||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
break;
|
break;
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
if (!(ev.xkey.state & ControlMask) && ev.xkey.keycode < 128)
|
if (ev.xkey.keycode < 128) {
|
||||||
key_press_cb(&ev.xkey, &master);
|
key_press_cb(&ev.xkey, &master);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Expose:
|
case Expose:
|
||||||
needs_refresh = 1;
|
needs_refresh = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user