1 /* editor syntax highlighting.
3 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007 Free Software Foundation, Inc.
6 Authors: 1998 Paul Sheer
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 * \brief Source: editor syntax highlighting
29 * Mispelled words are flushed from the syntax highlighting rules
30 * when they have been around longer than
31 * TRANSIENT_WORD_TIME_OUT seconds. At a cursor rate of 30
32 * chars per second and say 3 chars + a space per word, we can
33 * accumulate 450 words absolute max with a value of 60. This is
34 * below this limit of 1024 words in a context.
41 #include <sys/types.h>
49 #include "../src/global.h"
51 #include "edit-impl.h"
52 #include "edit-widget.h"
54 #include "../src/search/search.h" /* search engine */
56 #include "../src/tty/color.h"
58 #include "edit-impl.h"
59 #include "edit-widget.h"
61 #include "../src/main.h" /* mc_home */
62 #include "../src/wtools.h" /* message() */
63 #include "../src/strutil.h" /* utf string functions */
66 #define SYNTAX_MARKER_DENSITY 512
68 #define TRANSIENT_WORD_TIME_OUT 60
70 #define UNKNOWN_FORMAT "unknown"
72 #define MAX_WORDS_PER_CONTEXT 1024
73 #define MAX_CONTEXTS 128
75 #define RULE_ON_LEFT_BORDER 1
76 #define RULE_ON_RIGHT_BORDER 2
78 #define SYNTAX_TOKEN_STAR '\001'
79 #define SYNTAX_TOKEN_PLUS '\002'
80 #define SYNTAX_TOKEN_BRACKET '\003'
81 #define SYNTAX_TOKEN_BRACE '\004'
86 char *whole_word_chars_left
;
87 char *whole_word_chars_right
;
94 unsigned char first_left
;
96 unsigned char first_right
;
98 char line_start_right
;
99 int between_delimiters
;
100 char *whole_word_chars_left
;
101 char *whole_word_chars_right
;
102 char *keyword_first_chars
;
104 /* first word is word[1] */
105 struct key_word
**keyword
;
108 struct _syntax_marker
{
110 struct syntax_rule rule
;
111 struct _syntax_marker
*next
;
114 int option_syntax_highlighting
= 1;
115 int option_auto_syntax
= 1;
116 char *option_syntax_type
= NULL
;
119 mc_defines_destroy (gpointer key
, gpointer value
, gpointer data
)
121 char **values
= value
;
133 /* Completely destroys the defines tree */
135 destroy_defines (GTree
**defines
)
137 g_tree_traverse (*defines
, mc_defines_destroy
, G_POST_ORDER
, NULL
);
138 g_tree_destroy (*defines
);
143 subst_defines (GTree
*defines
, char **argv
, char **argv_end
)
148 while (*argv
&& argv
< argv_end
) {
149 if ((t
= g_tree_lookup (defines
, *argv
))) {
152 /* Count argv array members */
154 for (p
= &argv
[1]; *p
; p
++)
157 /* Count members of definition array */
160 p
= &argv
[count
+ argc
];
162 /* Buffer overflow or infinitive loop in define */
166 /* Move rest of argv after definition members */
168 *p
-- = argv
[argc
-- + 1];
170 /* Copy definition members to argv */
171 for (p
= argv
; *t
; *p
++ = *t
++);
178 compare_word_to_right (WEdit
*edit
, long i
, const char *text
,
179 const char *whole_left
, const char *whole_right
,
182 const unsigned char *p
, *q
;
187 c
= edit_get_byte (edit
, i
- 1);
192 if (strchr (whole_left
, c
))
195 for (p
= (unsigned char *) text
, q
= p
+ str_term_width1 ((char *) p
); p
< q
; p
++, i
++) {
197 case SYNTAX_TOKEN_STAR
:
201 c
= edit_get_byte (edit
, i
);
204 if (!strchr (whole_right
, c
))
213 case SYNTAX_TOKEN_PLUS
:
218 c
= edit_get_byte (edit
, i
);
221 if (*p
== *text
&& !p
[1]) /* handle eg '+' and @+@ keywords properly */
224 if (j
&& strchr ((char *) p
+ 1, c
)) /* c exists further down, so it will get matched later */
226 if (c
== '\n' || c
== '\t' || c
== ' ') {
237 if (!strchr (whole_right
, c
)) {
250 case SYNTAX_TOKEN_BRACKET
:
256 c
= edit_get_byte (edit
, i
);
257 for (j
= 0; p
[j
] != SYNTAX_TOKEN_BRACKET
&& p
[j
]; j
++)
262 ; /* dummy command */
265 while (*p
!= SYNTAX_TOKEN_BRACKET
&& p
<= q
)
272 case SYNTAX_TOKEN_BRACE
:
275 c
= edit_get_byte (edit
, i
);
276 for (; *p
!= SYNTAX_TOKEN_BRACE
&& *p
; p
++)
281 while (*p
!= SYNTAX_TOKEN_BRACE
&& p
< q
)
285 if (*p
!= edit_get_byte (edit
, i
))
290 if (strchr (whole_right
, edit_get_byte (edit
, i
)))
295 static inline const char *xx_strchr (const unsigned char *s
, int c
)
297 while (*s
>= '\005' && *s
!= (unsigned char) c
) {
300 return (const char *) s
;
303 static inline struct syntax_rule
apply_rules_going_right (WEdit
* edit
, long i
, struct syntax_rule rule
)
305 struct context_rule
*r
;
306 int contextchanged
= 0, c
;
307 int found_right
= 0, found_left
= 0, keyword_foundleft
= 0, keyword_foundright
= 0;
310 struct syntax_rule _rule
= rule
;
312 if (!(c
= edit_get_byte (edit
, i
)))
314 is_end
= (rule
.end
== (unsigned char) i
);
316 /* check to turn off a keyword */
318 if (edit_get_byte (edit
, i
- 1) == '\n')
322 keyword_foundleft
= 1;
326 /* check to turn off a context */
327 if (_rule
.context
&& !_rule
.keyword
) {
329 r
= edit
->rules
[_rule
.context
];
330 if (r
->first_right
== c
&& !(rule
.border
& RULE_ON_RIGHT_BORDER
) && (e
= compare_word_to_right (edit
, i
, r
->right
, r
->whole_word_chars_left
, r
->whole_word_chars_right
, r
->line_start_right
)) > 0) {
333 _rule
.border
= RULE_ON_RIGHT_BORDER
;
334 if (r
->between_delimiters
)
336 } else if (is_end
&& rule
.border
& RULE_ON_RIGHT_BORDER
) {
338 /* always turn off a context at 4 */
341 if (!keyword_foundleft
)
343 } else if (is_end
&& rule
.border
& RULE_ON_LEFT_BORDER
) {
345 /* never turn off a context at 2 */
351 /* check to turn on a keyword */
352 if (!_rule
.keyword
) {
355 p
= (r
= edit
->rules
[_rule
.context
])->keyword_first_chars
;
357 while (*(p
= xx_strchr ((unsigned char *) p
+ 1, c
))) {
362 count
= p
- r
->keyword_first_chars
;
363 k
= r
->keyword
[count
];
364 e
= compare_word_to_right (edit
, i
, k
->keyword
, k
->whole_word_chars_left
, k
->whole_word_chars_right
, k
->line_start
);
368 _rule
.keyword
= count
;
369 keyword_foundright
= 1;
374 /* check to turn on a context */
375 if (!_rule
.context
) {
376 if (!found_left
&& is_end
) {
377 if (rule
.border
& RULE_ON_RIGHT_BORDER
) {
383 } else if (rule
.border
& RULE_ON_LEFT_BORDER
) {
384 r
= edit
->rules
[_rule
._context
];
386 if (r
->between_delimiters
) {
388 _rule
.context
= _rule
._context
;
391 if (r
->first_right
== c
&& (e
= compare_word_to_right (edit
, i
, r
->right
, r
->whole_word_chars_left
, r
->whole_word_chars_right
, r
->line_start_right
)) >= end
) {
394 _rule
.border
= RULE_ON_RIGHT_BORDER
;
403 struct context_rule
**rules
= edit
->rules
;
405 for (count
= 1; rules
[count
]; count
++) {
407 if (r
->first_left
== c
) {
410 e
= compare_word_to_right (edit
, i
, r
->left
, r
->whole_word_chars_left
, r
->whole_word_chars_right
, r
->line_start_left
);
411 if (e
>= end
&& (!_rule
.keyword
|| keyword_foundright
)) {
414 _rule
.border
= RULE_ON_LEFT_BORDER
;
415 _rule
._context
= count
;
416 if (!r
->between_delimiters
)
417 if (!_rule
.keyword
) {
418 _rule
.context
= count
;
428 /* check again to turn on a keyword if the context switched */
429 if (contextchanged
&& !_rule
.keyword
) {
432 p
= (r
= edit
->rules
[_rule
.context
])->keyword_first_chars
;
433 while (*(p
= xx_strchr ((unsigned char *) p
+ 1, c
))) {
438 count
= p
- r
->keyword_first_chars
;
439 k
= r
->keyword
[count
];
440 e
= compare_word_to_right (edit
, i
, k
->keyword
, k
->whole_word_chars_left
, k
->whole_word_chars_right
, k
->line_start
);
443 _rule
.keyword
= count
;
451 static struct syntax_rule
edit_get_rule (WEdit
* edit
, long byte_index
)
455 if (byte_index
> edit
->last_get_rule
) {
456 for (i
= edit
->last_get_rule
+ 1; i
<= byte_index
; i
++) {
457 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
458 if (i
> (edit
->syntax_marker
? edit
->syntax_marker
->offset
+ SYNTAX_MARKER_DENSITY
: SYNTAX_MARKER_DENSITY
)) {
459 struct _syntax_marker
*s
;
461 s
= edit
->syntax_marker
;
462 edit
->syntax_marker
= g_malloc0 (sizeof (struct _syntax_marker
));
463 edit
->syntax_marker
->next
= s
;
464 edit
->syntax_marker
->offset
= i
;
465 edit
->syntax_marker
->rule
= edit
->rule
;
468 } else if (byte_index
< edit
->last_get_rule
) {
469 struct _syntax_marker
*s
;
472 if (!edit
->syntax_marker
) {
473 memset (&edit
->rule
, 0, sizeof (edit
->rule
));
474 for (i
= -1; i
<= byte_index
; i
++)
475 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
478 if (byte_index
>= edit
->syntax_marker
->offset
) {
479 edit
->rule
= edit
->syntax_marker
->rule
;
480 for (i
= edit
->syntax_marker
->offset
+ 1; i
<= byte_index
; i
++)
481 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
484 s
= edit
->syntax_marker
->next
;
485 MC_PTR_FREE (edit
->syntax_marker
);
486 edit
->syntax_marker
= s
;
489 edit
->last_get_rule
= byte_index
;
493 static void translate_rule_to_color (WEdit
* edit
, struct syntax_rule rule
, int *color
)
497 k
= edit
->rules
[rule
.context
]->keyword
[rule
.keyword
];
501 void edit_get_syntax_color (WEdit
* edit
, long byte_index
, int *color
)
503 if (edit
->rules
&& byte_index
< edit
->last_byte
&&
504 option_syntax_highlighting
&& tty_use_colors ()) {
505 translate_rule_to_color (edit
, edit_get_rule (edit
, byte_index
), color
);
507 *color
= tty_use_colors () ? EDITOR_NORMAL_COLOR_INDEX
: 0;
513 Returns 0 on error/eof or a count of the number of bytes read
514 including the newline. Result must be free'd.
515 In case of an error, *line will not be modified.
517 static int read_one_line (char **line
, FILE * f
)
519 GString
*p
= g_string_new ("");
533 /* handle all of \r\n, \r, \n correctly. */
535 if ( (c
= fgetc (f
)) == '\n')
544 g_string_append_c (p
, c
);
548 g_string_free (p
, FALSE
);
550 g_string_free (p
, TRUE
);
555 static char *convert (char *s
)
589 *p
= SYNTAX_TOKEN_BRACKET
;
593 *p
= SYNTAX_TOKEN_BRACE
;
604 *p
= SYNTAX_TOKEN_STAR
;
607 *p
= SYNTAX_TOKEN_PLUS
;
620 #define whiteness(x) ((x) == '\t' || (x) == '\n' || (x) == ' ')
622 static int get_args (char *l
, char **args
, int args_size
)
626 while (argc
< args_size
) {
628 while (*p
&& whiteness (*p
))
632 for (l
= p
+ 1; *l
&& !whiteness (*l
); l
++);
635 args
[argc
++] = convert (p
);
637 args
[argc
] = (char *) NULL
;
642 #define break_a {result=line;break;}
643 #define check_a {if(!*a){result=line;break;}}
644 #define check_not_a {if(*a){result=line;break;}}
647 this_try_alloc_color_pair (const char *fg
, const char *bg
)
649 char f
[80], b
[80], *p
;
658 g_strlcpy (f
, fg
, sizeof (f
));
665 g_strlcpy (b
, bg
, sizeof (b
));
671 return tty_try_alloc_color_pair (fg
, bg
);
674 static char *error_file_name
= 0;
676 static FILE *open_include_file (const char *filename
)
680 MC_PTR_FREE (error_file_name
);
681 error_file_name
= g_strdup (filename
);
682 if (*filename
== PATH_SEP
)
683 return fopen (filename
, "r");
685 g_free (error_file_name
);
686 error_file_name
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR PATH_SEP_STR
,
687 filename
, (char *) NULL
);
688 f
= fopen (error_file_name
, "r");
692 g_free (error_file_name
);
693 error_file_name
= g_strconcat (mc_home
, PATH_SEP_STR
, "syntax", PATH_SEP_STR
,
694 filename
, (char *) NULL
);
696 if ((f
= fopen (error_file_name
, "r"))) {
697 g_free (error_file_name
);
700 g_free (error_file_name
);
701 error_file_name
= g_strconcat (mc_home_alt
, PATH_SEP_STR
"syntax" PATH_SEP_STR
,
702 filename
, (char *) NULL
);
704 return fopen (error_file_name
, "r");
707 /* returns line number on error */
709 edit_read_syntax_rules (WEdit
*edit
, FILE *f
, char **args
, int args_size
)
713 char last_fg
[32] = "", last_bg
[32] = "";
714 char whole_right
[512];
715 char whole_left
[512];
717 int save_line
= 0, line
= 0;
718 struct context_rule
**r
, *c
= 0;
719 int num_words
= -1, num_contexts
= -1;
723 int alloc_contexts
= MAX_CONTEXTS
,
724 alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
,
725 max_alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
;
729 strcpy (whole_left
, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
730 strcpy (whole_right
, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
732 r
= edit
->rules
= g_malloc0 (alloc_contexts
* sizeof (struct context_rule
*));
735 edit
->defines
= g_tree_new ((GCompareFunc
) strcmp
);
742 if (!read_one_line (&l
, f
)) {
747 line
= save_line
+ 1;
748 MC_PTR_FREE (error_file_name
);
750 if (!read_one_line (&l
, f
))
756 argc
= get_args (l
, args
, args_size
);
760 } else if (!strcmp (args
[0], "include")) {
761 if (g
|| argc
!= 2) {
766 f
= open_include_file (args
[1]);
768 MC_PTR_FREE (error_file_name
);
774 } else if (!strcmp (args
[0], "wholechars")) {
776 if (!strcmp (*a
, "left")) {
778 g_strlcpy (whole_left
, *a
, sizeof (whole_left
));
779 } else if (!strcmp (*a
, "right")) {
781 g_strlcpy (whole_right
, *a
, sizeof (whole_right
));
783 g_strlcpy (whole_left
, *a
, sizeof (whole_left
));
784 g_strlcpy (whole_right
, *a
, sizeof (whole_right
));
788 } else if (!strcmp (args
[0], "context")) {
790 if (num_contexts
== -1) {
791 if (strcmp (*a
, "default")) { /* first context is the default */
795 c
= r
[0] = g_malloc0 (sizeof (struct context_rule
));
796 c
->left
= g_strdup (" ");
797 c
->right
= g_strdup (" ");
800 /* Terminate previous context. */
801 r
[num_contexts
- 1]->keyword
[num_words
] = NULL
;
802 c
= r
[num_contexts
] = g_malloc0 (sizeof (struct context_rule
));
803 if (!strcmp (*a
, "exclusive")) {
805 c
->between_delimiters
= 1;
808 if (!strcmp (*a
, "whole")) {
810 c
->whole_word_chars_left
= g_strdup (whole_left
);
811 c
->whole_word_chars_right
= g_strdup (whole_right
);
812 } else if (!strcmp (*a
, "wholeleft")) {
814 c
->whole_word_chars_left
= g_strdup (whole_left
);
815 } else if (!strcmp (*a
, "wholeright")) {
817 c
->whole_word_chars_right
= g_strdup (whole_right
);
820 if (!strcmp (*a
, "linestart")) {
822 c
->line_start_left
= 1;
825 c
->left
= g_strdup (*a
++);
827 if (!strcmp (*a
, "linestart")) {
829 c
->line_start_right
= 1;
832 c
->right
= g_strdup (*a
++);
833 c
->first_left
= *c
->left
;
834 c
->first_right
= *c
->right
;
836 c
->keyword
= g_malloc (alloc_words_per_context
* sizeof (struct key_word
*));
838 c
->keyword
[0] = g_malloc0 (sizeof (struct key_word
));
839 subst_defines (edit
->defines
, a
, &args
[1024]);
846 g_strlcpy (last_fg
, fg
? fg
: "", sizeof (last_fg
));
847 g_strlcpy (last_bg
, bg
? bg
: "", sizeof (last_bg
));
848 c
->keyword
[0]->color
= this_try_alloc_color_pair (fg
, bg
);
849 c
->keyword
[0]->keyword
= g_strdup (" ");
852 alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
;
853 if (++num_contexts
>= alloc_contexts
) {
854 struct context_rule
**tmp
;
856 alloc_contexts
+= 128;
857 tmp
= g_realloc (r
, alloc_contexts
* sizeof (struct context_rule
*));
860 } else if (!strcmp (args
[0], "spellcheck")) {
866 } else if (!strcmp (args
[0], "keyword")) {
872 k
= r
[num_contexts
- 1]->keyword
[num_words
] = g_malloc0 (sizeof (struct key_word
));
873 if (!strcmp (*a
, "whole")) {
875 k
->whole_word_chars_left
= g_strdup (whole_left
);
876 k
->whole_word_chars_right
= g_strdup (whole_right
);
877 } else if (!strcmp (*a
, "wholeleft")) {
879 k
->whole_word_chars_left
= g_strdup (whole_left
);
880 } else if (!strcmp (*a
, "wholeright")) {
882 k
->whole_word_chars_right
= g_strdup (whole_right
);
885 if (!strcmp (*a
, "linestart")) {
890 if (!strcmp (*a
, "whole")) {
893 k
->keyword
= g_strdup (*a
++);
894 k
->first
= *k
->keyword
;
895 subst_defines (edit
->defines
, a
, &args
[1024]);
906 k
->color
= this_try_alloc_color_pair (fg
, bg
);
909 if (++num_words
>= alloc_words_per_context
) {
910 struct key_word
**tmp
;
912 alloc_words_per_context
+= 1024;
914 if (alloc_words_per_context
> max_alloc_words_per_context
)
915 max_alloc_words_per_context
= alloc_words_per_context
;
917 tmp
= g_realloc (c
->keyword
, alloc_words_per_context
* sizeof (struct key_word
*));
920 } else if (*(args
[0]) == '#') {
921 /* do nothing for comment */
922 } else if (!strcmp (args
[0], "file")) {
924 } else if (!strcmp (args
[0], "define")) {
930 if ((argv
= g_tree_lookup (edit
->defines
, key
))) {
931 mc_defines_destroy (NULL
, argv
, NULL
);
933 key
= g_strdup (key
);
935 argv
= g_new (char *, argc
- 1);
936 g_tree_insert (edit
->defines
, key
, argv
);
938 *argv
++ = g_strdup (*a
++);
941 } else { /* anything else is an error */
950 /* Terminate context array. */
951 if (num_contexts
> 0) {
952 r
[num_contexts
- 1]->keyword
[num_words
] = NULL
;
953 r
[num_contexts
] = NULL
;
957 MC_PTR_FREE (edit
->rules
);
962 if (num_contexts
== -1) {
967 char *first_chars
, *p
;
969 first_chars
= g_malloc (max_alloc_words_per_context
+ 2);
971 for (i
= 0; edit
->rules
[i
]; i
++) {
975 for (j
= 1; c
->keyword
[j
]; j
++)
976 *p
++ = c
->keyword
[j
]->first
;
978 c
->keyword_first_chars
= g_strdup (first_chars
);
981 g_free (first_chars
);
987 void edit_free_syntax_rules (WEdit
* edit
)
994 destroy_defines (&edit
->defines
);
998 edit_get_rule (edit
, -1);
999 MC_PTR_FREE (edit
->syntax_type
);
1000 edit
->syntax_type
= 0;
1002 for (i
= 0; edit
->rules
[i
]; i
++) {
1003 if (edit
->rules
[i
]->keyword
) {
1004 for (j
= 0; edit
->rules
[i
]->keyword
[j
]; j
++) {
1005 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->keyword
);
1006 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->whole_word_chars_left
);
1007 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->whole_word_chars_right
);
1008 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]);
1011 MC_PTR_FREE (edit
->rules
[i
]->left
);
1012 MC_PTR_FREE (edit
->rules
[i
]->right
);
1013 MC_PTR_FREE (edit
->rules
[i
]->whole_word_chars_left
);
1014 MC_PTR_FREE (edit
->rules
[i
]->whole_word_chars_right
);
1015 MC_PTR_FREE (edit
->rules
[i
]->keyword
);
1016 MC_PTR_FREE (edit
->rules
[i
]->keyword_first_chars
);
1017 MC_PTR_FREE (edit
->rules
[i
]);
1020 while (edit
->syntax_marker
) {
1021 struct _syntax_marker
*s
= edit
->syntax_marker
->next
;
1022 MC_PTR_FREE (edit
->syntax_marker
);
1023 edit
->syntax_marker
= s
;
1026 MC_PTR_FREE (edit
->rules
);
1029 /* returns -1 on file error, line number on error in file syntax */
1031 edit_read_syntax_file (WEdit
* edit
, char ***pnames
, const char *syntax_file
,
1032 const char *editor_file
, const char *first_line
,
1037 char *args
[1024], *l
= 0;
1043 char **tmpnames
= NULL
;
1045 f
= fopen (syntax_file
, "r");
1047 lib_file
= concat_dir_and_file (mc_home
, "Syntax");
1048 f
= fopen (lib_file
, "r");
1058 if (!read_one_line (&l
, f
))
1060 (void)get_args (l
, args
, 1023); /* Final NULL */
1064 /* Looking for `include ...` lines before first `file ...` ones */
1065 if (!found
&& !strcmp (args
[0], "include")) {
1068 if (!args
[1] || !(g
= open_include_file (args
[1]))) {
1075 /* looking for `file ...' lines only */
1076 if (strcmp (args
[0], "file")) {
1081 /* must have two args or report error */
1082 if (!args
[1] || !args
[2]) {
1086 if (pnames
&& *pnames
) {
1088 /* 1: just collecting a list of names of rule sets */
1089 /* Reallocate the list if required */
1090 if (count
% NENTRIES
== 0) {
1091 if ((tmpnames
= (char**) g_realloc (*pnames
, (count
+ NENTRIES
1092 + 1) * sizeof (char*))) != NULL
)
1097 (*pnames
)[count
++] = g_strdup (args
[2]);
1098 (*pnames
)[count
] = NULL
;
1101 /* 2: rule set was explicitly specified by the caller */
1102 if (!strcmp (type
, args
[2]))
1104 } else if (editor_file
&& edit
) {
1106 /* 3: auto-detect rule set from regular expressions */
1108 q
= mc_search(args
[1], editor_file
, MC_SEARCH_T_REGEX
);
1109 /* does filename match arg 1 ? */
1110 if (!q
&& args
[3]) {
1111 /* does first line match arg 3 ? */
1112 q
= mc_search(args
[3], first_line
, MC_SEARCH_T_REGEX
);
1118 syntax_type
= args
[2];
1119 line_error
= edit_read_syntax_rules (edit
, g
? g
: f
, args
, 1023);
1121 if (!error_file_name
) /* an included file */
1122 result
= line
+ line_error
;
1124 result
= line_error
;
1126 MC_PTR_FREE (edit
->syntax_type
);
1127 edit
->syntax_type
= g_strdup (syntax_type
);
1128 /* if there are no rules then turn off syntax highlighting for speed */
1129 if (!g
&& !edit
->rules
[1])
1130 if (!edit
->rules
[0]->keyword
[1] && !edit
->rules
[0]->spelling
) {
1131 edit_free_syntax_rules (edit
);
1149 static char *get_first_editor_line (WEdit
* edit
)
1157 for (i
= 0; i
< 255; i
++) {
1158 s
[i
] = edit_get_byte (edit
, i
);
1169 * Load rules into edit struct. Either edit or *pnames must be NULL. If
1170 * edit is NULL, a list of types will be stored into names. If type is
1171 * NULL, then the type will be selected according to the filename.
1174 edit_load_syntax (WEdit
*edit
, char ***pnames
, const char *type
)
1179 if (option_auto_syntax
)
1182 edit_free_syntax_rules (edit
);
1184 if (!tty_use_colors ())
1187 if (!option_syntax_highlighting
&& (!pnames
|| !*pnames
))
1191 if (!edit
->filename
)
1193 if (!*edit
->filename
&& !type
)
1196 f
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
1197 r
= edit_read_syntax_file (edit
, pnames
, f
, edit
? edit
->filename
: 0,
1198 get_first_editor_line (edit
), type
);
1200 edit_free_syntax_rules (edit
);
1201 message (D_ERROR
, _(" Load syntax file "),
1202 _(" Cannot open file %s \n %s "), f
,
1203 unix_error_string (errno
));
1205 edit_free_syntax_rules (edit
);
1206 message (D_ERROR
, _(" Load syntax file "),
1207 _(" Error in file %s on line %d "),
1208 error_file_name
? error_file_name
: f
, r
);
1209 MC_PTR_FREE (error_file_name
);
1217 edit_get_syntax_type (const WEdit
*edit
)
1219 return edit
->syntax_type
;