bestliner 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3578 @@
1
+ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
2
+ │vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi│
3
+ ╞══════════════════════════════════════════════════════════════════════════════╡
4
+ │ │
5
+ │ Bestline ── Library for interactive pseudoteletypewriter command │
6
+ │ sessions using ANSI Standard X3.64 control sequences │
7
+ │ │
8
+ │ OVERVIEW │
9
+ │ │
10
+ │ Bestline is a fork of linenoise (a popular readline alternative) │
11
+ │ that fixes its bugs and adds the missing features while reducing │
12
+ │ binary footprint (surprisingly) by removing bloated dependencies │
13
+ │ which means you can finally have a permissively-licensed command │
14
+ │ prompt w/ a 30kb footprint that's nearly as good as gnu readline │
15
+ │ │
16
+ │ EXAMPLE │
17
+ │ │
18
+ │ main() { │
19
+ │ char *line; │
20
+ │ while ((line = bestlineWithHistory("IN> ", "foo"))) { │
21
+ │ fputs("OUT> ", stdout); │
22
+ │ fputs(line, stdout); │
23
+ │ fputs("\n", stdout); │
24
+ │ free(line); │
25
+ │ } │
26
+ │ } │
27
+ │ │
28
+ │ CHANGES │
29
+ │ │
30
+ │ - Remove bell │
31
+ │ - Add kill ring │
32
+ │ - Fix flickering │
33
+ │ - Add UTF-8 editing │
34
+ │ - Add CTRL-R search │
35
+ │ - Support unlimited lines │
36
+ │ - Add parentheses awareness │
37
+ │ - React to terminal resizing │
38
+ │ - Don't generate .data section │
39
+ │ - Support terminal flow control │
40
+ │ - Make history loading 10x faster │
41
+ │ - Make multiline mode the only mode │
42
+ │ - Accommodate O_NONBLOCK file descriptors │
43
+ │ - Restore raw mode on process foregrounding │
44
+ │ - Make source code compatible with C++ compilers │
45
+ │ - Fix corruption issues by using generalized parsing │
46
+ │ - Implement nearly all GNU readline editing shortcuts │
47
+ │ - Remove heavyweight dependencies like printf/sprintf │
48
+ │ - Remove ISIG→^C→EAGAIN hack and use ephemeral handlers │
49
+ │ - Support running on Windows in MinTTY or CMD.EXE on Win10+ │
50
+ │ - Support diacratics, русский, Ελληνικά, 中国人, 日本語, 한국인 │
51
+ │ │
52
+ │ SHORTCUTS │
53
+ │ │
54
+ │ CTRL-E END │
55
+ │ CTRL-A START │
56
+ │ CTRL-B BACK │
57
+ │ CTRL-F FORWARD │
58
+ │ CTRL-L CLEAR │
59
+ │ CTRL-H BACKSPACE │
60
+ │ CTRL-D DELETE │
61
+ │ CTRL-Y YANK │
62
+ │ CTRL-D EOF (IF EMPTY) │
63
+ │ CTRL-N NEXT HISTORY │
64
+ │ CTRL-P PREVIOUS HISTORY │
65
+ │ CTRL-R SEARCH HISTORY │
66
+ │ CTRL-G CANCEL SEARCH │
67
+ │ ALT-< BEGINNING OF HISTORY │
68
+ │ ALT-> END OF HISTORY │
69
+ │ ALT-F FORWARD WORD │
70
+ │ ALT-B BACKWARD WORD │
71
+ │ CTRL-ALT-F FORWARD EXPR │
72
+ │ CTRL-ALT-B BACKWARD EXPR │
73
+ │ ALT-RIGHT FORWARD EXPR │
74
+ │ ALT-LEFT BACKWARD EXPR │
75
+ │ ALT-SHIFT-B BARF EXPR │
76
+ │ ALT-SHIFT-S SLURP EXPR │
77
+ │ ALT-SHIFT-R RAISE EXPR │
78
+ │ CTRL-K KILL LINE FORWARDS │
79
+ │ CTRL-U KILL LINE BACKWARDS │
80
+ │ ALT-H KILL WORD BACKWARDS │
81
+ │ CTRL-W KILL WORD BACKWARDS │
82
+ │ CTRL-ALT-H KILL WORD BACKWARDS │
83
+ │ ALT-D KILL WORD FORWARDS │
84
+ │ ALT-Y ROTATE KILL RING AND YANK AGAIN │
85
+ │ ALT-\ SQUEEZE ADJACENT WHITESPACE │
86
+ │ CTRL-T TRANSPOSE │
87
+ │ ALT-T TRANSPOSE WORD │
88
+ │ ALT-U UPPERCASE WORD │
89
+ │ ALT-L LOWERCASE WORD │
90
+ │ ALT-C CAPITALIZE WORD │
91
+ │ CTRL-Z SUSPEND PROCESS │
92
+ │ CTRL-\ QUIT PROCESS │
93
+ │ CTRL-S PAUSE OUTPUT │
94
+ │ CTRL-Q UNPAUSE OUTPUT (IF PAUSED) │
95
+ │ CTRL-Q ESCAPED INSERT │
96
+ │ CTRL-SPACE SET MARK │
97
+ │ CTRL-X CTRL-X GOTO MARK │
98
+ │ PROTIP REMAP CAPS LOCK TO CTRL │
99
+ │ │
100
+ ╞══════════════════════════════════════════════════════════════════════════════╡
101
+ │ │
102
+ │ Copyright 2018-2021 Justine Tunney <jtunney@gmail.com> │
103
+ │ Copyright 2010-2016 Salvatore Sanfilippo <antirez@gmail.com> │
104
+ │ Copyright 2010-2013 Pieter Noordhuis <pcnoordhuis@gmail.com> │
105
+ │ │
106
+ │ All rights reserved. │
107
+ │ │
108
+ │ Redistribution and use in source and binary forms, with or without │
109
+ │ modification, are permitted provided that the following conditions are │
110
+ │ met: │
111
+ │ │
112
+ │ * Redistributions of source code must retain the above copyright │
113
+ │ notice, this list of conditions and the following disclaimer. │
114
+ │ │
115
+ │ * Redistributions in binary form must reproduce the above copyright │
116
+ │ notice, this list of conditions and the following disclaimer in the │
117
+ │ documentation and/or other materials provided with the distribution. │
118
+ │ │
119
+ │ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS │
120
+ │ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT │
121
+ │ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR │
122
+ │ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT │
123
+ │ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, │
124
+ │ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT │
125
+ │ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, │
126
+ │ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY │
127
+ │ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT │
128
+ │ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE │
129
+ │ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. │
130
+ │ │
131
+ ╚─────────────────────────────────────────────────────────────────────────────*/
132
+ #include "bestline.h"
133
+
134
+ #ifndef __COSMOPOLITAN__
135
+ #define _POSIX_C_SOURCE 1 /* so GCC builds in ANSI mode */
136
+ #define _XOPEN_SOURCE 700 /* so GCC builds in ANSI mode */
137
+ #define _DARWIN_C_SOURCE 1 /* so SIGWINCH / IUTF8 on XNU */
138
+ #include <termios.h>
139
+ #include <unistd.h>
140
+ #include <stdlib.h>
141
+ #include <stdio.h>
142
+ #include <errno.h>
143
+ #include <string.h>
144
+ #include <stdlib.h>
145
+ #include <ctype.h>
146
+ #include <sys/stat.h>
147
+ #include <sys/types.h>
148
+ #include <sys/ioctl.h>
149
+ #include <sys/mman.h>
150
+ #include <unistd.h>
151
+ #include <setjmp.h>
152
+ #include <poll.h>
153
+ #include <assert.h>
154
+ #include <signal.h>
155
+ #include <fcntl.h>
156
+ #include <limits.h>
157
+ #ifndef SIGWINCH
158
+ #define SIGWINCH 28 /* GNU/Systemd + XNU + FreeBSD + NetBSD + OpenBSD */
159
+ #endif
160
+ #ifndef IUTF8
161
+ #define IUTF8 0
162
+ #endif
163
+ #endif
164
+
165
+ __asm__(".ident\t\"\\n\\n\
166
+ Bestline (BSD-2)\\n\
167
+ Copyright 2018-2020 Justine Tunney <jtunney@gmail.com>\\n\
168
+ Copyright 2010-2016 Salvatore Sanfilippo <antirez@gmail.com>\\n\
169
+ Copyright 2010-2013 Pieter Noordhuis <pcnoordhuis@gmail.com>\"");
170
+
171
+ #ifndef BESTLINE_MAX_RING
172
+ #define BESTLINE_MAX_RING 8
173
+ #endif
174
+
175
+ #ifndef BESTLINE_MAX_HISTORY
176
+ #define BESTLINE_MAX_HISTORY 1024
177
+ #endif
178
+
179
+ #define BESTLINE_HISTORY_FIRST +BESTLINE_MAX_HISTORY
180
+ #define BESTLINE_HISTORY_PREV +1
181
+ #define BESTLINE_HISTORY_NEXT -1
182
+ #define BESTLINE_HISTORY_LAST -BESTLINE_MAX_HISTORY
183
+
184
+ #define Ctrl(C) ((C) ^ 0100)
185
+ #define Min(X, Y) ((Y) > (X) ? (X) : (Y))
186
+ #define Max(X, Y) ((Y) < (X) ? (X) : (Y))
187
+ #define Case(X, Y) case X: Y; break
188
+ #define Read16le(X) \
189
+ ((255 & (X)[0]) << 000 | \
190
+ (255 & (X)[1]) << 010)
191
+ #define Read32le(X) \
192
+ ((unsigned)(255 & (X)[0]) << 000 | \
193
+ (unsigned)(255 & (X)[1]) << 010 | \
194
+ (unsigned)(255 & (X)[2]) << 020 | \
195
+ (unsigned)(255 & (X)[3]) << 030)
196
+
197
+ struct abuf {
198
+ char *b;
199
+ unsigned len;
200
+ unsigned cap;
201
+ };
202
+
203
+ struct rune {
204
+ unsigned c;
205
+ unsigned n;
206
+ };
207
+
208
+ struct bestlineRing {
209
+ unsigned i;
210
+ char *p[BESTLINE_MAX_RING];
211
+ };
212
+
213
+ /* The bestlineState structure represents the state during line editing.
214
+ * We pass this state to functions implementing specific editing
215
+ * functionalities. */
216
+ struct bestlineState {
217
+ int ifd; /* terminal stdin file descriptor */
218
+ int ofd; /* terminal stdout file descriptor */
219
+ struct winsize ws; /* rows and columns in terminal */
220
+ char *buf; /* edited line buffer */
221
+ const char *prompt; /* prompt to display */
222
+ int hindex; /* history index */
223
+ int rows; /* rows being used */
224
+ int oldpos; /* previous refresh cursor position */
225
+ unsigned buflen; /* edited line buffer size */
226
+ unsigned pos; /* current buffer index */
227
+ unsigned len; /* current edited line length */
228
+ unsigned mark; /* saved cursor position */
229
+ unsigned yi, yj; /* boundaries of last yank */
230
+ char seq[2][16]; /* keystroke history for yanking code */
231
+ char final; /* set to true on last update */
232
+ char dirty; /* if an update was squashed */
233
+ };
234
+
235
+ static const char *const kUnsupported[] = {"dumb","cons25","emacs"};
236
+
237
+ static int gotint;
238
+ static int gotcont;
239
+ static int gotwinch;
240
+ static signed char rawmode;
241
+ static char maskmode;
242
+ static char ispaused;
243
+ static char iscapital;
244
+ static unsigned historylen;
245
+ static struct bestlineRing ring;
246
+ static struct sigaction orig_cont;
247
+ static struct sigaction orig_winch;
248
+ static struct termios orig_termios;
249
+ static char *history[BESTLINE_MAX_HISTORY];
250
+ static bestlineXlatCallback *xlatCallback;
251
+ static bestlineHintsCallback *hintsCallback;
252
+ static bestlineFreeHintsCallback *freeHintsCallback;
253
+ static bestlineCompletionCallback *completionCallback;
254
+
255
+ static void bestlineAtExit(void);
256
+ static void bestlineRefreshLine(struct bestlineState *);
257
+
258
+ static void bestlineOnInt(int sig) {
259
+ gotint = sig;
260
+ }
261
+
262
+ static void bestlineOnCont(int sig) {
263
+ gotcont = sig;
264
+ }
265
+
266
+ static void bestlineOnWinch(int sig) {
267
+ gotwinch = sig;
268
+ }
269
+
270
+ static char IsControl(unsigned c) {
271
+ return c <= 0x1F || (0x7F <= c && c <= 0x9F);
272
+ }
273
+
274
+ static int GetMonospaceCharacterWidth(unsigned c) {
275
+ return !IsControl(c)
276
+ + (c >= 0x1100 &&
277
+ (c <= 0x115f || c == 0x2329 || c == 0x232a ||
278
+ (c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) ||
279
+ (c >= 0xac00 && c <= 0xd7a3) ||
280
+ (c >= 0xf900 && c <= 0xfaff) ||
281
+ (c >= 0xfe10 && c <= 0xfe19) ||
282
+ (c >= 0xfe30 && c <= 0xfe6f) ||
283
+ (c >= 0xff00 && c <= 0xff60) ||
284
+ (c >= 0xffe0 && c <= 0xffe6) ||
285
+ (c >= 0x20000 && c <= 0x2fffd) ||
286
+ (c >= 0x30000 && c <= 0x3fffd)));
287
+ }
288
+
289
+ /**
290
+ * Returns nonzero if 𝑐 isn't alphanumeric.
291
+ *
292
+ * Line reading interfaces generally define this operation as UNICODE
293
+ * characters that aren't in the letter category (Lu, Ll, Lt, Lm, Lo)
294
+ * and aren't in the number categorie (Nd, Nl, No). We also add a few
295
+ * other things like blocks and emoji (So).
296
+ */
297
+ char bestlineIsSeparator(unsigned c) {
298
+ int m, l, r, n;
299
+ if (c < 0200) {
300
+ return !(('0' <= c && c <= '9') ||
301
+ ('A' <= c && c <= 'Z') ||
302
+ ('a' <= c && c <= 'z'));
303
+ }
304
+ if (c <= 0xffff) {
305
+ static const unsigned short kGlyphs[][2] = {
306
+ {0x00aa, 0x00aa}, /* 1x English */
307
+ {0x00b2, 0x00b3}, /* 2x English Arabic */
308
+ {0x00b5, 0x00b5}, /* 1x Greek */
309
+ {0x00b9, 0x00ba}, /* 2x English Arabic */
310
+ {0x00bc, 0x00be}, /* 3x Vulgar English Arabic */
311
+ {0x00c0, 0x00d6}, /* 23x Watin */
312
+ {0x00d8, 0x00f6}, /* 31x Watin */
313
+ {0x0100, 0x02c1}, /* 450x Watin-AB,IPA,Spacemod */
314
+ {0x02c6, 0x02d1}, /* 12x Spacemod */
315
+ {0x02e0, 0x02e4}, /* 5x Spacemod */
316
+ {0x02ec, 0x02ec}, /* 1x Spacemod */
317
+ {0x02ee, 0x02ee}, /* 1x Spacemod */
318
+ {0x0370, 0x0374}, /* 5x Greek */
319
+ {0x0376, 0x0377}, /* 2x Greek */
320
+ {0x037a, 0x037d}, /* 4x Greek */
321
+ {0x037f, 0x037f}, /* 1x Greek */
322
+ {0x0386, 0x0386}, /* 1x Greek */
323
+ {0x0388, 0x038a}, /* 3x Greek */
324
+ {0x038c, 0x038c}, /* 1x Greek */
325
+ {0x038e, 0x03a1}, /* 20x Greek */
326
+ {0x03a3, 0x03f5}, /* 83x Greek */
327
+ {0x03f7, 0x0481}, /* 139x Greek */
328
+ {0x048a, 0x052f}, /* 166x Cyrillic */
329
+ {0x0531, 0x0556}, /* 38x Armenian */
330
+ {0x0560, 0x0588}, /* 41x Armenian */
331
+ {0x05d0, 0x05ea}, /* 27x Hebrew */
332
+ {0x0620, 0x064a}, /* 43x Arabic */
333
+ {0x0660, 0x0669}, /* 10x Arabic */
334
+ {0x0671, 0x06d3}, /* 99x Arabic */
335
+ {0x06ee, 0x06fc}, /* 15x Arabic */
336
+ {0x0712, 0x072f}, /* 30x Syriac */
337
+ {0x074d, 0x07a5}, /* 89x Syriac,Arabic2,Thaana */
338
+ {0x07c0, 0x07ea}, /* 43x NKo */
339
+ {0x0800, 0x0815}, /* 22x Samaritan */
340
+ {0x0840, 0x0858}, /* 25x Mandaic */
341
+ {0x0904, 0x0939}, /* 54x Devanagari */
342
+ {0x0993, 0x09a8}, /* 22x Bengali */
343
+ {0x09e6, 0x09f1}, /* 12x Bengali */
344
+ {0x0a13, 0x0a28}, /* 22x Gurmukhi */
345
+ {0x0a66, 0x0a6f}, /* 10x Gurmukhi */
346
+ {0x0a93, 0x0aa8}, /* 22x Gujarati */
347
+ {0x0b13, 0x0b28}, /* 22x Oriya */
348
+ {0x0c92, 0x0ca8}, /* 23x Kannada */
349
+ {0x0caa, 0x0cb3}, /* 10x Kannada */
350
+ {0x0ce6, 0x0cef}, /* 10x Kannada */
351
+ {0x0d12, 0x0d3a}, /* 41x Malayalam */
352
+ {0x0d85, 0x0d96}, /* 18x Sinhala */
353
+ {0x0d9a, 0x0db1}, /* 24x Sinhala */
354
+ {0x0de6, 0x0def}, /* 10x Sinhala */
355
+ {0x0e01, 0x0e30}, /* 48x Thai */
356
+ {0x0e8c, 0x0ea3}, /* 24x Lao */
357
+ {0x0f20, 0x0f33}, /* 20x Tibetan */
358
+ {0x0f49, 0x0f6c}, /* 36x Tibetan */
359
+ {0x109e, 0x10c5}, /* 40x Myanmar,Georgian */
360
+ {0x10d0, 0x10fa}, /* 43x Georgian */
361
+ {0x10fc, 0x1248}, /* 333x Georgian,Hangul,Ethiopic */
362
+ {0x13a0, 0x13f5}, /* 86x Cherokee */
363
+ {0x1401, 0x166d}, /* 621x Aboriginal */
364
+ {0x16a0, 0x16ea}, /* 75x Runic */
365
+ {0x1700, 0x170c}, /* 13x Tagalog */
366
+ {0x1780, 0x17b3}, /* 52x Khmer */
367
+ {0x1820, 0x1878}, /* 89x Mongolian */
368
+ {0x1a00, 0x1a16}, /* 23x Buginese */
369
+ {0x1a20, 0x1a54}, /* 53x Tai Tham */
370
+ {0x1a80, 0x1a89}, /* 10x Tai Tham */
371
+ {0x1a90, 0x1a99}, /* 10x Tai Tham */
372
+ {0x1b05, 0x1b33}, /* 47x Balinese */
373
+ {0x1b50, 0x1b59}, /* 10x Balinese */
374
+ {0x1b83, 0x1ba0}, /* 30x Sundanese */
375
+ {0x1bae, 0x1be5}, /* 56x Sundanese */
376
+ {0x1c90, 0x1cba}, /* 43x Georgian2 */
377
+ {0x1cbd, 0x1cbf}, /* 3x Georgian2 */
378
+ {0x1e00, 0x1f15}, /* 278x Watin-C,Greek2 */
379
+ {0x2070, 0x2071}, /* 2x Supersub */
380
+ {0x2074, 0x2079}, /* 6x Supersub */
381
+ {0x207f, 0x2089}, /* 11x Supersub */
382
+ {0x2090, 0x209c}, /* 13x Supersub */
383
+ {0x2100, 0x2117}, /* 24x Letterlike */
384
+ {0x2119, 0x213f}, /* 39x Letterlike */
385
+ {0x2145, 0x214a}, /* 6x Letterlike */
386
+ {0x214c, 0x218b}, /* 64x Letterlike,Numbery */
387
+ {0x21af, 0x21cd}, /* 31x Arrows */
388
+ {0x21d5, 0x21f3}, /* 31x Arrows */
389
+ {0x230c, 0x231f}, /* 20x Technical */
390
+ {0x232b, 0x237b}, /* 81x Technical */
391
+ {0x237d, 0x239a}, /* 30x Technical */
392
+ {0x23b4, 0x23db}, /* 40x Technical */
393
+ {0x23e2, 0x2426}, /* 69x Technical,ControlPictures */
394
+ {0x2460, 0x25b6}, /* 343x Enclosed,Boxes,Blocks,Shapes */
395
+ {0x25c2, 0x25f7}, /* 54x Shapes */
396
+ {0x2600, 0x266e}, /* 111x Symbols */
397
+ {0x2670, 0x2767}, /* 248x Symbols,Dingbats */
398
+ {0x2776, 0x27bf}, /* 74x Dingbats */
399
+ {0x2800, 0x28ff}, /* 256x Braille */
400
+ {0x2c00, 0x2c2e}, /* 47x Glagolitic */
401
+ {0x2c30, 0x2c5e}, /* 47x Glagolitic */
402
+ {0x2c60, 0x2ce4}, /* 133x Watin-D */
403
+ {0x2d00, 0x2d25}, /* 38x Georgian2 */
404
+ {0x2d30, 0x2d67}, /* 56x Tifinagh */
405
+ {0x2d80, 0x2d96}, /* 23x Ethiopic2 */
406
+ {0x2e2f, 0x2e2f}, /* 1x Punctuation2 */
407
+ {0x3005, 0x3007}, /* 3x CJK Symbols & Punctuation */
408
+ {0x3021, 0x3029}, /* 9x CJK Symbols & Punctuation */
409
+ {0x3031, 0x3035}, /* 5x CJK Symbols & Punctuation */
410
+ {0x3038, 0x303c}, /* 5x CJK Symbols & Punctuation */
411
+ {0x3041, 0x3096}, /* 86x Hiragana */
412
+ {0x30a1, 0x30fa}, /* 90x Katakana */
413
+ {0x3105, 0x312f}, /* 43x Bopomofo */
414
+ {0x3131, 0x318e}, /* 94x Hangul Compatibility Jamo */
415
+ {0x31a0, 0x31ba}, /* 27x Bopomofo Extended */
416
+ {0x31f0, 0x31ff}, /* 16x Katakana Phonetic Extensions */
417
+ {0x3220, 0x3229}, /* 10x Enclosed CJK Letters & Months */
418
+ {0x3248, 0x324f}, /* 8x Enclosed CJK Letters & Months */
419
+ {0x3251, 0x325f}, /* 15x Enclosed CJK Letters & Months */
420
+ {0x3280, 0x3289}, /* 10x Enclosed CJK Letters & Months */
421
+ {0x32b1, 0x32bf}, /* 15x Enclosed CJK Letters & Months */
422
+ {0x3400, 0x4db5}, /* 6582x CJK Unified Ideographs Extension A */
423
+ {0x4dc0, 0x9fef}, /* 21040x Yijing Hexagram, CJK Unified Ideographs */
424
+ {0xa000, 0xa48c}, /* 1165x Yi Syllables */
425
+ {0xa4d0, 0xa4fd}, /* 46x Lisu */
426
+ {0xa500, 0xa60c}, /* 269x Vai */
427
+ {0xa610, 0xa62b}, /* 28x Vai */
428
+ {0xa6a0, 0xa6ef}, /* 80x Bamum */
429
+ {0xa80c, 0xa822}, /* 23x Syloti Nagri */
430
+ {0xa840, 0xa873}, /* 52x Phags-pa */
431
+ {0xa882, 0xa8b3}, /* 50x Saurashtra */
432
+ {0xa8d0, 0xa8d9}, /* 10x Saurashtra */
433
+ {0xa900, 0xa925}, /* 38x Kayah Li */
434
+ {0xa930, 0xa946}, /* 23x Rejang */
435
+ {0xa960, 0xa97c}, /* 29x Hangul Jamo Extended-A */
436
+ {0xa984, 0xa9b2}, /* 47x Javanese */
437
+ {0xa9cf, 0xa9d9}, /* 11x Javanese */
438
+ {0xaa00, 0xaa28}, /* 41x Cham */
439
+ {0xaa50, 0xaa59}, /* 10x Cham */
440
+ {0xabf0, 0xabf9}, /* 10x Meetei Mayek */
441
+ {0xac00, 0xd7a3}, /* 11172x Hangul Syllables */
442
+ {0xf900, 0xfa6d}, /* 366x CJK Compatibility Ideographs */
443
+ {0xfa70, 0xfad9}, /* 106x CJK Compatibility Ideographs */
444
+ {0xfb1f, 0xfb28}, /* 10x Alphabetic Presentation Forms */
445
+ {0xfb2a, 0xfb36}, /* 13x Alphabetic Presentation Forms */
446
+ {0xfb46, 0xfbb1}, /* 108x Alphabetic Presentation Forms */
447
+ {0xfbd3, 0xfd3d}, /* 363x Arabic Presentation Forms-A */
448
+ {0xfe76, 0xfefc}, /* 135x Arabic Presentation Forms-B */
449
+ {0xff10, 0xff19}, /* 10x Dubs */
450
+ {0xff21, 0xff3a}, /* 26x Dubs */
451
+ {0xff41, 0xff5a}, /* 26x Dubs */
452
+ {0xff66, 0xffbe}, /* 89x Dubs */
453
+ {0xffc2, 0xffc7}, /* 6x Dubs */
454
+ {0xffca, 0xffcf}, /* 6x Dubs */
455
+ {0xffd2, 0xffd7}, /* 6x Dubs */
456
+ {0xffda, 0xffdc}, /* 3x Dubs */
457
+ };
458
+ l = 0;
459
+ r = n = sizeof(kGlyphs) / sizeof(kGlyphs[0]);
460
+ while (l < r) {
461
+ m = (l + r) >> 1;
462
+ if (kGlyphs[m][1] < c) {
463
+ l = m + 1;
464
+ } else {
465
+ r = m;
466
+ }
467
+ }
468
+ return !(l < n && kGlyphs[l][0] <= c && c <= kGlyphs[l][1]);
469
+ } else {
470
+ static const unsigned kAstralGlyphs[][2] = {
471
+ {0x10107, 0x10133}, /* 45x Aegean */
472
+ {0x10140, 0x10178}, /* 57x Ancient Greek Numbers */
473
+ {0x1018a, 0x1018b}, /* 2x Ancient Greek Numbers */
474
+ {0x10280, 0x1029c}, /* 29x Lycian */
475
+ {0x102a0, 0x102d0}, /* 49x Carian */
476
+ {0x102e1, 0x102fb}, /* 27x Coptic Epact Numbers */
477
+ {0x10300, 0x10323}, /* 36x Old Italic */
478
+ {0x1032d, 0x1034a}, /* 30x Old Italic, Gothic */
479
+ {0x10350, 0x10375}, /* 38x Old Permic */
480
+ {0x10380, 0x1039d}, /* 30x Ugaritic */
481
+ {0x103a0, 0x103c3}, /* 36x Old Persian */
482
+ {0x103c8, 0x103cf}, /* 8x Old Persian */
483
+ {0x103d1, 0x103d5}, /* 5x Old Persian */
484
+ {0x10400, 0x1049d}, /* 158x Deseret, Shavian, Osmanya */
485
+ {0x104b0, 0x104d3}, /* 36x Osage */
486
+ {0x104d8, 0x104fb}, /* 36x Osage */
487
+ {0x10500, 0x10527}, /* 40x Elbasan */
488
+ {0x10530, 0x10563}, /* 52x Caucasian Albanian */
489
+ {0x10600, 0x10736}, /* 311x Linear A */
490
+ {0x10800, 0x10805}, /* 6x Cypriot Syllabary */
491
+ {0x1080a, 0x10835}, /* 44x Cypriot Syllabary */
492
+ {0x10837, 0x10838}, /* 2x Cypriot Syllabary */
493
+ {0x1083f, 0x1089e}, /* 86x Cypriot,ImperialAramaic,Palmyrene,Nabataean */
494
+ {0x108e0, 0x108f2}, /* 19x Hatran */
495
+ {0x108f4, 0x108f5}, /* 2x Hatran */
496
+ {0x108fb, 0x1091b}, /* 33x Hatran */
497
+ {0x10920, 0x10939}, /* 26x Lydian */
498
+ {0x10980, 0x109b7}, /* 56x Meroitic Hieroglyphs */
499
+ {0x109bc, 0x109cf}, /* 20x Meroitic Cursive */
500
+ {0x109d2, 0x10a00}, /* 47x Meroitic Cursive */
501
+ {0x10a10, 0x10a13}, /* 4x Kharoshthi */
502
+ {0x10a15, 0x10a17}, /* 3x Kharoshthi */
503
+ {0x10a19, 0x10a35}, /* 29x Kharoshthi */
504
+ {0x10a40, 0x10a48}, /* 9x Kharoshthi */
505
+ {0x10a60, 0x10a7e}, /* 31x Old South Arabian */
506
+ {0x10a80, 0x10a9f}, /* 32x Old North Arabian */
507
+ {0x10ac0, 0x10ac7}, /* 8x Manichaean */
508
+ {0x10ac9, 0x10ae4}, /* 28x Manichaean */
509
+ {0x10aeb, 0x10aef}, /* 5x Manichaean */
510
+ {0x10b00, 0x10b35}, /* 54x Avestan */
511
+ {0x10b40, 0x10b55}, /* 22x Inscriptional Parthian */
512
+ {0x10b58, 0x10b72}, /* 27x Inscriptional Parthian and Pahlavi */
513
+ {0x10b78, 0x10b91}, /* 26x Inscriptional Pahlavi, Psalter Pahlavi */
514
+ {0x10c00, 0x10c48}, /* 73x Old Turkic */
515
+ {0x10c80, 0x10cb2}, /* 51x Old Hungarian */
516
+ {0x10cc0, 0x10cf2}, /* 51x Old Hungarian */
517
+ {0x10cfa, 0x10d23}, /* 42x Old Hungarian, Hanifi Rohingya */
518
+ {0x10d30, 0x10d39}, /* 10x Hanifi Rohingya */
519
+ {0x10e60, 0x10e7e}, /* 31x Rumi Numeral Symbols */
520
+ {0x10f00, 0x10f27}, /* 40x Old Sogdian */
521
+ {0x10f30, 0x10f45}, /* 22x Sogdian */
522
+ {0x10f51, 0x10f54}, /* 4x Sogdian */
523
+ {0x10fe0, 0x10ff6}, /* 23x Elymaic */
524
+ {0x11003, 0x11037}, /* 53x Brahmi */
525
+ {0x11052, 0x1106f}, /* 30x Brahmi */
526
+ {0x11083, 0x110af}, /* 45x Kaithi */
527
+ {0x110d0, 0x110e8}, /* 25x Sora Sompeng */
528
+ {0x110f0, 0x110f9}, /* 10x Sora Sompeng */
529
+ {0x11103, 0x11126}, /* 36x Chakma */
530
+ {0x11136, 0x1113f}, /* 10x Chakma */
531
+ {0x11144, 0x11144}, /* 1x Chakma */
532
+ {0x11150, 0x11172}, /* 35x Mahajani */
533
+ {0x11176, 0x11176}, /* 1x Mahajani */
534
+ {0x11183, 0x111b2}, /* 48x Sharada */
535
+ {0x111c1, 0x111c4}, /* 4x Sharada */
536
+ {0x111d0, 0x111da}, /* 11x Sharada */
537
+ {0x111dc, 0x111dc}, /* 1x Sharada */
538
+ {0x111e1, 0x111f4}, /* 20x Sinhala Archaic Numbers */
539
+ {0x11200, 0x11211}, /* 18x Khojki */
540
+ {0x11213, 0x1122b}, /* 25x Khojki */
541
+ {0x11280, 0x11286}, /* 7x Multani */
542
+ {0x11288, 0x11288}, /* 1x Multani */
543
+ {0x1128a, 0x1128d}, /* 4x Multani */
544
+ {0x1128f, 0x1129d}, /* 15x Multani */
545
+ {0x1129f, 0x112a8}, /* 10x Multani */
546
+ {0x112b0, 0x112de}, /* 47x Khudawadi */
547
+ {0x112f0, 0x112f9}, /* 10x Khudawadi */
548
+ {0x11305, 0x1130c}, /* 8x Grantha */
549
+ {0x1130f, 0x11310}, /* 2x Grantha */
550
+ {0x11313, 0x11328}, /* 22x Grantha */
551
+ {0x1132a, 0x11330}, /* 7x Grantha */
552
+ {0x11332, 0x11333}, /* 2x Grantha */
553
+ {0x11335, 0x11339}, /* 5x Grantha */
554
+ {0x1133d, 0x1133d}, /* 1x Grantha */
555
+ {0x11350, 0x11350}, /* 1x Grantha */
556
+ {0x1135d, 0x11361}, /* 5x Grantha */
557
+ {0x11400, 0x11434}, /* 53x Newa */
558
+ {0x11447, 0x1144a}, /* 4x Newa */
559
+ {0x11450, 0x11459}, /* 10x Newa */
560
+ {0x1145f, 0x1145f}, /* 1x Newa */
561
+ {0x11480, 0x114af}, /* 48x Tirhuta */
562
+ {0x114c4, 0x114c5}, /* 2x Tirhuta */
563
+ {0x114c7, 0x114c7}, /* 1x Tirhuta */
564
+ {0x114d0, 0x114d9}, /* 10x Tirhuta */
565
+ {0x11580, 0x115ae}, /* 47x Siddham */
566
+ {0x115d8, 0x115db}, /* 4x Siddham */
567
+ {0x11600, 0x1162f}, /* 48x Modi */
568
+ {0x11644, 0x11644}, /* 1x Modi */
569
+ {0x11650, 0x11659}, /* 10x Modi */
570
+ {0x11680, 0x116aa}, /* 43x Takri */
571
+ {0x116b8, 0x116b8}, /* 1x Takri */
572
+ {0x116c0, 0x116c9}, /* 10x Takri */
573
+ {0x11700, 0x1171a}, /* 27x Ahom */
574
+ {0x11730, 0x1173b}, /* 12x Ahom */
575
+ {0x11800, 0x1182b}, /* 44x Dogra */
576
+ {0x118a0, 0x118f2}, /* 83x Warang Citi */
577
+ {0x118ff, 0x118ff}, /* 1x Warang Citi */
578
+ {0x119a0, 0x119a7}, /* 8x Nandinagari */
579
+ {0x119aa, 0x119d0}, /* 39x Nandinagari */
580
+ {0x119e1, 0x119e1}, /* 1x Nandinagari */
581
+ {0x119e3, 0x119e3}, /* 1x Nandinagari */
582
+ {0x11a00, 0x11a00}, /* 1x Zanabazar Square */
583
+ {0x11a0b, 0x11a32}, /* 40x Zanabazar Square */
584
+ {0x11a3a, 0x11a3a}, /* 1x Zanabazar Square */
585
+ {0x11a50, 0x11a50}, /* 1x Soyombo */
586
+ {0x11a5c, 0x11a89}, /* 46x Soyombo */
587
+ {0x11a9d, 0x11a9d}, /* 1x Soyombo */
588
+ {0x11ac0, 0x11af8}, /* 57x Pau Cin Hau */
589
+ {0x11c00, 0x11c08}, /* 9x Bhaiksuki */
590
+ {0x11c0a, 0x11c2e}, /* 37x Bhaiksuki */
591
+ {0x11c40, 0x11c40}, /* 1x Bhaiksuki */
592
+ {0x11c50, 0x11c6c}, /* 29x Bhaiksuki */
593
+ {0x11c72, 0x11c8f}, /* 30x Marchen */
594
+ {0x11d00, 0x11d06}, /* 7x Masaram Gondi */
595
+ {0x11d08, 0x11d09}, /* 2x Masaram Gondi */
596
+ {0x11d0b, 0x11d30}, /* 38x Masaram Gondi */
597
+ {0x11d46, 0x11d46}, /* 1x Masaram Gondi */
598
+ {0x11d50, 0x11d59}, /* 10x Masaram Gondi */
599
+ {0x11d60, 0x11d65}, /* 6x Gunjala Gondi */
600
+ {0x11d67, 0x11d68}, /* 2x Gunjala Gondi */
601
+ {0x11d6a, 0x11d89}, /* 32x Gunjala Gondi */
602
+ {0x11d98, 0x11d98}, /* 1x Gunjala Gondi */
603
+ {0x11da0, 0x11da9}, /* 10x Gunjala Gondi */
604
+ {0x11ee0, 0x11ef2}, /* 19x Makasar */
605
+ {0x11fc0, 0x11fd4}, /* 21x Tamil Supplement */
606
+ {0x12000, 0x12399}, /* 922x Cuneiform */
607
+ {0x12400, 0x1246e}, /* 111x Cuneiform Numbers & Punctuation */
608
+ {0x12480, 0x12543}, /* 196x Early Dynastic Cuneiform */
609
+ {0x13000, 0x1342e}, /* 1071x Egyptian Hieroglyphs */
610
+ {0x14400, 0x14646}, /* 583x Anatolian Hieroglyphs */
611
+ {0x16800, 0x16a38}, /* 569x Bamum Supplement */
612
+ {0x16a40, 0x16a5e}, /* 31x Mro */
613
+ {0x16a60, 0x16a69}, /* 10x Mro */
614
+ {0x16ad0, 0x16aed}, /* 30x Bassa Vah */
615
+ {0x16b00, 0x16b2f}, /* 48x Pahawh Hmong */
616
+ {0x16b40, 0x16b43}, /* 4x Pahawh Hmong */
617
+ {0x16b50, 0x16b59}, /* 10x Pahawh Hmong */
618
+ {0x16b5b, 0x16b61}, /* 7x Pahawh Hmong */
619
+ {0x16b63, 0x16b77}, /* 21x Pahawh Hmong */
620
+ {0x16b7d, 0x16b8f}, /* 19x Pahawh Hmong */
621
+ {0x16e40, 0x16e96}, /* 87x Medefaidrin */
622
+ {0x16f00, 0x16f4a}, /* 75x Miao */
623
+ {0x16f50, 0x16f50}, /* 1x Miao */
624
+ {0x16f93, 0x16f9f}, /* 13x Miao */
625
+ {0x16fe0, 0x16fe1}, /* 2x Ideographic Symbols & Punctuation */
626
+ {0x16fe3, 0x16fe3}, /* 1x Ideographic Symbols & Punctuation */
627
+ {0x17000, 0x187f7}, /* 6136x Tangut */
628
+ {0x18800, 0x18af2}, /* 755x Tangut Components */
629
+ {0x1b000, 0x1b11e}, /* 287x Kana Supplement */
630
+ {0x1b150, 0x1b152}, /* 3x Small Kana Extension */
631
+ {0x1b164, 0x1b167}, /* 4x Small Kana Extension */
632
+ {0x1b170, 0x1b2fb}, /* 396x Nushu */
633
+ {0x1bc00, 0x1bc6a}, /* 107x Duployan */
634
+ {0x1bc70, 0x1bc7c}, /* 13x Duployan */
635
+ {0x1bc80, 0x1bc88}, /* 9x Duployan */
636
+ {0x1bc90, 0x1bc99}, /* 10x Duployan */
637
+ {0x1d2e0, 0x1d2f3}, /* 20x Mayan Numerals */
638
+ {0x1d360, 0x1d378}, /* 25x Counting Rod Numerals */
639
+ {0x1d400, 0x1d454}, /* 85x 𝐀..𝑔 Math */
640
+ {0x1d456, 0x1d49c}, /* 71x 𝑖..𝒜 Math */
641
+ {0x1d49e, 0x1d49f}, /* 2x 𝒞..𝒟 Math */
642
+ {0x1d4a2, 0x1d4a2}, /* 1x 𝒢..𝒢 Math */
643
+ {0x1d4a5, 0x1d4a6}, /* 2x 𝒥..𝒦 Math */
644
+ {0x1d4a9, 0x1d4ac}, /* 4x 𝒩..𝒬 Math */
645
+ {0x1d4ae, 0x1d4b9}, /* 12x 𝒮..𝒹 Math */
646
+ {0x1d4bb, 0x1d4bb}, /* 1x 𝒻..𝒻 Math */
647
+ {0x1d4bd, 0x1d4c3}, /* 7x 𝒽..𝓃 Math */
648
+ {0x1d4c5, 0x1d505}, /* 65x 𝓅..𝔅 Math */
649
+ {0x1d507, 0x1d50a}, /* 4x 𝔇..𝔊 Math */
650
+ {0x1d50d, 0x1d514}, /* 8x 𝔍..𝔔 Math */
651
+ {0x1d516, 0x1d51c}, /* 7x 𝔖..𝔜 Math */
652
+ {0x1d51e, 0x1d539}, /* 28x 𝔞..𝔹 Math */
653
+ {0x1d53b, 0x1d53e}, /* 4x 𝔻..𝔾 Math */
654
+ {0x1d540, 0x1d544}, /* 5x 𝕀..𝕄 Math */
655
+ {0x1d546, 0x1d546}, /* 1x 𝕆..𝕆 Math */
656
+ {0x1d54a, 0x1d550}, /* 7x 𝕊..𝕐 Math */
657
+ {0x1d552, 0x1d6a5}, /* 340x 𝕒..𝚥 Math */
658
+ {0x1d6a8, 0x1d6c0}, /* 25x 𝚨..𝛀 Math */
659
+ {0x1d6c2, 0x1d6da}, /* 25x 𝛂..𝛚 Math */
660
+ {0x1d6dc, 0x1d6fa}, /* 31x 𝛜..𝛺 Math */
661
+ {0x1d6fc, 0x1d714}, /* 25x 𝛼..𝜔 Math */
662
+ {0x1d716, 0x1d734}, /* 31x 𝜖..𝜴 Math */
663
+ {0x1d736, 0x1d74e}, /* 25x 𝜶..𝝎 Math */
664
+ {0x1d750, 0x1d76e}, /* 31x 𝝐..𝝮 Math */
665
+ {0x1d770, 0x1d788}, /* 25x 𝝰..𝞈 Math */
666
+ {0x1d78a, 0x1d7a8}, /* 31x 𝞊..𝞨 Math */
667
+ {0x1d7aa, 0x1d7c2}, /* 25x 𝞪..𝟂 Math */
668
+ {0x1d7c4, 0x1d7cb}, /* 8x 𝟄..𝟋 Math */
669
+ {0x1d7ce, 0x1d9ff}, /* 562x Math, Sutton SignWriting */
670
+ {0x1f100, 0x1f10c}, /* 13x Enclosed Alphanumeric Supplement */
671
+ {0x20000, 0x2a6d6}, /* 42711x CJK Unified Ideographs Extension B */
672
+ {0x2a700, 0x2b734}, /* 4149x CJK Unified Ideographs Extension C */
673
+ {0x2b740, 0x2b81d}, /* 222x CJK Unified Ideographs Extension D */
674
+ {0x2b820, 0x2cea1}, /* 5762x CJK Unified Ideographs Extension E */
675
+ {0x2ceb0, 0x2ebe0}, /* 7473x CJK Unified Ideographs Extension F */
676
+ {0x2f800, 0x2fa1d}, /* 542x CJK Compatibility Ideographs Supplement */
677
+ };
678
+ l = 0;
679
+ r = n = sizeof(kAstralGlyphs) / sizeof(kAstralGlyphs[0]);
680
+ while (l < r) {
681
+ m = (l + r) >> 1;
682
+ if (kAstralGlyphs[m][1] < c) {
683
+ l = m + 1;
684
+ } else {
685
+ r = m;
686
+ }
687
+ }
688
+ return !(l < n && kAstralGlyphs[l][0] <= c && c <= kAstralGlyphs[l][1]);
689
+ }
690
+ }
691
+
692
+ unsigned bestlineLowercase(unsigned c) {
693
+ int m, l, r, n;
694
+ if (c < 0200) {
695
+ if ('A' <= c && c <= 'Z') {
696
+ return c + 32;
697
+ } else {
698
+ return c;
699
+ }
700
+ } else if (c <= 0xffff) {
701
+ if ((0x0100 <= c && c <= 0x0176) || /* 60x Ā..ā → ā..ŵ Watin-A */
702
+ (0x01de <= c && c <= 0x01ee) || /* 9x Ǟ..Ǯ → ǟ..ǯ Watin-B */
703
+ (0x01f8 <= c && c <= 0x021e) || /* 20x Ǹ..Ȟ → ǹ..ȟ Watin-B */
704
+ (0x0222 <= c && c <= 0x0232) || /* 9x Ȣ..Ȳ → ȣ..ȳ Watin-B */
705
+ (0x1e00 <= c && c <= 0x1eff)) { /*256x Ḁ..Ỿ → ḁ..ỿ Watin-C */
706
+ if (c == 0x0130) return c - 199;
707
+ if (c == 0x1e9e) return c;
708
+ return c + (~c & 1);
709
+ } else if (0x01cf <= c && c <= 0x01db) {
710
+ return c + (c & 1); /* 7x Ǐ..Ǜ → ǐ..ǜ Watin-B */
711
+ } else if (0x13a0 <= c && c <= 0x13ef) {
712
+ return c + 38864; /* 80x Ꭰ ..Ꮿ → ꭰ ..ꮿ Cherokee */
713
+ } else {
714
+ static const struct {
715
+ unsigned short a;
716
+ unsigned short b;
717
+ short d;
718
+ } kLower[] = {
719
+ {0x00c0, 0x00d6, +32}, /* 23x À ..Ö → à ..ö Watin */
720
+ {0x00d8, 0x00de, +32}, /* 7x Ø ..Þ → ø ..þ Watin */
721
+ {0x0178, 0x0178, -121}, /* 1x Ÿ ..Ÿ → ÿ ..ÿ Watin-A */
722
+ {0x0179, 0x0179, +1}, /* 1x Ź ..Ź → ź ..ź Watin-A */
723
+ {0x017b, 0x017b, +1}, /* 1x Ż ..Ż → ż ..ż Watin-A */
724
+ {0x017d, 0x017d, +1}, /* 1x Ž ..Ž → ž ..ž Watin-A */
725
+ {0x0181, 0x0181, +210}, /* 1x Ɓ ..Ɓ → ɓ ..ɓ Watin-B */
726
+ {0x0182, 0x0182, +1}, /* 1x Ƃ ..Ƃ → ƃ ..ƃ Watin-B */
727
+ {0x0184, 0x0184, +1}, /* 1x Ƅ ..Ƅ → ƅ ..ƅ Watin-B */
728
+ {0x0186, 0x0186, +206}, /* 1x Ɔ ..Ɔ → ɔ ..ɔ Watin-B */
729
+ {0x0187, 0x0187, +1}, /* 1x Ƈ ..Ƈ → ƈ ..ƈ Watin-B */
730
+ {0x0189, 0x018a, +205}, /* 2x Ɖ ..Ɗ → ɖ ..ɗ Watin-B */
731
+ {0x018b, 0x018b, +1}, /* 1x Ƌ ..Ƌ → ƌ ..ƌ Watin-B */
732
+ {0x018e, 0x018e, +79}, /* 1x Ǝ ..Ǝ → ǝ ..ǝ Watin-B */
733
+ {0x018f, 0x018f, +202}, /* 1x Ə ..Ə → ə ..ə Watin-B */
734
+ {0x0190, 0x0190, +203}, /* 1x Ɛ ..Ɛ → ɛ ..ɛ Watin-B */
735
+ {0x0191, 0x0191, +1}, /* 1x Ƒ ..Ƒ → ƒ ..ƒ Watin-B */
736
+ {0x0193, 0x0193, +205}, /* 1x Ɠ ..Ɠ → ɠ ..ɠ Watin-B */
737
+ {0x0194, 0x0194, +207}, /* 1x Ɣ ..Ɣ → ɣ ..ɣ Watin-B */
738
+ {0x0196, 0x0196, +211}, /* 1x Ɩ ..Ɩ → ɩ ..ɩ Watin-B */
739
+ {0x0197, 0x0197, +209}, /* 1x Ɨ ..Ɨ → ɨ ..ɨ Watin-B */
740
+ {0x0198, 0x0198, +1}, /* 1x Ƙ ..Ƙ → ƙ ..ƙ Watin-B */
741
+ {0x019c, 0x019c, +211}, /* 1x Ɯ ..Ɯ → ɯ ..ɯ Watin-B */
742
+ {0x019d, 0x019d, +213}, /* 1x Ɲ ..Ɲ → ɲ ..ɲ Watin-B */
743
+ {0x019f, 0x019f, +214}, /* 1x Ɵ ..Ɵ → ɵ ..ɵ Watin-B */
744
+ {0x01a0, 0x01a0, +1}, /* 1x Ơ ..Ơ → ơ ..ơ Watin-B */
745
+ {0x01a2, 0x01a2, +1}, /* 1x Ƣ ..Ƣ → ƣ ..ƣ Watin-B */
746
+ {0x01a4, 0x01a4, +1}, /* 1x Ƥ ..Ƥ → ƥ ..ƥ Watin-B */
747
+ {0x01a6, 0x01a6, +218}, /* 1x Ʀ ..Ʀ → ʀ ..ʀ Watin-B */
748
+ {0x01a7, 0x01a7, +1}, /* 1x Ƨ ..Ƨ → ƨ ..ƨ Watin-B */
749
+ {0x01a9, 0x01a9, +218}, /* 1x Ʃ ..Ʃ → ʃ ..ʃ Watin-B */
750
+ {0x01ac, 0x01ac, +1}, /* 1x Ƭ ..Ƭ → ƭ ..ƭ Watin-B */
751
+ {0x01ae, 0x01ae, +218}, /* 1x Ʈ ..Ʈ → ʈ ..ʈ Watin-B */
752
+ {0x01af, 0x01af, +1}, /* 1x Ư ..Ư → ư ..ư Watin-B */
753
+ {0x01b1, 0x01b2, +217}, /* 2x Ʊ ..Ʋ → ʊ ..ʋ Watin-B */
754
+ {0x01b3, 0x01b3, +1}, /* 1x Ƴ ..Ƴ → ƴ ..ƴ Watin-B */
755
+ {0x01b5, 0x01b5, +1}, /* 1x Ƶ ..Ƶ → ƶ ..ƶ Watin-B */
756
+ {0x01b7, 0x01b7, +219}, /* 1x Ʒ ..Ʒ → ʒ ..ʒ Watin-B */
757
+ {0x01b8, 0x01b8, +1}, /* 1x Ƹ ..Ƹ → ƹ ..ƹ Watin-B */
758
+ {0x01bc, 0x01bc, +1}, /* 1x Ƽ ..Ƽ → ƽ ..ƽ Watin-B */
759
+ {0x01c4, 0x01c4, +2}, /* 1x DŽ ..DŽ → dž ..dž Watin-B */
760
+ {0x01c5, 0x01c5, +1}, /* 1x Dž ..Dž → dž ..dž Watin-B */
761
+ {0x01c7, 0x01c7, +2}, /* 1x LJ ..LJ → lj ..lj Watin-B */
762
+ {0x01c8, 0x01c8, +1}, /* 1x Lj ..Lj → lj ..lj Watin-B */
763
+ {0x01ca, 0x01ca, +2}, /* 1x NJ ..NJ → nj ..nj Watin-B */
764
+ {0x01cb, 0x01cb, +1}, /* 1x Nj ..Nj → nj ..nj Watin-B */
765
+ {0x01cd, 0x01cd, +1}, /* 1x Ǎ ..Ǎ → ǎ ..ǎ Watin-B */
766
+ {0x01f1, 0x01f1, +2}, /* 1x DZ ..DZ → dz ..dz Watin-B */
767
+ {0x01f2, 0x01f2, +1}, /* 1x Dz ..Dz → dz ..dz Watin-B */
768
+ {0x01f4, 0x01f4, +1}, /* 1x Ǵ ..Ǵ → ǵ ..ǵ Watin-B */
769
+ {0x01f6, 0x01f6, -97}, /* 1x Ƕ ..Ƕ → ƕ ..ƕ Watin-B */
770
+ {0x01f7, 0x01f7, -56}, /* 1x Ƿ ..Ƿ → ƿ ..ƿ Watin-B */
771
+ {0x0220, 0x0220, -130}, /* 1x Ƞ ..Ƞ → ƞ ..ƞ Watin-B */
772
+ {0x023b, 0x023b, +1}, /* 1x Ȼ ..Ȼ → ȼ ..ȼ Watin-B */
773
+ {0x023d, 0x023d, -163}, /* 1x Ƚ ..Ƚ → ƚ ..ƚ Watin-B */
774
+ {0x0241, 0x0241, +1}, /* 1x Ɂ ..Ɂ → ɂ ..ɂ Watin-B */
775
+ {0x0243, 0x0243, -195}, /* 1x Ƀ ..Ƀ → ƀ ..ƀ Watin-B */
776
+ {0x0244, 0x0244, +69}, /* 1x Ʉ ..Ʉ → ʉ ..ʉ Watin-B */
777
+ {0x0245, 0x0245, +71}, /* 1x Ʌ ..Ʌ → ʌ ..ʌ Watin-B */
778
+ {0x0246, 0x0246, +1}, /* 1x Ɇ ..Ɇ → ɇ ..ɇ Watin-B */
779
+ {0x0248, 0x0248, +1}, /* 1x Ɉ ..Ɉ → ɉ ..ɉ Watin-B */
780
+ {0x024a, 0x024a, +1}, /* 1x Ɋ ..Ɋ → ɋ ..ɋ Watin-B */
781
+ {0x024c, 0x024c, +1}, /* 1x Ɍ ..Ɍ → ɍ ..ɍ Watin-B */
782
+ {0x024e, 0x024e, +1}, /* 1x Ɏ ..Ɏ → ɏ ..ɏ Watin-B */
783
+ {0x0386, 0x0386, +38}, /* 1x Ά ..Ά → ά ..ά Greek */
784
+ {0x0388, 0x038a, +37}, /* 3x Έ ..Ί → έ ..ί Greek */
785
+ {0x038c, 0x038c, +64}, /* 1x Ό ..Ό → ό ..ό Greek */
786
+ {0x038e, 0x038f, +63}, /* 2x Ύ ..Ώ → ύ ..ώ Greek */
787
+ {0x0391, 0x03a1, +32}, /* 17x Α ..Ρ → α ..ρ Greek */
788
+ {0x03a3, 0x03ab, +32}, /* 9x Σ ..Ϋ → σ ..ϋ Greek */
789
+ {0x03dc, 0x03dc, +1}, /* 1x Ϝ ..Ϝ → ϝ ..ϝ Greek */
790
+ {0x03f4, 0x03f4, -60}, /* 1x ϴ ..ϴ → θ ..θ Greek */
791
+ {0x0400, 0x040f, +80}, /* 16x Ѐ ..Џ → ѐ ..џ Cyrillic */
792
+ {0x0410, 0x042f, +32}, /* 32x А ..Я → а ..я Cyrillic */
793
+ {0x0460, 0x0460, +1}, /* 1x Ѡ ..Ѡ → ѡ ..ѡ Cyrillic */
794
+ {0x0462, 0x0462, +1}, /* 1x Ѣ ..Ѣ → ѣ ..ѣ Cyrillic */
795
+ {0x0464, 0x0464, +1}, /* 1x Ѥ ..Ѥ → ѥ ..ѥ Cyrillic */
796
+ {0x0472, 0x0472, +1}, /* 1x Ѳ ..Ѳ → ѳ ..ѳ Cyrillic */
797
+ {0x0490, 0x0490, +1}, /* 1x Ґ ..Ґ → ґ ..ґ Cyrillic */
798
+ {0x0498, 0x0498, +1}, /* 1x Ҙ ..Ҙ → ҙ ..ҙ Cyrillic */
799
+ {0x049a, 0x049a, +1}, /* 1x Қ ..Қ → қ ..қ Cyrillic */
800
+ {0x0531, 0x0556, +48}, /* 38x Ա ..Ֆ → ա ..ֆ Armenian */
801
+ {0x10a0, 0x10c5, +7264}, /* 38x Ⴀ ..Ⴥ → ⴀ ..ⴥ Georgian */
802
+ {0x10c7, 0x10c7, +7264}, /* 1x Ⴧ ..Ⴧ → ⴧ ..ⴧ Georgian */
803
+ {0x10cd, 0x10cd, +7264}, /* 1x Ⴭ ..Ⴭ → ⴭ ..ⴭ Georgian */
804
+ {0x13f0, 0x13f5, +8}, /* 6x Ᏸ ..Ᏽ → ᏸ ..ᏽ Cherokee */
805
+ {0x1c90, 0x1cba, -3008}, /* 43x Ა ..Ჺ → ა ..ჺ Georgian2 */
806
+ {0x1cbd, 0x1cbf, -3008}, /* 3x Ჽ ..Ჿ → ჽ ..ჿ Georgian2 */
807
+ {0x1f08, 0x1f0f, -8}, /* 8x Ἀ ..Ἇ → ἀ ..ἇ Greek2 */
808
+ {0x1f18, 0x1f1d, -8}, /* 6x Ἐ ..Ἕ → ἐ ..ἕ Greek2 */
809
+ {0x1f28, 0x1f2f, -8}, /* 8x Ἠ ..Ἧ → ἠ ..ἧ Greek2 */
810
+ {0x1f38, 0x1f3f, -8}, /* 8x Ἰ ..Ἷ → ἰ ..ἷ Greek2 */
811
+ {0x1f48, 0x1f4d, -8}, /* 6x Ὀ ..Ὅ → ὀ ..ὅ Greek2 */
812
+ {0x1f59, 0x1f59, -8}, /* 1x Ὑ ..Ὑ → ὑ ..ὑ Greek2 */
813
+ {0x1f5b, 0x1f5b, -8}, /* 1x Ὓ ..Ὓ → ὓ ..ὓ Greek2 */
814
+ {0x1f5d, 0x1f5d, -8}, /* 1x Ὕ ..Ὕ → ὕ ..ὕ Greek2 */
815
+ {0x1f5f, 0x1f5f, -8}, /* 1x Ὗ ..Ὗ → ὗ ..ὗ Greek2 */
816
+ {0x1f68, 0x1f6f, -8}, /* 8x Ὠ ..Ὧ → ὠ ..ὧ Greek2 */
817
+ {0x1f88, 0x1f8f, -8}, /* 8x ᾈ ..ᾏ → ᾀ ..ᾇ Greek2 */
818
+ {0x1f98, 0x1f9f, -8}, /* 8x ᾘ ..ᾟ → ᾐ ..ᾗ Greek2 */
819
+ {0x1fa8, 0x1faf, -8}, /* 8x ᾨ ..ᾯ → ᾠ ..ᾧ Greek2 */
820
+ {0x1fb8, 0x1fb9, -8}, /* 2x Ᾰ ..Ᾱ → ᾰ ..ᾱ Greek2 */
821
+ {0x1fba, 0x1fbb, -74}, /* 2x Ὰ ..Ά → ὰ ..ά Greek2 */
822
+ {0x1fbc, 0x1fbc, -9}, /* 1x ᾼ ..ᾼ → ᾳ ..ᾳ Greek2 */
823
+ {0x1fc8, 0x1fcb, -86}, /* 4x Ὲ ..Ή → ὲ ..ή Greek2 */
824
+ {0x1fcc, 0x1fcc, -9}, /* 1x ῌ ..ῌ → ῃ ..ῃ Greek2 */
825
+ {0x1fd8, 0x1fd9, -8}, /* 2x Ῐ ..Ῑ → ῐ ..ῑ Greek2 */
826
+ {0x1fda, 0x1fdb, -100}, /* 2x Ὶ ..Ί → ὶ ..ί Greek2 */
827
+ {0x1fe8, 0x1fe9, -8}, /* 2x Ῠ ..Ῡ → ῠ ..ῡ Greek2 */
828
+ {0x1fea, 0x1feb, -112}, /* 2x Ὺ ..Ύ → ὺ ..ύ Greek2 */
829
+ {0x1fec, 0x1fec, -7}, /* 1x Ῥ ..Ῥ → ῥ ..ῥ Greek2 */
830
+ {0x1ff8, 0x1ff9, -128}, /* 2x Ὸ ..Ό → ὸ ..ό Greek2 */
831
+ {0x1ffa, 0x1ffb, -126}, /* 2x Ὼ ..Ώ → ὼ ..ώ Greek2 */
832
+ {0x1ffc, 0x1ffc, -9}, /* 1x ῼ ..ῼ → ῳ ..ῳ Greek2 */
833
+ {0x2126, 0x2126, -7517}, /* 1x Ω ..Ω → ω ..ω Letterlike */
834
+ {0x212a, 0x212a, -8383}, /* 1x K ..K → k ..k Letterlike */
835
+ {0x212b, 0x212b, -8262}, /* 1x Å ..Å → å ..å Letterlike */
836
+ {0x2132, 0x2132, +28}, /* 1x Ⅎ ..Ⅎ → ⅎ ..ⅎ Letterlike */
837
+ {0x2160, 0x216f, +16}, /* 16x Ⅰ ..Ⅿ → ⅰ ..ⅿ Numbery */
838
+ {0x2183, 0x2183, +1}, /* 1x Ↄ ..Ↄ → ↄ ..ↄ Numbery */
839
+ {0x24b6, 0x24cf, +26}, /* 26x Ⓐ ..Ⓩ → ⓐ ..ⓩ Enclosed */
840
+ {0x2c00, 0x2c2e, +48}, /* 47x Ⰰ ..Ⱞ → ⰰ ..ⱞ Glagolitic */
841
+ {0xff21, 0xff3a, +32}, /* 26x A..Z → a..z Dubs */
842
+ };
843
+ l = 0;
844
+ r = n = sizeof(kLower) / sizeof(kLower[0]);
845
+ while (l < r) {
846
+ m = (l + r) >> 1;
847
+ if (kLower[m].b < c) {
848
+ l = m + 1;
849
+ } else {
850
+ r = m;
851
+ }
852
+ }
853
+ if (l < n && kLower[l].a <= c && c <= kLower[l].b) {
854
+ return c + kLower[l].d;
855
+ } else {
856
+ return c;
857
+ }
858
+ }
859
+ } else {
860
+ static struct {
861
+ unsigned a;
862
+ unsigned b;
863
+ short d;
864
+ } kAstralLower[] = {
865
+ {0x10400, 0x10427, +40}, /* 40x 𐐀 ..𐐧 → 𐐨 ..𐑏 Deseret */
866
+ {0x104b0, 0x104d3, +40}, /* 36x 𐒰 ..𐓓 → 𐓘 ..𐓻 Osage */
867
+ {0x1d400, 0x1d419, +26}, /* 26x 𝐀 ..𝐙 → 𝐚 ..𝐳 Math */
868
+ {0x1d43c, 0x1d44d, +26}, /* 18x 𝐼 ..𝑍 → 𝑖 ..𝑧 Math */
869
+ {0x1d468, 0x1d481, +26}, /* 26x 𝑨 ..𝒁 → 𝒂 ..𝒛 Math */
870
+ {0x1d4ae, 0x1d4b5, +26}, /* 8x 𝒮 ..𝒵 → 𝓈 ..𝓏 Math */
871
+ {0x1d4d0, 0x1d4e9, +26}, /* 26x 𝓐 ..𝓩 → 𝓪 ..𝔃 Math */
872
+ {0x1d50d, 0x1d514, +26}, /* 8x 𝔍 ..𝔔 → 𝔧 ..𝔮 Math */
873
+ {0x1d56c, 0x1d585, +26}, /* 26x 𝕬 ..𝖅 → 𝖆 ..𝖟 Math */
874
+ {0x1d5a0, 0x1d5b9, +26}, /* 26x 𝖠 ..𝖹 → 𝖺 ..𝗓 Math */
875
+ {0x1d5d4, 0x1d5ed, +26}, /* 26x 𝗔 ..𝗭 → 𝗮 ..𝘇 Math */
876
+ {0x1d608, 0x1d621, +26}, /* 26x 𝘈 ..𝘡 → 𝘢 ..𝘻 Math */
877
+ {0x1d63c, 0x1d655, -442}, /* 26x 𝘼 ..𝙕 → 𝒂 ..𝒛 Math */
878
+ {0x1d670, 0x1d689, +26}, /* 26x 𝙰 ..𝚉 → 𝚊 ..𝚣 Math */
879
+ {0x1d6a8, 0x1d6b8, +26}, /* 17x 𝚨 ..𝚸 → 𝛂 ..𝛒 Math */
880
+ {0x1d6e2, 0x1d6f2, +26}, /* 17x 𝛢 ..𝛲 → 𝛼 ..𝜌 Math */
881
+ {0x1d71c, 0x1d72c, +26}, /* 17x 𝜜 ..𝜬 → 𝜶 ..𝝆 Math */
882
+ {0x1d756, 0x1d766, +26}, /* 17x 𝝖 ..𝝦 → 𝝰 ..𝞀 Math */
883
+ {0x1d790, 0x1d7a0, -90}, /* 17x 𝞐 ..𝞠 → 𝜶 ..𝝆 Math */
884
+ };
885
+ l = 0;
886
+ r = n = sizeof(kAstralLower) / sizeof(kAstralLower[0]);
887
+ while (l < r) {
888
+ m = (l + r) >> 1;
889
+ if (kAstralLower[m].b < c) {
890
+ l = m + 1;
891
+ } else {
892
+ r = m;
893
+ }
894
+ }
895
+ if (l < n && kAstralLower[l].a <= c && c <= kAstralLower[l].b) {
896
+ return c + kAstralLower[l].d;
897
+ } else {
898
+ return c;
899
+ }
900
+ }
901
+ }
902
+
903
+ unsigned bestlineUppercase(unsigned c) {
904
+ int m, l, r, n;
905
+ if (c < 0200) {
906
+ if ('a' <= c && c <= 'z') {
907
+ return c - 32;
908
+ } else {
909
+ return c;
910
+ }
911
+ } else if (c <= 0xffff) {
912
+ if ((0x0101 <= c && c <= 0x0177) || /* 60x ā..ŵ → Ā..ā Watin-A */
913
+ (0x01df <= c && c <= 0x01ef) || /* 9x ǟ..ǯ → Ǟ..Ǯ Watin-B */
914
+ (0x01f8 <= c && c <= 0x021e) || /* 20x ǹ..ȟ → Ǹ..Ȟ Watin-B */
915
+ (0x0222 <= c && c <= 0x0232) || /* 9x ȣ..ȳ → Ȣ..Ȳ Watin-B */
916
+ (0x1e01 <= c && c <= 0x1eff)) { /*256x ḁ..ỿ → Ḁ..Ỿ Watin-C */
917
+ if (c == 0x0131) return c + 232;
918
+ if (c == 0x1e9e) return c;
919
+ return c - (c & 1);
920
+ } else if (0x01d0 <= c && c <= 0x01dc) {
921
+ return c - (~c & 1); /* 7x ǐ..ǜ → Ǐ..Ǜ Watin-B */
922
+ } else if (0xab70 <= c && c <= 0xabbf) {
923
+ return c - 38864; /* 80x ꭰ ..ꮿ → Ꭰ ..Ꮿ Cherokee Supplement */
924
+ } else {
925
+ static const struct {
926
+ unsigned short a;
927
+ unsigned short b;
928
+ short d;
929
+ } kUpper[] = {
930
+ {0x00b5, 0x00b5, +743}, /* 1x µ ..µ → Μ ..Μ Watin */
931
+ {0x00e0, 0x00f6, -32}, /* 23x à ..ö → À ..Ö Watin */
932
+ {0x00f8, 0x00fe, -32}, /* 7x ø ..þ → Ø ..Þ Watin */
933
+ {0x00ff, 0x00ff, +121}, /* 1x ÿ ..ÿ → Ÿ ..Ÿ Watin */
934
+ {0x017a, 0x017a, -1}, /* 1x ź ..ź → Ź ..Ź Watin-A */
935
+ {0x017c, 0x017c, -1}, /* 1x ż ..ż → Ż ..Ż Watin-A */
936
+ {0x017e, 0x017e, -1}, /* 1x ž ..ž → Ž ..Ž Watin-A */
937
+ {0x017f, 0x017f, -300}, /* 1x ſ ..ſ → S ..S Watin-A */
938
+ {0x0180, 0x0180, +195}, /* 1x ƀ ..ƀ → Ƀ ..Ƀ Watin-B */
939
+ {0x0183, 0x0183, -1}, /* 1x ƃ ..ƃ → Ƃ ..Ƃ Watin-B */
940
+ {0x0185, 0x0185, -1}, /* 1x ƅ ..ƅ → Ƅ ..Ƅ Watin-B */
941
+ {0x0188, 0x0188, -1}, /* 1x ƈ ..ƈ → Ƈ ..Ƈ Watin-B */
942
+ {0x018c, 0x018c, -1}, /* 1x ƌ ..ƌ → Ƌ ..Ƌ Watin-B */
943
+ {0x0192, 0x0192, -1}, /* 1x ƒ ..ƒ → Ƒ ..Ƒ Watin-B */
944
+ {0x0195, 0x0195, +97}, /* 1x ƕ ..ƕ → Ƕ ..Ƕ Watin-B */
945
+ {0x0199, 0x0199, -1}, /* 1x ƙ ..ƙ → Ƙ ..Ƙ Watin-B */
946
+ {0x019a, 0x019a, +163}, /* 1x ƚ ..ƚ → Ƚ ..Ƚ Watin-B */
947
+ {0x019e, 0x019e, +130}, /* 1x ƞ ..ƞ → Ƞ ..Ƞ Watin-B */
948
+ {0x01a1, 0x01a1, -1}, /* 1x ơ ..ơ → Ơ ..Ơ Watin-B */
949
+ {0x01a3, 0x01a3, -1}, /* 1x ƣ ..ƣ → Ƣ ..Ƣ Watin-B */
950
+ {0x01a5, 0x01a5, -1}, /* 1x ƥ ..ƥ → Ƥ ..Ƥ Watin-B */
951
+ {0x01a8, 0x01a8, -1}, /* 1x ƨ ..ƨ → Ƨ ..Ƨ Watin-B */
952
+ {0x01ad, 0x01ad, -1}, /* 1x ƭ ..ƭ → Ƭ ..Ƭ Watin-B */
953
+ {0x01b0, 0x01b0, -1}, /* 1x ư ..ư → Ư ..Ư Watin-B */
954
+ {0x01b4, 0x01b4, -1}, /* 1x ƴ ..ƴ → Ƴ ..Ƴ Watin-B */
955
+ {0x01b6, 0x01b6, -1}, /* 1x ƶ ..ƶ → Ƶ ..Ƶ Watin-B */
956
+ {0x01b9, 0x01b9, -1}, /* 1x ƹ ..ƹ → Ƹ ..Ƹ Watin-B */
957
+ {0x01bd, 0x01bd, -1}, /* 1x ƽ ..ƽ → Ƽ ..Ƽ Watin-B */
958
+ {0x01bf, 0x01bf, +56}, /* 1x ƿ ..ƿ → Ƿ ..Ƿ Watin-B */
959
+ {0x01c5, 0x01c5, -1}, /* 1x Dž ..Dž → DŽ ..DŽ Watin-B */
960
+ {0x01c6, 0x01c6, -2}, /* 1x dž ..dž → DŽ ..DŽ Watin-B */
961
+ {0x01c8, 0x01c8, -1}, /* 1x Lj ..Lj → LJ ..LJ Watin-B */
962
+ {0x01c9, 0x01c9, -2}, /* 1x lj ..lj → LJ ..LJ Watin-B */
963
+ {0x01cb, 0x01cb, -1}, /* 1x Nj ..Nj → NJ ..NJ Watin-B */
964
+ {0x01cc, 0x01cc, -2}, /* 1x nj ..nj → NJ ..NJ Watin-B */
965
+ {0x01ce, 0x01ce, -1}, /* 1x ǎ ..ǎ → Ǎ ..Ǎ Watin-B */
966
+ {0x01dd, 0x01dd, -79}, /* 1x ǝ ..ǝ → Ǝ ..Ǝ Watin-B */
967
+ {0x01f2, 0x01f2, -1}, /* 1x Dz ..Dz → DZ ..DZ Watin-B */
968
+ {0x01f3, 0x01f3, -2}, /* 1x dz ..dz → DZ ..DZ Watin-B */
969
+ {0x01f5, 0x01f5, -1}, /* 1x ǵ ..ǵ → Ǵ ..Ǵ Watin-B */
970
+ {0x023c, 0x023c, -1}, /* 1x ȼ ..ȼ → Ȼ ..Ȼ Watin-B */
971
+ {0x023f, 0x0240,+10815}, /* 2x ȿ ..ɀ → Ȿ ..Ɀ Watin-B */
972
+ {0x0242, 0x0242, -1}, /* 1x ɂ ..ɂ → Ɂ ..Ɂ Watin-B */
973
+ {0x0247, 0x0247, -1}, /* 1x ɇ ..ɇ → Ɇ ..Ɇ Watin-B */
974
+ {0x0249, 0x0249, -1}, /* 1x ɉ ..ɉ → Ɉ ..Ɉ Watin-B */
975
+ {0x024b, 0x024b, -1}, /* 1x ɋ ..ɋ → Ɋ ..Ɋ Watin-B */
976
+ {0x024d, 0x024d, -1}, /* 1x ɍ ..ɍ → Ɍ ..Ɍ Watin-B */
977
+ {0x024f, 0x024f, -1}, /* 1x ɏ ..ɏ → Ɏ ..Ɏ Watin-B */
978
+ {0x037b, 0x037d, +130}, /* 3x ͻ ..ͽ → Ͻ ..Ͽ Greek */
979
+ {0x03ac, 0x03ac, -38}, /* 1x ά ..ά → Ά ..Ά Greek */
980
+ {0x03ad, 0x03af, -37}, /* 3x έ ..ί → Έ ..Ί Greek */
981
+ {0x03b1, 0x03c1, -32}, /* 17x α ..ρ → Α ..Ρ Greek */
982
+ {0x03c2, 0x03c2, -31}, /* 1x ς ..ς → Σ ..Σ Greek */
983
+ {0x03c3, 0x03cb, -32}, /* 9x σ ..ϋ → Σ ..Ϋ Greek */
984
+ {0x03cc, 0x03cc, -64}, /* 1x ό ..ό → Ό ..Ό Greek */
985
+ {0x03cd, 0x03ce, -63}, /* 2x ύ ..ώ → Ύ ..Ώ Greek */
986
+ {0x03d0, 0x03d0, -62}, /* 1x ϐ ..ϐ → Β ..Β Greek */
987
+ {0x03d1, 0x03d1, -57}, /* 1x ϑ ..ϑ → Θ ..Θ Greek */
988
+ {0x03d5, 0x03d5, -47}, /* 1x ϕ ..ϕ → Φ ..Φ Greek */
989
+ {0x03d6, 0x03d6, -54}, /* 1x ϖ ..ϖ → Π ..Π Greek */
990
+ {0x03dd, 0x03dd, -1}, /* 1x ϝ ..ϝ → Ϝ ..Ϝ Greek */
991
+ {0x03f0, 0x03f0, -86}, /* 1x ϰ ..ϰ → Κ ..Κ Greek */
992
+ {0x03f1, 0x03f1, -80}, /* 1x ϱ ..ϱ → Ρ ..Ρ Greek */
993
+ {0x03f5, 0x03f5, -96}, /* 1x ϵ ..ϵ → Ε ..Ε Greek */
994
+ {0x0430, 0x044f, -32}, /* 32x а ..я → А ..Я Cyrillic */
995
+ {0x0450, 0x045f, -80}, /* 16x ѐ ..џ → Ѐ ..Џ Cyrillic */
996
+ {0x0461, 0x0461, -1}, /* 1x ѡ ..ѡ → Ѡ ..Ѡ Cyrillic */
997
+ {0x0463, 0x0463, -1}, /* 1x ѣ ..ѣ → Ѣ ..Ѣ Cyrillic */
998
+ {0x0465, 0x0465, -1}, /* 1x ѥ ..ѥ → Ѥ ..Ѥ Cyrillic */
999
+ {0x0473, 0x0473, -1}, /* 1x ѳ ..ѳ → Ѳ ..Ѳ Cyrillic */
1000
+ {0x0491, 0x0491, -1}, /* 1x ґ ..ґ → Ґ ..Ґ Cyrillic */
1001
+ {0x0499, 0x0499, -1}, /* 1x ҙ ..ҙ → Ҙ ..Ҙ Cyrillic */
1002
+ {0x049b, 0x049b, -1}, /* 1x қ ..қ → Қ ..Қ Cyrillic */
1003
+ {0x0561, 0x0586, -48}, /* 38x ա ..ֆ → Ա ..Ֆ Armenian */
1004
+ {0x10d0, 0x10fa, +3008}, /* 43x ა ..ჺ → Ა ..Ჺ Georgian */
1005
+ {0x10fd, 0x10ff, +3008}, /* 3x ჽ ..ჿ → Ჽ ..Ჿ Georgian */
1006
+ {0x13f8, 0x13fd, -8}, /* 6x ᏸ ..ᏽ → Ᏸ ..Ᏽ Cherokee */
1007
+ {0x214e, 0x214e, -28}, /* 1x ⅎ ..ⅎ → Ⅎ ..Ⅎ Letterlike */
1008
+ {0x2170, 0x217f, -16}, /* 16x ⅰ ..ⅿ → Ⅰ ..Ⅿ Numbery */
1009
+ {0x2184, 0x2184, -1}, /* 1x ↄ ..ↄ → Ↄ ..Ↄ Numbery */
1010
+ {0x24d0, 0x24e9, -26}, /* 26x ⓐ ..ⓩ → Ⓐ ..Ⓩ Enclosed */
1011
+ {0x2c30, 0x2c5e, -48}, /* 47x ⰰ ..ⱞ → Ⰰ ..Ⱞ Glagolitic */
1012
+ {0x2d00, 0x2d25, -7264}, /* 38x ⴀ ..ⴥ → Ⴀ ..Ⴥ Georgian2 */
1013
+ {0x2d27, 0x2d27, -7264}, /* 1x ⴧ ..ⴧ → Ⴧ ..Ⴧ Georgian2 */
1014
+ {0x2d2d, 0x2d2d, -7264}, /* 1x ⴭ ..ⴭ → Ⴭ ..Ⴭ Georgian2 */
1015
+ {0xff41, 0xff5a, -32}, /* 26x a..z → A..Z Dubs */
1016
+ };
1017
+ l = 0;
1018
+ r = n = sizeof(kUpper) / sizeof(kUpper[0]);
1019
+ while (l < r) {
1020
+ m = (l + r) >> 1;
1021
+ if (kUpper[m].b < c) {
1022
+ l = m + 1;
1023
+ } else {
1024
+ r = m;
1025
+ }
1026
+ }
1027
+ if (l < n && kUpper[l].a <= c && c <= kUpper[l].b) {
1028
+ return c + kUpper[l].d;
1029
+ } else {
1030
+ return c;
1031
+ }
1032
+ }
1033
+ } else {
1034
+ static const struct {
1035
+ unsigned a;
1036
+ unsigned b;
1037
+ short d;
1038
+ } kAstralUpper[] = {
1039
+ {0x10428, 0x1044f, -40}, /* 40x 𐐨..𐑏 → 𐐀..𐐧 Deseret */
1040
+ {0x104d8, 0x104fb, -40}, /* 36x 𐓘..𐓻 → 𐒰..𐓓 Osage */
1041
+ {0x1d41a, 0x1d433, -26}, /* 26x 𝐚..𝐳 → 𝐀..𝐙 Math */
1042
+ {0x1d456, 0x1d467, -26}, /* 18x 𝑖..𝑧 → 𝐼..𝑍 Math */
1043
+ {0x1d482, 0x1d49b, -26}, /* 26x 𝒂..𝒛 → 𝑨..𝒁 Math */
1044
+ {0x1d4c8, 0x1d4cf, -26}, /* 8x 𝓈..𝓏 → 𝒮..𝒵 Math */
1045
+ {0x1d4ea, 0x1d503, -26}, /* 26x 𝓪..𝔃 → 𝓐..𝓩 Math */
1046
+ {0x1d527, 0x1d52e, -26}, /* 8x 𝔧..𝔮 → 𝔍..𝔔 Math */
1047
+ {0x1d586, 0x1d59f, -26}, /* 26x 𝖆..𝖟 → 𝕬..𝖅 Math */
1048
+ {0x1d5ba, 0x1d5d3, -26}, /* 26x 𝖺..𝗓 → 𝖠..𝖹 Math */
1049
+ {0x1d5ee, 0x1d607, -26}, /* 26x 𝗮..𝘇 → 𝗔..𝗭 Math */
1050
+ {0x1d622, 0x1d63b, -26}, /* 26x 𝘢..𝘻 → 𝘈..𝘡 Math */
1051
+ {0x1d68a, 0x1d6a3, +442}, /* 26x 𝒂..𝒛 → 𝘼..𝙕 Math */
1052
+ {0x1d6c2, 0x1d6d2, -26}, /* 26x 𝚊..𝚣 → 𝙰..𝚉 Math */
1053
+ {0x1d6fc, 0x1d70c, -26}, /* 17x 𝛂..𝛒 → 𝚨..𝚸 Math */
1054
+ {0x1d736, 0x1d746, -26}, /* 17x 𝛼..𝜌 → 𝛢..𝛲 Math */
1055
+ {0x1d770, 0x1d780, -26}, /* 17x 𝜶..𝝆 → 𝜜..𝜬 Math */
1056
+ {0x1d770, 0x1d756, -26}, /* 17x 𝝰..𝞀 → 𝝖..𝝦 Math */
1057
+ {0x1d736, 0x1d790, -90}, /* 17x 𝜶..𝝆 → 𝞐..𝞠 Math */
1058
+ };
1059
+ l = 0;
1060
+ r = n = sizeof(kAstralUpper) / sizeof(kAstralUpper[0]);
1061
+ while (l < r) {
1062
+ m = (l + r) >> 1;
1063
+ if (kAstralUpper[m].b < c) {
1064
+ l = m + 1;
1065
+ } else {
1066
+ r = m;
1067
+ }
1068
+ }
1069
+ if (l < n && kAstralUpper[l].a <= c && c <= kAstralUpper[l].b) {
1070
+ return c + kAstralUpper[l].d;
1071
+ } else {
1072
+ return c;
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ char bestlineNotSeparator(unsigned c) {
1078
+ return !bestlineIsSeparator(c);
1079
+ }
1080
+
1081
+ static unsigned GetMirror(const unsigned short A[][2], size_t n, unsigned c) {
1082
+ int l, m, r;
1083
+ l = 0;
1084
+ r = n - 1;
1085
+ while (l <= r) {
1086
+ m = (l + r) >> 1;
1087
+ if (A[m][0] < c) {
1088
+ l = m + 1;
1089
+ } else if (A[m][0] > c) {
1090
+ r = m - 1;
1091
+ } else {
1092
+ return A[m][1];
1093
+ }
1094
+ }
1095
+ return 0;
1096
+ }
1097
+
1098
+ unsigned bestlineMirrorLeft(unsigned c) {
1099
+ static const unsigned short kMirrorRight[][2] = {
1100
+ {L')', L'('}, {L']', L'['}, {L'}', L'{'}, {L'⁆', L'⁅'},
1101
+ {L'⁾', L'⁽'}, {L'₎', L'₍'}, {L'⌉', L'⌈'}, {L'⌋', L'⌊'},
1102
+ {L'〉', L'〈'}, {L'❩', L'❨'}, {L'❫', L'❪'}, {L'❭', L'❬'},
1103
+ {L'❯', L'❮'}, {L'❱', L'❰'}, {L'❳', L'❲'}, {L'❵', L'❴'},
1104
+ {L'⟆', L'⟅'}, {L'⟧', L'⟦'}, {L'⟩', L'⟨'}, {L'⟫', L'⟪'},
1105
+ {L'⟭', L'⟬'}, {L'⟯', L'⟮'}, {L'⦄', L'⦃'}, {L'⦆', L'⦅'},
1106
+ {L'⦈', L'⦇'}, {L'⦊', L'⦉'}, {L'⦌', L'⦋'}, {L'⦎', L'⦏'},
1107
+ {L'⦐', L'⦍'}, {L'⦒', L'⦑'}, {L'⦔', L'⦓'}, {L'⦘', L'⦗'},
1108
+ {L'⧙', L'⧘'}, {L'⧛', L'⧚'}, {L'⧽', L'⧼'}, {L'﹚', L'﹙'},
1109
+ {L'﹜', L'﹛'}, {L'﹞', L'﹝'}, {L')', L'('}, {L']', L'['},
1110
+ {L'}', L'{'}, {L'」', L'「'},
1111
+ };
1112
+ return GetMirror(kMirrorRight,
1113
+ sizeof(kMirrorRight) / sizeof(kMirrorRight[0]),
1114
+ c);
1115
+ }
1116
+
1117
+ unsigned bestlineMirrorRight(unsigned c) {
1118
+ static const unsigned short kMirrorLeft[][2] = {
1119
+ {L'(', L')'}, {L'[', L']'}, {L'{', L'}'}, {L'⁅', L'⁆'},
1120
+ {L'⁽', L'⁾'}, {L'₍', L'₎'}, {L'⌈', L'⌉'}, {L'⌊', L'⌋'},
1121
+ {L'〈', L'〉'}, {L'❨', L'❩'}, {L'❪', L'❫'}, {L'❬', L'❭'},
1122
+ {L'❮', L'❯'}, {L'❰', L'❱'}, {L'❲', L'❳'}, {L'❴', L'❵'},
1123
+ {L'⟅', L'⟆'}, {L'⟦', L'⟧'}, {L'⟨', L'⟩'}, {L'⟪', L'⟫'},
1124
+ {L'⟬', L'⟭'}, {L'⟮', L'⟯'}, {L'⦃', L'⦄'}, {L'⦅', L'⦆'},
1125
+ {L'⦇', L'⦈'}, {L'⦉', L'⦊'}, {L'⦋', L'⦌'}, {L'⦍', L'⦐'},
1126
+ {L'⦏', L'⦎'}, {L'⦑', L'⦒'}, {L'⦓', L'⦔'}, {L'⦗', L'⦘'},
1127
+ {L'⧘', L'⧙'}, {L'⧚', L'⧛'}, {L'⧼', L'⧽'}, {L'﹙', L'﹚'},
1128
+ {L'﹛', L'﹜'}, {L'﹝', L'﹞'}, {L'(', L')'}, {L'[', L']'},
1129
+ {L'{', L'}'}, {L'「', L'」'},
1130
+ };
1131
+ return GetMirror(kMirrorLeft,
1132
+ sizeof(kMirrorLeft) / sizeof(kMirrorLeft[0]),
1133
+ c);
1134
+ }
1135
+
1136
+ char bestlineIsXeparator(unsigned c) {
1137
+ return (bestlineIsSeparator(c) &&
1138
+ !bestlineMirrorLeft(c) &&
1139
+ !bestlineMirrorRight(c));
1140
+ }
1141
+
1142
+ static unsigned Capitalize(unsigned c) {
1143
+ if (!iscapital) {
1144
+ c = bestlineUppercase(c);
1145
+ iscapital = 1;
1146
+ }
1147
+ return c;
1148
+ }
1149
+
1150
+ static inline int Bsr(unsigned long long x) {
1151
+ #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
1152
+ int b;
1153
+ b = __builtin_clzll(x);
1154
+ b ^= sizeof(unsigned long long) * CHAR_BIT - 1;
1155
+ return b;
1156
+ #else
1157
+ static const char kDebruijn[64] = {
1158
+ 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28, 16, 3, 61,
1159
+ 54, 58, 35, 52, 50, 42, 21, 44, 38, 32, 29, 23, 17, 11, 4, 62,
1160
+ 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43, 31, 22, 10, 45,
1161
+ 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63,
1162
+ };
1163
+ x |= x >> 1;
1164
+ x |= x >> 2;
1165
+ x |= x >> 4;
1166
+ x |= x >> 8;
1167
+ x |= x >> 16;
1168
+ x |= x >> 32;
1169
+ return kDebruijn[(x * 0x03f79d71b4cb0a89) >> 58];
1170
+ #endif
1171
+ }
1172
+
1173
+ static struct rune DecodeUtf8(int c) {
1174
+ struct rune r;
1175
+ if (c < 252) {
1176
+ r.n = Bsr(255 & ~c);
1177
+ r.c = c & (((1 << r.n) - 1) | 3);
1178
+ r.n = 6 - r.n;
1179
+ } else {
1180
+ r.c = c & 3;
1181
+ r.n = 5;
1182
+ }
1183
+ return r;
1184
+ }
1185
+
1186
+ static unsigned long long EncodeUtf8(unsigned c) {
1187
+ static const unsigned short kTpEnc[32 - 7] = {
1188
+ 1|0300<<8, 1|0300<<8, 1|0300<<8, 1|0300<<8, 2|0340<<8,
1189
+ 2|0340<<8, 2|0340<<8, 2|0340<<8, 2|0340<<8, 3|0360<<8,
1190
+ 3|0360<<8, 3|0360<<8, 3|0360<<8, 3|0360<<8, 4|0370<<8,
1191
+ 4|0370<<8, 4|0370<<8, 4|0370<<8, 4|0370<<8, 5|0374<<8,
1192
+ 5|0374<<8, 5|0374<<8, 5|0374<<8, 5|0374<<8, 5|0374<<8,
1193
+ };
1194
+ int e, n;
1195
+ unsigned long long w;
1196
+ if (c < 0200) return c;
1197
+ e = kTpEnc[Bsr(c) - 7];
1198
+ n = e & 0xff;
1199
+ w = 0;
1200
+ do {
1201
+ w |= 0200 | (c & 077);
1202
+ w <<= 8;
1203
+ c >>= 6;
1204
+ } while (--n);
1205
+ return c | w | e >> 8;
1206
+ }
1207
+
1208
+ static struct rune GetUtf8(const char *p, size_t n) {
1209
+ struct rune r;
1210
+ if ((r.n = r.c = 0) < n && (r.c = p[r.n++] & 255) >= 0300) {
1211
+ r.c = DecodeUtf8(r.c).c;
1212
+ while (r.n < n && (p[r.n] & 0300) == 0200) {
1213
+ r.c = r.c << 6 | (p[r.n++] & 077);
1214
+ }
1215
+ }
1216
+ return r;
1217
+ }
1218
+
1219
+ static char *FormatUnsigned(char *p, unsigned x) {
1220
+ char t;
1221
+ size_t i, a, b;
1222
+ i = 0;
1223
+ do {
1224
+ p[i++] = x % 10 + '0';
1225
+ x = x / 10;
1226
+ } while (x > 0);
1227
+ p[i] = '\0';
1228
+ if (i) {
1229
+ for (a = 0, b = i - 1; a < b; ++a, --b) {
1230
+ t = p[a];
1231
+ p[a] = p[b];
1232
+ p[b] = t;
1233
+ }
1234
+ }
1235
+ return p + i;
1236
+ }
1237
+
1238
+ static void abInit(struct abuf *a) {
1239
+ a->len = 0;
1240
+ a->cap = 16;
1241
+ a->b = (char *)malloc(a->cap);
1242
+ a->b[0] = 0;
1243
+ }
1244
+
1245
+ static char abGrow(struct abuf *a, int need) {
1246
+ int cap;
1247
+ char *b;
1248
+ cap = a->cap;
1249
+ do cap += cap / 2;
1250
+ while (cap < need);
1251
+ if (!(b = (char *)realloc(a->b, cap * sizeof(*a->b)))) return 0;
1252
+ a->cap = cap;
1253
+ a->b = b;
1254
+ return 1;
1255
+ }
1256
+
1257
+ static void abAppendw(struct abuf *a, unsigned long long w) {
1258
+ char *p;
1259
+ if (a->len + 8 > a->cap && !abGrow(a, a->len + 8)) return;
1260
+ p = a->b + a->len;
1261
+ p[0] = (0x00000000000000FF & w) >> 000;
1262
+ p[1] = (0x000000000000FF00 & w) >> 010;
1263
+ p[2] = (0x0000000000FF0000 & w) >> 020;
1264
+ p[3] = (0x00000000FF000000 & w) >> 030;
1265
+ p[4] = (0x000000FF00000000 & w) >> 040;
1266
+ p[5] = (0x0000FF0000000000 & w) >> 050;
1267
+ p[6] = (0x00FF000000000000 & w) >> 060;
1268
+ p[7] = (0xFF00000000000000 & w) >> 070;
1269
+ a->len += w ? (Bsr(w) >> 3) + 1 : 1;
1270
+ }
1271
+
1272
+ static void abAppend(struct abuf *a, const char *s, int len) {
1273
+ if (a->len + len + 1 > a->cap && !abGrow(a, a->len + len + 1)) return;
1274
+ memcpy(a->b + a->len, s, len);
1275
+ a->b[a->len + len] = 0;
1276
+ a->len += len;
1277
+ }
1278
+
1279
+ static void abAppends(struct abuf *a, const char *s) {
1280
+ abAppend(a, s, strlen(s));
1281
+ }
1282
+
1283
+ static void abAppendu(struct abuf *a, unsigned u) {
1284
+ char b[11];
1285
+ abAppend(a, b, FormatUnsigned(b, u) - b);
1286
+ }
1287
+
1288
+ static void abFree(struct abuf *a) {
1289
+ free(a->b);
1290
+ a->b = 0;
1291
+ }
1292
+
1293
+ static size_t GetFdSize(int fd) {
1294
+ struct stat st;
1295
+ st.st_size = 0;
1296
+ fstat(fd, &st);
1297
+ return st.st_size;
1298
+ }
1299
+
1300
+ static char IsCharDev(int fd) {
1301
+ struct stat st;
1302
+ st.st_mode = 0;
1303
+ fstat(fd, &st);
1304
+ return (st.st_mode & S_IFMT) == S_IFCHR;
1305
+ }
1306
+
1307
+ static int WaitUntilReady(int fd, int events) {
1308
+ struct pollfd p[1];
1309
+ p[0].fd = fd;
1310
+ p[0].events = events;
1311
+ return poll(p, 1, -1);
1312
+ }
1313
+
1314
+ static char HasPendingInput(int fd) {
1315
+ struct pollfd p[1];
1316
+ p[0].fd = fd;
1317
+ p[0].events = POLLIN;
1318
+ return poll(p, 1, 0) == 1;
1319
+ }
1320
+
1321
+ static char *GetLineBlock(FILE *f) {
1322
+ ssize_t rc;
1323
+ char *p = 0;
1324
+ size_t n, c = 0;
1325
+ if ((rc = getdelim(&p, &c, '\n', f)) != EOF) {
1326
+ for (n = rc; n; --n) {
1327
+ if (p[n - 1] == '\r' || p[n - 1] == '\n') {
1328
+ p[n - 1] = 0;
1329
+ } else {
1330
+ break;
1331
+ }
1332
+ }
1333
+ return p;
1334
+ } else {
1335
+ free(p);
1336
+ return 0;
1337
+ }
1338
+ }
1339
+
1340
+ long bestlineReadCharacter(int fd, char *p, unsigned long n) {
1341
+ int e;
1342
+ size_t i;
1343
+ ssize_t rc;
1344
+ struct rune r;
1345
+ unsigned char c;
1346
+ enum { kAscii, kUtf8, kEsc, kCsi1, kCsi2, kSs, kNf, kStr, kStr2, kDone } t;
1347
+ i = 0;
1348
+ r.c = 0;
1349
+ r.n = 0;
1350
+ e = errno;
1351
+ t = kAscii;
1352
+ if (n) p[0] = 0;
1353
+ do {
1354
+ for (;;) {
1355
+ if (gotint) {
1356
+ errno = EINTR;
1357
+ return -1;
1358
+ }
1359
+ if (n) {
1360
+ rc = read(fd,&c,1);
1361
+ } else {
1362
+ rc = read(fd,0,0);
1363
+ }
1364
+ if (rc == -1 && errno == EINTR) {
1365
+ if (!i) {
1366
+ return -1;
1367
+ }
1368
+ } else if (rc == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
1369
+ if (WaitUntilReady(fd, POLLIN) == -1) {
1370
+ if (rc == -1 && errno == EINTR) {
1371
+ if (!i) {
1372
+ return -1;
1373
+ }
1374
+ } else {
1375
+ return -1;
1376
+ }
1377
+ }
1378
+ } else if (rc == -1) {
1379
+ return -1;
1380
+ } else if (!rc) {
1381
+ if (!i) {
1382
+ errno = e;
1383
+ return 0;
1384
+ } else {
1385
+ errno = EILSEQ;
1386
+ return -1;
1387
+ }
1388
+ } else {
1389
+ break;
1390
+ }
1391
+ }
1392
+ if (i + 1 < n) {
1393
+ p[i] = c;
1394
+ p[i+1] = 0;
1395
+ } else if (i < n) {
1396
+ p[i] = 0;
1397
+ }
1398
+ ++i;
1399
+ switch (t) {
1400
+ Whoopsie:
1401
+ if (n) p[0] = c;
1402
+ t = kAscii;
1403
+ i = 1;
1404
+ /* fallthrough */
1405
+ case kAscii:
1406
+ if (c < 0200) {
1407
+ if (c == 033) {
1408
+ t = kEsc;
1409
+ } else {
1410
+ t = kDone;
1411
+ }
1412
+ } else if (c >= 0300) {
1413
+ t = kUtf8;
1414
+ r = DecodeUtf8(c);
1415
+ } else {
1416
+ /* ignore overlong sequences */
1417
+ }
1418
+ break;
1419
+ case kUtf8:
1420
+ if ((c & 0300) == 0200) {
1421
+ r.c <<= 6;
1422
+ r.c |= c & 077;
1423
+ if (!--r.n) {
1424
+ switch (r.c) {
1425
+ case 033:
1426
+ t = kEsc; /* parsed but not canonicalized */
1427
+ break;
1428
+ case 0x9b:
1429
+ t = kCsi1; /* unusual but legal */
1430
+ break;
1431
+ case 0x8e: /* SS2 (Single Shift Two) */
1432
+ case 0x8f: /* SS3 (Single Shift Three) */
1433
+ t = kSs;
1434
+ break;
1435
+ case 0x90: /* DCS (Device Control String) */
1436
+ case 0x98: /* SOS (Start of String) */
1437
+ case 0x9d: /* OSC (Operating System Command) */
1438
+ case 0x9e: /* PM (Privacy Message) */
1439
+ case 0x9f: /* APC (Application Program Command) */
1440
+ t = kStr;
1441
+ break;
1442
+ default:
1443
+ t = kDone;
1444
+ break;
1445
+ }
1446
+ }
1447
+ } else {
1448
+ goto Whoopsie; /* ignore underlong sequences if not eof */
1449
+ }
1450
+ break;
1451
+ case kEsc:
1452
+ if (0x20 <= c && c <= 0x2f) { /* Nf */
1453
+ /*
1454
+ * Almost no one uses ANSI Nf sequences
1455
+ * They overlaps with alt+graphic keystrokes
1456
+ * We care more about being able to type alt-/
1457
+ */
1458
+ if (c == ' ' || c == '#') {
1459
+ t = kNf;
1460
+ } else {
1461
+ t = kDone;
1462
+ }
1463
+ } else if (0x30 <= c && c <= 0x3f) { /* Fp */
1464
+ t = kDone;
1465
+ } else if (0x20 <= c && c <= 0x5F) { /* Fe */
1466
+ switch (c) {
1467
+ case '[':
1468
+ t = kCsi1;
1469
+ break;
1470
+ case 'N': /* SS2 (Single Shift Two) */
1471
+ case 'O': /* SS3 (Single Shift Three) */
1472
+ t = kSs;
1473
+ break;
1474
+ case 'P': /* DCS (Device Control String) */
1475
+ case 'X': /* SOS (Start of String) */
1476
+ case ']': /* OSC (Operating System Command) */
1477
+ case '^': /* PM (Privacy Message) */
1478
+ case '_': /* APC (Application Program Command) */
1479
+ t = kStr;
1480
+ break;
1481
+ default:
1482
+ t = kDone;
1483
+ break;
1484
+ }
1485
+ } else if (0x60 <= c && c <= 0x7e) { /* Fs */
1486
+ t = kDone;
1487
+ } else if (c == 033) {
1488
+ if (i < 3) {
1489
+ /* alt chording */
1490
+ } else {
1491
+ t = kDone; /* esc mashing */
1492
+ i = 1;
1493
+ }
1494
+ } else {
1495
+ t = kDone;
1496
+ }
1497
+ break;
1498
+ case kSs:
1499
+ t = kDone;
1500
+ break;
1501
+ case kNf:
1502
+ if (0x30 <= c && c <= 0x7e) {
1503
+ t = kDone;
1504
+ } else if (!(0x20 <= c && c <= 0x2f)) {
1505
+ goto Whoopsie;
1506
+ }
1507
+ break;
1508
+ case kCsi1:
1509
+ if (0x20 <= c && c <= 0x2f) {
1510
+ t = kCsi2;
1511
+ } else if (c == '[' && ((i == 3) ||
1512
+ (i == 4 && p[1] == 033))) {
1513
+ /* linux function keys */
1514
+ } else if (0x40 <= c && c <= 0x7e) {
1515
+ t = kDone;
1516
+ } else if (!(0x30 <= c && c <= 0x3f)) {
1517
+ goto Whoopsie;
1518
+ }
1519
+ break;
1520
+ case kCsi2:
1521
+ if (0x40 <= c && c <= 0x7e) {
1522
+ t = kDone;
1523
+ } else if (!(0x20 <= c && c <= 0x2f)) {
1524
+ goto Whoopsie;
1525
+ }
1526
+ break;
1527
+ case kStr:
1528
+ switch (c) {
1529
+ case '\a':
1530
+ t = kDone;
1531
+ break;
1532
+ case 0033: /* ESC */
1533
+ case 0302: /* C1 (UTF-8) */
1534
+ t = kStr2;
1535
+ break;
1536
+ default:
1537
+ break;
1538
+ }
1539
+ break;
1540
+ case kStr2:
1541
+ switch (c) {
1542
+ case '\a':
1543
+ case '\\': /* ST (ASCII) */
1544
+ case 0234: /* ST (UTF-8) */
1545
+ t = kDone;
1546
+ break;
1547
+ default:
1548
+ t = kStr;
1549
+ break;
1550
+ }
1551
+ break;
1552
+ default:
1553
+ assert(0);
1554
+ }
1555
+ } while (t != kDone);
1556
+ errno = e;
1557
+ return i;
1558
+ }
1559
+
1560
+ static char *GetLineChar(int fin, int fout) {
1561
+ size_t got;
1562
+ ssize_t rc;
1563
+ char seq[16];
1564
+ struct abuf a;
1565
+ struct sigaction sa[3];
1566
+ abInit(&a);
1567
+ gotint = 0;
1568
+ sigemptyset(&sa->sa_mask);
1569
+ sa->sa_flags = 0;
1570
+ sa->sa_handler = bestlineOnInt;
1571
+ sigaction(SIGINT,sa,sa+1);
1572
+ sigaction(SIGQUIT,sa,sa+2);
1573
+ for (;;) {
1574
+ if (gotint) {
1575
+ rc = -1;
1576
+ break;
1577
+ }
1578
+ if ((rc = bestlineReadCharacter(fin, seq, sizeof(seq))) == -1) {
1579
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
1580
+ if (WaitUntilReady(fin, POLLIN) > 0) {
1581
+ continue;
1582
+ }
1583
+ }
1584
+ if (errno == EINTR) {
1585
+ continue;
1586
+ } else {
1587
+ break;
1588
+ }
1589
+ }
1590
+ if (!(got = rc)) {
1591
+ if (a.len) {
1592
+ break;
1593
+ } else {
1594
+ rc = -1;
1595
+ break;
1596
+ }
1597
+ }
1598
+ if (seq[0] == '\r') {
1599
+ if (HasPendingInput(fin)) {
1600
+ if ((rc = bestlineReadCharacter(fin, seq + 1, sizeof(seq) - 1)) > 0) {
1601
+ if (seq[0] == '\n') {
1602
+ break;
1603
+ }
1604
+ } else {
1605
+ rc = -1;
1606
+ break;
1607
+ }
1608
+ } else {
1609
+ write(fout, "\n", 1);
1610
+ break;
1611
+ }
1612
+ } else if (seq[0] == Ctrl('D')) {
1613
+ break;
1614
+ } else if (seq[0] == '\n') {
1615
+ break;
1616
+ } else if (seq[0] == '\b') {
1617
+ while (a.len && (a.b[a.len - 1] & 0300) == 0200) --a.len;
1618
+ if (a.len) --a.len;
1619
+ }
1620
+ if (!IsControl(seq[0])) {
1621
+ abAppend(&a, seq, got);
1622
+ }
1623
+ }
1624
+ sigaction(SIGQUIT,sa+2,0);
1625
+ sigaction(SIGINT,sa+1,0);
1626
+ if (gotint) {
1627
+ abFree(&a);
1628
+ raise(gotint);
1629
+ errno = EINTR;
1630
+ rc = -1;
1631
+ }
1632
+ if (rc != -1) {
1633
+ return a.b;
1634
+ } else {
1635
+ abFree(&a);
1636
+ return 0;
1637
+ }
1638
+ }
1639
+
1640
+ static char *GetLine(FILE *in, FILE *out) {
1641
+ if (!IsCharDev(fileno(in))) {
1642
+ return GetLineBlock(in);
1643
+ } else {
1644
+ return GetLineChar(fileno(in), fileno(out));
1645
+ }
1646
+ }
1647
+
1648
+ static char *Copy(char *d, const char *s, size_t n) {
1649
+ memcpy(d, s, n);
1650
+ return d + n;
1651
+ }
1652
+
1653
+ static int CompareStrings(const char *a, const char *b) {
1654
+ size_t i;
1655
+ int x, y, c;
1656
+ for (i = 0;; ++i) {
1657
+ x = bestlineLowercase(a[i] & 255);
1658
+ y = bestlineLowercase(b[i] & 255);
1659
+ if ((c = x - y) || !x) {
1660
+ return c;
1661
+ }
1662
+ }
1663
+ }
1664
+
1665
+ static const char *FindSubstringReverse(const char *p, size_t n,
1666
+ const char *q, size_t m) {
1667
+ size_t i;
1668
+ if (m <= n) {
1669
+ n -= m;
1670
+ do {
1671
+ for (i = 0; i < m; ++i) {
1672
+ if (p[n + i] != q[i]) {
1673
+ break;
1674
+ }
1675
+ }
1676
+ if (i == m) {
1677
+ return p + n;
1678
+ }
1679
+ } while (n--);
1680
+ }
1681
+ return 0;
1682
+ }
1683
+
1684
+ static int ParseUnsigned(const char *s, void *e) {
1685
+ int c, x;
1686
+ for (x = 0; (c = *s++);) {
1687
+ if ('0' <= c && c <= '9') {
1688
+ x = Min(c - '0' + x * 10, 32767);
1689
+ } else {
1690
+ break;
1691
+ }
1692
+ }
1693
+ if (e) *(const char **)e = s;
1694
+ return x;
1695
+ }
1696
+
1697
+ /**
1698
+ * Returns UNICODE CJK Monospace Width of string.
1699
+ *
1700
+ * Control codes and ANSI sequences have a width of zero. We only parse
1701
+ * a limited subset of ANSI here since we don't store ANSI codes in the
1702
+ * linenoiseState::buf, but we do encourage CSI color codes in prompts.
1703
+ */
1704
+ static size_t GetMonospaceWidth(const char *p, size_t n, char *out_haswides) {
1705
+ int c, d;
1706
+ size_t i, w;
1707
+ struct rune r;
1708
+ char haswides;
1709
+ enum { kAscii, kUtf8, kEsc, kCsi1, kCsi2 } t;
1710
+ for (haswides = r.c = r.n = w = i = 0, t = kAscii; i < n; ++i) {
1711
+ c = p[i] & 255;
1712
+ switch (t) {
1713
+ Whoopsie:
1714
+ t = kAscii;
1715
+ /* fallthrough */
1716
+ case kAscii:
1717
+ if (c < 0200) {
1718
+ if (c == 033) {
1719
+ t = kEsc;
1720
+ } else {
1721
+ ++w;
1722
+ }
1723
+ } else if (c >= 0300) {
1724
+ t = kUtf8;
1725
+ r = DecodeUtf8(c);
1726
+ }
1727
+ break;
1728
+ case kUtf8:
1729
+ if ((c & 0300) == 0200) {
1730
+ r.c <<= 6;
1731
+ r.c |= c & 077;
1732
+ if (!--r.n) {
1733
+ d = GetMonospaceCharacterWidth(r.c);
1734
+ d = Max(0, d);
1735
+ w += d;
1736
+ haswides |= d > 1;
1737
+ t = kAscii;
1738
+ break;
1739
+ }
1740
+ } else {
1741
+ goto Whoopsie;
1742
+ }
1743
+ break;
1744
+ case kEsc:
1745
+ if (c == '[') {
1746
+ t = kCsi1;
1747
+ } else {
1748
+ t = kAscii;
1749
+ }
1750
+ break;
1751
+ case kCsi1:
1752
+ if (0x20 <= c && c <= 0x2f) {
1753
+ t = kCsi2;
1754
+ } else if (0x40 <= c && c <= 0x7e) {
1755
+ t = kAscii;
1756
+ } else if (!(0x30 <= c && c <= 0x3f)) {
1757
+ goto Whoopsie;
1758
+ }
1759
+ break;
1760
+ case kCsi2:
1761
+ if (0x40 <= c && c <= 0x7e) {
1762
+ t = kAscii;
1763
+ } else if (!(0x20 <= c && c <= 0x2f)) {
1764
+ goto Whoopsie;
1765
+ }
1766
+ break;
1767
+ default:
1768
+ assert(0);
1769
+ }
1770
+ }
1771
+ if (out_haswides) {
1772
+ *out_haswides = haswides;
1773
+ }
1774
+ return w;
1775
+ }
1776
+
1777
+ static int bestlineIsUnsupportedTerm(void) {
1778
+ size_t i;
1779
+ char *term;
1780
+ static char once, res;
1781
+ if (!once) {
1782
+ if ((term = getenv("TERM"))) {
1783
+ for (i = 0; i < sizeof(kUnsupported) / sizeof(*kUnsupported); i++) {
1784
+ if (!CompareStrings(term,kUnsupported[i])) {
1785
+ res = 1;
1786
+ break;
1787
+ }
1788
+ }
1789
+ }
1790
+ once = 1;
1791
+ }
1792
+ return res;
1793
+ }
1794
+
1795
+ static int enableRawMode(int fd) {
1796
+ struct termios raw;
1797
+ struct sigaction sa;
1798
+ if (tcgetattr(fd,&orig_termios) != -1) {
1799
+ raw = orig_termios;
1800
+ raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
1801
+ raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
1802
+ raw.c_oflag &= ~OPOST;
1803
+ raw.c_iflag |= IUTF8;
1804
+ raw.c_cflag |= CS8;
1805
+ raw.c_cc[VMIN] = 1;
1806
+ raw.c_cc[VTIME] = 0;
1807
+ if (tcsetattr(fd,TCSANOW,&raw) != -1) {
1808
+ sa.sa_flags = 0;
1809
+ sa.sa_handler = bestlineOnCont;
1810
+ sigemptyset(&sa.sa_mask);
1811
+ sigaction(SIGCONT,&sa,&orig_cont);
1812
+ sa.sa_handler = bestlineOnWinch;
1813
+ sigaction(SIGWINCH,&sa,&orig_winch);
1814
+ rawmode = fd;
1815
+ gotwinch = 0;
1816
+ gotcont = 0;
1817
+ return 0;
1818
+ }
1819
+ }
1820
+ errno = ENOTTY;
1821
+ return -1;
1822
+ }
1823
+
1824
+ static void bestlineUnpause(int fd) {
1825
+ if (ispaused) {
1826
+ tcflow(fd, TCOON);
1827
+ ispaused = 0;
1828
+ }
1829
+ }
1830
+
1831
+ void bestlineDisableRawMode(void) {
1832
+ if (rawmode != -1) {
1833
+ bestlineUnpause(rawmode);
1834
+ sigaction(SIGCONT,&orig_cont,0);
1835
+ sigaction(SIGWINCH,&orig_winch,0);
1836
+ tcsetattr(rawmode,TCSANOW,&orig_termios);
1837
+ rawmode = -1;
1838
+ }
1839
+ }
1840
+
1841
+ static int bestlineWrite(int fd, const void *p, size_t n) {
1842
+ ssize_t rc;
1843
+ size_t wrote;
1844
+ do {
1845
+ for (;;) {
1846
+ if (gotint) {
1847
+ errno = EINTR;
1848
+ return -1;
1849
+ }
1850
+ if (ispaused) {
1851
+ return 0;
1852
+ }
1853
+ rc = write(fd, p, n);
1854
+ if (rc == -1 && errno == EINTR) {
1855
+ continue;
1856
+ } else if (rc == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
1857
+ if (WaitUntilReady(fd, POLLOUT) == -1) {
1858
+ if (errno == EINTR) {
1859
+ continue;
1860
+ } else {
1861
+ return -1;
1862
+ }
1863
+ }
1864
+ } else {
1865
+ break;
1866
+ }
1867
+ }
1868
+ if (rc != -1) {
1869
+ wrote = rc;
1870
+ n -= wrote;
1871
+ p = (char *)p + wrote;
1872
+ } else {
1873
+ return -1;
1874
+ }
1875
+ } while (n);
1876
+ return 0;
1877
+ }
1878
+
1879
+ static int bestlineWriteStr(int fd, const char *p) {
1880
+ return bestlineWrite(fd, p, strlen(p));
1881
+ }
1882
+
1883
+ static ssize_t bestlineRead(int fd, char *buf, size_t size,
1884
+ struct bestlineState *l) {
1885
+ size_t got;
1886
+ ssize_t rc;
1887
+ int refreshme;
1888
+ do {
1889
+ refreshme = 0;
1890
+ if (gotint) {
1891
+ errno = EINTR;
1892
+ return -1;
1893
+ }
1894
+ if (gotcont && rawmode != -1) {
1895
+ enableRawMode(rawmode);
1896
+ if (l) refreshme = 1;
1897
+ }
1898
+ if (gotwinch && l) {
1899
+ refreshme = 1;
1900
+ }
1901
+ if (refreshme) bestlineRefreshLine(l);
1902
+ rc = bestlineReadCharacter(fd, buf, size);
1903
+ } while (rc == -1 && errno == EINTR);
1904
+ if (rc != -1) {
1905
+ got = rc;
1906
+ if (got > 0 && l) {
1907
+ memcpy(l->seq[1], l->seq[0], sizeof(l->seq[0]));
1908
+ memset(l->seq[0], 0, sizeof(l->seq[0]));
1909
+ memcpy(l->seq[0], buf, Min(Min(size, got), sizeof(l->seq[0]) - 1));
1910
+ }
1911
+ }
1912
+ return rc;
1913
+ }
1914
+
1915
+ /**
1916
+ * Returns number of columns in current terminal.
1917
+ *
1918
+ * 1. Checks COLUMNS environment variable (set by Emacs)
1919
+ * 2. Tries asking termios (works for pseudoteletypewriters)
1920
+ * 3. Falls back to inband signalling (works w/ pipe or serial)
1921
+ * 4. Otherwise we conservatively assume 80 columns
1922
+ *
1923
+ * @param ws should be initialized by caller to zero before first call
1924
+ * @param ifd is input file descriptor
1925
+ * @param ofd is output file descriptor
1926
+ * @return window size
1927
+ */
1928
+ static struct winsize GetTerminalSize(struct winsize ws, int ifd, int ofd) {
1929
+ int x;
1930
+ ssize_t n;
1931
+ char *p, *s, b[16];
1932
+ ioctl(ofd, TIOCGWINSZ, &ws);
1933
+ if ((!ws.ws_row &&
1934
+ (s = getenv("ROWS")) &&
1935
+ (x = ParseUnsigned(s, 0)))) {
1936
+ ws.ws_row = x;
1937
+ }
1938
+ if ((!ws.ws_col &&
1939
+ (s = getenv("COLUMNS")) &&
1940
+ (x = ParseUnsigned(s, 0)))) {
1941
+ ws.ws_col = x;
1942
+ }
1943
+ if (((!ws.ws_col || !ws.ws_row) &&
1944
+ bestlineRead(ifd,0,0,0) != -1 &&
1945
+ bestlineWriteStr(ofd,
1946
+ "\0337" /* save position */
1947
+ "\033[9979;9979H" /* move cursor to bottom right corner */
1948
+ "\033[6n" /* report position */
1949
+ "\0338") != -1 && /* restore position */
1950
+ (n = bestlineRead(ifd,b,sizeof(b),0)) != -1 &&
1951
+ n && b[0] == 033 && b[1] == '[' && b[n - 1] == 'R')) {
1952
+ p = b+2;
1953
+ if ((x = ParseUnsigned(p,&p))) ws.ws_row = x;
1954
+ if (*p++ == ';' && (x = ParseUnsigned(p,0))) ws.ws_col = x;
1955
+ }
1956
+ if (!ws.ws_col) ws.ws_col = 80;
1957
+ if (!ws.ws_row) ws.ws_row = 24;
1958
+ return ws;
1959
+ }
1960
+
1961
+ /* Clear the screen. Used to handle ctrl+l */
1962
+ void bestlineClearScreen(int fd) {
1963
+ bestlineWriteStr(fd,
1964
+ "\033[H" /* move cursor to top left corner */
1965
+ "\033[2J"); /* erase display */
1966
+ }
1967
+
1968
+ static void bestlineBeep(void) {
1969
+ /* THE TERMINAL BELL IS DEAD - HISTORY HAS KILLED IT */
1970
+ }
1971
+
1972
+ static char bestlineGrow(struct bestlineState *ls, size_t n) {
1973
+ char *p;
1974
+ size_t m;
1975
+ m = ls->buflen;
1976
+ if (m >= n) return 1;
1977
+ do m += m >> 1;
1978
+ while (m < n);
1979
+ if (!(p = (char *)realloc(ls->buf, m * sizeof(*ls->buf)))) return 0;
1980
+ ls->buf = p;
1981
+ ls->buflen = m;
1982
+ return 1;
1983
+ }
1984
+
1985
+ /* This is an helper function for bestlineEdit() and is called when the
1986
+ * user types the <tab> key in order to complete the string currently in the
1987
+ * input.
1988
+ *
1989
+ * The state of the editing is encapsulated into the pointed bestlineState
1990
+ * structure as described in the structure definition. */
1991
+ static ssize_t bestlineCompleteLine(struct bestlineState *ls, char *seq, int size) {
1992
+ ssize_t nread;
1993
+ size_t i, n, stop;
1994
+ bestlineCompletions lc;
1995
+ struct bestlineState saved;
1996
+ nread=0;
1997
+ memset(&lc,0,sizeof(lc));
1998
+ completionCallback(ls->buf,&lc);
1999
+ if (!lc.len) {
2000
+ bestlineBeep();
2001
+ } else {
2002
+ i = 0;
2003
+ stop = 0;
2004
+ while (!stop) {
2005
+ /* Show completion or original buffer */
2006
+ if (i < lc.len) {
2007
+ saved = *ls;
2008
+ ls->len = ls->pos = strlen(lc.cvec[i]);
2009
+ ls->buf = lc.cvec[i];
2010
+ bestlineRefreshLine(ls);
2011
+ ls->len = saved.len;
2012
+ ls->pos = saved.pos;
2013
+ ls->buf = saved.buf;
2014
+ } else {
2015
+ bestlineRefreshLine(ls);
2016
+ }
2017
+ if ((nread = bestlineRead(ls->ifd,seq,size,ls)) <= 0) {
2018
+ bestlineFreeCompletions(&lc);
2019
+ return -1;
2020
+ }
2021
+ switch (seq[0]) {
2022
+ case '\t':
2023
+ i = (i+1) % (lc.len+1);
2024
+ if (i == lc.len) {
2025
+ bestlineBeep();
2026
+ }
2027
+ break;
2028
+ default:
2029
+ if (i < lc.len) {
2030
+ n = strlen(lc.cvec[i]);
2031
+ if (bestlineGrow(ls, n + 1)) {
2032
+ memcpy(ls->buf, lc.cvec[i], n + 1);
2033
+ ls->len = ls->pos = n;
2034
+ }
2035
+ }
2036
+ stop = 1;
2037
+ break;
2038
+ }
2039
+ }
2040
+ }
2041
+ bestlineFreeCompletions(&lc);
2042
+ return nread;
2043
+ }
2044
+
2045
+ static void bestlineEditHistoryGoto(struct bestlineState *l, unsigned i) {
2046
+ size_t n;
2047
+ if (historylen <= 1) return;
2048
+ i = Max(Min(i,historylen-1),0);
2049
+ free(history[historylen - 1 - l->hindex]);
2050
+ history[historylen - 1 - l->hindex] = strdup(l->buf);
2051
+ l->hindex = i;
2052
+ n = strlen(history[historylen - 1 - l->hindex]);
2053
+ bestlineGrow(l, n + 1);
2054
+ n = Min(n, l->buflen - 1);
2055
+ memcpy(l->buf, history[historylen - 1 - l->hindex], n);
2056
+ l->buf[n] = 0;
2057
+ l->len = l->pos = n;
2058
+ bestlineRefreshLine(l);
2059
+ }
2060
+
2061
+ static void bestlineEditHistoryMove(struct bestlineState *l, int dx) {
2062
+ bestlineEditHistoryGoto(l,l->hindex+dx);
2063
+ }
2064
+
2065
+ static char *bestlineMakeSearchPrompt(struct abuf *ab, int fail, const char *s, int n) {
2066
+ ab->len=0;
2067
+ abAppendw(ab,'(');
2068
+ if (fail) abAppends(ab,"failed ");
2069
+ abAppends(ab,"reverse-i-search `\033[4m");
2070
+ abAppend(ab,s,n);
2071
+ abAppends(ab,"\033[24m");
2072
+ abAppends(ab,s+n);
2073
+ abAppendw(ab,Read32le("') "));
2074
+ return ab->b;
2075
+ }
2076
+
2077
+ static int bestlineSearch(struct bestlineState *l, char *seq, int size) {
2078
+ char *p;
2079
+ char isstale;
2080
+ struct abuf ab;
2081
+ struct abuf prompt;
2082
+ unsigned i, j, k, matlen;
2083
+ const char *oldprompt, *q;
2084
+ int rc, fail, added, oldpos, oldindex;
2085
+ if (historylen <= 1) return 0;
2086
+ abInit(&ab);
2087
+ abInit(&prompt);
2088
+ oldpos = l->pos;
2089
+ oldprompt = l->prompt;
2090
+ oldindex = l->hindex;
2091
+ for (fail=matlen=0;;) {
2092
+ l->prompt = bestlineMakeSearchPrompt(&prompt,fail,ab.b,matlen);
2093
+ bestlineRefreshLine(l);
2094
+ fail = 1;
2095
+ added = 0;
2096
+ j = l->pos;
2097
+ i = l->hindex;
2098
+ rc = bestlineRead(l->ifd,seq,size,l);
2099
+ if (rc > 0) {
2100
+ if (seq[0] == Ctrl('?') || seq[0] == Ctrl('H')) {
2101
+ if (ab.len) {
2102
+ --ab.len;
2103
+ matlen = Min(matlen, ab.len);
2104
+ }
2105
+ } else if (seq[0] == Ctrl('R')) {
2106
+ if (j) {
2107
+ --j;
2108
+ } else if (i + 1 < historylen) {
2109
+ ++i;
2110
+ j = strlen(history[historylen - 1 - i]);
2111
+ }
2112
+ } else if (seq[0] == Ctrl('G')) {
2113
+ bestlineEditHistoryGoto(l,oldindex);
2114
+ l->pos = oldpos;
2115
+ rc = 0;
2116
+ break;
2117
+ } else if (IsControl(seq[0])) { /* only sees canonical c0 */
2118
+ break;
2119
+ } else {
2120
+ abAppend(&ab,seq,rc);
2121
+ added = rc;
2122
+ }
2123
+ } else {
2124
+ break;
2125
+ }
2126
+ isstale = 0;
2127
+ while (i < historylen) {
2128
+ p = history[historylen - 1 - i];
2129
+ k = strlen(p);
2130
+ if (!isstale) {
2131
+ j = Min(k, j + ab.len);
2132
+ } else {
2133
+ isstale = 0;
2134
+ j = k;
2135
+ }
2136
+ if ((q = FindSubstringReverse(p, j, ab.b, ab.len))) {
2137
+ bestlineEditHistoryGoto(l,i);
2138
+ l->pos = q - p;
2139
+ fail = 0;
2140
+ if (added) {
2141
+ matlen += added;
2142
+ added = 0;
2143
+ }
2144
+ break;
2145
+ } else {
2146
+ isstale = 1;
2147
+ ++i;
2148
+ }
2149
+ }
2150
+ }
2151
+ l->prompt = oldprompt;
2152
+ bestlineRefreshLine(l);
2153
+ abFree(&prompt);
2154
+ abFree(&ab);
2155
+ bestlineRefreshLine(l);
2156
+ return rc;
2157
+ }
2158
+
2159
+ static void bestlineRingFree(void) {
2160
+ size_t i;
2161
+ for (i = 0; i < BESTLINE_MAX_RING; ++i) {
2162
+ if (ring.p[i]) {
2163
+ free(ring.p[i]);
2164
+ ring.p[i] = 0;
2165
+ }
2166
+ }
2167
+ }
2168
+
2169
+ static void bestlineRingPush(const char *p, size_t n) {
2170
+ char *q;
2171
+ if (!n) return;
2172
+ if (!(q = (char *)malloc(n + 1))) return;
2173
+ ring.i = (ring.i + 1) % BESTLINE_MAX_RING;
2174
+ free(ring.p[ring.i]);
2175
+ ring.p[ring.i] = (char *)memcpy(q, p, n);
2176
+ ring.p[ring.i][n] = 0;
2177
+ }
2178
+
2179
+ static void bestlineRingRotate(void) {
2180
+ size_t i;
2181
+ for (i = 0; i < BESTLINE_MAX_RING; ++i) {
2182
+ ring.i = (ring.i - 1) % BESTLINE_MAX_RING;
2183
+ if (ring.p[ring.i]) break;
2184
+ }
2185
+ }
2186
+
2187
+ static char *bestlineRefreshHints(struct bestlineState *l) {
2188
+ char *hint;
2189
+ struct abuf ab;
2190
+ const char *ansi1 = "\033[90m", *ansi2 = "\033[39m";
2191
+ if (!hintsCallback) return 0;
2192
+ if (!(hint = hintsCallback(l->buf, &ansi1, &ansi2))) return 0;
2193
+ abInit(&ab);
2194
+ if (ansi1) abAppends(&ab, ansi1);
2195
+ abAppends(&ab, hint);
2196
+ if (ansi2) abAppends(&ab, ansi2);
2197
+ if (freeHintsCallback) freeHintsCallback(hint);
2198
+ return ab.b;
2199
+ }
2200
+
2201
+ static size_t Backward(struct bestlineState *l, size_t pos) {
2202
+ if (pos) {
2203
+ do --pos;
2204
+ while (pos && (l->buf[pos] & 0300) == 0200);
2205
+ }
2206
+ return pos;
2207
+ }
2208
+
2209
+ static int bestlineEditMirrorLeft(struct bestlineState *l, int res[2]) {
2210
+ unsigned c, pos, left, right, depth, index;
2211
+ if ((pos = Backward(l, l->pos))) {
2212
+ right = GetUtf8(l->buf + pos, l->len - pos).c;
2213
+ if ((left = bestlineMirrorLeft(right))) {
2214
+ depth = 0;
2215
+ index = pos;
2216
+ do {
2217
+ pos = Backward(l, pos);
2218
+ c = GetUtf8(l->buf + pos, l->len - pos).c;
2219
+ if (c == right) {
2220
+ ++depth;
2221
+ } else if (c == left) {
2222
+ if (depth) {
2223
+ --depth;
2224
+ } else {
2225
+ res[0] = pos;
2226
+ res[1] = index;
2227
+ return 0;
2228
+ }
2229
+ }
2230
+ } while (pos);
2231
+ }
2232
+ }
2233
+ return -1;
2234
+ }
2235
+
2236
+ static int bestlineEditMirrorRight(struct bestlineState *l, int res[2]) {
2237
+ struct rune rune;
2238
+ unsigned pos, left, right, depth, index;
2239
+ pos = l->pos;
2240
+ rune = GetUtf8(l->buf + pos, l->len - pos);
2241
+ left = rune.c;
2242
+ if ((right = bestlineMirrorRight(left))) {
2243
+ depth = 0;
2244
+ index = pos;
2245
+ do {
2246
+ pos += rune.n;
2247
+ rune = GetUtf8(l->buf + pos, l->len - pos);
2248
+ if (rune.c == left) {
2249
+ ++depth;
2250
+ } else if (rune.c == right) {
2251
+ if (depth) {
2252
+ --depth;
2253
+ } else {
2254
+ res[0] = index;
2255
+ res[1] = pos;
2256
+ return 0;
2257
+ }
2258
+ }
2259
+ } while (pos + rune.n < l->len);
2260
+ }
2261
+ return -1;
2262
+ }
2263
+
2264
+ static int bestlineEditMirror(struct bestlineState *l, int res[2]) {
2265
+ int rc;
2266
+ rc = bestlineEditMirrorLeft(l, res);
2267
+ if (rc == -1) rc = bestlineEditMirrorRight(l, res);
2268
+ return rc;
2269
+ }
2270
+
2271
+ static void bestlineRefreshLineImpl(struct bestlineState *l, int force) {
2272
+ char *hint;
2273
+ char flipit;
2274
+ char hasflip;
2275
+ char haswides;
2276
+ struct abuf ab;
2277
+ const char *buf;
2278
+ struct rune rune;
2279
+ struct winsize oldsize;
2280
+ int fd, plen, rows, len, pos;
2281
+ unsigned x, xn, yn, width, pwidth;
2282
+ int i, t, cx, cy, tn, resized, flip[2];
2283
+
2284
+ /*
2285
+ * synchonize the i/o state
2286
+ */
2287
+ if (ispaused) {
2288
+ if (force) {
2289
+ bestlineUnpause(l->ofd);
2290
+ } else {
2291
+ return;
2292
+ }
2293
+ }
2294
+ if (!force && HasPendingInput(l->ifd)) {
2295
+ l->dirty = 1;
2296
+ return;
2297
+ }
2298
+ oldsize = l->ws;
2299
+ if ((resized = gotwinch) && rawmode != -1) {
2300
+ gotwinch = 0;
2301
+ l->ws = GetTerminalSize(l->ws, l->ifd, l->ofd);
2302
+ }
2303
+ hasflip = !l->final && !bestlineEditMirror(l, flip);
2304
+
2305
+ StartOver:
2306
+ fd = l->ofd;
2307
+ buf = l->buf;
2308
+ pos = l->pos;
2309
+ len = l->len;
2310
+ xn = l->ws.ws_col;
2311
+ yn = l->ws.ws_row;
2312
+ plen = strlen(l->prompt);
2313
+ pwidth = GetMonospaceWidth(l->prompt, plen, 0);
2314
+ width = GetMonospaceWidth(buf, len, &haswides);
2315
+
2316
+ /*
2317
+ * handle the case where the line is larger than the whole display
2318
+ * gnu readline actually isn't able to deal with this situation!!!
2319
+ * we kludge xn to address the edge case of wide chars on the edge
2320
+ */
2321
+ for (tn = xn - haswides * 2;;) {
2322
+ if (pwidth + width + 1 < tn * yn) break; /* we're fine */
2323
+ if (!len || width < 2) break; /* we can't do anything */
2324
+ if (pwidth + 2 > tn * yn) break; /* we can't do anything */
2325
+ if (pos > len / 2) {
2326
+ /* hide content on the left if we're editing on the right */
2327
+ rune = GetUtf8(buf, len);
2328
+ buf += rune.n;
2329
+ len -= rune.n;
2330
+ pos -= rune.n;
2331
+ } else {
2332
+ /* hide content on the right if we're editing on left */
2333
+ t = len;
2334
+ while (len && (buf[len - 1] & 0300) == 0200) --len;
2335
+ if (len) --len;
2336
+ rune = GetUtf8(buf + len, t - len);
2337
+ }
2338
+ if ((t = GetMonospaceCharacterWidth(rune.c)) > 0) {
2339
+ width -= t;
2340
+ }
2341
+ }
2342
+ pos = Max(0, Min(pos, len));
2343
+
2344
+ /*
2345
+ * now generate the terminal codes to update the line
2346
+ *
2347
+ * since we support unlimited lines it's important that we don't
2348
+ * clear the screen before we draw the screen. doing that causes
2349
+ * flickering. the key with terminals is to overwrite cells, and
2350
+ * then use \e[K and \e[J to clear everything else.
2351
+ *
2352
+ * we make the assumption that prompts and hints may contain ansi
2353
+ * sequences, but the buffer does not.
2354
+ *
2355
+ * we need to handle the edge case where a wide character like 度
2356
+ * might be at the edge of the window, when there's one cell left.
2357
+ * so we can't use division based on string width to compute the
2358
+ * coordinates and have to track it as we go.
2359
+ */
2360
+ cy = -1;
2361
+ cx = -1;
2362
+ rows = 1;
2363
+ abInit(&ab);
2364
+ abAppendw(&ab, '\r'); /* start of line */
2365
+ if (l->rows - l->oldpos - 1 > 0) {
2366
+ abAppends(&ab, "\033[");
2367
+ abAppendu(&ab, l->rows - l->oldpos - 1);
2368
+ abAppendw(&ab, 'A'); /* cursor up clamped */
2369
+ }
2370
+ abAppends(&ab, l->prompt);
2371
+ x = pwidth;
2372
+ for (i = 0; i < len; i += rune.n) {
2373
+ rune = GetUtf8(buf + i, len - i);
2374
+ if (x && x + rune.n > xn) {
2375
+ if (cy >= 0) ++cy;
2376
+ if (x < xn) {
2377
+ abAppends(&ab, "\033[K"); /* clear line forward */
2378
+ }
2379
+ abAppends(&ab, "\r" /* start of line */
2380
+ "\n"); /* cursor down unclamped */
2381
+ ++rows;
2382
+ x = 0;
2383
+ }
2384
+ if (i == pos) {
2385
+ cy = 0;
2386
+ cx = x;
2387
+ }
2388
+ if (maskmode) {
2389
+ abAppendw(&ab, '*');
2390
+ } else {
2391
+ flipit = hasflip && (i == flip[0] || i == flip[1]);
2392
+ if (flipit) abAppends(&ab, "\033[1m");
2393
+ abAppendw(&ab, EncodeUtf8(rune.c));
2394
+ if (flipit) abAppends(&ab, "\033[22m");
2395
+ }
2396
+ t = GetMonospaceCharacterWidth(rune.c);
2397
+ t = Max(0, t);
2398
+ x += t;
2399
+ }
2400
+ if (!l->final && (hint = bestlineRefreshHints(l))) {
2401
+ if (GetMonospaceWidth(hint, strlen(hint), 0) < xn - x) {
2402
+ if (cx < 0) {
2403
+ cx = x;
2404
+ }
2405
+ abAppends(&ab, hint);
2406
+ }
2407
+ free(hint);
2408
+ }
2409
+ abAppendw(&ab, Read32le("\033[J")); /* erase display forwards */
2410
+
2411
+ /*
2412
+ * if we are at the very end of the screen with our prompt, we need
2413
+ * to emit a newline and move the prompt to the first column.
2414
+ */
2415
+ if (pos && pos == len && x >= xn) {
2416
+ abAppendw(&ab, Read32le("\n\r\0"));
2417
+ ++rows;
2418
+ }
2419
+
2420
+ /*
2421
+ * move cursor to right position
2422
+ */
2423
+ if (cy > 0) {
2424
+ abAppends(&ab, "\033[");
2425
+ abAppendu(&ab, cy);
2426
+ abAppendw(&ab, 'A'); /* cursor up */
2427
+ }
2428
+ if (cx > 0) {
2429
+ abAppendw(&ab, Read32le("\r\033["));
2430
+ abAppendu(&ab, cx);
2431
+ abAppendw(&ab, 'C'); /* cursor right */
2432
+ } else if (!cx) {
2433
+ abAppendw(&ab, '\r'); /* start */
2434
+ }
2435
+
2436
+ /*
2437
+ * now get ready to progress state
2438
+ * we use a mostly correct kludge when the tty resizes
2439
+ */
2440
+ l->rows = rows;
2441
+ if (resized && oldsize.ws_col > l->ws.ws_col) {
2442
+ resized = 0;
2443
+ abFree(&ab);
2444
+ goto StartOver;
2445
+ }
2446
+ l->dirty = 0;
2447
+ l->oldpos = Max(0, cy);
2448
+
2449
+ /*
2450
+ * send codes to terminal
2451
+ */
2452
+ bestlineWrite(fd, ab.b, ab.len);
2453
+ abFree(&ab);
2454
+ }
2455
+
2456
+ static void bestlineRefreshLine(struct bestlineState *l) {
2457
+ bestlineRefreshLineImpl(l, 0);
2458
+ }
2459
+
2460
+ static void bestlineRefreshLineForce(struct bestlineState *l) {
2461
+ bestlineRefreshLineImpl(l, 1);
2462
+ }
2463
+
2464
+ static void bestlineEditInsert(struct bestlineState *l,
2465
+ const char *p, size_t n) {
2466
+ if (!bestlineGrow(l, l->len + n + 1)) return;
2467
+ memmove(l->buf + l->pos + n, l->buf + l->pos, l->len - l->pos);
2468
+ memcpy(l->buf + l->pos, p, n);
2469
+ l->pos += n;
2470
+ l->len += n;
2471
+ l->buf[l->len] = 0;
2472
+ bestlineRefreshLine(l);
2473
+ }
2474
+
2475
+ static void bestlineEditHome(struct bestlineState *l) {
2476
+ l->pos = 0;
2477
+ bestlineRefreshLine(l);
2478
+ }
2479
+
2480
+ static void bestlineEditEnd(struct bestlineState *l) {
2481
+ l->pos = l->len;
2482
+ bestlineRefreshLine(l);
2483
+ }
2484
+
2485
+ static void bestlineEditUp(struct bestlineState *l) {
2486
+ bestlineEditHistoryMove(l,BESTLINE_HISTORY_PREV);
2487
+ }
2488
+
2489
+ static void bestlineEditDown(struct bestlineState *l) {
2490
+ bestlineEditHistoryMove(l,BESTLINE_HISTORY_NEXT);
2491
+ }
2492
+
2493
+ static void bestlineEditBof(struct bestlineState *l) {
2494
+ bestlineEditHistoryMove(l,BESTLINE_HISTORY_FIRST);
2495
+ }
2496
+
2497
+ static void bestlineEditEof(struct bestlineState *l) {
2498
+ bestlineEditHistoryMove(l,BESTLINE_HISTORY_LAST);
2499
+ }
2500
+
2501
+ static void bestlineEditRefresh(struct bestlineState *l) {
2502
+ bestlineClearScreen(l->ofd);
2503
+ bestlineRefreshLine(l);
2504
+ }
2505
+
2506
+ static size_t Forward(struct bestlineState *l, size_t pos) {
2507
+ return pos + GetUtf8(l->buf + pos, l->len - pos).n;
2508
+ }
2509
+
2510
+ static size_t Backwards(struct bestlineState *l, size_t pos, char pred(unsigned)) {
2511
+ size_t i;
2512
+ struct rune r;
2513
+ while (pos) {
2514
+ i = Backward(l, pos);
2515
+ r = GetUtf8(l->buf + i, l->len - i);
2516
+ if (pred(r.c)) {
2517
+ pos = i;
2518
+ } else {
2519
+ break;
2520
+ }
2521
+ }
2522
+ return pos;
2523
+ }
2524
+
2525
+ static size_t Forwards(struct bestlineState *l, size_t pos, char pred(unsigned)) {
2526
+ struct rune r;
2527
+ while (pos < l->len) {
2528
+ r = GetUtf8(l->buf + pos, l->len - pos);
2529
+ if (pred(r.c)) {
2530
+ pos += r.n;
2531
+ } else {
2532
+ break;
2533
+ }
2534
+ }
2535
+ return pos;
2536
+ }
2537
+
2538
+ static size_t ForwardWord(struct bestlineState *l, size_t pos) {
2539
+ pos = Forwards(l, pos, bestlineIsSeparator);
2540
+ pos = Forwards(l, pos, bestlineNotSeparator);
2541
+ return pos;
2542
+ }
2543
+
2544
+ static size_t BackwardWord(struct bestlineState *l, size_t pos) {
2545
+ pos = Backwards(l, pos, bestlineIsSeparator);
2546
+ pos = Backwards(l, pos, bestlineNotSeparator);
2547
+ return pos;
2548
+ }
2549
+
2550
+ static size_t EscapeWord(struct bestlineState *l, size_t i) {
2551
+ size_t j;
2552
+ struct rune r;
2553
+ for (; i && i < l->len; i += r.n) {
2554
+ if (i < l->len) {
2555
+ r = GetUtf8(l->buf + i, l->len - i);
2556
+ if (bestlineIsSeparator(r.c)) break;
2557
+ }
2558
+ if ((j = i)) {
2559
+ do --j;
2560
+ while (j && (l->buf[j] & 0300) == 0200);
2561
+ r = GetUtf8(l->buf + j, l->len - j);
2562
+ if (bestlineIsSeparator(r.c)) break;
2563
+ }
2564
+ }
2565
+ return i;
2566
+ }
2567
+
2568
+ static void bestlineEditLeft(struct bestlineState *l) {
2569
+ l->pos = Backward(l, l->pos);
2570
+ bestlineRefreshLine(l);
2571
+ }
2572
+
2573
+ static void bestlineEditRight(struct bestlineState *l) {
2574
+ if (l->pos == l->len) return;
2575
+ do l->pos++;
2576
+ while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200);
2577
+ bestlineRefreshLine(l);
2578
+ }
2579
+
2580
+ static void bestlineEditLeftWord(struct bestlineState *l) {
2581
+ l->pos = BackwardWord(l, l->pos);
2582
+ bestlineRefreshLine(l);
2583
+ }
2584
+
2585
+ static void bestlineEditRightWord(struct bestlineState *l) {
2586
+ l->pos = ForwardWord(l, l->pos);
2587
+ bestlineRefreshLine(l);
2588
+ }
2589
+
2590
+ static void bestlineEditLeftExpr(struct bestlineState *l) {
2591
+ int mark[2];
2592
+ l->pos = Backwards(l, l->pos, bestlineIsXeparator);
2593
+ if (!bestlineEditMirrorLeft(l, mark)) {
2594
+ l->pos = mark[0];
2595
+ } else {
2596
+ l->pos = Backwards(l, l->pos, bestlineNotSeparator);
2597
+ }
2598
+ bestlineRefreshLine(l);
2599
+ }
2600
+
2601
+ static void bestlineEditRightExpr(struct bestlineState *l) {
2602
+ int mark[2];
2603
+ l->pos = Forwards(l, l->pos, bestlineIsXeparator);
2604
+ if (!bestlineEditMirrorRight(l, mark)) {
2605
+ l->pos = Forward(l, mark[1]);
2606
+ } else {
2607
+ l->pos = Forwards(l, l->pos, bestlineNotSeparator);
2608
+ }
2609
+ bestlineRefreshLine(l);
2610
+ }
2611
+
2612
+ static void bestlineEditDelete(struct bestlineState *l) {
2613
+ size_t i;
2614
+ if (l->pos == l->len) return;
2615
+ i = Forward(l, l->pos);
2616
+ memmove(l->buf+l->pos, l->buf+i, l->len-i+1);
2617
+ l->len -= i - l->pos;
2618
+ bestlineRefreshLine(l);
2619
+ }
2620
+
2621
+ static void bestlineEditRubout(struct bestlineState *l) {
2622
+ size_t i;
2623
+ if (!l->pos) return;
2624
+ i = Backward(l, l->pos);
2625
+ memmove(l->buf+i, l->buf+l->pos, l->len-l->pos+1);
2626
+ l->len -= l->pos - i;
2627
+ l->pos = i;
2628
+ bestlineRefreshLine(l);
2629
+ }
2630
+
2631
+ static void bestlineEditDeleteWord(struct bestlineState *l) {
2632
+ size_t i;
2633
+ if (l->pos == l->len) return;
2634
+ i = ForwardWord(l, l->pos);
2635
+ bestlineRingPush(l->buf + l->pos, i - l->pos);
2636
+ memmove(l->buf + l->pos, l->buf + i, l->len - i + 1);
2637
+ l->len -= i - l->pos;
2638
+ bestlineRefreshLine(l);
2639
+ }
2640
+
2641
+ static void bestlineEditRuboutWord(struct bestlineState *l) {
2642
+ size_t i;
2643
+ if (!l->pos) return;
2644
+ i = BackwardWord(l, l->pos);
2645
+ bestlineRingPush(l->buf + i, l->pos - i);
2646
+ memmove(l->buf + i, l->buf + l->pos, l->len - l->pos + 1);
2647
+ l->len -= l->pos - i;
2648
+ l->pos = i;
2649
+ bestlineRefreshLine(l);
2650
+ }
2651
+
2652
+ static void bestlineEditXlatWord(struct bestlineState *l, unsigned xlat(unsigned)) {
2653
+ unsigned c;
2654
+ size_t i, j;
2655
+ struct rune r;
2656
+ struct abuf ab;
2657
+ abInit(&ab);
2658
+ i = Forwards(l, l->pos, bestlineIsSeparator);
2659
+ for (j = i; j < l->len; j += r.n) {
2660
+ r = GetUtf8(l->buf + j, l->len - j);
2661
+ if (bestlineIsSeparator(r.c)) break;
2662
+ if ((c = xlat(r.c)) != r.c) {
2663
+ abAppendw(&ab, EncodeUtf8(c));
2664
+ } else { /* avoid canonicalization */
2665
+ abAppend(&ab, l->buf + j, r.n);
2666
+ }
2667
+ }
2668
+ if (ab.len && bestlineGrow(l, i + ab.len + l->len - j + 1)) {
2669
+ l->pos = i + ab.len;
2670
+ abAppend(&ab, l->buf + j, l->len - j);
2671
+ l->len = i + ab.len;
2672
+ memcpy(l->buf + i, ab.b, ab.len + 1);
2673
+ bestlineRefreshLine(l);
2674
+ }
2675
+ abFree(&ab);
2676
+ }
2677
+
2678
+ static void bestlineEditLowercaseWord(struct bestlineState *l) {
2679
+ bestlineEditXlatWord(l, bestlineLowercase);
2680
+ }
2681
+
2682
+ static void bestlineEditUppercaseWord(struct bestlineState *l) {
2683
+ bestlineEditXlatWord(l, bestlineUppercase);
2684
+ }
2685
+
2686
+ static void bestlineEditCapitalizeWord(struct bestlineState *l) {
2687
+ iscapital = 0;
2688
+ bestlineEditXlatWord(l, Capitalize);
2689
+ }
2690
+
2691
+ static void bestlineEditKillLeft(struct bestlineState *l) {
2692
+ size_t diff, old_pos;
2693
+ bestlineRingPush(l->buf, l->pos);
2694
+ old_pos = l->pos;
2695
+ l->pos = 0;
2696
+ diff = old_pos - l->pos;
2697
+ memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
2698
+ l->len -= diff;
2699
+ bestlineRefreshLine(l);
2700
+ }
2701
+
2702
+ static void bestlineEditKillRight(struct bestlineState *l) {
2703
+ bestlineRingPush(l->buf + l->pos, l->len - l->pos);
2704
+ l->buf[l->pos] = '\0';
2705
+ l->len = l->pos;
2706
+ bestlineRefreshLine(l);
2707
+ }
2708
+
2709
+ static void bestlineEditYank(struct bestlineState *l) {
2710
+ char *p;
2711
+ size_t n;
2712
+ if (!ring.p[ring.i]) return;
2713
+ n = strlen(ring.p[ring.i]);
2714
+ if (!bestlineGrow(l, l->len + n + 1)) return;
2715
+ if (!(p = (char *)malloc(l->len - l->pos + 1))) return;
2716
+ memcpy(p, l->buf + l->pos, l->len - l->pos + 1);
2717
+ memcpy(l->buf + l->pos, ring.p[ring.i], n);
2718
+ memcpy(l->buf + l->pos + n, p, l->len - l->pos + 1);
2719
+ free(p);
2720
+ l->yi = l->pos;
2721
+ l->yj = l->pos + n;
2722
+ l->pos += n;
2723
+ l->len += n;
2724
+ bestlineRefreshLine(l);
2725
+ }
2726
+
2727
+ static void bestlineEditRotate(struct bestlineState *l) {
2728
+ if ((l->seq[1][0] == Ctrl('Y') ||
2729
+ (l->seq[1][0] == 033 && l->seq[1][1] == 'y'))) {
2730
+ if (l->yi < l->len && l->yj <= l->len) {
2731
+ memmove(l->buf + l->yi, l->buf + l->yj, l->len - l->yj + 1);
2732
+ l->len -= l->yj - l->yi;
2733
+ l->pos -= l->yj - l->yi;
2734
+ }
2735
+ bestlineRingRotate();
2736
+ bestlineEditYank(l);
2737
+ }
2738
+ }
2739
+
2740
+ static void bestlineEditTranspose(struct bestlineState *l) {
2741
+ char *q, *p;
2742
+ size_t a, b, c;
2743
+ b = l->pos;
2744
+ if (b == l->len) --b;
2745
+ a = Backward(l, b);
2746
+ c = Forward(l, b);
2747
+ if (!(a < b && b < c)) return;
2748
+ p = q = (char *)malloc(c - a);
2749
+ p = Copy(p, l->buf + b, c - b);
2750
+ p = Copy(p, l->buf + a, b - a);
2751
+ assert((size_t)(p - q) == c - a);
2752
+ memcpy(l->buf + a, q, p - q);
2753
+ l->pos = c;
2754
+ free(q);
2755
+ bestlineRefreshLine(l);
2756
+ }
2757
+
2758
+ static void bestlineEditTransposeWords(struct bestlineState *l) {
2759
+ char *q, *p;
2760
+ size_t i, pi, xi, xj, yi, yj;
2761
+ i = l->pos;
2762
+ if (i == l->len) {
2763
+ i = Backwards(l, i, bestlineIsSeparator);
2764
+ i = Backwards(l, i, bestlineNotSeparator);
2765
+ }
2766
+ pi = EscapeWord(l, i);
2767
+ xj = Backwards(l, pi, bestlineIsSeparator);
2768
+ xi = Backwards(l, xj, bestlineNotSeparator);
2769
+ yi = Forwards(l, pi, bestlineIsSeparator);
2770
+ yj = Forwards(l, yi, bestlineNotSeparator);
2771
+ if (!(xi < xj && xj < yi && yi < yj)) return;
2772
+ p = q = (char *)malloc(yj - xi);
2773
+ p = Copy(p, l->buf + yi, yj - yi);
2774
+ p = Copy(p, l->buf + xj, yi - xj);
2775
+ p = Copy(p, l->buf + xi, xj - xi);
2776
+ assert((size_t)(p - q) == yj - xi);
2777
+ memcpy(l->buf + xi, q, p - q);
2778
+ l->pos = yj;
2779
+ free(q);
2780
+ bestlineRefreshLine(l);
2781
+ }
2782
+
2783
+ static void bestlineEditSqueeze(struct bestlineState *l) {
2784
+ size_t i, j;
2785
+ i = Backwards(l, l->pos, bestlineIsSeparator);
2786
+ j = Forwards(l, l->pos, bestlineIsSeparator);
2787
+ if (!(i < j)) return;
2788
+ memmove(l->buf + i, l->buf + j, l->len - j + 1);
2789
+ l->len -= j - i;
2790
+ l->pos = i;
2791
+ bestlineRefreshLine(l);
2792
+ }
2793
+
2794
+ static void bestlineEditMark(struct bestlineState *l) {
2795
+ l->mark = l->pos;
2796
+ }
2797
+
2798
+ static void bestlineEditGoto(struct bestlineState *l) {
2799
+ if (l->mark > l->len) return;
2800
+ l->pos = Min(l->mark, l->len);
2801
+ bestlineRefreshLine(l);
2802
+ }
2803
+
2804
+ static size_t bestlineEscape(char *d, const char *s, size_t n) {
2805
+ char *p;
2806
+ size_t i;
2807
+ unsigned c, w, l;
2808
+ for (p = d, l = i = 0; i < n; ++i) {
2809
+ switch ((c = s[i] & 255)) {
2810
+ Case('\a', w = Read16le("\\a"));
2811
+ Case('\b', w = Read16le("\\b"));
2812
+ Case('\t', w = Read16le("\\t"));
2813
+ Case('\n', w = Read16le("\\n"));
2814
+ Case('\v', w = Read16le("\\v"));
2815
+ Case('\f', w = Read16le("\\f"));
2816
+ Case('\r', w = Read16le("\\r"));
2817
+ Case('"', w = Read16le("\\\""));
2818
+ Case('\'', w = Read16le("\\\'"));
2819
+ Case('\\', w = Read16le("\\\\"));
2820
+ default:
2821
+ if (c <= 0x1F || c == 0x7F ||
2822
+ (c == '?' && l == '?')) {
2823
+ w = Read16le("\\x");
2824
+ w |= "0123456789abcdef"[(c & 0xF0) >> 4] << 020;
2825
+ w |= "0123456789abcdef"[(c & 0x0F) >> 0] << 030;
2826
+ } else {
2827
+ w = c;
2828
+ }
2829
+ break;
2830
+ }
2831
+ p[0] = (w & 0x000000ff) >> 000;
2832
+ p[1] = (w & 0x0000ff00) >> 010;
2833
+ p[2] = (w & 0x00ff0000) >> 020;
2834
+ p[3] = (w & 0xff000000) >> 030;
2835
+ p += (Bsr(w) >> 3) + 1;
2836
+ l = w;
2837
+ }
2838
+ return p - d;
2839
+ }
2840
+
2841
+ static void bestlineEditInsertEscape(struct bestlineState *l) {
2842
+ size_t m;
2843
+ ssize_t n;
2844
+ char seq[16];
2845
+ char esc[sizeof(seq) * 4];
2846
+ if ((n = bestlineRead(l->ifd, seq, sizeof(seq), l)) > 0) {
2847
+ m = bestlineEscape(esc, seq, n);
2848
+ bestlineEditInsert(l, esc, m);
2849
+ }
2850
+ }
2851
+
2852
+ static void bestlineEditInterrupt(void) {
2853
+ gotint = SIGINT;
2854
+ }
2855
+
2856
+ static void bestlineEditQuit(void) {
2857
+ gotint = SIGQUIT;
2858
+ }
2859
+
2860
+ static void bestlineEditSuspend(void) {
2861
+ raise(SIGSTOP);
2862
+ }
2863
+
2864
+ static void bestlineEditPause(struct bestlineState *l) {
2865
+ tcflow(l->ofd, TCOOFF);
2866
+ ispaused = 1;
2867
+ }
2868
+
2869
+ static void bestlineEditCtrlq(struct bestlineState *l) {
2870
+ if (ispaused) {
2871
+ bestlineUnpause(l->ofd);
2872
+ bestlineRefreshLineForce(l);
2873
+ } else {
2874
+ bestlineEditInsertEscape(l);
2875
+ }
2876
+ }
2877
+
2878
+ /**
2879
+ * Moves last item inside current s-expression to outside, e.g.
2880
+ *
2881
+ * (a| b c)
2882
+ * (a| b) c
2883
+ *
2884
+ * The cursor position changes only if a paren is moved before it:
2885
+ *
2886
+ * (a b c |)
2887
+ * (a b) c |
2888
+ *
2889
+ * To accommodate non-LISP languages we connect unspaced outer symbols:
2890
+ *
2891
+ * f(a,| b, g())
2892
+ * f(a,| b), g()
2893
+ *
2894
+ * Our standard keybinding is ALT-SHIFT-B.
2895
+ */
2896
+ static void bestlineEditBarf(struct bestlineState *l) {
2897
+ struct rune r;
2898
+ unsigned long w;
2899
+ size_t i, pos, depth = 0;
2900
+ unsigned lhs, rhs, end, *stack = 0;
2901
+ /* go as far right within current s-expr as possible */
2902
+ for (pos = l->pos;; pos += r.n) {
2903
+ if (pos == l->len) goto Finish;
2904
+ r = GetUtf8(l->buf + pos, l->len - pos);
2905
+ if (depth) {
2906
+ if (r.c == stack[depth - 1]) {
2907
+ --depth;
2908
+ }
2909
+ } else {
2910
+ if ((rhs = bestlineMirrorRight(r.c))) {
2911
+ stack = (unsigned *)realloc(stack, ++depth * sizeof(*stack));
2912
+ stack[depth - 1] = rhs;
2913
+ } else if (bestlineMirrorLeft(r.c)) {
2914
+ end = pos;
2915
+ break;
2916
+ }
2917
+ }
2918
+ }
2919
+ /* go back one item */
2920
+ pos = Backwards(l, pos, bestlineIsXeparator);
2921
+ for (;; pos = i) {
2922
+ if (!pos) goto Finish;
2923
+ i = Backward(l, pos);
2924
+ r = GetUtf8(l->buf + i, l->len - i);
2925
+ if (depth) {
2926
+ if (r.c == stack[depth - 1]) {
2927
+ --depth;
2928
+ }
2929
+ } else {
2930
+ if ((lhs = bestlineMirrorLeft(r.c))) {
2931
+ stack = (unsigned *)realloc(stack, ++depth * sizeof(*stack));
2932
+ stack[depth - 1] = lhs;
2933
+ } else if (bestlineIsSeparator(r.c)) {
2934
+ break;
2935
+ }
2936
+ }
2937
+ }
2938
+ pos = Backwards(l, pos, bestlineIsXeparator);
2939
+ /* now move the text */
2940
+ r = GetUtf8(l->buf + end, l->len - end);
2941
+ memmove(l->buf + pos + r.n, l->buf + pos, end - pos);
2942
+ w = EncodeUtf8(r.c);
2943
+ for (i = 0; i < r.n; ++i) {
2944
+ l->buf[pos + i] = w;
2945
+ w >>= 8;
2946
+ }
2947
+ if (l->pos > pos) {
2948
+ l->pos += r.n;
2949
+ }
2950
+ bestlineRefreshLine(l);
2951
+ Finish:
2952
+ free(stack);
2953
+ }
2954
+
2955
+ /**
2956
+ * Moves first item outside current s-expression to inside, e.g.
2957
+ *
2958
+ * (a| b) c d
2959
+ * (a| b c) d
2960
+ *
2961
+ * To accommodate non-LISP languages we connect unspaced outer symbols:
2962
+ *
2963
+ * f(a,| b), g()
2964
+ * f(a,| b, g())
2965
+ *
2966
+ * Our standard keybinding is ALT-SHIFT-S.
2967
+ */
2968
+ static void bestlineEditSlurp(struct bestlineState *l) {
2969
+ char rp[6];
2970
+ struct rune r;
2971
+ size_t pos, depth = 0;
2972
+ unsigned rhs, point = 0, start = 0, *stack = 0;
2973
+ /* go to outside edge of current s-expr */
2974
+ for (pos = l->pos; pos < l->len; pos += r.n) {
2975
+ r = GetUtf8(l->buf + pos, l->len - pos);
2976
+ if (depth) {
2977
+ if (r.c == stack[depth - 1]) {
2978
+ --depth;
2979
+ }
2980
+ } else {
2981
+ if ((rhs = bestlineMirrorRight(r.c))) {
2982
+ stack = (unsigned *)realloc(stack, ++depth * sizeof(*stack));
2983
+ stack[depth - 1] = rhs;
2984
+ } else if (bestlineMirrorLeft(r.c)) {
2985
+ point = pos;
2986
+ pos += r.n;
2987
+ start = pos;
2988
+ break;
2989
+ }
2990
+ }
2991
+ }
2992
+ /* go forward one item */
2993
+ pos = Forwards(l, pos, bestlineIsXeparator);
2994
+ for (; pos < l->len ; pos += r.n) {
2995
+ r = GetUtf8(l->buf + pos, l->len - pos);
2996
+ if (depth) {
2997
+ if (r.c == stack[depth - 1]) {
2998
+ --depth;
2999
+ }
3000
+ } else {
3001
+ if ((rhs = bestlineMirrorRight(r.c))) {
3002
+ stack = (unsigned *)realloc(stack, ++depth * sizeof(*stack));
3003
+ stack[depth - 1] = rhs;
3004
+ } else if (bestlineIsSeparator(r.c)) {
3005
+ break;
3006
+ }
3007
+ }
3008
+ }
3009
+ /* now move the text */
3010
+ memcpy(rp, l->buf + point, start - point);
3011
+ memmove(l->buf + point, l->buf + start, pos - start);
3012
+ memcpy(l->buf + pos - (start - point), rp, start - point);
3013
+ bestlineRefreshLine(l);
3014
+ free(stack);
3015
+ }
3016
+
3017
+ static void bestlineEditRaise(struct bestlineState *l) {
3018
+ (void)l;
3019
+ }
3020
+
3021
+ /**
3022
+ * Runs bestline engine.
3023
+ *
3024
+ * This function is the core of the line editing capability of bestline.
3025
+ * It expects 'fd' to be already in "raw mode" so that every key pressed
3026
+ * will be returned ASAP to read().
3027
+ *
3028
+ * The resulting string is put into 'buf' when the user type enter, or
3029
+ * when ctrl+d is typed.
3030
+ *
3031
+ * Returns chomped character count in buf >=0 or -1 on eof / error
3032
+ */
3033
+ static ssize_t bestlineEdit(int stdin_fd, int stdout_fd, const char *prompt,
3034
+ char **obuf) {
3035
+ ssize_t rc;
3036
+ size_t nread;
3037
+ struct rune rune;
3038
+ char *p, seq[16];
3039
+ unsigned long long w;
3040
+ struct bestlineState l;
3041
+ memset(&l,0,sizeof(l));
3042
+ if (!(l.buf = (char *)malloc((l.buflen = 32)))) return -1;
3043
+ l.buf[0] = 0;
3044
+ l.ifd = stdin_fd;
3045
+ l.ofd = stdout_fd;
3046
+ l.prompt = prompt ? prompt : "";
3047
+ l.ws = GetTerminalSize(l.ws,l.ifd,l.ofd);
3048
+ bestlineHistoryAdd("");
3049
+ bestlineWriteStr(l.ofd,l.prompt);
3050
+ while (1) {
3051
+ if (l.dirty) bestlineRefreshLineForce(&l);
3052
+ rc = bestlineRead(l.ifd,seq,sizeof(seq),&l);
3053
+ if (rc > 0) {
3054
+ if (seq[0] == Ctrl('R')) {
3055
+ rc = bestlineSearch(&l,seq,sizeof(seq));
3056
+ if (!rc) continue;
3057
+ } else if (seq[0] == '\t' && completionCallback) {
3058
+ rc = bestlineCompleteLine(&l,seq,sizeof(seq));
3059
+ if (!rc) continue;
3060
+ }
3061
+ }
3062
+ if (rc > 0) {
3063
+ nread = rc;
3064
+ } else if (!rc && l.len) {
3065
+ nread = 1;
3066
+ seq[0] = '\r';
3067
+ seq[1] = 0;
3068
+ } else {
3069
+ free(history[--historylen]);
3070
+ history[historylen] = 0;
3071
+ free(l.buf);
3072
+ return -1;
3073
+ }
3074
+ switch (seq[0]) {
3075
+ Case(Ctrl('P'), bestlineEditUp(&l));
3076
+ Case(Ctrl('E'), bestlineEditEnd(&l));
3077
+ Case(Ctrl('N'), bestlineEditDown(&l));
3078
+ Case(Ctrl('A'), bestlineEditHome(&l));
3079
+ Case(Ctrl('B'), bestlineEditLeft(&l));
3080
+ Case(Ctrl('@'), bestlineEditMark(&l));
3081
+ Case(Ctrl('Y'), bestlineEditYank(&l));
3082
+ Case(Ctrl('Q'), bestlineEditCtrlq(&l));
3083
+ Case(Ctrl('F'), bestlineEditRight(&l));
3084
+ Case(Ctrl('\\'), bestlineEditQuit());
3085
+ Case(Ctrl('S'), bestlineEditPause(&l));
3086
+ Case(Ctrl('?'), bestlineEditRubout(&l));
3087
+ Case(Ctrl('H'), bestlineEditRubout(&l));
3088
+ Case(Ctrl('L'), bestlineEditRefresh(&l));
3089
+ Case(Ctrl('Z'), bestlineEditSuspend());
3090
+ Case(Ctrl('U'), bestlineEditKillLeft(&l));
3091
+ Case(Ctrl('T'), bestlineEditTranspose(&l));
3092
+ Case(Ctrl('K'), bestlineEditKillRight(&l));
3093
+ Case(Ctrl('W'), bestlineEditRuboutWord(&l));
3094
+ case Ctrl('C'):
3095
+ if (bestlineRead(l.ifd,seq,sizeof(seq),&l) != 1) break;
3096
+ switch (seq[0]) {
3097
+ Case(Ctrl('C'), bestlineEditInterrupt());
3098
+ Case(Ctrl('B'), bestlineEditBarf(&l));
3099
+ Case(Ctrl('S'), bestlineEditSlurp(&l));
3100
+ Case(Ctrl('R'), bestlineEditRaise(&l));
3101
+ default:
3102
+ break;
3103
+ }
3104
+ break;
3105
+ case Ctrl('X'):
3106
+ if (l.seq[1][0] == Ctrl('X')) {
3107
+ bestlineEditGoto(&l);
3108
+ }
3109
+ break;
3110
+ case Ctrl('D'):
3111
+ if (l.len) {
3112
+ bestlineEditDelete(&l);
3113
+ } else {
3114
+ free(history[--historylen]);
3115
+ history[historylen] = 0;
3116
+ free(l.buf);
3117
+ return -1;
3118
+ }
3119
+ break;
3120
+ case '\r':
3121
+ l.final = 1;
3122
+ free(history[--historylen]);
3123
+ history[historylen] = 0;
3124
+ bestlineEditEnd(&l);
3125
+ bestlineRefreshLineForce(&l);
3126
+ if ((p = (char *)realloc(l.buf, l.len + 1))) l.buf = p;
3127
+ *obuf = l.buf;
3128
+ return l.len;
3129
+ case 033:
3130
+ if (nread < 2) break;
3131
+ switch (seq[1]) {
3132
+ Case('<', bestlineEditBof(&l));
3133
+ Case('>', bestlineEditEof(&l));
3134
+ Case('B', bestlineEditBarf(&l));
3135
+ Case('S', bestlineEditSlurp(&l));
3136
+ Case('R', bestlineEditRaise(&l));
3137
+ Case('y', bestlineEditRotate(&l));
3138
+ Case('\\', bestlineEditSqueeze(&l));
3139
+ Case('b', bestlineEditLeftWord(&l));
3140
+ Case('f', bestlineEditRightWord(&l));
3141
+ Case('h', bestlineEditRuboutWord(&l));
3142
+ Case('d', bestlineEditDeleteWord(&l));
3143
+ Case('l', bestlineEditLowercaseWord(&l));
3144
+ Case('u', bestlineEditUppercaseWord(&l));
3145
+ Case('c', bestlineEditCapitalizeWord(&l));
3146
+ Case('t', bestlineEditTransposeWords(&l));
3147
+ Case(Ctrl('B'), bestlineEditLeftExpr(&l));
3148
+ Case(Ctrl('F'), bestlineEditRightExpr(&l));
3149
+ Case(Ctrl('H'), bestlineEditRuboutWord(&l));
3150
+ case '[':
3151
+ if (nread < 3) break;
3152
+ if (seq[2] >= '0' && seq[2] <= '9') {
3153
+ if (nread < 4) break;
3154
+ if (seq[3] == '~') {
3155
+ switch (seq[2]) {
3156
+ Case('1', bestlineEditHome(&l)); /* \e[1~ */
3157
+ Case('3', bestlineEditDelete(&l)); /* \e[3~ */
3158
+ Case('4', bestlineEditEnd(&l)); /* \e[4~ */
3159
+ default:
3160
+ break;
3161
+ }
3162
+ }
3163
+ } else {
3164
+ switch (seq[2]) {
3165
+ Case('A', bestlineEditUp(&l));
3166
+ Case('B', bestlineEditDown(&l));
3167
+ Case('C', bestlineEditRight(&l));
3168
+ Case('D', bestlineEditLeft(&l));
3169
+ Case('H', bestlineEditHome(&l));
3170
+ Case('F', bestlineEditEnd(&l));
3171
+ default:
3172
+ break;
3173
+ }
3174
+ }
3175
+ break;
3176
+ case 'O':
3177
+ if (nread < 3) break;
3178
+ switch (seq[2]) {
3179
+ Case('A', bestlineEditUp(&l));
3180
+ Case('B', bestlineEditDown(&l));
3181
+ Case('C', bestlineEditRight(&l));
3182
+ Case('D', bestlineEditLeft(&l));
3183
+ Case('H', bestlineEditHome(&l));
3184
+ Case('F', bestlineEditEnd(&l));
3185
+ default:
3186
+ break;
3187
+ }
3188
+ break;
3189
+ case 033:
3190
+ if (nread < 3) break;
3191
+ switch (seq[2]) {
3192
+ case '[':
3193
+ if (nread < 4) break;
3194
+ switch (seq[3]) {
3195
+ Case('C', bestlineEditRightExpr(&l)); /* \e\e[C alt-right */
3196
+ Case('D', bestlineEditLeftExpr(&l)); /* \e\e[D alt-left */
3197
+ default:
3198
+ break;
3199
+ }
3200
+ break;
3201
+ case 'O':
3202
+ if (nread < 4) break;
3203
+ switch (seq[3]) {
3204
+ Case('C', bestlineEditRightExpr(&l)); /* \e\eOC alt-right */
3205
+ Case('D', bestlineEditLeftExpr(&l)); /* \e\eOD alt-left */
3206
+ default:
3207
+ break;
3208
+ }
3209
+ break;
3210
+ default:
3211
+ break;
3212
+ }
3213
+ break;
3214
+ default:
3215
+ break;
3216
+ }
3217
+ break;
3218
+ default:
3219
+ if (!IsControl(seq[0])) { /* only sees canonical c0 */
3220
+ if (xlatCallback) {
3221
+ rune = GetUtf8(seq,nread);
3222
+ w = EncodeUtf8(xlatCallback(rune.c));
3223
+ nread = 0;
3224
+ do {
3225
+ seq[nread++] = w;
3226
+ } while ((w >>= 8));
3227
+ }
3228
+ bestlineEditInsert(&l,seq,nread);
3229
+ }
3230
+ break;
3231
+ }
3232
+ }
3233
+ }
3234
+
3235
+ void bestlineFree(void *ptr) {
3236
+ free(ptr);
3237
+ }
3238
+
3239
+ void bestlineHistoryFree(void) {
3240
+ size_t i;
3241
+ for (i = 0; i < BESTLINE_MAX_HISTORY; i++) {
3242
+ if (history[i]) {
3243
+ free(history[i]);
3244
+ history[i] = 0;
3245
+ }
3246
+ }
3247
+ historylen = 0;
3248
+ }
3249
+
3250
+ static void bestlineAtExit(void) {
3251
+ bestlineDisableRawMode();
3252
+ bestlineHistoryFree();
3253
+ bestlineRingFree();
3254
+ }
3255
+
3256
+ int bestlineHistoryAdd(const char *line) {
3257
+ char *linecopy;
3258
+ if (!BESTLINE_MAX_HISTORY) return 0;
3259
+ if (historylen && !strcmp(history[historylen-1], line)) return 0;
3260
+ if (!(linecopy = strdup(line))) return 0;
3261
+ if (historylen == BESTLINE_MAX_HISTORY) {
3262
+ free(history[0]);
3263
+ memmove(history,history+1,sizeof(char*)*(BESTLINE_MAX_HISTORY-1));
3264
+ historylen--;
3265
+ }
3266
+ history[historylen++] = linecopy;
3267
+ return 1;
3268
+ }
3269
+
3270
+ /**
3271
+ * Saves line editing history to file.
3272
+ *
3273
+ * @return 0 on success, or -1 w/ errno
3274
+ */
3275
+ int bestlineHistorySave(const char *filename) {
3276
+ FILE *fp;
3277
+ unsigned j;
3278
+ mode_t old_umask;
3279
+ old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
3280
+ fp = fopen(filename,"w");
3281
+ umask(old_umask);
3282
+ if (!fp) return -1;
3283
+ chmod(filename,S_IRUSR|S_IWUSR);
3284
+ for (j = 0; j < historylen; j++) {
3285
+ fputs(history[j],fp);
3286
+ fputc('\n',fp);
3287
+ }
3288
+ fclose(fp);
3289
+ return 0;
3290
+ }
3291
+
3292
+ /**
3293
+ * Loads history from the specified file.
3294
+ *
3295
+ * If the file doesn't exist, zero is returned and this will do nothing.
3296
+ * If the file does exists and the operation succeeded zero is returned
3297
+ * otherwise on error -1 is returned.
3298
+ *
3299
+ * @return 0 on success, or -1 w/ errno
3300
+ */
3301
+ int bestlineHistoryLoad(const char *filename) {
3302
+ char **h;
3303
+ int rc, fd, err;
3304
+ size_t i, j, k, n, t;
3305
+ char *m, *e, *p, *q, *f, *s;
3306
+ err = errno, rc = 0;
3307
+ if (!BESTLINE_MAX_HISTORY) return 0;
3308
+ if (!(h = (char**)calloc(2*BESTLINE_MAX_HISTORY,sizeof(char*)))) return -1;
3309
+ if ((fd = open(filename,O_RDONLY)) != -1) {
3310
+ if ((n = GetFdSize(fd))) {
3311
+ if ((m = (char *)mmap(0,n,PROT_READ,MAP_SHARED,fd,0))!=MAP_FAILED) {
3312
+ for (i = 0, e = (p = m) + n; p < e; p = f + 1) {
3313
+ if (!(q = (char *)memchr(p, '\n', e - p))) q = e;
3314
+ for (f = q; q > p; --q) {
3315
+ if (q[-1] != '\n' && q[-1] != '\r') break;
3316
+ }
3317
+ if (q > p) {
3318
+ h[i * 2 + 0] = p;
3319
+ h[i * 2 + 1] = q;
3320
+ i = (i + 1) % BESTLINE_MAX_HISTORY;
3321
+ }
3322
+ }
3323
+ bestlineHistoryFree();
3324
+ for (j = 0; j < BESTLINE_MAX_HISTORY; ++j) {
3325
+ if (h[(k = (i + j) % BESTLINE_MAX_HISTORY) * 2]) {
3326
+ if ((s = (char *)malloc((t=h[k*2+1]-h[k*2])+1))) {
3327
+ memcpy(s,h[k*2],t),s[t]=0;
3328
+ history[historylen++] = s;
3329
+ }
3330
+ }
3331
+ }
3332
+ munmap(m,n);
3333
+ } else {
3334
+ rc = -1;
3335
+ }
3336
+ }
3337
+ close(fd);
3338
+ } else if (errno == ENOENT) {
3339
+ errno = err;
3340
+ } else {
3341
+ rc = -1;
3342
+ }
3343
+ free(h);
3344
+ return rc;
3345
+ }
3346
+
3347
+ /**
3348
+ * Reads line interactively.
3349
+ *
3350
+ * This function can be used instead of bestline() in cases where we
3351
+ * know for certain we're dealing with a terminal, which means we can
3352
+ * avoid linking any stdio code.
3353
+ *
3354
+ * @return chomped allocated string of read line or null on eof/error
3355
+ */
3356
+ char *bestlineRaw(const char *prompt, int infd, int outfd) {
3357
+ char *buf;
3358
+ ssize_t rc;
3359
+ static char once;
3360
+ struct sigaction sa[3];
3361
+ if (!once) atexit(bestlineAtExit), once = 1;
3362
+ if (enableRawMode(infd) == -1) return 0;
3363
+ buf = 0;
3364
+ gotint = 0;
3365
+ sigemptyset(&sa->sa_mask);
3366
+ sa->sa_flags = 0;
3367
+ sa->sa_handler = bestlineOnInt;
3368
+ sigaction(SIGINT,sa,sa+1);
3369
+ sigaction(SIGQUIT,sa,sa+2);
3370
+ rc = bestlineEdit(infd,outfd,prompt,&buf);
3371
+ bestlineDisableRawMode();
3372
+ sigaction(SIGQUIT,sa+2,0);
3373
+ sigaction(SIGINT,sa+1,0);
3374
+ if (gotint) {
3375
+ free(buf);
3376
+ buf = 0;
3377
+ raise(gotint);
3378
+ errno = EINTR;
3379
+ rc = -1;
3380
+ }
3381
+ if (rc != -1) {
3382
+ bestlineWriteStr(outfd,"\n");
3383
+ return buf;
3384
+ } else {
3385
+ free(buf);
3386
+ return 0;
3387
+ }
3388
+ }
3389
+
3390
+ /**
3391
+ * Reads line intelligently.
3392
+ *
3393
+ * The high level function that is the main API of the bestline library.
3394
+ * This function checks if the terminal has basic capabilities, just checking
3395
+ * for a blacklist of inarticulate terminals, and later either calls the line
3396
+ * editing function or uses dummy fgets() so that you will be able to type
3397
+ * something even in the most desperate of the conditions.
3398
+ *
3399
+ * @param prompt is printed before asking for input if we have a term
3400
+ * and this may be set to empty or null to disable and prompt may
3401
+ * contain ansi escape sequences, color, utf8, etc.
3402
+ * @return chomped allocated string of read line or null on eof/error
3403
+ */
3404
+ char *bestline(const char *prompt) {
3405
+ if (prompt && *prompt &&
3406
+ (strchr(prompt, '\n') || strchr(prompt, '\t') ||
3407
+ strchr(prompt + 1, '\r'))) {
3408
+ errno = EINVAL;
3409
+ return 0;
3410
+ }
3411
+ if ((!isatty(fileno(stdin)) ||
3412
+ !isatty(fileno(stdout)))) {
3413
+ if (prompt && *prompt && (IsCharDev(fileno(stdin)) &&
3414
+ IsCharDev(fileno(stdout)))) {
3415
+ fputs(prompt,stdout);
3416
+ fflush(stdout);
3417
+ }
3418
+ return GetLine(stdin, stdout);
3419
+ } else if (bestlineIsUnsupportedTerm()) {
3420
+ if (prompt && *prompt) {
3421
+ fputs(prompt,stdout);
3422
+ fflush(stdout);
3423
+ }
3424
+ return GetLine(stdin, stdout);
3425
+ } else {
3426
+ fflush(stdout);
3427
+ return bestlineRaw(prompt,fileno(stdin),fileno(stdout));
3428
+ }
3429
+ }
3430
+
3431
+ /**
3432
+ * Reads line intelligently w/ history, e.g.
3433
+ *
3434
+ * // see ~/.foo_history
3435
+ * main() {
3436
+ * char *line;
3437
+ * while ((line = bestlineWithHistory("IN> ", "foo"))) {
3438
+ * printf("OUT> %s\n", line);
3439
+ * free(line);
3440
+ * }
3441
+ * }
3442
+ *
3443
+ * @param prompt is printed before asking for input if we have a term
3444
+ * and this may be set to empty or null to disable and prompt may
3445
+ * contain ansi escape sequences, color, utf8, etc.
3446
+ * @param prog is name of your app, used to generate history filename
3447
+ * however if it contains a slash / dot then we'll assume prog is
3448
+ * the history filename which as determined by the caller
3449
+ * @return chomped allocated string of read line or null on eof/error
3450
+ */
3451
+ char *bestlineWithHistory(const char *prompt, const char *prog) {
3452
+ char *line;
3453
+ struct abuf path;
3454
+ const char *a, *b;
3455
+ abInit(&path);
3456
+ if (prog) {
3457
+ if (strchr(prog, '/') || strchr(prog, '.')) {
3458
+ abAppends(&path, prog);
3459
+ } else {
3460
+ b = "";
3461
+ if (!(a = getenv("HOME"))) {
3462
+ if (!(a = getenv("HOMEDRIVE")) ||
3463
+ !(b = getenv("HOMEPATH"))) {
3464
+ a = "";
3465
+ }
3466
+ }
3467
+ if (*a) {
3468
+ abAppends(&path, a);
3469
+ abAppends(&path, b);
3470
+ abAppendw(&path, '/');
3471
+ }
3472
+ abAppendw(&path, '.');
3473
+ abAppends(&path, prog);
3474
+ abAppends(&path, "_history");
3475
+ }
3476
+ }
3477
+ if (path.len) {
3478
+ bestlineHistoryLoad(path.b);
3479
+ }
3480
+ line = bestline(prompt);
3481
+ if (path.len && line && *line) {
3482
+ /* history here is inefficient but helpful when the user has multiple
3483
+ * repls open at the same time, so history propagates between them */
3484
+ bestlineHistoryLoad(path.b);
3485
+ bestlineHistoryAdd(line);
3486
+ bestlineHistorySave(path.b);
3487
+ }
3488
+ abFree(&path);
3489
+ return line;
3490
+ }
3491
+
3492
+ /**
3493
+ * Registers tab completion callback.
3494
+ */
3495
+ void bestlineSetCompletionCallback(bestlineCompletionCallback *fn) {
3496
+ completionCallback = fn;
3497
+ }
3498
+
3499
+ /**
3500
+ * Registers hints callback.
3501
+ *
3502
+ * Register a hits function to be called to show hits to the user at the
3503
+ * right of the prompt.
3504
+ */
3505
+ void bestlineSetHintsCallback(bestlineHintsCallback *fn) {
3506
+ hintsCallback = fn;
3507
+ }
3508
+
3509
+ /**
3510
+ * Sets free hints callback.
3511
+ *
3512
+ * This registers a function to free the hints returned by the hints
3513
+ * callback registered with bestlineSetHintsCallback().
3514
+ */
3515
+ void bestlineSetFreeHintsCallback(bestlineFreeHintsCallback *fn) {
3516
+ freeHintsCallback = fn;
3517
+ }
3518
+
3519
+ /**
3520
+ * Sets character translation callback.
3521
+ */
3522
+ void bestlineSetXlatCallback(bestlineXlatCallback *fn) {
3523
+ xlatCallback = fn;
3524
+ }
3525
+
3526
+ /**
3527
+ * Adds completion.
3528
+ *
3529
+ * This function is used by the callback function registered by the user
3530
+ * in order to add completion options given the input string when the
3531
+ * user typed <tab>. See the example.c source code for a very easy to
3532
+ * understand example.
3533
+ */
3534
+ void bestlineAddCompletion(bestlineCompletions *lc, const char *str) {
3535
+ size_t len;
3536
+ char *copy, **cvec;
3537
+ if ((copy = (char *)malloc((len = strlen(str))+1))) {
3538
+ memcpy(copy,str,len+1);
3539
+ if ((cvec = (char **)realloc(lc->cvec,(lc->len+1)*sizeof(*lc->cvec)))) {
3540
+ lc->cvec = cvec;
3541
+ lc->cvec[lc->len++] = copy;
3542
+ } else {
3543
+ free(copy);
3544
+ }
3545
+ }
3546
+ }
3547
+
3548
+ /**
3549
+ * Frees list of completion option populated by bestlineAddCompletion().
3550
+ */
3551
+ void bestlineFreeCompletions(bestlineCompletions *lc) {
3552
+ size_t i;
3553
+ for (i = 0; i < lc->len; i++)
3554
+ free(lc->cvec[i]);
3555
+ if (lc->cvec)
3556
+ free(lc->cvec);
3557
+ }
3558
+
3559
+ /**
3560
+ * Enables "mask mode".
3561
+ *
3562
+ * When it is enabled, instead of the input that the user is typing, the
3563
+ * terminal will just display a corresponding number of asterisks, like
3564
+ * "****". This is useful for passwords and other secrets that should
3565
+ * not be displayed.
3566
+ *
3567
+ * @see bestlineMaskModeDisable()
3568
+ */
3569
+ void bestlineMaskModeEnable(void) {
3570
+ maskmode = 1;
3571
+ }
3572
+
3573
+ /**
3574
+ * Disables "mask mode".
3575
+ */
3576
+ void bestlineMaskModeDisable(void) {
3577
+ maskmode = 0;
3578
+ }