1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
terminal_state : struct {
size : ivec2;
cursor := ivec2.{-1, -1}; // {-1, -1} if cursor hidden
last_mode : Graphics_Mode;
}
update_terminal_size :: () {
TIOCGWINSZ :: 0x5413;
winsize : struct {
ws_row, ws_col, ws_xpixel, ws_ypixel : u16;
}
ioctl(0, TIOCGWINSZ, *winsize);
terminal_state.size = .{xx winsize.ws_col, xx winsize.ws_row};
}
ks_init :: () {
#if OS == .LINUX {
__old_logger = context.logger;
context.logger = file_logger;
ks_write("\e[?25l"); // hide cursor
ks_write("\e7"); // save cursor position
ks_write("\e[?1047h"); // switch screen
ks_write("\e[?30l"); // hide scrollbar
ks_write("\e[H"); // move to top left corner
ks_write("\e[0m"); // set default mode
ks_write("\e[2J"); // clear screen
{
tcgetattr(STDIN_FILENO, *__term);
term_new := __term;
term_new.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
term_new.c_oflag &= 0xFFFFFFFE;// ~OPOST;
term_new.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
term_new.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB);
term_new.c_cflag |= 0x00000030;
tcsetattr(STDIN_FILENO, 0, *term_new);
}
update_terminal_size();
} else {
assert(false, "procedure call on unsupported OS\n");
}
}
ks_terminate :: () {
#if OS == .LINUX {
tcsetattr(STDIN_FILENO, 0, *__term); // return echo
ks_write("\e[?47l"); // restore screen
ks_write("\e8"); // restore cursor
ks_write("\e[?25h"); // show cursor
ks_write("\e[?30h"); // show scrollbar
terminal_state = .{};
context.logger = __old_logger;
} else {
assert(false, "procedure call on unsupported OS\n");
}
}
use_ks_curses :: () #expand {
ks_init();
`defer {
ks_terminate();
}
}
use_default_winch_handler :: () #expand {
init_default_winch_handler();
`defer deinit_default_winch_handler();
}
init_default_winch_handler :: () {
#if OS == .LINUX {
act := sigaction_t.{
sa_handler = (sig : s32) #c_call {
new_context: Context;
push_context new_context {
update_terminal_size();
}
},
sa_mask = sigset_t.{__val[0] = SIGWINCH}
};
sigaction(SIGWINCH, *act, null);
} else {
assert(false, "procedure call on unsupported OS\n");
}
}
deinit_default_winch_handler :: () {
#if OS == .LINUX {
sa : sigaction_t;
sa.sa_handler = SIG_DFL;
sigaction(SIGWINCH, null, *sa);
} else {
}
}
#scope_file
__old_logger : type_of(context.logger);
#if OS == .LINUX {
__term : My_Termios;
My_Termios :: struct {
c_iflag : u32;
c_oflag : u32;
c_cflag : u32;
c_lflag : u32;
unknown_pad : u8;
c_cc : [32]u8;
c_ispeed : u32;
c_ospeed : u32;
}
libc :: #system_library "libc";
tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *My_Termios) -> s32 #foreign libc;
tcgetattr :: (fd : s32, termios_p : *My_Termios) -> s32 #foreign libc;
}
#import "File";
file_logger :: (message: string, data: *void, info: Log_Info) {
file, ok := file_open("log.txt",for_writing=true, keep_existing_content=true);
if !ok return;
file_write(*file, tprint("[%] %", calendar_to_string(to_calendar(current_time_consensus())), message));
file_close(*file);
}
|