remove trailing whitespace at end of lines
[reactos.git] / rosapps / mc / edit / syntax.c
1 /* editor syntax highlighting.
2
3 Copyright (C) 1996, 1997, 1998 the Free Software Foundation
4
5 Authors: 1998 Paul Sheer
6
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; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <config.h>
22 #ifdef MIDNIGHT
23 #include "edit.h"
24 #else
25 #include "coolwidget.h"
26 #endif
27
28 #if !defined(MIDNIGHT) || defined(HAVE_SYNTAXH)
29
30 int option_syntax_highlighting = 1;
31
32 /* these three functions are called from the outside */
33 void edit_load_syntax (WEdit * edit, char **names, char *type);
34 void edit_free_syntax_rules (WEdit * edit);
35 void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg);
36
37 static void *syntax_malloc (size_t x)
38 {
39 void *p;
40 p = malloc (x);
41 memset (p, 0, x);
42 return p;
43 }
44
45 #define syntax_free(x) {if(x){free(x);(x)=0;}}
46
47 static int compare_word_to_right (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
48 {
49 char *p;
50 int c, j;
51 if (!*text)
52 return 0;
53 c = edit_get_byte (edit, i - 1);
54 if (line_start)
55 if (c != '\n')
56 return 0;
57 if (whole_left)
58 if (strchr (whole_left, c))
59 return 0;
60 for (p = text; *p; p++, i++) {
61 switch (*p) {
62 case '\001':
63 p++;
64 for (;;) {
65 c = edit_get_byte (edit, i);
66 if (c == *p)
67 break;
68 if (c == '\n')
69 return 0;
70 i++;
71 }
72 break;
73 case '\002':
74 p++;
75 for (;;) {
76 c = edit_get_byte (edit, i);
77 if (c == *p)
78 break;
79 if (c == '\n' || c == '\t' || c == ' ')
80 return 0;
81 i++;
82 }
83 break;
84 case '\003':
85 p++;
86 #if 0
87 c = edit_get_byte (edit, i++);
88 for (j = 0; p[j] != '\003'; j++)
89 if (c == p[j])
90 goto found_char1;
91 return 0;
92 found_char1:
93 #endif
94 for (;;i++) {
95 c = edit_get_byte (edit, i);
96 for (j = 0; p[j] != '\003'; j++)
97 if (c == p[j])
98 goto found_char2;
99 break;
100 found_char2:;
101 }
102 i--;
103 while (*p != '\003')
104 p++;
105 break;
106 #if 0
107 case '\004':
108 p++;
109 c = edit_get_byte (edit, i++);
110 for (j = 0; p[j] != '\004'; j++)
111 if (c == p[j])
112 return 0;
113 for (;;i++) {
114 c = edit_get_byte (edit, i);
115 for (j = 0; p[j] != '\004'; j++)
116 if (c == p[j])
117 goto found_char4;
118 continue;
119 found_char4:
120 break;
121 }
122 i--;
123 while (*p != '\004')
124 p++;
125 break;
126 #endif
127 default:
128 if (*p != edit_get_byte (edit, i))
129 return 0;
130 }
131 }
132 if (whole_right)
133 if (strchr (whole_right, edit_get_byte (edit, i)))
134 return 0;
135 return 1;
136 }
137
138 static int compare_word_to_left (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
139 {
140 char *p;
141 int c, j;
142 #if 0
143 int d;
144 #endif
145 if (!*text)
146 return 0;
147 if (whole_right)
148 if (strchr (whole_right, edit_get_byte (edit, i + 1)))
149 return 0;
150 for (p = text + strlen (text) - 1; (unsigned long) p >= (unsigned long) text; p--, i--) {
151 switch (*p) {
152 case '\001':
153 p--;
154 for (;;) {
155 c = edit_get_byte (edit, i);
156 if (c == *p)
157 break;
158 if (c == '\n')
159 return 0;
160 i--;
161 }
162 break;
163 case '\002':
164 p--;
165 for (;;) {
166 c = edit_get_byte (edit, i);
167 if (c == *p)
168 break;
169 if (c == '\n' || c == '\t' || c == ' ')
170 return 0;
171 i--;
172 }
173 break;
174 case '\003':
175 while (*(--p) != '\003');
176 p++;
177 #if 0
178 c = edit_get_byte (edit, i--);
179 for (j = 0; p[j] != '\003'; j++)
180 if (c == p[j])
181 goto found_char1;
182 return 0;
183 found_char1:
184 #endif
185 for (;; i--) {
186 c = edit_get_byte (edit, i);
187 for (j = 0; p[j] != '\003'; j++)
188 if (c == p[j])
189 goto found_char2;
190 break;
191 found_char2:;
192 }
193 i++;
194 p--;
195 break;
196 #if 0
197 case '\004':
198 while (*(--p) != '\004');
199 d = *p;
200 p++;
201 c = edit_get_byte (edit, i--);
202 for (j = 0; p[j] != '\004'; j++)
203 if (c == p[j])
204 return 0;
205 for (;; i--) {
206 c = edit_get_byte (edit, i);
207 for (j = 0; p[j] != '\004'; j++)
208 if (c == p[j] || c == '\n' || c == d)
209 goto found_char4;
210 continue;
211 found_char4:
212 break;
213 }
214 i++;
215 p--;
216 break;
217 #endif
218 default:
219 if (*p != edit_get_byte (edit, i))
220 return 0;
221 }
222 }
223 c = edit_get_byte (edit, i);
224 if (line_start)
225 if (c != '\n')
226 return 0;
227 if (whole_left)
228 if (strchr (whole_left, c))
229 return 0;
230 return 1;
231 }
232
233
234 #if 0
235 #define debug_printf(x,y) fprintf(stderr,x,y)
236 #else
237 #define debug_printf(x,y)
238 #endif
239
240 static inline unsigned long apply_rules_going_right (WEdit * edit, long i, unsigned long rule)
241 {
242 struct context_rule *r;
243 int context, contextchanged = 0, keyword, c1, c2;
244 int found_right = 0, found_left = 0, keyword_foundleft = 0;
245 int done = 0;
246 unsigned long border;
247 context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
248 keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
249 border = rule & (RULE_ON_LEFT_BORDER | RULE_ON_RIGHT_BORDER);
250 c1 = edit_get_byte (edit, i - 1);
251 c2 = edit_get_byte (edit, i);
252 if (!c2 || !c1)
253 return rule;
254
255 debug_printf ("%c->", c1);
256 debug_printf ("%c ", c2);
257
258 /* check to turn off a keyword */
259 if (keyword) {
260 struct key_word *k;
261 k = edit->rules[context]->keyword[keyword];
262 if (c1 == '\n')
263 keyword = 0;
264 if (k->last == c1 && compare_word_to_left (edit, i - 1, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
265 keyword = 0;
266 keyword_foundleft = 1;
267 debug_printf ("keyword=%d ", keyword);
268 }
269 }
270 debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
271
272 /* check to turn off a context */
273 if (context && !keyword) {
274 r = edit->rules[context];
275 if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
276 &&!(rule & RULE_ON_RIGHT_BORDER)) {
277 debug_printf ("A:3 ", 0);
278 found_right = 1;
279 border = RULE_ON_RIGHT_BORDER;
280 if (r->between_delimiters)
281 context = 0;
282 } else if (!found_left) {
283 if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
284 &&(rule & RULE_ON_RIGHT_BORDER)) {
285 /* always turn off a context at 4 */
286 debug_printf ("A:4 ", 0);
287 found_left = 1;
288 border = 0;
289 if (!keyword_foundleft)
290 context = 0;
291 } else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
292 &&(rule & RULE_ON_LEFT_BORDER)) {
293 /* never turn off a context at 2 */
294 debug_printf ("A:2 ", 0);
295 found_left = 1;
296 border = 0;
297 }
298 }
299 }
300 debug_printf ("\n", 0);
301
302 /* check to turn on a keyword */
303 if (!keyword) {
304 char *p;
305 p = (r = edit->rules[context])->keyword_first_chars;
306 while ((p = strchr (p + 1, c2))) {
307 struct key_word *k;
308 int count;
309 count = (unsigned long) p - (unsigned long) r->keyword_first_chars;
310 k = r->keyword[count];
311 if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
312 keyword = count;
313 debug_printf ("keyword=%d ", keyword);
314 break;
315 }
316 }
317 }
318 /* check to turn on a context */
319 if (!context) {
320 int count;
321 for (count = 1; edit->rules[count] && !done; count++) {
322 r = edit->rules[count];
323 if (!found_left) {
324 if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
325 &&(rule & RULE_ON_RIGHT_BORDER)) {
326 debug_printf ("B:4 count=%d", count);
327 found_left = 1;
328 border = 0;
329 context = 0;
330 contextchanged = 1;
331 keyword = 0;
332 } else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
333 &&(rule & RULE_ON_LEFT_BORDER)) {
334 debug_printf ("B:2 ", 0);
335 found_left = 1;
336 border = 0;
337 if (r->between_delimiters) {
338 context = count;
339 contextchanged = 1;
340 keyword = 0;
341 debug_printf ("context=%d ", context);
342 if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) {
343 debug_printf ("B:3 ", 0);
344 found_right = 1;
345 border = RULE_ON_RIGHT_BORDER;
346 context = 0;
347 }
348 }
349 break;
350 }
351 }
352 if (!found_right) {
353 if (r->first_left == c2 && compare_word_to_right (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left)) {
354 debug_printf ("B:1 ", 0);
355 found_right = 1;
356 border = RULE_ON_LEFT_BORDER;
357 if (!r->between_delimiters) {
358 debug_printf ("context=%d ", context);
359 if (!keyword)
360 context = count;
361 }
362 break;
363 }
364 }
365 }
366 }
367 if (!keyword && contextchanged) {
368 char *p;
369 p = (r = edit->rules[context])->keyword_first_chars;
370 while ((p = strchr (p + 1, c2))) {
371 struct key_word *k;
372 int coutner;
373 coutner = (unsigned long) p - (unsigned long) r->keyword_first_chars;
374 k = r->keyword[coutner];
375 if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
376 keyword = coutner;
377 debug_printf ("keyword=%d ", keyword);
378 break;
379 }
380 }
381 }
382 debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
383 debug_printf ("keyword=%d ", keyword);
384
385 debug_printf (" %d#\n\n", context);
386
387 return (context << RULE_CONTEXT_SHIFT) | (keyword << RULE_WORD_SHIFT) | border;
388 }
389
390 static inline int resolve_left_delim (WEdit * edit, long i, struct context_rule *r, int s)
391 {
392 int c, count;
393 if (!r->conflicts)
394 return s;
395 for (;;) {
396 c = edit_get_byte (edit, i);
397 if (c == '\n')
398 break;
399 for (count = 1; r->conflicts[count]; count++) {
400 struct context_rule *p;
401 p = edit->rules[r->conflicts[count]];
402 if (!p)
403 break;
404 if (p->first_left == c && r->between_delimiters == p->between_delimiters && compare_word_to_right (edit, i, p->left, p->whole_word_chars_left, r->whole_word_chars_right, p->line_start_left))
405 return r->conflicts[count];
406 }
407 i--;
408 }
409 return 0;
410 }
411
412 static inline unsigned long apply_rules_going_left (WEdit * edit, long i, unsigned long rule)
413 {
414 struct context_rule *r;
415 int context, contextchanged = 0, keyword, c2, c1;
416 int found_left = 0, found_right = 0, keyword_foundright = 0;
417 int done = 0;
418 unsigned long border;
419 context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
420 keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
421 border = rule & (RULE_ON_RIGHT_BORDER | RULE_ON_LEFT_BORDER);
422 c1 = edit_get_byte (edit, i);
423 c2 = edit_get_byte (edit, i + 1);
424 if (!c2 || !c1)
425 return rule;
426
427 debug_printf ("%c->", c2);
428 debug_printf ("%c ", c1);
429
430 /* check to turn off a keyword */
431 if (keyword) {
432 struct key_word *k;
433 k = edit->rules[context]->keyword[keyword];
434 if (c2 == '\n')
435 keyword = 0;
436 if ((k->first == c2 && compare_word_to_right (edit, i + 1, k->keyword, k->whole_word_chars_right, k->whole_word_chars_left, k->line_start)) || (c2 == '\n')) {
437 keyword = 0;
438 keyword_foundright = 1;
439 debug_printf ("keyword=%d ", keyword);
440 }
441 }
442 debug_printf ("border=%s ", border ? ((border & RULE_ON_RIGHT_BORDER) ? "right" : "left") : "off");
443
444 /* check to turn off a context */
445 if (context && !keyword) {
446 r = edit->rules[context];
447 if (r->last_left == c1 && compare_word_to_left (edit, i, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left) \
448 &&!(rule & RULE_ON_LEFT_BORDER)) {
449 debug_printf ("A:2 ", 0);
450 found_left = 1;
451 border = RULE_ON_LEFT_BORDER;
452 if (r->between_delimiters)
453 context = 0;
454 } else if (!found_right) {
455 if (r->first_left == c2 && compare_word_to_right (edit, i + 1, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left) \
456 &&(rule & RULE_ON_LEFT_BORDER)) {
457 /* always turn off a context at 4 */
458 debug_printf ("A:1 ", 0);
459 found_right = 1;
460 border = 0;
461 if (!keyword_foundright)
462 context = 0;
463 } else if (r->first_right == c2 && compare_word_to_right (edit, i + 1, r->right, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_right) \
464 &&(rule & RULE_ON_RIGHT_BORDER)) {
465 /* never turn off a context at 2 */
466 debug_printf ("A:3 ", 0);
467 found_right = 1;
468 border = 0;
469 }
470 }
471 }
472 debug_printf ("\n", 0);
473
474 /* check to turn on a keyword */
475 if (!keyword) {
476 char *p;
477 p = (r = edit->rules[context])->keyword_last_chars;
478 while ((p = strchr (p + 1, c1))) {
479 struct key_word *k;
480 int count;
481 count = (unsigned long) p - (unsigned long) r->keyword_last_chars;
482 k = r->keyword[count];
483 if (compare_word_to_left (edit, i, k->keyword, k->whole_word_chars_right, k->whole_word_chars_left, k->line_start)) {
484 keyword = count;
485 debug_printf ("keyword=%d ", keyword);
486 break;
487 }
488 }
489 }
490 /* check to turn on a context */
491 if (!context) {
492 int count;
493 for (count = 1; edit->rules[count] && !done; count++) {
494 r = edit->rules[count];
495 if (!found_right) {
496 if (r->first_left == c2 && compare_word_to_right (edit, i + 1, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left) \
497 &&(rule & RULE_ON_LEFT_BORDER)) {
498 debug_printf ("B:1 count=%d", count);
499 found_right = 1;
500 border = 0;
501 context = 0;
502 contextchanged = 1;
503 keyword = 0;
504 } else if (r->first_right == c2 && compare_word_to_right (edit, i + 1, r->right, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_right) \
505 &&(rule & RULE_ON_RIGHT_BORDER)) {
506 if (!(c2 == '\n' && r->single_char)) {
507 debug_printf ("B:3 ", 0);
508 found_right = 1;
509 border = 0;
510 if (r->between_delimiters) {
511 debug_printf ("context=%d ", context);
512 context = resolve_left_delim (edit, i, r, count);
513 contextchanged = 1;
514 keyword = 0;
515 if (r->last_left == c1 && compare_word_to_left (edit, i, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left)) {
516 debug_printf ("B:2 ", 0);
517 found_left = 1;
518 border = RULE_ON_LEFT_BORDER;
519 context = 0;
520 }
521 }
522 break;
523 }
524 }
525 }
526 if (!found_left) {
527 if (r->last_right == c1 && compare_word_to_left (edit, i, r->right, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_right)) {
528 if (!(c1 == '\n' && r->single_char)) {
529 debug_printf ("B:4 ", 0);
530 found_left = 1;
531 border = RULE_ON_RIGHT_BORDER;
532 if (!keyword)
533 if (!r->between_delimiters)
534 context = resolve_left_delim (edit, i - 1, r, count);
535 break;
536 }
537 }
538 }
539 }
540 }
541 if (!keyword && contextchanged) {
542 char *p;
543 p = (r = edit->rules[context])->keyword_last_chars;
544 while ((p = strchr (p + 1, c1))) {
545 struct key_word *k;
546 int coutner;
547 coutner = (unsigned long) p - (unsigned long) r->keyword_last_chars;
548 k = r->keyword[coutner];
549 if (compare_word_to_left (edit, i, k->keyword, k->whole_word_chars_right, k->whole_word_chars_left, k->line_start)) {
550 keyword = coutner;
551 debug_printf ("keyword=%d ", keyword);
552 break;
553 }
554 }
555 }
556 debug_printf ("border=%s ", border ? ((border & RULE_ON_RIGHT_BORDER) ? "right" : "left") : "off");
557 debug_printf ("keyword=%d ", keyword);
558
559 debug_printf (" %d#\n\n", context);
560
561 return (context << RULE_CONTEXT_SHIFT) | (keyword << RULE_WORD_SHIFT) | border;
562 }
563
564
565 static unsigned long edit_get_rule (WEdit * edit, long byte_index)
566 {
567 long i;
568 if (byte_index < 0) {
569 edit->last_get_rule = -1;
570 edit->rule = 0;
571 return 0;
572 }
573 #if 0
574 if (byte_index < edit->last_get_rule_start_display) {
575 /* this is for optimisation */
576 for (i = edit->last_get_rule_start_display - 1; i >= byte_index; i--)
577 edit->rule_start_display = apply_rules_going_left (edit, i, edit->rule_start_display);
578 edit->last_get_rule_start_display = byte_index;
579 edit->rule = edit->rule_start_display;
580 } else
581 #endif
582 if (byte_index > edit->last_get_rule) {
583 for (i = edit->last_get_rule + 1; i <= byte_index; i++)
584 edit->rule = apply_rules_going_right (edit, i, edit->rule);
585 } else if (byte_index < edit->last_get_rule) {
586 for (i = edit->last_get_rule - 1; i >= byte_index; i--)
587 edit->rule = apply_rules_going_left (edit, i, edit->rule);
588 }
589 edit->last_get_rule = byte_index;
590 return edit->rule;
591 }
592
593 static void translate_rule_to_color (WEdit * edit, unsigned long rule, int *fg, int *bg)
594 {
595 struct key_word *k;
596 k = edit->rules[(rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT]->keyword[(rule & RULE_WORD) >> RULE_WORD_SHIFT];
597 *bg = k->bg;
598 *fg = k->fg;
599 }
600
601 void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg)
602 {
603 unsigned long rule;
604 if (!edit->rules || byte_index >= edit->last_byte || !option_syntax_highlighting) {
605 #ifdef MIDNIGHT
606 *fg = NORMAL_COLOR;
607 #else
608 *fg = NO_COLOR;
609 *bg = NO_COLOR;
610 #endif
611 } else {
612 rule = edit_get_rule (edit, byte_index);
613 translate_rule_to_color (edit, rule, fg, bg);
614 }
615 }
616
617
618 /*
619 Returns 0 on error/eof or a count of the number of bytes read
620 including the newline. Result must be free'd.
621 */
622 static int read_one_line (char **line, FILE * f)
623 {
624 char *p;
625 int len = 256, c, r = 0, i = 0;
626 p = syntax_malloc (len);
627 for (;;) {
628 c = fgetc (f);
629 if (c == -1) {
630 r = 0;
631 break;
632 } else if (c == '\n') {
633 r = i + 1; /* extra 1 for the newline just read */
634 break;
635 } else {
636 if (i >= len - 1) {
637 char *q;
638 q = syntax_malloc (len * 2);
639 memcpy (q, p, len);
640 syntax_free (p);
641 p = q;
642 len *= 2;
643 }
644 p[i++] = c;
645 }
646 }
647 p[i] = 0;
648 *line = p;
649 return r;
650 }
651
652 static char *strdup_convert (char *s)
653 {
654 #if 0
655 int e = 0;
656 #endif
657 char *r, *p;
658 p = r = strdup (s);
659 while (*s) {
660 switch (*s) {
661 case '\\':
662 s++;
663 switch (*s) {
664 case 'n':
665 *p = '\n';
666 break;
667 case 'r':
668 *p = '\r';
669 break;
670 case 't':
671 *p = '\t';
672 break;
673 case 's':
674 *p = ' ';
675 break;
676 case '*':
677 *p = '*';
678 break;
679 case '\\':
680 *p = '\\';
681 break;
682 case '[':
683 case ']':
684 if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
685 *p = *s;
686 else {
687 #if 0
688 if (!strncmp (s, "[^", 2)) {
689 *p = '\004';
690 e = 1;
691 s++;
692 } else {
693 if (e)
694 *p = '\004';
695 else
696 #endif
697 *p = '\003';
698 #if 0
699 e = 0;
700 }
701 #endif
702 }
703 break;
704 default:
705 *p = *s;
706 break;
707 }
708 break;
709 case '*':
710 /* a * or + at the beginning or end of the line must be interpreted literally */
711 if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
712 *p = '*';
713 else
714 *p = '\001';
715 break;
716 case '+':
717 if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
718 *p = '+';
719 else
720 *p = '\002';
721 break;
722 default:
723 *p = *s;
724 break;
725 }
726 s++;
727 p++;
728 }
729 *p = 0;
730 return r;
731 }
732
733 #define whiteness(x) ((x) == '\t' || (x) == '\n' || (x) == ' ')
734
735 static void get_args (char *l, char **args, int *argc)
736 {
737 *argc = 0;
738 l--;
739 for (;;) {
740 char *p;
741 for (p = l + 1; *p && whiteness (*p); p++);
742 if (!*p)
743 break;
744 for (l = p + 1; *l && !whiteness (*l); l++);
745 *l = '\0';
746 *args = strdup_convert (p);
747 (*argc)++;
748 args++;
749 }
750 *args = 0;
751 }
752
753 static void free_args (char **args)
754 {
755 while (*args) {
756 syntax_free (*args);
757 *args = 0;
758 args++;
759 }
760 }
761
762 #define check_a {if(!*a){result=line;break;}}
763 #define check_not_a {if(*a){result=line;break;}}
764
765 #ifdef MIDNIGHT
766
767 int try_alloc_color_pair (char *fg, char *bg);
768
769 int this_try_alloc_color_pair (char *fg, char *bg)
770 {
771 char f[80], b[80], *p;
772 if (fg) {
773 strcpy (f, fg);
774 p = strchr (f, '/');
775 if (p)
776 *p = '\0';
777 fg = f;
778 }
779 if (bg) {
780 strcpy (b, bg);
781 p = strchr (b, '/');
782 if (p)
783 *p = '\0';
784 bg = b;
785 }
786 return try_alloc_color_pair (fg, bg);
787 }
788 #else
789 int this_allocate_color (char *fg)
790 {
791 char *p;
792 if (!fg)
793 return allocate_color (0);
794 p = strchr (fg, '/');
795 if (!p)
796 return allocate_color (fg);
797 return allocate_color (p + 1);
798 }
799 #endif
800
801 /* returns line number on error */
802 static int edit_read_syntax_rules (WEdit * edit, FILE * f)
803 {
804 char *fg, *bg;
805 char whole_right[256];
806 char whole_left[256];
807 char *args[1024], *l = 0;
808 int line = 0;
809 struct context_rule **r, *c;
810 int num_words = -1, num_contexts = -1;
811 int argc, result = 0;
812 int i, j;
813
814 args[0] = 0;
815
816 strcpy (whole_left, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
817 strcpy (whole_right, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
818
819 r = edit->rules = syntax_malloc (256 * sizeof (struct context_rule *));
820
821 for (;;) {
822 char **a;
823 line++;
824 if (!read_one_line (&l, f))
825 break;
826 get_args (l, args, &argc);
827 a = args + 1;
828 if (!args[0]) {
829 /* do nothing */
830 } else if (!strcmp (args[0], "wholechars")) {
831 check_a;
832 if (!strcmp (*a, "left")) {
833 a++;
834 strcpy (whole_left, *a);
835 } else if (!strcmp (*a, "right")) {
836 a++;
837 strcpy (whole_right, *a);
838 } else {
839 strcpy (whole_left, *a);
840 strcpy (whole_right, *a);
841 }
842 a++;
843 check_not_a;
844 } else if (!strcmp (args[0], "context")) {
845 check_a;
846 if (num_contexts == -1) {
847 if (strcmp (*a, "default")) { /* first context is the default */
848 *a = 0;
849 check_a;
850 }
851 a++;
852 c = r[0] = syntax_malloc (sizeof (struct context_rule));
853 c->left = strdup (" ");
854 c->right = strdup (" ");
855 num_contexts = 0;
856 } else {
857 c = r[num_contexts] = syntax_malloc (sizeof (struct context_rule));
858 if (!strcmp (*a, "exclusive")) {
859 a++;
860 c->between_delimiters = 1;
861 }
862 check_a;
863 if (!strcmp (*a, "whole")) {
864 a++;
865 c->whole_word_chars_left = strdup (whole_left);
866 c->whole_word_chars_right = strdup (whole_right);
867 } else if (!strcmp (*a, "wholeleft")) {
868 a++;
869 c->whole_word_chars_left = strdup (whole_left);
870 } else if (!strcmp (*a, "wholeright")) {
871 a++;
872 c->whole_word_chars_right = strdup (whole_right);
873 }
874 check_a;
875 if (!strcmp (*a, "linestart")) {
876 a++;
877 c->line_start_left = 1;
878 }
879 check_a;
880 c->left = strdup (*a++);
881 check_a;
882 if (!strcmp (*a, "linestart")) {
883 a++;
884 c->line_start_right = 1;
885 }
886 check_a;
887 c->right = strdup (*a++);
888 c->last_left = c->left[strlen (c->left) - 1];
889 c->last_right = c->right[strlen (c->right) - 1];
890 c->first_left = *c->left;
891 c->first_right = *c->right;
892 c->single_char = (strlen (c->right) == 1);
893 }
894 c->keyword = syntax_malloc (1024 * sizeof (struct key_word *));
895 num_words = 1;
896 c->keyword[0] = syntax_malloc (sizeof (struct key_word));
897 fg = *a;
898 if (*a)
899 a++;
900 bg = *a;
901 if (*a)
902 a++;
903 #ifdef MIDNIGHT
904 c->keyword[0]->fg = this_try_alloc_color_pair (fg, bg);
905 #else
906 c->keyword[0]->fg = this_allocate_color (fg);
907 c->keyword[0]->bg = this_allocate_color (bg);
908 #endif
909 c->keyword[0]->keyword = strdup (" ");
910 check_not_a;
911 num_contexts++;
912 } else if (!strcmp (args[0], "keyword")) {
913 struct key_word *k;
914 if (num_words == -1)
915 *a = 0;
916 check_a;
917 k = r[num_contexts - 1]->keyword[num_words] = syntax_malloc (sizeof (struct key_word));
918 if (!strcmp (*a, "whole")) {
919 a++;
920 k->whole_word_chars_left = strdup (whole_left);
921 k->whole_word_chars_right = strdup (whole_right);
922 } else if (!strcmp (*a, "wholeleft")) {
923 a++;
924 k->whole_word_chars_left = strdup (whole_left);
925 } else if (!strcmp (*a, "wholeright")) {
926 a++;
927 k->whole_word_chars_right = strdup (whole_right);
928 }
929 check_a;
930 if (!strcmp (*a, "linestart")) {
931 a++;
932 k->line_start = 1;
933 }
934 check_a;
935 if (!strcmp (*a, "whole")) {
936 *a = 0;
937 check_a;
938 }
939 k->keyword = strdup (*a++);
940 k->last = k->keyword[strlen (k->keyword) - 1];
941 k->first = *k->keyword;
942 fg = *a;
943 if (*a)
944 a++;
945 bg = *a;
946 if (*a)
947 a++;
948 #ifdef MIDNIGHT
949 k->fg = this_try_alloc_color_pair (fg, bg);
950 #else
951 k->fg = this_allocate_color (fg);
952 k->bg = this_allocate_color (bg);
953 #endif
954 check_not_a;
955 num_words++;
956 } else if (!strncmp (args[0], "#", 1)) {
957 /* do nothing for comment */
958 } else if (!strcmp (args[0], "file")) {
959 break;
960 } else { /* anything else is an error */
961 *a = 0;
962 check_a;
963 }
964 free_args (args);
965 syntax_free (l);
966 }
967 free_args (args);
968 syntax_free (l);
969
970 if (result)
971 return result;
972
973 if (num_contexts == -1) {
974 result = line;
975 return result;
976 }
977 for (i = 1; edit->rules[i]; i++) {
978 for (j = i + 1; edit->rules[j]; j++) {
979 if (strstr (edit->rules[j]->right, edit->rules[i]->right) && strcmp (edit->rules[i]->right, "\n")) {
980 unsigned char *s;
981 if (!edit->rules[i]->conflicts)
982 edit->rules[i]->conflicts = syntax_malloc (sizeof (unsigned char) * 260);
983 s = edit->rules[i]->conflicts;
984 s[strlen ((char *) s)] = (unsigned char) j;
985 }
986 }
987 }
988
989 {
990 char first_chars[1024], *p;
991 char last_chars[1024], *q;
992 for (i = 0; edit->rules[i]; i++) {
993 c = edit->rules[i];
994 p = first_chars;
995 q = last_chars;
996 *p++ = (char) 1;
997 *q++ = (char) 1;
998 for (j = 1; c->keyword[j]; j++) {
999 *p++ = c->keyword[j]->first;
1000 *q++ = c->keyword[j]->last;
1001 }
1002 *p = '\0';
1003 *q = '\0';
1004 c->keyword_first_chars = strdup (first_chars);
1005 c->keyword_last_chars = strdup (last_chars);
1006 }
1007 }
1008
1009 return result;
1010 }
1011
1012 void (*syntax_change_callback) (CWidget *) = 0;
1013
1014 void edit_set_syntax_change_callback (void (*callback) (CWidget *))
1015 {
1016 syntax_change_callback = callback;
1017 }
1018
1019 void edit_free_syntax_rules (WEdit * edit)
1020 {
1021 int i, j;
1022 if (!edit)
1023 return;
1024 if (!edit->rules)
1025 return;
1026 syntax_free (edit->syntax_type);
1027 if (syntax_change_callback)
1028 #ifdef MIDNIGHT
1029 (*syntax_change_callback) (&edit->widget);
1030 #else
1031 (*syntax_change_callback) (edit->widget);
1032 #endif
1033 for (i = 0; edit->rules[i]; i++) {
1034 if (edit->rules[i]->keyword) {
1035 for (j = 0; edit->rules[i]->keyword[j]; j++) {
1036 syntax_free (edit->rules[i]->keyword[j]->keyword);
1037 syntax_free (edit->rules[i]->keyword[j]->whole_word_chars_left);
1038 syntax_free (edit->rules[i]->keyword[j]->whole_word_chars_right);
1039 syntax_free (edit->rules[i]->keyword[j]);
1040 }
1041 }
1042 syntax_free (edit->rules[i]->conflicts);
1043 syntax_free (edit->rules[i]->left);
1044 syntax_free (edit->rules[i]->right);
1045 syntax_free (edit->rules[i]->whole_word_chars_left);
1046 syntax_free (edit->rules[i]->whole_word_chars_right);
1047 syntax_free (edit->rules[i]->keyword);
1048 syntax_free (edit->rules[i]->keyword_first_chars);
1049 syntax_free (edit->rules[i]->keyword_last_chars);
1050 syntax_free (edit->rules[i]);
1051 }
1052 syntax_free (edit->rules);
1053 }
1054
1055 #define CURRENT_SYNTAX_RULES_VERSION "22"
1056
1057 char *syntax_text =
1058 "# syntax rules version " CURRENT_SYNTAX_RULES_VERSION "\n"
1059 "# Allowable colors for mc are\n"
1060 "# (after the slash is a Cooledit color, 0-26 or any of the X colors in rgb.txt)\n"
1061 "# black\n"
1062 "# red\n"
1063 "# green\n"
1064 "# brown\n"
1065 "# blue\n"
1066 "# magenta\n"
1067 "# cyan\n"
1068 "# lightgray\n"
1069 "# gray\n"
1070 "# brightred\n"
1071 "# brightgreen\n"
1072 "# yellow\n"
1073 "# brightblue\n"
1074 "# brightmagenta\n"
1075 "# brightcyan\n"
1076 "# white\n"
1077 "\n"
1078 "###############################################################################\n"
1079 "file ..\\*\\\\.tex$ LaTeX\\s2.09\\sDocument\n"
1080 "context default\n"
1081 "wholechars left \\\\\n"
1082 "wholechars right abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
1083 "\n"
1084 "# type style\n"
1085 " keyword whole \\\\tiny yellow/24\n"
1086 " keyword whole \\\\scriptsize yellow/24\n"
1087 " keyword whole \\\\footnotesize yellow/24\n"
1088 " keyword whole \\\\small yellow/24\n"
1089 " keyword whole \\\\normalsize yellow/24\n"
1090 " keyword whole \\\\large yellow/24\n"
1091 " keyword whole \\\\Large yellow/24\n"
1092 " keyword whole \\\\LARGE yellow/24\n"
1093 " keyword whole \\\\huge yellow/24\n"
1094 " keyword whole \\\\Huge yellow/24\n"
1095 "\n"
1096 "# accents and symbols\n"
1097 " keyword whole \\\\`{\\[aeiouAEIOU\\]} yellow/24\n"
1098 " keyword whole \\\\'{\\[aeiouAEIOU\\]} yellow/24\n"
1099 " keyword whole \\\\^{\\[aeiouAEIOU\\]} yellow/24\n"
1100 " keyword whole \\\\\"{\\[aeiouAEIOU\\]} yellow/24\n"
1101 " keyword whole \\\\~{\\[aeiouAEIOU\\]} yellow/24\n"
1102 " keyword whole \\\\={\\[aeiouAEIOU\\]} yellow/24\n"
1103 " keyword whole \\\\.{\\[aeiouAEIOU\\]} yellow/24\n"
1104 " keyword whole \\\\u{\\[aeiouAEIOU\\]} yellow/24\n"
1105 " keyword whole \\\\v{\\[aeiouAEIOU\\]} yellow/24\n"
1106 " keyword whole \\\\H{\\[aeiouAEIOU\\]} yellow/24\n"
1107 " keyword whole \\\\t{\\[aeiouAEIOU\\]} yellow/24\n"
1108 " keyword whole \\\\c{\\[aeiouAEIOU\\]} yellow/24\n"
1109 " keyword whole \\\\d{\\[aeiouAEIOU\\]} yellow/24\n"
1110 " keyword whole \\\\b{\\[aeiouAEIOU\\]} yellow/24\n"
1111 "\n"
1112 " keyword whole \\\\dag yellow/24\n"
1113 " keyword whole \\\\ddag yellow/24\n"
1114 " keyword whole \\\\S yellow/24\n"
1115 " keyword whole \\\\P yellow/24\n"
1116 " keyword whole \\\\copyright yellow/24\n"
1117 " keyword whole \\\\pounds yellow/24\n"
1118 "\n"
1119 "# sectioning and table of contents\n"
1120 " keyword whole \\\\part[*]{*} brightred/19\n"
1121 " keyword whole \\\\part{*} brightred/19\n"
1122 " keyword whole \\\\part\\*{*} brightred/19\n"
1123 " keyword whole \\\\chapter[*]{*} brightred/19\n"
1124 " keyword whole \\\\chapter{*} brightred/19\n"
1125 " keyword whole \\\\chapter\\*{*} brightred/19\n"
1126 " keyword whole \\\\section[*]{*} brightred/19\n"
1127 " keyword whole \\\\section{*} brightred/19\n"
1128 " keyword whole \\\\section\\*{*} brightred/19\n"
1129 " keyword whole \\\\subsection[*]{*} brightred/19\n"
1130 " keyword whole \\\\subsection{*} brightred/19\n"
1131 " keyword whole \\\\subsection\\*{*} brightred/19\n"
1132 " keyword whole \\\\subsubsection[*]{*} brightred/19\n"
1133 " keyword whole \\\\subsubsection{*} brightred/19\n"
1134 " keyword whole \\\\subsubsection\\*{*} brightred/19\n"
1135 " keyword whole \\\\paragraph[*]{*} brightred/19\n"
1136 " keyword whole \\\\paragraph{*} brightred/19\n"
1137 " keyword whole \\\\paragraph\\*{*} brightred/19\n"
1138 " keyword whole \\\\subparagraph[*]{*} brightred/19\n"
1139 " keyword whole \\\\subparagraph{*} brightred/19\n"
1140 " keyword whole \\\\subparagraph\\*{*} brightred/19\n"
1141 "\n"
1142 " keyword whole \\\\appendix brightred/19\n"
1143 " keyword whole \\\\tableofcontents brightred/19\n"
1144 "\n"
1145 "# misc\n"
1146 " keyword whole \\\\item[*] yellow/24\n"
1147 " keyword whole \\\\item yellow/24\n"
1148 " keyword whole \\\\\\\\ yellow/24\n"
1149 " keyword \\\\\\s yellow/24 black/0\n"
1150 " keyword %% yellow/24\n"
1151 "\n"
1152 "# docuement and page styles \n"
1153 " keyword whole \\\\documentstyle[*]{*} yellow/20\n"
1154 " keyword whole \\\\documentstyle{*} yellow/20\n"
1155 " keyword whole \\\\pagestyle{*} yellow/20\n"
1156 "\n"
1157 "# cross references\n"
1158 " keyword whole \\\\label{*} yellow/24\n"
1159 " keyword whole \\\\ref{*} yellow/24\n"
1160 "\n"
1161 "# bibliography and citations\n"
1162 " keyword whole \\\\bibliography{*} yellow/24\n"
1163 " keyword whole \\\\bibitem[*]{*} yellow/24\n"
1164 " keyword whole \\\\bibitem{*} yellow/24\n"
1165 " keyword whole \\\\cite[*]{*} yellow/24\n"
1166 " keyword whole \\\\cite{*} yellow/24\n"
1167 "\n"
1168 "# splitting the input\n"
1169 " keyword whole \\\\input{*} yellow/20\n"
1170 " keyword whole \\\\include{*} yellow/20\n"
1171 " keyword whole \\\\includeonly{*} yellow/20\n"
1172 "\n"
1173 "# line breaking\n"
1174 " keyword whole \\\\linebreak[\\[01234\\]] yellow/24\n"
1175 " keyword whole \\\\nolinebreak[\\[01234\\]] yellow/24\n"
1176 " keyword whole \\\\linebreak yellow/24\n"
1177 " keyword whole \\\\nolinebreak yellow/24\n"
1178 " keyword whole \\\\[+] yellow/24\n"
1179 " keyword whole \\\\- yellow/24\n"
1180 " keyword whole \\\\sloppy yellow/24\n"
1181 "\n"
1182 "# page breaking\n"
1183 " keyword whole \\\\pagebreak[\\[01234\\]] yellow/24\n"
1184 " keyword whole \\\\nopagebreak[\\[01234\\]] yellow/24\n"
1185 " keyword whole \\\\pagebreak yellow/24\n"
1186 " keyword whole \\\\nopagebreak yellow/24\n"
1187 " keyword whole \\\\samepage yellow/24\n"
1188 " keyword whole \\\\newpage yellow/24\n"
1189 " keyword whole \\\\clearpage yellow/24\n"
1190 "\n"
1191 "# defintiions\n"
1192 " keyword \\\\newcommand{*}[*] cyan/5\n"
1193 " keyword \\\\newcommand{*} cyan/5\n"
1194 " keyword \\\\newenvironment{*}[*]{*} cyan/5\n"
1195 " keyword \\\\newenvironment{*}{*} cyan/5\n"
1196 "\n"
1197 "# boxes\n"
1198 "\n"
1199 "# begins and ends\n"
1200 " keyword \\\\begin{document} brightred/14\n"
1201 " keyword \\\\begin{equation} brightred/14\n"
1202 " keyword \\\\begin{eqnarray} brightred/14\n"
1203 " keyword \\\\begin{quote} brightred/14\n"
1204 " keyword \\\\begin{quotation} brightred/14\n"
1205 " keyword \\\\begin{center} brightred/14\n"
1206 " keyword \\\\begin{verse} brightred/14\n"
1207 " keyword \\\\begin{verbatim} brightred/14\n"
1208 " keyword \\\\begin{itemize} brightred/14\n"
1209 " keyword \\\\begin{enumerate} brightred/14\n"
1210 " keyword \\\\begin{description} brightred/14\n"
1211 " keyword \\\\begin{array} brightred/14\n"
1212 " keyword \\\\begin{tabular} brightred/14\n"
1213 " keyword \\\\begin{thebibliography}{*} brightred/14\n"
1214 " keyword \\\\begin{sloppypar} brightred/14\n"
1215 "\n"
1216 " keyword \\\\end{document} brightred/14\n"
1217 " keyword \\\\end{equation} brightred/14\n"
1218 " keyword \\\\end{eqnarray} brightred/14\n"
1219 " keyword \\\\end{quote} brightred/14\n"
1220 " keyword \\\\end{quotation} brightred/14\n"
1221 " keyword \\\\end{center} brightred/14\n"
1222 " keyword \\\\end{verse} brightred/14\n"
1223 " keyword \\\\end{verbatim} brightred/14\n"
1224 " keyword \\\\end{itemize} brightred/14\n"
1225 " keyword \\\\end{enumerate} brightred/14\n"
1226 " keyword \\\\end{description} brightred/14\n"
1227 " keyword \\\\end{array} brightred/14\n"
1228 " keyword \\\\end{tabular} brightred/14\n"
1229 " keyword \\\\end{thebibliography}{*} brightred/14\n"
1230 " keyword \\\\end{sloppypar} brightred/14\n"
1231 "\n"
1232 " keyword \\\\begin{*} brightcyan/16\n"
1233 " keyword \\\\end{*} brightcyan/16\n"
1234 "\n"
1235 " keyword \\\\theorem{*}{*} yellow/24\n"
1236 "\n"
1237 "# if all else fails\n"
1238 " keyword whole \\\\+[*]{*}{*}{*} brightcyan/17\n"
1239 " keyword whole \\\\+[*]{*}{*} brightcyan/17\n"
1240 " keyword whole \\\\+{*}{*}{*}{*} brightcyan/17\n"
1241 " keyword whole \\\\+{*}{*}{*} brightcyan/17\n"
1242 " keyword whole \\\\+{*}{*} brightcyan/17\n"
1243 " keyword whole \\\\+{*} brightcyan/17\n"
1244 " keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\n brightcyan/17\n"
1245 " keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\s brightcyan/17\n"
1246 " keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\t brightcyan/17\n"
1247 "\n"
1248 "context \\\\pagenumbering{ } yellow/20\n"
1249 " keyword arabic brightcyan/17\n"
1250 " keyword roman brightcyan/17\n"
1251 " keyword alph brightcyan/17\n"
1252 " keyword Roman brightcyan/17\n"
1253 " keyword Alph brightcyan/17\n"
1254 "\n"
1255 "context % \\n brown/22\n"
1256 "\n"
1257 "# mathematical formulas\n"
1258 "context $ $ brightgreen/6\n"
1259 "context exclusive \\\\begin{equation} \\\\end{equation} brightgreen/6\n"
1260 "context exclusive \\\\begin{eqnarray} \\\\end{eqnarray} brightgreen/6\n"
1261 "\n"
1262 "\n"
1263 "###############################################################################\n"
1264 "file ..\\*\\\\.([chC]|CC|cxx|cc|cpp|CPP|CXX)$ C/C\\+\\+\\sProgram\n"
1265 "context default\n"
1266 " keyword whole auto yellow/24\n"
1267 " keyword whole break yellow/24\n"
1268 " keyword whole case yellow/24\n"
1269 " keyword whole char yellow/24\n"
1270 " keyword whole const yellow/24\n"
1271 " keyword whole continue yellow/24\n"
1272 " keyword whole default yellow/24\n"
1273 " keyword whole do yellow/24\n"
1274 " keyword whole double yellow/24\n"
1275 " keyword whole else yellow/24\n"
1276 " keyword whole enum yellow/24\n"
1277 " keyword whole extern yellow/24\n"
1278 " keyword whole float yellow/24\n"
1279 " keyword whole for yellow/24\n"
1280 " keyword whole goto yellow/24\n"
1281 " keyword whole if yellow/24\n"
1282 " keyword whole int yellow/24\n"
1283 " keyword whole long yellow/24\n"
1284 " keyword whole register yellow/24\n"
1285 " keyword whole return yellow/24\n"
1286 " keyword whole short yellow/24\n"
1287 " keyword whole signed yellow/24\n"
1288 " keyword whole sizeof yellow/24\n"
1289 " keyword whole static yellow/24\n"
1290 " keyword whole struct yellow/24\n"
1291 " keyword whole switch yellow/24\n"
1292 " keyword whole typedef yellow/24\n"
1293 " keyword whole union yellow/24\n"
1294 " keyword whole unsigned yellow/24\n"
1295 " keyword whole void yellow/24\n"
1296 " keyword whole volatile yellow/24\n"
1297 " keyword whole while yellow/24\n"
1298 " keyword whole asm yellow/24\n"
1299 " keyword whole catch yellow/24\n"
1300 " keyword whole class yellow/24\n"
1301 " keyword whole friend yellow/24\n"
1302 " keyword whole delete yellow/24\n"
1303 " keyword whole inline yellow/24\n"
1304 " keyword whole new yellow/24\n"
1305 " keyword whole operator yellow/24\n"
1306 " keyword whole private yellow/24\n"
1307 " keyword whole protected yellow/24\n"
1308 " keyword whole public yellow/24\n"
1309 " keyword whole this yellow/24\n"
1310 " keyword whole throw yellow/24\n"
1311 " keyword whole template yellow/24\n"
1312 " keyword whole try yellow/24\n"
1313 " keyword whole virtual yellow/24\n"
1314 " keyword whole bool yellow/24\n"
1315 " keyword whole const_cast yellow/24\n"
1316 " keyword whole dynamic_cast yellow/24\n"
1317 " keyword whole explicit yellow/24\n"
1318 " keyword whole false yellow/24\n"
1319 " keyword whole mutable yellow/24\n"
1320 " keyword whole namespace yellow/24\n"
1321 " keyword whole reinterpret_cast yellow/24\n"
1322 " keyword whole static_cast yellow/24\n"
1323 " keyword whole true yellow/24\n"
1324 " keyword whole typeid yellow/24\n"
1325 " keyword whole typename yellow/24\n"
1326 " keyword whole using yellow/24\n"
1327 " keyword whole wchar_t yellow/24\n"
1328 " keyword whole ... yellow/24\n"
1329 "\n"
1330 " keyword /\\* brown/22\n"
1331 " keyword \\*/ brown/22\n"
1332 "\n"
1333 " keyword '\\s' brightgreen/16\n"
1334 " keyword '+' brightgreen/16\n"
1335 " keyword > yellow/24\n"
1336 " keyword < yellow/24\n"
1337 " keyword \\+ yellow/24\n"
1338 " keyword - yellow/24\n"
1339 " keyword \\* yellow/24\n"
1340 " keyword / yellow/24\n"
1341 " keyword % yellow/24\n"
1342 " keyword = yellow/24\n"
1343 " keyword != yellow/24\n"
1344 " keyword == yellow/24\n"
1345 " keyword { brightcyan/14\n"
1346 " keyword } brightcyan/14\n"
1347 " keyword ( brightcyan/15\n"
1348 " keyword ) brightcyan/15\n"
1349 " keyword [ brightcyan/14\n"
1350 " keyword ] brightcyan/14\n"
1351 " keyword , brightcyan/14\n"
1352 " keyword : brightcyan/14\n"
1353 " keyword ; brightmagenta/19\n"
1354 "context exclusive /\\* \\*/ brown/22\n"
1355 "context linestart # \\n brightred/18\n"
1356 " keyword \\\\\\n yellow/24\n"
1357 " keyword /\\**\\*/ brown/22\n"
1358 " keyword \"+\" red/19\n"
1359 " keyword <+> red/19\n"
1360 "context \" \" green/6\n"
1361 " keyword \\\\\" brightgreen/16\n"
1362 " keyword %% brightgreen/16\n"
1363 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]e brightgreen/16\n"
1364 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]E brightgreen/16\n"
1365 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]f brightgreen/16\n"
1366 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]g brightgreen/16\n"
1367 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]G brightgreen/16\n"
1368 " keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]d brightgreen/16\n"
1369 " keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]i brightgreen/16\n"
1370 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]o brightgreen/16\n"
1371 " keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]u brightgreen/16\n"
1372 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]x brightgreen/16\n"
1373 " keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]X brightgreen/16\n"
1374 " keyword %\\[hl\\]n brightgreen/16\n"
1375 " keyword %\\[.\\]\\[0123456789\\]s brightgreen/16\n"
1376 " keyword %[*] brightgreen/16\n"
1377 " keyword %c brightgreen/16\n"
1378 " keyword \\\\\\\\ brightgreen/16\n"
1379 "\n"
1380 "###############################################################################\n"
1381 "file .\\*ChangeLog$ GNU\\sDistribution\\sChangeLog\\sFile\n"
1382 "\n"
1383 "context default\n"
1384 " keyword \\s+() brightmagenta/23\n"
1385 " keyword \\t+() brightmagenta/23\n"
1386 "\n"
1387 "context linestart \\t\\* : brightcyan/17\n"
1388 "context linestart \\s\\s\\s\\s\\s\\s\\s\\s\\* : brightcyan/17\n"
1389 "\n"
1390 "context linestart 19+-+\\s \\n yellow/24\n"
1391 " keyword <+@+> brightred/19\n"
1392 "context linestart 20+-+\\s \\n yellow/24\n"
1393 " keyword <+@+> brightred/19\n"
1394 "context linestart Mon\\s+\\s+\\s+\\s \\n yellow/24\n"
1395 " keyword <+@+> brightred/19\n"
1396 "context linestart Tue\\s+\\s+\\s+\\s \\n yellow/24\n"
1397 " keyword <+@+> brightred/19\n"
1398 "context linestart Wed\\s+\\s+\\s+\\s \\n yellow/24\n"
1399 " keyword <+@+> brightred/19\n"
1400 "context linestart Thu\\s+\\s+\\s+\\s \\n yellow/24\n"
1401 " keyword <+@+> brightred/19\n"
1402 "context linestart Fri\\s+\\s+\\s+\\s \\n yellow/24\n"
1403 " keyword <+@+> brightred/19\n"
1404 "context linestart Sat\\s+\\s+\\s+\\s \\n yellow/24\n"
1405 " keyword <+@+> brightred/19\n"
1406 "context linestart Sun\\s+\\s+\\s+\\s \\n yellow/24\n"
1407 " keyword <+@+> brightred/19\n"
1408 "\n"
1409 "\n"
1410 "###############################################################################\n"
1411 "file .\\*Makefile[\\\\\\.a-z]\\*$ Makefile\n"
1412 "\n"
1413 "context default\n"
1414 " keyword $(*) yellow/24\n"
1415 " keyword ${*} brightgreen/16\n"
1416 " keyword whole linestart include magenta\n"
1417 " keyword whole linestart endif magenta\n"
1418 " keyword whole linestart ifeq magenta\n"
1419 " keyword whole linestart ifneq magenta\n"
1420 " keyword whole linestart else magenta\n"
1421 " keyword linestart \\t lightgray/13 red\n"
1422 " keyword whole .PHONY white/25\n"
1423 " keyword whole .NOEXPORT white/25\n"
1424 " keyword = white/25\n"
1425 " keyword : yellow/24\n"
1426 " keyword \\\\\\n yellow/24\n"
1427 "# this handles strange cases like @something@@somethingelse@ properly\n"
1428 " keyword whole @+@ brightmagenta/23 black/0\n"
1429 " keyword @+@ brightmagenta/23 black/0\n"
1430 "\n"
1431 "context linestart # \\n brown/22\n"
1432 " keyword whole @+@ brightmagenta/23 black/0\n"
1433 " keyword @+@ brightmagenta/23 black/0\n"
1434 "\n"
1435 "context exclusive = \\n brightcyan/17\n"
1436 " keyword \\\\\\n yellow/24\n"
1437 " keyword $(*) yellow/24\n"
1438 " keyword ${*} brightgreen/16\n"
1439 " keyword linestart \\t lightgray/13 red\n"
1440 " keyword whole @+@ brightmagenta/23 black/0\n"
1441 " keyword @+@ brightmagenta/23 black/0\n"
1442 "\n"
1443 "context exclusive linestart \\t \\n\n"
1444 " keyword \\\\\\n yellow/24\n"
1445 " keyword $(*) yellow/24\n"
1446 " keyword ${*} brightgreen/16\n"
1447 " keyword linestart \\t lightgray/13 red\n"
1448 " keyword whole @+@ brightmagenta/23 black/0\n"
1449 " keyword @+@ brightmagenta/23 black/0\n"
1450 "\n"
1451 "###############################################################################\n"
1452 "\n"
1453 "file .\\*syntax$ Syntax\\sHighlighting\\sdefinitions\n"
1454 "\n"
1455 "context default\n"
1456 " keyword whole keyw\\ord yellow/24\n"
1457 " keyword whole whole\\[\\t\\s\\]l\\inestart brightcyan/17\n"
1458 " keyword whole whole\\[\\t\\s\\]l\\inestart brightcyan/17\n"
1459 " keyword whole wh\\oleleft\\[\\t\\s\\]l\\inestart brightcyan/17\n"
1460 " keyword whole wh\\oleright\\[\\t\\s\\]l\\inestart brightcyan/17\n"
1461 " keyword whole l\\inestart\\[\\t\\s\\]wh\\ole\n"
1462 " keyword whole l\\inestart\\[\\t\\s\\]wh\\ole\n"
1463 " keyword whole l\\inestart\\[\\t\\s\\]wh\\oleleft\n"
1464 " keyword whole l\\inestart\\[\\t\\s\\]wh\\oleright\n"
1465 " keyword wholeleft whole\\s brightcyan/17\n"
1466 " keyword wholeleft whole\\t brightcyan/17\n"
1467 " keyword whole wh\\oleleft brightcyan/17\n"
1468 " keyword whole wh\\oleright brightcyan/17\n"
1469 " keyword whole lin\\[e\\]start brightcyan/17\n"
1470 " keyword whole c\\ontext\\[\\t\\s\\]exclusive brightred/18\n"
1471 " keyword whole c\\ontext\\[\\t\\s\\]default brightred/18\n"
1472 " keyword whole c\\ontext brightred/18\n"
1473 " keyword whole wh\\olechars\\[\\t\\s\\]left brightcyan/17\n"
1474 " keyword whole wh\\olechars\\[\\t\\s\\]right brightcyan/17\n"
1475 " keyword whole wh\\olechars brightcyan/17\n"
1476 " keyword whole f\\ile brightgreen/6\n"
1477 "\n"
1478 " keyword whole 0 lightgray/0 blue/26\n"
1479 " keyword whole 1 lightgray/1 blue/26\n"
1480 " keyword whole 2 lightgray/2 blue/26\n"
1481 " keyword whole 3 lightgray/3 blue/26\n"
1482 " keyword whole 4 lightgray/4 blue/26\n"
1483 " keyword whole 5 lightgray/5 blue/26\n"
1484 " keyword whole 6 lightgray/6\n"
1485 " keyword whole 7 lightgray/7\n"
1486 " keyword whole 8 lightgray/8\n"
1487 " keyword whole 9 lightgray/9\n"
1488 " keyword whole 10 lightgray/10\n"
1489 " keyword whole 11 lightgray/11\n"
1490 " keyword whole 12 lightgray/12\n"
1491 " keyword whole 13 lightgray/13\n"
1492 " keyword whole 14 lightgray/14\n"
1493 " keyword whole 15 lightgray/15\n"
1494 " keyword whole 16 lightgray/16\n"
1495 " keyword whole 17 lightgray/17\n"
1496 " keyword whole 18 lightgray/18\n"
1497 " keyword whole 19 lightgray/19\n"
1498 " keyword whole 20 lightgray/20\n"
1499 " keyword whole 21 lightgray/21\n"
1500 " keyword whole 22 lightgray/22\n"
1501 " keyword whole 23 lightgray/23\n"
1502 " keyword whole 24 lightgray/24\n"
1503 " keyword whole 25 lightgray/25\n"
1504 " keyword whole 26 lightgray/26\n"
1505 "\n"
1506 " keyword wholeleft black\\/ black/0\n"
1507 " keyword wholeleft red\\/ red/DarkRed\n"
1508 " keyword wholeleft green\\/ green/green3\n"
1509 " keyword wholeleft brown\\/ brown/saddlebrown\n"
1510 " keyword wholeleft blue\\/ blue/blue3\n"
1511 " keyword wholeleft magenta\\/ magenta/magenta3\n"
1512 " keyword wholeleft cyan\\/ cyan/cyan3\n"
1513 " keyword wholeleft lightgray\\/ lightgray/lightgray\n"
1514 " keyword wholeleft gray\\/ gray/gray\n"
1515 " keyword wholeleft brightred\\/ brightred/red\n"
1516 " keyword wholeleft brightgreen\\/ brightgreen/green1\n"
1517 " keyword wholeleft yellow\\/ yellow/yellow\n"
1518 " keyword wholeleft brightblue\\/ brightblue/blue1\n"
1519 " keyword wholeleft brightmagenta\\/ brightmagenta/magenta\n"
1520 " keyword wholeleft brightcyan\\/ brightcyan/cyan1\n"
1521 " keyword wholeleft white\\/ white/26\n"
1522 "\n"
1523 "context linestart # \\n brown/22\n"
1524 "\n"
1525 "file \\.\\* Help\\ssupport\\sother\\sfile\\stypes\n"
1526 "context default\n"
1527 "file \\.\\* by\\scoding\\srules\\sin\\s~/.cedit/syntax.\n"
1528 "context default\n"
1529 "file \\.\\* See\\sman/syntax\\sin\\sthe\\ssource\\sdistribution\n"
1530 "context default\n"
1531 "file \\.\\* and\\sconsult\\sthe\\sman\\spage.\n"
1532 "context default\n";
1533
1534
1535
1536 FILE *upgrade_syntax_file (char *syntax_file)
1537 {
1538 FILE *f;
1539 char line[80];
1540 f = fopen (syntax_file, "r");
1541 if (!f) {
1542 f = fopen (syntax_file, "w");
1543 if (!f)
1544 return 0;
1545 fprintf (f, "%s", syntax_text);
1546 fclose (f);
1547 return fopen (syntax_file, "r");
1548 }
1549 memset (line, 0, 79);
1550 fread (line, 80, 1, f);
1551 if (!strstr (line, "syntax rules version")) {
1552 goto rename_rule_file;
1553 } else {
1554 char *p;
1555 p = strstr (line, "version") + strlen ("version") + 1;
1556 if (atoi (p) < atoi (CURRENT_SYNTAX_RULES_VERSION)) {
1557 char s[1024];
1558 rename_rule_file:
1559 strcpy (s, syntax_file);
1560 strcat (s, ".OLD");
1561 unlink (s);
1562 rename (syntax_file, s);
1563 unlink (syntax_file); /* might rename() fail ? */
1564 #ifdef MIDNIGHT
1565 edit_message_dialog (" Load Syntax Rules ", " Your syntax rule file is outdated \n A new rule file is being installed. \n Your old rule file has been saved with a .OLD extension. ");
1566 #else
1567 CMessageDialog (0, 20, 20, 0, " Load Syntax Rules ", " Your syntax rule file is outdated \n A new rule file is being installed. \n Your old rule file has been saved with a .OLD extension. ");
1568 #endif
1569 return upgrade_syntax_file (syntax_file);
1570 } else {
1571 rewind (f);
1572 return (f);
1573 }
1574 }
1575 return 0; /* not reached */
1576 }
1577
1578 /* returns -1 on file error, line number on error in file syntax */
1579 static int edit_read_syntax_file (WEdit * edit, char **names, char *syntax_file, char *editor_file, char *type)
1580 {
1581 FILE *f;
1582 regex_t r;
1583 regmatch_t pmatch[1];
1584 char *args[1024], *l;
1585 int line = 0;
1586 int argc;
1587 int result = 0;
1588 int count = 0;
1589
1590 f = upgrade_syntax_file (syntax_file);
1591 if (!f)
1592 return -1;
1593 args[0] = 0;
1594
1595 for (;;) {
1596 line++;
1597 if (!read_one_line (&l, f))
1598 break;
1599 get_args (l, args, &argc);
1600 if (!args[0]) {
1601 } else if (!strcmp (args[0], "file")) {
1602 if (!args[1] || !args[2]) {
1603 result = line;
1604 break;
1605 }
1606 if (regcomp (&r, args[1], REG_EXTENDED)) {
1607 result = line;
1608 break;
1609 }
1610 if (names) {
1611 names[count++] = strdup (args[2]);
1612 names[count] = 0;
1613 } else if (type) {
1614 if (!strcmp (type, args[2]))
1615 goto found_type;
1616 } else if (editor_file && edit) {
1617 if (!regexec (&r, editor_file, 1, pmatch, 0)) {
1618 int line_error;
1619 found_type:
1620 line_error = edit_read_syntax_rules (edit, f);
1621 if (line_error)
1622 result = line + line_error;
1623 else {
1624 syntax_free (edit->syntax_type);
1625 edit->syntax_type = strdup (args[2]);
1626 if (syntax_change_callback)
1627 #ifdef MIDNIGHT
1628 (*syntax_change_callback) (&edit->widget);
1629 #else
1630 (*syntax_change_callback) (edit->widget);
1631 #endif
1632 /* if there are no rules then turn off syntax highlighting for speed */
1633 if (!edit->rules[1])
1634 if (!edit->rules[0]->keyword[1])
1635 edit_free_syntax_rules (edit);
1636 }
1637 break;
1638 }
1639 }
1640 }
1641 free_args (args);
1642 syntax_free (l);
1643 }
1644 free_args (args);
1645 syntax_free (l);
1646
1647 fclose (f);
1648
1649 return result;
1650 }
1651
1652 /* loads rules into edit struct. one of edit or names must be zero. if
1653 edit is zero, a list of types will be stored into name. type may be zero
1654 in which case the type will be selected according to the filename. */
1655 void edit_load_syntax (WEdit * edit, char **names, char *type)
1656 {
1657 int r;
1658 char *f;
1659
1660 edit_free_syntax_rules (edit);
1661
1662 #ifdef MIDNIGHT
1663 if (!SLtt_Use_Ansi_Colors)
1664 return;
1665 #endif
1666
1667 if (edit) {
1668 if (!edit->filename)
1669 return;
1670 if (!*edit->filename && !type)
1671 return;
1672 }
1673 f = catstrs (home_dir, SYNTAX_FILE, 0);
1674 r = edit_read_syntax_file (edit, names, f, edit ? edit->filename : 0, type);
1675 if (r == -1) {
1676 edit_free_syntax_rules (edit);
1677 edit_error_dialog (_ (" Load syntax file "), _ (" File access error "));
1678 return;
1679 }
1680 if (r) {
1681 char s[80];
1682 edit_free_syntax_rules (edit);
1683 sprintf (s, _ (" Syntax error in file %s on line %d "), f, r);
1684 edit_error_dialog (_ (" Load syntax file "), s);
1685 return;
1686 }
1687 }
1688
1689 #else
1690
1691 int option_syntax_highlighting = 0;
1692
1693 void edit_load_syntax (WEdit * edit, char **names, char *type)
1694 {
1695 return;
1696 }
1697
1698 void edit_free_syntax_rules (WEdit * edit)
1699 {
1700 return;
1701 }
1702
1703 void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg)
1704 {
1705 *fg = NORMAL_COLOR;
1706 }
1707
1708 #endif /* !defined(MIDNIGHT) || defined(HAVE_SYNTAXH) */
1709
1710
1711
1712