2 * YTerm -- (mostly) GNU/Linux X11 terminal emulator
4 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
5 * Understanding is not required. Only obedience.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 included directly into the main file.
25 #define XRM_BAD_COLOR (0xffffffffU)
27 static char xrm_key_value
[1024];
30 //==========================================================================
34 //==========================================================================
35 static yterm_bool
strEquCI (const char *s0
, const char *s1
) {
36 if (s0
== NULL
) s0
= "";
37 if (s1
== NULL
) s1
= "";
38 while (*s0
!= 0 && *s1
!= 0) {
40 if (c0
>= 'A' && c0
<= 'Z') c0
= c0
- 'A' + 'a';
42 if (c1
>= 'A' && c1
<= 'Z') c1
= c1
- 'A' + 'a';
43 if (c0
!= c1
) return 0;
45 return (s0
[0] == 0 && s1
[0] == 0);
49 //==========================================================================
53 //==========================================================================
54 static yterm_bool
parse_keybind (KeyBind
*kb
, const char *str
) {
56 KeySym keysym
= NoSymbol
;
58 while (*str
> 0 && *str
<= 32) str
+= 1;
61 if (str
[0] == 'C' && str
[1] == '-') {
62 modmask
= modmask
| ControlMask
;
64 } else if (str
[0] == 'M' && str
[1] == '-') {
65 modmask
= modmask
| Mod1Mask
;
67 } else if (str
[0] == 'H' && str
[1] == '-') {
68 modmask
= modmask
| Mod4Mask
;
70 } else if (str
[0] == 'S' && str
[1] == '-') {
71 modmask
= modmask
| ShiftMask
;
78 keysym
= XStringToKeysym(str
);
79 // this is what X.org returns from `XLookupKeysym()` even if shift is pressed
80 if (keysym
>= XK_A
&& keysym
<= XK_Z
) keysym
= keysym
- XK_A
+ XK_a
;
84 if (keysym
!= NoSymbol
) {
96 //==========================================================================
100 //==========================================================================
101 static int parse_signal_name (const char *str
) {
102 if ((str
[0] == 's' || str
[0] == 'S') &&
103 (str
[1] == 'i' || str
[1] == 'I') &&
104 (str
[2] == 'g' || str
[2] == 'G'))
108 while (*str
== '_') str
+= 1;
109 if (strEquCI(str
, "HUP")) return 1;
110 if (strEquCI(str
, "INT")) return 2;
111 if (strEquCI(str
, "QUIT")) return 3;
112 if (strEquCI(str
, "ILL")) return 4;
113 if (strEquCI(str
, "TRAP")) return 5;
114 if (strEquCI(str
, "ABRT")) return 6;
115 if (strEquCI(str
, "ABORT")) return 6;
116 //if (strEquCI(str, "IOT")) return 6;
117 if (strEquCI(str
, "BUS")) return 7;
118 if (strEquCI(str
, "FPE")) return 8;
119 if (strEquCI(str
, "KILL")) return 9;
120 if (strEquCI(str
, "USR1")) return 10;
121 if (strEquCI(str
, "SEGV")) return 11;
122 if (strEquCI(str
, "USR2")) return 12;
123 //if (strEquCI(str, "PIPE")) return 13;
124 if (strEquCI(str
, "ALRM")) return 14;
125 if (strEquCI(str
, "ALARM")) return 14;
126 if (strEquCI(str
, "TERM")) return 15;
127 if (strEquCI(str
, "STKFLT")) return 16;
128 //if (strEquCI(str, "CHLD")) return 17;
129 if (strEquCI(str
, "CONT")) return 18;
130 if (strEquCI(str
, "STOP")) return 19;
131 //if (strEquCI(str, "TSTP")) return 20;
132 //if (strEquCI(str, "TTIN")) return 21;
133 //if (strEquCI(str, "TTOU")) return 22;
134 if (strEquCI(str
, "URG")) return 23;
135 //if (strEquCI(str, "XCPU")) return 24;
136 //if (strEquCI(str, "XFSZ")) return 25;
137 //if (strEquCI(str, "VTALRM")) return 26;
138 //if (strEquCI(str, "PROF")) return 27;
139 //if (strEquCI(str, "WINCH")) return 28;
144 //==========================================================================
148 //==========================================================================
149 static char *xrm_val_to_val (XrmValue
*val
) {
152 const char *str
= (const char *)val
->addr
;
153 size_t slen
= (val
->size
> 0 && str
!= NULL
? strlen(str
) : 0);
154 // trim leading spaces
155 while (slen
> 0 && str
[0] > 0 && str
[0] <= 32) {
158 // trim trailing spaces
159 while (slen
> 0 && str
[slen
- 1] > 0 && str
[slen
- 1] <= 32) {
162 if (slen
> 0 && slen
< sizeof(xrm_key_value
)) {
163 memcpy(xrm_key_value
, str
, slen
);
164 xrm_key_value
[slen
] = 0;
172 //==========================================================================
176 //==========================================================================
177 static int parse_bool (const char *val
) {
180 if (strEquCI(val
, "tan")) res
= 1;
181 else if (strEquCI(val
, "yes")) res
= 1;
182 else if (strEquCI(val
, "true")) res
= 1;
183 else if (strEquCI(val
, "on")) res
= 1;
184 else if (strEquCI(val
, "1")) res
= 1;
185 else if (strEquCI(val
, "ona")) res
= 0;
186 else if (strEquCI(val
, "no")) res
= 0;
187 else if (strEquCI(val
, "false")) res
= 0;
188 else if (strEquCI(val
, "off")) res
= 0;
189 else if (strEquCI(val
, "0")) res
= 0;
195 //==========================================================================
199 //==========================================================================
200 static int hex_digit (char ch
) {
202 ch
>= '0' && ch
<= '9' ? ch
- '0' :
203 ch
>= 'A' && ch
<= 'F' ? ch
- 'A' + 10 :
204 ch
>= 'a' && ch
<= 'f' ? ch
- 'a' + 10 :
209 //==========================================================================
213 //==========================================================================
214 static uint32_t parse_hex_color (const char *cname
) {
215 if (cname
== NULL
) return XRM_BAD_COLOR
;
216 while (*cname
> 0 && *cname
<= 32) cname
+= 1;
217 if (cname
[0] != '#') return XRM_BAD_COLOR
;
219 while (*cname
> 0 && *cname
<= 32) cname
+= 1;
220 uint32_t vals
[6] = {0, 0, 0, 0, 0, 0};
222 while (ccnt
< 6 && *cname
> 32) {
223 const int dig
= hex_digit(*cname
); cname
+= 1;
224 if (dig
< 0) return XRM_BAD_COLOR
;
225 vals
[ccnt
] = (unsigned)dig
;
228 if (ccnt
!= 3 && ccnt
!= 6) return XRM_BAD_COLOR
;
229 while (*cname
> 0 && *cname
<= 32) cname
+= 1;
230 if (cname
[0]) return XRM_BAD_COLOR
;
232 vals
[4] = vals
[2]; vals
[5] = vals
[2];
233 vals
[2] = vals
[1]; vals
[3] = vals
[1];
237 (vals
[0] << 20) | (vals
[1] << 16) |
238 (vals
[2] << 12) | (vals
[3] << 8) |
239 (vals
[4] << 4) | vals
[5];
243 // ////////////////////////////////////////////////////////////////////////// //
244 static char xrm_errmenu_str
[128];
245 static int xrm_errmenu_strpos
= 0;
248 //==========================================================================
252 //==========================================================================
253 static void xrm_errmenu_put (const char *str
) {
255 int slen
= (int)strlen(str
);
256 if (xrm_errmenu_strpos
+ slen
>= (int)sizeof(xrm_errmenu_str
) - 1 - 4) {
257 xrm_errmenu_str
[xrm_errmenu_strpos
] = '.'; xrm_errmenu_strpos
+= 1;
258 xrm_errmenu_str
[xrm_errmenu_strpos
] = '.'; xrm_errmenu_strpos
+= 1;
259 xrm_errmenu_str
[xrm_errmenu_strpos
] = '.'; xrm_errmenu_strpos
+= 1;
260 xrm_errmenu_str
[xrm_errmenu_strpos
] = 0;
261 xrm_errmenu_strpos
= (int)sizeof(xrm_errmenu_str
);
263 strcpy(xrm_errmenu_str
+ xrm_errmenu_strpos
, str
);
264 xrm_errmenu_strpos
+= slen
;
270 //==========================================================================
274 //==========================================================================
275 static void show_error_menu (const char *errmsg
, XrmQuarkList quarks
) {
276 MenuWindow
*menu
= menu_new_window(0, 0, "Config Error!", 0, 0);
279 xrm_errmenu_strpos
= 0; xrm_errmenu_str
[0] = 0;
280 xrm_errmenu_put("Error: ");
281 xrm_errmenu_put(errmsg
);
282 menu_add_label(menu
, xrm_errmenu_str
, NULL
);
285 xrm_errmenu_strpos
= 0; xrm_errmenu_str
[0] = 0;
286 xrm_errmenu_put(" Key: ");
288 while (quarks
[f
] != NULLQUARK
) {
289 const char *qq
= XrmQuarkToString(quarks
[f
]);
290 if (f
!= 0) xrm_errmenu_put(".");
294 menu_add_label(menu
, xrm_errmenu_str
, NULL
);
295 menu_add_label(menu
, NULL
, NULL
);
297 menu
->curr_item
= menu
->items_count
;
298 menu_add_label(menu
, "&Close", &menu_msgbox_close_cb
);
304 //==========================================================================
308 //==========================================================================
309 static Bool
xrm_keybind_cb (XrmDatabase
*db
, XrmBindingList bindings
, XrmQuarkList quarks
,
310 XrmRepresentation
*type
, XrmValue
*value
, XPointer udata
)
312 (void)db
; (void)bindings
; (void)quarks
; (void)type
; (void)value
; (void)udata
;
313 //fprintf(stderr, "=====\n");
315 const char *errmsg
= NULL
;
317 if (quarks
[0] == NULLQUARK
|| strcmp(XrmQuarkToString(quarks
[0]), xrm_app_name
) != 0) return False
;
318 if (quarks
[1] == NULLQUARK
|| strcmp(XrmQuarkToString(quarks
[1]), "keybind") != 0) {
319 errmsg
= "invalid key name";
322 if (quarks
[2] == NULLQUARK
|| quarks
[3] == NULLQUARK
|| quarks
[4] != NULLQUARK
) {
323 errmsg
= "invalid key format";
327 if (!type
|| strcmp(XrmQuarkToString(*type
), "String") != 0) {
328 errmsg
= "invalid key type";
332 if (value
->size
== 0 || value
->addr
== NULL
) {
333 errmsg
= "empty key value";
337 KeyBind
*kb
= keybinds
;
338 while (kb
!= NULL
&& strcmp(kb
->bindname
, XrmQuarkToString(quarks
[2])) != 0) {
343 // create new empty keybind
344 kb
= malloc(sizeof(KeyBind
));
345 if (!kb
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
346 memset(kb
, 0, sizeof(KeyBind
));
348 kb
->bindname
= strdup(XrmQuarkToString(quarks
[2]));
351 kb
->allow_history
= -1;
356 const char *key
= XrmQuarkToString(quarks
[3]);
357 const char *val
= (const char *)value
->addr
;
361 fprintf(stderr
, "name: ");
363 while (quarks
[qc
] != NULLQUARK
) {
364 const char *qs
= XrmQuarkToString(quarks
[qc
]);
365 if (qc
!= 0) fputc('.', stderr
);
366 fprintf(stderr
, "%s", qs
);
370 fprintf(stderr
, " key: %s\n", key
);
371 fprintf(stderr
, " value: %s\n", val
);
375 if (strcmp(key
, "bind") == 0) {
376 // key binding, parse it
377 if (strEquCI(val
, "none") || strEquCI(val
, "disable") ||
378 strEquCI(val
, "disabled"))
380 kb
->killsignal
= KB_CMD_IGNORE
;
381 } else if (!parse_keybind(kb
, val
)) {
382 errmsg
= "invalid binding string";
385 } else if (strcmp(key
, "path") == 0) {
386 if (strcmp(val
, "$CWD") == 0) val
= "$PWD";
387 else if (strcmp(val
, "$PWD") == 0) {}
388 else if (strcmp(val
, "$HOME") == 0) {}
389 else if (val
[0] == '/') {}
391 errmsg
= "invalid path";
395 kb
->path
= strdup(val
);
396 if (!kb
->path
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
397 } else if (strcmp(key
, "color") == 0) {
398 if (strEquCI(val
, "bw") || strEquCI(val
, "mono")) kb
->colorMode
= CMODE_BW
;
399 else if (strEquCI(val
, "green")) kb
->colorMode
= CMODE_GREEN
;
400 else if (strEquCI(val
, "normal")) kb
->colorMode
= CMODE_NORMAL
;
401 else if (strEquCI(val
, "color")) kb
->colorMode
= CMODE_NORMAL
;
402 else if (strEquCI(val
, "default")) kb
->colorMode
= -1;
404 errmsg
= "invalid color mode";
407 } else if (strcmp(key
, "kill") == 0) {
408 int sig
= parse_signal_name(val
);
410 errmsg
= "invalid signal name";
413 free(kb
->exec
); kb
->exec
= NULL
;
414 if (kb
->killsignal
!= KB_CMD_IGNORE
) kb
->killsignal
= sig
;
415 } else if (strcmp(key
, "exec") == 0) {
417 kb
->exec
= strdup(val
);
418 if (!kb
->exec
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
419 if (kb
->killsignal
!= KB_CMD_IGNORE
) kb
->killsignal
= 0;
420 } else if (strcmp(key
, "paste") == 0) {
421 free(kb
->exec
); kb
->exec
= NULL
;
422 if (strEquCI(val
, "primary")) kb
->killsignal
= KB_CMD_PASTE_PRIMARY
;
423 else if (strEquCI(val
, "secondary")) kb
->killsignal
= KB_CMD_PASTE_SECONDARY
;
424 else if (strEquCI(val
, "clipboard")) kb
->killsignal
= KB_CMD_PASTE_CLIPBOARD
;
426 errmsg
= "invalid selection name";
429 } else if (strcmp(key
, "copy-to") == 0 || strcmp(key
, "copyto") == 0) {
430 free(kb
->exec
); kb
->exec
= NULL
;
431 if (strEquCI(val
, "primary")) kb
->killsignal
= KB_CMD_COPY_TO_PRIMARY
;
432 else if (strEquCI(val
, "secondary")) kb
->killsignal
= KB_CMD_COPY_TO_SECONDARY
;
433 else if (strEquCI(val
, "clipboard")) kb
->killsignal
= KB_CMD_COPY_TO_CLIPBOARD
;
435 errmsg
= "invalid selection name";
438 } else if (strcmp(key
, "tab") == 0) {
439 free(kb
->exec
); kb
->exec
= NULL
;
440 if (strEquCI(val
, "prev")) kb
->killsignal
= KB_CMD_TAB_PREV
;
441 else if (strEquCI(val
, "next")) kb
->killsignal
= KB_CMD_TAB_NEXT
;
442 else if (strEquCI(val
, "first")) kb
->killsignal
= KB_CMD_TAB_FIRST
;
443 else if (strEquCI(val
, "last")) kb
->killsignal
= KB_CMD_TAB_LAST
;
444 else if (strEquCI(val
, "move-left")) kb
->killsignal
= KB_CMD_TAB_MOVE_LEFT
;
445 else if (strEquCI(val
, "move-right")) kb
->killsignal
= KB_CMD_TAB_MOVE_RIGHT
;
447 errmsg
= "invalid tab command";
450 } else if (strcmp(key
, "history") == 0) {
452 if (strEquCI(val
, "default")) {
453 kb
->allow_history
= -1;
455 int bval
= parse_bool(val
);
457 errmsg
= "invalid history command";
460 kb
->allow_history
= bval
;
462 } else if (strcmp(key
, "selection") == 0) {
463 free(kb
->exec
); kb
->exec
= NULL
;
464 if (strEquCI(val
, "start")) kb
->killsignal
= KB_CMD_START_SELECTION
;
466 errmsg
= "invalid selection command";
469 } else if (strcmp(key
, "mouse-report") == 0 || strcmp(key
, "mouse-reports") == 0) {
470 free(kb
->exec
); kb
->exec
= NULL
;
471 if (strEquCI(val
, "toggle")) kb
->killsignal
= KB_CMD_MREPORTS_TOGGLE
;
473 int bval
= parse_bool(val
);
475 errmsg
= "invalid mouse-report command";
478 kb
->killsignal
= KB_CMD_MREPORTS_OFF
+ bval
;
480 } else if (strcmp(key
, "escesc") == 0 || strcmp(key
, "esc-esc") == 0) {
481 free(kb
->exec
); kb
->exec
= NULL
;
482 if (strEquCI(val
, "toggle")) kb
->killsignal
= KB_CMD_ESCESC_TOGGLE
;
484 int bval
= parse_bool(val
);
486 errmsg
= "invalid escesc command";
489 kb
->killsignal
= KB_CMD_ESCESC_OFF
+ bval
;
491 } else if (strcmp(key
, "cursor") == 0) {
492 free(kb
->exec
); kb
->exec
= NULL
;
493 if (strEquCI(val
, "toggle")) kb
->killsignal
= KB_CMD_CURSOR_TOGGLE
;
495 int bval
= parse_bool(val
);
497 errmsg
= "invalid escesc command";
500 kb
->killsignal
= KB_CMD_CURSOR_OFF
+ bval
;
502 } else if (strcmp(key
, "history-mode") == 0) {
503 free(kb
->exec
); kb
->exec
= NULL
;
504 if (strEquCI(val
, "toggle")) kb
->killsignal
= KB_CMD_HISTORY_TOGGLE
;
506 int bval
= parse_bool(val
);
508 errmsg
= "invalid history-mode command";
511 kb
->killsignal
= KB_CMD_HISTORY_OFF
+ bval
;
513 } else if (strcmp(key
, "color-mode") == 0) {
514 free(kb
->exec
); kb
->exec
= NULL
;
515 if (strEquCI(val
, "normal")) kb
->killsignal
= KB_CMD_COLOR_NORMAL
;
516 else if (strEquCI(val
, "color")) kb
->killsignal
= KB_CMD_COLOR_NORMAL
;
517 else if (strEquCI(val
, "default")) kb
->killsignal
= KB_CMD_COLOR_DEFAULT
;
518 else if (strEquCI(val
, "bw") || strEquCI(val
, "mono")) kb
->killsignal
= KB_CMD_COLOR_BW
;
519 else if (strEquCI(val
, "green")) kb
->killsignal
= KB_CMD_COLOR_GREEN
;
521 errmsg
= "invalid color-mode command";
524 } else if (strcmp(key
, "menu") == 0) {
525 free(kb
->exec
); kb
->exec
= NULL
;
526 if (strEquCI(val
, "tab-options")) kb
->killsignal
= KB_CMD_MENU_TAB_OPTIONS
;
527 else if (strEquCI(val
, "global-options")) kb
->killsignal
= KB_CMD_MENU_OPTIONS
;
529 errmsg
= "invalid menu command";
533 errmsg
= "unknown keybind option";
541 show_error_menu(errmsg
, quarks
);
544 fprintf(stderr
, "CONFIG ERROR: %s!\n", errmsg
);
545 fprintf(stderr
, " key: ");
547 while (quarks
[f
] != NULLQUARK
) {
548 const char *qq
= XrmQuarkToString(quarks
[f
]);
549 if (f
!= 0) fputc('.', stderr
);
550 fprintf(stderr
, "%s", qq
);
556 fprintf(stderr
, " type: %s\n", XrmQuarkToString(*type
));
557 if (strcmp(XrmQuarkToString(*type
), "String") == 0) {
558 fprintf(stderr
, " value: <%.*s>\n", (unsigned)value
->size
, (const char *)value
->addr
);
562 if (!xrm_reloading
) exit(1);
567 // ////////////////////////////////////////////////////////////////////////// //
570 XRM_MSTIME
, // positive
578 XRM_STRING
, // never empty
585 yterm_bool once
; // load only once?
588 XrmQuarkList quarks
; // will be sorted
592 static IniKey inikeys
[] = {
593 {.key
="window.title", .type
=XRM_STRING
, .varptr
=&opt_title
, .once
=1},
595 {.key
="term.name", .type
=XRM_STRING
, .varptr
=&opt_term
, .once
=1},
596 {.key
="term.type", .type
=XRM_TERMTYPE
, .varptr
=&opt_term_type
, .once
=1},
597 {.key
="term.font", .type
=XRM_FONT
, .varptr
=&opt_mono_font
, .once
=1},
599 {.key
="term.font.gfx", .type
=XRM_FONTGFX
, .varptr
=&opt_terminus_gfx
, .once
=1},
600 {.key
="term.winch.delay", .type
=XRM_MSTIME
, .varptr
=&opt_winch_delay
},
602 {.key
="tabs.font", .type
=XRM_FONT
, .varptr
=&opt_tabs_font
, .once
=1},
603 {.key
="tabs.visible", .type
=XRM_TABCOUNT
, .varptr
=&opt_tabs_visible
, .once
=1},
605 {.key
="paste.primary", .type
=XRM_STRING
, .varptr
=&opt_paste_from
[0]},
606 {.key
="paste.secondary", .type
=XRM_STRING
, .varptr
=&opt_paste_from
[1]},
607 {.key
="paste.clipboard", .type
=XRM_STRING
, .varptr
=&opt_paste_from
[2]},
609 {.key
="copyto.primary", .type
=XRM_STRING
, .varptr
=&opt_copy_to
[0]},
610 {.key
="copyto.secondary", .type
=XRM_STRING
, .varptr
=&opt_copy_to
[1]},
611 {.key
="copyto.clipboard", .type
=XRM_STRING
, .varptr
=&opt_copy_to
[2]},
613 {.key
="refresh.fps", .type
=XRM_FPS
, .varptr
=&opt_fps
},
615 {.key
="history.enabled", .type
=XRM_BOOL
, .varptr
=&opt_history_enabled
},
617 {.key
="esc-esc.fix", .type
=XRM_BOOL
, .varptr
=&opt_esc_twice
},
618 {.key
="mouse.reports", .type
=XRM_BOOL
, .varptr
=&opt_mouse_reports
},
620 {.key
="cursor.blink.time", .type
=XRM_MSTIME
, .varptr
=&opt_cur_blink_time
},
621 {.key
="cursor.color0.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&curColorsFG
[0]},
622 {.key
="cursor.color0.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&curColorsBG
[0]},
623 {.key
="cursor.color1.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&curColorsFG
[1]},
624 {.key
="cursor.color1.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&curColorsBG
[1]},
625 {.key
="cursor.color.inactive", .type
=XRM_COLOR_OR_NONE
, .varptr
=&curColorsBG
[2]},
627 {.key
="color.default.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_DEFAULT_FG
]},
628 {.key
="color.default.bg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_DEFAULT_BG
]},
629 {.key
="color.default.fg.high", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_DEFAULT_HIGH_FG
]},
630 {.key
="color.default.bg.high", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_DEFAULT_HIGH_BG
]},
632 {.key
="color.bold.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_BOLD_FG
]},
633 {.key
="color.underline.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_UNDER_FG
]},
634 {.key
="color.bold.underline.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_BOLD_UNDER_FG
]},
636 {.key
="color.high.bold.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_BOLD_HIGH_FG
]},
637 {.key
="color.high.underline.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_UNDER_HIGH_FG
]},
638 {.key
="color.high.bold.underline.fg", .type
=XRM_COLOR
, .varptr
=&colorsTTY
[CIDX_BOLD_UNDER_HIGH_FG
]},
640 {.key
="tab.color.frame.fg", .type
=XRM_COLOR
, .varptr
=&tab_frame_fg
},
641 {.key
="tab.color.frame.bg", .type
=XRM_COLOR
, .varptr
=&tab_frame_bg
},
643 {.key
="tab.color.normal.bg", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_NORMAL
].bg
},
644 {.key
="tab.color.normal.text", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_NORMAL
].text
},
645 {.key
="tab.color.normal.index", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_NORMAL
].index
},
646 {.key
="tab.color.normal.ellipsis", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_NORMAL
].ellipsis
},
648 {.key
="tab.color.active.bg", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_ACTIVE
].bg
},
649 {.key
="tab.color.active.text", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_ACTIVE
].text
},
650 {.key
="tab.color.active.index", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_ACTIVE
].index
},
651 {.key
="tab.color.active.ellipsis", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_ACTIVE
].ellipsis
},
653 {.key
="tab.color.dead.bg", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD
].bg
},
654 {.key
="tab.color.dead.text", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD
].text
},
655 {.key
="tab.color.dead.index", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD
].index
},
656 {.key
="tab.color.dead.ellipsis", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD
].ellipsis
},
658 {.key
="tab.color.dead.active.bg", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD_ACTIVE
].bg
},
659 {.key
="tab.color.dead.active.text", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD_ACTIVE
].text
},
660 {.key
="tab.color.dead.active.index", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD_ACTIVE
].index
},
661 {.key
="tab.color.dead.active.ellipsis", .type
=XRM_COLOR
, .varptr
=&tab_colors
[TABC_DEAD_ACTIVE
].ellipsis
},
663 {.key
="selection.color.fg", .type
=XRM_COLOR
, .varptr
=&colorAmberFG
},
664 {.key
="selection.color.bg", .type
=XRM_COLOR
, .varptr
=&colorAmberBG
},
665 {.key
="selection.block.color.fg", .type
=XRM_COLOR
, .varptr
=&colorSelectionFG
},
666 {.key
="selection.block.color.bg", .type
=XRM_COLOR
, .varptr
=&colorSelectionBG
},
668 {.key
="selection.tint", .type
=XRM_BOOL
, .varptr
=&opt_amber_tint
},
670 {.key
="osd-menu.shadow.color", .type
=XRM_COLOR_OR_NONE
, .varptr
=&opt_osd_menu_shadow_color
},
671 {.key
="osd-menu.shadow.x-ofs", .type
=XRM_SHADOW_OFS
, .varptr
=&opt_osd_menu_shadow_xofs
},
672 {.key
="osd-menu.shadow.y-ofs", .type
=XRM_SHADOW_OFS
, .varptr
=&opt_osd_menu_shadow_yofs
},
673 {.key
="osd-menu.shadow.xofs", .type
=XRM_SHADOW_OFS
, .varptr
=&opt_osd_menu_shadow_xofs
},
674 {.key
="osd-menu.shadow.yofs", .type
=XRM_SHADOW_OFS
, .varptr
=&opt_osd_menu_shadow_yofs
},
676 {.key
="osd-menu.color.passive.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[0]},
677 {.key
="osd-menu.color.passive.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[0]},
679 {.key
="osd-menu.color.active.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_ACTIVE
]},
680 {.key
="osd-menu.color.active.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_ACTIVE
]},
682 {.key
="osd-menu.color.passive.cursor.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_CURSOR
]},
683 {.key
="osd-menu.color.passive.cursor.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_CURSOR
]},
685 {.key
="osd-menu.color.active.cursor.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_ACTIVE
]},
686 {.key
="osd-menu.color.active.cursor.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_ACTIVE
]},
688 {.key
="osd-menu.color.passive.hotkey.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_HOTKEY
]},
689 {.key
="osd-menu.color.passive.hotkey.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_HOTKEY
]},
691 {.key
="osd-menu.color.active.hotkey.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_HOTKEY
| OSD_CSCHEME_ACTIVE
]},
692 {.key
="osd-menu.color.active.hotkey.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_HOTKEY
| OSD_CSCHEME_ACTIVE
]},
694 {.key
="osd-menu.color.passive.cursor.hotkey.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_HOTKEY
]},
695 {.key
="osd-menu.color.passive.cursor.hotkey.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_HOTKEY
]},
697 {.key
="osd-menu.color.active.cursor.hotkey.bg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_bg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_HOTKEY
| OSD_CSCHEME_ACTIVE
]},
698 {.key
="osd-menu.color.active.cursor.hotkey.fg", .type
=XRM_COLOR_OR_NONE
, .varptr
=&osd_menu_fg
[OSD_CSCHEME_CURSOR
| OSD_CSCHEME_HOTKEY
| OSD_CSCHEME_ACTIVE
]},
704 //==========================================================================
708 //==========================================================================
709 static int xq_cmp_cb (const void *aa
, const void *bb
) {
710 XrmQuark a
= *(const XrmQuark
*)aa
;
711 XrmQuark b
= *(const XrmQuark
*)bb
;
712 return (a
< b
? -1 : a
> b
? +1 : 0);
716 //==========================================================================
720 //==========================================================================
721 static void prepare_ikey_name (IniKey
*ikey
) {
722 yterm_assert(ikey
!= NULL
);
723 if (ikey
->quarks
== NULL
) {
726 yterm_assert(strlen(ikey
->key
) < sizeof(ktemp
));
727 strcpy(ktemp
, ikey
->key
);
729 for (const char *tmp
= ikey
->key
; *tmp
; tmp
+= 1) {
730 if (*tmp
== '.') pqcount
+= 1;
732 ikey
->quarks
= malloc((unsigned)pqcount
* sizeof(ikey
->quarks
[0]));
734 const char *kstr
= ikey
->key
;
739 const char *ep
= strchr(kstr
, '.');
740 if (ep
== NULL
) ep
= kstr
+ strlen(kstr
);
741 const size_t klen
= (size_t)(ptrdiff_t)(ep
- kstr
);
742 yterm_assert(klen
!= 0);
743 if (klen
>= sizeof(ktemp
)) abort();
744 memcpy(ktemp
, kstr
, klen
);
747 ikey
->quarks
[pqcount
] = XrmStringToQuark(ktemp
);
751 yterm_assert(pqcount
!= 0);
752 qsort(&ikey
->quarks
[0], (size_t)pqcount
, sizeof(ikey
->quarks
[0]), xq_cmp_cb
);
753 ikey
->quarks
[pqcount
] = NULLQUARK
;
755 fprintf(stderr
, "PARSED: ");
756 for (int cc
= 0; ikey
->quarks
[cc
]; cc
+= 1) {
757 if (cc
!= 0) fputc('.', stderr
);
758 fprintf(stderr
, "%s", XrmQuarkToString(ikey
->quarks
[cc
]));
766 #define DUMP_KEY_NAME() do { \
768 while (quarks[qnn] != NULLQUARK) { \
769 if (qnn != 0) fputc('.', stderr); \
770 fprintf(stderr, "%s", XrmQuarkToString(quarks[qnn])); \
776 #define DUMP_SKKEY_NAME() do { \
778 while (qlist[qnn] != NULLQUARK) { \
779 if (qnn != 0) fputc('.', stderr); \
780 fprintf(stderr, "%s", XrmQuarkToString(qlist[qnn])); \
786 //==========================================================================
790 //==========================================================================
791 static Bool
xrm_load_inis_cb (XrmDatabase
*db
, XrmBindingList bindings
, XrmQuarkList quarks
,
792 XrmRepresentation
*type
, XrmValue
*value
, XPointer udata
)
794 (void)db
; (void)bindings
; (void)quarks
; (void)type
; (void)value
; (void)udata
;
795 //fprintf(stderr, "=====\n");
797 const char *errmsg
= NULL
;
799 if (quarks
[0] == NULLQUARK
|| quarks
[1] == NULLQUARK
) {
800 errmsg
= "invalid key name";
806 while (count
< 16 && quarks
[count
+ 1] != NULLQUARK
) {
808 if (strcmp(XrmQuarkToString(quarks
[count
+ 1]), "keybind") == 0) {
809 return xrm_keybind_cb(db
, bindings
, quarks
, type
, value
, udata
);
811 qlist
[count
] = quarks
[count
+ 1];
815 if (count
< 1 || count
> 15) return False
;
816 qlist
[count
] = NULLQUARK
;
818 qsort(&qlist
[0], (size_t)count
, sizeof(qlist
[0]), xq_cmp_cb
);
821 fprintf(stderr
, "***: "); DUMP_SKKEY_NAME(); fputc('\n', stderr
);
824 for (IniKey
*ikey
= inikeys
; ikey
->key
!= NULL
; ikey
+= 1) {
825 prepare_ikey_name(ikey
);
828 while (qlist
[pos
] != NULLQUARK
&& ikey
->quarks
[pos
] != NULLQUARK
&&
829 qlist
[pos
] == ikey
->quarks
[pos
])
833 if (qlist
[pos
] == NULLQUARK
&& ikey
->quarks
[pos
] == NULLQUARK
) {
834 if (ikey
->sealed
) return False
; // this option is sealed
835 if (type
== NULL
|| strcmp(XrmQuarkToString(*type
), "String") != 0) {
836 errmsg
= "invalid key type";
839 char *sval
= xrm_val_to_val(value
);
841 errmsg
= "invalid key value";
844 switch (ikey
->type
) {
847 int bval
= parse_bool(sval
);
849 errmsg
= "invalid boolean value";
852 *(yterm_bool
*)ikey
->varptr
= bval
;
855 case XRM_MSTIME
: // positive
857 int bval
= parse_bool(sval
);
859 *(int *)ikey
->varptr
= 0;
862 long v
= strtol(sval
, &end
, 10);
863 if (*end
|| v
< 0 || v
> 2666) {
864 errmsg
= "invalid time value";
867 *(int *)ikey
->varptr
= (int)v
;
874 long v
= strtol(sval
, &end
, 10);
875 if (*end
|| v
< 1 || v
> 120) {
876 errmsg
= "invalid FPS value";
879 *(int *)ikey
->varptr
= (int)v
;
885 long v
= strtol(sval
, &end
, 10);
886 if (*end
|| v
< 1 || v
> 64) {
887 errmsg
= "invalid shadow offset value";
890 *(int *)ikey
->varptr
= (int)v
;
896 long v
= strtol(sval
, &end
, 10);
897 if (*end
|| v
< 0 || v
> 32) {
898 int bval
= parse_bool(sval
);
900 errmsg
= "invalid tab count value";
903 opt_enable_tabs
= bval
;
908 *(int *)ikey
->varptr
= (int)v
;
915 char **sptr
= (char **)ikey
->varptr
;
917 *sptr
= strdup(sval
);
918 if (*sptr
== NULL
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
923 uint32_t clr
= parse_hex_color(sval
);
924 if (clr
== XRM_BAD_COLOR
) {
925 errmsg
= "invalid color value";
928 *(uint32_t *)ikey
->varptr
= clr
;
931 case XRM_COLOR_OR_NONE
:
933 if (strEquCI(sval
, "none")) {
934 *(uint32_t *)ikey
->varptr
= 0xff000000U
;
936 uint32_t clr
= parse_hex_color(sval
);
937 if (clr
== XRM_BAD_COLOR
) {
938 errmsg
= "invalid color value";
941 *(uint32_t *)ikey
->varptr
= clr
;
945 case XRM_STRING
: // never empty
947 char **sptr
= (char **)ikey
->varptr
;
949 *sptr
= strdup(sval
);
950 if (*sptr
== NULL
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
954 if (strEquCI(sval
, "rxvt")) opt_term_type
= TT_RXVT
;
955 else if (strEquCI(sval
, "xterm")) opt_term_type
= TT_XTERM
;
957 errmsg
= "invalid terminal type";
962 if (strEquCI(sval
, "terminus")) opt_terminus_gfx
= 1;
963 else if (strEquCI(sval
, "unicode")) opt_terminus_gfx
= 0;
965 errmsg
= "invalid font gfx type";
970 fprintf(stderr
, "INTERNAL ERROR: ketmar forgot to handle some ini type!\n");
974 fprintf(stderr
, "OK KEY: "); DUMP_KEY_NAME(); fputc('\n', stderr
);
975 fprintf(stderr
, " type: %d; val=<%s>\n", ikey
->type
, sval
);
983 const char *qn
= XrmQuarkToString(qlist
[0]);
985 for (int f
= 0; idx
== -1 && f
< 16; f
+= 1) {
987 snprintf(kname
, sizeof(kname
), "color%d", f
);
988 if (strcmp(qn
, kname
) == 0) idx
= f
;
990 snprintf(kname
, sizeof(kname
), "color0%d", f
);
991 if (strcmp(qn
, kname
) == 0) idx
= f
;
995 yterm_assert(idx
>= 0 && idx
<= 15);
997 fprintf(stderr
, "TTYCOLOR %d KEY: ", idx
); DUMP_KEY_NAME(); fputc('\n', stderr
);
999 char *sval
= xrm_val_to_val(value
);
1001 errmsg
= "invalid key value";
1004 uint32_t clr
= parse_hex_color(sval
);
1005 if (clr
== XRM_BAD_COLOR
) {
1006 errmsg
= "invalid color value";
1009 colorsTTY
[idx
] = clr
;
1014 fprintf(stderr
, "UNKNOWN KEY: "); DUMP_KEY_NAME(); fputc('\n', stderr
);
1019 if (xrm_reloading
) {
1020 show_error_menu(errmsg
, quarks
);
1023 fprintf(stderr
, "CONFIG ERROR: %s!\n", errmsg
);
1024 fprintf(stderr
, " key: ");
1026 while (quarks
[f
] != NULLQUARK
) {
1027 const char *qq
= XrmQuarkToString(quarks
[f
]);
1028 if (f
!= 0) fputc('.', stderr
);
1029 fprintf(stderr
, "%s", qq
);
1032 fputc('\n', stderr
);
1035 fprintf(stderr
, " type: %s\n", XrmQuarkToString(*type
));
1036 if (strcmp(XrmQuarkToString(*type
), "String") == 0) {
1037 fprintf(stderr
, " value: <%.*s>\n", (unsigned)value
->size
, (const char *)value
->addr
);
1041 if (!xrm_reloading
) exit(1);
1046 //==========================================================================
1050 //==========================================================================
1051 static void xrm_load_inis (XrmDatabase db
) {
1053 XrmQuark classes
[2];
1055 names
[0] = XrmPermStringToQuark(xrm_app_name
);
1056 names
[1] = NULLQUARK
;
1058 classes
[0] = NULLQUARK
;
1060 XrmEnumerateDatabase(db
, names
, classes
, XrmEnumAllLevels
, xrm_load_inis_cb
, NULL
);
1064 //==========================================================================
1066 // xrm_seal_option_by_ptr
1068 //==========================================================================
1069 static void xrm_seal_option_by_ptr (const void *ptr
) {
1070 for (IniKey
*ikey
= inikeys
; ikey
->key
!= NULL
; ikey
+= 1) {
1071 if (ikey
->varptr
== ptr
&& ikey
->sealed
== 0) {
1078 //==========================================================================
1080 // xrm_is_option_sealed_by_ptr
1082 //==========================================================================
1083 static yterm_bool
xrm_is_option_sealed_by_ptr (const void *ptr
) {
1085 for (IniKey
*ikey
= inikeys
; res
== 0 && ikey
->key
!= NULL
; ikey
+= 1) {
1086 res
= (ikey
->varptr
== ptr
&& ikey
->sealed
== -1);
1092 //==========================================================================
1094 // xrm_unseal_ptr_options
1096 //==========================================================================
1097 static void xrm_unseal_ptr_options (void) {
1098 for (IniKey
*ikey
= inikeys
; ikey
->key
!= NULL
; ikey
+= 1) {
1099 if (ikey
->sealed
== -1) ikey
->sealed
= 0;
1104 //==========================================================================
1106 // xrm_new_command_keybind
1108 //==========================================================================
1109 static void xrm_new_command_keybind (const char *name
, const char *keys
, int cmd
) {
1110 yterm_assert(name
!= NULL
);
1111 yterm_assert(keys
!= NULL
);
1112 KeyBind
*kb
= malloc(sizeof(KeyBind
));
1113 if (!kb
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
1114 memset(kb
, 0, sizeof(KeyBind
));
1115 kb
->bindname
= strdup(name
);
1116 if (!kb
->bindname
) abort();
1117 if (!parse_keybind(kb
, keys
)) abort();
1119 kb
->killsignal
= cmd
;
1120 kb
->allow_history
= -1;
1121 kb
->next
= keybinds
;
1126 //==========================================================================
1128 // xrm_new_exec_keybind
1130 //==========================================================================
1131 static void xrm_new_exec_keybind (const char *name
, const char *keys
,
1132 const char *exec
, const char *path
)
1134 yterm_assert(name
!= NULL
);
1135 yterm_assert(keys
!= NULL
);
1136 yterm_assert(exec
!= NULL
);
1137 yterm_assert(path
!= NULL
);
1138 KeyBind
*kb
= malloc(sizeof(KeyBind
));
1139 if (!kb
) { fprintf(stderr
, "FATAL: out of memory!\n"); abort(); }
1140 memset(kb
, 0, sizeof(KeyBind
));
1141 kb
->bindname
= strdup(name
);
1142 if (!kb
->bindname
) abort();
1143 if (!parse_keybind(kb
, keys
)) abort();
1146 kb
->allow_history
= -1;
1147 kb
->exec
= strdup(exec
);
1148 if (!kb
->exec
) abort();
1149 kb
->path
= strdup(path
);
1150 if (!kb
->path
) abort();
1151 kb
->next
= keybinds
;
1156 //==========================================================================
1158 // xrm_add_default_keybinds
1160 //==========================================================================
1161 static void xrm_add_default_keybinds (void) {
1162 fprintf(stderr
, "adding default keybindings...\n");
1164 xrm_new_command_keybind("start-selection", "C-space", KB_CMD_START_SELECTION
);
1165 xrm_new_command_keybind("start-selection1", "C-KP_Insert", KB_CMD_START_SELECTION
);
1166 xrm_new_command_keybind("start-selection2", "M-KP_Insert", KB_CMD_START_SELECTION
);
1168 xrm_new_command_keybind("paste-primary", "S-Insert", KB_CMD_PASTE_PRIMARY
);
1169 xrm_new_command_keybind("paste-secondary", "M-Insert", KB_CMD_PASTE_SECONDARY
);
1170 xrm_new_command_keybind("paste-clipboard", "M-S-Insert", KB_CMD_PASTE_CLIPBOARD
);
1172 xrm_new_command_keybind("copy-to-primary", "S-Insert", KB_CMD_COPY_TO_PRIMARY
);
1173 xrm_new_command_keybind("copy-to-secondary", "M-Insert", KB_CMD_COPY_TO_SECONDARY
);
1174 xrm_new_command_keybind("copy-to-clipboard", "M-S-Insert", KB_CMD_COPY_TO_CLIPBOARD
);
1175 xrm_new_command_keybind("copy-to-primary", "M-S-c", KB_CMD_COPY_TO_PRIMARY
);
1177 xrm_new_command_keybind("prev-tab", "C-M-Left", KB_CMD_TAB_PREV
);
1178 xrm_new_command_keybind("next-tab", "C-M-Right", KB_CMD_TAB_NEXT
);
1179 xrm_new_command_keybind("first-tab", "C-M-Home", KB_CMD_TAB_FIRST
);
1180 xrm_new_command_keybind("last-tab", "C-M-End", KB_CMD_TAB_LAST
);
1181 xrm_new_command_keybind("tab-to-left", "M-S-Left", KB_CMD_TAB_MOVE_LEFT
);
1182 xrm_new_command_keybind("tab-to-right", "M-S-Right", KB_CMD_TAB_MOVE_RIGHT
);
1184 xrm_new_command_keybind("kill-process", "C-H-k", SIGKILL
);
1186 xrm_new_exec_keybind("newtab", "C-M-t", "$SHELL", "$PWD");
1187 xrm_new_exec_keybind("root-shell", "C-M-r", "suka -F -", "$PWD");
1188 keybinds
->colorMode
= CMODE_GREEN
;
1189 xrm_new_exec_keybind("mc", "C-M-m", "mc", "$PWD");
1191 xrm_new_command_keybind("menu-tab-options", "Menu", KB_CMD_MENU_TAB_OPTIONS
);
1195 //==========================================================================
1199 //==========================================================================
1200 static void xrm_load_options (void) {
1203 // some idiotic X11 instances doesn't have a system-wide resources
1204 // WARNING! don't free `sysdbstr()`! that's how it works.
1205 char *sysdbstr
= XResourceManagerString(x11_dpy
);
1206 XrmDatabase db
= XrmGetStringDatabase(sysdbstr
!= NULL
? sysdbstr
: "");
1209 while (keybinds
!= NULL
) {
1210 KeyBind
*kb
= keybinds
;
1211 keybinds
= keybinds
->next
;
1217 // load local settings
1219 const char *home
= getenv("HOME");
1220 if (home
&& home
[0]) {
1221 char *fname
= malloc(strlen(home
) + 128);
1222 strcpy(fname
, home
);
1223 if (home
[strlen(home
) - 1] != '/') strcat(fname
, "/");
1224 strcat(fname
, ".k8-yterm.Xresources");
1225 //fprintf(stderr, "<%s>\n", fname);
1227 if (XrmCombineFileDatabase(fname
, &db
, True
) == 0) {
1228 //fprintf(stderr, "SHIT!\n");
1231 db
= XrmGetFileDatabase(fname
);
1238 //xrm_load_keybinds(db);
1241 for (IniKey
*ikey
= inikeys
; ikey
->key
!= NULL
; ikey
+= 1) {
1243 ikey
->quarks
= NULL
;
1246 XrmDestroyDatabase(db
);
1248 yterm_assert(opt_tabs_visible
> 0);
1249 // check if we have more than one tab open, and don't disable tabs in this case
1250 if (!opt_enable_tabs
) {
1251 Term
*tt
= termlist
;
1252 while (tt
!= NULL
&& tt
->deadstate
== DS_DEAD
) tt
= tt
->next
;
1253 if (tt
!= NULL
) opt_enable_tabs
= 1;
1257 for (IniKey
*ikey
= inikeys
; ikey
->key
!= NULL
; ikey
+= 1) {
1258 if (ikey
->once
) ikey
->sealed
= 1;
1261 // remove dead keybinds
1262 KeyBind
*prev
= NULL
;
1264 KeyBind
*kb
= keybinds
;
1265 while (kb
!= NULL
) {
1266 if (kb
->ksym
== NoSymbol
|| kb
->killsignal
== KB_CMD_IGNORE
||
1267 (kb
->killsignal
<= 0 && kb
->exec
== NULL
))
1269 fprintf(stderr
, "XRM: removed empty/disabled keybind '%s'\n", kb
->bindname
);
1273 if (prev
!= NULL
) prev
->next
= kb
->next
; else keybinds
= kb
->next
;
1278 prev
= kb
; kb
= kb
->next
;
1282 // if we have no keybinds, add default
1283 if (keybinds
== NULL
) xrm_add_default_keybinds();
1285 // check for keybind conflicts
1286 for (kb
= keybinds
; kb
!= NULL
; kb
= kb
->next
) {
1287 for (KeyBind
*nkb
= kb
->next
; nkb
!= NULL
; nkb
= nkb
->next
) {
1288 if (nkb
!= kb
&& nkb
->ksym
== kb
->ksym
&& nkb
->mods
== kb
->mods
) {
1290 if (kb
->killsignal
== KB_CMD_PASTE_PRIMARY
||
1291 kb
->killsignal
== KB_CMD_PASTE_SECONDARY
||
1292 kb
->killsignal
== KB_CMD_PASTE_CLIPBOARD
)
1294 bad
= nkb
->killsignal
!= KB_CMD_COPY_TO_PRIMARY
&&
1295 nkb
->killsignal
!= KB_CMD_COPY_TO_SECONDARY
&&
1296 nkb
->killsignal
!= KB_CMD_COPY_TO_CLIPBOARD
;
1297 } else if (kb
->killsignal
== KB_CMD_COPY_TO_PRIMARY
||
1298 kb
->killsignal
== KB_CMD_COPY_TO_SECONDARY
||
1299 kb
->killsignal
== KB_CMD_COPY_TO_CLIPBOARD
)
1301 bad
= nkb
->killsignal
!= KB_CMD_PASTE_PRIMARY
&&
1302 nkb
->killsignal
!= KB_CMD_PASTE_SECONDARY
&&
1303 nkb
->killsignal
!= KB_CMD_PASTE_CLIPBOARD
;
1306 fprintf(stderr
, "WARNING! keybind '%s' conflicts with '%s'!\n",
1307 kb
->bindname
, nkb
->bindname
);
1315 if (keybinds
!= NULL
) {
1316 fprintf(stderr
, "=== KEYBINDS ===\n");
1317 for (kb
= keybinds
; kb
!= NULL
; kb
= kb
->next
) {
1318 const char *ksname
= XKeysymToString(kb
->ksym
);
1319 fprintf(stderr
, "--- %s ---\n", kb
->bindname
);
1320 fprintf(stderr
, " key: ");
1321 if (kb
->mods
& ControlMask
) fprintf(stderr
, "C-");
1322 if (kb
->mods
& Mod1Mask
) fprintf(stderr
, "M-");
1323 if (kb
->mods
& Mod4Mask
) fprintf(stderr
, "H-");
1324 if (kb
->mods
& ShiftMask
) fprintf(stderr
, "S-");
1325 fprintf(stderr
, "%s\n", ksname
);
1326 fprintf(stderr
, " path: %s\n", (kb
->path
!= NULL
? kb
->path
: "<default>"));
1327 fprintf(stderr
, " exec: %s\n", (kb
->exec
!= NULL
? kb
->exec
: "<none>"));
1328 if (kb
->killsignal
>= 600) {
1329 fprintf(stderr
, " command: %d\n", kb
->killsignal
);
1330 } else if (kb
->killsignal
> 0) {
1331 fprintf(stderr
, " kill: %d\n", kb
->killsignal
);
1333 fprintf(stderr
, " kill: <none>\n");
1340 fprintf(stderr
, "NOTE: cannot load X resources database (meh).\n");