]> git.sur5r.net Git - glabels/blob - glabels2/src/object-editor-text-page.c
ee4280eff5ab367775bffa5d5cc3ea8646797f48
[glabels] / glabels2 / src / object-editor-text-page.c
1 /*
2  *  object-editor-text-page.c
3  *  Copyright (C) 2003-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels 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 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "object-editor.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtktogglebutton.h>
27 #include <gtk/gtkspinbutton.h>
28 #include <gtk/gtkcombobox.h>
29 #include <math.h>
30
31 #include "prefs.h"
32 #include "color-combo.h"
33 #include "color.h"
34 #include "font-combo.h"
35 #include "font-util.h"
36 #include "util.h"
37
38 #include "object-editor-private.h"
39
40 #include "debug.h"
41
42
43 /*===========================================*/
44 /* Private macros                            */
45 /*===========================================*/
46
47
48 /*===========================================*/
49 /* Private data types                        */
50 /*===========================================*/
51
52
53 /*===========================================*/
54 /* Private globals                           */
55 /*===========================================*/
56
57
58 /*===========================================*/
59 /* Local function prototypes                 */
60 /*===========================================*/
61
62 static void align_toggle_cb (GtkToggleButton *toggle,
63                              glObjectEditor  *editor);
64 static void text_radio_toggled_cb              (glObjectEditor        *editor);
65
66
67 /*--------------------------------------------------------------------------*/
68 /* PRIVATE.  Prepare size page.                                             */
69 /*--------------------------------------------------------------------------*/
70 void
71 gl_object_editor_prepare_text_page (glObjectEditor       *editor)
72 {
73         GList        *family_names = NULL;
74
75         gl_debug (DEBUG_EDITOR, "START");
76
77         /* Extract widgets from XML tree. */
78         gl_util_get_builder_widgets (editor->priv->builder,
79                                      "text_page_vbox",         &editor->priv->text_page_vbox,
80                                      "text_family_hbox",       &editor->priv->text_family_hbox,
81                                      "text_size_spin",         &editor->priv->text_size_spin,
82                                      "text_bold_toggle",       &editor->priv->text_bold_toggle,
83                                      "text_italic_toggle",     &editor->priv->text_italic_toggle,
84                                      "text_color_hbox",        &editor->priv->text_color_hbox,
85                                      "text_color_radio",       &editor->priv->text_color_radio,
86                                      "text_color_key_radio",   &editor->priv->text_color_key_radio,
87                                      "text_color_key_combo",   &editor->priv->text_color_key_combo,
88                                      "text_left_toggle",       &editor->priv->text_left_toggle,
89                                      "text_center_toggle",     &editor->priv->text_center_toggle,
90                                      "text_right_toggle",      &editor->priv->text_right_toggle,
91                                      "text_line_spacing_spin", &editor->priv->text_line_spacing_spin,
92                                      "text_auto_shrink_check", &editor->priv->text_auto_shrink_check,
93                                      NULL);
94
95         editor->priv->text_family_combo = gl_font_combo_new ("Sans");
96         gtk_box_pack_start (GTK_BOX (editor->priv->text_family_hbox),
97                             editor->priv->text_family_combo,
98                             TRUE, TRUE, 0);
99
100         editor->priv->text_color_combo = gl_color_combo_new (_("Default"),
101                                                              GL_COLOR_TEXT_DEFAULT,
102                                                              gl_prefs->default_text_color);
103         gtk_box_pack_start (GTK_BOX (editor->priv->text_color_hbox),
104                             editor->priv->text_color_combo,
105                             FALSE, FALSE, 0);
106
107         gl_util_combo_box_add_text_model ( GTK_COMBO_BOX(editor->priv->text_color_key_combo));
108
109         /* Modify widgets */
110         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_color_radio), TRUE);
111         gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
112         gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
113
114         /* Un-hide */
115         gtk_widget_show_all (editor->priv->text_page_vbox);
116
117         /* Connect signals */
118         g_signal_connect_swapped (G_OBJECT (editor->priv->text_family_combo),
119                                   "changed",
120                                   G_CALLBACK (gl_object_editor_changed_cb),
121                                   G_OBJECT (editor));
122         g_signal_connect_swapped (G_OBJECT (editor->priv->text_size_spin),
123                                   "changed",
124                                   G_CALLBACK (gl_object_editor_changed_cb),
125                                   G_OBJECT (editor));
126         g_signal_connect_swapped (G_OBJECT (editor->priv->text_bold_toggle),
127                                   "toggled",
128                                   G_CALLBACK (gl_object_editor_changed_cb),
129                                   G_OBJECT (editor));
130         g_signal_connect_swapped (G_OBJECT (editor->priv->text_italic_toggle),
131                                   "toggled",
132                                   G_CALLBACK (gl_object_editor_changed_cb),
133                                   G_OBJECT (editor));
134         g_signal_connect_swapped (G_OBJECT (editor->priv->text_color_combo),
135                                   "color_changed",
136                                   G_CALLBACK (gl_object_editor_changed_cb),
137                                   G_OBJECT (editor));
138         g_signal_connect_swapped (G_OBJECT (editor->priv->text_color_key_combo),
139                                   "changed",
140                                   G_CALLBACK (gl_object_editor_changed_cb),
141                                   G_OBJECT (editor));
142         g_signal_connect_swapped (G_OBJECT (editor->priv->text_color_radio),
143                                   "toggled",
144                                   G_CALLBACK (text_radio_toggled_cb),
145                                   G_OBJECT (editor));                             
146         g_signal_connect_swapped (G_OBJECT (editor->priv->text_color_key_radio),
147                                   "toggled",
148                                   G_CALLBACK (text_radio_toggled_cb),
149                                   G_OBJECT (editor));
150
151         g_signal_connect (G_OBJECT (editor->priv->text_left_toggle),
152                           "toggled",
153                           G_CALLBACK (align_toggle_cb),
154                           G_OBJECT (editor));
155         g_signal_connect (G_OBJECT (editor->priv->text_center_toggle),
156                           "toggled",
157                           G_CALLBACK (align_toggle_cb),
158                           G_OBJECT (editor));
159         g_signal_connect (G_OBJECT (editor->priv->text_right_toggle),
160                           "toggled",
161                           G_CALLBACK (align_toggle_cb),
162                           G_OBJECT (editor));
163
164         g_signal_connect_swapped (G_OBJECT (editor->priv->text_line_spacing_spin),
165                                   "changed",
166                                   G_CALLBACK (gl_object_editor_changed_cb),
167                                   G_OBJECT (editor));
168
169         g_signal_connect_swapped (G_OBJECT (editor->priv->text_auto_shrink_check),
170                                   "toggled",
171                                   G_CALLBACK (gl_object_editor_changed_cb),
172                                   G_OBJECT (editor));
173
174         gl_debug (DEBUG_EDITOR, "END");
175 }
176
177
178 /*--------------------------------------------------------------------------*/
179 /* PRIVATE.  Alignment togglebutton callback.                               */
180 /*--------------------------------------------------------------------------*/
181 static void
182 align_toggle_cb (GtkToggleButton *toggle,
183                  glObjectEditor  *editor)
184 {
185         if (editor->priv->stop_signals) return;
186
187         if (gtk_toggle_button_get_active (toggle)) {
188  
189                 if (GTK_WIDGET (toggle) == GTK_WIDGET (editor->priv->text_left_toggle)) {
190                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
191                                                       (editor->priv->text_center_toggle),
192                                                       FALSE);
193                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
194                                                       (editor->priv->text_right_toggle),
195                                                       FALSE);
196                 } else if (GTK_WIDGET (toggle) ==
197                            GTK_WIDGET (editor->priv->text_center_toggle)) {
198                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
199                                                       (editor->priv->text_left_toggle),
200                                                       FALSE);
201                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
202                                                       (editor->priv->text_right_toggle),
203                                                       FALSE);
204                 } else if (GTK_WIDGET (toggle) ==
205                            GTK_WIDGET (editor->priv->text_right_toggle)) {
206                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
207                                                       (editor->priv->text_left_toggle),
208                                                       FALSE);
209                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
210                                                       (editor->priv->text_center_toggle),
211                                                       FALSE);
212                 }
213
214                 /* Emit our "changed" signal */
215                 g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
216         }
217
218 }
219
220
221 /*****************************************************************************/
222 /* Set font family.                                                          */
223 /*****************************************************************************/
224 void
225 gl_object_editor_set_font_family (glObjectEditor      *editor,
226                                   const gchar         *font_family)
227 {
228         GList    *family_names;
229         gchar    *old_font_family;
230         gchar    *good_font_family;
231
232         gl_debug (DEBUG_EDITOR, "START");
233
234         editor->priv->stop_signals = TRUE;
235
236         old_font_family = gl_font_combo_get_family (GL_FONT_COMBO (editor->priv->text_family_combo));
237
238         if ( !old_font_family || g_utf8_collate( old_font_family, font_family ) )
239         {
240
241                 /* Make sure we have a valid font family.  if not provide a good default. */
242                 family_names = gl_font_util_get_all_families ();
243                 if (g_list_find_custom (family_names, font_family, (GCompareFunc)g_utf8_collate)) {
244                         good_font_family = g_strdup (font_family);
245                 } else {
246                         if (family_names != NULL) {
247                                 good_font_family = g_strdup (family_names->data); /* 1st entry */
248                         } else {
249                                 good_font_family = NULL;
250                         }
251                 }
252                 gl_font_combo_set_family (GL_FONT_COMBO (editor->priv->text_family_combo), good_font_family);
253                 g_free (good_font_family);
254         }
255
256         g_free (old_font_family);
257
258         editor->priv->stop_signals = FALSE;
259
260         gl_debug (DEBUG_EDITOR, "END");
261 }
262
263
264 /*****************************************************************************/
265 /* Query font family.                                                        */
266 /*****************************************************************************/
267 gchar *
268 gl_object_editor_get_font_family (glObjectEditor      *editor)
269 {
270         gchar *font_family;
271
272         gl_debug (DEBUG_EDITOR, "START");
273
274         font_family = gl_font_combo_get_family (GL_FONT_COMBO (editor->priv->text_family_combo));
275
276         gl_debug (DEBUG_EDITOR, "END");
277
278         return font_family;
279 }
280
281
282 /*****************************************************************************/
283 /* Set font size.                                                            */
284 /*****************************************************************************/
285 void
286 gl_object_editor_set_font_size (glObjectEditor      *editor,
287                                 gdouble              font_size)
288 {
289         gl_debug (DEBUG_EDITOR, "START");
290
291         editor->priv->stop_signals = TRUE;
292
293         gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->text_size_spin),
294                                    font_size);
295
296         editor->priv->stop_signals = FALSE;
297
298         gl_debug (DEBUG_EDITOR, "END");
299 }
300
301
302 /*****************************************************************************/
303 /* Query font size.                                                          */
304 /*****************************************************************************/
305 gdouble
306 gl_object_editor_get_font_size (glObjectEditor      *editor)
307 {
308         gdouble font_size;
309
310         gl_debug (DEBUG_EDITOR, "START");
311
312         font_size =
313                 gtk_spin_button_get_value (GTK_SPIN_BUTTON(editor->priv->text_size_spin));
314
315         gl_debug (DEBUG_EDITOR, "END");
316
317         return font_size;
318 }
319
320
321 /*****************************************************************************/
322 /* Set font weight.                                                          */
323 /*****************************************************************************/
324 void
325 gl_object_editor_set_font_weight (glObjectEditor      *editor,
326                                   PangoWeight          font_weight)
327 {
328         gl_debug (DEBUG_EDITOR, "START");
329
330         editor->priv->stop_signals = TRUE;
331
332         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_bold_toggle),
333                                       (font_weight == PANGO_WEIGHT_BOLD));
334
335         editor->priv->stop_signals = FALSE;
336
337         gl_debug (DEBUG_EDITOR, "END");
338 }
339
340
341 /*****************************************************************************/
342 /* Query font weight.                                                        */
343 /*****************************************************************************/
344 PangoWeight
345 gl_object_editor_get_font_weight (glObjectEditor      *editor)
346 {
347         PangoWeight font_weight;
348
349         gl_debug (DEBUG_EDITOR, "START");
350
351         if (gtk_toggle_button_get_active
352             (GTK_TOGGLE_BUTTON (editor->priv->text_bold_toggle))) {
353                 font_weight = PANGO_WEIGHT_BOLD;
354         } else {
355                 font_weight = PANGO_WEIGHT_NORMAL;
356         }
357
358         gl_debug (DEBUG_EDITOR, "END");
359
360         return font_weight;
361 }
362
363
364 /*****************************************************************************/
365 /* Set font italic flag.                                                     */
366 /*****************************************************************************/
367 void
368 gl_object_editor_set_font_italic_flag (glObjectEditor      *editor,
369                                        gboolean             font_italic_flag)
370 {
371         gl_debug (DEBUG_EDITOR, "START");
372
373         editor->priv->stop_signals = TRUE;
374
375         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_italic_toggle),
376                                       font_italic_flag);
377
378         editor->priv->stop_signals = FALSE;
379
380         gl_debug (DEBUG_EDITOR, "END");
381 }
382
383
384 /*****************************************************************************/
385 /* Query font italic flag.                                                   */
386 /*****************************************************************************/
387 gboolean
388 gl_object_editor_get_font_italic_flag (glObjectEditor      *editor)
389 {
390         gboolean italic_flag;
391
392         gl_debug (DEBUG_EDITOR, "START");
393
394         italic_flag =
395                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
396                                               (editor->priv->text_italic_toggle));
397
398         gl_debug (DEBUG_EDITOR, "END");
399
400         return italic_flag;
401 }
402
403
404 /*****************************************************************************/
405 /* Set text alignment.                                                       */
406 /*****************************************************************************/
407 void
408 gl_object_editor_set_text_alignment (glObjectEditor      *editor,
409                                      PangoAlignment       align)
410 {
411         gl_debug (DEBUG_EDITOR, "START");
412
413         editor->priv->stop_signals = TRUE;
414
415         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_left_toggle),
416                                       (align == PANGO_ALIGN_LEFT));
417         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_center_toggle),
418                                       (align == PANGO_ALIGN_CENTER));
419         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_right_toggle),
420                                       (align == PANGO_ALIGN_RIGHT));
421
422         editor->priv->stop_signals = FALSE;
423
424         gl_debug (DEBUG_EDITOR, "END");
425 }
426
427
428 /*****************************************************************************/
429 /* Query text alignment.                                                     */
430 /*****************************************************************************/
431 PangoAlignment
432 gl_object_editor_get_text_alignment (glObjectEditor      *editor)
433 {
434         PangoAlignment align;
435
436         gl_debug (DEBUG_EDITOR, "START");
437
438         if (gtk_toggle_button_get_active
439             (GTK_TOGGLE_BUTTON (editor->priv->text_left_toggle))) {
440                 align = PANGO_ALIGN_LEFT;
441         } else
442             if (gtk_toggle_button_get_active
443                 (GTK_TOGGLE_BUTTON (editor->priv->text_right_toggle))) {
444                 align = PANGO_ALIGN_RIGHT;
445         } else
446             if (gtk_toggle_button_get_active
447                 (GTK_TOGGLE_BUTTON (editor->priv->text_center_toggle))) {
448                 align = PANGO_ALIGN_CENTER;
449         } else {
450                 align = PANGO_ALIGN_LEFT;       /* Should not happen. */
451         }
452
453         gl_debug (DEBUG_EDITOR, "END");
454
455         return align;
456 }
457
458
459 /*****************************************************************************/
460 /* Set text color.                                                           */
461 /*****************************************************************************/
462 void
463 gl_object_editor_set_text_color (glObjectEditor      *editor,
464                                  gboolean             merge_flag,
465                                  glColorNode         *text_color_node)
466 {
467         gl_debug (DEBUG_EDITOR, "START");
468
469         editor->priv->stop_signals = TRUE;
470
471         gl_debug (DEBUG_EDITOR, "color field %s(%d) / %X", text_color_node->key, text_color_node->field_flag, text_color_node->color);
472         
473         gtk_widget_set_sensitive (editor->priv->text_color_key_radio, merge_flag);
474
475         if ( text_color_node->color == GL_COLOR_NONE ) {
476
477                 gl_color_combo_set_to_default (GL_COLOR_COMBO(editor->priv->text_color_combo));
478
479         } else {
480                 
481                 gl_color_combo_set_color (GL_COLOR_COMBO(editor->priv->text_color_combo),
482                                           text_color_node->color);
483         }
484         
485         if (!text_color_node->field_flag) {
486                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
487                                                   (editor->priv->text_color_radio), TRUE); 
488                 gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
489                 gl_debug (DEBUG_EDITOR, "color field false 0");
490                 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
491                 
492         } else {
493                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
494                                                   (editor->priv->text_color_key_radio), TRUE); 
495                 gtk_widget_set_sensitive (editor->priv->text_color_combo, FALSE);
496                 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, TRUE);
497                 
498                 gl_debug (DEBUG_EDITOR, "color field true 1");
499                 gl_util_combo_box_set_active_text (GTK_COMBO_BOX (editor->priv->text_color_key_combo), "");
500                 gl_debug (DEBUG_EDITOR, "color field true 2");
501         }
502
503         editor->priv->stop_signals = FALSE;
504
505         gl_debug (DEBUG_EDITOR, "END");
506 }
507
508
509 /*****************************************************************************/
510 /* Query text color.                                                         */
511 /*****************************************************************************/
512 glColorNode*
513 gl_object_editor_get_text_color (glObjectEditor      *editor)
514 {
515         guint        color;
516         glColorNode *color_node;
517         gboolean     is_default;
518
519         gl_debug (DEBUG_EDITOR, "START");
520
521         color_node = gl_color_node_new_default ();
522         
523         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->priv->text_color_key_radio))) {
524                 color_node->field_flag = TRUE;
525                 color_node->color = gl_prefs->default_text_color;
526                 color_node->key = 
527                         gtk_combo_box_get_active_text (GTK_COMBO_BOX (editor->priv->text_color_key_combo));
528         } else {
529                 color_node->field_flag = FALSE;
530                 color_node->key = NULL;
531                 color = gl_color_combo_get_color (GL_COLOR_COMBO(editor->priv->text_color_combo),
532                                                   &is_default);
533
534                 if (is_default) {
535                         color_node->color = gl_prefs->default_text_color;
536                 } else {
537                         color_node->color = color;
538                 }
539         }      
540
541         gl_debug (DEBUG_EDITOR, "END");
542
543         return color_node;
544 }
545
546
547 /*****************************************************************************/
548 /* Set text line spacing.                                                    */
549 /*****************************************************************************/
550 void
551 gl_object_editor_set_text_line_spacing (glObjectEditor      *editor,
552                                         gdouble              text_line_spacing)
553 {
554         gl_debug (DEBUG_EDITOR, "START");
555
556         editor->priv->stop_signals = TRUE;
557
558         gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->priv->text_line_spacing_spin),
559                                    text_line_spacing);
560
561         editor->priv->stop_signals = FALSE;
562
563         gl_debug (DEBUG_EDITOR, "END");
564 }
565
566
567 /*****************************************************************************/
568 /* Query text line spacing.                                                  */
569 /*****************************************************************************/
570 gdouble
571 gl_object_editor_get_text_line_spacing (glObjectEditor      *editor)
572 {
573         gdouble text_line_spacing;
574
575         gl_debug (DEBUG_EDITOR, "START");
576
577         text_line_spacing = 
578                 gtk_spin_button_get_value (GTK_SPIN_BUTTON(editor->priv->text_line_spacing_spin));
579
580         gl_debug (DEBUG_EDITOR, "END");
581
582         return text_line_spacing;
583 }
584
585
586 /*****************************************************************************/
587 /* Set auto shrink checkbox.                                                 */
588 /*****************************************************************************/
589 void
590 gl_object_editor_set_text_auto_shrink (glObjectEditor      *editor,
591                                        gboolean             auto_shrink)
592 {
593         gl_debug (DEBUG_EDITOR, "START");
594
595         editor->priv->stop_signals = TRUE;
596
597         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->text_auto_shrink_check),
598                                       auto_shrink);
599
600         editor->priv->stop_signals = FALSE;
601
602         gl_debug (DEBUG_EDITOR, "END");
603 }
604
605
606 /*****************************************************************************/
607 /* Query auto shrink checkbox.                                               */
608 /*****************************************************************************/
609 gboolean    gl_object_editor_get_text_auto_shrink (glObjectEditor      *editor)
610 {
611         gboolean auto_shrink;
612
613         gl_debug (DEBUG_EDITOR, "START");
614
615         auto_shrink = 
616                 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->priv->text_auto_shrink_check));
617
618         gl_debug (DEBUG_EDITOR, "END");
619
620         return auto_shrink;
621 }
622
623
624 /*--------------------------------------------------------------------------*/
625 /* PRIVATE.  color radio callback.                                           */
626 /*--------------------------------------------------------------------------*/
627 static void
628 text_radio_toggled_cb (glObjectEditor *editor)
629 {
630         if (editor->priv->stop_signals) return;
631
632         gl_debug (DEBUG_EDITOR, "START");
633         
634         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->priv->text_color_radio))) {
635                 gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
636                 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
637         } else {
638                 gtk_widget_set_sensitive (editor->priv->text_color_combo, FALSE);
639                 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, TRUE);
640                 
641         }
642  
643         /* Emit our "changed" signal */
644         g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
645  
646         gl_debug (DEBUG_EDITOR, "END");
647 }
648
649
650
651 /*
652  * Local Variables:       -- emacs
653  * mode: C                -- emacs
654  * c-basic-offset: 8      -- emacs
655  * tab-width: 8           -- emacs
656  * indent-tabs-mode: nil  -- emacs
657  * End:                   -- emacs
658  */