1 /*
2 * modeline-parser.c
3 * Emacs, Kate and Vim-style modelines support for xed.
4 *
5 * Copyright (C) 2005-2007 - Steve Frécinaux <code@istique.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <gtk/gtk.h>
26 #include <gtksourceview/gtksource.h>
27 #include <xed/xed-debug.h>
28 #include <xed/xed-settings.h>
29 #include <xed/xed-utils.h>
30 #include "modeline-parser.h"
31
32 #define MODELINES_LANGUAGE_MAPPINGS_FILE "language-mappings"
33
34 /* base dir to lookup configuration files */
35 static gchar *modelines_data_dir;
36
37 /* Mappings: language name -> Xed language ID */
38 static GHashTable *vim_languages;
39 static GHashTable *emacs_languages;
40 static GHashTable *kate_languages;
41
42 typedef enum
43 {
44 MODELINE_SET_NONE = 0,
45 MODELINE_SET_TAB_WIDTH = 1 << 0,
46 MODELINE_SET_INDENT_WIDTH = 1 << 1,
47 MODELINE_SET_WRAP_MODE = 1 << 2,
48 MODELINE_SET_SHOW_RIGHT_MARGIN = 1 << 3,
49 MODELINE_SET_RIGHT_MARGIN_POSITION = 1 << 4,
50 MODELINE_SET_LANGUAGE = 1 << 5,
51 MODELINE_SET_INSERT_SPACES = 1 << 6
52 } ModelineSet;
53
54 typedef struct _ModelineOptions
55 {
56 gchar *language_id;
57
58 /* these options are similar to the GtkSourceView properties of the
59 * same names.
60 */
61 gboolean insert_spaces;
62 guint tab_width;
63 guint indent_width;
64 GtkWrapMode wrap_mode;
65 gboolean display_right_margin;
66 guint right_margin_position;
67
68 ModelineSet set;
69 } ModelineOptions;
70
71 #define MODELINE_OPTIONS_DATA_KEY "ModelineOptionsDataKey"
72
73 static gboolean
has_option(ModelineOptions * options,ModelineSet set)74 has_option (ModelineOptions *options,
75 ModelineSet set)
76 {
77 return options->set & set;
78 }
79
80 void
modeline_parser_init(const gchar * data_dir)81 modeline_parser_init (const gchar *data_dir)
82 {
83 if (modelines_data_dir == NULL)
84 {
85 modelines_data_dir = g_strdup (data_dir);
86 }
87 }
88
89 void
modeline_parser_shutdown()90 modeline_parser_shutdown ()
91 {
92 if (vim_languages != NULL)
93 g_hash_table_destroy (vim_languages);
94
95 if (emacs_languages != NULL)
96 g_hash_table_destroy (emacs_languages);
97
98 if (kate_languages != NULL)
99 g_hash_table_destroy (kate_languages);
100
101 vim_languages = NULL;
102 emacs_languages = NULL;
103 kate_languages = NULL;
104
105 g_free (modelines_data_dir);
106 modelines_data_dir = NULL;
107 }
108
109 static GHashTable *
load_language_mappings_group(GKeyFile * key_file,const gchar * group)110 load_language_mappings_group (GKeyFile *key_file, const gchar *group)
111 {
112 GHashTable *table;
113 gchar **keys;
114 gsize length = 0;
115 int i;
116
117 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
118
119 keys = g_key_file_get_keys (key_file, group, &length, NULL);
120
121 xed_debug_message (DEBUG_PLUGINS,
122 "%" G_GSIZE_FORMAT " mappings in group %s",
123 length, group);
124
125 for (i = 0; i < length; i++)
126 {
127 gchar *name = keys[i];
128 gchar *id = g_key_file_get_string (key_file, group, name, NULL);
129 g_hash_table_insert (table, name, id);
130 }
131 g_free (keys);
132
133 return table;
134 }
135
136 /* lazy loading of language mappings */
137 static void
load_language_mappings(void)138 load_language_mappings (void)
139 {
140 gchar *fname;
141 GKeyFile *mappings;
142 GError *error = NULL;
143
144 fname = g_build_filename (modelines_data_dir,
145 MODELINES_LANGUAGE_MAPPINGS_FILE,
146 NULL);
147
148 mappings = g_key_file_new ();
149
150 if (g_key_file_load_from_file (mappings, fname, 0, &error))
151 {
152 xed_debug_message (DEBUG_PLUGINS,
153 "Loaded language mappings from %s",
154 fname);
155
156 vim_languages = load_language_mappings_group (mappings, "vim");
157 emacs_languages = load_language_mappings_group (mappings, "emacs");
158 kate_languages = load_language_mappings_group (mappings, "kate");
159 }
160 else
161 {
162 xed_debug_message (DEBUG_PLUGINS,
163 "Failed to loaded language mappings from %s: %s",
164 fname, error->message);
165
166 g_error_free (error);
167 }
168
169 g_key_file_free (mappings);
170 g_free (fname);
171 }
172
173 static gchar *
get_language_id(const gchar * language_name,GHashTable * mapping)174 get_language_id (const gchar *language_name, GHashTable *mapping)
175 {
176 gchar *name;
177 gchar *language_id;
178
179 name = g_ascii_strdown (language_name, -1);
180
181 language_id = g_hash_table_lookup (mapping, name);
182
183 if (language_id != NULL)
184 {
185 g_free (name);
186 return g_strdup (language_id);
187 }
188 else
189 {
190 /* by default assume that the gtksourcevuew id is the same */
191 return name;
192 }
193 }
194
195 static gchar *
get_language_id_vim(const gchar * language_name)196 get_language_id_vim (const gchar *language_name)
197 {
198 if (vim_languages == NULL)
199 load_language_mappings ();
200
201 return get_language_id (language_name, vim_languages);
202 }
203
204 static gchar *
get_language_id_emacs(const gchar * language_name)205 get_language_id_emacs (const gchar *language_name)
206 {
207 if (emacs_languages == NULL)
208 load_language_mappings ();
209
210 return get_language_id (language_name, emacs_languages);
211 }
212
213 static gchar *
get_language_id_kate(const gchar * language_name)214 get_language_id_kate (const gchar *language_name)
215 {
216 if (kate_languages == NULL)
217 load_language_mappings ();
218
219 return get_language_id (language_name, kate_languages);
220 }
221
222 static gboolean
skip_whitespaces(gchar ** s)223 skip_whitespaces (gchar **s)
224 {
225 while (**s != '\0' && g_ascii_isspace (**s))
226 (*s)++;
227 return **s != '\0';
228 }
229
230 /* Parse vi(m) modelines.
231 * Vi(m) modelines looks like this:
232 * - first form: [text]{white}{vi:|vim:|ex:}[white]{options}
233 * - second form: [text]{white}{vi:|vim:|ex:}[white]se[t] {options}:[text]
234 * They can happen on the three first or last lines.
235 */
236 static gchar *
parse_vim_modeline(gchar * s,ModelineOptions * options)237 parse_vim_modeline (gchar *s,
238 ModelineOptions *options)
239 {
240 gboolean in_set = FALSE;
241 gboolean neg;
242 guint intval;
243 GString *key, *value;
244
245 key = g_string_sized_new (8);
246 value = g_string_sized_new (8);
247
248 while (*s != '\0' && !(in_set && *s == ':'))
249 {
250 while (*s != '\0' && (*s == ':' || g_ascii_isspace (*s)))
251 s++;
252
253 if (*s == '\0')
254 break;
255
256 if (strncmp (s, "set ", 4) == 0 ||
257 strncmp (s, "se ", 3) == 0)
258 {
259 s = strchr(s, ' ') + 1;
260 in_set = TRUE;
261 }
262
263 neg = FALSE;
264 if (strncmp (s, "no", 2) == 0)
265 {
266 neg = TRUE;
267 s += 2;
268 }
269
270 g_string_assign (key, "");
271 g_string_assign (value, "");
272
273 while (*s != '\0' && *s != ':' && *s != '=' &&
274 !g_ascii_isspace (*s))
275 {
276 g_string_append_c (key, *s);
277 s++;
278 }
279
280 if (*s == '=')
281 {
282 s++;
283 while (*s != '\0' && *s != ':' &&
284 !g_ascii_isspace (*s))
285 {
286 g_string_append_c (value, *s);
287 s++;
288 }
289 }
290
291 if (strcmp (key->str, "ft") == 0 ||
292 strcmp (key->str, "filetype") == 0)
293 {
294 g_free (options->language_id);
295 options->language_id = get_language_id_vim (value->str);
296
297 options->set |= MODELINE_SET_LANGUAGE;
298 }
299 else if (strcmp (key->str, "et") == 0 ||
300 strcmp (key->str, "expandtab") == 0)
301 {
302 options->insert_spaces = !neg;
303 options->set |= MODELINE_SET_INSERT_SPACES;
304 }
305 else if (strcmp (key->str, "ts") == 0 ||
306 strcmp (key->str, "tabstop") == 0)
307 {
308 intval = atoi (value->str);
309
310 if (intval)
311 {
312 options->tab_width = intval;
313 options->set |= MODELINE_SET_TAB_WIDTH;
314 }
315 }
316 else if (strcmp (key->str, "sw") == 0 ||
317 strcmp (key->str, "shiftwidth") == 0)
318 {
319 intval = atoi (value->str);
320
321 if (intval)
322 {
323 options->indent_width = intval;
324 options->set |= MODELINE_SET_INDENT_WIDTH;
325 }
326 }
327 else if (strcmp (key->str, "wrap") == 0)
328 {
329 options->wrap_mode = neg ? GTK_WRAP_NONE : GTK_WRAP_WORD;
330
331 options->set |= MODELINE_SET_WRAP_MODE;
332 }
333 else if (strcmp (key->str, "textwidth") == 0 || strcmp (key->str, "tw") == 0)
334 {
335 intval = atoi (value->str);
336
337 if (intval)
338 {
339 options->right_margin_position = intval;
340 options->display_right_margin = TRUE;
341
342 options->set |= MODELINE_SET_SHOW_RIGHT_MARGIN |
343 MODELINE_SET_RIGHT_MARGIN_POSITION;
344
345 }
346 }
347 }
348
349 g_string_free (key, TRUE);
350 g_string_free (value, TRUE);
351
352 return s;
353 }
354
355 /* Parse emacs modelines.
356 * Emacs modelines looks like this: "-*- key1: value1; key2: value2 -*-"
357 * They can happen on the first line, or on the second one if the first line is
358 * a shebang (#!)
359 * See http://www.delorie.com/gnu/docs/emacs/emacs_486.html
360 */
361 static gchar *
parse_emacs_modeline(gchar * s,ModelineOptions * options)362 parse_emacs_modeline (gchar *s,
363 ModelineOptions *options)
364 {
365 guint intval;
366 GString *key, *value;
367
368 key = g_string_sized_new (8);
369 value = g_string_sized_new (8);
370
371 while (*s != '\0')
372 {
373 while (*s != '\0' && (*s == ';' || g_ascii_isspace (*s)))
374 s++;
375 if (*s == '\0' || strncmp (s, "-*-", 3) == 0)
376 break;
377
378 g_string_assign (key, "");
379 g_string_assign (value, "");
380
381 while (*s != '\0' && *s != ':' && *s != ';' &&
382 !g_ascii_isspace (*s))
383 {
384 g_string_append_c (key, *s);
385 s++;
386 }
387
388 if (!skip_whitespaces (&s))
389 break;
390
391 if (*s != ':')
392 continue;
393 s++;
394
395 if (!skip_whitespaces (&s))
396 break;
397
398 while (*s != '\0' && *s != ';' && !g_ascii_isspace (*s))
399 {
400 g_string_append_c (value, *s);
401 s++;
402 }
403
404 xed_debug_message (DEBUG_PLUGINS,
405 "Emacs modeline bit: %s = %s",
406 key->str, value->str);
407
408 /* "Mode" key is case insenstive */
409 if (g_ascii_strcasecmp (key->str, "Mode") == 0)
410 {
411 g_free (options->language_id);
412 options->language_id = get_language_id_emacs (value->str);
413
414 options->set |= MODELINE_SET_LANGUAGE;
415 }
416 else if (strcmp (key->str, "tab-width") == 0)
417 {
418 intval = atoi (value->str);
419
420 if (intval)
421 {
422 options->tab_width = intval;
423 options->set |= MODELINE_SET_TAB_WIDTH;
424 }
425 }
426 else if (strcmp (key->str, "indent-offset") == 0)
427 {
428 intval = atoi (value->str);
429
430 if (intval)
431 {
432 options->indent_width = intval;
433 options->set |= MODELINE_SET_INDENT_WIDTH;
434 }
435 }
436 else if (strcmp (key->str, "indent-tabs-mode") == 0)
437 {
438 intval = strcmp (value->str, "nil") == 0;
439 options->insert_spaces = intval;
440
441 options->set |= MODELINE_SET_INSERT_SPACES;
442 }
443 else if (strcmp (key->str, "autowrap") == 0)
444 {
445 intval = strcmp (value->str, "nil") != 0;
446 options->wrap_mode = intval ? GTK_WRAP_WORD : GTK_WRAP_NONE;
447
448 options->set |= MODELINE_SET_WRAP_MODE;
449 }
450 }
451
452 g_string_free (key, TRUE);
453 g_string_free (value, TRUE);
454
455 return *s == '\0' ? s : s + 2;
456 }
457
458 /*
459 * Parse kate modelines.
460 * Kate modelines are of the form "kate: key1 value1; key2 value2;"
461 * These can happen on the 10 first or 10 last lines of the buffer.
462 * See http://wiki.kate-editor.org/index.php/Modelines
463 */
464 static gchar *
parse_kate_modeline(gchar * s,ModelineOptions * options)465 parse_kate_modeline (gchar *s,
466 ModelineOptions *options)
467 {
468 guint intval;
469 GString *key, *value;
470
471 key = g_string_sized_new (8);
472 value = g_string_sized_new (8);
473
474 while (*s != '\0')
475 {
476 while (*s != '\0' && (*s == ';' || g_ascii_isspace (*s)))
477 s++;
478 if (*s == '\0')
479 break;
480
481 g_string_assign (key, "");
482 g_string_assign (value, "");
483
484 while (*s != '\0' && *s != ';' && !g_ascii_isspace (*s))
485 {
486 g_string_append_c (key, *s);
487 s++;
488 }
489
490 if (!skip_whitespaces (&s))
491 break;
492 if (*s == ';')
493 continue;
494
495 while (*s != '\0' && *s != ';' &&
496 !g_ascii_isspace (*s))
497 {
498 g_string_append_c (value, *s);
499 s++;
500 }
501
502 xed_debug_message (DEBUG_PLUGINS,
503 "Kate modeline bit: %s = %s",
504 key->str, value->str);
505
506 if (strcmp (key->str, "hl") == 0 ||
507 strcmp (key->str, "syntax") == 0)
508 {
509 g_free (options->language_id);
510 options->language_id = get_language_id_kate (value->str);
511
512 options->set |= MODELINE_SET_LANGUAGE;
513 }
514 else if (strcmp (key->str, "tab-width") == 0)
515 {
516 intval = atoi (value->str);
517
518 if (intval)
519 {
520 options->tab_width = intval;
521 options->set |= MODELINE_SET_TAB_WIDTH;
522 }
523 }
524 else if (strcmp (key->str, "indent-width") == 0)
525 {
526 intval = atoi (value->str);
527 if (intval) options->indent_width = intval;
528 }
529 else if (strcmp (key->str, "space-indent") == 0)
530 {
531 intval = strcmp (value->str, "on") == 0 ||
532 strcmp (value->str, "true") == 0 ||
533 strcmp (value->str, "1") == 0;
534
535 options->insert_spaces = intval;
536 options->set |= MODELINE_SET_INSERT_SPACES;
537 }
538 else if (strcmp (key->str, "word-wrap") == 0)
539 {
540 intval = strcmp (value->str, "on") == 0 ||
541 strcmp (value->str, "true") == 0 ||
542 strcmp (value->str, "1") == 0;
543
544 options->wrap_mode = intval ? GTK_WRAP_WORD : GTK_WRAP_NONE;
545
546 options->set |= MODELINE_SET_WRAP_MODE;
547 }
548 else if (strcmp (key->str, "word-wrap-column") == 0)
549 {
550 intval = atoi (value->str);
551
552 if (intval)
553 {
554 options->right_margin_position = intval;
555 options->display_right_margin = TRUE;
556
557 options->set |= MODELINE_SET_RIGHT_MARGIN_POSITION |
558 MODELINE_SET_SHOW_RIGHT_MARGIN;
559 }
560 }
561 }
562
563 g_string_free (key, TRUE);
564 g_string_free (value, TRUE);
565
566 return s;
567 }
568
569 /* Scan a line for vi(m)/emacs/kate modelines.
570 * Line numbers are counted starting at one.
571 */
572 static void
parse_modeline(gchar * s,gint line_number,gint line_count,ModelineOptions * options)573 parse_modeline (gchar *s,
574 gint line_number,
575 gint line_count,
576 ModelineOptions *options)
577 {
578 gchar prev;
579
580 /* look for the beginning of a modeline */
581 for (prev = ' '; (s != NULL) && (*s != '\0'); prev = *(s++))
582 {
583 if (!g_ascii_isspace (prev))
584 continue;
585
586 if ((line_number <= 3 || line_number > line_count - 3) &&
587 (strncmp (s, "ex:", 3) == 0 ||
588 strncmp (s, "vi:", 3) == 0 ||
589 strncmp (s, "vim:", 4) == 0))
590 {
591 xed_debug_message (DEBUG_PLUGINS, "Vim modeline on line %d", line_number);
592
593 while (*s != ':') s++;
594 s = parse_vim_modeline (s + 1, options);
595 }
596 else if (line_number <= 2 && strncmp (s, "-*-", 3) == 0)
597 {
598 xed_debug_message (DEBUG_PLUGINS, "Emacs modeline on line %d", line_number);
599
600 s = parse_emacs_modeline (s + 3, options);
601 }
602 else if ((line_number <= 10 || line_number > line_count - 10) &&
603 strncmp (s, "kate:", 5) == 0)
604 {
605 xed_debug_message (DEBUG_PLUGINS, "Kate modeline on line %d", line_number);
606
607 s = parse_kate_modeline (s + 5, options);
608 }
609 }
610 }
611
612 static gboolean
check_previous(GtkSourceView * view,ModelineOptions * previous,ModelineSet set)613 check_previous (GtkSourceView *view,
614 ModelineOptions *previous,
615 ModelineSet set)
616 {
617 GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
618
619 /* Do not restore default when this is the first time */
620 if (!previous)
621 return FALSE;
622
623 /* Do not restore default when previous was not set */
624 if (!(previous->set & set))
625 return FALSE;
626
627 /* Only restore default when setting has not changed */
628 switch (set)
629 {
630 case MODELINE_SET_INSERT_SPACES:
631 return gtk_source_view_get_insert_spaces_instead_of_tabs (view) ==
632 previous->insert_spaces;
633 break;
634 case MODELINE_SET_TAB_WIDTH:
635 return gtk_source_view_get_tab_width (view) == previous->tab_width;
636 break;
637 case MODELINE_SET_INDENT_WIDTH:
638 return gtk_source_view_get_indent_width (view) == previous->indent_width;
639 break;
640 case MODELINE_SET_WRAP_MODE:
641 return gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view)) ==
642 previous->wrap_mode;
643 break;
644 case MODELINE_SET_RIGHT_MARGIN_POSITION:
645 return gtk_source_view_get_right_margin_position (view) ==
646 previous->right_margin_position;
647 break;
648 case MODELINE_SET_SHOW_RIGHT_MARGIN:
649 return gtk_source_view_get_show_right_margin (view) ==
650 previous->display_right_margin;
651 break;
652 case MODELINE_SET_LANGUAGE:
653 {
654 GtkSourceLanguage *language = gtk_source_buffer_get_language (buffer);
655
656 return (language == NULL && previous->language_id == NULL) ||
657 (language != NULL && g_strcmp0 (gtk_source_language_get_id (language),
658 previous->language_id) == 0);
659 }
660 break;
661 default:
662 return FALSE;
663 break;
664 }
665 }
666
667 static void
free_modeline_options(ModelineOptions * options)668 free_modeline_options (ModelineOptions *options)
669 {
670 g_free (options->language_id);
671 g_slice_free (ModelineOptions, options);
672 }
673
674 void
modeline_parser_apply_modeline(GtkSourceView * view)675 modeline_parser_apply_modeline (GtkSourceView *view)
676 {
677 ModelineOptions options;
678 GtkTextBuffer *buffer;
679 GtkTextIter iter, liter;
680 gint line_count;
681 GSettings *settings;
682
683 options.language_id = NULL;
684 options.set = MODELINE_SET_NONE;
685
686 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
687 gtk_text_buffer_get_start_iter (buffer, &iter);
688
689 line_count = gtk_text_buffer_get_line_count (buffer);
690
691 /* Parse the modelines on the 10 first lines... */
692 while ((gtk_text_iter_get_line (&iter) < 10) &&
693 !gtk_text_iter_is_end (&iter))
694 {
695 gchar *line;
696
697 liter = iter;
698 gtk_text_iter_forward_to_line_end (&iter);
699 line = gtk_text_buffer_get_text (buffer, &liter, &iter, TRUE);
700
701 parse_modeline (line,
702 1 + gtk_text_iter_get_line (&iter),
703 line_count,
704 &options);
705
706 gtk_text_iter_forward_line (&iter);
707
708 g_free (line);
709 }
710
711 /* ...and on the 10 last ones (modelines are not allowed in between) */
712 if (!gtk_text_iter_is_end (&iter))
713 {
714 gint cur_line;
715 guint remaining_lines;
716
717 /* we are on the 11th line (count from 0) */
718 cur_line = gtk_text_iter_get_line (&iter);
719 /* g_assert (10 == cur_line); */
720
721 remaining_lines = line_count - cur_line - 1;
722
723 if (remaining_lines > 10)
724 {
725 gtk_text_buffer_get_end_iter (buffer, &iter);
726 gtk_text_iter_backward_lines (&iter, 9);
727 }
728 }
729
730 while (!gtk_text_iter_is_end (&iter))
731 {
732 gchar *line;
733
734 liter = iter;
735 gtk_text_iter_forward_to_line_end (&iter);
736 line = gtk_text_buffer_get_text (buffer, &liter, &iter, TRUE);
737
738 parse_modeline (line,
739 1 + gtk_text_iter_get_line (&iter),
740 line_count,
741 &options);
742
743 gtk_text_iter_forward_line (&iter);
744
745 g_free (line);
746 }
747
748 /* Try to set language */
749 if (has_option (&options, MODELINE_SET_LANGUAGE) && options.language_id)
750 {
751 GtkSourceLanguageManager *manager;
752 GtkSourceLanguage *language;
753
754 manager = gtk_source_language_manager_get_default ();
755 language = gtk_source_language_manager_get_language
756 (manager, options.language_id);
757
758 if (language != NULL)
759 {
760 gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer),
761 language);
762 }
763 }
764
765 ModelineOptions *previous = g_object_get_data (G_OBJECT (buffer),
766 MODELINE_OPTIONS_DATA_KEY);
767
768 settings = g_settings_new ("org.x.editor.preferences.editor");
769
770 /* Apply the options we got from modelines and restore defaults if
771 we set them before */
772 if (has_option (&options, MODELINE_SET_INSERT_SPACES))
773 {
774 gtk_source_view_set_insert_spaces_instead_of_tabs
775 (view, options.insert_spaces);
776 }
777 else if (check_previous (view, previous, MODELINE_SET_INSERT_SPACES))
778 {
779 gboolean insert_spaces;
780
781 insert_spaces = g_settings_get_boolean (settings, XED_SETTINGS_INSERT_SPACES);
782 gtk_source_view_set_insert_spaces_instead_of_tabs (view, insert_spaces);
783 }
784
785 if (has_option (&options, MODELINE_SET_TAB_WIDTH))
786 {
787 gtk_source_view_set_tab_width (view, options.tab_width);
788 }
789 else if (check_previous (view, previous, MODELINE_SET_TAB_WIDTH))
790 {
791 guint tab_width;
792
793 tab_width = g_settings_get_uint (settings, XED_SETTINGS_TABS_SIZE);
794 gtk_source_view_set_tab_width (view, tab_width);
795 }
796
797 if (has_option (&options, MODELINE_SET_INDENT_WIDTH))
798 {
799 gtk_source_view_set_indent_width (view, options.indent_width);
800 }
801 else if (check_previous (view, previous, MODELINE_SET_INDENT_WIDTH))
802 {
803 gtk_source_view_set_indent_width (view, -1);
804 }
805
806 if (has_option (&options, MODELINE_SET_WRAP_MODE))
807 {
808 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), options.wrap_mode);
809 }
810 else if (check_previous (view, previous, MODELINE_SET_WRAP_MODE))
811 {
812 GtkWrapMode mode;
813
814 mode = g_settings_get_enum (settings, XED_SETTINGS_WRAP_MODE);
815 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), mode);
816 }
817
818 if (has_option (&options, MODELINE_SET_RIGHT_MARGIN_POSITION))
819 {
820 gtk_source_view_set_right_margin_position (view, options.right_margin_position);
821 }
822 else if (check_previous (view, previous, MODELINE_SET_RIGHT_MARGIN_POSITION))
823 {
824 guint right_margin_pos;
825
826 right_margin_pos = g_settings_get_uint (settings, XED_SETTINGS_RIGHT_MARGIN_POSITION);
827 gtk_source_view_set_right_margin_position (view, right_margin_pos);
828 }
829
830 if (has_option (&options, MODELINE_SET_SHOW_RIGHT_MARGIN))
831 {
832 gtk_source_view_set_show_right_margin (view, options.display_right_margin);
833 }
834 else if (check_previous (view, previous, MODELINE_SET_SHOW_RIGHT_MARGIN))
835 {
836 gboolean display_right_margin;
837
838 display_right_margin = g_settings_get_boolean (settings, XED_SETTINGS_DISPLAY_RIGHT_MARGIN);
839 gtk_source_view_set_show_right_margin (view, display_right_margin);
840 }
841
842 if (previous)
843 {
844 g_free (previous->language_id);
845 *previous = options;
846 previous->language_id = g_strdup (options.language_id);
847 }
848 else
849 {
850 previous = g_slice_new (ModelineOptions);
851 *previous = options;
852 previous->language_id = g_strdup (options.language_id);
853
854 g_object_set_data_full (G_OBJECT (buffer),
855 MODELINE_OPTIONS_DATA_KEY,
856 previous,
857 (GDestroyNotify)free_modeline_options);
858 }
859
860 g_free (options.language_id);
861 }
862
863 void
modeline_parser_deactivate(GtkSourceView * view)864 modeline_parser_deactivate (GtkSourceView *view)
865 {
866 g_object_set_data (G_OBJECT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))),
867 MODELINE_OPTIONS_DATA_KEY,
868 NULL);
869 }
870
871 /* vi:ts=8 */
872