1 /*======================================================================*\
2 |* Editor mined *|
3 |* part 1 *|
4 \*======================================================================*/
5
6 #include "mined.h"
7 #include "version.h"
8
9 #ifndef VAXC
10 #include <sys/stat.h> /* umask () */
11 #endif
12
13 #include "textfile.h"
14 #include "charprop.h"
15 #include "encoding.h"
16 #include "io.h"
17 #include "termprop.h"
18
19
20 #if defined (vms) || defined (__TURBOC__)
21 #ifndef VAXC
22 #define wildcard_expansion
23 #endif
24 #endif
25
26 #define dont_debug_wildcard_expansion
27 #ifdef debug_wildcard_expansion
28 #define wildcard_expansion
29 #endif
30
31 #ifdef wildcard_expansion
32 #include <dirent.h>
33 #endif
34
35
36 #include <errno.h> /* EEXIST */
37
38 #ifdef __CYGWIN__
39 #include <cygwin/version.h> /* check CYGWIN_VERSION_DLL_MAJOR >= 1007 ? */
40 #include <locale.h>
41 #if CYGWIN_VERSION_DLL_MAJOR >= 1007
42 #include <langinfo.h> /* available #if CYGWIN_VERSION_DLL_MAJOR >= 1005 */
43 #endif
44 #include <sys/utsname.h>
45 #endif
46
47
48 /**
49 How to deal with non-matching tty and terminal sizes.
50 Method 1: adjust_terminal_height
51 accept the tty size assumption and try to resize the terminal to it
52 - not needed anymore (see method 3)
53 Method 2: adjust_to_actual_termsize
54 request the terminal size, process the reponse asynchronously
55 - what a weird idea, never fully implemented ...
56 Method 3: checkwinsize ()
57 detect the terminal size: set the cursor way out the area,
58 request cursor position
59 (or use specific size request as in method 1 but synchronously)
60 */
61 #define dont_adjust_terminal_height
62 #define dont_adjust_to_actual_termsize /* not fully implemented */
63
64
65 /*======================================================================*\
66 |* Local function declarations and FLAGs *|
67 \*======================================================================*/
68
69 static void flush_keyboard _((void));
70 static char * get_terminal_report_string _((char * s));
71
72 static void check_cjk_width _((void));
73 static void config_markers _((void));
74
75
76 /*======================================================================*\
77 |* Data section *|
78 \*======================================================================*/
79
80 char * debug_mined = NIL_PTR;
81
82 LINE * header; /* Head of line list */
83 LINE * tail; /* Last line in line list */
84 LINE * cur_line; /* Current line in use */
85 LINE * top_line; /* First line of screen */
86 LINE * bot_line; /* Last line of screen */
87 char * cur_text; /* Current char on current line in use */
88 int last_y; /* Last y of screen. Usually SCREENMAX */
89 int x = 0; /* screen column of current text position */
90 int y = 0; /* screen row of current text position */
91 int line_number; /* current line # determined by file_status */
92 int total_lines = 0; /* Number of lines in file */
93 long total_chars = 0L; /* Number of characters in file */
94
95 int lines_per_page = 00; /* assumption for file_status */
96
97 FLAG loading = True; /* Loading a file? Init True for error handling */
98 static FLAG utf8_auto_detected = False;
99
100 int hop_flag = 0; /* Counter flag for the HOP function */
101 int hop_flag_displayed = 0;
102
103 FLAG quit = False; /* Set on SIGQUIT or quit character typed */
104 FLAG winchg = False; /* Set when window size has changed */
105 FLAG interrupted = False; /* Set when a signal interrupts */
106 FLAG isscreenmode = False; /* Set when screen mode is on */
107 FLAG stat_visible; /* Set if status line is visible */
108 FLAG top_line_dirty = False; /* Was menu line cleared? */
109 FLAG text_screen_dirty = False; /* Was text display position affected? */
110
111 FLAG waitingforinput = False; /* Set while waiting for the next command key */
112 FLAG reading_pipe = False; /* Set if file should be read from stdin */
113 FLAG writing_pipe = False; /* Set if file should be written to stdout */
114
115 char * minedprog; /* store argv [0] for help invocation */
116 character quit_char = '\034'; /* ^\/^G character to cancel command */
117
118 int YMAX, XMAX;
119
120 long chars_saved; /* # of chars in paste buffer */
121 long bytes_saved; /* # of bytes in paste buffer */
122 int lines_saved; /* # of lines in paste buffer */
123
124 char text_buffer [maxLINElen]; /* for get_line, modifications, get_tagline, build_string */
125
126 /**
127 Yank variables
128 */
129 char yank_file [maxFILENAMElen];
130 char yankie_file [maxFILENAMElen];
131 char spool_file [maxFILENAMElen];
132 char html_file [maxFILENAMElen]; /* temp. buffer for HTML embedding */
133 char panic_file [maxFILENAMElen];
134
135 /**
136 Terminal properties
137 */
138 static char * TERM;
139 static int terminal_type = -1;
140 static int terminal_version = 0;
141 static char * glyphs = NIL_PTR;
142 static FLAG combining_screen_selected = False; /* explicitly selected ? */
143 static FLAG term_encoding_selected = False; /* explicitly selected ? */
144 static FLAG text_encoding_selected = False; /* explicitly selected ? */
145 static FLAG limited_marker_font = False; /* -F to limit font usage? */
146 static FLAG very_limited_marker_font = False; /* -FF to limit font usage? */
147 static FLAG explicit_selection_style = False; /* -QQ or -Qq? */
148 FLAG suppress_unknown_cjk = True; /* on CJK terminal if no Unicode mapping */
149 FLAG suppress_invalid_cjk = True; /* on CJK terminal if invalid CJK code */
150 FLAG suppress_extended_cjk = False; /* on CJK terminal if in extended code range */
151 FLAG suppress_surrogates = True; /* suppress display of single Unicode surrogates */
152 FLAG suppress_non_BMP = False; /* suppress display of non-BMP range */
153 FLAG suppress_EF = True; /* suppress display of 0x*FFFE/F codes */
154 FLAG suppress_non_Unicode = True; /* suppress display of non-Unicode codes */
155 FLAG utf_cjk_wide_padding = False; /* always display CJK on UTF double-width ? */
156 #ifdef pc_term
157 FLAG dark_term = True; /* PC terminal */
158 #else
159 FLAG dark_term = False; /* dark colour terminal ? */
160 #endif
161 FLAG darkness_detected = False; /* could background colour be queried ? */
162 FLAG fg_yellowish = False; /* foreground colour near yellow ? */
163 FLAG bright_term = False; /* need to improved contrast ? */
164 FLAG bw_term = False; /* black/white terminal ? */
165 FLAG suppress_colour = False; /* don't use ANSI color settings */
166 static FLAG cygwin_console = False;
167 static FLAG can_report_props = True;
168
169 FLAG configure_xterm_keyboard = False; /* deleteIsDEL, metaSendsEscape */
170
171 FLAG combining_mode = False; /* UTF-8 combining character display support ? */
172 FLAG separate_isolated_combinings = True; /* separated display of comb. at line beg./after TAB ? */
173
174 static unsigned long dec_features = 1 << 4; /* assume SIXEL for mlterm */
175
176 #if defined (unix) || defined (ANSI)
177 /* window headline and icon text setting */
178 char * title_string_pattern = "";
179 char * mined_modf = " (*)";
180 #endif
181
182 FLAG apply_joining = True; /* apply LAM/ALEF joining ? */
183
184
185 /*======================================================================*\
186 |* File-related properties *|
187 \*======================================================================*/
188
189 lineend_type default_lineend = lineend_LF;
190 #ifdef msdos
191 lineend_type newfile_lineend = lineend_CRLF;
192 #else
193 lineend_type newfile_lineend = lineend_LF;
194 #endif
195 FLAG writable; /* Set if file cannot be written */
196 FLAG file_is_dir; /* Tried to open a directory as file? */
197 FLAG file_is_dev; /* Tried to open a char/block device file? */
198 FLAG file_is_fifo; /* Read from a named pipe? */
199
200 FLAG cjk_text = False; /* text in CJK encoding ? */
201 FLAG utf8_text = False; /* text in UTF-8 representation ? */
202 FLAG utf16_file = False; /* file encoded in UTF-16 ? */
203 FLAG utf16_little_endian = False; /* UTF-16 file encoded little endian ? */
204 FLAG mapped_text = False; /* text in 8 bit, non-Latin-1 representation ? */
205 FLAG ebcdic_text = False;
206 FLAG ebcdic_file = False;
207 FLAG utf8_lineends = True; /* detect UTF-8 LS and PS line ends ? */
208 FLAG poormansbidi = True; /* poor man's bidirectional support ? */
209
210 char file_name [maxFILENAMElen]; /* Name of file in use */
211
212 PROT fprot0 = 0644; /* default prot. mode for new files */
213 PROT fprot1 = 0; /* prot. mode for new file being edited */
214 PROT bufprot = 0600; /* prot. mode for paste buffer file */
215 static PROT exeprot = 0111; /* default prot. mask for executables */
216 PROT xprot = 0; /* actual prot. mask representing +x option */
217
218
219 /*======================================================================*\
220 |* Modes and options *|
221 \*======================================================================*/
222
223 static FLAG cmdline_selected = False;
224
225 short MENU = 1;
226 FLAG use_file_tabs = True;
227 static int splash_level = 2; /* Show no/text/SIXEL splash_logo? */
228
229 FLAG flags_changed = False; /* Should flag menu area be redrawn? */
230 static FLAG quickmenu = True; /* Right mouse button pops up menu */
231 static int wheel_scroll = 3; /* Number of lines scrolled by mouse wheel */
232 FLAG modified = False; /* Set when file is modified */
233 FLAG viewonly_mode = False; /* Set when view only mode is selected */
234 FLAG viewonly_locked = False; /* Enforced view only status */
235 FLAG viewonly_err = False; /* Error view only status */
236 FLAG restricted = False; /* Set when edited file shall not be switched */
237
238 /* emulation and keyboard assignment flags */
239 char emulation = 'm'; /* 'e'macs, 'p'ico, 'w'indows, word's'tar */
240 char keypad_mode = 'm'; /* 'm'ined, 'S'hift-select, 'w'indows */
241 FLAG shift_selection = False; /* selection highlighting on shift-cursor */
242 FLAG mined_keypad = True; /* Apply mined keypad assignments */
243 FLAG home_selection = False; /* numeric keypad Home/End forced to Mark/Copy */
244 FLAG small_home_selection = False; /* small keypad Home/End: Mark/Copy */
245 FLAG emacs_buffer = False; /* enable emacs buffer fct for ^K/^T */
246 FLAG paste_stay_left = False; /* cursor stays before pasted region */
247 FLAG tab_left = False; /* Set if moving up/down on TAB should go left */
248 FLAG tab_right = False; /* Set if moving up/down on TAB should go left */
249 FLAG plain_BS = False; /* prefer BS to perform plain rather than smart? */
250
251 FLAG append_flag = False; /* Set when buffer should be appended to */
252 FLAG pastebuf_utf8 = False; /* Paste buffer always treated as UTF-8? */
253 FLAG rectangular_paste_flag = False; /* Copy/Paste rectangular area? */
254 FLAG visselect_key = False; /* Visual selection on unmodified cursor key? */
255 FLAG visselect_anymouse = False; /* Visual selection on any mouse move? */
256 FLAG visselect_keeponsearch = False; /* Keep visual selection on search ? */
257 FLAG visselect_setonfind = False; /* Select search result? */
258 FLAG visselect_autocopy = True; /* Auto-copy selection? */
259 FLAG visselect_copydeselect = True; /* Deselect on copy? */
260 FLAG visselect_autodelete = False; /* Delete selection on insert? */
261
262 FLAG insert_mode = True; /* insert or overwrite */
263
264 int JUSlevel = 0; /* Keep justified while typing? */
265 int JUSmode = 0; /* 1: paragraphs end at empty line */
266 FLAG autoindent = True; /* Auto indent on input of Enter? */
267 FLAG autonumber = True; /* Auto numbering on input of Enter? */
268 FLAG backnumber = True; /* Auto-undent numbering on input of BS? */
269 FLAG backincrem = False; /* Auto-increment numbering on input of BS? */
270 FLAG lowcapstrop = False; /* capitalize letter symbols on input? */
271 FLAG dispunstrop = False; /* display stropped letters in bold? */
272 FLAG strop_selected = False; /* was stropping explictly selected? */
273 char strop_style = ' '; /* bold/underline? */
274 FLAG mark_HTML = UNSURE; /* Display HTML marked ? */
275 FLAG mark_JSP = True; /* Display JSP marked ? */
276
277 char backup_mode = 'a'; /* none ('\0'), simple, e/v/numbered, auto */
278 char * backup_directory = NIL_PTR; /* directory name for backup files */
279 char * recover_directory = NIL_PTR; /* directory name for recovery files */
280 static FLAG homedir_selected = False; /* option -~ given? */
281 static char * inisearch = NIL_PTR; /* Optional startup search string */
282
283 FLAG only_detect_text_encoding = False;
284 static FLAG only_detect_terminal_encoding = False;
285
286 FLAG wordnonblank = False; /* Handle all non-blank sequences as words */
287 FLAG proportional = False; /* Enable support for proportional fonts? */
288 FLAG hide_passwords = UNSURE; /* Hide passwords in display */
289 FLAG filtering_read = False; /* Use filter for reading file ? */
290 char * filter_read = NIL_PTR; /* Filter for reading file */
291 FLAG filtering_write = False; /* Use filter for writing file ? */
292 char * filter_write = NIL_PTR; /* Filter for writing file */
293 FLAG show_vt100_graph = False; /* Display letters as VT100 block graphics ? */
294 FLAG auto_detect = True; /* Auto detect character encoding from file ? */
295 char * detect_encodings; /* List of encodings to detect */
296 char language_tag = 0;
297 FLAG translate_output = False; /* Transform output diacritics to strings */
298 int translen; /* length of " */
299 char * transout; /* Output transformation table */
300 int tabsize = 8; /* Width of tab positions, 2 or 4 or 8 */
301 FLAG tabsize_selected = False; /* Tab width selected by explicit option? */
302 FLAG expand_tabs = False; /* Expand TABs to Spaces? */
303 FLAG controlQS = False; /* must respect ^Q/^S handshake ? */
304 character erase_char = '\010'; /* effective (configured) char for erase left */
305
306 FLAG prefer_comspec = False; /* for ESC ! command (cygwin) */
307 FLAG smart_quotes = True; /* replace " with typographic quote ? */
308 static char * ext_status = NIL_PTR; /* status line per option -_ */
309
310 FLAG disp_scrollbar = True; /* shall scrollbar be displayed ? */
311 FLAG fine_scrollbar = True; /* fine-grained UTF-8 scrollbar ? */
312 FLAG old_scrollbar_clickmode = False; /* old left/right click semantics ? */
313 int scrollbar_width = 1;
314 FLAG update_scrollbar_lazy = True; /* partial scrollbar refresh as needed ? */
315 static FLAG use_window_title = True; /* filename display in window title? */
316 static FLAG use_window_title_query = True; /* query old title / detect title encoding? */
317
318 static FLAG combining_mode_disabled = False; /* combining mode explicitly disabled ? */
319 static FLAG U_mode_set = False;
320
321 FLAG detect_esc_alt = True; /* Enable detection of Alt key by ESC prefix? */
322
323 char selection_space = SPACE_NEXT; /* space behaviour in keyboard mapping menu */
324 FLAG enforce_keymap = True; /* enable keyboard mapping even on non-suitable terminal */
325
326 FLAG page_scroll = False; /* use scroll for page up/down */
327 FLAG page_stay = False; /* stay at edge of screen after page up/down */
328 int display_delay = 3; /* delay between display lines */
329
330 FLAG paradisp = False; /* Shall paragraph end be distinguished? */
331
332 /**
333 Line indicators
334 */
335 static char TABdefault = '�'; /* default TAB indicator */
336 static char RETdefault = '�'; /* indicates line end */
337 static char PARAdefault = '�'; /* indicates end of paragraph */
338 char UNI_marker = '�'; /* Char to be shown in place of Unicode char */
339 char TAB_marker = ' '; /* Char to be shown in place of tab chars */
340 char TAB0_marker = '\0'; /* Char to be shown at start of tab chars */
341 char TAB2_marker = '\0'; /* Char to be shown at end of tab chars */
342 char TABmid_marker = '\0'; /* Char to be shown in middle of tab chars */
343 unsigned long CJK_TAB_marker = 0x2026; /* to be shown in place of tab */
344 char RET_marker = '\0'; /* Char indicating end of line (LF) */
345 char DOSRET_marker = '\0'; /* Char indicating DOS end of line (CRLF) */
346 char MACRET_marker = '\0'; /* Char indicating Mac end of line (CR) */
347 char PARA_marker = '\0'; /* Char indicating end of paragraph */
348 char RETfill_marker = '\0'; /* Char to fill the end of line with */
349 char RETfini_marker = '\0'; /* Char to fill last position of line with */
350 char SHIFT_marker = '�'; /* Char indicating that line continues */
351 char SHIFT_BEG_marker = '�'; /* Char indicating that line continues left */
352 char MENU_marker = '�'; /* Char to mark selected item */
353 char * UTF_TAB_marker = NIL_PTR; /* Char to be shown in place of tab chars */
354 char * UTF_TAB0_marker = NIL_PTR; /* Char to be shown at start of tab chars */
355 char * UTF_TAB2_marker = NIL_PTR; /* Char to be shown at end of tab chars */
356 char * UTF_TABmid_marker = NIL_PTR; /* Char to be shown in middle of tab chars */
357 char * UTF_RET_marker = NIL_PTR; /* Char indicating end of line */
358 char * UTF_DOSRET_marker = NIL_PTR; /* Char indicating DOS end of line */
359 char * UTF_MACRET_marker = NIL_PTR; /* Char indicating Mac end of line */
360 char * UTF_PARA_marker = NIL_PTR; /* Char indicating end of paragraph */
361 char * UTF_RETfill_marker = NIL_PTR; /* Char to fill the end of line with */
362 char * UTF_RETfini_marker = NIL_PTR; /* Char to fill last position of line with */
363 char * UTF_SHIFT_marker = NIL_PTR; /* Char indicating that line continues */
364 char * UTF_SHIFT_BEG_marker = NIL_PTR; /* Char indicating that line continues left */
365 char * UTF_MENU_marker = "✓"; /* Char to mark selected item */
366 static char * UTF_MENU_marker_fancy = "☛";
367 static char * UTF_MENU_marker_alt = "►";
368 char * submenu_marker = "▶";
369 static char * submenu_marker_alt = "►";
370 char * menu_cont_marker = "┆";
371 char * menu_cont_fatmarker = "┇";
372
373 /**
374 Information display preferences
375 */
376 FLAG always_disp_fstat = True; /* Permanent file status display on status line? */
377 FLAG always_disp_help = False; /* Permanent F2... help display on status line? */
378 FLAG always_disp_code = False; /* Permanent char code display on status line? */
379 FLAG disp_scriptname = True; /* display Unicode script range? */
380 FLAG disp_charname = True; /* display Unicode character name? */
381 FLAG disp_charseqname = True; /* display Unicode named sequences? */
382 FLAG disp_decomposition = False; /* display Unicode character decomposition? */
383 FLAG disp_mnemos = False; /* display mined input mnemos? */
384
385 FLAG always_disp_Han = False; /* Permanent Han character description display on status line? */
386 FLAG disp_Han_Mandarin = False; /* display this Han pronunciation ? */
387 FLAG disp_Han_Cantonese = False; /* display this Han pronunciation ? */
388 FLAG disp_Han_Japanese = False; /* display this Han pronunciation ? */
389 FLAG disp_Han_Sino_Japanese = False; /* display this Han pronunciation ? */
390 FLAG disp_Han_Hangul = False; /* display this Han pronunciation ? */
391 FLAG disp_Han_Korean = False; /* display this Han pronunciation ? */
392 FLAG disp_Han_Vietnamese = False; /* display this Han pronunciation ? */
393 FLAG disp_Han_HanyuPinlu = False; /* display this Han pronunciation ? */
394 FLAG disp_Han_HanyuPinyin = False; /* display this Han pronunciation ? */
395 FLAG disp_Han_XHCHanyuPinyin = False; /* display this Han pronunciation ? */
396 FLAG disp_Han_Tang = False; /* display this Han pronunciation ? */
397 FLAG disp_Han_description = True; /* display Han description ? */
398 FLAG disp_Han_full = True; /* display full popup Han description ? */
399
400
401 /*======================================================================*\
402 |* Mouse and other terminal interaction *|
403 \*======================================================================*/
404
405 static FLAG in_selection_mouse_mode = False;
406
407 static
408 void
selection_mouse_mode(selecting)409 selection_mouse_mode (selecting)
410 FLAG selecting;
411 {
412 if (use_mouse_release) {
413 in_selection_mouse_mode = selecting;
414 menu_mouse_mode (selecting);
415 }
416 }
417
418 static
419 void
mouse_scroll(S,P)420 mouse_scroll (S, P)
421 voidfunc S;
422 voidfunc P;
423 {
424 if (in_selection_mouse_mode == True) {
425 in_selection_mouse_mode = VALID;
426 setMARK (True);
427 }
428
429 if (mouse_shift & shift_button) {
430 (* P) ();
431 } else if (mouse_shift & control_button) {
432 (* S) ();
433 } else if (disp_scrollbar && mouse_xpos == XMAX) {
434 hop_flag = 1;
435 (* S) ();
436 } else {
437 int l;
438 for (l = 0; quit == False && l < wheel_scroll && l < YMAX; l ++) {
439 if (l > 0 && disp_scrollbar) {
440 (void) display_scrollbar (True);
441 }
442 (* S) ();
443 }
444 }
445
446 if (in_selection_mouse_mode) {
447 move_to (mouse_xpos, mouse_ypos);
448 }
449 }
450
451 mousebutton_type last_mouse_event = movebutton;
452 static mousebutton_type prev_mouse_event = movebutton;
453 static int prev_x = -1;
454 static int prev_y = -1;
455
456 #define dont_debug_mouse
457
458 /*
459 * MOUSEfunction () is invoked after a mouse escape sequence with
460 coordinates and button info already stored in
461 mouse_xpos, mouse_ypos, and mouse_button.
462 Then it performs a menu or other mouse controlled function.
463 * FOCUSout and FOCUSin are special cases of mouse report for
464 the window losing or gaining focus.
465 * AMBIGnarrow and AMBIGwide are mintty reports of changed ambiguous
466 character width (corresponding to xterm option -cjk_width).
467 */
468 /*
469 MOUSEfunction is most often called after checking parameter from
470 _readchar, as follows:
471 (_readchar:)
472 DIRECTxtermgetxy ('M');
473 keyproc = MOUSEfunction;
474
475 MOUSEfunction may also be called after reading and arranging the
476 parameters, as follows:
477 DIRECTxterm ()
478 {
479 DIRECTxtermgetxy ('M');
480 MOUSEfunction ();
481 }
482 */
483 void
MOUSEfunction()484 MOUSEfunction ()
485 {
486 if (! window_focus) {
487 return;
488 }
489 prev_mouse_event = last_mouse_event;
490 last_mouse_event = mouse_button;
491
492 trace_mouse ("MOUSEfunction");
493
494 if (mouse_ypos < -1) {
495 /* click in filename tab label area */
496 if (use_file_tabs) {
497 char * fn = filelist_search (mouse_ypos + MENU, mouse_xpos);
498 if (fn) {
499 if (! streq (fn, file_name)) {
500 save_text_load_file (fn);
501 }
502 } else {
503 /* "No specific file selected" - clicked on gap */
504 }
505 }
506 } else if (mouse_ypos == -1
507 && ! in_selection_mouse_mode
508 /* double-check whether movebutton enabled for buggy Haiku Terminal */
509 && (mouse_button != movebutton || use_mouse_anymove_always)
510 ) {
511 openmenuat (mouse_xpos);
512 } else if (mouse_button == wheelup) {
513 mouse_scroll (SU, MOVPU);
514 } else if (mouse_button == wheeldown) {
515 mouse_scroll (SD, MOVPD);
516 } else if (disp_scrollbar && mouse_xpos == XMAX) {
517 static int last_dir = 1;
518 if (mouse_button == leftbutton) {
519 if (old_scrollbar_clickmode) {
520 MOVPD ();
521 } else {
522 int cmp = check_scrollbar_pos ();
523 if (cmp < 0) {
524 MOVPU ();
525 last_dir = -1;
526 } else if (cmp > 0) {
527 MOVPD ();
528 last_dir = 1;
529 }
530 }
531 } else if (mouse_button == rightbutton) {
532 if (old_scrollbar_clickmode) {
533 MOVPU ();
534 } else {
535 int cmp = check_scrollbar_pos ();
536 if (cmp < 0) {
537 MOVPD ();
538 } else if (cmp > 0) {
539 MOVPU ();
540 } else if (last_dir > 0) {
541 MOVPU ();
542 } else {
543 MOVPD ();
544 }
545 }
546 } else if (mouse_button == middlebutton
547 || (mouse_button == releasebutton
548 && mouse_prevbutton == middlebutton)
549 || (mouse_button == movebutton
550 /* double-check for the sake of buggy Haiku Terminal */
551 && mouse_buttons_pressed > 0
552 )
553 ) {
554 int proz = (mouse_ypos + 1) * 100 / YMAX;
555 if (proz > 100) {
556 goproz (100);
557 } else {
558 goproz ((mouse_ypos + 1) * 100 / YMAX);
559 }
560 }
561 #if defined (unix) || defined (vms)
562 /* enable scrollbar dragging */
563 if (mouse_button != releasebutton) {
564 mouse_button_event_mode (True);
565 }
566 #endif
567 } else if (mouse_button == movebutton) {
568 /* keep drag-and-copy enabled */
569 report_release = True;
570 #ifdef debug_mouse
571 printf ("MOUSEfunction: report_release = True\n");
572 #endif
573
574 /* workaround for rxvt-unicode quirk:
575 urxvt focus-in sends 3 mouse event codes: click, move, release
576 */
577 if (mouse_prevbutton == leftbutton
578 && mouse_xpos == mouse_prevxpos && mouse_ypos == mouse_prevypos
579 ) {
580 if (rxvt_version > 0) {
581 FOCUSin ();
582 last_mouse_event = mouse_button;
583 }
584 } else if (in_selection_mouse_mode) {
585 /* initiate visual selection */
586 if (in_selection_mouse_mode == True) {
587 in_selection_mouse_mode = VALID;
588 setMARK (True);
589 }
590 /* extend visual selection */
591 if (mouse_ypos == -1) {
592 mouse_scroll (SU, MOVPU);
593 move_to (mouse_xpos, 0);
594 } else if (mouse_ypos == YMAX) {
595 mouse_scroll (SD, MOVPD);
596 move_to (mouse_xpos, YMAX - 1);
597 } else {
598 FLAG alt_mouse = mouse_shift & alt_button
599 ? True
600 : False;
601 adjust_rectangular_mode (alt_mouse);
602 move_to (mouse_xpos, mouse_ypos);
603 }
604 } else if (use_mouse_anymove_always) {
605 /* click-free mouse interface (alpha, experimental) */
606 if (! char_ready_within (350, "mouse")) {
607 if (mouse_ypos == -1) { /* menu stuff */
608 openmenuat (mouse_xpos);
609 }
610 }
611 }
612 } else if (mouse_ypos == YMAX
613 /* ensure that release on bottom line terminates selection */
614 && mouse_button != releasebutton) {
615 if (mouse_button == leftbutton) {
616 MOVPD ();
617 } else if (mouse_button == middlebutton) {
618 if (always_disp_fstat) {
619 display_code ();
620 } else {
621 FS ();
622 }
623 } else if (mouse_button == rightbutton) {
624 MOVPU ();
625 }
626 } else if (quickmenu) {
627 if (mouse_ypos > last_y) {
628 mouse_ypos = last_y;
629 }
630
631 if (mouse_button == leftbutton) {
632 char * prev_text = cur_text;
633 prev_x = x;
634 prev_y = y;
635 move_to (mouse_xpos, mouse_ypos);
636
637 if (x == prev_x && y == prev_y
638 && cur_text == prev_text /* unless moved or shifted */
639 && last_delta_readchar < 500 /* unless too slow */
640 ) {
641 /* word selection on double click */
642 MNW ();
643 setMARK (True);
644 MPW ();
645 } else {
646 if (! visselect_autocopy && ! mouse_shift) {
647 clear_highlight_selection ();
648 /* setMARK (True); */
649 }
650 if (shift_selection && (mouse_shift & shift_button)) {
651 continue_highlight_selection (mouse_xpos);
652 }
653 }
654
655 /* enable drag-and-copy */
656 report_release = True;
657 #ifdef debug_mouse
658 printf ("MOUSEfunction: report_release = True\n");
659 #endif
660
661 /* enable visual selection */
662 selection_mouse_mode (True);
663 } else if (mouse_button == middlebutton) {
664 if (always_disp_fstat) {
665 display_code ();
666 } else {
667 FS ();
668 }
669 } else if (mouse_button == rightbutton) {
670 if (! shift_selection) {
671 move_to (mouse_xpos, mouse_ypos);
672 }
673 display_flush ();
674 QUICKMENU ();
675 } else if (mouse_button == releasebutton
676 && mouse_prevbutton == leftbutton
677 && (mouse_xpos != mouse_prevxpos
678 || mouse_ypos != mouse_prevypos)) {
679 /* mouse-drag selection in terminal without move reports */
680 if (in_selection_mouse_mode != VALID) {
681 setMARK (True);
682 }
683 move_to (mouse_xpos, mouse_ypos);
684 if (visselect_autocopy) {
685 COPY ();
686 }
687 if (in_selection_mouse_mode) {
688 selection_mouse_mode (False);
689 }
690 } else if (mouse_button == releasebutton && in_selection_mouse_mode
691 && (mouse_xpos != mouse_prevxpos
692 || mouse_ypos != mouse_prevypos)) {
693 /* mouse-drag selection in terminal with mouse move reports */
694 move_to (mouse_xpos, mouse_ypos);
695 if (visselect_autocopy) {
696 COPY ();
697 }
698 selection_mouse_mode (False);
699 } else if (mouse_button == releasebutton
700 && prev_mouse_event == focusin
701 && rxvt_version > 0
702 ) {
703 /* try to revert previous click-positioning? */
704 move_to (prev_x, prev_y);
705 } else {
706 /* catch short click/release to not keep up selection */
707 if (in_selection_mouse_mode) {
708 selection_mouse_mode (False);
709 }
710 }
711 } else {
712 prev_x = x;
713 prev_y = y;
714
715 if (mouse_ypos > last_y) {
716 mouse_ypos = last_y;
717 }
718 move_to (mouse_xpos, mouse_ypos);
719
720 if (mouse_button == leftbutton) {
721 if (x == prev_x && y == prev_y) {
722 MNW ();
723 setMARK (True);
724 MPW ();
725 } else {
726 setMARK (True);
727 }
728 } else if (mouse_button == middlebutton) {
729 PASTE ();
730 } else if (mouse_button == rightbutton) {
731 COPY ();
732 }
733 }
734 }
735
736 void
FOCUSout()737 FOCUSout ()
738 {
739 #ifdef debug_mouse
740 printf ("mouse focus out\n");
741 #endif
742 window_focus = False;
743 mouse_button = focusout;
744 }
745
746 void
FOCUSin()747 FOCUSin ()
748 {
749 #ifdef debug_mouse
750 printf ("mouse focus in\n");
751 #endif
752 window_focus = True;
753 mouse_button = focusin;
754 }
755
756 void
AMBIGnarrow()757 AMBIGnarrow ()
758 {
759 /*check_cjk_width ();*/
760
761 width_data_version = cjk_width_data_version;
762 cjk_width_data_version = 0;
763 config_markers ();
764
765 RDwin ();
766 }
767
768 void
AMBIGwide()769 AMBIGwide ()
770 {
771 /*check_cjk_width ();*/
772 cjk_width_data_version = width_data_version;
773
774 fine_scrollbar = False;
775 limited_marker_font = True;
776 if (! explicit_border_style) {
777 use_stylish_menu_selection = False;
778 }
779 config_markers ();
780
781 RDwin ();
782 }
783
784
785 /*======================================================================*\
786 |* Screen size handling *|
787 \*======================================================================*/
788
789 #ifdef msdos
790 #ifdef __TURBOC__
791 #define msdos_screenfunctions
792 #endif
793 #endif
794
795
796 #define dont_debug_checkwinsize
797
798 #ifdef debug_checkwinsize
799 #define trace_checkwinsize(params) printf params
800 #else
801 #define trace_checkwinsize(params)
802 #endif
803
804 static
805 void
change_screen_size(sb,keep_columns)806 change_screen_size (sb, keep_columns)
807 FLAG sb;
808 FLAG keep_columns;
809 {
810 trace_checkwinsize (("change_screen_size (HOP %d) SML/BIG %d keep_col %d\n", hop_flag, sb, keep_columns));
811 /* Experimental area: */
812 /* set_screen_mode (mode1); any available mode number */
813 /* set_video_lines (mode1); 0/1/2: 200/350/400 lines */
814 /* does not seem to have any effect */
815 /* set_textmode_height (mode1); 0/1/2: font height 8/14/16 */
816 /* set_grafmode_height (mode1, mode2);
817 0/1/2: font height 8/14/16 1/2/3/n: 14/25/43/n lines */
818 /* set_fontbank (f); 0..7 */
819 /**/
820 if (hop_flag > 0) {
821 int index;
822 int mode1;
823
824 #ifdef msdos_screenfunctions
825 int mode2;
826
827 if (keep_columns) {
828 if (sb == BIGGER) {
829 index = get_number ("Switch to font bank (0..7) ", '\0', & mode1);
830 if (index == ERRORS) {
831 return;
832 }
833 set_fontbank (mode1);
834 } else {
835 index = get_number ("Set character height (<= 32 pixels) ", '\0', & mode1);
836 if (index == ERRORS) {
837 return;
838 }
839 set_font_height (mode1);
840 }
841 } else {
842 if (sb == BIGGER) {
843 #endif
844 index = get_number ("Select video mode ", '\0', & mode1);
845 if (index == ERRORS) {
846 return;
847 }
848 set_screen_mode (mode1);
849 #ifdef msdos_screenfunctions
850 } else {
851 index = get_number ("Select graf font (0/1/2: font height 8/14/16) ", '\0', & mode1);
852 if (index == ERRORS) {
853 return;
854 }
855 index = get_number ("Select line number (1/2/3/n: 14/25/43/n) ", '\0', & mode2);
856 if (index == ERRORS) {
857 return;
858 }
859 set_grafmode_height (mode1, mode2); /* 0/1/2: font height 8/14/16 */
860 /* 1/2/3/n: 14/25/43/n lines */
861 }
862 }
863 #endif
864 } else {
865 resize_the_screen (sb, keep_columns);
866 }
867 RDwin ();
868 }
869
870 static
871 void
change_font_size(inc)872 change_font_size (inc)
873 int inc;
874 {
875 resize_font (inc);
876 RDwin ();
877 }
878
879 void
screenmorelines()880 screenmorelines ()
881 {
882 change_screen_size (BIGGER, True);
883 }
884
885 void
screenlesslines()886 screenlesslines ()
887 {
888 change_screen_size (SMALLER, True);
889 }
890
891 void
screenmorecols()892 screenmorecols ()
893 {
894 change_screen_size (BIGGER, NOT_VALID);
895 }
896
897 void
screenlesscols()898 screenlesscols ()
899 {
900 change_screen_size (SMALLER, NOT_VALID);
901 }
902
903 void
screenbigger()904 screenbigger ()
905 {
906 change_screen_size (BIGGER, False);
907 }
908
909 void
screensmaller()910 screensmaller ()
911 {
912 change_screen_size (SMALLER, False);
913 }
914
915 void
fontbigger()916 fontbigger ()
917 {
918 change_font_size (1);
919 }
920
921 void
fontsmaller()922 fontsmaller ()
923 {
924 change_font_size (-1);
925 }
926
927 void
fontdefault()928 fontdefault ()
929 {
930 change_font_size (0);
931 }
932
933 void
LNCI()934 LNCI ()
935 {
936 switch_textmode_height (True);
937 RDwin ();
938 }
939
940 void
LNSW()941 LNSW ()
942 {
943 if (hop_flag > 0) {
944 hop_flag = 0;
945 LNCI ();
946 } else {
947 switch_textmode_height (False);
948 RDwin ();
949 }
950 }
951
952
953 /*======================================================================*\
954 |* Restriction handling *|
955 \*======================================================================*/
956
957 /*
958 * viewonlyerr () outputs an error message with a beep
959 */
960 void
viewonlyerr()961 viewonlyerr ()
962 {
963 ring_bell ();
964 error ("View only mode");
965 }
966
967 /*
968 * restrictederr () outputs an error message with a beep
969 */
970 void
restrictederr()971 restrictederr ()
972 {
973 ring_bell ();
974 error2 ("Restricted mode", " - function not allowed");
975 }
976
977
978 /*
979 * Set the modified flag
980 */
981 void
set_modified()982 set_modified ()
983 {
984 if (modified == False) {
985 modified = True;
986 #ifdef unix
987 RD_window_title ();
988 #endif
989 }
990 clear_highlight_selection ();
991 }
992
993
994 /*======================================================================*\
995 |* Keyboard macros *|
996 \*======================================================================*/
997
998 #define dont_enable_key_macros
999
1000 #ifdef enable_key_macros
1001 # define debug_key_macros
1002 #endif
1003
1004 #ifdef debug_key_macros
1005 #define trace_key_macros(params) printf params
1006 #else
1007 #define trace_key_macros(params)
1008 #endif
1009
1010 static FLAG key_recording = False;
1011 static FLAG key_replaying = False;
1012
1013 #ifndef enable_key_macros
1014 void
KEYREC()1015 KEYREC ()
1016 {
1017 }
1018 static
1019 void
KEYrecord(key)1020 KEYrecord (key)
1021 unsigned long key;
1022 {
1023 }
1024 static
1025 unsigned long
KEYreplay()1026 KEYreplay ()
1027 {
1028 return 0;
1029 }
1030 #else
1031
1032 /**
1033 first experimental attempt: one static limited buffer
1034 plan: multiple unlimited buffers, assignable to keys
1035 */
1036 static struct {
1037 unsigned long key;
1038 unsigned char shift;
1039 voidfunc proc;
1040 } keyrec [] = {
1041 {0, 0, I},
1042 {0, 0, I},
1043 {0, 0, I},
1044 {0, 0, I},
1045 {0, 0, I},
1046 {0, 0, I},
1047 {0, 0, I},
1048 {0, 0, I},
1049 {0, 0, I},
1050 {0, 0, I},
1051 {0, 0, I},
1052 };
1053 #define maxkeyreclen arrlen (keyrec)
1054
1055 static int keyreci = 0;
1056 static int keyreclen = 0;
1057
1058 void
KEYREC()1059 KEYREC ()
1060 {
1061 if (keyshift & shift_mask) {
1062 /* Record keyboard macro */
1063 if (key_replaying) {
1064 /* display notice that key replaying is aborted? */
1065 key_replaying = False;
1066 }
1067
1068 if (key_recording) {
1069 /* Stop keyboard macro recording */
1070 key_recording = False;
1071 keyreclen --; /* fix KEYREC already inserted */
1072 } else {
1073 /* Start keyboard macro recording */
1074 key_recording = True;
1075 keyreci = 0;
1076 }
1077 } else {
1078 /* Replay keyboard macro */
1079 if (key_recording) {
1080 /* display notice that key recording is aborted? */
1081 key_recording = False;
1082 }
1083
1084 if (key_replaying) {
1085 /* abort invalid recursive macro replaying */
1086 key_replaying = False;
1087 ring_bell ();
1088 } else if (keyreclen > 0) {
1089 /* Start keyboard macro replaying */
1090 keyreci = 0;
1091 key_replaying = True;
1092 } else {
1093 /* display notice that key replaying is not available? */
1094 ring_bell ();
1095 }
1096 }
1097 }
1098
1099 static
1100 void
KEYrecord(key)1101 KEYrecord (key)
1102 unsigned long key;
1103 {
1104 if (keyreci >= maxkeyreclen) {
1105 key_recording = False;
1106 trace_key_macros (("KEYrecord buf\n"));
1107 ring_bell ();
1108 } else {
1109 keyrec [keyreci].key = key;
1110 keyrec [keyreci].shift = keyshift;
1111 keyrec [keyreci].proc = keyproc;
1112 trace_key_macros (("KEYrecord [%d] %02lX\n", keyreci, key));
1113 keyreci ++;
1114 keyreclen = keyreci;
1115 }
1116 }
1117
1118 static
1119 unsigned long
KEYreplay()1120 KEYreplay ()
1121 {
1122 unsigned long key = keyrec [keyreci].key;
1123 keyshift = keyrec [keyreci].shift;
1124 keyproc = keyrec [keyreci].proc;
1125 trace_key_macros (("KEYreplay [%d (%d)] %02lX\n", keyreci, keyreclen, key));
1126 keyreci ++;
1127 if (keyreci >= keyreclen) {
1128 key_replaying = False;
1129 }
1130 return key;
1131 }
1132
1133 #endif
1134
1135
1136 /*======================================================================*\
1137 |* Setup display preferences *|
1138 \*======================================================================*/
1139
1140 /**
1141 Configure line and display markers.
1142 Width data detection must be settled for the case of UTF-8.
1143 */
1144 static
1145 void
config_markers()1146 config_markers ()
1147 {
1148 char * Mark;
1149
1150 Mark = envvar ("MINEDSHIFT");
1151 if (Mark != NIL_PTR) {
1152 SHIFT_BEG_marker = Mark [0];
1153 if (SHIFT_BEG_marker == ' ') {
1154 SHIFT_BEG_marker = '\0';
1155 }
1156 if (Mark [0] && Mark [1]) {
1157 SHIFT_marker = Mark [1];
1158 }
1159 }
1160
1161 Mark = envvar ("MINEDTAB");
1162 if (Mark != NIL_PTR) {
1163 if (Mark [0] == '\0') {
1164 TAB_marker = TABdefault;
1165 } else {
1166 TAB_marker = Mark [0];
1167 if (Mark [1]) {
1168 if (Mark [2]) {
1169 TAB0_marker = Mark [0];
1170 TAB_marker = Mark [1];
1171 TAB2_marker = Mark [2];
1172 } else {
1173 TABmid_marker = Mark [1];
1174 }
1175 }
1176 if (TAB_marker >= ' ' && TAB_marker != '\\' && TAB_marker < '~') {
1177 CJK_TAB_marker = TAB_marker;
1178 }
1179 }
1180 } else {
1181 TAB_marker = TABdefault;
1182 }
1183
1184 Mark = envvar ("MINEDRET");
1185 if (Mark != NIL_PTR) {
1186 RET_marker = Mark [0];
1187 if (RET_marker != '\0') {
1188 RETfill_marker = Mark [1];
1189 }
1190 if (RETfill_marker != '\0') {
1191 RETfini_marker = Mark [2];
1192 }
1193 } else {
1194 RET_marker = RETdefault;
1195 }
1196 Mark = envvar ("MINEDDOSRET");
1197 if (Mark && * Mark) {
1198 DOSRET_marker = Mark [0];
1199 } else {
1200 if (bw_term) {
1201 DOSRET_marker = '�';
1202 } else {
1203 DOSRET_marker = RET_marker;
1204 }
1205 }
1206 Mark = envvar ("MINEDMACRET");
1207 if (Mark && * Mark) {
1208 MACRET_marker = Mark [0];
1209 } else {
1210 if (bw_term) {
1211 MACRET_marker = '@';
1212 } else {
1213 MACRET_marker = RET_marker;
1214 }
1215 }
1216 Mark = envvar ("MINEDPARA");
1217 if (Mark && * Mark) {
1218 PARA_marker = Mark [0];
1219 } else {
1220 PARA_marker = PARAdefault;
1221 }
1222 Mark = envvar ("MINEDMENUMARKER");
1223 if (Mark) {
1224 if (* Mark) {
1225 MENU_marker = Mark [0];
1226 } else {
1227 /*MENU_marker = '`';*/
1228 MENU_marker = '*';
1229 }
1230 }
1231
1232 if (cjk_width_data_version) {
1233 submenu_marker = submenu_marker_alt;
1234 }
1235
1236 if (! limited_marker_font) {
1237 /* unlimited font settings */
1238 UTF_SHIFT_BEG_marker = envvar ("MINEDUTFSHIFT");
1239 if (UTF_SHIFT_BEG_marker && * UTF_SHIFT_BEG_marker) {
1240 UTF_SHIFT_marker = UTF_SHIFT_BEG_marker;
1241 advance_utf8 (& UTF_SHIFT_marker);
1242 if (* UTF_SHIFT_BEG_marker == ' ') {
1243 UTF_SHIFT_BEG_marker = "";
1244 }
1245 }
1246 UTF_TAB_marker = envvar ("MINEDUTFTAB");
1247 if (UTF_TAB_marker != NIL_PTR) {
1248 char * markpoi = UTF_TAB_marker;
1249 if (* markpoi) {
1250 advance_utf8 (& markpoi);
1251 if (* markpoi) {
1252 UTF_TAB0_marker = UTF_TAB_marker;
1253 UTF_TAB_marker = markpoi;
1254 advance_utf8 (& markpoi);
1255 if (* markpoi) {
1256 UTF_TAB2_marker = markpoi;
1257 } else {
1258 UTF_TABmid_marker = UTF_TAB_marker;
1259 UTF_TAB_marker = UTF_TAB0_marker;
1260 UTF_TAB0_marker = NIL_PTR;
1261 }
1262 }
1263 }
1264 }
1265 UTF_RET_marker = envvar ("MINEDUTFRET");
1266 if (UTF_RET_marker != NIL_PTR) {
1267 UTF_RETfill_marker = UTF_RET_marker;
1268 if (* UTF_RETfill_marker != '\0') {
1269 advance_utf8 (& UTF_RETfill_marker);
1270 }
1271 UTF_RETfini_marker = UTF_RETfill_marker;
1272 if (* UTF_RETfini_marker != '\0') {
1273 advance_utf8 (& UTF_RETfini_marker);
1274 }
1275 }
1276 UTF_DOSRET_marker = envvar ("MINEDUTFDOSRET");
1277 if (UTF_DOSRET_marker == NIL_PTR) {
1278 if (bw_term) {
1279 UTF_DOSRET_marker = "µ";
1280 } else {
1281 UTF_DOSRET_marker = UTF_RET_marker;
1282 }
1283 }
1284 UTF_MACRET_marker = envvar ("MINEDUTFMACRET");
1285 if (UTF_MACRET_marker == NIL_PTR) {
1286 if (bw_term) {
1287 UTF_MACRET_marker = "@";
1288 } else {
1289 UTF_MACRET_marker = UTF_RET_marker;
1290 }
1291 }
1292 UTF_PARA_marker = envvar ("MINEDUTFPARA");
1293 Mark = envvar ("MINEDUTFMENUMARKER");
1294 if (Mark) {
1295 if (* Mark) {
1296 int len;
1297 unsigned long unichar;
1298 utf8_info (Mark, & len, & unichar);
1299 if (len > 1 && ! iswide (unichar) && ! iscombining (unichar)) {
1300 UTF_MENU_marker = Mark;
1301 }
1302 } else {
1303 UTF_MENU_marker = UTF_MENU_marker_fancy;
1304 }
1305 }
1306 } else if (! very_limited_marker_font) {
1307 /* limited font settings */
1308 UTF_MENU_marker = UTF_MENU_marker_alt;
1309 submenu_marker = submenu_marker_alt;
1310 } else {
1311 /* very limited font settings */
1312 UTF_MENU_marker = "»";
1313 submenu_marker = "»";
1314 }
1315 }
1316
1317 #ifdef unix
1318
1319 static float dimfactor = 0.6; /* MUST be >= 0 AND <= 1 ! */
1320 static float bgdimfactor = 0.15; /* MUST be >= 0 AND <= 1 ! */
1321
1322 static
1323 char *
get_terminal_rgb(s)1324 get_terminal_rgb (s)
1325 char * s;
1326 {
1327 char * report = get_terminal_report_string (s);
1328 if (report) {
1329 return strstr (report, "rgb:");
1330 } else {
1331 return NIL_PTR;
1332 }
1333 }
1334
1335 static
1336 int
sscanrgb(s,__r,__g,__b)1337 sscanrgb (s, __r, __g, __b)
1338 char * s;
1339 unsigned int * __r;
1340 unsigned int * __g;
1341 unsigned int * __b;
1342 {
1343 char * rgb = strstr (s, "rgb:");
1344 if (rgb) {
1345 if (sscanf (rgb, "rgb:%04X/%04X/%04X", __r, __g, __b) == 3) {
1346 return 3;
1347 }
1348 }
1349 return 0;
1350 }
1351
1352 /**
1353 Determine a suitable dim mode for marker display
1354 (TAB, line end indicators).
1355 Also check whether terminal background is dark (to adjust highlighting).
1356 * Retrieve color values of text and background colors.
1357 * Calculate a value between them.
1358 * Retrieve color value of ANSI color 7 (for later restoring).
1359 * Redefine ANSI color 7 to calculated color for use as dim attribute.
1360 Works in xterm, should work in rxvt (but doesn't...).
1361 The feature is activated if the environment variable MINEDDIM is
1362 set to an empty value.
1363 The feature is not applied if the terminal provides a native dim mode.
1364 */
1365 static
1366 FLAG
determine_dim_mode(darkcheck_only)1367 determine_dim_mode (darkcheck_only)
1368 FLAG darkcheck_only;
1369 {
1370 char * color_report;
1371 int ret;
1372 int r, g, b, _r, _g, _b, r_, g_, b_, r3, g3, b3; /* signed! */
1373
1374 #define dont_debug_dim_mode
1375
1376 if (tmux_version > 0) {
1377 return False;
1378 }
1379
1380 /* check whether terminal can report ANSI colours */
1381 if (! (xterm_version > 2 || mintty_version >= 404 || rxvt_version >= 300 || gnome_terminal_version)) {
1382 return False;
1383 }
1384
1385 /* query current ANSI color 3 to fix misconfigured yellow */
1386 color_report = get_terminal_rgb ("\033]4;3;?\033\\");
1387 if (! color_report) {
1388 return False;
1389 }
1390 /* only redefine yellow if it's grossly misconfigured */
1391 ret = sscanrgb (color_report, & r3, & g3, & b3);
1392 #ifdef debug_dim_mode
1393 printf ("ANSI color 3 (yellow) %s -> %d: %04X %04X %04X\n", color_report, ret, r3, g3, b3);
1394 #endif
1395 if (ret < 3) {
1396 return False;
1397 }
1398 /* build escape string to restore ANSI color 3 */
1399 build_string (restore_ansi3, "\033]4;3;%s\033\\", color_report);
1400 /* check whether yellow is too dark (e.g. actually more brown) */
1401 r = (r3 - 0xC000) >> 8;
1402 g = (g3 - 0xC000) >> 8;
1403 b = b3 >> 8;
1404 if (r * r + g * g + b * b > 12000) {
1405 redefined_ansi3 = True;
1406 /* build escape string to define ANSI color 3 as yellow */
1407 build_string (set_ansi3, "\033]4;3;rgb:C000/C000/0000\033\\");
1408 #ifdef debug_dim_mode
1409 printf (" redefining yellow %s\n", set_ansi3 + 6);
1410 #endif
1411 /* redefine ANSI color 3 as yellow */
1412 putescape (set_ansi3);
1413 }
1414
1415 /* check whether terminal can report background colours */
1416 if (! (xterm_version > 0 || mintty_version >= 404 || rxvt_version >= 300)) {
1417 return False;
1418 }
1419
1420 /* query terminal background color */
1421 color_report = get_terminal_rgb ("\033]11;?\033\\");
1422 if (! color_report) {
1423 return False;
1424 }
1425 /* analyse query result */
1426 ret = sscanrgb (color_report, & _r, & _g, & _b);
1427 #ifdef debug_dim_mode
1428 printf ("background color %s -> %d: %04X %04X %04X\n", color_report, ret, _r, _g, _b);
1429 #endif
1430 if (ret < 3) {
1431 return False;
1432 }
1433
1434 darkness_detected = True;
1435
1436 /* check dark background */
1437 if (_r + _g + _b < 99000) { /* range is 0...65535 * 3 */
1438 dark_term = True;
1439 #ifdef debug_dim_mode
1440 printf (" -> dark_term\n");
1441 #endif
1442 }
1443
1444 /* query color 48, the one with the largest difference between
1445 256 color mode and 88 color mode
1446 */
1447 color_report = get_terminal_rgb ("\033]4;48;?\033\\");
1448 if (color_report) {
1449 /* analyse query result */
1450 ret = sscanrgb (color_report, & r, & g, & b);
1451 #ifdef debug_dim_mode
1452 printf ("color 48 %s -> %d: %04X %04X %04X\n", color_report, ret, r, g, b);
1453 #endif
1454 /* check whether it's nearer to color 48 of
1455 256 color mode or 88 color mode
1456 */
1457 if (ret == 3) {
1458 /* difference to 88 color mode color 48 */
1459 int _r = r - 170;
1460 int _g = g - 0;
1461 int _b = b - 0;
1462 /* difference to 256 color mode color 48 */
1463 int r_ = r - 0;
1464 int g_ = g - 255;
1465 int b_ = b - 102;
1466 if (_r * _r + _g * _g + _b * _b < r_ * r_ + g_ * g_ + b_ * b_) {
1467 colours_88 = True;
1468 colours_256 = False;
1469 } else {
1470 colours_256 = True;
1471 colours_88 = False;
1472 }
1473 #ifdef debug_dim_mode
1474 printf (" detected %d color mode\n", colours_256 ? 256 : 88);
1475 #endif
1476 }
1477 }
1478
1479 #ifdef dont_use_dimmed_menu_bg
1480 if (darkcheck_only) {
1481 return dark_term;
1482 }
1483 /* check whether we need to dim ourselves */
1484 if (can_dim) {
1485 #ifdef debug_dim_mode
1486 printf ("terminal has native dim attribute, not redefining colours\n");
1487 #endif
1488 return False;
1489 }
1490 #endif
1491
1492 /* query terminal text color */
1493 color_report = get_terminal_rgb ("\033]10;?\033\\");
1494 if (! color_report) {
1495 return darkcheck_only ? dark_term : False;
1496 }
1497 /* analyse query result */
1498 ret = sscanrgb (color_report, & r, & g, & b);
1499 #ifdef debug_dim_mode
1500 printf ("foreground color %s -> %d: %04X %04X %04X\n", color_report, ret, r, g, b);
1501 #endif
1502 if (ret < 3) {
1503 return darkcheck_only ? dark_term : False;
1504 }
1505
1506 if (! mlterm_version) {
1507 /* query terminal cursor color */
1508 color_report = get_terminal_rgb ("\033]12;?\033\\");
1509 if (color_report) {
1510 /* analyse query result */
1511 ret = sscanrgb (color_report, & r_, & g_, & b_);
1512 #ifdef debug_dim_mode
1513 printf ("cursor color %s -> %d: %04X %04X %04X\n", color_report, ret, r_, g_, b_);
1514 #endif
1515 if (ret == 3) {
1516 if ((r_ == r && g_ == g && b_ == b) || (r_ == _r && g_ == _g && b_ == _b)) {
1517 redefined_curscolr = True;
1518 /* build escape string to restore cursor color */
1519 build_string (restore_curscolr, "\033]12;%s\033\\", color_report);
1520 /* ensure cursor contrast */
1521 /* calculate cursor color, between foreground and background */
1522 r_ = _r + (r - _r) / 2;
1523 g_ = _g + (g - _g) / 2;
1524 b_ = _b + (b - _b) / 2;
1525 /* build escape string to define cursor color */
1526 build_string (set_curscolr, "\033]12;rgb:%04X/%04X/%04X\033\\", r_, g_, b_);
1527 #ifdef debug_dim_mode
1528 printf (" using cursor color %s\n", set_curscolr + 6);
1529 #endif
1530 /* redefine cursor color */
1531 putescape (set_curscolr);
1532 }
1533 }
1534 }
1535 }
1536
1537 /* check whether text color is near yellow */
1538 r3 = (0xC000 - r) >> 8;
1539 g3 = (0xC000 - g) >> 8;
1540 b3 = (0x0000 - b) >> 8;
1541 /* use blue (for flags) rather than yellow */
1542 if (r3 * r3 + g3 * g3 + b3 * b3 < 12000) {
1543 fg_yellowish = True;
1544 }
1545
1546 /* query current ANSI color 2 */
1547 color_report = get_terminal_rgb ("\033]4;2;?\033\\");
1548 if (! color_report) {
1549 return darkcheck_only ? dark_term : False;
1550 }
1551 /* build escape string to restore ANSI color 2 */
1552 build_string (restore_ansi2, "\033]4;2;%s\033\\", color_report);
1553 redefined_ansi2 = True;
1554 /* calculate menu bg color, dimmed from background */
1555 if (r + g + b > _r + _g + _b) {
1556 r_ = _r + (65535 - _r) * bgdimfactor;
1557 g_ = _g + (65535 - _g) * bgdimfactor;
1558 b_ = _b + (65535 - _b) * bgdimfactor;
1559 #ifdef debug_dim_mode
1560 printf (" %d,%d,%d > %d,%d,%d -> %d,%d,%d\n", r, g, b, _r, _g, _b, r_, g_, b_);
1561 #endif
1562 } else {
1563 r_ = _r + (0 - _r) * bgdimfactor;
1564 g_ = _g + (0 - _g) * bgdimfactor;
1565 b_ = _b + (0 - _b) * bgdimfactor;
1566 #ifdef debug_dim_mode
1567 printf (" %d,%d,%d < %d,%d,%d -> %d,%d,%d\n", r, g, b, _r, _g, _b, r_, g_, b_);
1568 #endif
1569 }
1570 /* build escape string to define ANSI color 2 as menu bg color */
1571 build_string (set_ansi2, "\033]4;2;rgb:%04X/%04X/%04X\033\\", r_, g_, b_);
1572 #ifdef debug_dim_mode
1573 printf (" using menu bg color %s\n", set_ansi2 + 6);
1574 #endif
1575 /* redefine ANSI color 2 as menu bg color */
1576 putescape (set_ansi2);
1577
1578 if (darkcheck_only) {
1579 #ifdef debug_dim_mode
1580 printf ("darkcheck only\n");
1581 #endif
1582 return dark_term;
1583 }
1584 /* check whether we need to dim ourselves */
1585 if (can_dim) {
1586 #ifdef debug_dim_mode
1587 printf ("terminal has native dim attribute, not redefining colours\n");
1588 #endif
1589 return False;
1590 }
1591
1592 /* query current ANSI color 7 */
1593 color_report = get_terminal_rgb ("\033]4;7;?\033\\");
1594 if (! color_report) {
1595 return False;
1596 }
1597 /* build escape string to restore ANSI color 7 */
1598 build_string (restore_ansi7, "\033]4;7;%s\033\\", color_report);
1599 redefined_ansi7 = True;
1600 /* calculate dim color, between foreground and background */
1601 r_ = _r + (r - _r) * dimfactor;
1602 g_ = _g + (g - _g) * dimfactor;
1603 b_ = _b + (b - _b) * dimfactor;
1604 /* mix in some red */
1605 r_ += (65535 - r_) / 2;
1606 /* build escape string to define ANSI color 7 as dim color */
1607 build_string (set_ansi7, "\033]4;7;rgb:%04X/%04X/%04X\033\\", r_, g_, b_);
1608 #ifdef debug_dim_mode
1609 printf (" using dim color %s\n", set_ansi7 + 6);
1610 #endif
1611 /* redefine ANSI color 7 as dim color */
1612 putescape (set_ansi7);
1613
1614 return True;
1615 }
1616
1617 #else
1618
1619 static
1620 FLAG
determine_dim_mode(darkcheck_only)1621 determine_dim_mode (darkcheck_only)
1622 FLAG darkcheck_only;
1623 {
1624 return False;
1625 }
1626
1627 #endif
1628
1629 /**
1630 Setup configured display attributes for certain items
1631 */
1632 static
1633 void
get_ansi_modes()1634 get_ansi_modes ()
1635 {
1636 markansi = envvar ("MINEDDIM");
1637 if (markansi != NIL_PTR) {
1638 #ifdef unix
1639 /* check if MINEDDIM is a percentage value */
1640 int dim_percent;
1641 char c;
1642 int res = sscanf (markansi, "%d%c", & dim_percent, & c);
1643 if (res == 2 && c == '%' && dim_percent > 0 && dim_percent < 100) {
1644 dimfactor = dim_percent / 100.0;
1645 markansi = ""; /* trigger procedure below */
1646 }
1647 #endif
1648 }
1649 if (markansi == NIL_PTR || * markansi == '\0') {
1650 if (determine_dim_mode (False)) {
1651 markansi = "37"; /* use redefined ANSI color 7 */
1652 } else {
1653 markansi = "31"; /* use red */
1654 }
1655 } else {
1656 (void) determine_dim_mode (True);
1657 }
1658
1659 emphansi = envvar ("MINEDEMPH");
1660 if (emphansi == NIL_PTR) {
1661 emphansi = "31"; /* use red */
1662 }
1663
1664 borderansi = envvar ("MINEDBORDER");
1665 if (borderansi == NIL_PTR) {
1666 borderansi = "31";
1667 }
1668
1669 selansi = envvar ("MINEDSEL");
1670 selfgansi = envvar ("MINEDSELFG");
1671 if (selfgansi == NIL_PTR) {
1672 selfgansi = "43";
1673 }
1674 if (selansi == NIL_PTR) {
1675 if (dark_term) {
1676 selansi = "34;1";
1677 } else {
1678 selansi = "34";
1679 }
1680 }
1681
1682 uniansi = envvar ("MINEDUNI");
1683 if (uniansi == NIL_PTR) {
1684 if (cjk_term) {
1685 /* needed for hanterm */
1686 uniansi = "36;7;40";
1687 } else {
1688 uniansi = "40;36;7";
1689 }
1690 } else if ((character) * uniansi > '9') {
1691 UNI_marker = * uniansi;
1692 do {
1693 uniansi ++;
1694 } while (* uniansi == ' ');
1695 }
1696 specialansi = envvar ("MINEDSPECIAL");
1697 if (specialansi == NIL_PTR) {
1698 specialansi = "36;1";
1699 }
1700 combiningansi = envvar ("MINEDCOMBINING");
1701 if (combiningansi == NIL_PTR) {
1702 combiningansi = "46;30";
1703 }
1704
1705 ctrlansi = envvar ("MINEDCTRL");
1706 if (ctrlansi == NIL_PTR) {
1707 ctrlansi = "";
1708 }
1709 menuansi = envvar ("MINEDMENU");
1710 if (menuansi == NIL_PTR) {
1711 menuansi = "";
1712 }
1713 HTMLansi = envvar ("MINEDHTML");
1714 if (HTMLansi == NIL_PTR) {
1715 if (dark_term) {
1716 HTMLansi = "36"; /* conflicts with JSP */
1717 HTMLansi = "1;34"; /* not sufficient with dark blue */
1718 HTMLansi = "34;42";
1719 HTMLansi = "34;46";
1720 #ifdef special_case_for_very_dark
1721 if (streq ("cygwin", TERM)) {
1722 HTMLansi = "1;36";
1723 }
1724 #endif
1725 } else {
1726 HTMLansi = "34";
1727 }
1728 }
1729 XMLattribansi = envvar ("MINEDXMLATTRIB");
1730 if (XMLattribansi == NIL_PTR) {
1731 if (dark_term) {
1732 XMLattribansi = "31;46";
1733 } else {
1734 XMLattribansi = "31";
1735 }
1736 }
1737 XMLvalueansi = envvar ("MINEDXMLVALUE");
1738 if (XMLvalueansi == NIL_PTR) {
1739 if (dark_term) {
1740 XMLvalueansi = "35;1;46";
1741 } else {
1742 XMLvalueansi = "35;1";
1743 }
1744 }
1745 diagansi = envstr ("MINEDDIAG");
1746
1747 scrollbgansi = envvar ("MINEDSCROLLBG");
1748 if (scrollbgansi == NIL_PTR) {
1749 if (colours_256 || colours_88) {
1750 /*scrollbgansi = "34;48;5;45";*/
1751 scrollbgansi = "46;34;48;5;45";
1752 } else {
1753 scrollbgansi = "46;34";
1754 }
1755 }
1756 scrollfgansi = envvar ("MINEDSCROLLFG");
1757 if (scrollfgansi == NIL_PTR) {
1758 scrollfgansi = "";
1759 if (colours_256 || colours_88) {
1760 /*scrollfgansi = "44;38;5;45";*/
1761 /*scrollfgansi = "44;36;38;5;45";*/
1762 } else if (cjk_term && (text_encoding_tag == 'K' || text_encoding_tag == 'H')
1763 && strisprefix ("xterm", TERM)
1764 ) {
1765 /* probably hanterm; attributes will all be reverse
1766 and could not be distinguished to build the scrollbar
1767 */
1768 /*scrollfgansi = "0";*/
1769 scrollfgansi = "44;36";
1770 } else {
1771 /*scrollfgansi = "44;36";*/
1772 }
1773 }
1774 }
1775
1776
1777 /*======================================================================*\
1778 |* Terminal report, window resize handling *|
1779 \*======================================================================*/
1780
1781 #define dont_debug_queries
1782
1783 #define dont_debug_ansiseq
1784 #define dont_debug_expect
1785
1786 #ifdef debug_expect
1787 #warning extra debug read will provoke hanging
1788 # define debug_queries
1789 #define trace_expect(params) printf ("[%lu] ", gettime ()); printf params
1790 static
1791 unsigned long
gettime()1792 gettime ()
1793 {
1794 struct timeval now;
1795 gettimeofday (& now, 0);
1796 return ((long) now.tv_sec) * 1000000 + now.tv_usec;
1797 }
1798 #else
1799 #define trace_expect(params)
1800 #endif
1801
1802 #ifdef debug_queries
1803 # define debug_ansiseq
1804 #define trace_query(params) printf params
1805 #else
1806 #define trace_query(params)
1807 #endif
1808
1809
1810 /* For the initial terminal report request, balance the delay time
1811 (to accept a response) so that reponses via slow remote
1812 terminal lines can be acquired but the user delay on a
1813 terminal that doesn't respond at all remains acceptable.
1814 */
1815 static int escape_delay = 0; /* wait to detect escape sequence */
1816 #ifdef vms
1817 static int default_escape_delay = 2000; /* overridden by $ESCDELAY */
1818 #else
1819 static int default_escape_delay = 450; /* overridden by $ESCDELAY */
1820 #endif
1821
1822 static
1823 void
adjust_escdelay()1824 adjust_escdelay ()
1825 {
1826 if (escape_delay == 0) {
1827 char * env = envvar ("ESCDELAY");
1828 if (env) {
1829 (void) scan_int (env, & escape_delay);
1830 }
1831
1832 /**
1833 The default escape waiting delay (or minimum, see below)
1834 is a trade-off between terminals that do not respond to
1835 certain requests and supporting slow remote connections
1836 on which extended delay is needed before timeout.
1837 */
1838 if (strisprefix ("rxvt", TERM)) {
1839 /* accept slow rxvt DA report */
1840 default_escape_delay = 25555;
1841 } else if (strisprefix ("xterm", TERM)
1842 || strisprefix ("screen", TERM)
1843 || (strisprefix ("vt", TERM) && TERM [2] >= '2' && TERM [2] < '5')
1844 ) {
1845 /* support slower remote connections */
1846 default_escape_delay = 3333;
1847 }
1848
1849 /* if unset (== 0) or too small (e.g. ESCDELAY=200), set to default */
1850 if (escape_delay < default_escape_delay) {
1851 escape_delay = default_escape_delay;
1852 }
1853 }
1854 }
1855
1856 static
1857 character
expect1byte(timeout,debug_tag)1858 expect1byte (timeout, debug_tag)
1859 FLAG timeout;
1860 char * debug_tag;
1861 {
1862 character c;
1863 FLAG awaiting = True;
1864 int delay = escape_delay;
1865 if (timeout == UNSURE) {
1866 /* timeout, but not too long, in case response is disabled */
1867 delay = 555;
1868 }
1869
1870 if (xterm_version > 0 || mintty_version > 0 || rxvt_version > 0) {
1871 /* if we know the terminal should respond, don't timeout
1872 in order to avoid garbage from late responses
1873 */
1874 }
1875
1876 trace_expect (("expect1byte [%s] (%d) escdel %d/%d\n", unnull (debug_tag), timeout, escape_delay, delay));
1877 if (char_ready_within (delay, "expect")) {
1878 awaiting = False;
1879 }
1880
1881 if (timeout && awaiting) {
1882 trace_expect (("expect1byte [%s] timeout\n", unnull (debug_tag)));
1883 #ifdef debug_expect
1884 c = read1byte ();
1885 trace_expect (("expect1byte [%s] read after timeout %02X\n", unnull (debug_tag), c));
1886 #endif
1887 return 0;
1888 }
1889
1890 if (awaiting) {
1891 status_uni ("... awaiting slow terminal response ...");
1892 }
1893
1894 if (timeout && streq (debug_tag, "acquire") && strisprefix ("rxvt", TERM)) {
1895 status_uni ("... waiting for rxvt to report device attributes ...");
1896 }
1897
1898 c = read1byte ();
1899 trace_expect (("expect1byte [%s] read %02X\n", unnull (debug_tag), c));
1900
1901 if (awaiting) {
1902 clear_status ();
1903 }
1904 return c;
1905 }
1906
1907
1908 static
1909 FLAG
receiving_response(c,debug_tag)1910 receiving_response (c, debug_tag)
1911 character c;
1912 char * debug_tag;
1913 {
1914 if (c == '\033') {
1915 return True;
1916 }
1917 #ifdef debug_queries
1918 printf ("not receiving response [%s] (esc_delay %d) (%02X)\n", unnull (debug_tag), escape_delay, c);
1919 #endif
1920 flush_keyboard ();
1921 return False;
1922 }
1923
1924 /**
1925 Check ANSI escape sequence (which has already been read)
1926 */
1927 void
ANSIseq()1928 ANSIseq ()
1929 {
1930 #ifdef debug_ansiseq
1931 printf ("ANSIseq %d:", ansi_params);
1932 { int i;
1933 for (i = 0; i < ansi_params; i ++) {
1934 printf (" %d", ansi_param [i]);
1935 }
1936 printf (" %c\n", ansi_fini);
1937 }
1938 #endif
1939
1940 if (ansi_fini == 'R') {
1941 /* could also be modified F3, though, not to arrive here */
1942 status_line ("Late screen mode response ",
1943 "- set ESCDELAY=2000 or higher for proper detection");
1944 } else if (ansi_fini == 't') {
1945 if (ansi_params == 3 && ansi_param [0] == 8) {
1946 # ifdef debug_terminal_resize
1947 printf ("received terminal size report %dx%d\n", ansi_param [1], ansi_param [2]);
1948 # endif
1949 #ifdef adjust_to_actual_termsize
1950 /* adjust to actual screen size reported by terminal */
1951 if (YMAX != ansi_param [1] - 1 - MENU || XMAX != ansi_param [2] - 1) {
1952 YMAX = ansi_param [1] - 1 - MENU;
1953 XMAX = ansi_param [2] - 1;
1954 RD ();
1955 ... see RDwin
1956 flush ();
1957 }
1958 #endif
1959 } else {
1960 error ("Unknown terminal status report");
1961 }
1962 } else if (ansi_fini == 'c') {
1963 if (strisprefix ("rxvt", TERM)) {
1964 error ("Late device attribute report - restart mined for proper screen detection");
1965 } else {
1966 error ("Unexpected (delayed) device attribute report");
1967 }
1968 } else {
1969 error ("Unknown keyboard control sequence");
1970 }
1971 }
1972
1973
1974 static
1975 FLAG
get_CPR(rowpoi,colpoi)1976 get_CPR (rowpoi, colpoi)
1977 int * rowpoi;
1978 int * colpoi;
1979 {
1980 character c;
1981 /* apply timeout to cursor position report? */
1982 static FLAG timeout_CPR = True;
1983 trace_checkwinsize (("get_CPR\n"));
1984
1985 if (cygwin_console) {
1986 trace_query (("-> skipped on cygwin console\n"));
1987 return False;
1988 }
1989
1990 adjust_escdelay ();
1991 trace_query (("query CPR\n"));
1992
1993 c = expect1byte (timeout_CPR, "CPR"); /* ESC */
1994 if (receiving_response (c, "CPR")) {
1995 int row, col;
1996 timeout_CPR = False;
1997 c = expect1byte (False, "CPR."); /* '[' */
1998 c = get_digits (& row);
1999 if (c == ';') {
2000 c = get_digits (& col);
2001 * rowpoi = row;
2002 * colpoi = col;
2003
2004 trace_checkwinsize (("get_CPR %d %d\n", row, col));
2005 trace_query (("-> %d %d\n", row, col));
2006 return True;
2007 }
2008 }
2009
2010 trace_checkwinsize (("get_CPR failed\n"));
2011 trace_query (("-> failed\n"));
2012 return False;
2013 }
2014
2015 static
2016 FLAG
get_TSZ(rowpoi,colpoi)2017 get_TSZ (rowpoi, colpoi)
2018 int * rowpoi;
2019 int * colpoi;
2020 {
2021 character c;
2022 /* apply timeout to cursor position report? */
2023 static FLAG timeout_CPR = True;
2024 trace_query (("query TSZ\n"));
2025
2026 if (! can_report_props || xterm_version == 2) {
2027 trace_query (("-> skipped\n"));
2028 return False;
2029 }
2030
2031 adjust_escdelay ();
2032
2033 c = expect1byte (timeout_CPR, "TSZ"); /* ESC */
2034 if (receiving_response (c, "TSZ")) {
2035 int dum, row, col;
2036 timeout_CPR = False;
2037 c = expect1byte (False, "TSZ."); /* '[' */
2038 c = get_digits (& dum); /* '8' */
2039 c = get_digits (& row);
2040 if (c == ';') {
2041 c = get_digits (& col);
2042 * rowpoi = row;
2043 * colpoi = col;
2044
2045 trace_query (("-> %d %d\n", row, col));
2046 return True;
2047 }
2048 }
2049
2050 trace_query (("-> failed\n"));
2051 return False;
2052 }
2053
2054 static FLAG can_get_winsize = True;
2055
2056 static
2057 void
checkwinsize()2058 checkwinsize ()
2059 {
2060 static int checking_winsize = 0;
2061 trace_checkwinsize (("checkwinsize\n"));
2062 if (can_get_winsize) {
2063 /* try to get screen size from terminal device driver (ioctl/BIOS) */
2064 getwinsize ();
2065 trace_checkwinsize (("using getwinsize: %d %d\n", YMAX + 1 + MENU, XMAX + 1));
2066 }
2067 #ifndef msdos
2068 if (checking_winsize) {
2069 /* this doesn't need to be atomic with checking_winsize = 1 below
2070 because there is no parallel or asynchronous processing here;
2071 RDwinchg is not called from catchwinch anymore;
2072 the recursive invocation can only occur from further down
2073 in the execution tree below
2074 (calling RDwinchg from readchar/__readchar)
2075 */
2076 trace_checkwinsize (("skip checking winsize\n"));
2077 return;
2078 }
2079 if (ansi_esc) {
2080 int row, col;
2081 checking_winsize = 1;
2082 /* scrolling region is cleared during screen initialization */
2083 set_cursor (2222, 2222);
2084 trace_checkwinsize (("trying ^[[6n\n"));
2085 flush_keyboard ();
2086 putescape ("\033[6n");
2087 /* could probably use putescape ("\033[18t") rightaway (see below);
2088 however, let's prefer the method used by the 'resize' tool
2089 */
2090 flush ();
2091 trace_checkwinsize (("... waiting ...\n"));
2092 if (get_CPR (& row, & col) && row > 1 && col > 1) {
2093 row = row - 1 - MENU;
2094 col = col - 1;
2095 if (YMAX != row || XMAX != col) {
2096 YMAX = row;
2097 XMAX = col;
2098 can_get_winsize = False;
2099 }
2100 trace_checkwinsize (("using ^[[6n: %d %d\n", row + 1 + MENU, col + 1));
2101 checking_winsize = 0;
2102 return;
2103 }
2104
2105 /* the cursor-beyond-limits method failed (maybe with curses...) */
2106 trace_checkwinsize (("trying ^[[18t\n"));
2107 flush_keyboard ();
2108 putescape ("\033[18t"); /* long timeout if response disabled? */
2109 flush ();
2110 trace_checkwinsize (("... waiting ...\n"));
2111 if (get_TSZ (& row, & col)) {
2112 row = row - 1 - MENU;
2113 col = col - 1;
2114 if (YMAX != row || XMAX != col) {
2115 YMAX = row;
2116 XMAX = col;
2117 can_get_winsize = False;
2118 }
2119 trace_checkwinsize (("using ^[[18t: %d %d\n", row + 1 + MENU, col + 1));
2120 checking_winsize = 0;
2121 return;
2122 }
2123 trace_checkwinsize (("terminal size detection failed\n"));
2124 }
2125 checking_winsize = 0;
2126 #endif
2127 }
2128
2129
2130 /*======================================================================*\
2131 |* Screen redraw and Window title handling *|
2132 \*======================================================================*/
2133
2134 #ifdef unix
2135
2136 #define dont_debug_window_title
2137
2138 /*
2139 * Set window headline and icon text
2140 */
2141 static
2142 void
build_window_title(ws,title,icon)2143 build_window_title (ws, title, icon)
2144 char * ws;
2145 char * title;
2146 char * icon;
2147 {
2148 if (strcontains (title_string_pattern, "%d")) {
2149 /* hpterm */
2150 int lent = strlen (title);
2151 int leni = strlen (icon);
2152 build_string (ws, title_string_pattern, lent, title, leni, icon);
2153 } else {
2154 build_string (ws, title_string_pattern, title, icon);
2155 }
2156 }
2157
2158 static char old_window_title [maxXMAX + 9];
2159 static char old_icon_title [maxXMAX + 9];
2160 static FLAG saved_old_window_title = False;
2161
2162 static
2163 void
save_old_window_title()2164 save_old_window_title ()
2165 {
2166 if (xterm_version >= 251 || mintty_version >= 10003) {
2167 putescape ("\033[22t");
2168 saved_old_window_title = True;
2169 } else if (use_window_title_query && ansi_esc && xterm_version > 2 && ! mlterm_version) {
2170 /* title query can be disabled since xterm 174 (allowWindowOps)
2171 the default is false since xterm 249 (security concerns);
2172 to mitigate this, get_terminal_report_string enforces a
2173 shorter timeout (since 2014.24)
2174 */
2175 char * t = get_terminal_report_string ("\033[21t");
2176 if (t && * t) {
2177 t ++;
2178 strcpy (old_window_title, t);
2179 saved_old_window_title = True;
2180 t = get_terminal_report_string ("\033[20t");
2181 if (t && * t) {
2182 t ++;
2183 strcpy (old_icon_title, t);
2184 }
2185 } else {
2186 use_window_title_query = False;
2187 }
2188 }
2189 }
2190
2191 static
2192 void
restore_old_window_title()2193 restore_old_window_title ()
2194 {
2195 if (saved_old_window_title) {
2196 if (xterm_version >= 251 || mintty_version >= 10003) {
2197 putescape ("\033[23t");
2198 } else if (* old_window_title) {
2199 char window_string [2 * maxXMAX + 18];
2200 build_window_title (window_string, old_window_title, old_icon_title);
2201 putescape (window_string);
2202 }
2203 }
2204 }
2205
2206 void
clear_window_title()2207 clear_window_title ()
2208 {
2209 char window_string [2 * maxXMAX + 18];
2210
2211 if (! use_window_title) {
2212 return;
2213 }
2214
2215 if (! saved_old_window_title) {
2216 save_old_window_title ();
2217 }
2218
2219 build_window_title (window_string, " ", " ");
2220 putescape (window_string);
2221
2222 restore_old_window_title ();
2223 }
2224
2225 static char title_encoding = ' ';
2226 static FLAG title_encoding_xterm_to_be_checked = False;
2227
2228 static
2229 void
check_title_encoding()2230 check_title_encoding ()
2231 {
2232 if (title_encoding == ' ') {
2233 title_encoding_xterm_to_be_checked = False;
2234 if (konsole_version > 0) {
2235 /* locale dependent */
2236 title_encoding = 'T'; /* terminal encoding */
2237 } else if (gnome_terminal_version > 0) {
2238 /* probably gnome-terminal */
2239 /* locale dependent */
2240 title_encoding = 'T'; /* terminal encoding */
2241 } else if (mintty_version > 136) {
2242 /* mintty: locale dependent since 0.3.9 */
2243 title_encoding = 'T'; /* terminal encoding */
2244 } else if (mintty_version == 136) {
2245 /* PuTTY: Windows Western */
2246 title_encoding = 'W';
2247 } else if (xterm_version >= 210) {
2248 /* title string controlled by utf8Title since xterm 210 */
2249 if (utf8_screen) {
2250 if (use_window_title_query) {
2251 title_encoding_xterm_to_be_checked = True;
2252 /* fall-back assumption */
2253 title_encoding = 'U'; /* UTF-8 */
2254 } else {
2255 title_encoding = 'A'; /* ASCII */
2256 }
2257 } else {
2258 title_encoding = 'L'; /* ISO Latin-1 */
2259 }
2260 } else if (xterm_version >= 201) {
2261 title_encoding = 'L'; /* ISO Latin-1 */
2262 } else if (xterm_version > 0 && utf8_screen) {
2263 title_encoding = 'A'; /* ASCII */
2264 } else if (rxvt_version > 0) {
2265 #ifdef incapable_X_windows
2266 /* how to detect this? */
2267 if (utf8_screen) {
2268 title_encoding = 'A'; /* workaround rxvt bug? */
2269 } else {
2270 title_encoding = 'L'; /* ISO Latin-1 */
2271 }
2272 #else
2273 title_encoding = 'T'; /* terminal encoding */
2274 #endif
2275 } else if (streq (TERM, "cygwin")) {
2276 if (term_encoding_tag == 'W') {
2277 /* assume cygwin 1.5 */
2278 # ifdef __CYGWIN__
2279 /* drop this assumption unless verified locally */
2280 if (CYGWIN_VERSION_DLL_MAJOR < 1007) {
2281 title_encoding = 'P'; /* PC-Latin-1 (CP850) */
2282 } else {
2283 title_encoding = 'T'; /* terminal encoding */
2284 }
2285 # endif
2286 } else {
2287 /* cygwin 1.5 codepage:oem or cygwin 1.7.0-49 */
2288 title_encoding = 'T'; /* terminal encoding */
2289 }
2290 } else {
2291 #ifdef msdos
2292 title_encoding = 'P'; /* PC-Latin-1 (CP850) */
2293 #endif
2294 }
2295 if (title_encoding == ' ') {
2296 if (utf8_screen) {
2297 title_encoding = 'U'; /* UTF-8 */
2298 } else {
2299 title_encoding = 'L'; /* ISO Latin-1 */
2300 }
2301 }
2302 }
2303
2304 if (title_encoding_xterm_to_be_checked) { /* => xterm_version >= 210 */
2305 /* first check if we can skip the check (ASCII-only file name) */
2306 char * filename_poi = file_name;
2307 FLAG check_xterm = False;
2308 while (* filename_poi != '\0') {
2309 if (* filename_poi ++ & 0x80) {
2310 check_xterm = True;
2311 break;
2312 }
2313 }
2314
2315 if (check_xterm) {
2316 if (xterm_version >= 252 && utf8_screen) {
2317 /* assume that it's reasonable to just set utf8Title mode */
2318 #ifdef debug_window_title
2319 printf ("setting xterm window title encoding to UTF-8");
2320 putescape ("\033[>2t");
2321 title_encoding = 'U'; /* UTF-8 */
2322 #endif
2323 } else {
2324 #ifdef debug_window_title
2325 printf ("checking xterm window title encoding");
2326 #endif
2327 /* title string controlled by utf8Title since xterm 210 */
2328 char * r = get_terminal_report_string ("\033]2;x�x\033[21t");
2329 title_encoding_xterm_to_be_checked = False;
2330 if (! r || ! r [0]) {
2331 /* no response, resource 'allowWindowOps' disabled
2332 or non-xterm */
2333 use_window_title_query = False;
2334 title_encoding = 'A'; /* ASCII */
2335 } else if (r [2] == '�') {
2336 /* only with utf8Title: false */
2337 title_encoding = 'L'; /* ISO Latin-1 */
2338 } else {
2339 /* only with utf8Title: true */
2340 title_encoding = 'U'; /* UTF-8 */
2341 }
2342 #ifdef debug_window_title
2343 printf ("window title:");
2344 while (* r) {
2345 printf (" %02X%c", (character) * r, * r);
2346 r ++;
2347 }
2348 printf ("\n");
2349 #endif
2350 }
2351 }
2352 }
2353 }
2354
2355 void
RD_window_title()2356 RD_window_title ()
2357 {
2358 char window_string [2 * (maxFILENAMElen + maxXMAX) + 18];
2359 char filename_ok [maxFILENAMElen];
2360 char * filename_dispoi;
2361 char * filename_poi;
2362 char * save_term_encoding = NIL_PTR;
2363
2364 if (! use_window_title) {
2365 return;
2366 }
2367
2368 if (! saved_old_window_title) {
2369 save_old_window_title ();
2370 }
2371
2372 check_title_encoding ();
2373
2374 if (title_encoding == 'P' || title_encoding == 'W') {
2375 save_term_encoding = get_term_encoding ();
2376 if (title_encoding == 'P') {
2377 (void) set_term_encoding ("CP850", 'P');
2378 } else {
2379 (void) set_term_encoding ("CP1252", 'W');
2380 }
2381 }
2382
2383 filename_poi = file_name;
2384 filename_dispoi = filename_ok;
2385 while (* filename_poi != '\0') {
2386 unsigned long c = unicodevalue (filename_poi);
2387 if (no_unichar (c) || c < (character) ' ' || (c >= 0x80 && c < 0xA0)) {
2388 * filename_dispoi ++ = '?';
2389 } else if (title_encoding == 'L') {
2390 if (c >= 0x100) {
2391 * filename_dispoi ++ = '?';
2392 } else {
2393 * filename_dispoi ++ = (character) c;
2394 }
2395 } else if (title_encoding == 'A' && c >= 0x80) {
2396 * filename_dispoi ++ = '?';
2397 } else if (title_encoding == 'U') {
2398 #ifdef incapable_X_windows
2399 /* how to detect this? */
2400 if (c >= 0x100) {
2401 /* only a few selected non-Latin-1 chars are displayed */
2402 * filename_dispoi ++ = '?';
2403 } else {
2404 filename_dispoi += utfencode (c, filename_dispoi);
2405 }
2406 #else
2407 filename_dispoi += utfencode (c, filename_dispoi);
2408 #endif
2409 } else { /* assume title encoding is same as screen encoding */
2410 if (utf8_screen) {
2411 filename_dispoi += utfencode (c, filename_dispoi);
2412 } else if (cjk_term || mapped_term) {
2413 unsigned long tc = mappedtermchar (c);
2414 if (no_char (tc)) {
2415 * filename_dispoi ++ = '?';
2416 } else if (cjk_term) {
2417 filename_dispoi += cjkencode_char (True, mappedtermchar (c), filename_dispoi);
2418 } else {
2419 * filename_dispoi ++ = tc;
2420 }
2421 } else { /* also fall-back for ASCII chars in all cases */
2422 * filename_dispoi ++ = (character) c;
2423 }
2424 }
2425 advance_char (& filename_poi);
2426 }
2427 * filename_dispoi = '\0';
2428
2429 if (save_term_encoding != NIL_PTR) {
2430 (void) set_term_encoding (save_term_encoding, ' ');
2431 }
2432
2433 #ifdef __CYGWIN__
2434 #define mined_name " - MinEd"
2435 #else
2436 #define mined_name ""
2437 #endif
2438
2439 if (loading == False) {
2440 char title_text [maxFILENAMElen + maxXMAX];
2441 char icon_text [maxFILENAMElen + maxXMAX];
2442 build_string (title_text, "%s%s%s",
2443 file_name [0] == '\0' ? "[no file]" : filename_ok,
2444 modified ? mined_modf: "",
2445 mined_name);
2446 build_string (icon_text, "%s%s",
2447 modified ? mined_modf: "",
2448 file_name [0] == '\0' ? "[no file]" : getbasename (filename_ok));
2449 build_window_title (window_string, title_text, icon_text);
2450 putescape (window_string);
2451 }
2452 }
2453
2454 #endif
2455
2456
2457 /*
2458 * Redraw the screen
2459 */
2460 static
2461 void
RD_nobot()2462 RD_nobot ()
2463 {
2464 reverse_off ();
2465 clearscreen ();
2466
2467 #ifdef use_logo
2468 if (xterm_version > 0 || mintty_version > 0 || decterm_version > 0) {
2469 /* double line logo - would waste 2 lines */
2470 /* show accent conditionally, see splash_logo () */
2471 set_cursor (XMAX - 10, 1);
2472 putescape ("\033#3ḿ MinEd");
2473 set_cursor (XMAX - 10, 2);
2474 putescape ("\033#4ḿ MinEd");
2475 }
2476 #endif
2477
2478 /* display page */
2479 display (0, top_line, last_y, y);
2480
2481 /* redraw scroll bar */
2482 if (disp_scrollbar && ! winchg) {
2483 (void) display_scrollbar (False);
2484 }
2485
2486 /* clear/redraw last line */
2487 set_cursor (0, YMAX);
2488 clear_lastline ();
2489 move_address (cur_text, find_y_w_o_RD (cur_line));
2490
2491 #ifdef unix
2492 RD_window_title ();
2493 #endif
2494 }
2495
2496 void
RD()2497 RD ()
2498 {
2499 RD_nobot ();
2500 if (stat_visible) {
2501 rd_bottom_line ();
2502 }
2503 }
2504
2505 void
RD_y(y_pos)2506 RD_y (y_pos)
2507 int y_pos;
2508 {
2509 reverse_off ();
2510 clearscreen ();
2511
2512 /* display page */
2513 display (0, top_line, last_y, y_pos);
2514
2515 /* clear/redraw last line */
2516 set_cursor (0, YMAX);
2517 clear_lastline ();
2518 if (stat_visible) {
2519 rd_bottom_line ();
2520 }
2521 }
2522
2523 /*
2524 * Adjust current window size after WINCH signal
2525 */
2526 static
2527 void
RDwin_menu(rd_menu,after_winchg)2528 RDwin_menu (rd_menu, after_winchg)
2529 FLAG rd_menu;
2530 FLAG after_winchg;
2531 {
2532 screen_buffer (True);
2533
2534 #ifdef debug_terminal_resize
2535 printf ("RDwin %dx%d", YMAX + 1 + MENU, XMAX + 1);
2536 #endif
2537 winchg = False;
2538 checkwinsize ();
2539 #ifdef debug_terminal_resize
2540 printf (" -> %dx%d\n", YMAX + 1 + MENU, XMAX + 1);
2541 #endif
2542
2543 #ifdef adjust_to_actual_termsize /* incomplete & obsolete */
2544 flush_keyboard ();
2545 putescape ("\033[18t"); /* long timeout if response disabled? */
2546 flush ();
2547 if (char_ready_within (...)) { /* c = expect1byte (True, NIL_PTR); if (receiving_response (c, NIL_PTR)) { */
2548 c = readcharacter ();...
2549 if (command (c) == ANSIseq) {
2550 ANSIseq ();
2551 ... but without RD which is actually done here ...
2552 in both cases, reset the variables below, however ...
2553 }
2554 }
2555 #endif
2556
2557 if (loading == False) {
2558 LINE * current_line = cur_line;
2559 reset (top_line, y);
2560 /* move_y (find_y_w_o_RD (current_line)); */
2561 move_address (cur_text, find_y_w_o_RD (current_line));
2562
2563 RD_nobot ();
2564 if (MENU && ! winchg) {
2565 displaymenuline (True);
2566 if (rd_menu) {
2567 redrawmenu ();
2568 }
2569 }
2570 }
2571
2572 display_flush ();
2573
2574 if (after_winchg && ! winchg) {
2575 (void) display_scrollbar (True);
2576 }
2577
2578 set_cursor_xy ();
2579
2580 if (stat_visible && ! winchg) {
2581 rd_bottom_line ();
2582 /* could call redraw_prompt () instead, but:
2583 - menu header missing
2584 - with empty text: line marker not restored?
2585 */
2586 }
2587
2588 if (winchg) {
2589 trace_checkwinsize (("recursive RDwin_menu after winchg\n"));
2590 RDwin_menu (rd_menu, after_winchg);
2591 }
2592
2593 flush ();
2594 }
2595
2596 void
RDwin()2597 RDwin ()
2598 {
2599 RDwin_menu (True, False);
2600 }
2601
2602 void
RDcenter()2603 RDcenter ()
2604 {
2605 LINE * l = cur_line;
2606 int targy = YMAX / 2 - 1;
2607 int li = 0;
2608 while (l->prev != header && li < targy) {
2609 l = l->prev;
2610 li ++;
2611 }
2612 reset (l, li);
2613
2614 RDwin ();
2615 }
2616
2617 void
RDwinchg()2618 RDwinchg ()
2619 {
2620 trace_checkwinsize (("RDwinchg\n"));
2621 if (loading) {
2622 #ifdef debug_terminal_resize
2623 printf ("RDwin (skip/loading) %dx%d\n", YMAX + 1 + MENU, XMAX + 1);
2624 #endif
2625 /* cannot use text buffer for refresh */
2626 return;
2627 }
2628 RDwin_menu (True, True);
2629 }
2630
2631 void
RDwin_nomenu()2632 RDwin_nomenu ()
2633 {
2634 RDwin_menu (False, False);
2635 }
2636
2637
2638 /*======================================================================*\
2639 |* Terminal mode debugging *|
2640 \*======================================================================*/
2641
2642 #define dont_debug_encoding
2643
2644
2645 #define dont_debug_test_screen_width
2646
2647 #define dont_debug_screenmode
2648 #define dont_debug_width_data_version
2649
2650 #define dont_debug_graphics
2651
2652
2653 #ifdef debug_test_screen_width
2654 # define debug_encoding
2655 #endif
2656
2657
2658 #ifdef debug_encoding
2659
2660 static
2661 FLAG
do_set_term_encoding(function,line,charmap,tag)2662 do_set_term_encoding (function, line, charmap, tag)
2663 char * function;
2664 unsigned int line;
2665 char * charmap;
2666 char tag;
2667 {
2668 FLAG ret = set_term_encoding (charmap, tag);
2669 printf ("set_term_encoding [%s:%d] %s '%c' -> %d %s\n", function, line, charmap, tag, ret, get_term_encoding ());
2670 return ret;
2671 }
2672
2673 #define set_term_encoding(charmap, tag) do_set_term_encoding (__FUNCTION__, __LINE__, charmap, tag)
2674
2675 #define trace_encoding(tag) \
2676 printf ("[%s] TERM <%s> '%c' utf8 %d cjk %d map %d comb/bidi %d/%d\n TEXT <%s> '%c' (auto %d) utf8 %d utf16 %d cjk %d map %d\n", \
2677 tag, \
2678 get_term_encoding (), term_encoding_tag, utf8_screen, cjk_term, mapped_term, combining_screen, bidi_screen, \
2679 get_text_encoding (), text_encoding_tag, auto_detect, utf8_text, utf16_file, cjk_text, mapped_text)
2680
2681 #else
2682
2683 #define trace_encoding(tag)
2684
2685 #endif
2686
2687
2688 #ifdef debug_width_data_version
2689
2690 #define trace_width_data_version(tag) \
2691 printf ("[%s] width_data_version %d (CJK %d) nonbmp %X combining_data_version %d (Jamo %d)\n", \
2692 tag, \
2693 width_data_version, cjk_width_data_version, nonbmp_width_data, \
2694 combining_data_version, hangul_jamo_extended)
2695
2696 #else
2697
2698 #define trace_width_data_version(tag)
2699
2700 #endif
2701
2702
2703 /*======================================================================*\
2704 |* TTY setup *|
2705 \*======================================================================*/
2706
2707 /* workaround for cygwin console delaying some escape sequences */
2708 #ifdef __CYGWIN__
2709 static
2710 void
install_console_pipe()2711 install_console_pipe ()
2712 {
2713 if ((streq ("cygwin", TERM) && ! screen_version && ! tmux_version)) {
2714 struct utsname uts;
2715 int pfds [2];
2716 int pid;
2717 int cygwin_version_major = CYGWIN_VERSION_DLL_MAJOR;
2718 int cygwin_version_minor = CYGWIN_VERSION_DLL_MINOR;
2719
2720 if (uname (& uts) == 0) {
2721 int mil, maj, min;
2722 int ret = sscanf (uts.release, "%d.%d.%d", & mil, & maj, & min);
2723 if (ret == 3) {
2724 cygwin_version_major = mil * 1000 + maj;
2725 cygwin_version_minor = min;
2726 }
2727 }
2728
2729 if (cygwin_version_major < 1007 || cygwin_version_minor < 10) {
2730 /* no bug yet */
2731 } else if (pipe (pfds) < 0) {
2732 /* don't fork, accept deficiencies */
2733 } else {
2734 pid = fork ();
2735 if (pid < 0) { /* fork error */
2736 /* ignore, accept deficiencies */
2737 } else if (pid == 0) { /* child */
2738 int n;
2739 (void) close (pfds [0]);
2740 sleep (1);
2741 /* copy input_fd to pipe */
2742 do {
2743 character c;
2744 n = read (input_fd, & c, 1);
2745 if (n > 0) {
2746 n = write (pfds [1], & c, 1);
2747 }
2748 } while (n >= 0);
2749 _exit (127);
2750 } else { /* parent */
2751 (void) close (pfds [1]);
2752 /* redirect input from pipe */
2753 input_fd = pfds [0];
2754 /* proceed with editing */
2755 }
2756 }
2757 }
2758 }
2759 #else
2760 #define install_console_pipe()
2761 #endif
2762
2763
2764 /*======================================================================*\
2765 |* Terminal setup *|
2766 \*======================================================================*/
2767
2768 /**
2769 Request the terminal (VT100-like, xterm and derivatives) to send
2770 Device Attributes report containing terminal type and version.
2771 */
2772 static
2773 void
acquire_device_attributes(again)2774 acquire_device_attributes (again)
2775 FLAG again;
2776 {
2777 #ifndef msdos
2778 character c;
2779
2780 trace_query (("query ^[[>c\n"));
2781
2782 terminal_type = -1;
2783 terminal_version = 0;
2784
2785 flush_keyboard ();
2786 putescape ("\033[>c");
2787 flush ();
2788
2789 adjust_escdelay ();
2790
2791 c = expect1byte (True, "acquire"); /* ESC */
2792 if (receiving_response (c, "acquire")) {
2793 c = expect1byte (False, "acquire."); /* '[' */
2794 c = expect1byte (False, "acquire..");
2795 /* '>' (secondary DA) or '?' (CJK terminals) */
2796 c = get_digits (& terminal_type);
2797 if (c == ';') {
2798 c = get_digits (& terminal_version);
2799 }
2800 while (c == '.') {
2801 int dummy;
2802 /* mrxvt sends sub-version 0.4.1 */
2803 c = get_digits (& dummy);
2804 terminal_version = terminal_version * 100 + dummy;
2805 }
2806 while (c == ';') {
2807 int dummy;
2808 c = get_digits (& dummy);
2809 }
2810 }
2811
2812 trace_query (("-> %d %d\n", terminal_type, terminal_version));
2813 #endif
2814 }
2815
2816 static
2817 void
acquire_primary_device_attributes()2818 acquire_primary_device_attributes ()
2819 {
2820 #ifndef msdos
2821 character c;
2822
2823 trace_query (("query ^[[c\n"));
2824
2825 flush_keyboard ();
2826 putescape ("\033[c");
2827 flush ();
2828
2829 adjust_escdelay ();
2830
2831 c = expect1byte (True, "acquirep"); /* ESC */
2832 if (receiving_response (c, "acquirep")) {
2833 c = expect1byte (False, "acquirep."); /* '[' */
2834 c = expect1byte (False, "acquirep.."); /* '?' */
2835 dec_features = 0;
2836 do {
2837 int feature;
2838 c = get_digits (& feature);
2839 trace_query (("terminal feature %d\n", feature));
2840 dec_features |= 1 << feature;
2841 } while (c == ';');
2842 trace_query (("terminal features %08lX\n", dec_features));
2843 }
2844 #endif
2845 }
2846
2847
2848 /**
2849 Swallow keyboard input.
2850 For use before enquiring all kinds of terminal reports.
2851 */
2852 static
2853 void
flush_keyboard()2854 flush_keyboard ()
2855 {
2856 /* swallow either
2857 - key typed in by user while requesting terminal
2858 - delayed response to a previous request
2859 which could not be handled in time
2860 */
2861 #ifndef vms_slow_lookahead
2862 while (char_ready_within (30, "swallow")) {
2863 #ifdef debug_expect
2864 unsigned long swallowed = _readchar_nokeymap ();
2865 printf ("swallowed %04lX\n", swallowed);
2866 (void) swallowed;
2867 #else
2868 (void) _readchar_nokeymap ();
2869 #endif
2870 }
2871 #endif
2872 }
2873
2874 /**
2875 Retrieve terminal response to various enquiry escape sequences.
2876 Used for:
2877 color report
2878 window title report (not with newer xterm/mintty)
2879 glyph availability report (with newer mintty)
2880 */
2881 static
2882 char *
get_terminal_report_string(s)2883 get_terminal_report_string (s)
2884 char * s;
2885 {
2886 #ifndef msdos
2887 character c;
2888 static char sbuf [maxMSGlen];
2889 char * spoi = sbuf;
2890
2891 trace_query (("query [%d] ^[%s\n", escape_delay, s + 1));
2892
2893 flush_keyboard ();
2894 putescape (s);
2895 flush ();
2896
2897 /* UNSURE: enforce shorter timeout to mitigate delay
2898 if xterm resource allowWindowOps is false
2899 */
2900 c = expect1byte (UNSURE, "report"); /* ESC */
2901 if (receiving_response (c, s + 1)) {
2902 c = expect1byte (False, "report."); /* ']' */
2903 while ((c = expect1byte (False, "report..")) != '\033' && c != '\007' && c != 0x9C) {
2904 if (spoi < & sbuf [maxMSGlen - 1]) {
2905 * spoi ++ = c;
2906 }
2907 }
2908 if (c == '\033' && rxvt_version < 300) {
2909 /* rxvt-unicode fails to send the final \ */
2910 c = expect1byte (False, "report..."); /* '\\' */
2911 }
2912 }
2913 * spoi = '\0';
2914
2915 if (debug_mined) {
2916 debuglog ("report", s + 1, sbuf);
2917 }
2918 trace_query (("-> ^[%s\n", sbuf));
2919 return sbuf;
2920 #else
2921 return "";
2922 #endif
2923 }
2924
2925 static
2926 void
get_width_report(s,wpoi)2927 get_width_report (s, wpoi)
2928 char * s;
2929 int * wpoi;
2930 {
2931 int row, col;
2932 if (get_CPR (& row, & col)) {
2933 #ifdef debug_test_screen_width
2934 printf ("width <%s> -> %d\n", s, col - 1);
2935 #endif
2936 * wpoi = col - 1;
2937 }
2938 }
2939
2940 static
2941 int
test_screen_width(s)2942 test_screen_width (s)
2943 char * s;
2944 {
2945 int col = -1;
2946
2947 #ifndef msdos
2948
2949 if (! ansi_esc) {
2950 return -1;
2951 }
2952
2953 /* if (xterm_version >= 201) {
2954 suppress visible effect by setting invisible character mode
2955 - this would need intensive regression testing, so leave it
2956 }
2957 */
2958 putescape ("\r");
2959 flush_keyboard ();
2960 debuglog ("6n", "", screen_version ? "s" : "");
2961 putstring (s); /* don't use putescape here for 'screen' 4.0 */
2962 putescape ("\033[6n"); /* maybe termcap u7 but not really defined */
2963 putescape ("\r");
2964 clear_eol (); /* reduce visible effect */
2965 flush ();
2966 debuglog ("6n", "", "flush");
2967
2968 get_width_report (s, & col);
2969 debuglog ("CPR", "", "");
2970 #endif
2971
2972 return col;
2973 }
2974
2975 typedef struct {
2976 char * test;
2977 int width;
2978 } screen_width;
2979
2980 static screen_width utf8_widths [] = {
2981 /* detecting combining mode: */
2982 {"a̡"},
2983
2984 /* detecting width data version: */
2985 {"《》〚〛⦅⦆"},
2986 {"︐"},
2987 {"ꥠ"},
2988 {""}, /* non-BMP characters cannot reliably be used for detection */
2989
2990 /* detecting combining_data_version: */
2991 {"a"},
2992 {"aͣ"},
2993 {".͐.឴."},
2994 {".͘.͙"},
2995 {".᷄.᷅"},
2996 {".҇.᷌"}, /* U510 */
2997 {".ࠖ.ऀ"}, /* U520 */
2998 {".ٟ.ऺ"}, /* U600 */
2999 {"..ꙴ"}, /* U620 */
3000 {".."}, /* U630 */
3001 {".᪰.ᷮ"}, /* U700 */
3002 {"ᄀힰᄀퟋ"}, /* Hangul Jamo Extended-B */
3003
3004 /* detecting xterm -cjk_width: */
3005 {"‘’“”…―"},
3006 #ifdef single_width_check
3007 {"…―…"},
3008 #endif
3009
3010 /* detecting non-BMP width properties: */
3011 {"aaa"},
3012 {""},
3013 /* detecting unassigned character width properties: */
3014 {"ㄯ"},
3015
3016 /* detecting Yijing Hexagram widths and printable bidi markers: */
3017 {"䷀䷀"},
3018 #ifdef poderosa_detect_string
3019 {"¡×"},
3020 #endif
3021
3022 #ifdef oldmlterm_wideboldborderbug_workaround
3023 {"╭"},
3024 #endif
3025 };
3026
3027 static screen_width cjk_widths [] = {
3028 {"�0�2"},
3029 {"����ꥦ�ޡ"},
3030 {"����"},
3031 {"���x"},
3032 {"��"},
3033 {"��"},
3034 };
3035
3036 static
3037 int
get_screen_width(s,sw,len)3038 get_screen_width (s, sw, len)
3039 char * s;
3040 screen_width * sw;
3041 int len;
3042 {
3043 int i;
3044 for (i = 0; i < len; i ++) {
3045 /* if screen width has been acquired for this test string, return */
3046 if (streq (s, sw [i].test) && sw [i].width) {
3047 #ifdef debug_test_screen_width
3048 printf ("get <%s> -> %d\n", s, sw [i].width);
3049 #endif
3050 return sw [i].width;
3051 }
3052 }
3053 return test_screen_width (s);
3054 }
3055
3056 static
3057 void
acquire_screen_widths(sw,len)3058 acquire_screen_widths (sw, len)
3059 screen_width * sw;
3060 int len;
3061 {
3062 #ifdef vms
3063 /* VMS cannot buffer more than 80 characters,
3064 so it would hang on trying to read the responses...
3065 Even the response read-ahead trick below doesn't seem to work.
3066 */
3067 #else
3068 #ifndef msdos
3069 int i;
3070 int k = 0;
3071
3072 /*
3073 if (xterm_version >= 201) {
3074 suppress visible effect by setting invisible character mode
3075 (invisible mode double width bug fixed in xterm 201)
3076 - this would need intensive regression testing, so leave it
3077 }
3078 */
3079 #ifdef debug_test_screen_width
3080 printf ("acquire_screen_widths\n");
3081 #endif
3082 debuglog ("6n", "**", screen_version ? "s" : "");
3083 flush_keyboard ();
3084 putescape ("\r");
3085 for (i = 0; i < len; i ++) {
3086 /*debuglog ("6n", "*", screen_version ? "s" : "");*/
3087 putstring (sw [i].test); /* don't use putescape here for 'screen' 4.0 */
3088 putescape ("\033[6n"); /* maybe termcap u7 but not really defined */
3089 putescape ("\r");
3090 #ifdef vms
3091 clear_eol ();
3092 flush ();
3093 while (k <= i && char_ready_within (35, NIL_PTR)) {
3094 get_width_report (sw [k].test, & sw [k].width);
3095 /*debuglog ("CPR", "!", "");*/
3096 k ++;
3097 }
3098 #endif
3099 }
3100 #ifndef vms
3101 clear_eol (); /* reduce visible effect */
3102 flush ();
3103 #endif
3104 debuglog ("6n", "**", "flush");
3105
3106 for (; k < len; k ++) {
3107 get_width_report (sw [k].test, & sw [k].width);
3108 /*debuglog ("CPR", "*", "");*/
3109 }
3110 debuglog ("CPR", "**", "");
3111 #endif
3112 #endif
3113 }
3114
3115 static
3116 void
check_cjk_width()3117 check_cjk_width ()
3118 {
3119 static FLAG init = True;
3120
3121 cjk_width_data_version = 0;
3122
3123 if (utf8_screen) {
3124 if (width_data_version >= U320) {
3125 int swidth;
3126 if (init) {
3127 swidth = get_screen_width ("‘’“”…―", utf8_widths, arrlen (utf8_widths));
3128 init = False;
3129 } else {
3130 swidth = test_screen_width ("‘’“”…―");
3131 }
3132 if (swidth > 8) {
3133 /* xterm -cjk_width (since xterm 168) */
3134 #ifdef consider_wide_block_slices
3135 /* not useful since block chars used for
3136 fine scrollbar have ambiguous width
3137 */
3138 if (! explicit_scrollbar_style) {
3139 fine_scrollbar = False;
3140 }
3141 #else
3142 fine_scrollbar = False;
3143 #endif
3144 if (! explicit_border_style) {
3145 use_stylish_menu_selection = False;
3146 }
3147 if (swidth & 1) {
3148 /* soft hyphen is narrow, Unicode 4.0 */
3149 cjk_width_data_version = U400;
3150 /* ?
3151 if (width_data_version < U400) {
3152 width_data_version = U400;
3153 }
3154 */
3155 } else {
3156 /* soft hyphen is wide (ambiguous), Unicode 3.0/3.2 */
3157 cjk_width_data_version = U320beta;
3158 }
3159 trace_width_data_version ("cjk");
3160 }
3161 #ifdef single_width_check
3162 swidth = get_screen_width ("…―…", utf8_widths, arrlen (utf8_widths));
3163 if ((swidth & 1) == 0) {
3164 /* ― is wide */
3165 }
3166 if (swidth >= 5) {
3167 /* … is wide */
3168 }
3169 #endif
3170 }
3171 }
3172 }
3173
3174 static
3175 int
isglyph_code(glyph)3176 isglyph_code (glyph)
3177 char * glyph;
3178 {
3179 char * match;
3180 if (! glyphs || ! * glyphs) {
3181 return 0; /* no info -> reject */
3182 }
3183 match = strcontains (glyphs, glyph);
3184 if (match) {
3185 char * post = match + strlen (glyph);
3186 if (* (match - 1) == ';'
3187 && (* post < '0' || * post > '9')) {
3188 return 1;
3189 }
3190 }
3191 return 0;
3192 }
3193
3194 int
isglyph_uni(u)3195 isglyph_uni (u)
3196 unsigned long u;
3197 {
3198 if (u == 0) {
3199 /* detect whether glyph info available */
3200 return glyphs != NIL_PTR;
3201 }
3202
3203 if (u < 255) {
3204 return 1;
3205 } else {
3206 char glyphcode [20];
3207 build_string (glyphcode, "%ld", u);
3208 return isglyph_code (glyphcode);
3209 }
3210 }
3211
3212 static
3213 int
isglyph_utf(c)3214 isglyph_utf (c)
3215 char * c;
3216 {
3217 if (! c || ! * c) {
3218 return 0;
3219 } else {
3220 return isglyph_uni (utf8value (c));
3221 }
3222 }
3223
3224 /**
3225 Request terminal type and version from terminal.
3226 */
3227 static
3228 void
detect_terminal_type()3229 detect_terminal_type ()
3230 {
3231 trace_query (("detect_terminal_type @ %s\n", TERM));
3232 if ((strisprefix ("xterm", TERM)
3233 || strisprefix ("rxvt", TERM)
3234 || strisprefix ("gnome", TERM)
3235 || strisprefix ("konsole", TERM)
3236 || strisprefix ("screen", TERM)
3237 || (strisprefix ("vt", TERM)
3238 && ! streq ("vt52", TERM)
3239 && ! strisprefix ("vt50", TERM)
3240 )
3241 )
3242 #ifdef indulge_mlterm
3243 /* mlterm does not respond to secondary device attribute request;
3244 to avoid the timeout, we could suppress the request but only
3245 if we detected mlterm by its joining property first;
3246 also, be sure about possible other joining terminals...
3247 (note: mintty is only "half-joining" - it joins the glyphs
3248 but not the two character cells, and leaves a dummy space)
3249 - OBSOLETE in newer mlterm, 3.1.2 at least
3250 */
3251 && ! joining_screen
3252 #endif
3253 ) {
3254 acquire_device_attributes (False);
3255 if (terminal_type == 'S') { /* screen */
3256 screen_version = terminal_version / 100;
3257 } else if (strisprefix ("screen", TERM)) {
3258 screen_version = 1;
3259 }
3260 if (screen_version > 0) {
3261 #ifdef __CYGWIN__
3262 if (strcontains (envstr ("STY"), ".cons")) {
3263 /* suppress host terminal attribute enquiry
3264 (pass-through) in screen in cygwin console;
3265 workaround for not capturing the response then
3266 (which would later be inserted as garbage)
3267 */
3268 terminal_type = 'C';
3269 terminal_version = CYGWIN_VERSION_DLL_MAJOR * 100 + CYGWIN_VERSION_DLL_MINOR;
3270 } else {
3271 acquire_device_attributes (True);
3272 }
3273 #else
3274 /* check host terminal;
3275 with screen_version set, terminal requests will
3276 apply the pass-through escape sequence of 'screen'
3277 (for host terminal detection here
3278 and width auto-detection below)
3279 */
3280 acquire_device_attributes (True);
3281 #endif
3282 }
3283
3284 #ifdef test_DEC_features
3285 if (strisprefix ("vt", TERM)) {
3286 decterm_version = terminal_version;
3287 }
3288 #endif
3289 if (terminal_type == 0 && terminal_version == 95 && getenv ("TMUX")) {
3290 tmux_version = 1;
3291 } else if (terminal_type == 'T') { /* tmux 2.0 */
3292 tmux_version = 2;
3293 } else if (terminal_type == 0 && terminal_version == 115) {
3294 konsole_version = terminal_version;
3295 set_fkeymap ("xterm");
3296 } else if ((terminal_type | 1) == 1 && konsole_version <= 0) {
3297 if (terminal_version >= 1115) {
3298 /* probably gnome-terminal */
3299 gnome_terminal_version = terminal_version;
3300 } else if (terminal_version == 136) {
3301 /* MinTTY 0.3, PuTTY */
3302 mintty_version = terminal_version;
3303 } else if (terminal_version == 115) {
3304 /* KDE konsole */
3305 konsole_version = terminal_version;
3306 } else if (terminal_version == 10) { /* VT220 */
3307 decterm_version = 220;
3308 } else if (terminal_version == 2) { /* Openwin xterm */
3309 xterm_version = terminal_version;
3310 } else if (terminal_version <= 20) { /* ? */
3311 decterm_version = terminal_version;
3312 #ifdef test_DEC_locator_on_xterm
3313 } else if (strisprefix ("vt", TERM)) {
3314 decterm_version = terminal_version;
3315 #endif
3316 } else {
3317 xterm_version = terminal_version;
3318 }
3319 set_fkeymap ("xterm");
3320 } else if (terminal_type == 'M') { /* mintty */
3321 mintty_version = terminal_version;
3322 set_fkeymap ("xterm");
3323 } else if (terminal_type == 'R') { /* old rxvt */
3324 rxvt_version = terminal_version / 100;
3325 TERM = "rxvt";
3326 } else if (terminal_type == 'U') { /* rxvt-unicode */
3327 rxvt_version = terminal_version * 10;
3328 TERM = "rxvt";
3329 } else if (terminal_type == 6) { /* Haiku Terminal */
3330 fine_scrollbar = False;
3331 use_stylish_menu_selection = False;
3332 } else if (terminal_type == 2) { /* VT240 */
3333 decterm_version = 240;
3334 } else if (terminal_type == 18) { /* VT330 */
3335 decterm_version = 330;
3336 } else if (terminal_type == 19) { /* VT340 */
3337 decterm_version = 340;
3338 } else if (terminal_type == 24) { /* VT320 */
3339 decterm_version = 320;
3340 } else if (terminal_type == 28) { /* DECterm window */
3341 decterm_version = 1;
3342 } else if (terminal_type == 41) { /* VT420 */
3343 decterm_version = 420;
3344 } else if (terminal_type == 61) { /* VT510 */
3345 decterm_version = 510;
3346 } else if (terminal_type == 64) { /* VT520 */
3347 decterm_version = 520;
3348 } else if (terminal_type == 65) { /* VT525 */
3349 decterm_version = 525;
3350 } else if (terminal_type < 64) { /* ? */
3351 decterm_version = terminal_type;
3352 }
3353 if (decterm_version > 1 && terminal_version >= 280) {
3354 xterm_version = terminal_version;
3355 }
3356 }
3357
3358 /* try to detect KDE konsole */
3359 if (! konsole_version &&
3360 (strisprefix ("konsole", TERM)
3361 #ifdef heuristic_konsole_detection
3362 || envvar ("KONSOLE_DCOP") || envvar ("KONSOLE_DBUS_SESSION")
3363 #endif
3364 )
3365 ) {
3366 konsole_version = 1;
3367 /*xterm_version = 0;*/
3368 }
3369
3370 /* check whether xterm supports SIXEL graphics */
3371 if (xterm_version >= 298) {
3372 acquire_primary_device_attributes ();
3373 }
3374
3375 /* try to detect gnome-terminal */
3376 if (strisprefix ("gnome-terminal", envstr ("COLORTERM")) && gnome_terminal_version <= 0) {
3377 gnome_terminal_version = 1;
3378 }
3379
3380 /* try to identify mlterm */
3381 if (bidi_screen && ! mintty_version) { /* probably mlterm */
3382 mlterm_version = 1;
3383 } else if (strisprefix ("mlterm", TERM)) {
3384 mlterm_version = 1;
3385 } else if (streq ("xterm", TERM) && envvar ("MLTERM")) {
3386 mlterm_version = 1;
3387 }
3388 if (mlterm_version) {
3389 char * mlterm= envvar ("MLTERM");
3390 int v1, v2, v3;
3391 int ret = sscanf (mlterm, "%d.%d.%d", & v1, & v2, & v3);
3392 if (ret == 3) {
3393 mlterm_version = 100 * v1 + 10 * v2 + v3;
3394 }
3395 }
3396 }
3397
3398 static
3399 void
check_glyphs()3400 check_glyphs ()
3401 {
3402 if (mintty_version >= 909) {
3403 #ifdef vms
3404 /* real VMS limits the glyph detection response
3405 by its 80 characters input buffer,
3406 so check only the most essential markers:
3407 ╭9581;▁9601;▶9654;►9658;⏎9166;‣8227;⇾8702;→8594
3408 */
3409 glyphs = get_terminal_report_string ("\033]7771;?;9581;9601;9654;9658;9166;8227;8702;8594");
3410 #else
3411 glyphs = get_terminal_report_string ("\033]7771;?;9472;9581;9484;9601;9613;9654;9658;10003;8231;8702;8594;8227;9166;8629;8626;10007;8623;8226;9755;9758;8228;8229;8230;9655;9656;9657;9659;9664;9665;9666;9667;9668;9669;9670;9830;9672;11032;11033;11030;11031;9478;9479;8364;699;769;8472");
3412 #endif
3413 if (glyphs) {
3414 glyphs = strchr (glyphs, '!');
3415 if (glyphs) {
3416 glyphs = dupstr (glyphs);
3417 /* update ḿ */
3418 /* used to call splash_logo () here */
3419 }
3420 }
3421 }
3422 }
3423
3424
3425 #define use_splash_logo
3426 #define use_sixel_splash
3427
3428 #ifdef use_sixel_splash
3429 static char * sixelsplash = "P0;0;8q\"1;1\
3430 #0;2;0;0;0#1;2;0;18;0#2;2;0;32;0#3;2;0;45;0#4;2;0;57;0#5;2;0;69;0#6;2;0;80;0\
3431 #0!105@$\
3432 #0!105A$\
3433 #0!105C$\
3434 #0!105G$\
3435 #0!105O$\
3436 #0!105_$\
3437 -\
3438 #0!105@$\
3439 #0!105A$\
3440 #0!105C$\
3441 #0!105G$\
3442 #0!105O$\
3443 #0!105_$\
3444 -\
3445 #0!105@$\
3446 #0!105A$\
3447 #0!105C$\
3448 #0!105G$\
3449 #0!105O$\
3450 #0!105_$\
3451 -\
3452 #0!59@#2@#6!9@#0!36@$\
3453 #0!58A#5A#6!11A#0!35A$\
3454 #0!57C#3C#6!11C#3C#0!35C$\
3455 #0!57G#6!11G#4G#0!36G$\
3456 #0!56O#4O#6!10O#5O#0!37O$\
3457 #0!55_#2_#6!11_#0!38_$\
3458 -\
3459 #0!55@#6!11@#1@#0!38@$\
3460 #0!54A#3A#6!10A#2A#0!39A$\
3461 #0!53C#1C#6!10C#3C#0!40C$\
3462 #0!53G#5G#6!9G#4G#0!41G$\
3463 #0!52O#3O#6!9O#5O#0!42O$\
3464 #0!52_#6!10_#0!43_$\
3465 -\
3466 #0!51@#4@#6!9@#1@#0!43@$\
3467 #0!50A#1A#6!9A#2A#0!44A$\
3468 #0!51C#5C#6!7C#0!46C$\
3469 #0!105G$\
3470 #0!105O$\
3471 #0!105_$\
3472 -\
3473 #0!105@$\
3474 #0!105A$\
3475 #0!40C#4C#6!7C#3C#0!18C#2C#6!8C#0!29C$\
3476 #0!20G#1G#6!8G#1G#0!7G#2G#6!13G#2G#0!13G#6!13G#4G#0!26G$\
3477 #0!20O#6!10O#0!5O#1O#6!17O#0!10O#5O#6!16O#2O#0!24O$\
3478 #0!20_#6!10_#0!4_#3_#6!19_#1_#0!6_#1_#6!19_#4_#0!23_$\
3479 -\
3480 #0!20@#6!10@#0!3@#5@#6!21@#1@#0!4@#3@#6!21@#3@#0!22@$\
3481 #0!20A#6!10A#0!2A#5A#6!22A#5A#0!3A#4A#6!23A#2A#0!21A$\
3482 #0!20C#6!10C#0C#6!25C#3C#0C#4C#6!25C#0!21C$\
3483 #0!20G#6!10G#5G#6!26G#4G#6!26G#3G#0!20G$\
3484 #0!20O#6!64O#5O#0!20O$\
3485 #0!20_#6!65_#2_#0!19_$\
3486 -\
3487 #0!20@#6!18@#2@#0!4@#4@#6!21@#4@#0!4@#3@#6!14@#3@#0!19@$\
3488 #0!20A#6!16A#3A#0!7A#1A#6!18A#5A#0!8A#6!13A#5A#0!19A$\
3489 #0!20C#6!15C#2C#0!9C#2C#6!16C#4C#0!10C#6!13C#0!19C$\
3490 #0!20G#6!14G#2G#0!11G#5G#6!14G#4G#0!11G#3G#6!12G#1G#0!18G$\
3491 #0!20O#6!13O#2O#0!12O#3O#6!13O#4O#0!12O#1O#6!12O#1O#0!18O$\
3492 #0!20_#6!12_#3_#0!13_#1_#6!12_#5_#0!14_#5_#6!11_#2_#0!18_$\
3493 -\
3494 #0!20@#6!11@#4@#0!15@#6!12@#0!15@#4@#6!11@#2@#0!18@$\
3495 #0!20A#6!11A#4A#0!15A#5A#6!11A#0!15A#3A#6!11A#2A#0!18A$\
3496 #0!20C#6!11C#4C#0!15C#5C#6!11C#0!15C#2C#6!11C#2C#0!18C$\
3497 #0!20G#6!11G#4G#0!15G#4G#6!11G#0!15G#2G#6!11G#2G#0!18G$\
3498 #0!20O#6!11O#4O#0!15O#4O#6!11O#0!15O#2O#6!11O#2O#0!18O$\
3499 #0!20_#6!11_#4_#0!15_#4_#6!11_#0!15_#2_#6!11_#2_#0!18_$\
3500 -\
3501 #0!20@#6!11@#4@#0!15@#4@#6!11@#0!15@#2@#6!11@#2@#0!18@$\
3502 #0!20A#6!11A#4A#0!15A#4A#6!11A#0!15A#2A#6!11A#2A#0!18A$\
3503 #0!20C#6!11C#4C#0!15C#4C#6!11C#0!15C#2C#6!11C#2C#0!18C$\
3504 #0!20G#6!11G#4G#0!15G#4G#6!11G#0!15G#2G#6!11G#2G#0!18G$\
3505 #0!20O#6!11O#4O#0!15O#4O#6!11O#0!15O#2O#6!11O#2O#0!18O$\
3506 #0!20_#6!11_#4_#0!15_#4_#6!11_#0!15_#2_#6!11_#2_#0!18_$\
3507 -\
3508 #0!20@#6!11@#4@#0!15@#4@#6!11@#0!15@#2@#6!11@#2@#0!18@$\
3509 #0!20A#6!11A#4A#0!15A#4A#6!11A#0!15A#2A#6!11A#2A#0!18A$\
3510 #0!20C#6!11C#4C#0!15C#4C#6!11C#0!15C#2C#6!11C#2C#0!18C$\
3511 #0!20G#6!11G#4G#0!15G#4G#6!11G#0!15G#2G#6!11G#2G#0!18G$\
3512 #0!20O#6!11O#4O#0!15O#4O#6!11O#0!15O#2O#6!11O#2O#0!18O$\
3513 #0!20_#6!11_#4_#0!15_#4_#6!11_#0!15_#2_#6!11_#2_#0!18_$\
3514 -\
3515 #0!20@#6!11@#4@#0!15@#4@#6!11@#0!15@#2@#6!11@#2@#0!18@$\
3516 #0!20A#6!11A#4A#0!15A#4A#6!11A#0!15A#2A#6!11A#2A#0!18A$\
3517 #0!20C#6!11C#4C#0!15C#4C#6!11C#0!15C#2C#6!11C#2C#0!18C$\
3518 #0!20G#6!11G#4G#0!15G#4G#6!11G#0!15G#2G#6!11G#2G#0!18G$\
3519 #0!20O#6!11O#4O#0!15O#4O#6!11O#0!15O#2O#6!11O#2O#0!18O$\
3520 #0!20_#6!11_#4_#0!15_#4_#6!11_#0!15_#2_#6!11_#2_#0!18_$\
3521 -\
3522 #0!20@#6!11@#4@#0!15@#4@#6!11@#0!15@#2@#6!11@#2@#0!18@$\
3523 #0!20A#6!11A#4A#0!15A#4A#6!11A#0!15A#2A#6!11A#2A#0!18A$\
3524 #0!20C#6!11C#4C#0!15C#4C#6!11C#0!15C#2C#6!11C#2C#0!18C$\
3525 #0!20G#6!11G#4G#0!15G#4G#6!11G#0!15G#2G#6!11G#2G#0!18G$\
3526 #0!20O#6!11O#4O#0!15O#4O#6!11O#0!15O#2O#6!11O#2O#0!18O$\
3527 #0!21_#6!9_#3_#0!17_#3_#6!8_#5_#0!17_#2_#6!9_#1_#0!19_$\
3528 -\
3529 #0!105@$\
3530 #0!105A$\
3531 #0!105C$\
3532 #0!105G$\
3533 #0!105O$\
3534 #0!105_$\
3535 -\
3536 #0!105@$\
3537 #0!105A$\
3538 #0!105C$\
3539 #0!105G$\
3540 #0!105O$\
3541 #0!105_$\
3542 -\
3543 #0!105@$\
3544 #0!105A$\
3545 #0!105C$\
3546 #0!105G$\
3547 #0!105O$\
3548 #0!105_$\
3549 -\
3550 #0!105@$\
3551 #0!105A$\
3552 #0!105C$\
3553 #0!105G$\
3554 \\";
3555 #endif
3556
3557 void
splash_logo()3558 splash_logo ()
3559 {
3560 #ifdef use_splash_logo
3561 static FLAG splash_init_done = False;
3562 int splashpos = YMAX / 3;
3563
3564 if (splash_level == 0) {
3565 return;
3566 }
3567
3568 clear_screen ();
3569 if ((xterm_version > 2 && ! mlterm_version)
3570 || mintty_version > 0 || decterm_version > 0) {
3571 /* cjk_width_data_version not yet determined @ first invocation! */
3572 char * logo1 = (mapped_term || cjk_term
3573 || cjk_width_data_version || ! mintty_version)
3574 ? "` MinEd " VERSION
3575 : utf8_screen
3576 ? "´ MinEd " VERSION
3577 : "� MinEd " VERSION;
3578 char * logo2 = "m MinEd " VERSION;
3579 int xpos;
3580
3581 if (utf8_screen &&
3582 (combining_screen || mintty_version > 0 || xterm_version > 141)) {
3583 if (! screen_version && mintty_version > 0 && isglyph_code ("769")) {
3584 /* double-height combining works in mintty */
3585 logo1 = "ḿ MinEd " VERSION;
3586 logo2 = logo1;
3587 }
3588 }
3589 xpos = XMAX / 4 - strlen ("m MinEd " VERSION) / 2 + 1;
3590 if (! mlterm_version) {
3591 set_cursor (xpos, YMAX / 3);
3592 putescape ("\033#3"); putescape (logo1);
3593 set_cursor (xpos, YMAX / 3 + 1);
3594 putescape ("\033#4"); putescape (logo2);
3595 putstring ("\n");
3596 splashpos = YMAX / 3 + 3;
3597 }
3598 }
3599 #ifdef use_sixel_splash
3600 if (splash_level > 1 &&
3601 ((xterm_version >= 298 && dec_features & (1 << 4))
3602 || mlterm_version >= 319 /* actually since 3.1.9 */
3603 )
3604 ) {
3605 set_cursor (XMAX / 2 - 5, splashpos);
3606 putescape (sixelsplash);
3607 putstring ("\n");
3608 flush ();
3609
3610 if (splash_init_done || filelist_count () == 0) {
3611 /* don't sleep (1); */
3612 }
3613 splash_init_done = True;
3614 }
3615 #endif
3616 flush ();
3617 #endif
3618 }
3619
3620 void
switchAltScreen()3621 switchAltScreen ()
3622 {
3623 status_msg ("Trying to switch to command line view (normal screen)");
3624 screen_buffer (False);
3625 flush ();
3626 (void) readcharacter ();
3627 RDwin ();
3628 status_msg ("Returned to editing view (alternate screen)");
3629 }
3630
3631 static
3632 void
print_terminal_info()3633 print_terminal_info ()
3634 {
3635 printf ("Terminal size %d x %d\n", YMAX + 1 + MENU, XMAX + 1);
3636 printf ("Terminal encoding %s\n", get_term_encoding ());
3637 printf ("- combining %d, bidi %d, joining %d, halfjoining %d\n",
3638 combining_screen, bidi_screen,
3639 joining_screen, halfjoining_screen);
3640 if (utf8_auto_detected) {
3641 printf ("- UTF-8 auto-detected\n");
3642 }
3643 printf ("- width data version %d - %s\n",
3644 width_data_version,
3645 term_Unicode_version_name (width_data_version));
3646 if (cjk_term) {
3647 printf ("- CJK terminal%s%s\n",
3648 cjk_uni_term ? " - Unicode based" : "",
3649 gb18030_term ? " - GB18030" : "");
3650 }
3651 if (cjk_width_data_version) {
3652 printf ("- CJK width data version %d - %s\n",
3653 cjk_width_data_version,
3654 term_Unicode_version_name (cjk_width_data_version));
3655 }
3656 if (combining_screen) {
3657 printf ("- combining data version %d - %s (Hangul Jamo extended %d)\n",
3658 combining_data_version,
3659 term_Unicode_version_name (combining_data_version),
3660 hangul_jamo_extended);
3661 }
3662 printf ("- non-BMP width data mode %02X: plane_2_double %d plane_1_comb %d plane_14_comb %d\n",
3663 nonbmp_width_data, plane_2_double_width,
3664 plane_1_combining, plane_14_combining);
3665
3666 if (terminal_type > ' ') {
3667 printf ("- terminal type %d ('%c') version %d\n",
3668 terminal_type, terminal_type, terminal_version);
3669 } else if (terminal_type >= 0) {
3670 printf ("- terminal type %d version %d\n",
3671 terminal_type, terminal_version);
3672 }
3673 if (screen_version > 0) {
3674 printf ("- 'screen' version %d\n", screen_version);
3675 }
3676 if (tmux_version > 0) {
3677 printf ("- 'tmux' version %d\n", tmux_version);
3678 }
3679 if (xterm_version > 0) {
3680 printf ("- 'xterm' version %d\n", xterm_version);
3681 }
3682 if (decterm_version > 0) {
3683 printf ("- 'DEC terminal' version %d\n", decterm_version);
3684 }
3685 if (rxvt_version > 0) {
3686 if (terminal_type == 'U') {
3687 printf ("- 'rxvt-unicode' version %d\n", rxvt_version);
3688 } else {
3689 printf ("- 'rxvt' version %d\n", rxvt_version);
3690 }
3691 }
3692 if (gnome_terminal_version > 0) {
3693 printf ("- 'gnome terminal' version %d\n", gnome_terminal_version);
3694 }
3695 if (konsole_version > 0) {
3696 printf ("- 'KDE konsole' version %d\n", konsole_version);
3697 }
3698 if (mintty_version > 0) {
3699 printf ("- 'mintty' version %d\n", mintty_version);
3700 }
3701 if (mlterm_version > 1) {
3702 printf ("- 'mlterm' version %d\n", mlterm_version);
3703 } else if (mlterm_version > 0) {
3704 printf ("- 'mlterm'\n");
3705 }
3706 if (colours_256) {
3707 printf ("- assuming 256%s color mode\n", colours_88 ? " (maybe 88)" : "");
3708 } else if (colours_88) {
3709 printf ("- assuming 88 color mode\n");
3710 }
3711 /* check #ifdef debug_screenmode for further information */
3712
3713 /*printf ("- window title encoding <%c>\n", title_encoding);*/
3714
3715 printf ("Menu border characters: ~ %s\n",
3716 use_ascii_graphics ? "ASCII" :
3717 use_vga_block_graphics ? "VGA" :
3718 use_pc_block_graphics ? "PC-compatible":
3719 use_vt100_block_graphics ? "VT100 block graphics":
3720 utf8_screen ? "Unicode":
3721 "VT100 block graphics"
3722 );
3723
3724 if (dark_term) {
3725 printf ("- dark terminal background\n");
3726 }
3727 printf ("- dim mode: ");
3728 if (can_dim) {
3729 printf ("native\n");
3730 #ifdef unix
3731 } else if (redefined_ansi7) {
3732 printf ("redefining ansi mode\n");
3733 #endif
3734 } else {
3735 printf ("none\n");
3736 }
3737 }
3738
3739 /**
3740 Perform terminal detection, encoding auto-detection, determine features,
3741 setup terminal.
3742 */
3743 static
3744 void
terminal_configure_init()3745 terminal_configure_init ()
3746 {
3747 int swidth;
3748
3749 /* terminal mode initialisation */
3750 /* Note: this must be called before any screen interaction,
3751 e.g. test_screen_width, acquire_screen_widths, get_screen_width
3752 but after pipe handling (I/O redirection)
3753 */
3754 get_term (TERM);
3755
3756 /* Set tty to appropriate mode; don't rely on checkwinsize() yet! */
3757 raw_mode (True);
3758 if (erase_char != '\0') {
3759 key_map [erase_char] = DPC;
3760 }
3761 #ifdef vms
3762 /* detection of terminal setting fails, so in case DEL is on Backarrow: */
3763 key_map ['\177'] = DPC;
3764 #endif
3765
3766
3767 checkwinsize ();
3768 if (XMAX < 39 || YMAX < 1) {
3769 panic ("Min. 3x40 size needed for terminal", "too small");
3770 }
3771
3772
3773 /* ensure feedback after start-up when terminal is slow on queries */
3774 if (strisprefix ("rxvt", TERM)) {
3775 get_ansi_modes ();
3776 clearscreen ();
3777 status_msg ("Auto-detecting terminal properties - waiting for rxvt to report");
3778 set_cursor (0, 0);
3779 flush ();
3780
3781 /* Make sure output is flushed in rxvt (was apparently needed): */
3782 (void) char_ready_within (30, NIL_PTR);
3783 }
3784
3785
3786 /* request terminal type and version from terminal */
3787 detect_terminal_type ();
3788
3789 #ifdef debug_graphics
3790 printf ("(ty) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
3791 #endif
3792
3793
3794 /* detect screen encoding and calibrate screen properties */
3795
3796 /* detect kterm encodings */
3797 #define sjis_3bytes "x�a"
3798 /*#define sjis_3bytes "���"*/
3799 if (streq ("kterm", TERM)) {
3800 if (test_screen_width (sjis_3bytes) == 3) {
3801 (void) set_term_encoding ("Shift-JIS", 'S');
3802 if (! text_encoding_selected) {
3803 (void) set_text_encoding ("Shift-JIS", 'S', "TERM=kterm");
3804 }
3805 } else {
3806 (void) set_term_encoding ("EUC-JP", 'J');
3807 if (! text_encoding_selected) {
3808 (void) set_text_encoding ("EUC-JP", 'J', "TERM=kterm");
3809 }
3810 }
3811 auto_detect = False;
3812 trace_encoding ("kterm");
3813 }
3814
3815
3816 /* detect UTF-8 and CJK screen encodings */
3817 trace_encoding ("init");
3818
3819 swidth = test_screen_width ("åلاษษ刈墢");
3820 #ifdef debug_screenmode
3821 printf ("test_screen_width -> %d\n", swidth);
3822 #endif
3823
3824 if (screen_version > 0 && swidth == 3) {
3825 /* workaround for problem to get LAM through 'screen' */
3826 swidth = test_screen_width ("ålษษ刈墢");
3827 #ifdef debug_screenmode
3828 printf ("test_screen_width -> %d\n", swidth);
3829 #endif
3830 }
3831
3832 if (swidth > 0) {
3833 /**
3834 check cursor column after test string, determine screen mode
3835 6 -> UTF-8, no double-width, with LAM/ALEF ligature joining
3836 7 -> UTF-8, no double-width, no LAM/ALEF ligature joining
3837 8 -> UTF-8, double-width, with LAM/ALEF ligature joining
3838 9 -> UTF-8, double-width, no LAM/ALEF ligature joining
3839 11,16 -> CJK terminal (with luit)
3840 10,15 -> 8 bit terminal or CJK terminal
3841 13 -> Poderosa terminal emulator, UTF-8, or TIS620 terminal
3842 14,17 -> CJK terminal
3843 16 -> Poderosa, ISO Latin-1
3844 (17) -> Poderosa, (JIS)
3845 18 -> CJK terminal (or 8 bit terminal, e.g. Linux console)
3846 */
3847
3848 if (swidth == 13) {
3849 /* TIS620 terminal or Poderosa UTF-8 mode */
3850 if (test_screen_width ("å") == 1) {
3851 poderosa_version = 1;
3852 swidth = 9; /* continue with UTF-8 checks */
3853 } else {
3854 set_term_encoding ("TIS", 'T');
3855 }
3856 } else if (swidth == 16) {
3857 poderosa_version = 1;
3858 }
3859
3860 if (swidth > 0 && swidth <= 9) {
3861 int xwidth;
3862 FLAG do_width_checks = True;
3863
3864 utf8_screen = True;
3865 utf8_auto_detected = True;
3866 utf8_input = True;
3867 cjk_term = False;
3868 mapped_term = False;
3869
3870 check_glyphs ();
3871 splash_logo ();
3872
3873 #ifdef vms
3874 if (rxvt_version > 0
3875 || mintty_version > 0
3876 ) {
3877 /* checks are too slow... */
3878 do_width_checks = False;
3879 }
3880 #endif
3881
3882 if (do_width_checks) {
3883 acquire_screen_widths (utf8_widths, arrlen (utf8_widths));
3884 }
3885
3886 if (get_screen_width ("a̡", utf8_widths, arrlen (utf8_widths)) == 1) {
3887 combining_screen = True;
3888 if (! combining_mode_disabled) {
3889 combining_mode = True;
3890 }
3891 } else {
3892 combining_screen = False;
3893 combining_mode = False;
3894 }
3895 if ((swidth & 1) == 0) {
3896 /* ligature joining detected, must also be bidi */
3897 joining_screen = True;
3898 bidi_screen = True;
3899 poormansbidi = False;
3900 /* disable scrollbar to prevent interference */
3901 if (! explicit_scrollbar_style) {
3902 disp_scrollbar = False;
3903 scrollbar_width = 0;
3904 }
3905 }
3906
3907 /* used to call splash_logo () here */
3908
3909 if (swidth < 8) {
3910 /* no wide character support */
3911 width_data_version = 0;
3912 trace_width_data_version ("0");
3913 } else if (do_width_checks) {
3914 if (get_screen_width ("", utf8_widths, arrlen (utf8_widths)) == 3) {
3915 width_data_version = U600;
3916 trace_width_data_version ("600");
3917 } else if (get_screen_width ("ꥠ", utf8_widths, arrlen (utf8_widths)) >= 2) {
3918 width_data_version = U520;
3919 trace_width_data_version ("520");
3920 } else if (get_screen_width ("︐", utf8_widths, arrlen (utf8_widths)) >= 2) {
3921 width_data_version = U410;
3922 trace_width_data_version ("410");
3923 } else if (get_screen_width ("《》〚〛⦅⦆", utf8_widths, arrlen (utf8_widths)) < 9) {
3924 /* older width data (before xterm 167) */
3925 width_data_version = U300;
3926 trace_width_data_version ("300");
3927 }
3928 }
3929
3930 if (do_width_checks) {
3931 /* determine combining data version */
3932
3933 /* Add new test strings to array utf8_widths
3934 (section detecting combining_data_version) */
3935 if (get_screen_width (".᪰.ᷮ", utf8_widths, arrlen (utf8_widths)) == 2) {
3936 combining_data_version = U700;
3937 } else if (get_screen_width ("..", utf8_widths, arrlen (utf8_widths)) == 2) {
3938 combining_data_version = U630;
3939 } else if (get_screen_width ("..ꙴ", utf8_widths, arrlen (utf8_widths)) == 2) {
3940 combining_data_version = U620;
3941 } else if (get_screen_width (".ٟ.ऺ", utf8_widths, arrlen (utf8_widths)) == 2) {
3942 combining_data_version = U600;
3943 } else if (get_screen_width (".ࠖ.ऀ", utf8_widths, arrlen (utf8_widths)) == 2) {
3944 combining_data_version = U520;
3945 } else if (get_screen_width (".҇.᷌", utf8_widths, arrlen (utf8_widths)) == 2) {
3946 combining_data_version = U510;
3947 } else if (get_screen_width (".᷄.᷅", utf8_widths, arrlen (utf8_widths)) == 2) {
3948 combining_data_version = U500;
3949 } else if (get_screen_width (".͘.͙", utf8_widths, arrlen (utf8_widths)) == 2) {
3950 combining_data_version = U410;
3951 } else if (get_screen_width (".͐.឴.", utf8_widths, arrlen (utf8_widths)) == 4) {
3952 combining_data_version = U400;
3953 } else if (get_screen_width ("aͣ", utf8_widths, arrlen (utf8_widths)) == 1) {
3954 combining_data_version = U320;
3955 } else if (get_screen_width ("a", utf8_widths, arrlen (utf8_widths)) == 1) {
3956 combining_data_version = U300;
3957 } else {
3958 combining_data_version = U300beta;
3959 }
3960 if (combining_data_version >= U520) {
3961 if (get_screen_width ("ᄀힰᄀퟋ", utf8_widths, arrlen (utf8_widths)) == 4) {
3962 hangul_jamo_extended = True;
3963 }
3964 }
3965 trace_width_data_version ("comb");
3966
3967 check_cjk_width ();
3968
3969 /* check non-BMP width properties */
3970 nonbmp_width_data = get_screen_width ("aaa", utf8_widths, arrlen (utf8_widths)) - 7;
3971 if (nonbmp_width_data > 7) {
3972 /* non-BMP combining characters are wide;
3973 xterm -cjk_width ?
3974 */
3975 nonbmp_width_data -= 3;
3976 }
3977 if (get_screen_width ("", utf8_widths, arrlen (utf8_widths)) > 3 && suppress_non_BMP == False) {
3978 /* e.g. KDE konsole */
3979 suppress_non_BMP = True;
3980 }
3981 /* check unassigned character width properties;
3982 they are sometimes displayed single-width by rxvt
3983 or xterm +mk_width (the default)
3984 */
3985 xwidth = get_screen_width ("ㄯ", utf8_widths, arrlen (utf8_widths));
3986 if (xwidth < 18) {
3987 unassigned_single_width = True;
3988 }
3989
3990 xwidth = get_screen_width ("䷀䷀", utf8_widths, arrlen (utf8_widths));
3991 /* check Yijing Hexagram width (wcwidth glitch) */
3992 if (xwidth < 4) {
3993 wide_Yijing_hexagrams = False;
3994 }
3995 /* check bidi markers printable width (since xterm 230) */
3996 if (xwidth & 1) {
3997 printable_bidi_controls = True;
3998 }
3999 }
4000 } else {
4001 utf8_screen = False;
4002 utf8_input = False;
4003
4004 splash_logo ();
4005
4006 if (! combining_screen_selected) {
4007 combining_screen = False;
4008 combining_mode = False;
4009 }
4010 acquire_screen_widths (cjk_widths, arrlen (cjk_widths));
4011 if (swidth > 13) {
4012 int cwidth = get_screen_width ("�0�2", cjk_widths, arrlen (cjk_widths));
4013 if (cwidth > 2) {
4014 /* quite safe detection */
4015 gb18030_term = False;
4016 suppress_extended_cjk = True;
4017 } else if (cwidth >= 0) {
4018 cjk_term = True;
4019 if (cwidth == 1) {
4020 cjk_uni_term = True;
4021 }
4022 }
4023 /* if any of the following characters is smaller
4024 than 2 character cells,
4025 it's not a native CJK terminal
4026 */
4027 cwidth = get_screen_width ("����ꥦ�ޡ���", cjk_widths, arrlen (cjk_widths));
4028 if (cwidth < 14) {
4029 cjk_uni_term = True;
4030 }
4031 cwidth = get_screen_width ("����", cjk_widths, arrlen (cjk_widths));
4032 if (cwidth > 2) {
4033 /* quite safe detection */
4034 euc4_term = False;
4035 suppress_extended_cjk = True;
4036 } else if (cwidth >= 0 && swidth != 15 /* mlterm */) {
4037 if (! mapped_term) {
4038 cjk_term = True;
4039 }
4040 }
4041 if (euc3_term && get_screen_width ("���x", cjk_widths, arrlen (cjk_widths)) > 3) {
4042 /* unsafe detection */
4043 euc3_term = False;
4044 suppress_extended_cjk = True;
4045 }
4046 if (get_screen_width ("��", cjk_widths, arrlen (cjk_widths)) < 2) {
4047 cjklow_term = False;
4048 }
4049 }
4050 if ((swidth > 10 && swidth != 13 && swidth != 15 && swidth < 18) || cjk_term) {
4051 /* if the test string width did not comply
4052 with 8 bit behaviour, or a
4053 GB18030 or EUC 4 byte (EUC-TW) terminal
4054 was asserted, assume CJK terminal;
4055 a EUC 3 byte (EUC-JP) terminal cannot
4056 be asserted but can just be assumed as
4057 an 8 bit terminal might respond with
4058 the same width behaviour
4059 */
4060 utf8_screen = False;
4061 utf8_input = False;
4062 if (! combining_screen_selected) {
4063 combining_screen = False;
4064 combining_mode = False;
4065 }
4066 /* assume CJK terminal with unspecific encoding */
4067 if (! mapped_term) {
4068 cjk_term = True;
4069 }
4070
4071 }
4072 }
4073 trace_encoding ("detected");
4074 } else {
4075 #ifdef __ANDROID__
4076 swidth = 0; /* no CPR */
4077 #endif
4078 if (swidth == 0) { /* e.g. Better Terminal on Android */
4079 (void) set_term_encoding ("ASCII", ' ');
4080 use_ascii_graphics = True;
4081 menu_border_style = 'r';
4082 }
4083
4084 splash_logo ();
4085 }
4086
4087 /* detect and adjust Poderosa terminal emulator (narrow ¡ and wide ×) */
4088 if (poderosa_version > 0) {
4089 if (utf8_screen
4090 #ifdef poderosa_detect_string
4091 && get_screen_width ("¡×", utf8_widths, arrlen (utf8_widths)) == 3
4092 #endif
4093 ) {
4094 /* Poderosa utf-8 (or undetected euc-jp/shift-jis) */
4095 limited_marker_font = True;
4096 } else if (! cjk_term
4097 #ifdef poderosa_detect_string
4098 && ! utf8_screen && get_screen_width ("��", cjk_widths, arrlen (cjk_widths)) == 3
4099 #endif
4100 ) {
4101 /* Poderosa iso-8859-1 */
4102 (void) set_term_encoding ("ISO-8859-1", ' ');
4103 } else {
4104 poderosa_version = 0;
4105 }
4106 if (poderosa_version > 0) {
4107 cjk_width_data_version = U300beta;
4108 use_vt100_block_graphics = False;
4109 use_ascii_graphics = True;
4110 menu_border_style = 'r';
4111 use_vga_block_graphics = False;
4112 use_mouse = False;
4113 use_appl_keypad = False;
4114 colours_256 = False;
4115 colours_88 = False;
4116 }
4117 }
4118
4119 #ifdef debug_graphics
4120 printf ("(tw) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
4121 #endif
4122
4123
4124 /* determine combining character support on non-Unicode terminal */
4125 if (cjk_term) {
4126 unsigned long cjk_combining = mappedtermchar (0x0300);
4127 if (no_char (cjk_combining)) {
4128 combining_screen = False;
4129 } else {
4130 char cjk_check [9];
4131 char * check = cjk_check;
4132 * check ++ = 'a';
4133 check += cjkencode_char (True, cjk_combining, check);
4134 * check = '\0';
4135 if (test_screen_width (cjk_check) == 1) {
4136 combining_screen = True;
4137 if (! combining_mode_disabled) {
4138 combining_mode = True;
4139 }
4140 #ifdef debug_screenmode
4141 printf ("cjk combining screen %d (disabled %d) mode %d\n", combining_screen, combining_mode_disabled, combining_mode);
4142 #endif
4143 }
4144 }
4145 } else if (mapped_term) {
4146 character c;
4147 combining_screen = False;
4148 for (c = 0x80; ; c ++) {
4149 unsigned long u = lookup_mappedtermchar (c);
4150 if (! no_unichar (u) && iscombining (u)) {
4151 char comb_check [3];
4152 comb_check [0] = 'a';
4153 comb_check [1] = c;
4154 comb_check [2] = '\0';
4155 if (test_screen_width (comb_check) == 1) {
4156 combining_screen = True;
4157 if (! combining_mode_disabled) {
4158 combining_mode = True;
4159 }
4160 }
4161 break;
4162 }
4163 if (c == 0xFF) {
4164 break;
4165 }
4166 }
4167 }
4168
4169 /* determine joining character support on non-Unicode terminal */
4170 if (cjk_term || mapped_term) {
4171 unsigned long lam = mappedtermchar (0x0644);
4172 if (! no_char (lam)) {
4173 unsigned long alef = mappedtermchar (0x0627);
4174 char join_check [9];
4175 char * check = join_check;
4176 * check ++ = 'a';
4177 if (cjk_term) {
4178 check += cjkencode_char (True, lam, check);
4179 check += cjkencode_char (True, alef, check);
4180 } else {
4181 * check ++ = lam;
4182 * check ++ = alef;
4183 }
4184 * check = '\0';
4185 if (test_screen_width (join_check) == 2) {
4186 /* ligature joining detected, must also be bidi */
4187 joining_screen = True;
4188 bidi_screen = True;
4189 poormansbidi = False;
4190 /* disable scrollbar to prevent interference */
4191 if (! explicit_scrollbar_style) {
4192 disp_scrollbar = False;
4193 scrollbar_width = 0;
4194 }
4195 /* bold does not work */
4196 use_bold = False;
4197 #ifdef debug_screenmode
4198 printf ("bidi screen\n");
4199 #endif
4200 }
4201 }
4202 }
4203
4204 /* determine terminal restrictions relevant for marker configuration */
4205
4206 if (strisprefix ("terminator", TERM)) {
4207 limited_marker_font = True;
4208 }
4209
4210
4211 /* adjust CJK width properties */
4212 /* adjust CJK line markers */
4213 if (cjk_term) {
4214 /* determine size of line markers in CJK terminal encoding */
4215 int cjk_ellipsis_width;
4216 unsigned long cjk_degree = mappedtermchar (0x00B0); /* ° */
4217 unsigned long cjk_lineend = mappedtermchar (0x300A); /* 《 */
4218 unsigned long cjk_ellipsis = mappedtermchar (0x2026); /* … */
4219 unsigned long cjk_uni = mappedtermchar (0x00A2); /* ¢ */
4220 unsigned long cjk_dot = mappedtermchar (0x00B7); /* · */
4221 unsigned long cjk_lat = mappedtermchar (0x00F8); /* ø */
4222 unsigned long cjk_shy = mappedtermchar (0x00AD); /* */
4223 unsigned long cjk_ten = mappedtermchar (0x3248); /* ㉈ */
4224
4225 char cjk_check [29];
4226 char * check = cjk_check;
4227 int cjkwidth;
4228 cjk_currency_width = 1;
4229 check += cjkencode_char (True, cjk_ellipsis, check);
4230 check += cjkencode_char (True, cjk_lineend, check);
4231 check += cjkencode_char (True, cjk_lineend, check);
4232 if (no_char (cjk_uni)) {
4233 cjk_currency_width = 0;
4234 cjk_uni = cjk_shy;
4235 if (no_char (cjk_uni)) {
4236 cjk_uni = mappedtermchar (0x00AF); /* ¯ */
4237 }
4238 }
4239 if (! no_char (cjk_uni)) {
4240 check += cjkencode_char (True, cjk_uni, check);
4241 check += cjkencode_char (True, cjk_uni, check);
4242 check += cjkencode_char (True, cjk_uni, check);
4243 check += cjkencode_char (True, cjk_uni, check);
4244 }
4245 * check = '\0';
4246 cjkwidth = test_screen_width (cjk_check);
4247 cjkwidth --;
4248 cjk_ellipsis_width = 1 + (cjkwidth & 1);
4249 cjkwidth = (cjkwidth >> 1) - 1;
4250 cjk_lineend_width = 1 + (cjkwidth & 1);
4251 cjkwidth = (cjkwidth >> 1) - 1;
4252 if (cjk_currency_width && cjkwidth == 1) {
4253 cjk_currency_width = 2;
4254 }
4255 if (! no_char (cjk_uni) && (cjkwidth & 1) == 0) {
4256 cjk_uni_term = True;
4257 }
4258
4259 if (cjk_uni_term) {
4260 if (! no_char (cjk_degree)) {
4261 check = cjk_check;
4262 check += cjkencode_char (True, cjk_degree, check);
4263 * check = '\0';
4264 if (test_screen_width (cjk_check) == 2) {
4265 cjk_width_data_version = U320beta;
4266 }
4267 }
4268
4269 if (cjk_lineend_width == 1) {
4270 if (width_data_version > 0) {
4271 width_data_version = U300;
4272 }
4273 } else if (cjk_ellipsis_width == 2) {
4274 cjk_width_data_version = U400;
4275 /* ?
4276 if (width_data_version < U400) {
4277 if (width_data_version > 0) {
4278 width_data_version = U400;
4279 }
4280 }
4281 */
4282
4283 if (! no_char (cjk_ten)) {
4284 check = cjk_check;
4285 check += cjkencode_char (True, cjk_ten, check);
4286 * check = '\0';
4287 if (test_screen_width (cjk_check) == 2) {
4288 cjk_width_data_version = U520;
4289 }
4290 }
4291
4292 if (cjk_width_data_version < U520 && ! no_char (cjk_shy)) {
4293 check = cjk_check;
4294 check += cjkencode_char (True, cjk_shy, check);
4295 * check = '\0';
4296 if (test_screen_width (cjk_check) == 2) {
4297 cjk_width_data_version = U320beta;
4298 }
4299 }
4300
4301 if (! no_char (cjk_lat)) {
4302 check = cjk_check;
4303 check += cjkencode_char (True, cjk_lat, check);
4304 * check = '\0';
4305 if (test_screen_width (cjk_check) == 2) {
4306 cjk_wide_latin1 = True;
4307 } else {
4308 cjk_wide_latin1 = False;
4309 }
4310 }
4311 } else if (rxvt_version > 0 && ! no_char (cjk_dot)) {
4312 check = cjk_check;
4313 check += cjkencode_char (True, cjk_dot, check);
4314 * check = '\0';
4315 if (test_screen_width (cjk_check) == 1) {
4316 /* fix this as a workaround for buggy rxvt */
4317 if (width_data_version > 0) {
4318 width_data_version = U320;
4319 }
4320 }
4321 }
4322 trace_width_data_version ("cjk_uni_term");
4323 #ifdef debug_screenmode
4324 printf ("cjk_uni_term (width_data_version %d CJK %d) ", width_data_version, cjk_width_data_version);
4325 #endif
4326 }
4327 #ifdef debug_screenmode
4328 printf ("CJK %c\n", text_encoding_tag);
4329 printf ("euc3 %d, euc4 %d, low cjk %d\n", euc3_term, euc4_term, cjklow_term);
4330 #endif
4331
4332 if (CJK_TAB_marker >= 0x80) {
4333 #ifdef CJKTAB_MIDDLE_DOT
4334 /* not available in all CJK encodings and terminals */
4335 CJK_TAB_marker = 0x00B7;
4336 cjk_tab_width = cjk_dot_width;
4337 #else
4338 cjk_tab_width = cjk_ellipsis_width;
4339 #endif
4340 if (term_encoding_tag == 'H') {
4341 /* workaround for buggy hanterm */
4342 CJK_TAB_marker = '.';
4343 }
4344 if (limited_marker_font) {
4345 CJK_TAB_marker = '.';
4346 }
4347 }
4348 if (CJK_TAB_marker < 0x80) {
4349 cjk_tab_width = 1;
4350 }
4351
4352 /* ensure further markers work for CJK */
4353 SHIFT_marker = ' ';
4354 MENU_marker = '>';
4355 }
4356
4357
4358 #ifdef debug_screenmode
4359 printf ("width_data_version %d (CJK %d), combining_data_version %d\n", width_data_version, cjk_width_data_version, combining_data_version);
4360 #else
4361 trace_width_data_version ("final");
4362 #endif
4363
4364
4365 /* request terminal type and version from terminal */
4366 /* detect_terminal_type (); moved above */
4367
4368
4369 /* 'screen' tweaks */
4370 if (screen_version > 0) {
4371 if (! explicit_scrollbar_style) {
4372 fine_scrollbar = False;
4373 }
4374 if (! explicit_border_style) {
4375 use_stylish_menu_selection = False;
4376 use_vt100_block_graphics = True;
4377 }
4378 if (limited_marker_font) {
4379 very_limited_marker_font = True;
4380 } else {
4381 limited_marker_font = True;
4382 }
4383 use_mouse_anymove_inmenu = True;
4384 }
4385
4386 /* 'tmux' tweaks */
4387 if (tmux_version > 0) {
4388 if (limited_marker_font) {
4389 very_limited_marker_font = True;
4390 } else {
4391 limited_marker_font = True;
4392 }
4393 if (! explicit_border_style) {
4394 use_stylish_menu_selection = False;
4395 }
4396 bold_border = False; /* could be in mintty using DejaVu fonts */
4397 }
4398
4399 /* mlterm tweaks */
4400 /* since mlterm does not identify itself, try to reveal it: */
4401 if (! mlterm_version) {
4402 if (streq ("mlterm", TERM)) {
4403 mlterm_version = 1;
4404 } else if (bidi_screen && ! mintty_version) { /* probably mlterm */
4405 mlterm_version = 1;
4406 }
4407 }
4408 if (mlterm_version > 0) {
4409 use_appl_keypad = True;
4410 apply_joining = False; /* use native LAM/ALEF joining of mlterm */
4411 unassigned_single_width = True;
4412 spacing_combining = True;
4413 /* bold would use weird font */
4414 use_bold = False;
4415 if (xterm_version >= 96) { /* mlterm 3.1.0 */
4416 use_mouse_1015 = True; /* mlterm 3.1.2 supports 1015 and 1006 */
4417 }
4418 /* enforce some observed font limitations of cygwin mlterm */
4419 if (limited_marker_font) {
4420 very_limited_marker_font = True;
4421 } else {
4422 limited_marker_font = True;
4423 }
4424 if (! explicit_border_style) {
4425 use_stylish_menu_selection = False;
4426 }
4427 if (! explicit_scrollbar_style) {
4428 disp_scrollbar = False;
4429 scrollbar_width = 0;
4430 }
4431 fine_scrollbar = False;
4432 }
4433
4434 /* workaround for buggy mlterm bold/width chaos */
4435 #ifdef oldmlterm_wideboldborderbug_workaround
4436 if (! explicit_border_style && ! cjk_width_data_version) {
4437 bold_on ();
4438 /* check width of upper left rounded corner */
4439 if (get_screen_width ("╭", utf8_widths, arrlen (utf8_widths)) > 1) {
4440 use_vt100_block_graphics = True;
4441 }
4442 bold_off ();
4443 }
4444 #endif
4445
4446 /* tweaks for KDE konsole; disable use of some features */
4447 if (konsole_version > 0) {
4448 colours_256 = False;
4449 if (! utf8_screen) {
4450 /* VT100 block graphics work now with workaround for
4451 missing eA capability (see io.c) */
4452 /* disable use of VT100 block graphics for
4453 konsole instances that do not support them */
4454 if (strcontains (TERM, "linux")) {
4455 use_ascii_graphics = True;
4456 menu_border_style = 'r';
4457 use_vga_block_graphics = False;
4458 }
4459 }
4460 /* disable use of Unicode fine-grained block graphics */
4461 if (! explicit_border_style) {
4462 use_stylish_menu_selection = False;
4463 if (! use_ascii_graphics) {
4464 menu_border_style = 's';
4465 }
4466 }
4467 /* make menu selections more visible ? */
4468 /*dark_term = True;*/ /* fatal if not actually dark */
4469
4470 /* workaround for buggy behaviour on systems that report
4471 wrong window size (SCO Unixware Caldera Linux) */
4472 if (! can_get_winsize) {
4473 can_delete_line = False;
4474 }
4475 }
4476
4477 /* handle mintty/PuTTY */
4478 if (mintty_version > 0) {
4479 display_delay = 0;
4480
4481 if (utf8_screen && mintty_version >= 909) {
4482 /* used to check_glyphs () here */
4483 if (! glyphs) {
4484 limited_marker_font = True;
4485 }
4486 } else {
4487 if (limited_marker_font) {
4488 very_limited_marker_font = True;
4489 } else {
4490 limited_marker_font = True;
4491 }
4492 }
4493
4494 spacing_combining = False;
4495 if (mintty_version < 500 && suppress_non_BMP == False) {
4496 suppress_non_BMP = True;
4497 }
4498 bidi_screen = True;
4499 halfjoining_screen = True;
4500 apply_joining = True;
4501 poormansbidi = False;
4502 /* disable scrollbar to prevent interference */
4503 if (! explicit_scrollbar_style) {
4504 /*disp_scrollbar = False;*/
4505 /*scrollbar_width = 0;*/
4506 }
4507
4508 /* mintty display adjustment */
4509 if (! explicit_scrollbar_style) {
4510 if (! isglyph_code ("9601")) { /* LOWER ONE EIGHTH BLOCK */
4511 fine_scrollbar = False;
4512 }
4513 }
4514 if (! explicit_selection_style) {
4515 #ifdef assume_proper_vertical_blocks
4516 if (! isglyph_code ("9613")) { /* LEFT THREE EIGHTHS BLOCK */
4517 use_stylish_menu_selection = False;
4518 }
4519 #else
4520 /* defensively disable use of crap vertical blocks */
4521 use_stylish_menu_selection = False;
4522 #endif
4523 }
4524 if (! explicit_border_style) {
4525 if (mintty_version >= 400) {
4526 if (isglyph_code ("9581")) { /* BOX DRAWINGS ARC */
4527 menu_border_style = 'r';
4528 } else if (isglyph_code ("9484")) { /* BOX DRAW. CORNER */
4529 menu_border_style = 's';
4530 } else {
4531 use_vt100_block_graphics = True;
4532 /*use_ascii_graphics = True;*/
4533 menu_border_style = 'r';
4534 }
4535 } else {
4536 menu_border_style = 'd';
4537 }
4538 }
4539 /* for the sake of DejaVu fonts */
4540 bold_border = False;
4541
4542 can_dim = True; /* ? some shading problems... */
4543 #ifdef avoid_light_pseudo_bold
4544 dark_term = False;
4545 #endif
4546
4547 if (mintty_version >= 400) {
4548 use_modifyOtherKeys = True;
4549 use_appl_cursor = False;
4550 use_appl_keypad = True;
4551 }
4552 if (mintty_version >= 10004) {
4553 /* numeric encoding of mouse coordinates */
4554 use_mouse_1015 = True;
4555 } else {
4556 use_mouse_1015 = False; /* buggy in 1.0.3 */
4557 if (mintty_version >= 900) {
4558 /* UTF-8 encoding of mouse coordinates */
4559 use_mouse_extended = True;
4560 }
4561 }
4562 /* enable mouse move reporting without button pressed (for menus) */
4563 use_mouse_anymove_inmenu = True;
4564 /* limit terminal to ASCII in POSIX locale */
4565 (void) locale_terminal_encoding ();
4566 }
4567
4568 if (strisprefix ("xterm", TERM) && xterm_version != 2) {
4569 colours_256 = True;
4570 }
4571
4572 /* disable VT100 graphics for openwin xterm (but not for cxterm etc) */
4573 if (xterm_version == 2 && ! cjk_term) {
4574 use_ascii_graphics = True;
4575 use_vt100_block_graphics = False;
4576 menu_border_style = 'r';
4577 }
4578
4579 /* disable erase characters for older xterm */
4580 if (xterm_version < 154 && mlterm_version == 0) {
4581 can_erase_chars = False;
4582 }
4583
4584 /* indicate enabling of special terminal modes */
4585 if (xterm_version >= 216) {
4586 use_modifyOtherKeys = True;
4587 /*use_appl_keypad = True;*/
4588 }
4589 if (xterm_version > 0) {
4590 /* enable mouse move reporting without button pressed (for menus) */
4591 use_mouse_anymove_inmenu = True;
4592 }
4593 if (xterm_version >= 277) {
4594 /* numeric encoding of mouse coordinates */
4595 use_mouse_1015 = True;
4596 } else if (xterm_version >= 262) {
4597 /* UTF-8 encoding of mouse coordinates */
4598 use_mouse_extended = True;
4599 }
4600 if (xterm_version > 305) {
4601 can_dim = True;
4602 }
4603 if (xterm_version > 0 /* && xterm_version < ?? */) {
4604 suppress_non_BMP = True;
4605 }
4606
4607 #ifdef use_mouse_hilite_tracking
4608 /* suppress mouse highlight tracking when it would lock xterm */
4609 if (xterm_version == 224) {
4610 /* xterm bug broke hilite mode abort sequence */
4611 use_mouse_hilite_tracking = False;
4612 }
4613 #endif
4614
4615 /* suppress fancy graphic characters in gnome-terminal, fix keyboard mapping */
4616 if (gnome_terminal_version > 0) {
4617 /* give built-in keydefs precedence over buggy termcap */
4618 set_fkeymap (NIL_PTR);
4619 /* workaround for unusual keypad assignments */
4620 if (mined_keypad) {
4621 mined_keypad = False;
4622 } else { /* in case option -k reversed it already */
4623 mined_keypad = True;
4624 }
4625
4626 /* probably gnome-terminal */
4627 if (! use_ascii_graphics) {
4628 menu_border_style = 's';
4629 }
4630 use_stylish_menu_selection = False;
4631 fine_scrollbar = False;
4632
4633 /* make menu selections more visible ? */
4634 /*dark_term = True;*/ /* fatal if not actually dark */
4635
4636 /* suppress attempts to display invalid Unicode characters */
4637 suppress_EF = True;
4638
4639 /* enable mouse move reporting without button pressed (for menus) */
4640 use_mouse_anymove_inmenu = True;
4641
4642 if (gnome_terminal_version >= 2000 && gnome_terminal_version < 2800) {
4643 /* for the sake of sakura */
4644 use_vt100_block_graphics = True;
4645 limited_marker_font = True;
4646 very_limited_marker_font = True;
4647 }
4648
4649 cursor_style = 0;
4650 }
4651
4652 /* special cases of terminal capabilities handling (esp. block graphics) */
4653
4654 if (strcontains (TERM, "vt220")
4655 || strcontains (TERM, "vt320")
4656 || strcontains (TERM, "vt340")
4657 || strcontains (TERM, "vt400")
4658 || strcontains (TERM, "vt420")
4659 || strcontains (TERM, "vt510")
4660 || strcontains (TERM, "vt520")
4661 || strcontains (TERM, "vt525")
4662 || strisprefix ("pcvt", TERM)
4663 || strisprefix ("ncsa", TERM)
4664 || strisprefix ("ti916", TERM)
4665 || strisprefix ("bq300", TERM)
4666 || strisprefix ("z340", TERM)
4667 || strisprefix ("ncr160vt300", TERM)
4668 || strisprefix ("ncr260vt300", TERM)
4669 || streq ("emu-220", TERM)
4670 || streq ("crt", TERM)
4671 ) {
4672 use_appl_keypad = True;
4673 }
4674 if (strcontains (TERM, "linux")) {
4675 set_fkeymap ("linux");
4676 fine_scrollbar = False;
4677 use_stylish_menu_selection = False;
4678 UTF_MENU_marker = "»";
4679 submenu_marker = "»";
4680 dark_term = True;
4681 bold_border = False; /* needed e.g. for Debian VGA console */
4682 use_appl_keypad = True;
4683 if (! explicit_border_style) {
4684 if (utf8_screen) {
4685 /*use_ascii_graphics = True;*/
4686 if (! use_ascii_graphics) {
4687 /* 's' or 'd' work */
4688 menu_border_style = 's';
4689 }
4690 } else if (use_vt100_block_graphics == False) {
4691 use_vga_block_graphics = True;
4692 }
4693 }
4694 }
4695 if (! can_alt_cset && ! use_pc_block_graphics && ! use_vga_block_graphics && ! utf8_screen ) {
4696 use_ascii_graphics = True;
4697 menu_border_style = 'r';
4698 }
4699 if (cjk_term) {
4700 /* make sure lineend marker will always fit: */
4701 scrollbar_width = 1;
4702
4703 /*use_bgcolor = False;*/
4704
4705 if (strisprefix ("rxvt", TERM)) {
4706 /* seems to work now */
4707 } else if (xterm_version == 2) {
4708 /* cxterm would blink instead of setting 256 color mode */
4709 colours_256 = False;
4710 colours_88 = False;
4711 }
4712 }
4713 #ifdef debug_graphics
4714 printf ("(tt) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
4715 #endif
4716
4717 /* derive further terminal restrictions */
4718 if (standout_glitch) {
4719 use_bold = False;
4720 }
4721
4722
4723 /* some terminal-specific properties */
4724 if (strisprefix ("vt1", TERM)) {
4725 use_appl_keypad = True;
4726 }
4727 if (rxvt_version > 0 || strisprefix ("rxvt", TERM)) {
4728 use_appl_keypad = True;
4729
4730 if (rxvt_version < 909 && rxvt_version >= 380) {
4731 colours_256 = False;
4732 colours_88 = True;
4733 /* ?? colour mode doesn't work with older buggy rxvt after configure --enable-text-blink --disable-256-color */
4734 }
4735
4736 #ifdef check_unassigned_single_width_here
4737 /* rxvt-unicode sometimes displays all unassigned Unicode chars
4738 in single width;
4739 According to change log, this could have been fixed in:
4740 4.4: rewrote handling of default-char width
4741 8.0: fixed urxvt::strwidth to calculate width in the same way as screen.C
4742 8.1: rewrote handling of default-char width
4743 It does not happen with cygwin rxvt-unicode
4744 (which is not locale-driven).
4745 Check should not be limited to certain versions (e.g. < 810):
4746 - inconsistent behaviour (e.g. cygwin, see above)
4747 - unreliable version detection, e.g. rxvt 7.7 reports to be 9.4
4748 */
4749 /* issue also sometimes occurs with xterm +mk_width,
4750 so the check was moved out (see above)
4751 */
4752 if (rxvt_version > 0) {
4753 if (test_screen_width ("ㄯ") < 18) {
4754 unassigned_single_width = True;
4755 }
4756 }
4757 #endif
4758
4759 /* rxvt sends ESC prefix for Alt-modified escape sequences */
4760 detect_esc_alt = True;
4761 /* disable use of VT100 block graphics on rxvt which does not support them */
4762 if (! utf8_screen) {
4763 /* VT100 block graphics work now with workaround for
4764 missing eA capability (see io.c) */
4765 if (rxvt_version < 300) { /* old (non-Unicode) rxvt */
4766 /* VT100 block graphics depend on font capabilities */
4767 use_ascii_graphics = True;
4768 menu_border_style = 'r';
4769 }
4770 }
4771
4772 if (rxvt_version >= 840) {
4773 use_mouse_anymove_inmenu = True;
4774 }
4775 /* numeric encoding of mouse coordinates since rxvt-unicode 9.10 */
4776 use_mouse_1015 = True;
4777 }
4778
4779 #ifdef debug_graphics
4780 printf ("(tx) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
4781 #endif
4782
4783
4784 /* disable graphics on some CJK terminals */
4785 if (cjk_term && ! use_vt100_block_graphics && ! can_alt_cset) {
4786 use_ascii_graphics = True;
4787 menu_border_style = 'r';
4788 }
4789 #ifdef debug_graphics
4790 printf ("(ct) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
4791 #endif
4792
4793
4794 /* configure line markers */
4795 config_markers ();
4796
4797 /* adjust wide line markers */
4798 if (cjk_width_data_version) {
4799 if (UTF_TAB_marker && iswide (utf8value (UTF_TAB_marker))) {
4800 UTF_TAB_marker = NIL_PTR;
4801 }
4802 if (UTF_TAB0_marker && iswide (utf8value (UTF_TAB0_marker))) {
4803 UTF_TAB0_marker = NIL_PTR;
4804 }
4805 if (UTF_TAB2_marker && iswide (utf8value (UTF_TAB2_marker))) {
4806 UTF_TAB2_marker = NIL_PTR;
4807 }
4808 if (UTF_TABmid_marker && iswide (utf8value (UTF_TABmid_marker))) {
4809 UTF_TABmid_marker = NIL_PTR;
4810 }
4811 }
4812
4813 /* adjust to glyph detection */
4814 if (glyphs && * glyphs) { /* utf8_screen && mintty_version >= 909 */
4815 /*
4816 the check covers misc. configurable alternatives and char. substitutes:
4817 border styles:
4818 border ┌ ┆/╎/┊
4819 - rnd ╭
4820 - fat ┏ ╏/┇/┋
4821 - dbl ╔
4822 - cont ◆ ♦ ◈ ⬘ ⬙
4823 - yet unchecked: 9487┏;9556╔;9550╎;9482┊;9551╏;9483┋
4824 markers (additional):
4825 menu • ☛ ☞
4826 tab ․ ‥ … ▷ ▸ ▹ ▻
4827 ret ◀ ◁ ◂ ◃ ◄ ◅
4828 shift tab/ret ⬖ ⬗
4829 special characters:
4830 char ✓ ✗ ↯
4831 */
4832 /* Usage of TAB markers:
4833 TAB0 TAB TAB TAB TAB TAB TAB (TAB2)
4834 TAB TAB TAB TAB TABmid TAB TAB TAB
4835 */
4836 if (! isglyph_utf (UTF_TAB_marker)) {
4837 if (isglyph_code ("8231")) {
4838 UTF_TAB_marker = "‧";
4839 } else {
4840 UTF_TAB_marker = "·";
4841 }
4842 }
4843 if (! isglyph_utf (UTF_TABmid_marker)) {
4844 if (isglyph_code ("8227")) {
4845 UTF_TABmid_marker = "‣";
4846 } else if (isglyph_code ("8702")) {
4847 UTF_TABmid_marker = "⇾";
4848 } else if (isglyph_code ("8594")) {
4849 UTF_TABmid_marker = "→";
4850 } else {
4851 UTF_TABmid_marker = UTF_TAB_marker;
4852 }
4853 }
4854 if (! isglyph_utf (UTF_TAB0_marker)) {
4855 if (UTF_TAB2_marker != NIL_PTR) {
4856 UTF_TAB0_marker = UTF_TAB_marker;
4857 } else {
4858 UTF_TAB0_marker = NIL_PTR;
4859 }
4860 }
4861 if (! isglyph_utf (UTF_TAB2_marker)) {
4862 UTF_TAB2_marker = NIL_PTR;
4863 }
4864
4865 if (! isglyph_utf (UTF_RET_marker)) {
4866 if (isglyph_code ("9166")) {
4867 UTF_RET_marker = "⏎";
4868 } else if (isglyph_code ("8629")) {
4869 UTF_RET_marker = "↵";
4870 } else if (isglyph_code ("8626")) {
4871 UTF_RET_marker = "↲";
4872 } else {
4873 UTF_RET_marker = "«";
4874 }
4875 }
4876 if (! isglyph_utf (UTF_RETfill_marker)) {
4877 UTF_RETfill_marker = "";
4878 }
4879 if (! isglyph_utf (UTF_RETfini_marker)) {
4880 UTF_RETfini_marker = "";
4881 }
4882 if (! isglyph_utf (UTF_DOSRET_marker)) {
4883 UTF_DOSRET_marker = UTF_RET_marker;
4884 }
4885 if (! isglyph_utf (UTF_MACRET_marker)) {
4886 UTF_MACRET_marker = UTF_RET_marker;
4887 }
4888 if (UTF_PARA_marker && ! isglyph_utf (UTF_PARA_marker)) {
4889 UTF_PARA_marker = NIL_PTR;
4890 }
4891
4892 if (! isglyph_utf (UTF_SHIFT_marker)) {
4893 UTF_SHIFT_marker = "»";
4894 }
4895 if (! isglyph_utf (UTF_SHIFT_BEG_marker)) {
4896 UTF_SHIFT_BEG_marker = "«";
4897 }
4898
4899 if (! isglyph_utf (UTF_MENU_marker)) {
4900 if (isglyph_code ("10003")) {
4901 UTF_MENU_marker = "✓";
4902 } else if (isglyph_utf (UTF_MENU_marker_alt)) {
4903 UTF_MENU_marker = UTF_MENU_marker_alt;
4904 } else {
4905 UTF_MENU_marker = "»";
4906 }
4907 }
4908 if (! isglyph_utf (submenu_marker)) {
4909 submenu_marker = submenu_marker_alt;
4910 if (! isglyph_utf (submenu_marker)) {
4911 submenu_marker = "»";
4912 }
4913 }
4914
4915 /* menu scrolling indications */
4916 if (! isglyph_utf (menu_cont_marker)) {
4917 if (isglyph_code ("9830")) {
4918 menu_cont_marker = "♦";
4919 } else {
4920 menu_cont_marker = "│";
4921 }
4922 }
4923 if (! isglyph_utf (menu_cont_fatmarker)) {
4924 if (isglyph_code ("9830")) {
4925 menu_cont_fatmarker = "♦";
4926 } else {
4927 menu_cont_fatmarker = "┃";
4928 }
4929 }
4930 } else if (very_limited_marker_font) {
4931 glyphs = ""; /* pretend all checked glyphs unavailable */
4932 }
4933
4934
4935 /* setup terminal modes */
4936 /* call raw_mode again (was already called for initial tty configuration) */
4937 raw_mode (True);
4938
4939
4940 /* terminal height adjustment / detection
4941 - deprecated section, see checkwinsize ()
4942 terminal control codes useful here:
4943 ESC[<n>t (n>=24) resize to n lines
4944 ESC[18t report size of text area as ESC[8;<height>;<width>t
4945 ESC[8;<height>;<width>t resize text area
4946 */
4947 if (ansi_esc) {
4948 #ifdef adjust_terminal_height /* obsolete */
4949 if (strisprefix ("xterm", TERM) && konsole_version <= 0) {
4950 /* try to adjust the window to the size the tty assumes;
4951 workaround for buggy Cygwin/X xterm tty size assumption,
4952 also workaround for various rlogin/telnet size confusions;
4953 also workaround for false explicit stty rows settings
4954 */
4955 char resizebuf [19];
4956 int height = YMAX + 1 + MENU;
4957 #ifdef adjust_lines_only
4958 if (height >= 24 && rxvt_version <= 0) {
4959 /* this short form doesn't work with rxvt
4960 (which would become extra large)
4961 */
4962 build_string (resizebuf, "\033[%dt", height);
4963 # ifdef debug_terminal_resize
4964 printf ("setting terminal to %d lines\n", height);
4965 # endif
4966 } else {
4967 build_string (resizebuf, "\033[8;%d;%dt", height, XMAX + 1);
4968 # ifdef debug_terminal_resize
4969 printf ("setting terminal to %dx%d\n", height, XMAX + 1);
4970 # endif
4971 }
4972 #else
4973 build_string (resizebuf, "\033[8;%d;%dt", height, XMAX + 1);
4974 # ifdef debug_terminal_resize
4975 printf ("setting terminal to %dx%d\n", height, XMAX + 1);
4976 # endif
4977 #endif
4978 putescape (resizebuf);
4979 }
4980 #else
4981 #ifdef adjust_to_actual_termsize
4982 unsigned long c;
4983 /* response will be handled by ANSIseq */
4984 putescape ("\033[18t"); /* long timeout if response disabled? */
4985 # ifdef debug_terminal_resize
4986 printf ("requesting terminal size\n");
4987 # endif
4988 flush ();
4989 #endif
4990 #endif
4991 }
4992 }
4993
4994
4995 /*======================================================================*\
4996 |* Setup misc stuff *|
4997 \*======================================================================*/
4998
4999 /**
5000 generate names of paste, spool, panic files
5001 */
5002 static
5003 void
setup_temp_filenames()5004 setup_temp_filenames ()
5005 {
5006 char * temp_dir;
5007 char temp_dn [maxFILENAMElen];
5008 char * minedtemp_dir;
5009 char * username = envvar ("MINEDUSER");
5010 if (! username) {
5011 username = getusername ();
5012 }
5013
5014 #ifdef unix
5015 temp_dir = envvar ("TMPDIR");
5016 if (temp_dir == NIL_PTR || temp_dir [0] == '\0' || access (temp_dir, W_OK | X_OK) < 0) {
5017 temp_dir = envvar ("TMP");
5018 }
5019 if (temp_dir == NIL_PTR || temp_dir [0] == '\0' || access (temp_dir, W_OK | X_OK) < 0) {
5020 temp_dir = envvar ("TEMP");
5021 }
5022 if (temp_dir == NIL_PTR || temp_dir [0] == '\0' || access (temp_dir, W_OK | X_OK) < 0) {
5023 /* the less volatile traditional tmp dir (often link to /var/tmp) */
5024 temp_dir = "/usr/tmp";
5025 }
5026 if (access (temp_dir, W_OK | X_OK) < 0) {
5027 temp_dir = "/tmp";
5028 }
5029 if (access (temp_dir, W_OK | X_OK) < 0) {
5030 /* in case there is no $TMP, no /tmp etc (e.g. Android): */
5031 temp_dir = gethomedir ();
5032 }
5033
5034 strcpy (temp_dn, temp_dir);
5035 strip_trailingslash (temp_dn);
5036 temp_dir = temp_dn;
5037
5038 /* prefer $MINEDTMP for buffer and spool files (but not for panic files) */
5039 minedtemp_dir = envvar ("MINEDTMP");
5040 if (minedtemp_dir == NIL_PTR || minedtemp_dir [0] == '\0' || access (minedtemp_dir, W_OK | X_OK) < 0) {
5041 minedtemp_dir = temp_dir;
5042 }
5043
5044 build_string (panic_file, "%s/minedrecover.%s.%d", temp_dir, username, (int) getpid ());
5045 build_string (yankie_file, "%s/mined.%s", minedtemp_dir, username);
5046 build_string (spool_file, "%s/minedprint.%s.%d", minedtemp_dir, username, (int) getpid ());
5047 #endif
5048 #ifdef vms
5049 if (envvar ("SYS$SCRATCH")) {
5050 temp_dir = "SYS$SCRATCH";
5051 } else {
5052 temp_dir = "SYS$LOGIN";
5053 }
5054
5055 /* prefer $MINEDTMP for buffer and spool files (but not for panic files) */
5056 if (envvar ("SYS$MINEDTMP")) {
5057 minedtemp_dir = "SYS$MINEDTMP";
5058 } else {
5059 minedtemp_dir = temp_dir;
5060 }
5061
5062 build_string (panic_file, "%s:$MINEDRECOVER$%s$%d", temp_dir, username, getpid ());
5063 build_string (yankie_file, "%s:$MINED$%s", minedtemp_dir, username);
5064 build_string (spool_file, "%s:$MINEDPRINT$%s$%d", minedtemp_dir, username, getpid ());
5065 #endif
5066 #ifdef msdos
5067 temp_dir = envvar ("TEMP");
5068 if (temp_dir == NIL_PTR || temp_dir [0] == '\0') {
5069 temp_dir = envvar ("TMP");
5070 }
5071 if (temp_dir == NIL_PTR || temp_dir [0] == '\0') {
5072 temp_dir = "\\";
5073 }
5074
5075 /* prefer %MINEDTMP% for buffer and spool files (but not for panic files) */
5076 minedtemp_dir = envvar ("MINEDTMP");
5077 if (minedtemp_dir == NIL_PTR || minedtemp_dir [0] == '\0') {
5078 minedtemp_dir = temp_dir;
5079 }
5080
5081 build_string (panic_file, "%s\\$minedsv_%s", temp_dir, username);
5082 build_string (yankie_file, "%s\\$minedbf_%s", minedtemp_dir, username);
5083 build_string (spool_file, "%s\\$minedpr_%s", minedtemp_dir, username);
5084 #endif
5085 }
5086
5087
5088 /*======================================================================*\
5089 |* Main *|
5090 \*======================================================================*/
5091
5092 void
emul_mined()5093 emul_mined ()
5094 {
5095 int i;
5096
5097 for (i = 0; i < 32; i ++) {
5098 key_map [i] = mined_key_map [i];
5099 }
5100 key_map [erase_char] = DPC;
5101 quit_char = '\034';
5102
5103 emulation = 'm';
5104 shift_selection = False;
5105 visselect_autocopy = True;
5106 visselect_copydeselect = True;
5107 visselect_autodelete = False;
5108
5109 emacs_buffer = False;
5110 paste_stay_left = False;
5111 JUSmode = 0;
5112 }
5113
5114 void
emul_emacs()5115 emul_emacs ()
5116 {
5117 int i;
5118
5119 for (i = 0; i < 32; i ++) {
5120 key_map [i] = emacs_key_map [i];
5121 }
5122 key_map [erase_char] = DPC;
5123 quit_char = '\007'; /* ^G */
5124
5125 emulation = 'e';
5126 shift_selection = False;
5127 visselect_autocopy = True;
5128 visselect_copydeselect = True;
5129 visselect_autodelete = False;
5130
5131 emacs_buffer = True;
5132 paste_stay_left = False;
5133 JUSmode = 1;
5134 }
5135
5136 void
emul_WordStar()5137 emul_WordStar ()
5138 {
5139 int i;
5140
5141 for (i = 0; i < 32; i ++) {
5142 key_map [i] = ws_key_map [i];
5143 }
5144 key_map [erase_char] = DPC;
5145 quit_char = '\034';
5146
5147 emulation = 's';
5148 shift_selection = True;
5149 visselect_autocopy = False;
5150 visselect_copydeselect = False;
5151 visselect_autodelete = True;
5152
5153 emacs_buffer = False;
5154 paste_stay_left = True;
5155 JUSmode = 0;
5156 }
5157
5158 void
emul_Windows()5159 emul_Windows ()
5160 {
5161 int i;
5162
5163 for (i = 0; i < 32; i ++) {
5164 key_map [i] = windows_key_map [i];
5165 }
5166 key_map [erase_char] = DPC;
5167 quit_char = '\034';
5168
5169 emulation = 'w';
5170 shift_selection = True;
5171 visselect_autocopy = False;
5172 visselect_copydeselect = False;
5173 visselect_autodelete = True;
5174
5175 emacs_buffer = False;
5176 paste_stay_left = False;
5177 JUSmode = 0;
5178 }
5179
5180 void
emul_pico()5181 emul_pico ()
5182 {
5183 int i;
5184
5185 for (i = 0; i < 32; i ++) {
5186 key_map [i] = pico_key_map [i];
5187 }
5188 key_map [erase_char] = DPC;
5189 quit_char = '\034';
5190
5191 emulation = 'p';
5192 shift_selection = True;
5193 visselect_autocopy = False;
5194 visselect_copydeselect = False;
5195 visselect_autodelete = True;
5196
5197 emacs_buffer = True;
5198 paste_stay_left = False;
5199 JUSmode = 1;
5200 }
5201
5202 void
set_keypad_mined()5203 set_keypad_mined ()
5204 {
5205 keypad_mode = 'm';
5206 shift_selection = False;
5207 visselect_autocopy = True;
5208 visselect_copydeselect = True;
5209 visselect_autodelete = False;
5210 }
5211
5212 void
set_keypad_shift_selection()5213 set_keypad_shift_selection ()
5214 {
5215 keypad_mode = 'S';
5216 shift_selection = UNSURE;
5217 visselect_copydeselect = True;
5218 visselect_autocopy = False;
5219 visselect_autodelete = True;
5220 }
5221
5222 void
set_keypad_windows()5223 set_keypad_windows ()
5224 {
5225 keypad_mode = 'w';
5226 shift_selection = True;
5227 visselect_copydeselect = False;
5228 visselect_autocopy = False;
5229 visselect_autodelete = True;
5230 }
5231
5232
5233 /*
5234 check if string w matches initial words of string s (esp. a locale prefix)
5235 "ti" "ti_ER" -> True
5236 "ti" "tig_ER" -> False
5237 "ti_ER" "ti_ER.UTF-8" -> True
5238 "aa_E*" "aa_ER" -> True
5239 */
5240 static
5241 FLAG
matchwords(w,s)5242 matchwords (w, s)
5243 char * w;
5244 char * s;
5245 {
5246 if (strisprefix (w, s)) {
5247 char fini = s [strlen (w)];
5248 if ((fini >= 'A' && fini <= 'Z') || (fini >= 'a' && fini <= 'z')) {
5249 return False;
5250 } else {
5251 return True;
5252 }
5253 } else if (w [strlen (w) - 1] == '*' && strncmp (s, w, strlen (w) - 1) == 0) {
5254 return True;
5255 } else {
5256 return False;
5257 }
5258 }
5259
5260 static
5261 FLAG
set_charmap_2(term,charmap_term,charmap_text)5262 set_charmap_2 (term, charmap_term, charmap_text)
5263 FLAG term;
5264 char * charmap_term;
5265 char * charmap_text;
5266 {
5267 if (term) {
5268 return set_term_encoding (charmap_term, ' ');
5269 } else {
5270 return set_text_encoding (charmap_text, ' ', "set_charmap_2");
5271 }
5272 }
5273
5274 static
5275 FLAG
set_charmap(term,charmap)5276 set_charmap (term, charmap)
5277 FLAG term;
5278 char * charmap;
5279 {
5280 if (term) {
5281 return set_term_encoding (charmap, ' ');
5282 } else {
5283 return set_text_encoding (charmap, ' ', "set_charmap");
5284 }
5285 }
5286
5287 #ifdef debug_encoding
5288
5289 static
5290 FLAG
do_set_charmap_2(function,line,term,charmap_term,charmap_text)5291 do_set_charmap_2 (function, line, term, charmap_term, charmap_text)
5292 char * function;
5293 unsigned int line;
5294 FLAG term;
5295 char * charmap_term;
5296 char * charmap_text;
5297 {
5298 if (term) {
5299 printf ("set_charmap [%s:%d] %s\n", function, line, charmap_term);
5300 }
5301 return set_charmap_2 (term, charmap_term, charmap_text);
5302 }
5303
5304 #define set_charmap(term, charmap) do_set_charmap_2 (__FUNCTION__, __LINE__, term, charmap, charmap)
5305 #define set_charmap_2(term, charmap_term, charmap_text) do_set_charmap_2 (__FUNCTION__, __LINE__, term, charmap_term, charmap_text)
5306
5307 #endif
5308
5309 static
5310 struct {
5311 char * locale;
5312 char * quotes;
5313 char * altquotes;
5314 } quotestyles [] = {
5315 #include "quotes.t"
5316 };
5317
5318 static
5319 void
set_quote_styles(style,altstyle)5320 set_quote_styles (style, altstyle)
5321 char * style;
5322 char * altstyle;
5323 {
5324 set_quote_style (altstyle);
5325 prev_quote_type = quote_type;
5326 set_quote_style (style);
5327 }
5328
5329 void
handle_locale_quotes(lang,alt)5330 handle_locale_quotes (lang, alt)
5331 char * lang;
5332 FLAG alt;
5333 {
5334 int i;
5335 char * style = "“”";
5336 char * altstyle = NIL_PTR;
5337
5338 if (! lang) {
5339 (void) locale_text_encoding ();
5340 lang = language_code;
5341 if (alt == UNSURE && language_preference) {
5342 /* enable smart quotes if using LANGUAGE= or TEXTLANG= */
5343 smart_quotes = VALID;
5344 alt = False;
5345 }
5346 }
5347
5348 for (i = 0; i < arrlen (quotestyles); i ++) {
5349 if (matchwords (quotestyles [i].locale, lang)) {
5350 style = quotestyles [i].quotes;
5351 altstyle = quotestyles [i].altquotes;
5352 if (strcontains (quotestyles [i].locale, "_")) {
5353 break;
5354 }
5355 }
5356 }
5357
5358 if (alt == UNSURE) {
5359 set_quote_styles ("\"\"", style);
5360 } else if (alt && altstyle != NIL_PTR) {
5361 set_quote_styles (altstyle, style);
5362 } else if (altstyle != NIL_PTR) {
5363 set_quote_styles (style, altstyle);
5364 } else {
5365 set_quote_style (style);
5366 }
5367 default_quote_type = quote_type;
5368
5369 #ifdef dont_set_spacing_here
5370 if (matchwords ("fr", lang) && ! matchwords ("fr_CH", lang)) {
5371 spacing_quotes = True;
5372 }
5373 #endif
5374 }
5375
5376 static
5377 struct {
5378 char * locale;
5379 char * charmap;
5380 char * charmap_text;
5381 } locmaps [] = {
5382 #include "locales.t"
5383 };
5384
5385 static
5386 FLAG
handle_locale_encoding(term,encoding)5387 handle_locale_encoding (term, encoding)
5388 FLAG term;
5389 char * encoding;
5390 {
5391 /* determine language-specific text handling features */
5392 if (! term) {
5393 if (matchwords ("de", language_code)) {
5394 language_tag = 'g';
5395 } else if (matchwords ("da", language_code)) {
5396 language_tag = 'd';
5397 } else if (matchwords ("fr", language_code)) {
5398 language_tag = 'f';
5399 } else if (matchwords ("tr", language_code)
5400 || matchwords ("az", language_code)
5401 /* https://bugzilla.mozilla.org/show_bug.cgi?id=231162#c17 */
5402 || matchwords ("crh", language_code)
5403 || matchwords ("tt", language_code)
5404 || matchwords ("ba", language_code)
5405 ) {
5406 language_tag = 't';
5407 } else if (matchwords ("lt", language_code)) {
5408 language_tag = 'l';
5409 } else if (matchwords ("nl", language_code)) {
5410 language_tag = 'n'; /* -> cap. IJsselmeer */
5411 }
5412 }
5413
5414 /* detect encoding by locale suffix;
5415 if there is no encoding suffix (starting after "."),
5416 as a fallback, try to interpret the country suffix
5417 (starting with '_' as returned by the functions above)
5418 */
5419 if (strisprefix ("GB", encoding)
5420 || strisprefix ("gb", encoding)
5421 || strisprefix ("EUC-CN", encoding)
5422 || strisprefix ("euccn", encoding)
5423 || strisprefix ("eucCN", encoding)
5424 ) {
5425 return set_charmap (term, "GB");
5426 } else if (strisprefix ("BIG5", encoding)
5427 || strisprefix ("Big5", encoding)
5428 || strisprefix ("big5", encoding)
5429 ) {
5430 return set_charmap (term, "Big5");
5431 } else if (strisprefix ("EUC-TW", encoding)
5432 || strisprefix ("euctw", encoding)
5433 || strisprefix ("eucTW", encoding)
5434 ) {
5435 return set_charmap (term, "CNS");
5436 } else if (strisprefix ("UHC", encoding)
5437 || strisprefix ("EUC-KR", encoding)
5438 || strisprefix ("euckr", encoding)
5439 || strisprefix ("eucKR", encoding)
5440 ) {
5441 return set_charmap (term, "UHC");
5442 } else if (strisprefix ("EUC-JP", encoding)
5443 || strisprefix ("eucjp", encoding)
5444 || strisprefix ("eucJP", encoding)
5445 || strisprefix ("ujis", encoding)
5446 ) {
5447 return set_charmap (term, "EUC-JP");
5448 } else if (strisprefix ("Shift_JIS", encoding)
5449 || strisprefix ("shiftjis", encoding)
5450 || strisprefix ("sjis", encoding)
5451 || strisprefix ("SJIS", encoding)
5452 ) {
5453 return set_charmap (term, "CP932");
5454 } else if (strisprefix ("JOHAB", encoding)) {
5455 return set_charmap (term, "Johab");
5456
5457 } else if (strisprefix ("@euro", encoding)) {
5458 if (matchwords ("fy_NL", language_code)) {
5459 return set_charmap (term, "UTF-8");
5460 } else if (matchwords ("hsb_DE", language_code)) {
5461 return set_charmap (term, "ISO-8859-2");
5462 } else {
5463 return set_charmap (term, "ISO-8859-15");
5464 }
5465 } else if (strisprefix ("@tradicional", encoding)) {
5466 return set_charmap (term, "ISO-8859-15");
5467 } else if (strisprefix ("@devanagari", encoding)) {
5468 return set_charmap (term, "UTF-8");
5469 } else if (strisprefix ("@latin", encoding)) {
5470 return set_charmap (term, "UTF-8");
5471 } else if (strisprefix ("@cyrillic", encoding)) {
5472 if (matchwords ("uz_UZ", language_code)) {
5473 return set_charmap (term, "UTF-8");
5474 } else {
5475 return set_charmap (term, "ISO-8859-5");
5476 }
5477 } else if (strisprefix ("@iqtelif", encoding)) {
5478 return set_charmap (term, "UTF-8");
5479 } else if (strisprefix ("iso8859", encoding)
5480 || strisprefix ("ISO8859", encoding)
5481 || strisprefix ("iso-8859", encoding)
5482 || strisprefix ("ISO-8859", encoding)
5483 ) {
5484 if (encoding [3] == '-') {
5485 encoding += 8;
5486 } else {
5487 encoding += 7;
5488 }
5489 if (* encoding == '-' || * encoding == '_') {
5490 encoding ++;
5491 }
5492 if (streq ("1", encoding)) {
5493 return set_charmap (term, "ISO-8859-1");
5494 } else if (streq ("5", encoding)) {
5495 return set_charmap (term, "ISO-8859-5");
5496 } else if (streq ("6", encoding)) {
5497 return set_charmap_2 (term, "ISO-8859-6", "MacArabic");
5498 } else if (streq ("7", encoding)) {
5499 return set_charmap (term, "ISO-8859-7");
5500 } else if (streq ("8", encoding)) {
5501 return set_charmap_2 (term, "ISO-8859-8", "CP1255");
5502 } else if (streq ("15", encoding)) {
5503 return set_charmap (term, "ISO-8859-15");
5504
5505 } else if (streq ("2", encoding)) {
5506 return set_charmap (term, "ISO-8859-2");
5507 } else if (streq ("3", encoding)) {
5508 return set_charmap (term, "ISO-8859-3");
5509 } else if (streq ("4", encoding)) {
5510 return set_charmap (term, "ISO-8859-4");
5511 } else if (streq ("9", encoding)) {
5512 return set_charmap (term, "ISO-8859-9");
5513 } else if (streq ("10", encoding)) {
5514 return set_charmap (term, "ISO-8859-10");
5515 } else if (streq ("13", encoding)) {
5516 return set_charmap (term, "ISO-8859-13");
5517 } else if (streq ("14", encoding)) {
5518 return set_charmap (term, "ISO-8859-14");
5519 } else if (streq ("16", encoding)) {
5520 return set_charmap (term, "ISO-8859-16");
5521 } else if (streq ("11", encoding)) {
5522 return set_charmap (term, "TIS");
5523 }
5524 } else if (strisprefix ("koi8t", encoding)) {
5525 return set_charmap (term, "KOI8-T");
5526 } else if (strisprefix ("KOI8-T", encoding)) {
5527 return set_charmap (term, "KOI8-T");
5528 } else if (strisprefix ("koi8r", encoding)) {
5529 return set_charmap_2 (term, "KOI8-R", "KOI8-RU");
5530 } else if (strisprefix ("KOI8-R", encoding)) {
5531 return set_charmap_2 (term, "KOI8-R", "KOI8-RU");
5532 } else if (strisprefix ("koi8u", encoding)) {
5533 return set_charmap_2 (term, "KOI8-U", "KOI8-RU");
5534 } else if (strisprefix ("KOI8-U", encoding)) {
5535 return set_charmap_2 (term, "KOI8-U", "KOI8-RU");
5536 } else if (strisprefix ("koi", encoding)) {
5537 return set_charmap (term, "KOI8-RU");
5538 } else if (strisprefix ("tcvn", encoding)) {
5539 return set_charmap (term, "TCVN");
5540 } else if (strisprefix ("viscii", encoding)) {
5541 return set_charmap (term, "VISCII");
5542 } else if (strisprefix ("tis", encoding)
5543 || strisprefix ("TIS", encoding)
5544 ) {
5545 return set_charmap (term, "TIS");
5546 } else if (strisprefix ("roman", encoding)) {
5547 return set_charmap (term, "MacRoman");
5548 } else if (strisprefix ("cp1252", encoding)
5549 || strisprefix ("CP1252", encoding)
5550 ) {
5551 return set_charmap (term, "CP1252");
5552 } else if (strisprefix ("cp1251", encoding)
5553 || strisprefix ("CP1251", encoding)
5554 ) {
5555 return set_charmap (term, "CP1251");
5556 } else if (strisprefix ("cp850", encoding)
5557 || strisprefix ("CP850", encoding)
5558 ) {
5559 return set_charmap (term, "CP850");
5560 } else if (strisprefix ("cp1255", encoding)
5561 || strisprefix ("CP1255", encoding)
5562 ) {
5563 return set_charmap (term, "CP1255");
5564 } else if (strisprefix ("cp1131", encoding)
5565 || strisprefix ("CP1131", encoding)
5566 ) {
5567 return set_charmap (term, "CP1131");
5568 } else if (strisprefix ("georgianps", encoding)) {
5569 return set_charmap (term, "Georgian-PS");
5570 } else if (strisprefix ("pt154", encoding)) {
5571 return set_charmap (term, "PT154");
5572 } else if (strisprefix ("armscii", encoding)
5573 || strisprefix ("ARMSCII", encoding)
5574 ) {
5575 return set_charmap (term, "ARMSCII");
5576 } else if (strisprefix ("utf8", encoding)
5577 || strisprefix ("UTF-8", encoding)
5578 ) {
5579 return set_charmap (term, "UTF-8");
5580
5581 } else if (strisprefix ("EBCDIC", encoding)
5582 || strisprefix ("cp1047", encoding)
5583 || strisprefix ("CP1047", encoding)
5584 ) {
5585 return set_charmap (term, "CP1047");
5586
5587 } else if (streq ("EUC", encoding)
5588 || strisprefix ("euc", encoding)
5589 ) {
5590 if (strisprefix ("zh_TW", language_code)) {
5591 return set_charmap (term, "CNS");
5592 } else if (strisprefix ("zh", language_code)) {
5593 return set_charmap (term, "GB");
5594 } else if (strisprefix ("ja", language_code)) {
5595 return set_charmap (term, "EUC-JP");
5596 } else if (strisprefix ("ko", language_code)) {
5597 return set_charmap (term, "EUC-KR");
5598 }
5599
5600 } else if (encoding [0] != '\0' && set_charmap (term, encoding)) {
5601 /* has been set to other encoding suffix */
5602 } else {
5603 /* handle locale shortcut names that imply an encoding */
5604 int i;
5605 for (i = arrlen (locmaps) - 1; i >= 0; i --) {
5606 if (matchwords (locmaps [i].locale, language_code)) {
5607 if (! term && locmaps [i].charmap_text) {
5608 return set_charmap (False, locmaps [i].charmap_text);
5609 } else {
5610 return set_charmap (term, locmaps [i].charmap);
5611 }
5612 }
5613 }
5614 }
5615
5616 return False;
5617 }
5618
5619
5620 static
5621 void
eval_options(minedopt,command_line)5622 eval_options (minedopt, command_line)
5623 char * minedopt;
5624 FLAG command_line;
5625 {
5626 FLAG plus_opt = False; /* set if options start with '+' */
5627 FLAG Cflag = False; /* -C interacts with -E for compatibility */
5628
5629 while (* minedopt != '\0') {
5630 switch (* minedopt) {
5631 case '+':
5632 plus_opt = True;
5633 break;
5634 case '-':
5635 plus_opt = False;
5636 minedopt ++;
5637 if (* minedopt == '-') {
5638 restricted = True;
5639 } else {
5640 minedopt --;
5641 }
5642 break;
5643 case ' ':
5644 break;
5645 case 'M':
5646 if (* (minedopt + 1) == ':') {
5647 minedopt ++;
5648 if (plus_opt) {
5649 MENU = 1;
5650 use_file_tabs = True;
5651 } else {
5652 use_file_tabs = False;
5653 }
5654 break;
5655 }
5656 if (plus_opt) {
5657 if (MENU) {
5658 if (quickmenu) {
5659 /*MENU ++;*/
5660 use_file_tabs = True;
5661 }
5662 quickmenu = True;
5663 } else {
5664 MENU = 1;
5665 }
5666 } else {
5667 if (use_file_tabs) {
5668 use_file_tabs = False;
5669 } else if (MENU) {
5670 MENU = 0;
5671 } else {
5672 quickmenu = False;
5673 }
5674 }
5675 break;
5676 case 'H':
5677 mark_HTML = plus_opt;
5678 break;
5679 case '@':
5680 if (plus_opt) {
5681 groom_stat = True;
5682 } else {
5683 groom_info_files = False;
5684 groom_info_file = False;
5685 }
5686 break;
5687 case '*':
5688 if (plus_opt) {
5689 if (use_mouse) {
5690 /* enable mouse move reporting without button pressed
5691 (for menus) */
5692 if (use_mouse_anymove_inmenu) {
5693 use_mouse_anymove_always = True;
5694 } else {
5695 use_mouse_anymove_inmenu = True;
5696 }
5697 } else {
5698 use_mouse = True;
5699 }
5700 } else {
5701 if (use_mouse_anymove_inmenu) {
5702 /* disable mouse move reporting w/o button */
5703 use_mouse_anymove_inmenu = False;
5704 } else {
5705 /* disable mouse altogether */
5706 use_mouse = False;
5707 }
5708 }
5709 break;
5710 case '~':
5711 minedopt ++;
5712 if (* minedopt == '=') {
5713 minedopt ++;
5714 sethomedir (minedopt);
5715 homedir_selected = True;
5716 while (* minedopt) {
5717 minedopt ++;
5718 }
5719 }
5720 break;
5721 case 'L':
5722 minedopt ++;
5723 minedopt = scan_int (minedopt, & wheel_scroll);
5724 minedopt --;
5725 break;
5726 case 'v':
5727 viewonly_mode = True;
5728 break;
5729 case 'P':
5730 if (plus_opt) {
5731 hide_passwords = False;
5732 } else {
5733 hide_passwords = True;
5734 }
5735 break;
5736 case 'p':
5737 if (plus_opt) {
5738 proportional = True;
5739 } else {
5740 paradisp = True;
5741 }
5742 break;
5743 case 'r':
5744 minedopt ++;
5745 if (* minedopt == '?') {
5746 if (plus_opt) { /* +r? CRLF for new files */
5747 newfile_lineend = lineend_CRLF;
5748 } else { /* -r? LF for new files */
5749 newfile_lineend = lineend_LF;
5750 }
5751 } else {
5752 minedopt --;
5753 if (plus_opt) { /* +r convert LF to CRLF */
5754 lineends_LFtoCRLF = True;
5755 } else { /* -r convert CRLF to LF */
5756 lineends_CRLFtoLF = True;
5757 }
5758 }
5759 break;
5760 case 'R':
5761 if (plus_opt) { /* +R handle CR */
5762 lineends_detectCR = True;
5763 } else { /* -R convert CR to LF */
5764 lineends_detectCR = True;
5765 lineends_CRtoLF = True;
5766 }
5767 break;
5768 case 'Q':
5769 minedopt ++;
5770 if (* minedopt >= '0' && * minedopt <= '9') {
5771 if (plus_opt) {
5772 splash_level = * minedopt - '0';
5773 } else {
5774 menumargin = * minedopt - '0';
5775 }
5776 } else if (* minedopt == 'Q') {
5777 explicit_selection_style = command_line;
5778 use_stylish_menu_selection = True;
5779 } else if (* minedopt == 'q') {
5780 explicit_selection_style = command_line;
5781 use_stylish_menu_selection = False;
5782 } else if (* minedopt == 'a') {
5783 explicit_border_style = command_line;
5784 use_ascii_graphics = True;
5785 use_vt100_block_graphics = False;
5786 menu_border_style = 'r';
5787 } else if (* minedopt == 'v') {
5788 explicit_border_style = command_line;
5789 use_vt100_block_graphics = True;
5790 use_ascii_graphics = False;
5791 } else if (* minedopt == 'p' || * minedopt == 'P') {
5792 menu_border_style = * minedopt;
5793 explicit_border_style = command_line;
5794 } else if (* minedopt == 'b') {
5795 full_menu_bg = False;
5796 } else if (* minedopt == 'B') {
5797 full_menu_bg = True;
5798 if (menu_border_style == '@') {
5799 menu_border_style = 'p';
5800 }
5801 } else {
5802 menu_border_style = * minedopt;
5803 if (menu_border_style != 'd') {
5804 explicit_border_style = command_line;
5805 }
5806 if (menu_border_style == '@') {
5807 full_menu_bg = False;
5808 }
5809 }
5810 break;
5811 case 'O':
5812 use_script_colour = plus_opt;
5813 break;
5814 case 'f':
5815 if (menu_border_style == 's') {
5816 if (use_vt100_block_graphics) {
5817 use_ascii_graphics = True;
5818 menu_border_style = 'r'; /* by option */
5819 use_vt100_block_graphics = False;
5820 } else {
5821 use_vt100_block_graphics = True;
5822 }
5823 } else {
5824 menu_border_style = 's';
5825 }
5826 use_stylish_menu_selection = False;
5827 fine_scrollbar = False;
5828 break;
5829 case 'F':
5830 if (plus_opt) {
5831 if (very_limited_marker_font) {
5832 very_limited_marker_font = False;
5833 } else {
5834 limited_marker_font = False;
5835 }
5836 } else {
5837 if (limited_marker_font) {
5838 very_limited_marker_font = True;
5839 } else {
5840 limited_marker_font = True;
5841 }
5842 }
5843 break;
5844 case 'o':
5845 minedopt ++;
5846 explicit_scrollbar_style = command_line;
5847 switch (* minedopt) {
5848 case '0':
5849 disp_scrollbar = False;
5850 scrollbar_width = 0;
5851 break;
5852 case '1':
5853 disp_scrollbar = True;
5854 fine_scrollbar = False;
5855 scrollbar_width = 1;
5856 break;
5857 case '2':
5858 disp_scrollbar = True;
5859 fine_scrollbar = True;
5860 scrollbar_width = 1;
5861 break;
5862 case '8':
5863 update_scrollbar_lazy = False;
5864 break;
5865 case '9':
5866 update_scrollbar_lazy = True;
5867 break;
5868 case 'o':
5869 old_scrollbar_clickmode = True; /* old left/right click semantics */
5870 break;
5871 default:
5872 minedopt --;
5873 /* disable/enable scrollbar */
5874 if (plus_opt) {
5875 disp_scrollbar = True;
5876 scrollbar_width = 1;
5877 } else {
5878 disp_scrollbar = False;
5879 scrollbar_width = 0;
5880 }
5881 }
5882 break;
5883 case 'c':
5884 if (plus_opt) {
5885 combining_screen = True;
5886 combining_mode = True;
5887 combining_screen_selected = True;
5888 } else {
5889 if (combining_mode_disabled) {
5890 combining_screen = False;
5891 } else {
5892 combining_mode = False;
5893 combining_mode_disabled = True;
5894 }
5895 }
5896 break;
5897 case 'C':
5898 if (plus_opt) {
5899 cjk_term = True;
5900 /* output CJK encoded characters transparently */
5901 if (suppress_unknown_cjk) {
5902 suppress_unknown_cjk = False;
5903 } else if (suppress_invalid_cjk) {
5904 suppress_invalid_cjk = False;
5905 } else {
5906 suppress_extended_cjk = False;
5907 }
5908 /* output non-Unicode codes transparently */
5909 suppress_non_BMP = NOT_VALID;
5910 if (suppress_EF) {
5911 suppress_EF = False;
5912 } else if (suppress_surrogates) {
5913 suppress_surrogates = False;
5914 } else {
5915 suppress_non_Unicode = False;
5916 }
5917 } else {
5918 Cflag = True;
5919 }
5920 break;
5921 case 'U':
5922 if (plus_opt) {
5923 if (U_mode_set) {
5924 bidi_screen = True;
5925 joining_screen = True;
5926 poormansbidi = False;
5927 /* disable scrollbar to prevent interference */
5928 disp_scrollbar = False;
5929 scrollbar_width = 0;
5930 } else {
5931 utf8_screen = True;
5932 utf8_input = True;
5933 combining_screen = True;
5934 combining_mode = True;
5935 U_mode_set = True;
5936 cjk_term = False;
5937 mapped_term = False;
5938 }
5939 } else if (bidi_screen) {
5940 joining_screen = False;
5941 } else if (utf8_input) {
5942 utf8_screen = False;
5943 utf8_input = False;
5944 combining_screen = False;
5945 combining_mode = False;
5946 } else {
5947 utf8_screen = True;
5948 utf8_input = True;
5949 combining_screen = True;
5950 combining_mode = True;
5951 cjk_term = False;
5952 mapped_term = False;
5953 }
5954 break;
5955 case 'u':
5956 auto_detect = False;
5957 if (plus_opt) {
5958 (void) set_text_encoding (NIL_PTR, 'L', "+u");
5959 utf8_lineends = False;
5960 } else {
5961 (void) set_text_encoding (NIL_PTR, 'U', "-u");
5962 text_encoding_selected = True;
5963 }
5964 break;
5965 case 'l':
5966 auto_detect = False;
5967 (void) set_text_encoding (NIL_PTR, 'L', "-l");
5968 text_encoding_selected = True;
5969 break;
5970 case 'E':
5971 minedopt ++;
5972 if (* minedopt == '?') {
5973 if (plus_opt) {
5974 only_detect_terminal_encoding = True;
5975 } else {
5976 only_detect_text_encoding = True;
5977 }
5978 } else if (* minedopt == 'u') {
5979 pastebuf_utf8 = True;
5980 } else if (* minedopt == 'U' || * minedopt == 'L') {
5981 if (plus_opt) {
5982 cjk_term = False;
5983 mapped_term = False;
5984 if (* minedopt == 'U') {
5985 utf8_screen = True;
5986 utf8_input = True;
5987 combining_screen = True;
5988 combining_mode = True;
5989 } else {
5990 utf8_screen = False;
5991 utf8_input = False;
5992 combining_screen = False;
5993 combining_mode = False;
5994 }
5995 cjk_term = False;
5996 mapped_term = False;
5997 term_encoding_selected = True;
5998 } else {
5999 if (set_text_encoding (NIL_PTR, * minedopt, "-EU/L")) {
6000 auto_detect = False;
6001 text_encoding_selected = True;
6002 }
6003 }
6004 } else if (* minedopt == '.') {
6005 minedopt ++;
6006 if (handle_locale_encoding (plus_opt, minedopt)) {
6007 if (plus_opt) {
6008 term_encoding_selected = True;
6009 } else {
6010 auto_detect = False;
6011 text_encoding_selected = True;
6012 }
6013 } else {
6014 if (plus_opt) {
6015 errprintf ("Unknown terminal encoding %s\n", minedopt);
6016 } else {
6017 errprintf ("Unknown text encoding %s\n", minedopt);
6018 }
6019 sleep (1);
6020
6021 }
6022 while (* minedopt) {
6023 minedopt ++;
6024 }
6025 } else if (* minedopt == '=') {
6026 minedopt ++;
6027 if (set_charmap (plus_opt, minedopt)) {
6028 if (plus_opt) {
6029 term_encoding_selected = True;
6030 } else {
6031 auto_detect = False;
6032 text_encoding_selected = True;
6033 }
6034 } else {
6035 if (plus_opt) {
6036 errprintf ("Unknown terminal charmap %s\n", minedopt);
6037 } else {
6038 errprintf ("Unknown text charmap %s\n", minedopt);
6039 }
6040 sleep (1);
6041 }
6042 while (* minedopt) {
6043 minedopt ++;
6044 }
6045 } else if (* minedopt == ':') {
6046 if (set_charmap (plus_opt, minedopt)) {
6047 if (plus_opt) {
6048 term_encoding_selected = True;
6049 } else {
6050 auto_detect = False;
6051 text_encoding_selected = True;
6052 }
6053 } else {
6054 if (plus_opt) {
6055 errprintf ("Unknown terminal encoding flag %s\n", minedopt + 1);
6056 } else {
6057 errprintf ("Unknown text encoding flag %s\n", minedopt + 1);
6058 }
6059 sleep (1);
6060 }
6061 minedopt ++;
6062 if (* minedopt) {
6063 minedopt ++;
6064 }
6065 if (* minedopt) {
6066 minedopt ++;
6067 }
6068 } else if (* minedopt == '-' || * minedopt == '\0') {
6069 if (! plus_opt) {
6070 auto_detect = False;
6071 }
6072 } else {
6073 char enctag = * minedopt;
6074 switch (enctag) {
6075 case 'g': if (plus_opt || Cflag) {
6076 gb18030_term = False;
6077 suppress_extended_cjk = True;
6078 }
6079 enctag = 'G';
6080 break;
6081 case 'j': if (plus_opt || Cflag) {
6082 euc3_term = False;
6083 suppress_extended_cjk = True;
6084 }
6085 enctag = 'J';
6086 break;
6087 case 'c': if (plus_opt || Cflag) {
6088 euc4_term = False;
6089 suppress_extended_cjk = True;
6090 }
6091 enctag = 'C';
6092 break;
6093 }
6094 if (plus_opt || Cflag) {
6095 if (set_term_encoding (NIL_PTR, enctag)) {
6096 term_encoding_selected = True;
6097 } else {
6098 errprintf ("Unknown terminal encoding tag %c\n", * minedopt);
6099 sleep (1);
6100 break;
6101 }
6102 }
6103 if (! plus_opt) {
6104 if (set_text_encoding (NIL_PTR, enctag, "-E")) {
6105 auto_detect = False;
6106 text_encoding_selected = True;
6107 } else {
6108 errprintf ("Unknown text encoding tag %c\n", * minedopt);
6109 sleep (1);
6110 break;
6111 }
6112 }
6113 }
6114 break;
6115 case 'b':
6116 if (plus_opt) {
6117 minedopt ++;
6118 if (* minedopt == '-' || * minedopt == 'o') {
6119 backup_mode = '\0';
6120 } else if (* minedopt == '\0') {
6121 backup_mode = 'a';
6122 } else if (* minedopt == '=') {
6123 minedopt ++;
6124 if (minedopt [0] == '~'
6125 && (minedopt [1] == '/' || minedopt [1] == '\0')) {
6126 char expandedname [maxFILENAMElen];
6127 strcpy (expandedname, "");
6128 strappend (expandedname, gethomedir (), maxFILENAMElen);
6129 minedopt ++;
6130 strip_trailingslash (expandedname);
6131 strappend (expandedname, minedopt, maxFILENAMElen);
6132 backup_directory = dupstr (expandedname);
6133 } else {
6134 backup_directory = dupstr (minedopt);
6135 }
6136 return;
6137 } else {
6138 backup_mode = * minedopt;
6139 }
6140 } else {
6141 if (poormansbidi) {
6142 poormansbidi = False;
6143 } else {
6144 poormansbidi = True;
6145 bidi_screen = False;
6146 }
6147 }
6148 break;
6149 case 'z':
6150 /* file chooser sort options */
6151 minedopt ++;
6152 if (* minedopt == 'x') {
6153 sort_by_extension = plus_opt;
6154 } else if (* minedopt == 'd') {
6155 sort_dirs_first = plus_opt;
6156 }
6157 break;
6158 case 'B':
6159 if (plus_opt) {
6160 minedopt ++;
6161 if (* minedopt == 'p') {
6162 plain_BS = True;
6163 }
6164 } else {
6165 /*
6166 key_map ['\010'] = DPC;
6167 key_map ['\177'] = DCC;
6168 */
6169 key_map ['\010'] = LFkey;
6170 key_map ['\177'] = DPC;
6171 }
6172 break;
6173 case 'K':
6174 if (plus_opt) {
6175 /* obsolete since 2000.15 as this is the default */
6176 enforce_keymap = True;
6177 } else {
6178 minedopt ++;
6179 if (* minedopt == '=') {
6180 minedopt ++;
6181 if (setKEYMAP (minedopt)) {
6182 explicit_keymap = True;
6183 } else {
6184 errprintf ("Unknown input method %s\n", minedopt);
6185 sleep (1);
6186 }
6187 return;
6188 } else {
6189 selection_space = * minedopt;
6190 }
6191 }
6192 break;
6193 case '[':
6194 rectangular_paste_flag = plus_opt;
6195 break;
6196 case 'D':
6197 configure_xterm_keyboard = plus_opt;
6198 break;
6199 case 'w':
6200 if (wordnonblank) {
6201 wordnonblank = False;
6202 } else {
6203 wordnonblank = True;
6204 }
6205 break;
6206 case 'Z':
6207 minedopt ++;
6208 switch (* minedopt) {
6209 case '_':
6210 strop_style = * minedopt;
6211 break;
6212 case 'Z':
6213 if (plus_opt) {
6214 lowcapstrop = True;
6215 dispunstrop = True;
6216 } else {
6217 lowcapstrop = False;
6218 dispunstrop = False;
6219 }
6220 strop_selected = True;
6221 break;
6222 }
6223 break;
6224 case 'q':
6225 smart_quotes = VALID;
6226 minedopt ++;
6227 if (* minedopt == '=' || * minedopt == ':') {
6228 minedopt ++;
6229 if (* minedopt >= 'A' && * minedopt <= 'z') {
6230 handle_locale_quotes (minedopt, plus_opt);
6231 } else if (* minedopt) {
6232 set_quote_style (minedopt);
6233 default_quote_type = quote_type;
6234 } else {
6235 handle_locale_quotes (NIL_PTR, plus_opt);
6236 }
6237 return;
6238 } else {
6239 minedopt --;
6240 handle_locale_quotes (NIL_PTR, plus_opt);
6241 }
6242 break;
6243 case 'a':
6244 append_flag = True;
6245 break;
6246 case 'j':
6247 if (plus_opt) {
6248 minedopt ++;
6249 if (* minedopt == '=') {
6250 minedopt ++;
6251 if (* minedopt >= '0' && * minedopt <= '2') {
6252 JUSlevel = * minedopt - '0';
6253 }
6254 } else {
6255 minedopt --;
6256 if (JUSlevel < 2) {
6257 JUSlevel ++;
6258 }
6259 }
6260 } else if (JUSlevel == 1) {
6261 JUSlevel = 2;
6262 } else {
6263 JUSlevel = 1;
6264 }
6265 break;
6266 case 'J':
6267 JUSlevel = 2;
6268 break;
6269 case 'T':
6270 if (plus_opt) {
6271 tab_right = True;
6272 } else {
6273 tab_left = True;
6274 }
6275 break;
6276 case 'V':
6277 minedopt ++;
6278 if (* minedopt == ':' || * minedopt == '=') {
6279 minedopt ++;
6280 if (* minedopt == 'k') {
6281 visselect_keeponsearch = plus_opt;
6282 } else if (* minedopt == 'c') {
6283 visselect_autocopy = plus_opt;
6284 visselect_copydeselect = plus_opt;
6285 }
6286 } else {
6287 minedopt --;
6288 if (plus_opt) {
6289 if (paste_stay_left) {
6290 paste_stay_left = False;
6291 } else {
6292 emacs_buffer = True;
6293 }
6294 } else {
6295 if (! paste_stay_left) {
6296 paste_stay_left = True;
6297 } else {
6298 emacs_buffer = False;
6299 }
6300 }
6301 }
6302 break;
6303 case 's':
6304 page_stay = True;
6305 break;
6306 case 'S':
6307 page_scroll = True;
6308 break;
6309 case 'x':
6310 xprot = exeprot;
6311 break;
6312 case 'X':
6313 use_window_title_query = use_window_title;
6314 use_window_title = plus_opt;
6315 break;
6316 case 'd':
6317 minedopt ++;
6318 if (* minedopt == '-') {
6319 display_delay = -1;
6320 } else if (* minedopt >= '0' && * minedopt <= '9') {
6321 display_delay = (int) * minedopt - (int) '0';
6322 } else {
6323 minedopt --;
6324 }
6325 break;
6326 case '':
6327 minedopt ++;
6328 if (* minedopt >= '0' && * minedopt <= '9') {
6329 cursor_style = (int) * minedopt - (int) '0';
6330 } else {
6331 minedopt --;
6332 }
6333 break;
6334 case '4':
6335 if (! tabsize_selected) {
6336 tabsize = 4;
6337 tabsize_selected = cmdline_selected;
6338 expand_tabs = plus_opt;
6339 }
6340 break;
6341 case '2':
6342 if (! tabsize_selected) {
6343 tabsize = 2;
6344 tabsize_selected = cmdline_selected;
6345 expand_tabs = plus_opt;
6346 }
6347 break;
6348 case '8':
6349 if (! tabsize_selected) {
6350 tabsize = 8;
6351 tabsize_selected = cmdline_selected;
6352 expand_tabs = plus_opt;
6353 }
6354 break;
6355 case '?':
6356 minedopt ++;
6357 if (* minedopt == 'c') { /* enable char info */
6358 if (plus_opt) {
6359 always_disp_code = True;
6360 always_disp_fstat = False;
6361 if (! disp_Han_full) {
6362 always_disp_Han = False;
6363 }
6364 } else {
6365 always_disp_code = False;
6366 }
6367 } else if (* minedopt == 's') { /* enable char/script info */
6368 if (plus_opt) {
6369 disp_scriptname = True;
6370 /* also enable char info: */
6371 always_disp_code = True;
6372 always_disp_fstat = False;
6373 if (! disp_Han_full) {
6374 always_disp_Han = False;
6375 }
6376 } else {
6377 disp_scriptname = False;
6378 }
6379 } else if (* minedopt == 'n') { /* enable char/name info */
6380 if (plus_opt) {
6381 disp_charname = True;
6382 /* also enable char info: */
6383 always_disp_code = True;
6384 always_disp_fstat = False;
6385 if (! disp_Han_full) {
6386 always_disp_Han = False;
6387 }
6388 } else {
6389 disp_charname = False;
6390 }
6391 } else if (* minedopt == 'q') { /* enable named seq info */
6392 if (plus_opt) {
6393 disp_charseqname = True;
6394 /* also enable char info: */
6395 always_disp_code = True;
6396 always_disp_fstat = False;
6397 if (! disp_Han_full) {
6398 always_disp_Han = False;
6399 }
6400 } else {
6401 disp_charseqname = False;
6402 }
6403 } else if (* minedopt == 'd') { /* enable char/decomposition info */
6404 if (plus_opt) {
6405 disp_decomposition = True;
6406 disp_charname = False;
6407 /* also enable char info: */
6408 always_disp_code = True;
6409 always_disp_fstat = False;
6410 if (! disp_Han_full) {
6411 always_disp_Han = False;
6412 }
6413 } else {
6414 disp_decomposition = False;
6415 }
6416 } else if (* minedopt == 'm') { /* enable char/menmos info */
6417 if (plus_opt) {
6418 disp_mnemos = True;
6419 disp_charname = False;
6420 /* also enable char info: */
6421 always_disp_code = True;
6422 always_disp_fstat = False;
6423 if (! disp_Han_full) {
6424 always_disp_Han = False;
6425 }
6426 } else {
6427 disp_mnemos = False;
6428 }
6429 } else if (* minedopt == 'f') { /* enable file info */
6430 if (plus_opt) {
6431 always_disp_fstat = True;
6432 always_disp_code = False;
6433 if (! disp_Han_full) {
6434 always_disp_Han = False;
6435 }
6436 } else {
6437 always_disp_fstat = False;
6438 }
6439 } else if (* minedopt == 'h') { /* enable popup Han info */
6440 if (plus_opt) {
6441 always_disp_Han = True;
6442 disp_Han_full = True;
6443 } else {
6444 disp_Han_full = False;
6445 }
6446 } else if (* minedopt == 'x') { /* enable short Han info */
6447 if (plus_opt) {
6448 always_disp_Han = True;
6449 disp_Han_full = False;
6450 always_disp_fstat = False;
6451 always_disp_code = False;
6452 } else {
6453 always_disp_Han = False;
6454 }
6455 }
6456 break;
6457 case '#':
6458 dark_term = plus_opt;
6459 break;
6460 case 'W':
6461 emul_WordStar ();
6462 break;
6463 case 'e':
6464 if (plus_opt) {
6465 minedopt ++;
6466 switch (* minedopt) {
6467 case 'e': emul_emacs (); break;
6468 case 's': emul_WordStar (); break;
6469 case 'p': emul_pico (); break;
6470 case 'W': newfile_lineend = lineend_CRLF;
6471 prefer_comspec = True;
6472 /*FALLTHROUGH*/
6473 case 'w': emul_Windows (); break;
6474 case 'm': emul_mined (); break;
6475 default: errprintf ("Unknown emulation mode %c\n", * minedopt);
6476 sleep (1);
6477 }
6478 } else {
6479 emul_emacs ();
6480 }
6481 break;
6482 case 'k':
6483 if (plus_opt) {
6484 use_appl_keypad = True;
6485 } else {
6486 minedopt ++;
6487 switch (* minedopt) {
6488 case 'c': small_home_selection = True;
6489 break;
6490 case 'C': home_selection = True;
6491 break;
6492 case 'm': set_keypad_mined ();
6493 break;
6494 case 's':
6495 case 'S': set_keypad_shift_selection ();
6496 break;
6497 case 'w': set_keypad_windows ();
6498 break;
6499 default: minedopt --;
6500 if (mined_keypad) {
6501 mined_keypad = False;
6502 } else {
6503 mined_keypad = True;
6504 }
6505 }
6506 }
6507 break;
6508 case 't': /* deprecated; 2012.21 compatibility */
6509 if (plus_opt) {
6510 if (shift_selection == True) {
6511 set_keypad_shift_selection ();
6512 } else {
6513 set_keypad_windows ();
6514 }
6515 } else {
6516 set_keypad_mined ();
6517 }
6518 break;
6519 case 'n':
6520 minedopt ++;
6521 if (* minedopt == 'c') {
6522 suppress_colour = True;
6523 bw_term = True;
6524 }
6525 break;
6526 case '':
6527 /* viewing mined help file */
6528 viewing_help = True; /* also triggers mark_HTML = True */
6529 viewonly_mode = True;
6530 restricted = True;
6531 ext_status = ++ minedopt;
6532 return;
6533 case '_':
6534 ext_status = ++ minedopt;
6535 return;
6536 case '/':
6537 minedopt ++;
6538 inisearch = minedopt;
6539 return;
6540 case '':
6541 minedopt ++;
6542 if (* minedopt) {
6543 filtering_read = plus_opt;
6544 free_space (filter_read);
6545 filter_read = dupstr (minedopt);
6546 }
6547 return;
6548 case '':
6549 minedopt ++;
6550 if (* minedopt) {
6551 filtering_write = plus_opt;
6552 free_space (filter_write);
6553 filter_write = dupstr (minedopt);
6554 }
6555 return;
6556 default:
6557 errprintf ("Unknown option %c\n", * minedopt);
6558 if (command_line) {
6559 sleep (1);
6560 }
6561 break;
6562 }
6563 if (* minedopt != '\0') {
6564 minedopt ++;
6565 }
6566 }
6567 }
6568
6569
6570 static int mined_argc;
6571 static char * * mined_argv;
6572 static int initlini = 0;
6573
6574 static
6575 int
eval_commandline()6576 eval_commandline ()
6577 {
6578 char * minedopt;
6579 int argi = 1;
6580 FLAG goon = True;
6581
6582 if (mined_argv [0]) {
6583 minedprog = mined_argv [0];
6584 minedopt = strrchr (mined_argv [0], '/');
6585 if (minedopt) {
6586 minedopt ++;
6587 } else {
6588 minedopt = mined_argv [0];
6589 }
6590 if (strisprefix ("r", minedopt)) {
6591 restricted = True;
6592 minedopt ++;
6593 }
6594 if (strisprefix ("minma", minedopt)) {
6595 eval_options ("-e", False);
6596 } else if (strisprefix ("mstar", minedopt)) {
6597 eval_options ("-W", False);
6598 } else if (strisprefix ("mpico", minedopt)) {
6599 emul_pico ();
6600 }
6601 } else {
6602 minedprog = "mined";
6603 }
6604
6605 do {
6606 if (argi < mined_argc) {
6607 if (streq (mined_argv [argi], "++")) {
6608 argi += 1;
6609 goon = False;
6610 } else if (* mined_argv [argi] == '+' && mined_argv [argi] [1] >= '0' && mined_argv [argi] [1] <= '9') {
6611 initlini = argi;
6612 argi += 1;
6613 } else if (* mined_argv [argi] == '-'
6614 || * mined_argv [argi] == '+'
6615 #ifdef msdos
6616 || * mined_argv [argi] == '/'
6617 #endif
6618 )
6619 {
6620 minedopt = mined_argv [argi];
6621 eval_options (minedopt, True);
6622 argi += 1;
6623 } else {
6624 goon = False;
6625 }
6626 } else {
6627 goon = False;
6628 }
6629 } while (goon);
6630
6631 return argi;
6632 }
6633
6634
6635 #ifdef __GNUC__
6636 #define mempoi void *
6637 #else
6638 /* most non-GNU C compilers, following standard C, do not permit
6639 pointer arithmetic on void *
6640 */
6641 #define mempoi char *
6642 #endif
6643
6644 static mempoi prefbuf = 0;
6645 static mempoi prefpoi;
6646 static int prefsaving;
6647 static int preflen = 200;
6648
6649 #define dont_debug_preferences
6650
6651 #ifdef debug_preferences
6652 #define trace_pref(params) printf params
6653 #else
6654 #define trace_pref(params)
6655 #endif
6656
6657 static
6658 void
6659 #ifdef debug_preferences
do_prefmov(varpoi,varsize,varname)6660 do_prefmov (varpoi, varsize, varname)
6661 void * varpoi;
6662 int varsize;
6663 char * varname;
6664 #else
6665 do_prefmov (varpoi, varsize)
6666 void * varpoi;
6667 int varsize;
6668 #endif
6669 {
6670 if (prefsaving) {
6671 if (prefpoi - prefbuf + varsize > preflen) {
6672 #define prefinc 50
6673 mempoi newbuf = realloc (prefbuf, preflen + prefinc);
6674 if (newbuf) {
6675 trace_pref (("realloc %p->%p (%d)\n", prefbuf, newbuf, preflen + prefinc));
6676 prefpoi = newbuf + (prefpoi - prefbuf);
6677 prefbuf = newbuf;
6678 preflen += prefinc;
6679 } else {
6680 trace_pref (("realloc failed\n"));
6681 return;
6682 }
6683 }
6684 memcpy (prefpoi, varpoi, varsize);
6685 trace_pref (("%p:%04X <- %s (%d)\n", prefpoi, * (unsigned int *) prefpoi, varname, varsize));
6686 prefpoi += varsize;
6687 } else {
6688 trace_pref (("%p:%04X -> %s (%d)\n", prefpoi, * (unsigned int *) prefpoi, varname, varsize));
6689 memcpy (varpoi, prefpoi, varsize);
6690 prefpoi += varsize;
6691 }
6692 }
6693
6694 #ifdef debug_preferences
6695 #define prefmov(var) do_prefmov (& var, sizeof (var), #var)
6696 #else
6697 /* stringification (#var) not supported on various systems (e.g. HPUX) */
6698 #define prefmov(var) do_prefmov (& var, sizeof (var))
6699 #endif
6700
6701 static
6702 void
preferences(save_restore)6703 preferences (save_restore)
6704 FLAG save_restore;
6705 {
6706 prefsaving = save_restore != REVERSE;
6707
6708 if (prefsaving && ! prefbuf) {
6709 prefbuf = alloc (preflen);
6710 }
6711 if (! prefbuf) {
6712 return;
6713 }
6714
6715 prefpoi = prefbuf;
6716
6717 prefmov (restricted); /* just to be safe (cannot be toggled) */
6718 prefmov (use_file_tabs);
6719 prefmov (backup_mode);
6720
6721 prefmov (smart_quotes);
6722 prefmov (quote_type);
6723 prefmov (prev_quote_type);
6724 prefmov (wordnonblank);
6725 prefmov (JUSlevel);
6726 prefmov (JUSmode);
6727 prefmov (mark_HTML);
6728 prefmov (mark_JSP);
6729 prefmov (viewonly_mode);
6730 prefmov (lowcapstrop);
6731 prefmov (dispunstrop);
6732 prefmov (strop_style);
6733 prefmov (autoindent);
6734 prefmov (autonumber);
6735 prefmov (backnumber);
6736 prefmov (backincrem);
6737 prefmov (tabsize);
6738 prefmov (tabsize_selected);
6739 prefmov (expand_tabs);
6740 prefmov (hide_passwords);
6741 prefmov (filtering_read);
6742 prefmov (filtering_write);
6743
6744 trace_pref (("preferences (saving %d) length %d\n", prefsaving, prefpoi - prefbuf));
6745 }
6746
6747 static struct {
6748 char * name;
6749 char * eval;
6750 } config_options [] = {
6751 {"tab", "-%s"},
6752 {"tabstop", "-%s"},
6753 {"tabwidth", "-%s"},
6754 {"tabexpand", "-+%s"},
6755 {"rectangular", "+["},
6756 {"square", "+["},
6757 {"emul", "+e%s"},
6758 {"keypad_windows", "-kw"},
6759 {"keypad_shift_selection", "-kS"},
6760 {"keypad_mined", "-km"},
6761 {"home_selection", "-kM"},
6762 {"small_home_selection", "-km"},
6763 {"im_space", "-K%s"},
6764 {"im", "-K=%s"},
6765 {"strop_bold", "+ZZ"},
6766 {"strop_underline", "+ZZZ_"},
6767 {"unicode_paste_buffer", "-Eu"},
6768 {"separated_display", "-c"},
6769 {"backup_mode", "+b%s"},
6770 {"backup_directory", "+b=%s"},
6771 {"file_chooser", "+z%s"},
6772 {"file_tabs", "+M:"},
6773 {"tab_snap", "%sT"},
6774 {"justify", "+j=%s"},
6775 {"display_mac", "+R"},
6776 {"display_paragraphs", "-p"},
6777 {"page_stay", "-s"},
6778 {"paste_stay", "-V"},
6779 {"delete_to_buffer", "+VV"},
6780 {"no_window_title", "-X"},
6781 {"word_skip", "-w"},
6782 {"smart_quotes", "-q=%s"},
6783 {"highlight_html", "+H"},
6784 {"highlight_xml", "+H"},
6785 {"cursor_style", "-%s"},
6786 {"hide_passwords", "-P"},
6787 {"show_passwords", "+P"},
6788 {"sel_keep_on_search", "+V:k"},
6789 {"sel_auto_copy", "+V:c"},
6790 {"display_charinfo", "+?c"},
6791 {"no_display_charinfo", "-?c"},
6792 {"display_script", "+?s"},
6793 {"display_charname", "+?n"},
6794 {"display_namedseq", "+?q"},
6795 {"display_decomposition", "+?d"},
6796 {"display_mnemos", "+?m"},
6797 {"display_fileinfo", "+?f"},
6798 {"display_haninfo_short", "+?x"},
6799 {"display_haninfo_full", "+?h"},
6800 {"plain_BS", "+Bp"},
6801 {"filter_read", "+%s"},
6802 {"filter_write", "+%s"},
6803 {"menu_corners_simple", "-Qs"},
6804 {"menu_corners_round", "-Qr"},
6805 {"menu_borders_fat", "-Qf"},
6806 {"menu_borders_double", "-Qd"},
6807 {"menu_borders_ascii", "-Qa"},
6808 {"menu_borders_vt100", "-Qv"},
6809 {"menu_borders_plain", "-Qp"},
6810 {"menu_borders_none", "-QP"},
6811 {"menu_background", "-QB"},
6812 {"menu_selection_fancy", "-QQ"},
6813 {"menu_selection_plain", "-Qq"},
6814 {"splash_logo", "+Q%s"},
6815 {NIL_PTR}
6816 };
6817
6818 /**
6819 Read and evaluate mined runtime configuration file.
6820 applyall = True: initially evaluate common options
6821 False: apply conditional options only
6822 Preferences management concept:
6823 initially:
6824 configure_preferences (True); ... calling eval_options
6825 ... check various environment preferences
6826 (void) eval_commandline (); ... overriding preset values
6827 preferences (FORWARD); ... saving preferences
6828 load_file:
6829 update_file_name:
6830 configure_preferences (False); ... restoring initial preferences first
6831 preferences (REVERSE); ... restore saved preferences
6832 ... read file name specific preferences
6833 get_open_pos ... override saved file preferences
6834 set_file_type_flags ()
6835 ... deriving generic file specific preferences
6836 configure_preferences (OPEN); ... restore command line options
6837 (void) eval_commandline ();
6838 However, the latter does not work as long as there are
6839 cumulative options, i.e. options that have different effect
6840 if applied multiple times; thus, for now, specific checks
6841 are still needed (e.g. tabsize_selected).
6842 This applies to the following options:
6843 M
6844 *
6845 f
6846 F
6847 c
6848 C
6849 U
6850 -b
6851 w
6852 -j
6853 V
6854 +t
6855 -k (plain)
6856 and possibly to the following guarding flags:
6857 tabsize_selected
6858 strop_selected
6859 explicit_keymap
6860 explicit_border_style
6861 explicit_scrollbar_style
6862 explicit_selection_style
6863 default_quote_type
6864 preselect_quote_style
6865 default_text_encoding
6866 text_encoding_selected
6867 default_lineend
6868 homedir_selected
6869 */
6870 #define dont_debug_confpref
6871 void
configure_preferences(applycommon)6872 configure_preferences (applycommon)
6873 FLAG applycommon;
6874 {
6875 char rcfn [maxFILENAMElen];
6876 int rc_fd;
6877 FLAG condition = applycommon;
6878 char pref_name [maxFILENAMElen]; /* filename to check */
6879 strcpy (pref_name, file_name);
6880
6881 /* mark subsequent selections to be preconfigured (e.g. .minedrc) */
6882 cmdline_selected = False;
6883
6884 if (applycommon == OPEN) {
6885 #ifdef apply_cmdline_options_again
6886 #warning implementation incomplete, some options may cumulate
6887 /* recover command line options */
6888 (void) eval_commandline ();
6889 #endif
6890 return;
6891 } else if (! applycommon) {
6892 /* restore initial preferences */
6893 preferences (REVERSE);
6894 }
6895
6896 strcpy (rcfn, gethomedir ());
6897 #ifdef vms
6898 strappend (rcfn, ".minedrc", maxFILENAMElen);
6899 #else
6900 strip_trailingslash (rcfn);
6901 strappend (rcfn, "/.minedrc", maxFILENAMElen);
6902 #endif
6903 rc_fd = open (rcfn, O_RDONLY | O_BINARY, 0);
6904
6905 if (rc_fd >= 0) {
6906 static off_t seek_position = 0;
6907 int dumlen;
6908
6909 if (! applycommon) {
6910 if (lseek (rc_fd, seek_position, SEEK_SET) < 0) {
6911 /* ignore, just read from beginning */
6912 }
6913 }
6914
6915 reset_get_line (False);
6916 while (line_gotten (get_line (rc_fd, text_buffer, & dumlen, False))) {
6917 long linelen = strlen (text_buffer);
6918 if (text_buffer [0] == '[') {
6919 /* determine condition to apply configuration options */
6920 char * condopt = strrchr (text_buffer, ']');
6921 if (condopt) {
6922 * condopt = '\0';
6923 }
6924 condition = False;
6925 /* check if considering common or specific options */
6926 if (applycommon) {
6927 break;
6928 } else {
6929 /* check specific preferences filter */
6930 condopt = & text_buffer [2];
6931 if (text_buffer [1] == '=') {
6932 /* filter terminal type */
6933 if (streq (condopt, TERM)) {
6934 condition = True;
6935 }
6936 #ifdef pref_match_only_suffix
6937 } else if (text_buffer [1] == '.') {
6938 /* filter filename suffix */
6939 char * suf = strstr (pref_name, condopt);
6940 if (suf && strlen (suf) == strlen (condopt)) {
6941 condition = True;
6942 }
6943 #endif
6944 } else if (wildcard (& text_buffer [1], pref_name)) {
6945 condition = True;
6946 }
6947 #ifdef debug_confpref
6948 printf ("conf %d %s\n", condition, text_buffer);
6949 #endif
6950 }
6951 } else if (condition && text_buffer [0] > '#') {
6952 char * option = text_buffer;
6953 char * negoption = NIL_PTR;
6954 char * optval;
6955 character * optpoi; /* unsigned ! */
6956 char optvalsep = ' ';
6957
6958 if (* option == '-') {
6959 option ++;
6960 } else if (strisprefix ("set", option) && option [3] <= ' ') {
6961 option += 3;
6962 while (* option == ' ' || * option == '\t') {
6963 option ++;
6964 }
6965 } else if (strisprefix ("unset", option) && option [5] <= ' ') {
6966 option += 5;
6967 while (* option == ' ' || * option == '\t') {
6968 option ++;
6969 }
6970 negoption = option;
6971 }
6972 /*option [strlen (option) - 1] = '\0';*/
6973 if (strisprefix ("no_", option)) {
6974 if (negoption) {
6975 negoption = NIL_PTR;
6976 option += 3;
6977 } else {
6978 negoption = option + 3;
6979 }
6980 }
6981
6982 /* skip option name, terminate it with NUL */
6983 optpoi = option;
6984 while (* optpoi > ' ' && * optpoi != '=') {
6985 if (* optpoi == '-') {
6986 * optpoi = '_';
6987 }
6988 optpoi ++;
6989 }
6990 while (* optpoi == ' ' || * optpoi == '\t' || * optpoi == '=') {
6991 * optpoi ++ = '\0';
6992 }
6993
6994 /* check option value delimiter */
6995 if (* optpoi == '"' || * optpoi == '\'') {
6996 optvalsep = * optpoi;
6997 optpoi ++;
6998 }
6999
7000 /* option value starts here */
7001 optval = optpoi;
7002
7003 /* skip option value, terminate it with NUL */
7004 while (* optpoi >= ' ' && * optpoi != optvalsep) {
7005 optpoi ++;
7006 }
7007 * optpoi = '\0';
7008
7009 #ifdef debug_confpref
7010 printf ("conf %s=%s\n", option, optval);
7011 #endif
7012 if (streq (option, "<<")) {
7013 strncpy (pref_name, optval, maxFILENAMElen);
7014 pref_name [maxFILENAMElen - 1] = '\0';
7015 } else {
7016 int opt_i = 0;
7017 while (config_options [opt_i].name != NIL_PTR) {
7018 if (streq (option, config_options [opt_i].name)) {
7019 char eval [maxCMDlen];
7020 build_string (eval, config_options [opt_i].eval, optval);
7021 #ifdef debug_confpref
7022 printf (" ->%s\n", eval);
7023 #endif
7024 eval_options (eval, False);
7025 if (strisprefix ("filter_", option)) {
7026 char * suf = strrchr (pref_name, '.');
7027 if (suf) {
7028 * suf = '\0';
7029 }
7030 }
7031 break;
7032 } else if (negoption
7033 && streq (negoption, config_options [opt_i].name)
7034 && config_options [opt_i].eval [0] == '+'
7035 ) {
7036 char eval [maxCMDlen];
7037 build_string (eval, config_options [opt_i].eval, optval);
7038 eval [0] = '-';
7039 #ifdef debug_confpref
7040 printf (" ->%s\n", eval);
7041 #endif
7042 eval_options (eval, False);
7043 break;
7044 }
7045 opt_i ++;
7046 }
7047 }
7048 }
7049 if (applycommon) {
7050 seek_position += linelen;
7051 }
7052 }
7053 (void) close (rc_fd);
7054 clear_filebuf (); /* which needs to call clear_get_line too */
7055 }
7056 }
7057
7058
7059 /**
7060 configuration and initialisation;
7061 load the file (if any);
7062 main loop of the editor
7063 */
7064 int
main(argc,argv)7065 main (argc, argv)
7066 int argc;
7067 char * argv [];
7068 {
7069 int argi;
7070 unsigned long inputchar;
7071 int initlinenum;
7072 LINE * initline;
7073 char * env;
7074 char * minedopt;
7075
7076 debug_mined = envvar ("DEBUG_MINED");
7077 TERM = envstr ("TERM");
7078
7079 mined_argc = argc;
7080 mined_argv = argv;
7081
7082 /* determine various modes and display options from environment settings */
7083 if (envvar ("NoCtrlSQ") || envvar ("NoControlSQ")) {
7084 /* ^S and ^Q may come arbitrarily from terminal, so don't use them */
7085 controlQS = True;
7086 key_map ['\021'] = I;
7087 key_map ['\023'] = I;
7088 }
7089
7090 transout = envstr ("MINEDOUT");
7091 if (* transout != '\0') {
7092 translen = strlen (transout);
7093 translate_output = True;
7094 use_ascii_graphics = True;
7095 menu_border_style = 'r';
7096 }
7097 #ifdef unix
7098 if (envvar ("MINEDMODF")) {
7099 mined_modf = envvar ("MINEDMODF");
7100 }
7101 #endif
7102 #ifdef pc_winlowdelay
7103 if (is_Windows ()) {
7104 display_delay = 0;
7105 }
7106 #endif
7107
7108 #ifdef debug_graphics
7109 printf ("(mn) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
7110 #endif
7111
7112
7113 /* derive screen mode and default text encoding from environment */
7114
7115 #ifdef __CYGWIN__
7116 /* check misconfigured cygwin console and ignore $TERM if detected;
7117 if $WINDIR is in environment rather than $windir,
7118 there has been an underlying cygwin instance
7119 before spawning the console and thus the value of $TERM is bogus
7120 */
7121 if (strisprefix ("/dev/cons", unnull (ttyname (2))) && envvar ("WINDIR")) {
7122 TERM = "cygwin";
7123 }
7124 #endif
7125
7126 if (streq (TERM, "cygwin")) {
7127 cygwin_console = True;
7128 }
7129
7130 /* detect PC terminal modes for native PC and for telnet from PC to Unix */
7131 #ifdef pc_term
7132 if (envvar ("USERPROFILE")) {
7133 (void) set_term_encoding ("CP850", 'P');
7134 } else {
7135 (void) set_term_encoding ("CP437", 'p');
7136 }
7137 #endif
7138 if (strisprefix ("nansi", TERM)
7139 || strisprefix ("ansi.", TERM)
7140 || strisprefix ("opennt", TERM)
7141 || strcontains (TERM, "-emx")
7142 || strisprefix ("interix", TERM)
7143 ) {
7144 #ifdef __CYGWIN__
7145 TERM = "cygwin";
7146 #else
7147 dark_term = True;
7148 (void) set_term_encoding ("CP437", 'p');
7149 term_encoding_selected = True;
7150 if (! text_encoding_selected) {
7151 (void) set_text_encoding ("CP850", 'P', "TERM=nansi");
7152 }
7153 use_vga_block_graphics = True;
7154 use_mouse_button_event_tracking = False;
7155 #endif
7156 } else if (strisprefix ("pcansi", TERM)
7157 || strisprefix ("hpansi", TERM)
7158 || streq ("ansi", TERM)
7159 || streq ("ansi-nt", TERM)
7160 ) {
7161 #ifdef __CYGWIN__
7162 TERM = "cygwin";
7163 #else
7164 dark_term = True;
7165 (void) set_term_encoding ("CP850", 'P');
7166 term_encoding_selected = True;
7167 if (! text_encoding_selected) {
7168 (void) set_text_encoding ("CP850", 'P', "TERM=pcansi");
7169 }
7170 use_vga_block_graphics = True;
7171 use_mouse_button_event_tracking = False;
7172 #endif
7173 }
7174 #ifdef __CYGWIN__
7175 {
7176 char * path = envstr ("PATH");
7177 char * p = strstr (path, "WindowsPowerShell");
7178 if (p) {
7179 char * sys = strstr (path, "%SystemRoot%");
7180 if (sys && sys + 22 == path) {
7181 /* Windows PowerShell */
7182 TERM = "cygwin";
7183 dark_term = True;
7184 }
7185 }
7186 }
7187 #endif
7188 if (strisprefix ("ansi", TERM)) {
7189 can_report_props = False;
7190 use_ascii_graphics = True;
7191 menu_border_style = 'r';
7192 }
7193 if (strisprefix ("Eterm", TERM)) {
7194 bright_term = True;
7195 }
7196
7197 /* check if cygwin console is configured to be in PC character set mode */
7198 if (streq (TERM, "cygwin")) {
7199 can_report_props = False;
7200 dark_term = True;
7201 /* avoid_reverse_colour = True; workaround obsolete */
7202 use_script_colour = False;
7203 #ifdef msdos
7204 /* if the djgpp version of mined is called from a cygwin shell,
7205 it will still see TERM=cygwin but the cygwin encoding emulation
7206 is not applicable (it's done by the cygwin DLL, not the terminal);
7207 djgpp mined assumes CP850 terminal "codepage" by default,
7208 may be overridden by codepage detection below
7209 */
7210 (void) set_term_encoding ("CP850", 'P');
7211 #else
7212 if (strcontains (envstr ("CYGWIN"), "codepage:oem")) {
7213 /* CP850 */
7214 (void) set_term_encoding ("CP850", 'P');
7215 term_encoding_selected = True;
7216 } else if (strcontains (envstr ("CYGWIN"), "codepage:utf8")) {
7217 (void) set_term_encoding (NIL_PTR, 'U');
7218 term_encoding_selected = True;
7219 } else {
7220 use_pc_block_graphics = True;
7221 # ifdef __CYGWIN__
7222 # if CYGWIN_VERSION_DLL_MAJOR < 1007 /* avoid langinfo for MSYS */
7223 # if CYGWIN_VERSION_DLL_MAJOR < 1005 /* MSYS */
7224 use_ascii_graphics = True;
7225 menu_border_style = 'r';
7226 # endif
7227 if (! set_term_encoding (":cw", ' ')) {
7228 (void) set_term_encoding ("CP1252", 'W');
7229 }
7230 # else
7231 if (setlocale (LC_CTYPE, "")) {
7232 (void) set_term_encoding (nl_langinfo (CODESET), ' ');
7233 term_encoding_selected = True;
7234 } else {
7235 # ifdef fallback_builtin
7236 (void) locale_terminal_encoding ();
7237 if (streq (language_code, "")) {
7238 (void) set_term_encoding (NIL_PTR, 'U');
7239 } else {
7240 /* leave to handle_locale_encoding below */
7241 }
7242 # else
7243 (void) set_term_encoding (NIL_PTR, 'U');
7244 term_encoding_selected = True;
7245 # endif
7246 }
7247 # endif
7248 # else
7249 /* set default terminal encoding assumption
7250 for remote login from a cygwin console
7251 */
7252 /* cygwin 1.5: */
7253 /*(void) set_term_encoding ("CP1252", 'W');*/
7254 /* cygwin 1.7: */
7255 /*(void) set_term_encoding (NIL_PTR, 'U');*/
7256 /* safe common fall-back: */
7257 (void) set_term_encoding ("ASCII", ' ');
7258 /* encodings should be indicated properly in environment ...
7259 */
7260 # endif
7261 }
7262
7263 /* limit terminal to ASCII in POSIX locale */
7264 (void) locale_terminal_encoding ();
7265 /* relic of early cygwin 1.7 versions:
7266 if (streq (language_code, "C") || streq (language_code, "POSIX")) {
7267 (void) set_term_encoding ("ASCII", ' ');
7268 }
7269 */
7270
7271 /* enable mouse move reporting without button pressed (for menus) */
7272 use_mouse_anymove_inmenu = True;
7273 /* adjust Unicode limitations in case UTF-8 is configured later */
7274 /* (e.g. with LC_... after rlogin) */
7275 width_data_version = 0;
7276 utf_cjk_wide_padding = False;
7277 suppress_non_BMP = True;
7278 suppress_extended_cjk = True;
7279 if (limited_marker_font) {
7280 very_limited_marker_font = True;
7281 } else {
7282 limited_marker_font = True;
7283 }
7284 if (! explicit_scrollbar_style) {
7285 fine_scrollbar = False;
7286 }
7287 use_vga_block_graphics = True;
7288
7289 /* workaround for unusual keypad assignments */
7290 if (mined_keypad) {
7291 mined_keypad = False;
7292 } else { /* in case option -k reversed it already */
7293 mined_keypad = True;
7294 }
7295 #endif
7296
7297 if (! text_encoding_selected) {
7298 /*(void) set_text_encoding ("CP1252", 'W', "TERM=cygwin");*/
7299 /* align with changed non-locale terminal encoding */
7300 (void) set_text_encoding ("ISO-8859-1", 'L', "TERM=cygwin");
7301 }
7302 trace_encoding ("cygwin");
7303
7304 /* numeric encoding of mouse coordinates */
7305 use_mouse_1015 = True;
7306 }
7307
7308 /* now derive screen mode and default text encoding from locale environment */
7309 if (! term_encoding_selected) {
7310 #ifdef msdos
7311 char codepagename [13];
7312 # ifdef debug_encoding
7313 printf ("codepage %d\n", get_codepage ());
7314 # endif
7315 build_string (codepagename, "CP%d", get_codepage ());
7316 if (! set_term_encoding (codepagename, ' ')) {
7317 (void) set_term_encoding ("ASCII", ' ');
7318 } else if (! text_encoding_selected) {
7319 /* transparent editing in current codepage */
7320 (void) set_text_encoding (codepagename, ' ', "codepage");
7321 }
7322 if (lookup_mappedtermchar (0xB2) != 0x2593) {
7323 /* codepage does not include VGA block graphics */
7324 use_ascii_graphics = True;
7325 menu_border_style = 'r';
7326 }
7327 trace_encoding ("codepage");
7328 #else
7329 (void) handle_locale_encoding (True, locale_terminal_encoding ());
7330 trace_encoding ("term locale");
7331 #endif
7332 }
7333 if (! text_encoding_selected) {
7334 (void) handle_locale_encoding (False, locale_text_encoding ());
7335 trace_encoding ("text locale");
7336 }
7337
7338
7339 /* fall-back/default config actions */
7340 handle_locale_quotes (NIL_PTR, UNSURE);
7341
7342
7343 /* configuration common preferences */
7344 configure_preferences (True); /* calling eval_options */
7345
7346
7347 /* backup and recovery environment settings */
7348 if (envvar ("BACKUP_DIRECTORY")) {
7349 backup_directory = envvar ("BACKUP_DIRECTORY");
7350 }
7351 if (! backup_directory || backup_directory [0] == '\0') {
7352 if (envvar ("BACKUPDIR")) {
7353 backup_directory = envvar ("BACKUPDIR");
7354 }
7355 }
7356 if (backup_directory && backup_directory [0] == '\0') {
7357 backup_directory = NIL_PTR;
7358 }
7359 if (backup_directory && is_absolute_path (backup_directory)) {
7360 if (mkdir (backup_directory, 0700) == 0 || geterrno () == EEXIST) {
7361 /* backup directory OK */
7362 } else {
7363 backup_directory = NIL_PTR;
7364 }
7365 }
7366 if ((minedopt = envvar ("VERSION_CONTROL")) != NIL_PTR) {
7367 if (streq ("none", minedopt) || streq ("off", minedopt)) {
7368 /* never make backups (cp: "even if --backup is given") */
7369 backup_mode = '\0';
7370 } else if (streq ("numbered", minedopt) || streq ("t", minedopt)) {
7371 /* make numbered backups (emacs style) */
7372 backup_mode = 'e';
7373 } else if (streq ("existing", minedopt) || streq ("nil", minedopt)) {
7374 /* numbered if numbered backups exist, simple otherwise */
7375 backup_mode = 'a';
7376 } else if (streq ("simple", minedopt) || streq ("never", minedopt)) {
7377 /* always make simple backups */
7378 backup_mode = 's';
7379 }
7380 }
7381 recover_directory = envvar ("AUTO_SAVE_DIRECTORY");
7382 if (! recover_directory || recover_directory [0] == '\0') {
7383 recover_directory = envvar ("AUTOSAVEDIR");
7384 }
7385 if (recover_directory && recover_directory [0] == '\0') {
7386 recover_directory = NIL_PTR;
7387 }
7388 if (recover_directory && is_absolute_path (recover_directory)) {
7389 if (mkdir (recover_directory, 0700) == 0 || geterrno () == EEXIST) {
7390 /* recovery directory OK */
7391 } else {
7392 recover_directory = NIL_PTR;
7393 }
7394 }
7395 if (! recover_directory || recover_directory [0] == '\0') {
7396 recover_directory = backup_directory;
7397 }
7398
7399
7400 /* process options configured in environment */
7401 minedopt = envvar ("MINEDOPT");
7402 if (minedopt == NIL_PTR) {
7403 #ifdef vms
7404 minedopt = envvar ("MINED$OPT");
7405 #else
7406 minedopt = envvar ("MINED");
7407 #endif
7408 }
7409 if (minedopt != NIL_PTR) {
7410 eval_options (minedopt, False);
7411 }
7412
7413
7414 /* set configured keyboard mapping */
7415 (void) setKEYMAP (envvar ("MINEDKEYMAP"));
7416
7417
7418 /* mark subsequent selections to be manually selected */
7419 cmdline_selected = True;
7420
7421 /* evaluate command line options (not file names) */
7422 argi = eval_commandline ();
7423 cmdline_selected = False;
7424
7425 /* save initial preferences */
7426 preferences (FORWARD);
7427
7428
7429 #ifdef debug_graphics
7430 printf ("(op) ascii %d, vga %d, vt100 %d\n", use_ascii_graphics, use_vga_block_graphics, use_vt100_block_graphics);
7431 #endif
7432 trace_encoding ("options");
7433
7434 #ifdef debug_wildcard_expansion
7435 #define trace_expansion(params) printf params
7436 #else
7437 #define trace_expansion(params)
7438 #endif
7439
7440 if (argi < argc) {
7441 int fi;
7442 for (fi = argi; fi < argc; fi ++) {
7443 #ifdef wildcard_expansion
7444 char * fnami = argv [fi];
7445 FLAG match = False;
7446 trace_expansion (("expanding %d <%s>\n", fi, fnami));
7447 if (strchr (fnami, '*') || strchr (fnami, '?')
7448 #ifdef vms
7449 || strchr (fnami, '%')
7450 #else
7451 || (strchr (fnami, '[') && strchr (fnami, ']'))
7452 #endif
7453 ) {
7454 char * bn;
7455 char dn [maxFILENAMElen];
7456 DIR * dir;
7457 * dn = '\0';
7458 strappend (dn, fnami, maxFILENAMElen);
7459 bn = getbasename (dn);
7460 if (bn == dn) {
7461 strcpy (dn, "");
7462 } else {
7463 * bn = '\0';
7464 }
7465 bn = getbasename (fnami);
7466
7467 trace_expansion (("dir <%s>\n", dn));
7468 if (* dn) {
7469 dir = opendir (dn);
7470 } else {
7471 dir = opendir (".");
7472 }
7473 if (dir) {
7474 #ifdef vms
7475 char * prevfn = "";
7476 #endif
7477 struct dirent * direntry;
7478 while ((direntry = readdir (dir)) != 0) {
7479 trace_expansion (("matching <%s> in <%s>\n", bn, direntry->d_name));
7480 if (wildcard (bn, direntry->d_name)) {
7481 char * fn = alloc (strlen (dn) + strlen (direntry->d_name) + 2);
7482
7483 if (! fn) {
7484 break;
7485 }
7486 strcpy (fn, dn);
7487 strcat (fn, direntry->d_name);
7488 trace_expansion (("-> <%s>\n", fn));
7489
7490 match = True;
7491
7492 #ifdef vms
7493 /* does pattern contain version? */
7494 if (strchr (bn, ';')) {
7495 /* add match with version */
7496 trace_expansion ((" -> added with version\n"));
7497 filelist_add (fn, True);
7498 } else {
7499 /* handle []x* -> X.;1 X.;2 */
7500
7501 /* strip version from match */
7502 char * ver = strrchr (fn, ';');
7503 if (ver) {
7504 * ver = '\0';
7505 }
7506
7507 if (streq (prevfn, fn)) {
7508 /* drop duplicate versions */
7509 trace_expansion ((" -> dropped\n"));
7510 } else {
7511 trace_expansion ((" -> added\n"));
7512 filelist_add (fn, True);
7513 }
7514 }
7515 prevfn = fn;
7516 #else
7517 filelist_add (fn, True);
7518 #endif
7519 }
7520 }
7521 closedir (dir);
7522 }
7523 trace_expansion (("match: %d\n", match));
7524 }
7525 if (! match) { /* no wildcard or no match */
7526 filelist_add (fnami, True);
7527 }
7528 #else
7529 filelist_add (argv [fi], True);
7530 #endif
7531 }
7532 argi = 0;
7533 } else {
7534 argi = -1; /* indicate "no file" */
7535 }
7536
7537
7538 /* handling of input/output redirection */
7539 /* Note: this must be called before terminal mode initialisation
7540 (get_term)
7541 */
7542 /* Note:
7543 - input redirection does not work with DOS version
7544 - handling of input/output redirection has to be suppressed in
7545 DOSBox or mined cannot start there (probably a DOSBox bug)
7546 */
7547 #ifdef msdos
7548 if (strisprefix ("Z:\\", envstr ("COMSPEC")))
7549 {
7550 /* DOSBox detected */
7551 }
7552 else
7553 #endif
7554 {
7555 #ifndef __MINGW32__
7556 if (! isatty (STD_IN)) { /* Reading from pipe */
7557 if (argi >= 0) {
7558 panic ("Cannot read both pipe and file", NIL_PTR);
7559 }
7560 reading_pipe = True;
7561
7562 /* wait for pipe data available in order to prevent screen control
7563 interference with previous pipe programs;
7564 must be called before changing input_fd
7565 and before calling terminal_configure_init ();
7566 this enhances pipe robustness slightly; a better solution would
7567 read the complete pipe before tackling the screen
7568 */
7569 (void) inputreadyafter (-1);
7570
7571 /* set modified flag not to loose buffer */
7572 set_modified ();
7573
7574 /* open terminal tty */
7575 #ifdef msdos
7576 panic ("Cannot edit after input from pipe", "MSDOS incompatibility");
7577 #else
7578 if ((input_fd = open ("/dev/tty", O_RDONLY, 0)) < 0) {
7579 panic ("Cannot open /dev/tty for reading", serror ());
7580 }
7581 #endif
7582 }
7583
7584 if (! isatty (STD_OUT)) {
7585 writing_pipe = True;
7586 set_modified (); /* Set modified flag not to ignore buffer on exit */
7587 if ((output_fd = open ("/dev/tty", O_WRONLY, 0)) < 0) {
7588 panic ("Cannot open /dev/tty for writing", serror ());
7589 }
7590 }
7591 #endif
7592 }
7593
7594
7595 /* setup terminal, auto-detect encoding, fine-tune modes */
7596 /*if (! only_detect_text_encoding)?*/
7597 terminal_configure_init ();
7598
7599
7600 /* install workaround for cygwin console delaying some escape sequences */
7601 install_console_pipe ();
7602
7603
7604 /* determine terminal-specific escape sequences and restrictions */
7605 if (strisprefix ("vt1", TERM)) {
7606 set_fkeymap ("vt100");
7607 }
7608 if (strisprefix ("rxvt", TERM) && mintty_version == 0) {
7609 set_fkeymap ("rxvt");
7610 }
7611 if (strisprefix ("hp", TERM)
7612 || streq ("xterm-hp", TERM)
7613 || strisprefix ("superbee", TERM)
7614 || strisprefix ("sb", TERM)
7615 || strisprefix ("microb", TERM)
7616 ) {
7617 if (! streq ("hpansi", TERM)) {
7618 set_fkeymap ("hp");
7619 }
7620 use_ascii_graphics = True;
7621 menu_border_style = 'r';
7622 use_bold = False;
7623 }
7624 if (strisprefix ("hp", TERM)) {
7625 bw_term = True;
7626 }
7627 if (streq ("vt52", TERM)
7628 || strcontains (TERM, "-vt52")
7629 ) {
7630 set_fkeymap ("52");
7631 (void) set_term_encoding ("ASCII", ' ');
7632 use_ascii_graphics = True;
7633 menu_border_style = 'r';
7634 use_bold = False;
7635 }
7636 if (strisprefix ("scoansi", TERM)
7637 || streq ("xterm-sco", TERM)
7638 || strisprefix ("cons", TERM) /* FreeBSD console */
7639 || streq ("att605-pc", TERM)
7640 || streq ("ti_ansi", TERM)
7641 || streq ("mgterm", TERM)
7642 ) {
7643 set_fkeymap ("o");
7644 }
7645 if (strcontains (TERM, "koi")) {
7646 (void) set_term_encoding ("KOI8-R", ' ');
7647 }
7648 if (strisprefix ("cons", TERM) && strlen (TERM) >= 6) {
7649 /* FreeBSD console */
7650 if (strisprefix ("r", TERM + 6)) {
7651 (void) set_term_encoding ("KOI8-R", ' ');
7652 } else if (strisprefix ("l1", TERM + 6)) {
7653 (void) set_term_encoding ("ISO-8859-1", ' ');
7654 } else {
7655 (void) set_term_encoding ("CP437", 'p');
7656 }
7657 }
7658 if (strisprefix ("mac", TERM)) {
7659 (void) set_term_encoding ("MacRoman", 'M');
7660 }
7661 if (strisprefix ("nsterm", TERM)) {
7662 if (strcontains (TERM, "7")) {
7663 (void) set_term_encoding ("ASCII", ' ');
7664 } else if (streq ("+mac", TERM + 6)
7665 || streq ("-m", TERM + 6)
7666 || streq ("-m-s", TERM + 6)
7667 || streq ("", TERM + 6)
7668 || streq ("-c", TERM + 6)
7669 || streq ("-s", TERM + 6)
7670 || streq ("-c-s", TERM + 6)
7671 ) {
7672 (void) set_term_encoding ("MacRoman", 'M');
7673 }
7674 }
7675 if (strisprefix ("9780", TERM)) {
7676 set_fkeymap ("siemens");
7677 use_ascii_graphics = True;
7678 menu_border_style = 'r';
7679 }
7680 if (strisprefix ("interix", TERM)) {
7681 set_fkeymap ("interix");
7682 use_mouse = False;
7683 }
7684 #ifdef assume_sco_dtterm_broken_default_font
7685 if (streq ("dtterm", TERM)) {
7686 TABdefault = '.';
7687 RETdefault = '<';
7688 (void) set_term_encoding ("ASCII", ' ');
7689 }
7690 #endif
7691 #ifdef __ANDROID__
7692 if (streq ("screen", TERM)) {
7693 /* Terminal Emulator (Jack Palevich) */
7694 suppress_colour = True;
7695 }
7696 #endif
7697
7698
7699 if (! use_bold || menu_border_style == 'f' || menu_border_style == 'd') {
7700 bold_border = False;
7701 }
7702
7703
7704 /* get/update ANSI screen mode configuration */
7705 get_ansi_modes (); /* also calls determine_dim_mode */
7706
7707
7708 /* if request with option +E?, only report terminal encoding */
7709 if (only_detect_terminal_encoding) {
7710 /* display character data version information (for +E? option) */
7711 raw_mode (False);
7712 print_terminal_info ();
7713 exit (0);
7714 }
7715
7716
7717 /* remember determined default text encoding for further files */
7718 default_text_encoding = get_text_encoding ();
7719
7720 /* read filter that defines which CJK encodings may be auto-detected */
7721 detect_encodings = envvar ("MINEDDETECT");
7722 /* if not defined, fallback to default set of auto-detected encodings */
7723 if (! detect_encodings) {
7724 detect_encodings = "BGC JSXx KH LWP";
7725 }
7726
7727
7728 /* get preconfigured smart quotes style */
7729 preselect_quote_style = envvar ("MINEDQUOTES");
7730
7731
7732 /* get selection of Han character information to be displayed */
7733 env = envvar ("MINEDHANINFO");
7734 if (env) {
7735 if (* env) {
7736 always_disp_Han = True;
7737 disp_Han_description = False;
7738 disp_Han_full = False;
7739 } else {
7740 always_disp_Han = False;
7741 }
7742 if (strchr (env, 'M') != NIL_PTR) {
7743 disp_Han_Mandarin = True;
7744 }
7745 if (strchr (env, 'C') != NIL_PTR) {
7746 disp_Han_Cantonese = True;
7747 }
7748 if (strchr (env, 'J') != NIL_PTR) {
7749 disp_Han_Japanese = True;
7750 }
7751 if (strchr (env, 'S') != NIL_PTR) {
7752 disp_Han_Sino_Japanese = True;
7753 }
7754 if (strchr (env, 'H') != NIL_PTR) {
7755 disp_Han_Hangul = True;
7756 }
7757 if (strchr (env, 'K') != NIL_PTR) {
7758 disp_Han_Korean = True;
7759 }
7760 if (strchr (env, 'V') != NIL_PTR) {
7761 disp_Han_Vietnamese = True;
7762 }
7763 if (strchr (env, 'P') != NIL_PTR) {
7764 disp_Han_HanyuPinlu = True;
7765 }
7766 if (strchr (env, 'Y') != NIL_PTR) {
7767 disp_Han_HanyuPinyin = True;
7768 }
7769 if (strchr (env, 'X') != NIL_PTR) {
7770 disp_Han_XHCHanyuPinyin = True;
7771 }
7772 if (strchr (env, 'T') != NIL_PTR) {
7773 disp_Han_Tang = True;
7774 }
7775 if (strchr (env, 'D') != NIL_PTR) {
7776 disp_Han_description = True;
7777 }
7778 if (strchr (env, 'F') != NIL_PTR) {
7779 disp_Han_description = True;
7780 disp_Han_full = True;
7781 }
7782 }
7783
7784
7785 setup_temp_filenames ();
7786
7787
7788 /* determine default permission setting for new files */
7789 fprot0 = ~ umask (0) & 0666;
7790
7791 /* option +@: grooming .@mined */
7792 if (groom_stat) {
7793 GROOM_INFO ();
7794 if (argi < 0) {
7795 raw_mode (False);
7796 exit (0);
7797 }
7798 }
7799
7800
7801 /* ----------------------------------------------------------------------- */
7802
7803 /* prepare editing buffer */
7804 header = tail = alloc_header (); /* Make header of list */
7805 if (header == NIL_LINE) {
7806 panic ("Cannot allocate memory", NIL_PTR);
7807 }
7808 header->text = NIL_PTR;
7809 header->next = tail->prev = header;
7810 header->syntax_mask = syntax_none;
7811 header->sel_begin = NIL_PTR;
7812 header->sel_end = NIL_PTR;
7813
7814 /* load the file (if any) */
7815 if (argi < 0) {
7816 if (! only_detect_text_encoding) {
7817 if (homedir_selected) {
7818 (void) chdir (gethomedir ());
7819 }
7820 load_wild_file (NIL_PTR, reading_pipe, False);
7821 }
7822 } else {
7823 load_wild_file (filelist_get (argi), False, False);
7824 }
7825 trace_encoding ("load");
7826
7827 if (only_detect_text_encoding) {
7828 raw_mode (False);
7829 if (argi < 0) {
7830 printf ("%s\n", get_text_encoding ());
7831 } else {
7832 printf ("%s: %s\n", filelist_get (argi), get_text_encoding ());
7833 viewonly_mode = True;
7834 while (argi + 1 < filelist_count ()) {
7835 argi ++;
7836 raw_mode (True);
7837 load_wild_file (filelist_get (argi), False, True);
7838 raw_mode (False);
7839 printf ("%s: %s\n", filelist_get (argi), get_text_encoding ());
7840 }
7841 }
7842 exit (0);
7843 }
7844
7845 loading = True; /* keep loading flag True until entering main loop */
7846
7847 if (initlini != 0) {
7848 (void) scan_int (argv [initlini] + 1, & initlinenum);
7849 if (initlinenum > 0) {
7850 if (initlinenum <= 0 || (initline = proceed (header->next, initlinenum - 1)) == tail) {
7851 error2 ("Invalid line number: ", dec_out ((long) initlinenum));
7852 } else {
7853 move_to (x, find_y_w_o_RD (initline));
7854 fstatus ("Loaded", -1L, -1L);
7855 }
7856 }
7857 }
7858
7859 if (inisearch != NIL_PTR) {
7860 if (search_ini (inisearch, FORWARD, True) == False) {
7861 sleep (1); /* show "not found" message */
7862 }
7863 if (! viewing_help) {
7864 fstatus ("Loaded", -1L, -1L);
7865 }
7866 }
7867
7868 if (writing_pipe) {
7869 file_name [0] = '\0'; /* don't let user believe he's editing a file */
7870 fstatus ("Editing for standard output", -1L, -1L);
7871 } else if (reading_pipe) {
7872 file_name [0] = '\0'; /* switch from [standard input] to [no file] */
7873 }
7874
7875 loading = False;
7876 catch_signals ();
7877
7878 /* display text which was postponed for the sake of +N or +/expr options */
7879 display (0, top_line, last_y, 0);
7880 flush ();
7881
7882 trace_encoding ("main");
7883 /* main loop of the editor */
7884 for (;;) {
7885 /* FLAG cursor_somewhere = False; */
7886 if (last_mouse_event == releasebutton && in_selection_mouse_mode) {
7887 selection_mouse_mode (False);
7888 }
7889 /* update selection highlighting */
7890 display_flush ();
7891 /* ... cursor_somewhere = True; */
7892
7893 /* display status line contents unless there is a message */
7894 if (! stat_visible) {
7895 if (ext_status != NIL_PTR) {
7896 /* interpret status text in terminal encoding? */
7897 /*?*/
7898 /* interpret status text in text file encoding? */
7899 /*status_fmt2 (ext_status, NIL_PTR);*/
7900 /* interpret status text in Unicode */
7901 status_uni (ext_status);
7902 } else if (always_disp_fstat) {
7903 FSTATUS ();
7904 } else if (always_disp_code) {
7905 display_the_code ();
7906 } else if (always_disp_Han && ! disp_Han_full) {
7907 display_Han (cur_text, False);
7908 } else if (always_disp_help) {
7909 display_FHELP ();
7910 }
7911 }
7912 if (always_disp_Han && disp_Han_full) {
7913 display_Han (cur_text, False);
7914 }
7915
7916 if ((hop_flag_displayed && ! hop_flag) || (hop_flag && ! hop_flag_displayed)) {
7917 /* since hop_flag is often cleared on-the-fly as needed in
7918 editing functions, we need extra detection and handling
7919 */
7920 flags_changed = True;
7921 }
7922
7923 /* refresh display items (top line, scrollbar, cursor position) */
7924 if (MENU && top_line_dirty) {
7925 displaymenuline (True);
7926 flags_changed = False;
7927 /*cursor_somewhere = True;*/
7928 }
7929 if (text_screen_dirty) {
7930 RDwin ();
7931 text_screen_dirty = False;
7932 }
7933 if (MENU && flags_changed) {
7934 displayflags ();
7935 /*cursor_somewhere = True;*/
7936 }
7937 if (disp_scrollbar) {
7938 if (display_scrollbar (update_scrollbar_lazy)) {
7939 /*cursor_somewhere = True;*/
7940 }
7941 }
7942 /*
7943 if (cursor_somewhere) {
7944 set_cursor_xy ();
7945 }
7946 */
7947 set_cursor_xy ();
7948
7949 flush (); /* Flush output (if any) */
7950 debuglog (0, "flush", 0);
7951
7952 input:
7953
7954 if (key_replaying) {
7955 inputchar = KEYreplay (); /* also set keyshift */
7956 } else {
7957 do {
7958 inputchar = readcharacter_unicode_mapped ();
7959 trace_keytrack ("main", inputchar);
7960 } while (inputchar == CHAR_UNKNOWN);
7961 }
7962 if (key_recording) {
7963 KEYrecord (inputchar); /* also log keyshift */
7964 }
7965
7966 if (command (inputchar) != Scharacter
7967 && command (inputchar) != Sdash
7968 && command (inputchar) != Ssinglequote
7969 && command (inputchar) != Sdoublequote
7970 ) {
7971 reset_smart_replacement ();
7972 }
7973
7974 if (command (inputchar) != Scharacter) {
7975 keyproc = command (inputchar);
7976 inputchar = FUNcmd;
7977 } else {
7978 inputchar = encodedchar (inputchar);
7979 }
7980
7981 #ifdef adjust_to_actual_termsize
7982 if (command (inputchar) == ANSIseq) {
7983 ANSIseq ();
7984 goto input;
7985 }
7986 #endif
7987
7988 if (command (inputchar) == FOCUSin) {
7989 #ifdef debug_mouse
7990 printf ("FOCUSin received\n");
7991 #endif
7992 check_file_modified ();
7993 goto input;
7994 }
7995
7996 if (always_disp_Han) {
7997 clean_menus ();
7998 }
7999
8000 if (stat_visible) {
8001 clear_status ();
8002 }
8003 if (quit == False) { /* Call the function for the typed key */
8004 invoke_key_function (inputchar);
8005 if (hop_flag > 0) {
8006 hop_flag --;
8007 flags_changed = True;
8008 }
8009 if (buffer_open_flag > 0) {
8010 buffer_open_flag --;
8011 #ifdef debug_ring_buffer
8012 if (buffer_open_flag == 0) {
8013 flags_changed = True;
8014 }
8015 #endif
8016 }
8017 }
8018 if (quit) {
8019 if (hop_flag > 0) {
8020 flags_changed = True;
8021 }
8022 CANCEL ();
8023 quit = False;
8024 }
8025 }
8026 /* NOTREACHED */
8027 }
8028
8029
8030 /*======================================================================*\
8031 |* End *|
8032 \*======================================================================*/
8033