Increase the size of the 'message' buffer, which is currently
[sgt/tweak] / rcfile.c
1 #include "tweak.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7
8 #if defined(unix) && !defined(GO32)
9 #define RCNAME ".tweakrc"
10 #elif defined(MSDOS)
11 #define RCNAME "tweak.rc"
12 #endif
13
14 static char *default_rc[] = {
15 "# Default "RCNAME" generated by `tweak -D'.",
16 "#",
17 "# Key bindings: movement keys",
18 "bind top-of-file ^[<",
19 #if defined(unix) && !defined(GO32)
20 "bind page-up ^[[5~",
21 #elif defined(MSDOS)
22 "bind page-up ^@I",
23 "bind page-up ^@/",
24 #endif
25 "bind page-up ^[V",
26 "bind page-up ^[v",
27 "bind move-up ^P",
28 #if defined(unix) && !defined(GO32)
29 "bind move-up ^[[A",
30 #elif defined(MSDOS)
31 "bind move-up ^@H",
32 #endif
33 "bind begin-line ^A",
34 #if defined(unix) && !defined(GO32)
35 "bind begin-line ^[[H",
36 "bind begin-line ^[[1~",
37 #elif defined(MSDOS)
38 "bind begin-line ^@G",
39 #endif
40 "bind move-left ^B",
41 #if defined(unix) && !defined(GO32)
42 "bind move-left ^[[D",
43 #elif defined(MSDOS)
44 "bind move-left ^@K",
45 #endif
46 "bind move-right ^F",
47 #if defined(unix) && !defined(GO32)
48 "bind move-right ^[[C",
49 #elif defined(MSDOS)
50 "bind move-right ^@M",
51 #endif
52 "bind end-line ^E",
53 #if defined(unix) && !defined(GO32)
54 "bind end-line ^[Ow",
55 "bind end-line ^[[4~",
56 #elif defined(MSDOS)
57 "bind end-line ^@O",
58 #endif
59 "bind move-down ^N",
60 #if defined(unix) && !defined(GO32)
61 "bind move-down ^[[B",
62 #elif defined(MSDOS)
63 "bind move-down ^@P",
64 #endif
65 "bind page-down ^V",
66 #if defined(unix) && !defined(GO32)
67 "bind page-down ^[[6~",
68 #elif defined(MSDOS)
69 "bind page-down ^@Q",
70 #endif
71 "bind bottom-of-file ^[>",
72 "",
73 "# Key bindings: miscellaneous editing keys",
74 "bind toggle-insert ^X^I",
75 #if defined(unix) && !defined(GO32)
76 "bind toggle-insert ^[[2~",
77 #elif defined(MSDOS)
78 "bind toggle-insert ^@R",
79 #endif
80 "bind change-mode ^M",
81 "bind change-mode ^J",
82 "bind quote-next ^Q",
83 "bind toggle-status ^XH",
84 "bind toggle-status ^Xh",
85 "bind toggle-status ^XX",
86 "bind toggle-status ^Xx",
87 "",
88 "# Key bindings: deletion keys",
89 "bind delete-left ^?",
90 "bind delete-left ^H",
91 "bind delete-right ^D",
92 #if defined(unix) && !defined(GO32)
93 "bind delete-right ^[[3~",
94 #elif defined(MSDOS)
95 "bind delete-right ^@S",
96 #endif
97 "",
98 "# Key bindings: cut and paste keys",
99 #if defined(unix) && !defined(GO32)
100 "bind mark-place ^@",
101 #elif defined(MSDOS)
102 "bind mark-place ^@^C",
103 #endif
104 "bind cut ^W",
105 "bind copy ^[W",
106 "bind copy ^[w",
107 #ifdef MSDOS
108 "bind copy ^@^Q",
109 #endif
110 "bind paste ^Y",
111 "",
112 "# Key bindings: additional movement keys",
113 "bind search ^S",
114 "bind search-back ^R",
115 "bind goto-position ^XG",
116 "bind goto-position ^Xg",
117 "bind screen-recentre ^L",
118 "",
119 "# Standard screen size parameters, plus keybindings to alter them",
120 "width 16",
121 "offset 0",
122 "bind new-width ^XW",
123 "bind new-width ^Xw",
124 "bind new-offset ^XO",
125 "bind new-offset ^Xo",
126 "",
127 "# Key bindings: overall program/file control",
128 "bind suspend ^Z",
129 "bind exit ^X^C",
130 "bind save-file ^X^S",
131 "# unbound by default: exit-and-save",
132 "",
133 #ifdef TEST_BUFFER
134 "bind diagnostics ^X^D",
135 "",
136 #endif
137 "# End of default "RCNAME,
138 NULL
139 };
140
141 extern char *pname;
142
143 void read_rc (void) {
144 FILE *fp;
145 char **p, *q, *r, *s, *keyseq;
146 char rcbuffer[256];
147 char rcname[FILENAME_MAX];
148 int lineno = 0;
149 int errors = FALSE, errors_here;
150
151 #if defined(unix) && !defined(GO32)
152 rcname[0] = '\0';
153 if (getenv("HOME"))
154 strcpy (rcname, getenv("HOME"));
155 strcat (rcname, "/.tweakrc");
156 #elif defined(MSDOS)
157 /*
158 * Use environment variable TWEAKRC if set. Otherwise, look for
159 * TWEAK.RC in the same directory as TWEAK.EXE, if _that_ exists,
160 * and failing everything else, try C:\TWEAK\TWEAK.RC.
161 */
162 if (getenv("TWEAKRC"))
163 strcpy (rcname, getenv("TWEAKRC"));
164 else {
165 if ( (q = strrchr(pname, '\\')) != NULL) {
166 FILE *tempfp;
167
168 strncpy (rcname, pname, q+1-pname);
169 strcpy (rcname+(q+1-pname), "TWEAK.RC");
170 if ( (tempfp = fopen(rcname, "r")) != NULL)
171 fclose (tempfp);
172 else
173 strcpy (rcname, "C:\\TWEAK\\TWEAK.RC");
174 } else
175 strcpy (rcname, "C:\\TWEAK\\TWEAK.RC");
176 }
177 #endif
178
179 { /* easy keybindings: self inserts */
180 int i;
181 char c;
182 for (i=32; i<127; i++) {
183 c = i;
184 bind_key (&c, 1, act_self_ins);
185 }
186 }
187
188 fp = fopen(rcname, "r");
189 p = default_rc;
190 for (EVER) {
191 if (fp) {
192 if (!fgets(rcbuffer, sizeof(rcbuffer), fp)) {
193 fclose (fp);
194 break;
195 }
196 rcbuffer[strcspn(rcbuffer, "\r\n")] = '\0';
197 } else {
198 if (!*p)
199 break;
200 strcpy (rcbuffer, *p++);
201 }
202 lineno++;
203 errors_here = FALSE;
204
205 /*
206 * Now we have a line from the .rc file, wherever it's
207 * really come from. Process it.
208 */
209 q = rcbuffer;
210 while (*q && isspace((unsigned char)*q))
211 q++;
212
213 if (!*q || *q == '#')
214 continue; /* comment or blank line */
215
216 r = q;
217 while (*r && !isspace((unsigned char)*r))
218 r++;
219 if (*r)
220 *r++ = '\0';
221
222 /*
223 * Now "q" points to the command word, "r" to the rest of
224 * the line.
225 */
226 if (!strcmp(q, "bind")) {
227 /*
228 * It's a "bind" directive. The rest of the line should
229 * consist of an action name, then a single whitespace
230 * character, then a key sequence.
231 */
232 keyact action;
233
234 while (*r && isspace((unsigned char)*r))
235 r++;
236
237 q = r;
238 while (*q && !isspace((unsigned char)*q))
239 q++;
240 if (*q)
241 *q++ = '\0';
242 else {
243 fprintf(stderr, "%s: no key sequence after \"bind\" command"
244 " on line %d of "RCNAME, pname, lineno);
245 errors = TRUE;
246 continue;
247 }
248
249 /*
250 * "r" points to the action name; "q" to the key sequence.
251 */
252 keyseq = s = q;
253 while (*q) {
254 if (*q == '^') {
255 if (!*++q) {
256 fprintf(stderr, "%s: nothing follows `^' on line %d"
257 " of "RCNAME, pname, lineno);
258 errors = TRUE;
259 errors_here = TRUE;
260 } else {
261 *s++ = *q++ ^ 0x40;
262 }
263 } else if (*q == '\\') {
264 if (!*++q) {
265 fprintf(stderr, "%s: nothing follows `\\' on line %d"
266 " of "RCNAME, pname, lineno);
267 errors = TRUE;
268 errors_here = TRUE;
269 } else if (*q == '\\' || *q == '^') {
270 *s++ = *q++;
271 } else if (isxdigit((unsigned char)*q) &&
272 q[1] && isxdigit((unsigned char)q[1])) {
273 char buf[3];
274 buf[0] = *q++;
275 buf[1] = *q++;
276 buf[2] = '\0';
277 *s++ = strtol (buf, NULL, 16);
278 } else {
279 fprintf(stderr, "%s: badly formed `\\' sequence on"
280 " line %d of "RCNAME, pname, lineno);
281 errors = TRUE;
282 errors_here = TRUE;
283 }
284 } else
285 *s++ = *q++;
286 }
287 if (errors_here)
288 continue;
289
290 if (!strcmp(r, "quote-next")) {
291 /*
292 * The "quote next" sequence requires special
293 * treatment.
294 */
295 int i;
296
297 for (i=0; i<256; i++) {
298 *s = i;
299 bind_key (keyseq, s-keyseq+1, act_self_ins);
300 }
301 } else if ( (action = parse_action (r)) ) {
302 /*
303 * An ordinary action, requiring ordinary treatment.
304 */
305 bind_key (keyseq, s-keyseq, action);
306 } else {
307 fprintf(stderr, "%s: unrecognised key action \"%s\""
308 " at line %d of "RCNAME"\n",
309 pname, r, lineno);
310 errors = TRUE;
311 }
312 } else if (!strcmp(q, "width")) {
313 width = atoi(r);
314 } else if (!strcmp(q, "offset")) {
315 realoffset = atoi(r);
316 } else {
317 fprintf(stderr, "%s: unrecognised "RCNAME" directive \"%s\""
318 " at line %d of "RCNAME"\n",
319 pname, q, lineno);
320 errors = TRUE;
321 }
322 }
323 if (errors)
324 exit(1);
325 }
326
327 void write_default_rc (void) {
328 char **p;
329
330 for (p = default_rc; *p; p++)
331 puts (*p);
332 }