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