mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Port the editor to non-sortix operating systems.
This commit is contained in:
parent
63146072a4
commit
e5ed21520c
8 changed files with 347 additions and 60 deletions
|
@ -1,4 +1,3 @@
|
|||
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||
include ../build-aux/platform.mak
|
||||
include ../build-aux/compiler.mak
|
||||
include ../build-aux/version.mak
|
||||
|
@ -10,6 +9,10 @@ CFLAGS?=$(OPTLEVEL)
|
|||
CPPFLAGS:=$(CPPFLAGS) -DVERSIONSTR=\"$(VERSION)\"
|
||||
CFLAGS:=$(CFLAGS) -Wall -Wextra
|
||||
|
||||
ifeq ($(HOST_IS_SORTIX),0)
|
||||
CPPFLAGS+=-D_GNU_SOURCE
|
||||
endif
|
||||
|
||||
BINARY=editor
|
||||
|
||||
OBJS=\
|
||||
|
|
|
@ -814,6 +814,11 @@ void editor_type_paste(struct editor* editor)
|
|||
}
|
||||
}
|
||||
|
||||
void editor_type_suspend(struct editor* editor)
|
||||
{
|
||||
editor->suspend_requested = true;
|
||||
}
|
||||
|
||||
void editor_type_character(struct editor* editor, wchar_t c)
|
||||
{
|
||||
if ( editor->control )
|
||||
|
@ -832,6 +837,7 @@ void editor_type_character(struct editor* editor, wchar_t c)
|
|||
editor_type_save(editor); break;
|
||||
case L'v': editor_type_paste(editor); break;
|
||||
case L'x': editor_type_cut(editor); break;
|
||||
case L'z': editor_type_suspend(editor); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ void editor_type_raw_character(struct editor* editor, wchar_t c);
|
|||
void editor_type_copy(struct editor* editor);
|
||||
void editor_type_cut(struct editor* editor);
|
||||
void editor_type_paste(struct editor* editor);
|
||||
void editor_type_suspend(struct editor* editor);
|
||||
void editor_type_character(struct editor* editor, wchar_t c);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
|
@ -91,7 +91,7 @@ void editor_load_config_path(struct editor* editor, const char* path)
|
|||
if ( !fp )
|
||||
{
|
||||
if ( errno != ENOENT )
|
||||
error(0, errno, "%s", path);
|
||||
warn("%s", path);
|
||||
return;
|
||||
}
|
||||
char* line = NULL;
|
||||
|
@ -106,7 +106,7 @@ void editor_load_config_path(struct editor* editor, const char* path)
|
|||
editor_modal_command_config(editor, line);
|
||||
}
|
||||
if ( ferror(fp) )
|
||||
error(0, errno, "getline: %s", path);
|
||||
warn("getline: %s", path);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ void editor_load_config(struct editor* editor)
|
|||
char* path;
|
||||
if ( asprintf(&path, "%s/.editor", home) < 0 )
|
||||
{
|
||||
error(0, errno, "malloc");
|
||||
warn("malloc");
|
||||
return;
|
||||
}
|
||||
editor_load_config_path(editor, path);
|
||||
|
@ -275,9 +275,9 @@ int main(int argc, char* argv[])
|
|||
setlocale(LC_ALL, "");
|
||||
|
||||
if ( !isatty(0) )
|
||||
error(1, errno, "standard input");
|
||||
err(1, "standard input");
|
||||
if ( !isatty(1) )
|
||||
error(1, errno, "standard output");
|
||||
err(1, "standard output");
|
||||
|
||||
struct editor editor;
|
||||
initialize_editor(&editor);
|
||||
|
@ -285,7 +285,7 @@ int main(int argc, char* argv[])
|
|||
editor_load_config(&editor);
|
||||
|
||||
if ( 2 <= argc && !editor_load_file(&editor, argv[1]) )
|
||||
error(1, errno, "`%s'", argv[1]);
|
||||
err(1, "`%s'", argv[1]);
|
||||
|
||||
struct editor_input editor_input;
|
||||
editor_input_begin(&editor_input);
|
||||
|
@ -297,6 +297,14 @@ int main(int argc, char* argv[])
|
|||
|
||||
while ( editor.mode != MODE_QUIT )
|
||||
{
|
||||
if ( editor.suspend_requested )
|
||||
{
|
||||
editor_input_suspend(&editor_input);
|
||||
editor.suspend_requested = false;
|
||||
reset_terminal_state(stdout, &stdout_state);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
struct terminal_state output_state;
|
||||
make_terminal_state(stdout, &output_state);
|
||||
editor_colorize(&editor);
|
||||
|
|
|
@ -86,6 +86,7 @@ struct editor
|
|||
bool modal_error;
|
||||
enum language highlight_source;
|
||||
bool line_numbering;
|
||||
bool suspend_requested;
|
||||
};
|
||||
|
||||
__attribute__((unused))
|
||||
|
|
321
editor/input.c
321
editor/input.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,19 +17,88 @@
|
|||
|
||||
#if defined(__sortix__)
|
||||
#include <sys/keycodes.h>
|
||||
#include <sys/termmode.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "editor.h"
|
||||
#include "input.h"
|
||||
#include "modal.h"
|
||||
|
||||
struct terminal_sequence
|
||||
{
|
||||
const char* sequence;
|
||||
int kbkey;
|
||||
bool control;
|
||||
bool shift;
|
||||
};
|
||||
|
||||
// TODO: The terminal doesn't deliver shift-pageup and shift-pagedown events.
|
||||
// TODO: The terminal doesn't deliver shift-home and shift-end events.
|
||||
|
||||
struct terminal_sequence terminal_sequences[] =
|
||||
{
|
||||
{ "\e[1;2A", KBKEY_UP, false, true },
|
||||
{ "\e[1;2B", KBKEY_DOWN, false, true },
|
||||
{ "\e[1;2C", KBKEY_RIGHT, false, true },
|
||||
{ "\e[1;2D", KBKEY_LEFT, false, true },
|
||||
{ "\e[1;2F", KBKEY_END, false, true },
|
||||
{ "\e[1;2H", KBKEY_HOME, false, true },
|
||||
{ "\e[1;2~", KBKEY_HOME, false, true },
|
||||
{ "\e[1;5A", KBKEY_UP, true, false },
|
||||
{ "\e[1;5B", KBKEY_DOWN, true, false },
|
||||
{ "\e[1;5C", KBKEY_RIGHT, true, false },
|
||||
{ "\e[1;5D", KBKEY_LEFT, true, false },
|
||||
{ "\e[1;5F", KBKEY_END, true, false },
|
||||
{ "\e[1;5H", KBKEY_HOME, true, false },
|
||||
{ "\e[1;5~", KBKEY_HOME, true, false },
|
||||
{ "\e[1;6A", KBKEY_UP, true, true },
|
||||
{ "\e[1;6B", KBKEY_DOWN, true, true },
|
||||
{ "\e[1;6C", KBKEY_RIGHT, true, true },
|
||||
{ "\e[1;6D", KBKEY_LEFT, true, true },
|
||||
{ "\e[1;6F", KBKEY_END, true, true },
|
||||
{ "\e[1;6H", KBKEY_HOME, true, true },
|
||||
{ "\e[1;6~", KBKEY_HOME, true, true },
|
||||
{ "\e[1~", KBKEY_HOME, false, false },
|
||||
{ "\e[3;2~", KBKEY_DELETE, false, true },
|
||||
{ "\e[3;5~", KBKEY_DELETE, true, false },
|
||||
{ "\e[3;6~", KBKEY_DELETE, true, true },
|
||||
{ "\e[3~", KBKEY_DELETE, false, false },
|
||||
{ "\e[4;2~", KBKEY_END, false, true },
|
||||
{ "\e[4;5~", KBKEY_END, true, false },
|
||||
{ "\e[4;6~", KBKEY_END, true, true },
|
||||
{ "\e[4~", KBKEY_END, false, false },
|
||||
{ "\e[5;2~", KBKEY_PGUP, false, true },
|
||||
{ "\e[5;5~", KBKEY_PGUP, true, false },
|
||||
{ "\e[5;6~", KBKEY_PGUP, true, true },
|
||||
{ "\e[5~", KBKEY_PGUP, false, false },
|
||||
{ "\e[6;2~", KBKEY_PGDOWN, false, true },
|
||||
{ "\e[6;5~", KBKEY_PGDOWN, true, false },
|
||||
{ "\e[6;6~", KBKEY_PGDOWN, true, true },
|
||||
{ "\e[6~", KBKEY_PGDOWN, false, false },
|
||||
{ "\e[A", KBKEY_UP, false, false },
|
||||
{ "\e[B", KBKEY_DOWN, false, false },
|
||||
{ "\e[C", KBKEY_RIGHT, false, false },
|
||||
{ "\e[D", KBKEY_LEFT, false, false },
|
||||
{ "\e[F", KBKEY_END, false, false },
|
||||
{ "\e[H", KBKEY_HOME, false, false },
|
||||
{ "\e:", KBKEY_ESC, false, false },
|
||||
{ "\eOF", KBKEY_END, false, false },
|
||||
{ "\eOH", KBKEY_HOME, false, false },
|
||||
{ "\x7F", KBKEY_BKSPC, false, false },
|
||||
};
|
||||
|
||||
void editor_codepoint(struct editor* editor, uint32_t codepoint)
|
||||
{
|
||||
wchar_t c = (wchar_t) codepoint;
|
||||
|
@ -43,7 +112,6 @@ void editor_codepoint(struct editor* editor, uint32_t codepoint)
|
|||
editor_modal_character(editor, c);
|
||||
}
|
||||
|
||||
#if defined(__sortix__)
|
||||
void editor_type_kbkey(struct editor* editor, int kbkey)
|
||||
{
|
||||
if ( kbkey < 0 )
|
||||
|
@ -131,67 +199,232 @@ void editor_modal_kbkey(struct editor* editor, int kbkey)
|
|||
|
||||
void editor_kbkey(struct editor* editor, int kbkey)
|
||||
{
|
||||
int abskbkey = kbkey < 0 ? -kbkey : kbkey;
|
||||
|
||||
if ( abskbkey == KBKEY_LCTRL )
|
||||
{
|
||||
editor->control = 0 <= kbkey;
|
||||
return;
|
||||
}
|
||||
if ( abskbkey == KBKEY_LSHIFT )
|
||||
{
|
||||
editor->lshift = 0 <= kbkey;
|
||||
editor->shift = editor->lshift || editor->rshift;
|
||||
return;
|
||||
}
|
||||
if ( abskbkey == KBKEY_RSHIFT )
|
||||
{
|
||||
editor->rshift = 0 <= kbkey;
|
||||
editor->shift = editor->lshift || editor->rshift;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( editor->mode == MODE_EDIT )
|
||||
editor_type_kbkey(editor, kbkey);
|
||||
else
|
||||
editor_modal_kbkey(editor, kbkey);
|
||||
}
|
||||
|
||||
void editor_emulate_kbkey(struct editor* editor,
|
||||
int kbkey,
|
||||
bool control,
|
||||
bool shift)
|
||||
{
|
||||
editor->control = control;
|
||||
editor->lshift = shift;
|
||||
editor->rshift = false;
|
||||
editor->shift = shift;
|
||||
|
||||
editor_kbkey(editor, kbkey);
|
||||
editor_kbkey(editor, -kbkey);
|
||||
|
||||
editor->control = false;
|
||||
editor->lshift = false;
|
||||
editor->rshift = false;
|
||||
editor->shift = false;
|
||||
}
|
||||
|
||||
void editor_emulate_control_letter(struct editor* editor, uint32_t c)
|
||||
{
|
||||
#if !defined(__sortix__)
|
||||
if ( c == 'Z' )
|
||||
{
|
||||
raise(SIGSTOP);
|
||||
}
|
||||
#endif
|
||||
|
||||
editor->control = true;
|
||||
editor_codepoint(editor, c);
|
||||
editor->control = false;
|
||||
}
|
||||
|
||||
void editor_input_begin(struct editor_input* editor_input)
|
||||
{
|
||||
#if defined(__sortix__)
|
||||
gettermmode(0, &editor_input->saved_termmode);
|
||||
settermmode(0, TERMMODE_KBKEY | TERMMODE_UNICODE);
|
||||
#else
|
||||
(void) editor_input;
|
||||
#endif
|
||||
memset(editor_input, 0, sizeof(*editor_input));
|
||||
|
||||
tcgetattr(0, &editor_input->saved_termios);
|
||||
struct termios tcattr;
|
||||
memcpy(&tcattr, &editor_input->saved_termios, sizeof(struct termios));
|
||||
tcattr.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
|
||||
tcattr.c_iflag |= ICRNL;
|
||||
tcattr.c_cc[VMIN] = 1;
|
||||
tcattr.c_cc[VTIME] = 0;
|
||||
tcsetattr(0, TCSADRAIN, &tcattr);
|
||||
if ( getenv("TERM") && strcmp(getenv("TERM"), "sortix") != 0 )
|
||||
{
|
||||
printf("\e[?1049h");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void editor_input_process(struct editor_input* editor_input,
|
||||
struct editor* editor)
|
||||
{
|
||||
#if defined(__sortix__)
|
||||
(void) editor_input;
|
||||
uint32_t input;
|
||||
if ( read(0, &input, sizeof(input)) != sizeof(input) )
|
||||
return;
|
||||
int kbkey;
|
||||
if ( (kbkey = KBKEY_DECODE(input)) )
|
||||
editor_kbkey(editor, kbkey);
|
||||
bool was_ambiguous_escape = editor_input->ambiguous_escape;
|
||||
editor_input->ambiguous_escape = false;
|
||||
|
||||
if ( was_ambiguous_escape )
|
||||
fcntl(0, F_SETFL, fcntl(0, F_GETFL, (void*) NULL) | O_NONBLOCK);
|
||||
|
||||
unsigned char uc;
|
||||
ssize_t amount_read = read(0, &uc, sizeof(uc));
|
||||
|
||||
if ( was_ambiguous_escape )
|
||||
fcntl(0, F_SETFL, fcntl(0, F_GETFL, (void*) NULL) &~ O_NONBLOCK);
|
||||
|
||||
if ( amount_read != sizeof(uc) )
|
||||
{
|
||||
if ( was_ambiguous_escape &&
|
||||
(errno == EWOULDBLOCK || errno == EAGAIN) )
|
||||
uc = ':';
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ( 1 <= uc && uc <= 26 )
|
||||
fprintf(stderr, "Input: ^%c\n", 'A' + uc - 1);
|
||||
else if ( uc == '\e' )
|
||||
fprintf(stderr, "Input: ^[\n");
|
||||
else
|
||||
editor_codepoint(editor, input);
|
||||
#else
|
||||
(void) editor_input;
|
||||
(void) editor;
|
||||
fprintf(stderr, "Input: '%c'\n", uc);
|
||||
#endif
|
||||
#if 0
|
||||
fputc(uc, stderr);
|
||||
#endif
|
||||
|
||||
if ( editor_input->termseq_used < MAX_TERMSEQ_SIZE )
|
||||
editor_input->termseq[editor_input->termseq_used++] = (char) uc;
|
||||
|
||||
size_t num_seqs = sizeof(terminal_sequences) / sizeof(terminal_sequences[0]);
|
||||
|
||||
while ( editor_input->termseq_seen < editor_input->termseq_used )
|
||||
{
|
||||
size_t match = 0;
|
||||
size_t match_size = 0;
|
||||
bool full_match = false;
|
||||
bool partial_match = false;
|
||||
|
||||
for ( size_t i = 0; i < num_seqs; i++ )
|
||||
{
|
||||
struct terminal_sequence* terminal_sequence = &terminal_sequences[i];
|
||||
const char* sequence = terminal_sequence->sequence;
|
||||
|
||||
bool potential_partial_match = false;
|
||||
for ( size_t n = 0; n < editor_input->termseq_used; n++ )
|
||||
{
|
||||
if ( sequence[n] != editor_input->termseq[n] )
|
||||
{
|
||||
potential_partial_match = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( sequence[n+1] == '\0' )
|
||||
{
|
||||
potential_partial_match = false;
|
||||
full_match = true;
|
||||
match = i;
|
||||
match_size = n + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
potential_partial_match = true;
|
||||
}
|
||||
|
||||
if ( potential_partial_match )
|
||||
partial_match = true;
|
||||
}
|
||||
|
||||
if ( full_match )
|
||||
{
|
||||
editor_emulate_kbkey(editor,
|
||||
terminal_sequences[match].kbkey,
|
||||
terminal_sequences[match].control,
|
||||
terminal_sequences[match].shift);
|
||||
memmove(editor_input->termseq,
|
||||
editor_input->termseq + match_size,
|
||||
editor_input->termseq_used - match_size);
|
||||
editor_input->termseq_used -= match_size;
|
||||
editor_input->termseq_seen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( partial_match )
|
||||
{
|
||||
editor_input->termseq_seen = editor_input->termseq_used;
|
||||
|
||||
// HACK: We can't reliably tell an actual escape press apart from
|
||||
// the beginning of an escape sequence. However, we could use
|
||||
// timing to get close to the truth, through the assumption
|
||||
// that a following non-blocking read will fail only if this
|
||||
// was a single escape press.
|
||||
if ( editor_input->termseq_used == 1 &&
|
||||
editor_input->termseq[0] == '\e' )
|
||||
{
|
||||
editor_input->ambiguous_escape = true;
|
||||
return editor_input_process(editor_input, editor);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
char input = editor_input->termseq[0];
|
||||
|
||||
if ( 1 <= input && input <= 26 && input != '\t' && input != '\n' )
|
||||
{
|
||||
editor_emulate_control_letter(editor, L'A' + input - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t wc;
|
||||
size_t amount = mbrtowc(&wc, &input, 1, &editor_input->ps);
|
||||
if ( amount == (size_t) -1 )
|
||||
memset(&editor_input->ps, 0, sizeof(editor_input->ps));
|
||||
if ( amount == (size_t) 1 )
|
||||
editor_codepoint(editor, (uint32_t) wc);
|
||||
}
|
||||
|
||||
memmove(editor_input->termseq,
|
||||
editor_input->termseq + 1,
|
||||
editor_input->termseq_used - 1);
|
||||
editor_input->termseq_used--;
|
||||
editor_input->termseq_seen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void editor_input_end(struct editor_input* editor_input)
|
||||
{
|
||||
#if defined(__sortix__)
|
||||
settermmode(0, editor_input->saved_termmode);
|
||||
#else
|
||||
if ( getenv("TERM") && strcmp(getenv("TERM"), "sortix") != 0 )
|
||||
{
|
||||
printf("\e[?1049l");
|
||||
fflush(stdout);
|
||||
}
|
||||
tcsetattr(0, TCSADRAIN, &editor_input->saved_termios);
|
||||
}
|
||||
|
||||
void editor_input_suspend(struct editor_input* editor_input)
|
||||
{
|
||||
(void) editor_input;
|
||||
|
||||
#if !defined(__sortix__)
|
||||
struct termios current_termios;
|
||||
|
||||
if ( getenv("TERM") && strcmp(getenv("TERM"), "sortix") != 0 )
|
||||
{
|
||||
printf("\e[?1049l");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
tcgetattr(0, ¤t_termios);
|
||||
|
||||
raise(SIGSTOP);
|
||||
|
||||
tcsetattr(0, TCSADRAIN, ¤t_termios);
|
||||
|
||||
if ( getenv("TERM") && strcmp(getenv("TERM"), "sortix") != 0 )
|
||||
{
|
||||
printf("\e[?1049h");
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -20,18 +20,41 @@
|
|||
#ifndef EDITOR_INPUT_H
|
||||
#define EDITOR_INPUT_H
|
||||
|
||||
#include <termios.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#if !defined(__sortix__)
|
||||
#define KBKEY_ESC 0x01
|
||||
#define KBKEY_BKSPC 0x0E
|
||||
#define KBKEY_HOME (0x80 + 0x47)
|
||||
#define KBKEY_UP (0x80 + 0x48)
|
||||
#define KBKEY_PGUP (0x80 + 0x49)
|
||||
#define KBKEY_LEFT (0x80 + 0x4B)
|
||||
#define KBKEY_RIGHT (0x80 + 0x4D)
|
||||
#define KBKEY_END (0x80 + 0x4F)
|
||||
#define KBKEY_DOWN (0x80 + 0x50)
|
||||
#define KBKEY_PGDOWN (0x80 + 0x51)
|
||||
#define KBKEY_DELETE (0x80 + 0x53)
|
||||
#endif
|
||||
|
||||
struct editor;
|
||||
|
||||
#define MAX_TERMSEQ_SIZE 16
|
||||
|
||||
struct editor_input
|
||||
{
|
||||
#if defined(__sortix__)
|
||||
unsigned int saved_termmode;
|
||||
#endif
|
||||
struct termios saved_termios;
|
||||
mbstate_t ps;
|
||||
char termseq[MAX_TERMSEQ_SIZE];
|
||||
size_t termseq_used;
|
||||
size_t termseq_seen;
|
||||
bool ambiguous_escape;
|
||||
};
|
||||
|
||||
void editor_input_begin(struct editor_input* editor_input);
|
||||
void editor_input_process(struct editor_input* editor_input,
|
||||
struct editor* editor);
|
||||
void editor_input_end(struct editor_input* editor_input);
|
||||
void editor_input_suspend(struct editor_input* editor_input);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,6 +17,8 @@
|
|||
* Terminal handling.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -37,9 +39,19 @@ void update_terminal_color(FILE* fp, uint8_t desired_color,
|
|||
uint8_t current_fg = (current->color >> 0) % 16;
|
||||
uint8_t current_bg = (current->color >> 4) % 16;
|
||||
if ( desired_fg != current_fg )
|
||||
fprintf(fp, "\e[%im", desired_fg + (desired_fg < 8 ? 30 : 90-8) );
|
||||
{
|
||||
if ( desired_fg == 7 )
|
||||
fprintf(fp, "\e[39m");
|
||||
else
|
||||
fprintf(fp, "\e[%im", desired_fg + (desired_fg < 8 ? 30 : 90-8));
|
||||
}
|
||||
if ( desired_bg != current_bg )
|
||||
fprintf(fp, "\e[%im", desired_bg + (desired_bg < 8 ? 40 : 100-8) );
|
||||
{
|
||||
if ( desired_bg == 0 ) // Transparent background colors and such.
|
||||
fprintf(fp, "\e[49m");
|
||||
else
|
||||
fprintf(fp, "\e[%im", desired_bg + (desired_bg < 8 ? 40 : 100-8));
|
||||
}
|
||||
current->color = desired_color;
|
||||
}
|
||||
|
||||
|
@ -109,7 +121,7 @@ void make_terminal_state(FILE* fp, struct terminal_state* state)
|
|||
memset(state, 0, sizeof(*state));
|
||||
|
||||
struct winsize terminal_size;
|
||||
tcgetwinsize(fileno(fp), &terminal_size);
|
||||
ioctl(fileno(fp), TIOCGWINSZ, &terminal_size);
|
||||
state->width = (int) terminal_size.ws_col;
|
||||
state->height = (int) terminal_size.ws_row;
|
||||
size_t data_length = state->width * state->height;
|
||||
|
|
Loading…
Reference in a new issue