4 * (C) 1992 Joseph H. Allen;
6 * This file is part of JOE (Joe's Own Editor)
12 __RCSID("$MirOS: contrib/code/jupp/rc.c,v 1.26 2017/12/02 04:32:41 tg Exp $");
19 #ifdef HAVE_BSD_STRING_H
20 #include <bsd/string.h>
42 #define OPT_BUF_SIZE 60
44 static struct context {
48 } *contexts = NULL; /* List of named contexts */
50 /* Find a context of a given name- if not found, one with an empty kmap
54 KMAP *kmap_getcontext(unsigned char *name, int docreate)
58 for (c = contexts; c; c = c->next)
59 if (!strcmp(c->name, name))
65 c = (struct context *) joe_malloc(sizeof(struct context));
68 c->name = (unsigned char *)strdup((char *)name);
70 return c->kmap = mkkmap();
73 OPTIONS *options = NULL;
75 /* Global variable options */
76 extern int mid, dspasis, dspctrl, help, square, csmode, nobackups, lightoff, exask, skiptop;
77 extern int noxon, lines, columns, Baud, dopadding, orphan, marking, keepup, nonotice;
78 extern int notite, pastetite, usetabs, assume_color, guesscrlf, guessindent, menu_explorer, icase, wrap, autoswap;
79 extern unsigned char *backpath;
81 /* Default options for prompt windows */
85 NULL, /* *name_regex */
86 NULL, /* *contents_regex */
93 ' ', /* indent char */
101 0, /* french spacing */
109 NULL, /* Syntax name */
111 NULL, /* Name of character set */
112 NULL, /* Character set */
113 0, /* Smart home key */
114 0, /* Goto indent first */
115 0, /* Smart backspace key */
116 0, /* Purify indentation */
117 0, /* Picture mode */
118 NULL, /* macro to execute for new files */
119 NULL, /* macro to execute for existing files */
120 NULL, /* macro to execute before saving new files */
121 NULL, /* macro to execute before saving existing files */
122 0, /* visible spaces */
126 /* Default options for file windows */
128 char main_context[] = "main";
131 NULL, /* *name_regex */
132 NULL, /* *contents_regex */
139 ' ', /* indent char */
141 US main_context, /* *context */
142 US "\\i%n %m %M", /* *lmsg */
143 US " %S Ctrl-K H for help", /* *rmsg */
145 0, /* line numbers */
147 0, /* french spacing */
155 NULL, /* Syntax name */
157 NULL, /* Name of character set */
158 NULL, /* Character set */
159 0, /* Smart home key */
160 0, /* Goto indent first */
161 0, /* Smart backspace key */
162 0, /* Purity indentation */
163 0, /* Picture mode */
164 NULL, NULL, NULL, NULL, /* macros (see above) */
165 0, /* visible spaces */
171 void lazy_opts(OPTIONS *o)
173 o->syntax = load_dfa(o->syntax_name);
174 o->charmap = find_charmap(o->map_name);
176 o->charmap = fdefault.charmap;
177 /* Hex not allowed with UTF-8 */
178 if (o->hex && o->charmap->type) {
179 o->charmap = find_charmap(US "c");
183 /* Set local options depending on file name and contents */
185 void setopt(B *b, unsigned char *parsed_name)
189 unsigned char *pieces[26];
190 for (x = 0; x!=26; ++x)
193 for (o = options; o; o = o->next)
194 if (rmatch(o->name_regex, parsed_name)) {
195 if(o->contents_regex) {
197 if (pmatch(pieces,o->contents_regex,strlen((char *)o->contents_regex),p,0,0)) {
216 for (x = 0; x!=26; ++x)
220 /* Table of options and how to set them */
222 /* local means it's in an OPTION structure, global means it's in a global
226 unsigned char *name; /* Option name */
227 int type; /* 0 for global option flag
228 1 for global option numeric
229 2 for global option string
230 4 for local option flag
231 5 for local option numeric
232 6 for local option string
233 7 for local option numeric+1, with range checking
235 int *set; /* Address of global option */
236 unsigned char *addr; /* Local options structure member address */
237 unsigned char *yes; /* Message if option was turned on, or prompt string */
238 unsigned char *no; /* Message if option was turned off */
239 unsigned char *menu; /* Menu string */
240 int ofst; /* Local options structure member offset */
241 int low; /* Low limit for numeric options */
242 int high; /* High limit for numeric options */
244 {US "noxon", 0, &noxon, NULL, US "XON/XOFF processing disabled", US "XON/XOFF processing enabled", US " XON/XOFF usable " },
245 {US "keepup", 0, &keepup, NULL, US "Status line updated constantly", US "Status line updated once/sec", US " Fast status line " },
246 {US "baud", 1, &Baud, NULL, US "Terminal baud rate (%d): ", 0, US " Baud rate ", 0, 0, 38400 },
247 {US "overwrite",4, NULL, (unsigned char *) &fdefault.overtype, US "Overtype mode", US "Insert mode", US "T Overtype " },
248 {US "autoindent", 4, NULL, (unsigned char *) &fdefault.autoindent, US "Autoindent enabled", US "Autoindent disabled", US "I Autoindent " },
249 {US "wordwrap", 4, NULL, (unsigned char *) &fdefault.wordwrap, US "Wordwrap enabled", US "Wordwrap disabled", US "Word wrap " },
250 {US "tab", 5, NULL, (unsigned char *) &fdefault.tab, US "Tab width (%d): ", 0, US "D Tab width ", 0, 1, 64 },
251 {US "lmargin", 7, NULL, (unsigned char *) &fdefault.lmargin, US "Left margin (%d): ", 0, US "Left margin ", 0, 0, 63 },
252 {US "rmargin", 7, NULL, (unsigned char *) &fdefault.rmargin, US "Right margin (%d): ", 0, US "Right margin ", 0, 7, 255 },
253 {US "square", 0, &square, NULL, US "Rectangle mode", US "Text-stream mode", US "X Rectangle mode " },
254 {US "icase", 0, &icase, NULL, US "Ignore case by default", US "Case sensitive by default", US " Case insensitive " },
255 {US "wrap", 0, &wrap, NULL, US "Search wraps", US "Search doesn't wrap", US " Search wraps " },
256 {US "menu_explorer", 0, &menu_explorer, NULL, US "Menu explorer mode", US " Simple completion", US " Menu explorer " },
257 {US "autoswap", 0, &autoswap, NULL, US "Autoswap ^KB and ^KK", US " Autoswap off ", US " Autoswap mode " },
258 {US "indentc", 5, NULL, (unsigned char *) &fdefault.indentc, US "Indent char %d (SPACE=32, TAB=9, ^C to abort): ", 0, US " Indent char ", 0, 0, 255 },
259 {US "istep", 5, NULL, (unsigned char *) &fdefault.istep, US "Indent step %d (^C to abort): ", 0, US " Indent step ", 0, 1, 64 },
260 {US "french", 4, NULL, (unsigned char *) &fdefault.french, US "One space after periods for paragraph reformat", US "Two spaces after periods for paragraph reformat", US " French spacing " },
261 {US "highlight", 4, NULL, (unsigned char *) &fdefault.highlight, US "Highlighting enabled", US "Highlighting disabled", US "Highlighting " },
262 {US "spaces", 4, NULL, (unsigned char *) &fdefault.spaces, US "Inserting spaces when tab key is hit", US "Inserting tabs when tab key is hit", US " Disable tabs " },
263 {US "mid", 0, &mid, NULL, US "Cursor will be recentered on scrolls", US "Cursor will not be recentered on scroll", US "Center on scroll " },
264 {US "guess_crlf",0, &guesscrlf, NULL, US "Automatically detect MS-DOS files", US "Do not automatically detect MS-DOS files", US " Auto detect CR-LF " },
265 {US "guess_indent",0, &guessindent, NULL, US "Automatically detect indentation", US "Do not automatically detect indentation", US " Guess indent " },
266 {US "crlf", 4, NULL, (unsigned char *) &fdefault.crlf, US "CR-LF is line terminator", US "LF is line terminator", US "Z CR-LF (MS-DOS) " },
267 {US "linums", 4, NULL, (unsigned char *) &fdefault.linums, US "Line numbers enabled", US "Line numbers disabled", US "N Line numbers " },
268 {US "marking", 0, &marking, NULL, US "Anchored block marking on", US "Anchored block marking off", US "Marking " },
269 {US "asis", 0, &dspasis, NULL, US "Characters above 127 shown as-is", US "Characters above 127 shown in inverse", US " Meta chars as-is " },
270 {US "force", 0, &force, NULL, US "Last line forced to have NL when file saved", US "Last line not forced to have NL", US "Force last NL " },
271 {US "nobackups", 0, &nobackups, NULL, US "Backup files will not be made", US "Backup files will be made", US " Disable backups " },
272 {US "lightoff", 0, &lightoff, NULL, US "Highlighting turned off after block operations", US "Highlighting not turned off after block operations", US "Auto unmark " },
273 {US "exask", 0, &exask, NULL, US "Prompt for filename in save & exit command", US "Don't prompt for filename in save & exit command", US " Exit ask " },
274 {US "beep", 0, &dobeep, NULL, US "Warning bell enabled", US "Warning bell disabled", US "Beeps " },
275 {US "nosta", 0, &staen, NULL, US "Top-most status line disabled", US "Top-most status line enabled", US " Disable status " },
276 {US "pg", 1, &pgamnt, NULL, US "Lines to keep for PgUp/PgDn or -1 for 1/2 window (%d): ", 0, US " # PgUp/PgDn lines ", 0, -1, 64 },
277 {US "csmode", 0, &csmode, NULL, US "Start search after a search repeats previous search", US "Start search always starts a new search", US "Continued search " },
278 {US "rdonly", 4, NULL, (unsigned char *) &fdefault.readonly, US "Read only", US "Full editing", US "O Read only " },
279 {US "smarthome", 4, NULL, (unsigned char *) &fdefault.smarthome, US "Smart home key enabled", US "Smart home key disabled", US " Smart home key " },
280 {US "indentfirst", 4, NULL, (unsigned char *) &fdefault.indentfirst, US "Smart home goes to indent first", US "Smart home goes home first", US " To indent first " },
281 {US "smartbacks", 4, NULL, (unsigned char *) &fdefault.smartbacks, US "Smart backspace key enabled", US "Smart backspace key disabled", US " Smart backspace " },
282 {US "purify", 4, NULL, (unsigned char *) &fdefault.purify, US "Indentation clean up enabled", US "Indentation clean up disabled", US " Clean up indents " },
283 {US "picture", 4, NULL, (unsigned char *) &fdefault.picture, US "Picture drawing mode enabled", US "Picture drawing mode disabled", US "Picture mode " },
284 {US "backpath", 2, (int *) &backpath, NULL, US "Backup files stored in (%s): ", 0, US " Backup file path " },
285 {US "vispace", 4, NULL, (unsigned char *) &fdefault.vispace, US "Spaces visible", US "Spaces invisible", US "Visible spaces " },
286 {US "hex", 4, NULL, (unsigned char *) &fdefault.hex, US "Hex edit mode", US "Text edit mode", US "G Hexedit mode "},
287 {US "syntax", 9, NULL, NULL, US "Select syntax (%s; ^C to abort): ", 0, US "Y Syntax" },
288 {US "encoding",13, NULL, NULL, US "Select file character set (%s; ^C to abort): ", 0, US "Encoding " },
289 {US "nonotice", 0, &nonotice, NULL, 0, 0, 0 },
290 {US "orphan", 0, &orphan, NULL, 0, 0, 0 },
291 {US "help", 0, &help, NULL, 0, 0, 0 },
292 {US "dopadding", 0, &dopadding, NULL, 0, 0, 0 },
293 {US "lines", 1, &lines, NULL, 0, 0, 0, 0, 2, 1024 },
294 {US "columns", 1, &columns, NULL, 0, 0, 0, 0, 2, 1024 },
295 {US "skiptop", 1, &skiptop, NULL, 0, 0, 0, 0, 0, 64 },
296 {US "notite", 0, ¬ite, NULL, 0, 0, 0 },
297 {US "pastetite", 0, &pastetite, NULL, 0, 0, 0 },
298 {US "usetabs", 0, &usetabs, NULL, 0, 0, 0 },
299 {US "assume_color", 0, &assume_color, NULL, 0, 0, 0 },
300 { NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
303 /* Initialize .ofsts above. Is this really necessary? */
307 static void izopts(void)
311 for (x = 0; glopts[x].name; ++x)
312 switch (glopts[x].type) {
318 glopts[x].ofst = glopts[x].addr - (unsigned char *) &fdefault;
323 /* Set a global or local option:
325 * 'arg' is a possible argument string (taken only if option has an arg)
326 * 'options' points to options structure to modify (can be NULL).
327 * 'set'==0: set only in 'options' if it's given.
328 * 'set'!=0: set global variable option.
329 * return value: no. of fields taken (1 or 2), or 0 if option not found.
331 * So this function is used both to set options, and to parse over options
332 * without setting them.
334 * These combinations are used:
336 * glopt(name,arg,NULL,1): set global variable option
337 * glopt(name,arg,NULL,0): parse over option
338 * glopt(name,arg,options,0): set file local option
339 * glopt(name,arg,&fdefault,1): set default file options
340 * glopt(name,arg,options,1): set file local option
343 int glopt(unsigned char *s, unsigned char *arg, OPTIONS *options_, int set)
347 int st = 1; /* 1 to set option, 0 to clear it */
350 /* Initialize offsets */
354 /* Clear instead of set? */
360 for (x = 0; glopts[x].name; ++x)
361 if (!strcmp(glopts[x].name, s)) {
362 switch (glopts[x].type) {
363 case 0: /* Global variable flag option */
367 case 1: /* Global variable integer option */
369 sscanf((char *)arg, "%d", &val);
370 if (val >= glopts[x].low && val <= glopts[x].high)
371 *glopts[x].set = val;
374 case 2: /* Global variable string option */
377 *(unsigned char **) glopts[x].set = (unsigned char *)strdup((char *)arg);
379 *(unsigned char **) glopts[x].set = 0;
382 case 4: /* Local option flag */
384 *(int *) ((unsigned char *) options_ + glopts[x].ofst) = st;
386 case 5: /* Local option integer */
389 sscanf((char *)arg, "%d", &val);
390 if (val >= glopts[x].low && val <= glopts[x].high)
391 *(int *) ((unsigned char *)
392 options_ + glopts[x].ofst) = val;
396 case 7: /* Local option numeric + 1, with range checking */
400 sscanf((char *)arg, "%d", &zz);
401 if (zz >= glopts[x].low && zz <= glopts[x].high) {
404 *(int *) ((unsigned char *)
405 options_ + glopts[x].ofst) = zz;
410 case 9: /* Set syntax */
412 options_->syntax_name = (unsigned char *)strdup((char *)arg);
413 /* this was causing all syntax files to be loaded...
415 options_->syntax = load_dfa(arg); */
418 case 13: /* Set byte mode encoding */
420 options_->map_name = (unsigned char *)strdup((char *)arg);
423 /* This is a stupid hack... */
424 if ((glopts[x].type & 3) == 0 || !arg)
429 /* Why no case 6, string option? */
430 /* Keymap, mold, mnew, etc. are not strings */
431 /* These options do not show up in ^T */
432 if (!strcmp(s, "lmsg")) {
435 options_->lmsg = (unsigned char *)strdup((char *)arg);
439 } else if (!strcmp(s, "rmsg")) {
442 options_->rmsg = (unsigned char *)strdup((char *)arg);
446 } else if (!strcmp(s, "hmsg")) {
449 options_->hmsg = strdup((char *)arg);
453 } else if (!strcmp(s, "keymap")) {
456 options_->context = (unsigned char *)strdup((char *)arg);
460 } else if (!strcmp(s, "mnew")) {
465 options_->mnew = mparse(NULL, arg, &sta);
469 } else if (!strcmp(s, "mold")) {
474 options_->mold = mparse(NULL, arg, &sta);
478 } else if (!strcmp(s, "msnew")) {
483 options_->msnew = mparse(NULL, arg, &sta);
487 } else if (!strcmp(s, "msold")) {
492 options_->msold = mparse(NULL, arg, &sta);
501 /* Option setting user interface (^T command) */
503 static int optx = 0; /* Menu cursor position: remember it for next time */
505 static int doabrt1(BW *bw, int *xx)
511 static int doopt1(BW *bw, unsigned char *s, int *xx, int *notify)
518 switch (glopts[x].type) {
526 msgnw(bw->parent, merrt);
528 } else if (v >= glopts[x].low && v <= glopts[x].high)
531 msgnw(bw->parent, US "Value out of range");
537 *(unsigned char **) glopts[x].set = (unsigned char *)strdup((char *)s);
546 msgnw(bw->parent, merrt);
548 } else if (v >= glopts[x].low && v <= glopts[x].high)
549 *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) = v;
551 msgnw(bw->parent, US "Value out of range");
562 msgnw(bw->parent, merrt);
564 } else if (v >= glopts[x].low && v <= glopts[x].high)
565 *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) = v;
567 msgnw(bw->parent, US "Value out of range");
581 static int dosyntax(BW *bw, unsigned char *s, int *xx, int *notify)
584 struct high_syntax *syn;
587 if ((syn = load_dfa(s)))
590 msgnw(bw->parent, US "Syntax definition file not found");
602 unsigned char **syntaxes = NULL; /* Array of available syntaxes */
604 static int syntaxcmplt(BW *bw)
607 unsigned char *oldpwd = pwd();
612 if (chJpwd(US ("syntax")))
614 t = rexpnd(US "*.jsf");
625 for (x = 0; x != aLEN(t); ++x) {
626 unsigned char *r = vsncpy(NULL,0,t[x],(unsigned char *)strrchr((char *)(t[x]),'.')-t[x]);
627 syntaxes = vaadd(syntaxes,r);
631 p = (unsigned char *)getenv("HOME");
633 unsigned char buf[1024];
634 joe_snprintf_1((char *)buf,sizeof(buf),"%s/.jupp/syntax",p);
635 if (!chpwd(buf) && (t = rexpnd(US "*.jsf"))) {
636 for (x = 0; x != aLEN(t); ++x)
637 *strrchr((char *)t[x],'.') = 0;
638 for (x = 0; x != aLEN(t); ++x) {
639 for (y = 0; y != aLEN(syntaxes); ++y)
640 if (!strcmp(t[x],syntaxes[y]))
642 if (y == aLEN(syntaxes)) {
643 unsigned char *r = vsncpy(NULL,0,sv(t[x]));
644 syntaxes = vaadd(syntaxes,r);
651 vasort(av(syntaxes));
654 return simple_cmplt(bw,syntaxes);
657 int check_for_hex(BW *bw)
662 for (w = bw->parent->link.next; w != bw->parent; w = w->link.next)
663 if ((w->watom == &watomtw || w->watom == &watompw) && ((BW *)w->object)->b == bw->b &&
664 ((BW *)w->object)->o.hex)
669 static int doencoding(BW *bw, unsigned char *s, int *xx, int *notify)
675 map = find_charmap(s);
677 map = fdefault.charmap;
679 if (map && map->type && check_for_hex(bw)) {
680 msgnw(bw->parent, US "UTF-8 encoding not allowed with hex-edit windows");
688 joe_snprintf_1((char *)msgbuf, JOE_MSGBUFSIZE, "%s encoding assumed for this file", map->name);
689 msgnw(bw->parent, msgbuf);
691 msgnw(bw->parent, US "Character set not found");
701 unsigned char **encodings = NULL; /* Array of available encodinges */
703 static int encodingcmplt(BW *bw)
706 encodings = get_encodings();
707 vasort(av(encodings));
709 return simple_cmplt(bw,encodings);
712 static int doopt(MENU *m, int x, void *object, int flg)
714 BW *bw = m->parent->win->object;
716 unsigned char buf[OPT_BUF_SIZE];
717 int *notify = m->parent->notify;
719 switch (glopts[x].type) {
722 *glopts[x].set = !*glopts[x].set;
728 msgnw(bw->parent, *glopts[x].set ? glopts[x].yes : glopts[x].no);
729 if (glopts[x].set == &noxon)
734 *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) = !*(int *) ((unsigned char *) &bw->o + glopts[x].ofst);
736 *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) = 1;
738 *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) = 0;
740 msgnw(bw->parent, *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) ? glopts[x].yes : glopts[x].no);
741 if (glopts[x].ofst == (unsigned char *) &fdefault.readonly - (unsigned char *) &fdefault)
742 bw->b->rdonly = bw->o.readonly;
743 /* Kill UTF-8 and CR-LF mode if we switch to hex display */
744 if (glopts[x].ofst == (unsigned char *)&fdefault.hex - (unsigned char *)&fdefault &&
746 if (bw->b->o.charmap->type) {
747 doencoding(bw, vsncpy(NULL, 0, sc("C")),
754 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes, *glopts[x].set);
755 xx = (int *) joe_malloc(sizeof(int));
758 m->parent->notify = 0;
760 if (wmkpw(bw->parent, buf, NULL, doopt1, NULL, doabrt1, utypebw, xx, notify, locale_map)) {
761 if (glopts[x].set == &Baud)
767 if (*(unsigned char **) glopts[x].set)
768 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes, *(unsigned char **) glopts[x].set);
770 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes, "");
771 xx = (int *) joe_malloc(sizeof(int));
774 m->parent->notify = 0;
776 if (wmkpw(bw->parent, buf, NULL, doopt1, NULL, doabrt1, utypebw, xx, notify, locale_map))
781 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes, *(int *) ((unsigned char *) &bw->o + glopts[x].ofst));
784 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes, *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) + 1);
785 in:xx = (int *) joe_malloc(sizeof(int));
788 m->parent->notify = 0;
790 if (wmkpw(bw->parent, buf, NULL, doopt1, NULL, doabrt1, utypebw, xx, notify, locale_map))
796 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes,
797 bw->b->o.syntax ? bw->b->o.syntax->name : US "(unset)");
798 m->parent->notify = 0;
800 if (wmkpw(bw->parent, buf, NULL, dosyntax, NULL, NULL, syntaxcmplt, NULL, notify, locale_map))
806 joe_snprintf_1((char *)buf, OPT_BUF_SIZE, (char *)glopts[x].yes,
807 bw->b->o.charmap ? bw->b->o.charmap->name : US "(unset)");
808 m->parent->notify = 0;
810 if (wmkpw(bw->parent, buf, NULL, doencoding, NULL, NULL, encodingcmplt, NULL, notify, locale_map))
823 static int doabrt(MENU *m, int x, unsigned char **s)
826 for (x = 0; s[x]; ++x)
837 bw->b->o.readonly = bw->o.readonly = bw->b->rdonly;
838 for (size = 0; glopts[size].menu; ++size) ;
839 s = (unsigned char **) joe_malloc(sizeof(unsigned char *) * (size + 1));
841 for (x = 0; x < size; ++x) {
842 s[x] = (unsigned char *) joe_malloc(OPT_BUF_SIZE);
843 if (glopts[x].menu[0] == ' ' || glopts[x].menu[1] == ' ')
844 strlcpy(s[x], glopts[x].menu, OPT_BUF_SIZE);
846 strlcpy(s[x] + 2, glopts[x].menu, OPT_BUF_SIZE);
850 if (strlen(s[x]) > len)
853 for (x = 0; x < size; ++x) {
854 size_t n = strlen(s[x]);
858 switch (glopts[x].type) {
860 joe_snprintf_1(s[x] + n, OPT_BUF_SIZE - n,
861 "%s", *glopts[x].set ? "ON" : "OFF");
864 joe_snprintf_1(s[x] + n, OPT_BUF_SIZE - n,
865 "%d", *glopts[x].set);
868 strlcpy(s[x] + n, "...", OPT_BUF_SIZE - n);
871 joe_snprintf_1(s[x] + n, OPT_BUF_SIZE - n,
872 "%s", *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) ? "ON" : "OFF");
875 joe_snprintf_1(s[x] + n, OPT_BUF_SIZE - n,
876 "%d", *(int *) ((unsigned char *) &bw->o + glopts[x].ofst));
879 joe_snprintf_1(s[x] + n, OPT_BUF_SIZE - n,
880 "%d", *(int *) ((unsigned char *) &bw->o + glopts[x].ofst) + 1);
883 /* XXX aligns differently so it doesn't get too large */
884 joe_snprintf_2(s[x] + 12, OPT_BUF_SIZE - 12, "%*s", (int)n - 9,
885 bw->b->o.syntax ? bw->b->o.syntax->name : US "(unset)");
888 /* XXX aligns differently so it doesn't get too large */
889 joe_snprintf_2(s[x] + 12, OPT_BUF_SIZE - 12, "%*s", (int)n - 9,
890 bw->b->o.charmap ? bw->b->o.charmap->name : US "(unset)");
897 if (mkmenu(bw->parent, s, doopt, doabrt, NULL, optx, s, NULL))
904 * Returns 0 if the rc file was succefully processed
905 * -1 if the rc file couldn't be opened
906 * 1 if there was a syntax error in the file
909 int procrc(CAP *cap, unsigned char *name)
911 OPTIONS *o = &fdefault; /* Current options */
912 KMAP *context = NULL; /* Current context */
913 unsigned char buf[1024]; /* Input buffer */
914 JFILE *fd; /* rc file */
915 int line = 0; /* Line number */
916 int err = 0; /* Set to 1 if there was a syntax error */
918 strlcpy((char *)buf, (char *)name, 1024);
920 fd = jfopen((char *)buf, "rt");
922 fd = jfopen((char *)buf, "r");
926 return -1; /* Return if we couldn't open the rc file */
928 fprintf(stderr, "Processing '%s'...", name);
931 while (jfgets((char *)buf, sizeof(buf), fd)) {
939 break; /* Skip comment lines */
940 case '*': /* Select file types for file-type dependant options */
944 o = (OPTIONS *) joe_malloc(sizeof(OPTIONS));
946 for (x = 0; buf[x] && buf[x] != '\n' && buf[x] != ' ' && buf[x] != '\t'; ++x) ;
950 o->name_regex = (unsigned char *)strdup((char *)buf);
953 case '+': /* Set file contents match regex */
957 for (x = 0; buf[x] && buf[x] != '\n' && buf[x] != '\r'; ++x) ;
960 o->contents_regex = (unsigned char *)strdup((char *)(buf+1));
963 case '-': /* Set an option */
965 unsigned char *opt = buf + 1;
967 unsigned char *arg = NULL;
969 for (x = 0; buf[x] && buf[x] != '\n' && buf[x] != ' ' && buf[x] != '\t'; ++x) ;
970 if (buf[x] && buf[x] != '\n') {
972 for (arg = buf + ++x; buf[x] && buf[x] != '\n'; ++x) ;
975 if (!glopt(opt, arg, o, 2)) {
977 fprintf(stderr, "\n%s:%d: Unknown option '%s'", name, line, opt);
981 case '{': /* Ignore help text */
983 while ((jfgets((char *)buf, 256, fd)) && (buf[0] != /*{*/ '}'))
987 fprintf(stderr, "\n%s:%d: End of joerc file occurred before end of help text\n", name, line);
992 case ':': /* Select context */
996 for (x = 1; !joe_isspace_eof(locale_map,buf[x]); ++x) ;
1000 if (!strcmp(buf + 1, "def")) {
1003 for (buf[x] = c; joe_isblank(locale_map,buf[x]); ++x) ;
1004 for (y = x; !joe_isspace_eof(locale_map,buf[y]); ++y) ;
1011 if (joe_isblank(locale_map,c)
1012 && (m = mparse(NULL, buf + y + 1, &sta)))
1016 fprintf(stderr, "\n%s:%d: macro missing from :def", name, line);
1020 fprintf(stderr, "\n%s:%d: command name missing from :def", name, line);
1022 } else if (!strcmp(buf + 1, "inherit"))
1024 for (buf[x] = c; joe_isblank(locale_map,buf[x]); ++x) ;
1025 for (c = x; !joe_isspace_eof(locale_map,buf[c]); ++c) ;
1028 kcpy(context, kmap_getcontext(buf + x, 1));
1031 fprintf(stderr, "\n%s:%d: context name missing from :inherit", name, line);
1035 fprintf(stderr, "\n%s:%d: No context selected for :inherit", name, line);
1036 } else if (!strcmp(buf + 1, "include")) {
1037 for (buf[x] = c; joe_isblank(locale_map,buf[x]); ++x) ;
1038 for (c = x; !joe_isspace_eof(locale_map,buf[c]); ++c) ;
1041 switch (procrc(cap, buf + x)) {
1046 fprintf(stderr, "\n%s:%d: Couldn't open %s", name, line, buf + x);
1054 fprintf(stderr, "\n%s:%d: :include missing file name", name, line);
1056 } else if (!strcmp(buf + 1, "delete"))
1060 for (buf[x] = c; joe_isblank(locale_map,buf[x]); ++x) ;
1061 for (y = x; buf[y] != 0 && buf[y] != '\t' && buf[y] != '\n' && (buf[y] != ' ' || buf[y + 1]
1064 kdel(context, buf + x);
1067 fprintf(stderr, "\n%s:%d: No context selected for :delete", name, line);
1069 context = kmap_getcontext(buf + 1, 1);
1072 fprintf(stderr, "\n%s:%d: Invalid context name", name, line);
1076 default: /* Get key-sequence to macro binding */
1083 fprintf(stderr, "\n%s:%d: No context selected for macro to key-sequence binding", name, line);
1089 m = mparse(m, buf, &x);
1092 fprintf(stderr, "\n%s:%d: Unknown command in macro", name, line);
1094 } else if (x == -2) {
1095 jfgets((char *)buf, 1024, fd);
1101 /* Skip to end of key sequence */
1102 for (y = x; buf[y] != 0 && buf[y] != '\t' && buf[y] != '\n' && (buf[y] != ' ' || buf[y + 1] != ' '); ++y) ;
1105 /* Add binding to context */
1106 if (kadd(cap, context, buf + x, m) == -1) {
1107 fprintf(stderr, "\n%s:%d: Bad key sequence '%s'", name, line, buf + x);
1114 jfclose(fd); /* Close rc file */
1116 /* Print proper ending string */
1118 fprintf(stderr, "\ndone\n");
1120 fprintf(stderr, "done\n");
1122 return err; /* 0 for success, 1 for syntax error */