Fix compiler warnings (missing #includes etc) thrown up by RedHat.
[sgt/tweak] / rcfile.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "tweak.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 goto-position ^XG",
115 "bind goto-position ^Xg",
116 "bind screen-recentre ^L",
117 "",
118 "# Standard screen size parameters, plus keybindings to alter them",
119 "width 16",
120 "offset 0",
121 "bind new-width ^XW",
122 "bind new-width ^Xw",
123 "bind new-offset ^XO",
124 "bind new-offset ^Xo",
125 "",
126 "# Key bindings: overall program/file control",
127 "bind suspend ^Z",
128 "bind exit ^X^C",
129 "bind save-file ^X^S",
130 "# unbound by default: exit-and-save",
131 "",
132 #ifdef TEST_BUFFER
133 "bind diagnostics ^X^D",
134 "",
135 #endif
136 "# End of default "RCNAME,
137 NULL
138 };
139
140 extern char *pname;
141
142 void read_rc (void) {
143 FILE *fp;
144 char **p, *q, *r, *s, *keyseq;
145 char rcbuffer[256];
146 char rcname[FILENAME_MAX];
147 int lineno = 0;
148 int errors = FALSE, errors_here;
149
150 #if defined(unix) && !defined(GO32)
151 rcname[0] = '\0';
152 if (getenv("HOME"))
153 strcpy (rcname, getenv("HOME"));
154 strcat (rcname, "/.tweakrc");
155 #elif defined(MSDOS)
156 /*
157 * Use environment variable TWEAKRC if set. Otherwise, look for
158 * TWEAK.RC in the same directory as TWEAK.EXE, if _that_ exists,
159 * and failing everything else, try C:\TWEAK\TWEAK.RC.
160 */
161 if (getenv("TWEAKRC"))
162 strcpy (rcname, getenv("TWEAKRC"));
163 else {
164 if ( (q = strrchr(pname, '\\')) != NULL) {
165 FILE *tempfp;
166
167 strncpy (rcname, pname, q+1-pname);
168 strcpy (rcname+(q+1-pname), "TWEAK.RC");
169 if ( (tempfp = fopen(rcname, "r")) != NULL)
170 fclose (tempfp);
171 else
172 strcpy (rcname, "C:\\TWEAK\\TWEAK.RC");
173 } else
174 strcpy (rcname, "C:\\TWEAK\\TWEAK.RC");
175 }
176 #endif
177
178 { /* easy keybindings: self inserts */
179 int i;
180 char c;
181 for (i=32; i<127; i++) {
182 c = i;
183 bind_key (&c, 1, act_self_ins);
184 }
185 }
186
187 fp = fopen(rcname, "r");
188 p = default_rc;
189 for (EVER) {
190 if (fp) {
191 if (!fgets(rcbuffer, sizeof(rcbuffer), fp)) {
192 fclose (fp);
193 break;
194 }
195 rcbuffer[strcspn(rcbuffer, "\r\n")] = '\0';
196 } else {
197 if (!*p)
198 break;
199 strcpy (rcbuffer, *p++);
200 }
201 lineno++;
202 errors_here = FALSE;
203
204 /*
205 * Now we have a line from the .rc file, wherever it's
206 * really come from. Process it.
207 */
208 q = rcbuffer;
209 while (*q && isspace(*q))
210 q++;
211
212 if (!*q || *q == '#')
213 continue; /* comment or blank line */
214
215 r = q;
216 while (*r && !isspace(*r))
217 r++;
218 if (*r)
219 *r++ = '\0';
220
221 /*
222 * Now "q" points to the command word, "r" to the rest of
223 * the line.
224 */
225 if (!strcmp(q, "bind")) {
226 /*
227 * It's a "bind" directive. The rest of the line should
228 * consist of an action name, then a single whitespace
229 * character, then a key sequence.
230 */
231 keyact action;
232
233 while (*r && isspace(*r))
234 r++;
235
236 q = r;
237 while (*q && !isspace(*q))
238 q++;
239 if (*q)
240 *q++ = '\0';
241 else {
242 fprintf(stderr, "%s: no key sequence after \"bind\" command"
243 " on line %d of "RCNAME, pname, lineno);
244 errors = TRUE;
245 continue;
246 }
247
248 /*
249 * "r" points to the action name; "q" to the key sequence.
250 */
251 keyseq = s = q;
252 while (*q) {
253 if (*q == '^') {
254 if (!*++q) {
255 fprintf(stderr, "%s: nothing follows `^' on line %d"
256 " of "RCNAME, pname, lineno);
257 errors = TRUE;
258 errors_here = TRUE;
259 } else {
260 *s++ = *q++ ^ 0x40;
261 }
262 } else if (*q == '\\') {
263 if (!*++q) {
264 fprintf(stderr, "%s: nothing follows `\\' on line %d"
265 " of "RCNAME, pname, lineno);
266 errors = TRUE;
267 errors_here = TRUE;
268 } else if (*q == '\\' || *q == '^') {
269 *s++ = *q++;
270 } else if (isxdigit(*q) && q[1] && isxdigit(q[1])) {
271 char buf[3];
272 buf[0] = *q++;
273 buf[1] = *q++;
274 buf[2] = '\0';
275 *s++ = strtol (buf, NULL, 16);
276 } else {
277 fprintf(stderr, "%s: badly formed `\\' sequence on"
278 " line %d of "RCNAME, pname, lineno);
279 errors = TRUE;
280 errors_here = TRUE;
281 }
282 } else
283 *s++ = *q++;
284 }
285 if (errors_here)
286 continue;
287
288 if (!strcmp(r, "quote-next")) {
289 /*
290 * The "quote next" sequence requires special
291 * treatment.
292 */
293 int i;
294
295 for (i=0; i<256; i++) {
296 *s = i;
297 bind_key (keyseq, s-keyseq+1, act_self_ins);
298 }
299 } else if ( (action = parse_action (r)) ) {
300 /*
301 * An ordinary action, requiring ordinary treatment.
302 */
303 bind_key (keyseq, s-keyseq, action);
304 } else {
305 fprintf(stderr, "%s: unrecognised key action \"%s\""
306 " at line %d of "RCNAME"\n",
307 pname, r, lineno);
308 errors = TRUE;
309 }
310 } else if (!strcmp(q, "width")) {
311 width = atoi(r);
312 } else if (!strcmp(q, "offset")) {
313 realoffset = atoi(r);
314 } else {
315 fprintf(stderr, "%s: unrecognised "RCNAME" directive \"%s\""
316 " at line %d of "RCNAME"\n",
317 pname, q, lineno);
318 errors = TRUE;
319 }
320 }
321 if (errors)
322 exit(1);
323 }
324
325 void write_default_rc (void) {
326 char **p;
327
328 for (p = default_rc; *p; p++)
329 puts (*p);
330 }