63 |
#include "interface.h" |
#include "interface.h" |
64 |
#include "undoredo.h" |
#include "undoredo.h" |
65 |
#include "conf.h" |
#include "conf.h" |
66 |
|
#include "oldsyhi.h" |
67 |
|
|
68 |
extern t_settings Settings; |
extern t_settings Settings; |
69 |
|
|
534 |
} |
} |
535 |
|
|
536 |
|
|
|
|
|
|
/* preconditions: iter points to possible start of interesting word |
|
|
postconditions: end is set to the end of the word in the buffer if it was found. |
|
|
if word found, returns TRUE, else FALSE*/ |
|
|
inline gboolean starts_string (gchar *text, gint i, gchar *word, gint *end) |
|
|
{ |
|
|
gunichar ch; |
|
|
gunichar k; |
|
|
gint j = 0; |
|
|
|
|
|
ch = text[i]; |
|
|
k = word[j]; |
|
|
while (ch && k) |
|
|
{ |
|
|
if (ch != k) |
|
|
{ |
|
|
return FALSE; |
|
|
} |
|
|
|
|
|
i++; |
|
|
ch = text[i]; |
|
|
j++; |
|
|
k = word[j]; |
|
|
} |
|
|
|
|
|
if (!ch && k) |
|
|
{ |
|
|
return FALSE; |
|
|
} |
|
|
|
|
|
if (end) |
|
|
*end = i; |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* returns color index of match, or -1 if none */ |
|
|
inline gint is_matching_keyword (gint Lg, const gchar *str) |
|
|
{ |
|
|
gint rv = -1; |
|
|
gpointer val; |
|
|
|
|
|
val = g_hash_table_lookup (Prefs.L[Lg].Hash, str); |
|
|
|
|
|
if (val) |
|
|
return GPOINTER_TO_INT (val) - 1; |
|
|
else |
|
|
return -1; |
|
|
|
|
|
return rv; |
|
|
} |
|
|
|
|
|
|
|
|
inline void refresh_markers (GtkTextBuffer *Buffer) |
|
|
{ |
|
|
gint CurrentPage; |
|
|
gint Lg; |
|
|
GList *markers, *tmp; |
|
|
GtkTextIter start, end; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
Lg = FPROPS(CurrentPage, WidgetInfo.Lg); |
|
|
markers = FPROPS(CurrentPage, WidgetInfo.markers); |
|
|
|
|
|
/* get rid of old tags */ |
|
|
gtk_text_buffer_get_bounds (FPROPS(CurrentPage, Buffer), &start, &end); |
|
|
gtk_text_buffer_remove_tag (FPROPS(CurrentPage, Buffer), |
|
|
FPROPS(CurrentPage, WidgetInfo.string0_tag), &start, &end); |
|
|
gtk_text_buffer_remove_tag (FPROPS(CurrentPage, Buffer), |
|
|
FPROPS(CurrentPage, WidgetInfo.string1_tag), &start, &end); |
|
|
gtk_text_buffer_remove_tag (FPROPS(CurrentPage, Buffer), |
|
|
FPROPS(CurrentPage, WidgetInfo.comment_tag), &start, &end); |
|
|
gtk_text_buffer_remove_tag (FPROPS(CurrentPage, Buffer), |
|
|
FPROPS(CurrentPage, WidgetInfo.comment_alt_tag), &start, &end); |
|
|
|
|
|
/* go through list of markers, applying tags */ |
|
|
tmp = markers; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m; |
|
|
gunichar ch; |
|
|
gboolean found = FALSE; |
|
|
|
|
|
m = (t_marker *) tmp->data; |
|
|
|
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &start, m->mark); |
|
|
|
|
|
switch (m->type) |
|
|
{ |
|
|
case TypeString0: |
|
|
/* find next string0 */ |
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
if (m2->type == TypeString0) |
|
|
{ |
|
|
found = TRUE; |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &end, m2->mark); |
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
if (!found) |
|
|
{ |
|
|
gtk_text_buffer_get_end_iter (Buffer, &end); |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.string0_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
|
|
|
case TypeString1: |
|
|
/* find next string1 */ |
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
if (m2->type == TypeString1) |
|
|
{ |
|
|
found = TRUE; |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &end, m2->mark); |
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
if (!found) |
|
|
{ |
|
|
gtk_text_buffer_get_end_iter (Buffer, &end); |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.string1_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
|
|
|
case TypeBlockCommentOn: |
|
|
/* find next BlockCommentOff */ |
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
if (m2->type == TypeBlockCommentOff) |
|
|
{ |
|
|
found = TRUE; |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &end, m2->mark); |
|
|
gtk_text_iter_forward_chars (&end, strlen (Prefs.L[Lg].BlockCommentOff)); |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
if (!found) |
|
|
{ |
|
|
gtk_text_buffer_get_end_iter (Buffer, &end); |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.comment_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
|
|
|
case TypeBlockCommentOnAlt: |
|
|
/* find next BlockCommentOffAlt*/ |
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
if (m2->type == TypeBlockCommentOffAlt) |
|
|
{ |
|
|
found = TRUE; |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &end, m2->mark); |
|
|
gtk_text_iter_forward_chars (&end, strlen (Prefs.L[Lg].BlockCommentOffAlt)); |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
if (!found) |
|
|
{ |
|
|
gtk_text_buffer_get_end_iter (Buffer, &end); |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.comment_alt_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
|
|
|
case TypeLineComment: |
|
|
/* find next end of line */ |
|
|
end = start; |
|
|
do |
|
|
{ |
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
ch = gtk_text_iter_get_char (&end); |
|
|
} |
|
|
while (ch && (ch != '\n' && ch != '\r')); |
|
|
|
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
|
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
GtkTextIter iter; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &iter, m2->mark); |
|
|
|
|
|
if (gtk_text_iter_compare (&iter, &end) >= 0) |
|
|
{ |
|
|
// back up |
|
|
tmp = tmp->prev; |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.comment_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
|
|
|
case TypeLineCommentAlt: |
|
|
/* find next end of line */ |
|
|
end = start; |
|
|
do |
|
|
{ |
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
ch = gtk_text_iter_get_char (&end); |
|
|
} |
|
|
while (ch && (ch != '\n' && ch != '\r')); |
|
|
|
|
|
gtk_text_iter_forward_cursor_position (&end); |
|
|
|
|
|
tmp = tmp->next; |
|
|
while (tmp) |
|
|
{ |
|
|
t_marker *m2; |
|
|
GtkTextIter iter; |
|
|
|
|
|
m2 = (t_marker *) tmp->data; |
|
|
|
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &iter, m2->mark); |
|
|
|
|
|
if (gtk_text_iter_compare (&iter, &end) >= 0) |
|
|
{ |
|
|
// back up |
|
|
tmp = tmp->prev; |
|
|
break; |
|
|
} |
|
|
|
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
gtk_text_buffer_apply_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.comment_alt_tag), |
|
|
&start, &end); |
|
|
break; |
|
|
} |
|
|
|
|
|
if (tmp) |
|
|
tmp = tmp->next; |
|
|
} |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
void search_for_keyword_correctly (gint page, GtkTextBuffer *Buffer, gchar *text, gint *i, gint offset, gint Lg) |
|
|
{ |
|
|
/* search for a keyword */ |
|
|
gint tmp; |
|
|
gint next, prev, edge, possible = -1; |
|
|
gboolean last_was_delimiter; |
|
|
int color = -1; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
next = *i; |
|
|
tmp = text[*i]; |
|
|
|
|
|
/* get to first useless char */ |
|
|
while (tmp && (Prefs.L[Lg].KeywordStatus[(int) tmp] & 1)) |
|
|
{ |
|
|
next++; |
|
|
tmp = text[next]; |
|
|
} |
|
|
|
|
|
edge = prev = next; |
|
|
prev++; |
|
|
|
|
|
last_was_delimiter = FALSE; |
|
|
do |
|
|
{ |
|
|
if ((last_was_delimiter || Prefs.L[Lg].IsADelimiter[tmp]) && |
|
|
Prefs.L[Lg].KeywordStatus[tmp] & 4) /* ends a keyword */ |
|
|
{ |
|
|
gchar *stuff; |
|
|
|
|
|
/* let's get text including this char */ |
|
|
stuff = g_strndup (&text[*i], prev - *i); |
|
|
color = is_matching_keyword (Lg, stuff); |
|
|
g_free (stuff); |
|
|
|
|
|
if (color >= 0) |
|
|
{ |
|
|
edge = prev; |
|
|
/* we found our match */ |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
if (Prefs.L[Lg].IsADelimiter[tmp]) |
|
|
{ |
|
|
if (next != *i && |
|
|
((Prefs.L[Lg].KeywordStatus[tmp] & 2) || |
|
|
(Prefs.L[Lg].KeywordStatus[tmp] & 8))) |
|
|
{ |
|
|
/* this starts some keywords, so we should come back to it |
|
|
if we can't find a match */ |
|
|
possible = next; |
|
|
} |
|
|
|
|
|
last_was_delimiter = TRUE; |
|
|
} |
|
|
else |
|
|
{ |
|
|
last_was_delimiter = FALSE; |
|
|
} |
|
|
|
|
|
prev = next; |
|
|
next--; |
|
|
tmp = text[next]; |
|
|
} |
|
|
while (*i <= next); |
|
|
|
|
|
if (color != -1) |
|
|
{ |
|
|
GtkTextIter start, end; |
|
|
|
|
|
/* apply tag */ |
|
|
gtk_text_buffer_get_iter_at_offset (Buffer, &start, offset + *i); |
|
|
gtk_text_buffer_get_iter_at_offset (Buffer, &end, offset + edge); |
|
|
gtk_text_buffer_apply_tag (Buffer, |
|
|
FPROPS (page, WidgetInfo.keyword_tags[color]), &start, &end); |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (possible >= 0) |
|
|
{ |
|
|
edge = possible; |
|
|
} |
|
|
} |
|
|
|
|
|
*i = edge; |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
|
|
|
inline void search_for_keyword_fastly (gint page, GtkTextBuffer *Buffer, gchar *text, gint *i, gint offset, gint Lg) |
|
|
{ |
|
|
/* search for a keyword */ |
|
|
gint tmp, next; |
|
|
gboolean possibly_a_keyword = TRUE; |
|
|
int color = -1; |
|
|
gchar *key; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
next = *i; |
|
|
tmp = text[next]; |
|
|
|
|
|
if (Prefs.L[Lg].IsADelimiter[tmp]) |
|
|
{ |
|
|
if (Prefs.L[Lg].KeywordStatus[tmp] & 2) |
|
|
{ |
|
|
/* check if this delimiter is itself a keyword. This is a work-around |
|
|
for coloring operators */ |
|
|
next++; |
|
|
} |
|
|
else |
|
|
{ |
|
|
*i += 1; |
|
|
return; |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* get to first useless char or delimiter */ |
|
|
while (tmp && !Prefs.L[Lg].IsADelimiter[tmp]) |
|
|
{ |
|
|
if (!Prefs.L[Lg].KeywordStatus[tmp] & 1) |
|
|
{ |
|
|
/* if we hit something that isn't in a keyword before we hit a delimiter, |
|
|
note it and stop */ |
|
|
possibly_a_keyword = FALSE; |
|
|
} |
|
|
|
|
|
next++; |
|
|
tmp = text[next]; |
|
|
} |
|
|
} |
|
|
|
|
|
if (possibly_a_keyword) |
|
|
{ |
|
|
key = g_strndup (&text[*i], next - *i); |
|
|
color = is_matching_keyword (Lg, key); |
|
|
g_free (key); |
|
|
|
|
|
if (color != -1) |
|
|
{ |
|
|
GtkTextIter start, end; |
|
|
|
|
|
/* apply tag */ |
|
|
gtk_text_buffer_get_iter_at_offset (Buffer, &start, offset + *i); |
|
|
gtk_text_buffer_get_iter_at_offset (Buffer, &end, offset + next); |
|
|
gtk_text_buffer_apply_tag (Buffer, |
|
|
FPROPS (page, WidgetInfo.keyword_tags[color]), &start, &end); |
|
|
} |
|
|
} |
|
|
|
|
|
*i = next; |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
void search_for_keyword (gint page, GtkTextBuffer *Buffer, gchar *text, gint *i, gint offset, gint Lg) |
|
|
{ |
|
|
/* the difference between searching fast or correct is that the fast search assumes no delimiters |
|
|
appear in keywords. Correct checks for this and also prefers the longest applicable match. |
|
|
|
|
|
HTML is the only big language right now that uses this, so we only do correct thing for HTML. |
|
|
*/ |
|
|
|
|
|
if (Prefs.L[Lg].IsHTML) |
|
|
{ |
|
|
search_for_keyword_correctly (page, Buffer, text, i, offset, Lg); |
|
|
} |
|
|
else |
|
|
{ |
|
|
search_for_keyword_fastly (page, Buffer, text, i, offset, Lg); |
|
|
} |
|
|
} |
|
|
|
|
|
void markup_syhi_range (GtkTextBuffer *Buffer, GtkTextIter start, GtkTextIter end) |
|
|
{ |
|
|
int CurrentPage; |
|
|
gint Lg, position, i, j; |
|
|
GList *markers, *tmp, *prev; |
|
|
gchar *text; |
|
|
GtkTextIter textiter; |
|
|
gboolean prev_set; |
|
|
gboolean last_was_escape; |
|
|
gboolean restart = FALSE; |
|
|
gboolean markers_changed = FALSE; |
|
|
GTimer *timer = g_timer_new (); |
|
|
|
|
|
START_FCN |
|
|
|
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
Lg = FPROPS(CurrentPage, WidgetInfo.Lg); |
|
|
markers = FPROPS(CurrentPage, WidgetInfo.markers); |
|
|
|
|
|
text = gtk_text_iter_get_text (&start, &end); |
|
|
i = 0; |
|
|
|
|
|
#ifdef DEBUG_SYHI |
|
|
g_print(__FILE__": %s(): Language of file modified: /L%i \"%s\"\n", __func__, |
|
|
Lg + 1, Prefs.L[Lg].Description); |
|
|
{ |
|
|
gchar *s; |
|
|
s = gtk_text_iter_get_text (&start, &end); |
|
|
g_print(__FILE__": Examining string \"%s\"\n", s); |
|
|
g_free (s); |
|
|
} |
|
|
#endif |
|
|
|
|
|
/* find place right before where we are in marker list, |
|
|
and delete all the markers between start and end*/ |
|
|
tmp = markers; |
|
|
prev = NULL; |
|
|
prev_set = FALSE; |
|
|
position = 0; |
|
|
while (tmp) |
|
|
{ |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &textiter, ((t_marker *) tmp->data)->mark); |
|
|
|
|
|
if (!prev && gtk_text_iter_compare (&textiter, &start) >= 0) |
|
|
{ |
|
|
/* save previous marker */ |
|
|
prev = tmp->prev; |
|
|
prev_set = TRUE; |
|
|
} |
|
|
|
|
|
if (prev_set && gtk_text_iter_compare (&textiter, &end) <= 0) |
|
|
{ |
|
|
GList *deleted; |
|
|
gtk_text_buffer_delete_mark (Buffer, ((t_marker *) tmp->data)->mark); |
|
|
deleted = tmp; |
|
|
tmp = tmp->next; |
|
|
markers = g_list_remove_link (markers, deleted); |
|
|
g_free (deleted->data); |
|
|
g_list_free_1 (deleted); |
|
|
|
|
|
markers_changed = TRUE; |
|
|
} |
|
|
else if (!prev_set) |
|
|
{ |
|
|
tmp = tmp->next; |
|
|
position ++; |
|
|
} |
|
|
else |
|
|
break; |
|
|
} |
|
|
|
|
|
if (prev) |
|
|
position = g_list_position (markers, prev) + 1; |
|
|
else if (!markers) |
|
|
position = 0; |
|
|
|
|
|
gtk_text_buffer_remove_tag (Buffer, FPROPS(CurrentPage, WidgetInfo.number_tag), &start, &end); |
|
|
for (j = 0; j < MAX_COL; j++) |
|
|
{ |
|
|
gtk_text_buffer_remove_tag (Buffer, |
|
|
FPROPS(CurrentPage, WidgetInfo.keyword_tags[j]), &start, &end); |
|
|
} |
|
|
|
|
|
last_was_escape = FALSE; |
|
|
g_timer_start (timer); |
|
|
while (text[i] && !restart) |
|
|
{ |
|
|
gint ch; |
|
|
gint word_end; |
|
|
t_marker *m; |
|
|
gboolean scan = FALSE; |
|
|
|
|
|
ch = text[i]; |
|
|
if (Prefs.L[Lg].EscapeChar == ch) |
|
|
{ |
|
|
i++; |
|
|
|
|
|
if (!last_was_escape) |
|
|
{ |
|
|
last_was_escape = TRUE; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
else if (Prefs.L[Lg].KeywordStatus[ch] & 8) |
|
|
{ |
|
|
if (Prefs.L[Lg].HaveString && Prefs.L[Lg].StringChar0 != '\0' && |
|
|
Prefs.L[Lg].StringChar0 == ch) |
|
|
{ |
|
|
if (last_was_escape) |
|
|
{ |
|
|
i++; |
|
|
} |
|
|
else |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeString0; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i++; |
|
|
} |
|
|
} |
|
|
else if (Prefs.L[Lg].HaveString && Prefs.L[Lg].StringChar1 != '\0' && |
|
|
Prefs.L[Lg].StringChar1 == ch) |
|
|
{ |
|
|
if (last_was_escape) |
|
|
{ |
|
|
i++; |
|
|
} |
|
|
else |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeString1; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i++; |
|
|
} |
|
|
} |
|
|
else if (Prefs.L[Lg].LineComment != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].LineComment, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeLineComment; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else if (Prefs.L[Lg].LineCommentAlt != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].LineCommentAlt, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeLineCommentAlt; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else if (Prefs.L[Lg].BlockCommentOn != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].BlockCommentOn, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeBlockCommentOn; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else if (Prefs.L[Lg].BlockCommentOnAlt != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].BlockCommentOnAlt, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeBlockCommentOnAlt; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else if (Prefs.L[Lg].BlockCommentOff != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].BlockCommentOff, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeBlockCommentOff; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else if (Prefs.L[Lg].BlockCommentOffAlt != NULL && |
|
|
starts_string (text, i, Prefs.L[Lg].BlockCommentOffAlt, &word_end)) |
|
|
{ |
|
|
GtkTextIter iter = start; |
|
|
|
|
|
m = g_malloc (sizeof (t_marker)); |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
m->mark = gtk_text_buffer_create_mark (Buffer, NULL, &iter, FALSE); |
|
|
m->type = TypeBlockCommentOffAlt; |
|
|
markers = g_list_insert (markers, m, position++); |
|
|
markers_changed = TRUE; |
|
|
|
|
|
i = word_end; |
|
|
} |
|
|
else |
|
|
{ |
|
|
scan = TRUE; |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
scan = TRUE; |
|
|
} |
|
|
|
|
|
last_was_escape = FALSE; |
|
|
|
|
|
if (!scan) |
|
|
continue; |
|
|
|
|
|
if (g_ascii_isdigit (ch)) |
|
|
{ |
|
|
GtkTextIter iter = start, iter2 = start; |
|
|
|
|
|
gtk_text_iter_forward_chars (&iter, i); |
|
|
|
|
|
/* go forward to next delimiter */ |
|
|
do |
|
|
{ |
|
|
i++; |
|
|
ch = text[i]; |
|
|
} |
|
|
while (ch && (ch > 255 || !Prefs.L[Lg].IsADelimiter[ch])); |
|
|
|
|
|
/* apply tag */ |
|
|
gtk_text_iter_forward_chars (&iter2, i); |
|
|
gtk_text_buffer_apply_tag (Buffer, |
|
|
FPROPS (CurrentPage, WidgetInfo.number_tag), &iter, &iter2); |
|
|
} |
|
|
else if (!(Prefs.L[Lg].KeywordStatus[ch] & 0x2)) |
|
|
{ |
|
|
/* this character does *not* start a keyword. */ |
|
|
|
|
|
if (Prefs.L[Lg].IsADelimiter[ch]) |
|
|
{ |
|
|
i++; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* go forward to next delimiter */ |
|
|
do |
|
|
{ |
|
|
i++; |
|
|
ch = text[i]; |
|
|
} |
|
|
while (ch && (ch > 255 || !Prefs.L[Lg].IsADelimiter[ch])); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
search_for_keyword (CurrentPage, Buffer, text, &i, gtk_text_iter_get_offset (&start), Lg); |
|
|
} |
|
|
|
|
|
/* this block is needed because if syhi is taking a long time, we want to update the gui -- |
|
|
to make it feel like it is running at reasonable speed */ |
|
|
#if 1 |
|
|
if (g_timer_elapsed (timer, NULL) >= 0.5) /* if half a second has elapsed, */ |
|
|
{ |
|
|
GtkTextMark *start_mark, *end_mark; |
|
|
|
|
|
FPROPS(CurrentPage, WidgetInfo.markers) = markers; |
|
|
if (markers_changed) |
|
|
{ |
|
|
refresh_markers (Buffer); |
|
|
} |
|
|
|
|
|
FPROPS(CurrentPage, WidgetInfo.syhi_ran) = FALSE; |
|
|
start_mark = gtk_text_buffer_create_mark (Buffer, NULL, |
|
|
&start, TRUE); |
|
|
end_mark = gtk_text_buffer_create_mark (Buffer, NULL, |
|
|
&end, TRUE); |
|
|
|
|
|
gtk_main_iteration_do (FALSE); |
|
|
|
|
|
/* if an insertion happened while we were 'sleeping,' restart syhi */ |
|
|
if (FPROPS (CurrentPage, WidgetInfo.syhi_ran)) |
|
|
{ |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &start, start_mark); |
|
|
gtk_text_buffer_get_iter_at_mark (Buffer, &end, end_mark); |
|
|
|
|
|
expand_syhi_iters (Buffer, &start, &end, Lg); |
|
|
|
|
|
restart = TRUE; |
|
|
} |
|
|
|
|
|
gtk_text_buffer_delete_mark (Buffer, start_mark); |
|
|
gtk_text_buffer_delete_mark (Buffer, end_mark); |
|
|
|
|
|
g_timer_start (timer); |
|
|
} |
|
|
#endif |
|
|
} |
|
|
|
|
|
g_free (text); |
|
|
g_timer_destroy (timer); |
|
|
|
|
|
FPROPS (CurrentPage, WidgetInfo.syhi_ran) = TRUE; |
|
|
FPROPS(CurrentPage, WidgetInfo.markers) = markers; |
|
|
|
|
|
if (restart) |
|
|
{ |
|
|
markup_syhi_range (Buffer, start, end); |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (markers_changed) |
|
|
{ |
|
|
refresh_markers (Buffer); |
|
|
} |
|
|
|
|
|
/* redraw the current page, because we may have changed some colors around */ |
|
|
gtk_widget_queue_draw (FPROPS(CurrentPage, Text)); |
|
|
} |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
|
|
|
void expand_syhi_iters (GtkTextBuffer *Buffer, GtkTextIter *start, GtkTextIter *end, gint Lg) |
|
|
{ |
|
|
gunichar tmp; |
|
|
gboolean inside_buffer; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
/* go backwards */ |
|
|
do |
|
|
{ |
|
|
inside_buffer = gtk_text_iter_backward_cursor_position (start); |
|
|
tmp = gtk_text_iter_get_char (start); |
|
|
} |
|
|
while (inside_buffer && |
|
|
(tmp <= 255 && ((Prefs.L[Lg].KeywordStatus[tmp] & 8) || |
|
|
(Prefs.L[Lg].KeywordStatus[tmp] & 1)))); |
|
|
|
|
|
if (inside_buffer) |
|
|
gtk_text_iter_forward_cursor_position (start); |
|
|
|
|
|
while (gtk_text_iter_get_char (start) && |
|
|
!g_unichar_isprint (gtk_text_iter_get_char (start))) |
|
|
{ |
|
|
gtk_text_iter_forward_cursor_position (start); |
|
|
} |
|
|
|
|
|
/* go forwards */ |
|
|
inside_buffer = tmp = gtk_text_iter_get_char (end); |
|
|
while (inside_buffer && |
|
|
(tmp <= 255 && ((Prefs.L[Lg].KeywordStatus[tmp] & 8) || |
|
|
(Prefs.L[Lg].KeywordStatus[tmp] & 1)))) |
|
|
{ |
|
|
inside_buffer = gtk_text_iter_forward_cursor_position (end); |
|
|
tmp = gtk_text_iter_get_char (end); |
|
|
} |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
|
|
|
void refresh_syhi_on_insert (GtkTextBuffer *Buffer, GtkTextIter *end_in, gchar *text, |
|
|
gint size, gpointer data) |
|
|
{ |
|
|
GtkTextIter start, end; |
|
|
gint CurrentPage, Lg; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
Lg = FPROPS(CurrentPage, WidgetInfo.Lg); |
|
|
|
|
|
if (Lg == -1) |
|
|
return; |
|
|
|
|
|
/* first we must move iters out to interesting edges */ |
|
|
end = start = *end_in; |
|
|
gtk_text_iter_backward_chars (&start, size); |
|
|
expand_syhi_iters (Buffer, &start, &end, Lg); |
|
|
|
|
|
markup_syhi_range (Buffer, start, end); |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
|
|
|
void refresh_syhi_on_delete (GtkTextBuffer *Buffer, GtkTextIter *start_in, |
|
|
GtkTextIter *end_in, gpointer data) |
|
|
{ |
|
|
GtkTextIter start, end; |
|
|
gint CurrentPage, Lg; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
Lg = FPROPS(CurrentPage, WidgetInfo.Lg); |
|
|
|
|
|
if (Lg == -1) |
|
|
return; |
|
|
|
|
|
start = *start_in; |
|
|
end = *end_in; |
|
|
expand_syhi_iters (Buffer, &start, &end, Lg); |
|
|
|
|
|
markup_syhi_range (Buffer, start, end); |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
|
|
|
|
void refresh_syhi_all (GtkTextView *View) |
|
|
{ |
|
|
GtkTextIter start, end; |
|
|
GtkTextBuffer *Buffer; |
|
|
gint Lg, CurrentPage; |
|
|
|
|
|
START_FCN |
|
|
|
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
Lg = FPROPS(CurrentPage, WidgetInfo.Lg); |
|
|
|
|
|
Buffer = gtk_text_view_get_buffer (View); |
|
|
gtk_text_buffer_get_start_iter (Buffer, &start); |
|
|
gtk_text_buffer_get_end_iter (Buffer, &end); |
|
|
expand_syhi_iters (Buffer, &start, &end, Lg); // this catches some cases, so we still need to call it |
|
|
markup_syhi_range (Buffer, start, end); |
|
|
|
|
|
END_FCN |
|
|
} |
|
|
|
|
537 |
void auto_indent_on_insert (GtkTextBuffer *Buffer, GtkTextIter *iter, gchar *text, |
void auto_indent_on_insert (GtkTextBuffer *Buffer, GtkTextIter *iter, gchar *text, |
538 |
gint size, gpointer data) |
gint size, gpointer data) |
539 |
{ |
{ |
686 |
END_FCN |
END_FCN |
687 |
} |
} |
688 |
|
|
|
|
|
|
/* |
|
|
** This func returns the language number of the current Editor |
|
|
** |
|
|
** Parameters : |
|
|
** void |
|
|
** |
|
|
** Return Values : |
|
|
** -1 Unknown language (extension not recognized) |
|
|
** 0..MAX_LANG - 1 Language number |
|
|
** |
|
|
** NOTE_WARNING: UEdit language numbers belongs to [1..MAX_LANG] |
|
|
*/ |
|
|
gint guess_lang(void) |
|
|
{ |
|
|
gchar *ext_orig; |
|
|
gint ext_len; |
|
|
gchar *ext_up; |
|
|
gint i; |
|
|
gint CurrentPage; |
|
|
|
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): Begin\n", __func__); |
|
|
#endif |
|
|
CurrentPage = gtk_notebook_get_current_page (GTK_NOTEBOOK(MainNotebook)); |
|
|
ext_orig = FPROPS(CurrentPage, Type); |
|
|
#ifdef DEBUG_EXT_REC |
|
|
g_print(__FILE__": %s(): Getting length of ext_orig...\n", __func__); |
|
|
#endif |
|
|
ext_len = strlen(ext_orig); |
|
|
/* This macro FPROPS is awful :) */ |
|
|
#ifdef DEBUG_EXT_REC |
|
|
g_print(__FILE__": %s(): Original extension = \"%s\", len = %i\n", __func__, |
|
|
ext_orig, ext_len); |
|
|
#endif |
|
|
ext_up = malloc(ext_len + 3); /* 1 space before, 1 after, and '\0' */ |
|
|
strcpy(ext_up + 1, ext_orig); |
|
|
ext_up[0] = ' '; |
|
|
ext_up[ext_len + 1] = ' '; |
|
|
ext_up[ext_len + 2] = '\0'; |
|
|
for (i = 1; i < ext_len + 1; i++) |
|
|
ext_up[i] = toupper(ext_up[i]); |
|
|
/* Now, ext_up contains the extension in upper case */ |
|
|
#ifdef DEBUG_EXT_REC |
|
|
g_print(__FILE__": %s(): ' ' + EXTENSION + ' ': \"%s\"\n", __func__, ext_up); |
|
|
#endif |
|
|
for (i = 0; i < MAX_LANG; i++) |
|
|
{ |
|
|
#ifdef DEBUG_EXT_REC |
|
|
g_print(__FILE__": %s(): Ext of language /L%i = \"%s\"\n", __func__, |
|
|
i + 1, Prefs.L[i].Extensions); |
|
|
#endif |
|
|
if (Prefs.L[i].IsDefined && strstr(Prefs.L[i].Extensions, ext_up)) |
|
|
{ |
|
|
free(ext_up); |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
return i; |
|
|
} |
|
|
} |
|
|
free(ext_up); |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
return -1; |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
** This fcn is used to read the UltraEdit wordfile to init different |
|
|
** fields of the global variable Prefs |
|
|
** |
|
|
** Parameters : |
|
|
** wf_name UEdit wordfile name |
|
|
** |
|
|
** Return Values : |
|
|
** 0 All is right |
|
|
** -1 Can not open wordfile |
|
|
** -2 Parse error in a language section |
|
|
*/ |
|
|
extern gint read_uedit_wordfile(const gchar *wf_name) |
|
|
{ |
|
|
FILE *fp; |
|
|
gint filesize; |
|
|
gchar *buffer; |
|
|
gint i; |
|
|
gint j; |
|
|
|
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): Begin\n", __func__); |
|
|
#endif |
|
|
/* Initialisation of all variables */ |
|
|
/* TODO: Free all these variables by creating a new fcn called when |
|
|
exiting Beaver */ |
|
|
for (i = 0; i < MAX_LANG; i++) |
|
|
{ |
|
|
for (j = 0; j < MAX_COL; j++) |
|
|
{ |
|
|
Prefs.L[i].C[j].Keywords = NULL; |
|
|
Prefs.L[i].C[j].Description[0] = '\0'; |
|
|
} |
|
|
Prefs.L[i].IsDefined = FALSE; |
|
|
Prefs.L[i].LargestKeyword = 0; |
|
|
Prefs.L[i].Description[0] = '\0'; |
|
|
Prefs.L[i].Extensions = NULL; |
|
|
Prefs.L[i].LineComment = NULL; |
|
|
Prefs.L[i].LineCommentAlt = NULL; |
|
|
Prefs.L[i].BlockCommentOn = NULL; |
|
|
Prefs.L[i].BlockCommentOff = NULL; |
|
|
Prefs.L[i].BlockCommentOnAlt = NULL; |
|
|
Prefs.L[i].BlockCommentOffAlt = NULL; |
|
|
Prefs.L[i].IsCaseSensitive = TRUE; |
|
|
Prefs.L[i].HaveString = TRUE; |
|
|
Prefs.L[i].StringChar0 = '\"'; |
|
|
Prefs.L[i].StringChar1 = '\0'; |
|
|
Prefs.L[i].EscapeChar = '\0'; |
|
|
Prefs.L[i].Delimiters = NULL; |
|
|
Prefs.L[i].IndentString = NULL; |
|
|
Prefs.L[i].UnindentString = NULL; |
|
|
Prefs.L[i].MarkerChars = NULL; |
|
|
Prefs.L[i].FunctionString = NULL; |
|
|
Prefs.L[i].IsHTML = FALSE; |
|
|
} |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Opening \"%s\"...\n", __func__, wf_name); |
|
|
#endif |
|
|
if (!(fp = fopen(wf_name, "rt"))) |
|
|
{ |
|
|
gchar *wf_not_found; |
|
|
|
|
|
wf_not_found = g_strdup_printf(_("WARNING: Cannot find wordfile \"%s\"."), wf_name); |
|
|
print_msg (wf_not_found); |
|
|
g_free (wf_not_found); |
|
|
return -1; |
|
|
} |
|
|
filesize = 0; |
|
|
while (getc(fp) != EOF) |
|
|
filesize++; |
|
|
if (filesize > 0) |
|
|
{ |
|
|
buffer = g_malloc(filesize + 2); |
|
|
fseek(fp, 0, SEEK_SET); |
|
|
for (i = 0; i < filesize; i++) |
|
|
buffer[i] = getc(fp); |
|
|
buffer[filesize] = '\n'; |
|
|
buffer[filesize + 1] = '\0'; |
|
|
} |
|
|
else |
|
|
buffer = NULL; |
|
|
fclose(fp); |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Wordfile size = %i\n", __func__, filesize); |
|
|
#endif |
|
|
/* Here: main work */ |
|
|
i = 0; |
|
|
while (i + 1 <= filesize) |
|
|
{ |
|
|
if (!strncmp(buffer + i, "/L", 2)) |
|
|
{ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Calling " |
|
|
"parse_language_section()\n", __func__); |
|
|
#endif |
|
|
if (parse_language_section(buffer, filesize, &i)) |
|
|
{ |
|
|
g_print(__FILE__": %s(): End, parse error in a " |
|
|
"language section of \"%s\"\n", __func__, wf_name); |
|
|
g_free(buffer); |
|
|
return -2; |
|
|
} |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
g_free(buffer); |
|
|
for (i = 0; i < MAX_LANG; i++) |
|
|
{ |
|
|
if (!Prefs.L[i].IsDefined) |
|
|
sprintf(Prefs.L[i].Description, "Language %i", i + 1); |
|
|
Prefs.L[i].Description[MAXLEN_LANG_DESCRIPTION] = 0; |
|
|
for (j = 0; j < MAX_COL; j++) |
|
|
{ |
|
|
if (!Prefs.L[i].C[j].Keywords) |
|
|
sprintf(Prefs.L[i].C[j].Description, "Keywords Group %i", j + 1); |
|
|
Prefs.L[i].C[j].Description[MAXLEN_COL_DESCRIPTION] = 0; |
|
|
} |
|
|
} |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
return 0; |
|
|
} |
|
|
|
|
|
/* |
|
|
** Parse a language section in a UEdit wordfile |
|
|
** |
|
|
** Parameters: |
|
|
** buffer Is a null-terminated string, representing the /Lx |
|
|
** section in a wordfile |
|
|
** size Size of the buffer |
|
|
** start buffer + *start points on "/Lx..." |
|
|
** |
|
|
** Return values: |
|
|
** 0 All is right |
|
|
** -1 Parse error in a color section |
|
|
*/ |
|
|
gint parse_language_section(gchar *buffer, |
|
|
gint size, |
|
|
gint *start) |
|
|
{ |
|
|
gint Lg; |
|
|
gint i; |
|
|
gint j; |
|
|
gchar c; |
|
|
|
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): Begin\n", __func__); |
|
|
#endif |
|
|
i = *start; |
|
|
i = i + 2; |
|
|
/* buffer[i] is the 1st digit of language number */ |
|
|
j = i; |
|
|
while (isdigit(buffer[j])) |
|
|
j++; |
|
|
/* buffer[j] is the first char after the last digit of language number */ |
|
|
c = buffer[j]; |
|
|
buffer[j] = 0; |
|
|
Lg = atoi(buffer + i) - 1; |
|
|
buffer[j] = c; |
|
|
if (Lg + 1 > MAX_LANG) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, /L%i section detected in wordfile " |
|
|
"but only %i are allowed\n", __func__, Lg + 1, MAX_LANG); |
|
|
return -1; |
|
|
} |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): /L%i section detected\n", __func__, Lg + 1); |
|
|
#endif |
|
|
Prefs.L[Lg].IsDefined = TRUE; |
|
|
i = j; |
|
|
if (buffer[i] == '\"') |
|
|
{ |
|
|
/* There is a description of the language */ |
|
|
j = ++i; |
|
|
while (buffer[j] != '\"') |
|
|
j++; |
|
|
/* buffer[i] is the 1st char of description and buffer[j] the 2nd '\"' */ |
|
|
if ((j - i) > MAXLEN_LANG_DESCRIPTION) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, description of " |
|
|
"language %i is longer than %i\n", __func__, Lg + 1, |
|
|
MAXLEN_LANG_DESCRIPTION); |
|
|
return -1; |
|
|
} |
|
|
strncpy(Prefs.L[Lg].Description, buffer + i, j - i); |
|
|
Prefs.L[Lg].Description[j - i] = '\0'; |
|
|
i = ++j; |
|
|
} |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Description of language %i = " |
|
|
"\"%s\"\n", __func__, Lg + 1, Prefs.L[Lg].Description); |
|
|
#endif |
|
|
memset (Prefs.L[Lg].KeywordStatus, 0, 256); |
|
|
/* Here, buffer[i (= j)] is next non-identified char */ |
|
|
/* The while loop below reads the line /Lx of a wordfile */ |
|
|
while (buffer[i] != '\n') |
|
|
{ |
|
|
/* LineComment */ |
|
|
if (!strncmp(buffer + i, "Line Comment = ", 15)) |
|
|
{ |
|
|
Prefs.L[Lg].LineComment = g_malloc(MAXLEN_LINE_COMMENT + 1); |
|
|
i += 15; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_LINE_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].LineComment[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_LINE_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Line Comment of " |
|
|
"language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_LINE_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].LineComment[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Line Comment = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].LineComment); |
|
|
#endif |
|
|
} |
|
|
/* LineCommentAlt */ |
|
|
else if (!strncmp(buffer + i, "Line Comment Alt = ", 19)) |
|
|
{ |
|
|
Prefs.L[Lg].LineCommentAlt = g_malloc(MAXLEN_LINE_COMMENT + 1); |
|
|
i += 19; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_LINE_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].LineCommentAlt[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_LINE_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Line Comment Alt of " |
|
|
"language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_LINE_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].LineCommentAlt[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Line Comment Alt = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].LineCommentAlt); |
|
|
#endif |
|
|
} |
|
|
/* LineComment Num */ |
|
|
else if (!strncmp(buffer + i, "Line Comment Num = ", 19)) |
|
|
{ |
|
|
gint line_cmt_len; |
|
|
|
|
|
Prefs.L[Lg].LineComment = g_malloc(MAXLEN_LINE_COMMENT + 1); |
|
|
line_cmt_len = buffer[i += 19] - '0'; |
|
|
if (line_cmt_len > MAXLEN_LINE_COMMENT) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Line Comment Num of " |
|
|
"language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_LINE_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
i++; |
|
|
/* Here buffer[i] is the 1st char of LineComment */ |
|
|
for (j = 0; j < line_cmt_len; j++) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].LineComment[j] = buffer[i + j]; |
|
|
} |
|
|
Prefs.L[Lg].LineComment[j] = '\0'; |
|
|
i += line_cmt_len; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Line Comment Num = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].LineComment); |
|
|
#endif |
|
|
} |
|
|
/* BlockCommentOn */ |
|
|
else if (!strncmp(buffer + i, "Block Comment On = ", 19)) |
|
|
{ |
|
|
Prefs.L[Lg].BlockCommentOn = g_malloc(MAXLEN_BLOCK_COMMENT + 1); |
|
|
i += 19; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].BlockCommentOn[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Block Comment On of " |
|
|
"language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_BLOCK_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].BlockCommentOn[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Block Comment On = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].BlockCommentOn); |
|
|
#endif |
|
|
} |
|
|
/* BlockCommentOff */ |
|
|
else if (!strncmp(buffer + i, "Block Comment Off = ", 20)) |
|
|
{ |
|
|
Prefs.L[Lg].BlockCommentOff = g_malloc(MAXLEN_BLOCK_COMMENT + 1); |
|
|
i += 20; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].BlockCommentOff[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Block Comment Off of " |
|
|
"language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_BLOCK_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].BlockCommentOff[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Block Comment Off = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].BlockCommentOff); |
|
|
#endif |
|
|
} |
|
|
/* BlockCommentOnAlt */ |
|
|
else if (!strncmp(buffer + i, "Block Comment On Alt = ", 23)) |
|
|
{ |
|
|
Prefs.L[Lg].BlockCommentOnAlt = g_malloc(MAXLEN_BLOCK_COMMENT + 1); |
|
|
i += 23; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].BlockCommentOnAlt[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Block Comment On Alt " |
|
|
"of language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_BLOCK_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].BlockCommentOnAlt[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Block Comment On Alt = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].BlockCommentOnAlt); |
|
|
#endif |
|
|
} |
|
|
/* BlockCommentOffAlt */ |
|
|
else if (!strncmp(buffer + i, "Block Comment Off Alt = ", 24)) |
|
|
{ |
|
|
Prefs.L[Lg].BlockCommentOffAlt = g_malloc(MAXLEN_BLOCK_COMMENT + 1); |
|
|
i += 24; |
|
|
j = -1; |
|
|
while ((++j < MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i + j]] |= 8; |
|
|
Prefs.L[Lg].BlockCommentOffAlt[j] = buffer[i + j]; |
|
|
} |
|
|
if ((j == MAXLEN_BLOCK_COMMENT) && (buffer[i + j] != ' ')) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, Block Comment Off Alt " |
|
|
"of language /L%i is longer than %i\n", __func__, |
|
|
Lg + 1, MAXLEN_BLOCK_COMMENT); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].BlockCommentOffAlt[j] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Block Comment Off Alt = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].BlockCommentOffAlt); |
|
|
#endif |
|
|
} |
|
|
/* StringChars */ |
|
|
else if (!strncmp(buffer + i, "String Chars = ", 15)) |
|
|
{ |
|
|
i += 15; |
|
|
if (buffer[i] != ' ') |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i]] |= 8; |
|
|
Prefs.L[Lg].StringChar0 = buffer[i]; |
|
|
} |
|
|
i++; |
|
|
if (buffer[i] != ' ') |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i]] |= 8; |
|
|
Prefs.L[Lg].StringChar1 = buffer[i]; |
|
|
} |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): String Chars = \'%c\' & \'%c\'\n", __func__, |
|
|
Prefs.L[Lg].StringChar0, Prefs.L[Lg].StringChar1); |
|
|
#endif |
|
|
} |
|
|
/* EscapeChar */ |
|
|
else if (!strncmp(buffer + i, "Escape Char = ", 14)) |
|
|
{ |
|
|
i += 14; |
|
|
if (buffer[i] != ' ') |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) buffer[i]] |= 8; |
|
|
Prefs.L[Lg].EscapeChar = buffer[i]; |
|
|
} |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Escape Char = \'%c\'\n", __func__, |
|
|
Prefs.L[Lg].EscapeChar); |
|
|
#endif |
|
|
} |
|
|
/* FileExtensions */ |
|
|
/* NOTE_WARNING: This sections is supposed to end the line /Lx */ |
|
|
else if (!strncmp(buffer + i, "File Extensions = ", 18)) |
|
|
{ |
|
|
i += 18; |
|
|
j = 0; |
|
|
while (buffer[i + j] != '\n') |
|
|
j++; |
|
|
Prefs.L[Lg].Extensions = g_malloc(1 + j + 1 + 1); |
|
|
Prefs.L[Lg].Extensions[0] = ' '; |
|
|
for (j = 0; buffer[i + j] != '\n'; j++) |
|
|
Prefs.L[Lg].Extensions[1 + j] = buffer[i + j]; |
|
|
Prefs.L[Lg].Extensions[j] = ' '; |
|
|
Prefs.L[Lg].Extensions[j + 1] = '\0'; |
|
|
i += j; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): File Extensions = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].Extensions); |
|
|
#endif |
|
|
} |
|
|
/* Nocase */ |
|
|
else if (!strncmp(buffer + i, "Nocase ", 7)) |
|
|
{ |
|
|
i += 7; |
|
|
Prefs.L[Lg].IsCaseSensitive = FALSE; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Nocase\n", __func__); |
|
|
#endif |
|
|
} |
|
|
/* Noquote */ |
|
|
else if (!strncmp(buffer + i, "Noquote ", 8)) |
|
|
{ |
|
|
i += 8; |
|
|
Prefs.L[Lg].HaveString = FALSE; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Noquote\n", __func__); |
|
|
#endif |
|
|
} |
|
|
/* HTML */ |
|
|
else if (!strncmp(buffer + i, "HTML_LANG ", 10)) |
|
|
{ |
|
|
i += 10; |
|
|
Prefs.L[Lg].IsHTML = TRUE; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): HTML_LANG\n", __func__); |
|
|
#endif |
|
|
} |
|
|
/* FORTRAN_LANG */ |
|
|
/* NOTE_TODO: Implement it: 'C', 'c' or '*' in the 1st column is a |
|
|
line comment */ |
|
|
else if (!strncmp(buffer + i, "FORTRAN_LANG ", 13)) |
|
|
{ |
|
|
i += 13; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): FORTRAN_LANG\n", __func__); |
|
|
#endif |
|
|
} |
|
|
/* LATEX_LANG */ |
|
|
/* NOTE_REMARK: LATEX_LANG is ignored, Beaver does not need it ! */ |
|
|
else if (!strncmp(buffer + i, "LATEX_LANG ", 11)) |
|
|
{ |
|
|
i += 11; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): LATEX_LANG\n", __func__); |
|
|
#endif |
|
|
} |
|
|
else if ((buffer[i] == ' ') || (buffer[i] == '\t')) |
|
|
i++; |
|
|
/* Nothing */ |
|
|
else |
|
|
{ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Unreconized string in /Lx line, " |
|
|
"beginning = \"%c%c%c%c...\"\n", __func__, |
|
|
buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]); |
|
|
#endif |
|
|
i++; |
|
|
} |
|
|
} /* while (buffer[i] != '\n') */ |
|
|
i++; |
|
|
while ((i + 1 < size) && strncmp(buffer + i, "/C", 2)) |
|
|
{ |
|
|
if (!strncmp(buffer + i, "/Delimiters = ", 14)) |
|
|
{ |
|
|
/* Delimiters */ |
|
|
j = (i += 14); |
|
|
while (buffer[j] != '\n') |
|
|
j++; |
|
|
j++; |
|
|
/* NOTE_WARNING: Yes, the '\n' needs to be into the Delimiters */ |
|
|
Prefs.L[Lg].Delimiters = g_malloc(j - i + 1); |
|
|
strncpy(Prefs.L[Lg].Delimiters, buffer + i, j - i); |
|
|
Prefs.L[Lg].Delimiters[j - i] = '\0'; |
|
|
i = j; |
|
|
for (j = 0; j < 256; j++) |
|
|
Prefs.L[Lg].IsADelimiter[j] = |
|
|
strchr(Prefs.L[Lg].Delimiters, j) ? 1 : 0; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Delimiters = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].Delimiters); |
|
|
#endif |
|
|
} |
|
|
else if (!strncmp(buffer + i, "/Indent Strings =", 17)) |
|
|
{ |
|
|
/* Indent Strings */ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Indent String = ", __func__); |
|
|
#endif |
|
|
i += 17; |
|
|
while ((buffer[i] != '\n') && (buffer[i] != '\"')) |
|
|
i++; |
|
|
if (buffer[i] == '\"') |
|
|
{ |
|
|
j = ++i; |
|
|
while ((buffer[j] != '\n') && (buffer[j] != '\"')) |
|
|
j++; |
|
|
/* Here, if buffer[j] == '\n', it is considered as a '\"' */ |
|
|
Prefs.L[Lg].IndentString = g_malloc(j - i + 1); |
|
|
strncpy(Prefs.L[Lg].IndentString, buffer + i, j - i); |
|
|
Prefs.L[Lg].IndentString[j - i] = '\0'; |
|
|
i = j; |
|
|
/* NOTE_TODO : Support multiple indent string... */ |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print("\"%s\"\n", Prefs.L[Lg].IndentString); |
|
|
#endif |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
else if (!strncmp(buffer + i, "/Unindent Strings =", 19)) |
|
|
{ |
|
|
/* Unindent Strings */ |
|
|
i += 19; |
|
|
while ((buffer[i] != '\n') && (buffer[i] != '\"')) |
|
|
i++; |
|
|
if (buffer[i] == '\"') |
|
|
{ |
|
|
j = ++i; |
|
|
while ((buffer[j] != '\n') && (buffer[j] != '\"')) |
|
|
j++; |
|
|
/* Here, if buffer[j] == '\n', it is considered as a '\"' */ |
|
|
Prefs.L[Lg].UnindentString = g_malloc(j - i + 1); |
|
|
strncpy(Prefs.L[Lg].UnindentString, buffer + i, j - i); |
|
|
Prefs.L[Lg].UnindentString[j - i] = '\0'; |
|
|
i = j; |
|
|
/* NOTE_TODO : Support multiple unindent string... */ |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Unindent String = \"%s\"\n", __func__, |
|
|
Prefs.L[Lg].UnindentString); |
|
|
#endif |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
else if (!strncmp(buffer + i, "/Marker Characters =", 20)) |
|
|
{ |
|
|
/* Marker Characters */ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Marker Chars = ", __func__); |
|
|
#endif |
|
|
i += 20; |
|
|
while ((buffer[i] != '\n') && (buffer[i] != '\"')) |
|
|
i++; |
|
|
if (buffer[i] == '\"') |
|
|
{ |
|
|
j = ++i; |
|
|
while ((buffer[j] != '\n') && (buffer[j] != '\"')) |
|
|
j++; |
|
|
/* Here, if buffer[j] == '\n', it is considered as a '\"' */ |
|
|
Prefs.L[Lg].MarkerChars = g_malloc(j - i + 1); |
|
|
strncpy(Prefs.L[Lg].MarkerChars, buffer + i, j - i); |
|
|
Prefs.L[Lg].MarkerChars[j - i] = '\0'; |
|
|
i = j; |
|
|
/* NOTE_TODO : Support marker chars... */ |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print("\"%s\"\n", Prefs.L[Lg].MarkerChars); |
|
|
#endif |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
else if (!strncmp(buffer + i, "/Function String =", 18)) |
|
|
{ |
|
|
/* Function String */ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Function String = ", __func__); |
|
|
#endif |
|
|
i += 18; |
|
|
while ((buffer[i] != '\n') && (buffer[i] != '\"')) |
|
|
i++; |
|
|
if (buffer[i] == '\"') |
|
|
{ |
|
|
j = ++i; |
|
|
while ((buffer[j] != '\n') && (buffer[j] != '\"')) |
|
|
j++; |
|
|
/* Here, if buffer[j] == '\n', it is considered as a '\"' */ |
|
|
Prefs.L[Lg].FunctionString = g_malloc(j - i + 1); |
|
|
strncpy(Prefs.L[Lg].FunctionString, buffer + i, j - i); |
|
|
Prefs.L[Lg].FunctionString[j - i] = '\0'; |
|
|
i = j; |
|
|
/* NOTE_TODO : Support function string */ |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print("\"%s\"\n", Prefs.L[Lg].FunctionString); |
|
|
#endif |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
else if ((buffer[i] == ' ') || (buffer[i] == '\t')) |
|
|
i++; |
|
|
else |
|
|
{ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Unregonized string between /Lx " |
|
|
"and /Cy: \"%c%c%c%c...\"\n", __func__, |
|
|
buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]); |
|
|
#endif |
|
|
i++; |
|
|
} |
|
|
} /* while (strncmp(buffer + i, "/C", 2)) */ |
|
|
while ((i + 1 <= size) && strncmp(buffer + i, "/L", 2)) |
|
|
{ |
|
|
if (!strncmp(buffer + i, "/C", 2)) |
|
|
{ |
|
|
if (parse_color_section(buffer, size, &i, Lg)) |
|
|
{ |
|
|
g_print(__FILE__": %s(): End, parse error in a color " |
|
|
"section of /L%i\n", __func__, Lg + 1); |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
else |
|
|
i++; |
|
|
} |
|
|
*start = i; |
|
|
/* |
|
|
** Now that all Prefs.L[Lg].C[_var_].Keywords are initialized, we can |
|
|
** fill in the keywords hash tables |
|
|
*/ |
|
|
#ifdef DEBUG_HASHTABLE |
|
|
g_print(__FILE__": %s(): Creating hash table for Lg %i\n", __func__, Lg); |
|
|
#endif |
|
|
if (Prefs.L[Lg].IsCaseSensitive) |
|
|
Prefs.L[Lg].Hash = g_hash_table_new(g_str_hash, g_str_equal); |
|
|
else |
|
|
Prefs.L[Lg].Hash = g_hash_table_new(my_g_strcase_hash, |
|
|
my_g_strcase_equal); |
|
|
for (i = 0; i < MAX_COL; i++) |
|
|
if (Prefs.L[Lg].C[i].Keywords) |
|
|
{ |
|
|
#ifdef DEBUG_HASHTABLE |
|
|
g_print(__FILE__": %s(): Inserting keywords group %i\n", __func__, i); |
|
|
#endif |
|
|
j = 1; |
|
|
while (Prefs.L[Lg].C[i].Keywords[j]) |
|
|
{ |
|
|
int len = 0; |
|
|
|
|
|
while (Prefs.L[Lg].C[i].Keywords[j + len] != ' ') |
|
|
len++; |
|
|
/* |
|
|
** Now, Keywords[j] is the 1st char of a word and len is its |
|
|
** length. We will insert it in the hash table. The value |
|
|
** associated to it will be the color plus 1 (i + 1). |
|
|
*/ |
|
|
Prefs.L[Lg].C[i].Keywords[j + len] = '\0'; |
|
|
|
|
|
Prefs.L[Lg].LargestKeyword = MAX (Prefs.L[Lg].LargestKeyword, len); |
|
|
|
|
|
#ifdef DEBUG_HASHTABLE |
|
|
g_print(__FILE__": %s(): Inserting keyword %s\n", __func__, |
|
|
Prefs.L[Lg].C[i].Keywords + j); |
|
|
#endif |
|
|
g_hash_table_insert(Prefs.L[Lg].Hash, |
|
|
g_strdup(Prefs.L[Lg].C[i].Keywords + j), |
|
|
GINT_TO_POINTER(i + 1)); |
|
|
Prefs.L[Lg].C[i].Keywords[j + len] = ' '; |
|
|
j += len + 1; |
|
|
} |
|
|
} |
|
|
#ifdef DEBUG_HASHTABLE |
|
|
g_print(__FILE__": %s(): Hash table created for Lg %i\n", __func__, Lg); |
|
|
#endif |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
return 0; |
|
|
} |
|
|
|
|
|
/* |
|
|
** Equivalent to the standard g_str_equal() function, but this one |
|
|
** is case-independant |
|
|
*/ |
|
|
gint my_g_strcase_equal (gconstpointer v, gconstpointer v2) |
|
|
{ |
|
|
return strcasecmp ((const gchar*)v, (const gchar*)v2) == 0; |
|
|
} |
|
|
|
|
|
/* |
|
|
** Equivalent to the standard g_str_hash() function, but this one |
|
|
** is case-independant |
|
|
*/ |
|
|
guint my_g_strcase_hash (gconstpointer key) |
|
|
{ |
|
|
const char *p = key; |
|
|
guint h = *p; |
|
|
|
|
|
if (h) |
|
|
{ |
|
|
if (h >= 'A' && h <= 'Z') |
|
|
h |= 0x20; |
|
|
for (p += 1; *p != '\0'; p++) |
|
|
h = (h << 5) - h + ((*p >= 'A' && *p <= 'Z') ? (*p | 0x20) : (*p)); |
|
|
} |
|
|
return h; |
|
|
} |
|
|
|
|
|
|
|
|
/* |
|
|
** Parse of color section in a UEdit wordfile |
|
|
** |
|
|
** Parameters: |
|
|
** buffer Is a null-terminated string, representing the /Cx |
|
|
** section in a wordfile |
|
|
** size Size of the buffer |
|
|
** start buffer + *start points on "/Cx..." |
|
|
** |
|
|
** Return values: |
|
|
** 0 No errors |
|
|
** -1 Parse error in a line |
|
|
*/ |
|
|
gint parse_color_section(gchar *buffer, |
|
|
gint size, |
|
|
gint *start, |
|
|
gint Lg) |
|
|
{ |
|
|
gint col; |
|
|
gint i; |
|
|
gint j; |
|
|
gchar c; |
|
|
|
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): Begin\n", __func__); |
|
|
#endif |
|
|
i = *start; |
|
|
i = i + 2; |
|
|
/* buffer[i] is the 1st digit of color number */ |
|
|
j = i; |
|
|
while (isdigit(buffer[j])) |
|
|
j++; |
|
|
/* buffer[j] is the first char after the last digit of language number */ |
|
|
c = buffer[j]; |
|
|
buffer[j] = 0; |
|
|
col = atoi(buffer + i) - 1; |
|
|
buffer[j] = c; |
|
|
if (col + 1 > MAX_COL) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, color %i section detected " |
|
|
"but only %i are allowed\n", __func__, col + 1, MAX_COL); |
|
|
return -1; |
|
|
} |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Color %i section detected\n", __func__, col + 1); |
|
|
#endif |
|
|
i = j; |
|
|
if (buffer[i] == '\"' || buffer[i] == ' ') |
|
|
{ |
|
|
/* There is a description of the color */ |
|
|
j = ++i; |
|
|
while (buffer[j] != '\"' && buffer[j] != '\n') |
|
|
j++; |
|
|
/* buffer[i] is the 1st char of description and buffer[j] the 2nd '\"' */ |
|
|
if ((j - i) > MAXLEN_COL_DESCRIPTION) |
|
|
{ |
|
|
g_print(__FILE__": %s(): Warning, description of color %i " |
|
|
"of language %i is longer than %i\n", __func__, col + 1, |
|
|
Lg + 1, MAXLEN_COL_DESCRIPTION); |
|
|
return -1; |
|
|
} |
|
|
strncpy(Prefs.L[Lg].C[col].Description, buffer + i, j - i); |
|
|
Prefs.L[Lg].C[col].Description[j - i] = '\0'; |
|
|
i = j; |
|
|
} |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Description of color %i = " |
|
|
"\"%s\"\n", __func__, col + 1, Prefs.L[Lg].C[col].Description); |
|
|
#endif |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
j = ++i; |
|
|
/* Here, buffer[i] is the first char of keywords area */ |
|
|
while ((i + 1 <= size) && |
|
|
strncmp(buffer + i, "/C", 2) && |
|
|
strncmp(buffer + i, "/L", 2)) |
|
|
{ |
|
|
if ((buffer[i] == '/') && (buffer[i + 1] != '/')) |
|
|
{ |
|
|
/* NOTE_TODO: Take into account this case (execute the 'command') */ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): In /L%i /C%i, command ignored\n", __func__, |
|
|
Lg + 1, col + 1); |
|
|
#endif |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
} |
|
|
else if (!strncmp(buffer + i, "**", 2)) |
|
|
{ |
|
|
/* NOTE_TODO: Take into account this case (colorize all words |
|
|
beginning with following prefixes) */ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): In /L%i, '**' ignored\n", __func__, |
|
|
Lg + 1); |
|
|
#endif |
|
|
while (buffer[i] != '\n') |
|
|
i++; |
|
|
i++; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if ((buffer[i] == '/') && (buffer[i + 1] == '/')) |
|
|
{ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): In /L%i, '//' detected\n", __func__, |
|
|
Lg + 1); |
|
|
#endif |
|
|
i += 2; |
|
|
} |
|
|
if (parse_line_of_keywords(buffer, size, &i, Lg, col)) |
|
|
{ |
|
|
g_print(__FILE__": %s(): End, parse error in a line of " |
|
|
"keywords of /L%i /C%i\n", __func__, Lg + 1, col + 1); |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
} |
|
|
*start = i; |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
return 0; |
|
|
} |
|
|
|
|
|
/* |
|
|
** Parse 1 line of keywords in a UEdit wordfile |
|
|
** |
|
|
** Parameters: |
|
|
** buffer Is a null-terminated string, representing the /Cx |
|
|
** section in a wordfile |
|
|
** size Size of the buffer |
|
|
** start buffer + *start points on "/Cx..." |
|
|
** |
|
|
** Return values: |
|
|
** 0 No errors |
|
|
** -1 Error while parsing line |
|
|
*/ |
|
|
gint parse_line_of_keywords(gchar *buffer, |
|
|
gint size, |
|
|
gint *start, |
|
|
gint Lg, |
|
|
gint col) |
|
|
{ |
|
|
gint i, j, k; |
|
|
gchar c; |
|
|
gint strlen_k; |
|
|
gint strlen_b; |
|
|
|
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): Begin\n", __func__); |
|
|
#endif |
|
|
(void)size; |
|
|
i = *start; |
|
|
while ((buffer[i] != '\r') && (buffer[i] != '\n')) |
|
|
{ |
|
|
if ((buffer[i] == ' ') || (buffer[i] == '\t')) |
|
|
i++; |
|
|
else |
|
|
{ |
|
|
/* buffer[i] is the first char of the keyword */ |
|
|
j = i; |
|
|
while ((buffer[j] != ' ') && (buffer[j] != '\t') && |
|
|
(buffer[j] != '\r') && (buffer[j] != '\n')) |
|
|
j++; |
|
|
/* buffer[j] is the first char after the last one of the keyword */ |
|
|
c = buffer[j]; |
|
|
buffer[j] = '\0'; |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): In /L%i /C%i, keyword \"%s\" " |
|
|
"detected\n", __func__, Lg + 1, col + 1, buffer + i); |
|
|
#endif |
|
|
if (Prefs.L[Lg].C[col].Keywords == NULL) |
|
|
{ |
|
|
#ifdef DEBUG_WORDFILE |
|
|
g_print(__FILE__": %s(): Ah ! Keywords == NULL\n", __func__); |
|
|
#endif |
|
|
if (!(Prefs.L[Lg].C[col].Keywords = g_malloc(2))) |
|
|
{ |
|
|
g_print(__FILE__": %s(): End, g_malloc() failed\n", __func__); |
|
|
return -1; |
|
|
} |
|
|
Prefs.L[Lg].C[col].Keywords[0] = ' '; |
|
|
Prefs.L[Lg].C[col].Keywords[1] = '\0'; |
|
|
} |
|
|
strlen_k = strlen(Prefs.L[Lg].C[col].Keywords); |
|
|
strlen_b = strlen(buffer + i); |
|
|
Prefs.L[Lg].C[col].Keywords = |
|
|
g_realloc(Prefs.L[Lg].C[col].Keywords, strlen_k + strlen_b + 2); |
|
|
if (Prefs.L[Lg].C[col].Keywords == NULL) |
|
|
{ |
|
|
g_print(__FILE__": %s(): End, g_realloc() failed\n", __func__); |
|
|
return -1; |
|
|
} |
|
|
strcat(Prefs.L[Lg].C[col].Keywords, buffer + i); |
|
|
strcat(Prefs.L[Lg].C[col].Keywords, " "); |
|
|
|
|
|
if (Prefs.L[Lg].IsCaseSensitive) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) *(buffer + i)] |= 0x2; |
|
|
/* if (j - i > 1) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) *(buffer + i + 1)] |= 0x16; |
|
|
}*/ |
|
|
for (k = i; k < j; k++) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) *(buffer + k)] |= 0x1; |
|
|
} |
|
|
Prefs.L[Lg].KeywordStatus[(int) *(buffer + j - 1)] |= 0x4; |
|
|
} |
|
|
else |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_toupper (*(buffer + i))] |= 0x2; |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_tolower (*(buffer + i))] |= 0x2; |
|
|
/* if (j - i > 1) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_toupper (*(buffer + i + 1))] |= 0x16; |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_tolower (*(buffer + i + 1))] |= 0x16; |
|
|
}*/ |
|
|
for (k = i; k < j; k++) |
|
|
{ |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_toupper (*(buffer + k))] |= 0x1; |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_tolower (*(buffer + k))] |= 0x1; |
|
|
} |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_toupper (*(buffer + j - 1))] |= 0x4; |
|
|
Prefs.L[Lg].KeywordStatus[(int) g_ascii_tolower (*(buffer + j - 1))] |= 0x4; |
|
|
} |
|
|
|
|
|
buffer[j] = c; |
|
|
i = j; |
|
|
} /* !((buffer[i] == ' ') || (buffer[i] == '\t')) */ |
|
|
} |
|
|
if (buffer[i] == '\r') |
|
|
i++; |
|
|
*start = i + 1; |
|
|
#ifdef DEBUG_FCN |
|
|
g_print(__FILE__": %s(): End\n", __func__); |
|
|
#endif |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|