Skip to content

Commit cc9eb4a

Browse files
committed
lol oops
1 parent 789c521 commit cc9eb4a

File tree

2 files changed

+379
-382
lines changed

2 files changed

+379
-382
lines changed

util/linenoise-win32.c

Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
2+
/* this code is not standalone
3+
* it is included into linenoise.c
4+
* for windows.
5+
* It is deliberately kept separate so that
6+
* applications that have no need for windows
7+
* support can omit this
8+
*/
9+
static DWORD orig_consolemode = 0;
10+
11+
static int flushOutput(struct current *current);
12+
static void outputNewline(struct current *current);
13+
14+
static void refreshStart(struct current *current)
15+
{
16+
(void)current;
17+
}
18+
19+
static void refreshEnd(struct current *current)
20+
{
21+
(void)current;
22+
}
23+
24+
static void refreshStartChars(struct current *current)
25+
{
26+
assert(current->output == NULL);
27+
/* We accumulate all output here */
28+
current->output = sb_alloc();
29+
#ifdef USE_UTF8
30+
current->ubuflen = 0;
31+
#endif
32+
}
33+
34+
static void refreshNewline(struct current *current)
35+
{
36+
DRL("<nl>");
37+
outputNewline(current);
38+
}
39+
40+
static void refreshEndChars(struct current *current)
41+
{
42+
assert(current->output);
43+
flushOutput(current);
44+
sb_free(current->output);
45+
current->output = NULL;
46+
}
47+
48+
static int enableRawMode(struct current *current) {
49+
DWORD n;
50+
INPUT_RECORD irec;
51+
52+
current->outh = GetStdHandle(STD_OUTPUT_HANDLE);
53+
current->inh = GetStdHandle(STD_INPUT_HANDLE);
54+
55+
if (!PeekConsoleInput(current->inh, &irec, 1, &n)) {
56+
return -1;
57+
}
58+
if (getWindowSize(current) != 0) {
59+
return -1;
60+
}
61+
if (GetConsoleMode(current->inh, &orig_consolemode)) {
62+
SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT);
63+
}
64+
#ifdef USE_UTF8
65+
/* XXX is this the right thing to do? */
66+
SetConsoleCP(65001);
67+
#endif
68+
return 0;
69+
}
70+
71+
static void disableRawMode(struct current *current)
72+
{
73+
SetConsoleMode(current->inh, orig_consolemode);
74+
}
75+
76+
void linenoiseClearScreen(void)
77+
{
78+
/* XXX: This is ugly. Should just have the caller pass a handle */
79+
struct current current;
80+
81+
current.outh = GetStdHandle(STD_OUTPUT_HANDLE);
82+
83+
if (getWindowSize(&current) == 0) {
84+
COORD topleft = { 0, 0 };
85+
DWORD n;
86+
87+
FillConsoleOutputCharacter(current.outh, ' ',
88+
current.cols * current.rows, topleft, &n);
89+
FillConsoleOutputAttribute(current.outh,
90+
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN,
91+
current.cols * current.rows, topleft, &n);
92+
SetConsoleCursorPosition(current.outh, topleft);
93+
}
94+
}
95+
96+
static void cursorToLeft(struct current *current)
97+
{
98+
COORD pos;
99+
DWORD n;
100+
101+
pos.X = 0;
102+
pos.Y = (SHORT)current->y;
103+
104+
FillConsoleOutputAttribute(current->outh,
105+
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n);
106+
current->x = 0;
107+
}
108+
109+
#ifdef USE_UTF8
110+
static void flush_ubuf(struct current *current)
111+
{
112+
COORD pos;
113+
DWORD nwritten;
114+
pos.Y = (SHORT)current->y;
115+
pos.X = (SHORT)current->x;
116+
SetConsoleCursorPosition(current->outh, pos);
117+
WriteConsoleW(current->outh, current->ubuf, current->ubuflen, &nwritten, 0);
118+
current->x += current->ubufcols;
119+
current->ubuflen = 0;
120+
current->ubufcols = 0;
121+
}
122+
123+
static void add_ubuf(struct current *current, int ch)
124+
{
125+
/* This code originally by: Author: Mark E. Davis, 1994. */
126+
static const int halfShift = 10; /* used for shifting by 10 bits */
127+
128+
static const DWORD halfBase = 0x0010000UL;
129+
static const DWORD halfMask = 0x3FFUL;
130+
131+
#define UNI_SUR_HIGH_START 0xD800
132+
#define UNI_SUR_HIGH_END 0xDBFF
133+
#define UNI_SUR_LOW_START 0xDC00
134+
#define UNI_SUR_LOW_END 0xDFFF
135+
136+
#define UNI_MAX_BMP 0x0000FFFF
137+
138+
if (ch > UNI_MAX_BMP) {
139+
/* convert from unicode to utf16 surrogate pairs
140+
* There is always space for one extra word in ubuf
141+
*/
142+
ch -= halfBase;
143+
current->ubuf[current->ubuflen++] = (WORD)((ch >> halfShift) + UNI_SUR_HIGH_START);
144+
current->ubuf[current->ubuflen++] = (WORD)((ch & halfMask) + UNI_SUR_LOW_START);
145+
}
146+
else {
147+
current->ubuf[current->ubuflen++] = ch;
148+
}
149+
current->ubufcols += utf8_width(ch);
150+
if (current->ubuflen >= UBUF_MAX_CHARS) {
151+
flush_ubuf(current);
152+
}
153+
}
154+
#endif
155+
156+
static int flushOutput(struct current *current)
157+
{
158+
const char *pt = sb_str(current->output);
159+
int len = sb_len(current->output);
160+
161+
#ifdef USE_UTF8
162+
/* convert utf8 in current->output into utf16 in current->ubuf
163+
*/
164+
while (len) {
165+
int ch;
166+
int n = utf8_tounicode(pt, &ch);
167+
168+
pt += n;
169+
len -= n;
170+
171+
add_ubuf(current, ch);
172+
}
173+
flush_ubuf(current);
174+
#else
175+
DWORD nwritten;
176+
COORD pos;
177+
178+
pos.Y = (SHORT)current->y;
179+
pos.X = (SHORT)current->x;
180+
181+
SetConsoleCursorPosition(current->outh, pos);
182+
WriteConsoleA(current->outh, pt, len, &nwritten, 0);
183+
184+
current->x += len;
185+
#endif
186+
187+
sb_clear(current->output);
188+
189+
return 0;
190+
}
191+
192+
static int outputChars(struct current *current, const char *buf, int len)
193+
{
194+
if (len < 0) {
195+
len = strlen(buf);
196+
}
197+
assert(current->output);
198+
199+
sb_append_len(current->output, buf, len);
200+
201+
return 0;
202+
}
203+
204+
static void outputNewline(struct current *current)
205+
{
206+
/* On the last row output a newline to force a scroll */
207+
if (current->y + 1 == current->rows) {
208+
outputChars(current, "\n", 1);
209+
}
210+
flushOutput(current);
211+
current->x = 0;
212+
current->y++;
213+
}
214+
215+
static void setOutputHighlight(struct current *current, const int *props, int nprops)
216+
{
217+
int colour = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
218+
int bold = 0;
219+
int reverse = 0;
220+
int i;
221+
222+
for (i = 0; i < nprops; i++) {
223+
switch (props[i]) {
224+
case 0:
225+
colour = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
226+
bold = 0;
227+
reverse = 0;
228+
break;
229+
case 1:
230+
bold = FOREGROUND_INTENSITY;
231+
break;
232+
case 7:
233+
reverse = 1;
234+
break;
235+
case 30:
236+
colour = 0;
237+
break;
238+
case 31:
239+
colour = FOREGROUND_RED;
240+
break;
241+
case 32:
242+
colour = FOREGROUND_GREEN;
243+
break;
244+
case 33:
245+
colour = FOREGROUND_RED | FOREGROUND_GREEN;
246+
break;
247+
case 34:
248+
colour = FOREGROUND_BLUE;
249+
break;
250+
case 35:
251+
colour = FOREGROUND_RED | FOREGROUND_BLUE;
252+
break;
253+
case 36:
254+
colour = FOREGROUND_BLUE | FOREGROUND_GREEN;
255+
break;
256+
case 37:
257+
colour = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
258+
break;
259+
}
260+
}
261+
262+
flushOutput(current);
263+
264+
if (reverse) {
265+
SetConsoleTextAttribute(current->outh, BACKGROUND_INTENSITY);
266+
}
267+
else {
268+
SetConsoleTextAttribute(current->outh, colour | bold);
269+
}
270+
}
271+
272+
static void eraseEol(struct current *current)
273+
{
274+
COORD pos;
275+
DWORD n;
276+
277+
pos.X = (SHORT) current->x;
278+
pos.Y = (SHORT) current->y;
279+
280+
FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n);
281+
}
282+
283+
static void setCursorXY(struct current *current)
284+
{
285+
COORD pos;
286+
287+
pos.X = (SHORT) current->x;
288+
pos.Y = (SHORT) current->y;
289+
290+
SetConsoleCursorPosition(current->outh, pos);
291+
}
292+
293+
294+
static void setCursorPos(struct current *current, int x)
295+
{
296+
current->x = x;
297+
setCursorXY(current);
298+
}
299+
300+
static void cursorUp(struct current *current, int n)
301+
{
302+
current->y -= n;
303+
setCursorXY(current);
304+
}
305+
306+
static void cursorDown(struct current *current, int n)
307+
{
308+
current->y += n;
309+
setCursorXY(current);
310+
}
311+
312+
static int fd_read(struct current *current)
313+
{
314+
while (1) {
315+
INPUT_RECORD irec;
316+
DWORD n;
317+
if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) {
318+
break;
319+
}
320+
if (!ReadConsoleInputW(current->inh, &irec, 1, &n)) {
321+
break;
322+
}
323+
if (irec.EventType == KEY_EVENT) {
324+
KEY_EVENT_RECORD *k = &irec.Event.KeyEvent;
325+
if (k->bKeyDown || k->wVirtualKeyCode == VK_MENU) {
326+
if (k->dwControlKeyState & ENHANCED_KEY) {
327+
switch (k->wVirtualKeyCode) {
328+
case VK_LEFT:
329+
return SPECIAL_LEFT;
330+
case VK_RIGHT:
331+
return SPECIAL_RIGHT;
332+
case VK_UP:
333+
return SPECIAL_UP;
334+
case VK_DOWN:
335+
return SPECIAL_DOWN;
336+
case VK_INSERT:
337+
return SPECIAL_INSERT;
338+
case VK_DELETE:
339+
return SPECIAL_DELETE;
340+
case VK_HOME:
341+
return SPECIAL_HOME;
342+
case VK_END:
343+
return SPECIAL_END;
344+
case VK_PRIOR:
345+
return SPECIAL_PAGE_UP;
346+
case VK_NEXT:
347+
return SPECIAL_PAGE_DOWN;
348+
case VK_RETURN:
349+
return k->uChar.UnicodeChar;
350+
}
351+
}
352+
/* Note that control characters are already translated in AsciiChar */
353+
else if (k->wVirtualKeyCode == VK_CONTROL)
354+
continue;
355+
else {
356+
return k->uChar.UnicodeChar;
357+
}
358+
}
359+
}
360+
}
361+
return -1;
362+
}
363+
364+
static int getWindowSize(struct current *current)
365+
{
366+
CONSOLE_SCREEN_BUFFER_INFO info;
367+
if (!GetConsoleScreenBufferInfo(current->outh, &info)) {
368+
return -1;
369+
}
370+
current->cols = info.dwSize.X;
371+
current->rows = info.dwSize.Y;
372+
if (current->cols <= 0 || current->rows <= 0) {
373+
current->cols = 80;
374+
return -1;
375+
}
376+
current->y = info.dwCursorPosition.Y;
377+
current->x = info.dwCursorPosition.X;
378+
return 0;
379+
}

0 commit comments

Comments
 (0)