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
28 * \author Mikhail Pobolovets
31 * Mispelled words are flushed from the syntax highlighting rules
32 * when they have been around longer than
33 * TRANSIENT_WORD_TIME_OUT seconds. At a cursor rate of 30
34 * chars per second and say 3 chars + a space per word, we can
35 * accumulate 450 words absolute max with a value of 60. This is
36 * below this limit of 1024 words in a context.
43 #include <sys/types.h>
51 #include "lib/global.h"
52 #include "lib/search.h" /* search engine */
54 #include "lib/strutil.h" /* utf string functions */
56 #include "src/main.h" /* mc_home */
57 #include "src/wtools.h" /* message() */
59 #include "edit-impl.h"
60 #include "edit-widget.h"
64 #define SYNTAX_MARKER_DENSITY 512
66 #define TRANSIENT_WORD_TIME_OUT 60
68 #define UNKNOWN_FORMAT "unknown"
70 #define MAX_WORDS_PER_CONTEXT 1024
71 #define MAX_CONTEXTS 128
73 #define RULE_ON_LEFT_BORDER 1
74 #define RULE_ON_RIGHT_BORDER 2
76 #define SYNTAX_TOKEN_STAR '\001'
77 #define SYNTAX_TOKEN_PLUS '\002'
78 #define SYNTAX_TOKEN_BRACKET '\003'
79 #define SYNTAX_TOKEN_BRACE '\004'
85 char *whole_word_chars_left
;
86 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
111 struct syntax_rule rule
;
112 struct _syntax_marker
*next
;
115 int option_syntax_highlighting
= 1;
116 int option_auto_syntax
= 1;
117 char *option_syntax_type
= NULL
;
120 mc_defines_destroy (gpointer key
, gpointer value
, gpointer data
)
122 char **values
= value
;
134 /* Completely destroys the defines tree */
136 destroy_defines (GTree
** defines
)
138 g_tree_traverse (*defines
, mc_defines_destroy
, G_POST_ORDER
, NULL
);
139 g_tree_destroy (*defines
);
143 /* Wrapper for case insensitive mode */
145 xx_tolower (WEdit
* edit
, int c
)
147 if (edit
->is_case_insensitive
)
155 subst_defines (GTree
* defines
, char **argv
, char **argv_end
)
160 while (*argv
&& argv
< argv_end
)
162 if ((t
= g_tree_lookup (defines
, *argv
)))
166 /* Count argv array members */
168 for (p
= &argv
[1]; *p
; p
++)
171 /* Count members of definition array */
174 p
= &argv
[count
+ argc
];
176 /* Buffer overflow or infinitive loop in define */
180 /* Move rest of argv after definition members */
182 *p
-- = argv
[argc
-- + 1];
184 /* Copy definition members to argv */
185 for (p
= argv
; *t
; *p
++ = *t
++);
192 compare_word_to_right (WEdit
* edit
, long i
, const char *text
,
193 const char *whole_left
, const char *whole_right
, int line_start
)
195 const unsigned char *p
, *q
;
200 c
= xx_tolower (edit
, edit_get_byte (edit
, i
- 1));
205 if (strchr (whole_left
, c
))
208 for (p
= (unsigned char *) text
, q
= p
+ str_term_width1 ((char *) p
); p
< q
; p
++, i
++)
212 case SYNTAX_TOKEN_STAR
:
217 c
= xx_tolower (edit
, edit_get_byte (edit
, i
));
220 if (!strchr (whole_right
, c
))
229 case SYNTAX_TOKEN_PLUS
:
235 c
= xx_tolower (edit
, edit_get_byte (edit
, i
));
239 if (*p
== *text
&& !p
[1]) /* handle eg '+' and @+@ keywords properly */
242 if (j
&& strchr ((char *) p
+ 1, c
)) /* c exists further down, so it will get matched later */
244 if (c
== '\n' || c
== '\t' || c
== ' ')
257 if (!strchr (whole_right
, c
))
272 case SYNTAX_TOKEN_BRACKET
:
279 c
= xx_tolower (edit
, edit_get_byte (edit
, i
));
280 for (j
= 0; p
[j
] != SYNTAX_TOKEN_BRACKET
&& p
[j
]; j
++)
285 ; /* dummy command */
288 while (*p
!= SYNTAX_TOKEN_BRACKET
&& p
<= q
)
295 case SYNTAX_TOKEN_BRACE
:
298 c
= xx_tolower (edit
, edit_get_byte (edit
, i
));
299 for (; *p
!= SYNTAX_TOKEN_BRACE
&& *p
; p
++)
304 while (*p
!= SYNTAX_TOKEN_BRACE
&& p
< q
)
308 if (*p
!= xx_tolower (edit
, edit_get_byte (edit
, i
)))
313 if (strchr (whole_right
, xx_tolower (edit
, edit_get_byte (edit
, i
))))
319 xx_strchr (WEdit
* edit
, const unsigned char *s
, int char_byte
)
321 while (*s
>= '\005' && xx_tolower (edit
, *s
) != char_byte
)
326 return (const char *) s
;
329 static struct syntax_rule
330 apply_rules_going_right (WEdit
* edit
, long i
, struct syntax_rule rule
)
332 struct context_rule
*r
;
333 int contextchanged
= 0, c
;
334 int found_right
= 0, found_left
= 0, keyword_foundleft
= 0, keyword_foundright
= 0;
337 struct syntax_rule _rule
= rule
;
339 if (!(c
= xx_tolower (edit
, edit_get_byte (edit
, i
))))
341 is_end
= (rule
.end
== (unsigned char) i
);
343 /* check to turn off a keyword */
346 if (edit_get_byte (edit
, i
- 1) == '\n')
351 keyword_foundleft
= 1;
355 /* check to turn off a context */
356 if (_rule
.context
&& !_rule
.keyword
)
359 r
= edit
->rules
[_rule
.context
];
360 if (r
->first_right
== c
&& !(rule
.border
& RULE_ON_RIGHT_BORDER
)
362 compare_word_to_right (edit
, i
, r
->right
, r
->whole_word_chars_left
,
363 r
->whole_word_chars_right
, r
->line_start_right
)) > 0)
367 _rule
.border
= RULE_ON_RIGHT_BORDER
;
368 if (r
->between_delimiters
)
371 else if (is_end
&& rule
.border
& RULE_ON_RIGHT_BORDER
)
374 /* always turn off a context at 4 */
377 if (!keyword_foundleft
)
380 else if (is_end
&& rule
.border
& RULE_ON_LEFT_BORDER
)
383 /* never turn off a context at 2 */
389 /* check to turn on a keyword */
394 p
= (r
= edit
->rules
[_rule
.context
])->keyword_first_chars
;
396 while (*(p
= xx_strchr (edit
, (unsigned char *) p
+ 1, c
)))
402 count
= p
- r
->keyword_first_chars
;
403 k
= r
->keyword
[count
];
404 e
= compare_word_to_right (edit
, i
, k
->keyword
, k
->whole_word_chars_left
,
405 k
->whole_word_chars_right
, k
->line_start
);
410 _rule
.keyword
= count
;
411 keyword_foundright
= 1;
416 /* check to turn on a context */
419 if (!found_left
&& is_end
)
421 if (rule
.border
& RULE_ON_RIGHT_BORDER
)
429 else if (rule
.border
& RULE_ON_LEFT_BORDER
)
431 r
= edit
->rules
[_rule
._context
];
433 if (r
->between_delimiters
)
436 _rule
.context
= _rule
._context
;
439 if (r
->first_right
== c
441 compare_word_to_right (edit
, i
, r
->right
, r
->whole_word_chars_left
,
442 r
->whole_word_chars_right
,
443 r
->line_start_right
)) >= end
)
447 _rule
.border
= RULE_ON_RIGHT_BORDER
;
457 struct context_rule
**rules
= edit
->rules
;
459 for (count
= 1; rules
[count
]; count
++)
462 if (r
->first_left
== c
)
466 e
= compare_word_to_right (edit
, i
, r
->left
, r
->whole_word_chars_left
,
467 r
->whole_word_chars_right
, r
->line_start_left
);
468 if (e
>= end
&& (!_rule
.keyword
|| keyword_foundright
))
472 _rule
.border
= RULE_ON_LEFT_BORDER
;
473 _rule
._context
= count
;
474 if (!r
->between_delimiters
)
477 _rule
.context
= count
;
487 /* check again to turn on a keyword if the context switched */
488 if (contextchanged
&& !_rule
.keyword
)
492 p
= (r
= edit
->rules
[_rule
.context
])->keyword_first_chars
;
493 while (*(p
= xx_strchr (edit
, (unsigned char *) p
+ 1, c
)))
499 count
= p
- r
->keyword_first_chars
;
500 k
= r
->keyword
[count
];
501 e
= compare_word_to_right (edit
, i
, k
->keyword
, k
->whole_word_chars_left
,
502 k
->whole_word_chars_right
, k
->line_start
);
506 _rule
.keyword
= count
;
514 static struct syntax_rule
515 edit_get_rule (WEdit
* edit
, long byte_index
)
519 if (byte_index
> edit
->last_get_rule
)
521 for (i
= edit
->last_get_rule
+ 1; i
<= byte_index
; i
++)
523 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
525 (edit
->syntax_marker
? edit
->syntax_marker
->offset
+
526 SYNTAX_MARKER_DENSITY
: SYNTAX_MARKER_DENSITY
))
528 struct _syntax_marker
*s
;
530 s
= edit
->syntax_marker
;
531 edit
->syntax_marker
= g_malloc (sizeof (struct _syntax_marker
));
532 edit
->syntax_marker
->next
= s
;
533 edit
->syntax_marker
->offset
= i
;
534 edit
->syntax_marker
->rule
= edit
->rule
;
538 else if (byte_index
< edit
->last_get_rule
)
540 struct _syntax_marker
*s
;
544 if (!edit
->syntax_marker
)
546 memset (&edit
->rule
, 0, sizeof (edit
->rule
));
547 for (i
= -1; i
<= byte_index
; i
++)
548 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
551 if (byte_index
>= edit
->syntax_marker
->offset
)
553 edit
->rule
= edit
->syntax_marker
->rule
;
554 for (i
= edit
->syntax_marker
->offset
+ 1; i
<= byte_index
; i
++)
555 edit
->rule
= apply_rules_going_right (edit
, i
, edit
->rule
);
558 s
= edit
->syntax_marker
->next
;
559 g_free (edit
->syntax_marker
);
560 edit
->syntax_marker
= s
;
563 edit
->last_get_rule
= byte_index
;
568 translate_rule_to_color (WEdit
* edit
, struct syntax_rule rule
, int *color
)
570 *color
= edit
->rules
[rule
.context
]->keyword
[rule
.keyword
]->color
;
574 edit_get_syntax_color (WEdit
* edit
, long byte_index
, int *color
)
576 if (!tty_use_colors ())
578 else if (edit
->rules
&& byte_index
< edit
->last_byte
&& option_syntax_highlighting
)
579 translate_rule_to_color (edit
, edit_get_rule (edit
, byte_index
), color
);
581 *color
= EDITOR_NORMAL_COLOR
;
586 Returns 0 on error/eof or a count of the number of bytes read
587 including the newline. Result must be free'd.
588 In case of an error, *line will not be modified.
591 read_one_line (char **line
, FILE * f
)
596 /* not reallocate string too often */
597 p
= g_string_sized_new (64);
616 /* handle all of \r\n, \r, \n correctly. */
629 g_string_append_c (p
, c
);
632 *line
= g_string_free (p
, FALSE
);
634 g_string_free (p
, TRUE
);
677 *p
= SYNTAX_TOKEN_BRACKET
;
681 *p
= SYNTAX_TOKEN_BRACE
;
692 *p
= SYNTAX_TOKEN_STAR
;
695 *p
= SYNTAX_TOKEN_PLUS
;
708 #define whiteness(x) ((x) == '\t' || (x) == '\n' || (x) == ' ')
711 get_args (char *l
, char **args
, int args_size
)
715 while (argc
< args_size
)
718 while (*p
&& whiteness (*p
))
722 for (l
= p
+ 1; *l
&& !whiteness (*l
); l
++);
725 args
[argc
++] = convert (p
);
727 args
[argc
] = (char *) NULL
;
732 #define break_a {result=line;break;}
733 #define check_a {if(!*a){result=line;break;}}
734 #define check_not_a {if(*a){result=line;break;}}
737 this_try_alloc_color_pair (const char *fg
, const char *bg
)
739 char f
[80], b
[80], *p
;
749 g_strlcpy (f
, fg
, sizeof (f
));
757 g_strlcpy (b
, bg
, sizeof (b
));
763 return tty_try_alloc_color_pair (fg
, bg
);
766 static char *error_file_name
= 0;
769 open_include_file (const char *filename
)
773 MC_PTR_FREE (error_file_name
);
774 error_file_name
= g_strdup (filename
);
775 if (*filename
== PATH_SEP
)
776 return fopen (filename
, "r");
778 g_free (error_file_name
);
779 error_file_name
= g_strconcat (home_dir
, PATH_SEP_STR EDIT_DIR PATH_SEP_STR
,
780 filename
, (char *) NULL
);
781 f
= fopen (error_file_name
, "r");
785 g_free (error_file_name
);
786 error_file_name
= g_strconcat (mc_home
, PATH_SEP_STR
, "syntax", PATH_SEP_STR
,
787 filename
, (char *) NULL
);
788 f
= fopen (error_file_name
, "r");
792 g_free (error_file_name
);
793 error_file_name
= g_strconcat (mc_home_alt
, PATH_SEP_STR
"syntax" PATH_SEP_STR
,
794 filename
, (char *) NULL
);
796 return fopen (error_file_name
, "r");
800 xx_lowerize_line (WEdit
* edit
, char *line
, size_t len
)
802 if (edit
->is_case_insensitive
)
805 for (i
= 0; i
< len
; ++i
)
806 line
[i
] = tolower (line
[i
]);
810 /* returns line number on error */
812 edit_read_syntax_rules (WEdit
* edit
, FILE * f
, char **args
, int args_size
)
816 char last_fg
[32] = "", last_bg
[32] = "";
817 char whole_right
[512];
818 char whole_left
[512];
820 int save_line
= 0, line
= 0;
821 struct context_rule
**r
, *c
= NULL
;
822 int num_words
= -1, num_contexts
= -1;
826 int alloc_contexts
= MAX_CONTEXTS
,
827 alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
,
828 max_alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
;
831 edit
->is_case_insensitive
= FALSE
;
833 strcpy (whole_left
, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
834 strcpy (whole_right
, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
836 r
= edit
->rules
= g_malloc0 (alloc_contexts
* sizeof (struct context_rule
*));
839 edit
->defines
= g_tree_new ((GCompareFunc
) strcmp
);
849 len
= read_one_line (&l
, f
);
857 line
= save_line
+ 1;
858 MC_PTR_FREE (error_file_name
);
860 len
= read_one_line (&l
, f
);
864 xx_lowerize_line (edit
, l
, len
);
873 xx_lowerize_line (edit
, l
, len
);
875 argc
= get_args (l
, args
, args_size
);
881 else if (!strcmp (args
[0], "include"))
889 f
= open_include_file (args
[1]);
892 MC_PTR_FREE (error_file_name
);
899 else if (!strcmp (args
[0], "caseinsensitive"))
901 edit
->is_case_insensitive
= TRUE
;
903 else if (!strcmp (args
[0], "wholechars"))
906 if (!strcmp (*a
, "left"))
909 g_strlcpy (whole_left
, *a
, sizeof (whole_left
));
911 else if (!strcmp (*a
, "right"))
914 g_strlcpy (whole_right
, *a
, sizeof (whole_right
));
918 g_strlcpy (whole_left
, *a
, sizeof (whole_left
));
919 g_strlcpy (whole_right
, *a
, sizeof (whole_right
));
924 else if (!strcmp (args
[0], "context"))
927 if (num_contexts
== -1)
929 if (strcmp (*a
, "default"))
930 { /* first context is the default */
934 c
= r
[0] = g_malloc0 (sizeof (struct context_rule
));
935 c
->left
= g_strdup (" ");
936 c
->right
= g_strdup (" ");
941 /* Terminate previous context. */
942 r
[num_contexts
- 1]->keyword
[num_words
] = NULL
;
943 c
= r
[num_contexts
] = g_malloc0 (sizeof (struct context_rule
));
944 if (!strcmp (*a
, "exclusive"))
947 c
->between_delimiters
= 1;
950 if (!strcmp (*a
, "whole"))
953 c
->whole_word_chars_left
= g_strdup (whole_left
);
954 c
->whole_word_chars_right
= g_strdup (whole_right
);
956 else if (!strcmp (*a
, "wholeleft"))
959 c
->whole_word_chars_left
= g_strdup (whole_left
);
961 else if (!strcmp (*a
, "wholeright"))
964 c
->whole_word_chars_right
= g_strdup (whole_right
);
967 if (!strcmp (*a
, "linestart"))
970 c
->line_start_left
= 1;
973 c
->left
= g_strdup (*a
++);
975 if (!strcmp (*a
, "linestart"))
978 c
->line_start_right
= 1;
981 c
->right
= g_strdup (*a
++);
982 c
->first_left
= *c
->left
;
983 c
->first_right
= *c
->right
;
985 c
->keyword
= g_malloc (alloc_words_per_context
* sizeof (struct key_word
*));
987 c
->keyword
[0] = g_malloc0 (sizeof (struct key_word
));
988 subst_defines (edit
->defines
, a
, &args
[1024]);
995 g_strlcpy (last_fg
, fg
? fg
: "", sizeof (last_fg
));
996 g_strlcpy (last_bg
, bg
? bg
: "", sizeof (last_bg
));
997 c
->keyword
[0]->color
= this_try_alloc_color_pair (fg
, bg
);
998 c
->keyword
[0]->keyword
= g_strdup (" ");
1001 alloc_words_per_context
= MAX_WORDS_PER_CONTEXT
;
1002 if (++num_contexts
>= alloc_contexts
)
1004 struct context_rule
**tmp
;
1006 alloc_contexts
+= 128;
1007 tmp
= g_realloc (r
, alloc_contexts
* sizeof (struct context_rule
*));
1011 else if (!strcmp (args
[0], "spellcheck"))
1020 else if (!strcmp (args
[0], "keyword"))
1024 if (num_words
== -1)
1027 k
= r
[num_contexts
- 1]->keyword
[num_words
] = g_malloc0 (sizeof (struct key_word
));
1028 if (!strcmp (*a
, "whole"))
1031 k
->whole_word_chars_left
= g_strdup (whole_left
);
1032 k
->whole_word_chars_right
= g_strdup (whole_right
);
1034 else if (!strcmp (*a
, "wholeleft"))
1037 k
->whole_word_chars_left
= g_strdup (whole_left
);
1039 else if (!strcmp (*a
, "wholeright"))
1042 k
->whole_word_chars_right
= g_strdup (whole_right
);
1045 if (!strcmp (*a
, "linestart"))
1051 if (!strcmp (*a
, "whole"))
1055 k
->keyword
= g_strdup (*a
++);
1056 k
->first
= *k
->keyword
;
1057 subst_defines (edit
->defines
, a
, &args
[1024]);
1068 k
->color
= this_try_alloc_color_pair (fg
, bg
);
1071 if (++num_words
>= alloc_words_per_context
)
1073 struct key_word
**tmp
;
1075 alloc_words_per_context
+= 1024;
1077 if (alloc_words_per_context
> max_alloc_words_per_context
)
1078 max_alloc_words_per_context
= alloc_words_per_context
;
1080 tmp
= g_realloc (c
->keyword
, alloc_words_per_context
* sizeof (struct key_word
*));
1084 else if (*(args
[0]) == '#')
1086 /* do nothing for comment */
1088 else if (!strcmp (args
[0], "file"))
1092 else if (!strcmp (args
[0], "define"))
1099 if ((argv
= g_tree_lookup (edit
->defines
, key
)))
1101 mc_defines_destroy (NULL
, argv
, NULL
);
1105 key
= g_strdup (key
);
1107 argv
= g_new (char *, argc
- 1);
1108 g_tree_insert (edit
->defines
, key
, argv
);
1111 *argv
++ = g_strdup (*a
++);
1116 { /* anything else is an error */
1125 /* Terminate context array. */
1126 if (num_contexts
> 0)
1128 r
[num_contexts
- 1]->keyword
[num_words
] = NULL
;
1129 r
[num_contexts
] = NULL
;
1132 if (!edit
->rules
[0])
1133 MC_PTR_FREE (edit
->rules
);
1138 if (num_contexts
== -1)
1144 char *first_chars
, *p
;
1146 first_chars
= g_malloc0 (max_alloc_words_per_context
+ 2);
1148 for (i
= 0; edit
->rules
[i
]; i
++)
1153 for (j
= 1; c
->keyword
[j
]; j
++)
1154 *p
++ = c
->keyword
[j
]->first
;
1156 c
->keyword_first_chars
= g_strdup (first_chars
);
1159 g_free (first_chars
);
1166 edit_free_syntax_rules (WEdit
* edit
)
1173 destroy_defines (&edit
->defines
);
1177 edit_get_rule (edit
, -1);
1178 MC_PTR_FREE (edit
->syntax_type
);
1180 for (i
= 0; edit
->rules
[i
]; i
++)
1182 if (edit
->rules
[i
]->keyword
)
1184 for (j
= 0; edit
->rules
[i
]->keyword
[j
]; j
++)
1186 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->keyword
);
1187 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->whole_word_chars_left
);
1188 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]->whole_word_chars_right
);
1189 MC_PTR_FREE (edit
->rules
[i
]->keyword
[j
]);
1192 MC_PTR_FREE (edit
->rules
[i
]->left
);
1193 MC_PTR_FREE (edit
->rules
[i
]->right
);
1194 MC_PTR_FREE (edit
->rules
[i
]->whole_word_chars_left
);
1195 MC_PTR_FREE (edit
->rules
[i
]->whole_word_chars_right
);
1196 MC_PTR_FREE (edit
->rules
[i
]->keyword
);
1197 MC_PTR_FREE (edit
->rules
[i
]->keyword_first_chars
);
1198 MC_PTR_FREE (edit
->rules
[i
]);
1201 while (edit
->syntax_marker
)
1203 struct _syntax_marker
*s
= edit
->syntax_marker
->next
;
1204 g_free (edit
->syntax_marker
);
1205 edit
->syntax_marker
= s
;
1208 MC_PTR_FREE (edit
->rules
);
1209 tty_color_free_all_tmp ();
1212 /* returns -1 on file error, line number on error in file syntax */
1214 edit_read_syntax_file (WEdit
* edit
, char ***pnames
, const char *syntax_file
,
1215 const char *editor_file
, const char *first_line
, const char *type
)
1219 char *args
[1024], *l
= NULL
;
1225 char **tmpnames
= NULL
;
1227 f
= fopen (syntax_file
, "r");
1230 lib_file
= concat_dir_and_file (mc_home
, "Syntax");
1231 f
= fopen (lib_file
, "r");
1242 if (read_one_line (&l
, f
) == 0)
1244 (void) get_args (l
, args
, 1023); /* Final NULL */
1248 /* Looking for `include ...` lines before first `file ...` ones */
1249 if (!found
&& !strcmp (args
[0], "include"))
1253 if (!args
[1] || !(g
= open_include_file (args
[1])))
1261 /* looking for `file ...' lines only */
1262 if (strcmp (args
[0], "file"))
1268 /* must have two args or report error */
1269 if (!args
[1] || !args
[2])
1274 if (pnames
&& *pnames
)
1277 /* 1: just collecting a list of names of rule sets */
1278 /* Reallocate the list if required */
1279 if (count
% NENTRIES
== 0)
1282 (char **) g_try_realloc (*pnames
, (count
+ NENTRIES
+ 1) * sizeof (char *));
1283 if (tmpnames
== NULL
)
1287 (*pnames
)[count
++] = g_strdup (args
[2]);
1288 (*pnames
)[count
] = NULL
;
1293 /* 2: rule set was explicitly specified by the caller */
1294 if (!strcmp (type
, args
[2]))
1297 else if (editor_file
&& edit
)
1300 /* 3: auto-detect rule set from regular expressions */
1302 q
= mc_search (args
[1], editor_file
, MC_SEARCH_T_REGEX
);
1303 /* does filename match arg 1 ? */
1306 /* does first line match arg 3 ? */
1307 q
= mc_search (args
[3], first_line
, MC_SEARCH_T_REGEX
);
1314 syntax_type
= args
[2];
1315 line_error
= edit_read_syntax_rules (edit
, g
? g
: f
, args
, 1023);
1318 if (!error_file_name
) /* an included file */
1319 result
= line
+ line_error
;
1321 result
= line_error
;
1325 MC_PTR_FREE (edit
->syntax_type
);
1326 edit
->syntax_type
= g_strdup (syntax_type
);
1327 /* if there are no rules then turn off syntax highlighting for speed */
1328 if (!g
&& !edit
->rules
[1])
1329 if (!edit
->rules
[0]->keyword
[1] && !edit
->rules
[0]->spelling
)
1331 edit_free_syntax_rules (edit
);
1353 get_first_editor_line (WEdit
* edit
)
1362 for (i
= 0; i
< sizeof (s
) - 1; i
++)
1364 s
[i
] = edit_get_byte (edit
, i
);
1371 s
[sizeof (s
) - 1] = '\0';
1376 * Load rules into edit struct. Either edit or *pnames must be NULL. If
1377 * edit is NULL, a list of types will be stored into names. If type is
1378 * NULL, then the type will be selected according to the filename.
1381 edit_load_syntax (WEdit
* edit
, char ***pnames
, const char *type
)
1386 if (option_auto_syntax
)
1389 edit_free_syntax_rules (edit
);
1391 if (!tty_use_colors ())
1394 if (!option_syntax_highlighting
&& (!pnames
|| !*pnames
))
1399 if (!edit
->filename
)
1401 if (!*edit
->filename
&& !type
)
1404 f
= concat_dir_and_file (home_dir
, EDIT_SYNTAX_FILE
);
1405 r
= edit_read_syntax_file (edit
, pnames
, f
, edit
? edit
->filename
: 0,
1406 get_first_editor_line (edit
), type
);
1409 edit_free_syntax_rules (edit
);
1410 message (D_ERROR
, _(" Load syntax file "),
1411 _(" Cannot open file %s \n %s "), f
, unix_error_string (errno
));
1415 edit_free_syntax_rules (edit
);
1416 message (D_ERROR
, _(" Load syntax file "),
1417 _(" Error in file %s on line %d "), error_file_name
? error_file_name
: f
, r
);
1418 MC_PTR_FREE (error_file_name
);
1428 edit_get_syntax_type (const WEdit
* edit
)
1430 return edit
->syntax_type
;