8 #include <gdk/gdkkeysyms.h>
10 typedef struct _Buffer Buffer;
11 typedef struct _View View;
13 static gint untitled_serial = 1;
15 GSList *active_window_stack = NULL;
20 GtkTextBuffer *buffer;
23 GtkTextTag *invisible_tag;
24 GtkTextTag *not_editable_tag;
25 GtkTextTag *found_text_tag;
26 GtkTextTag *custom_tabs_tag;
28 guint color_cycle_timeout;
36 GtkAccelGroup *accel_group;
37 GtkItemFactory *item_factory;
41 static void push_active_window (GtkWindow *window);
42 static void pop_active_window (void);
43 static GtkWindow *get_active_window (void);
45 static Buffer * create_buffer (void);
46 static gboolean check_buffer_saved (Buffer *buffer);
47 static gboolean save_buffer (Buffer *buffer);
48 static gboolean save_as_buffer (Buffer *buffer);
49 static char * buffer_pretty_name (Buffer *buffer);
50 static void buffer_filename_set (Buffer *buffer);
51 static void buffer_search_forward (Buffer *buffer,
54 static void buffer_search_backward (Buffer *buffer,
57 static void buffer_set_colors (Buffer *buffer,
59 static void buffer_cycle_colors (Buffer *buffer);
61 static View *view_from_widget (GtkWidget *widget);
63 static View *create_view (Buffer *buffer);
64 static void check_close_view (View *view);
65 static void close_view (View *view);
66 static void view_set_title (View *view);
67 static void view_init_menus (View *view);
69 GSList *buffers = NULL;
73 push_active_window (GtkWindow *window)
75 gtk_object_ref (GTK_OBJECT (window));
76 active_window_stack = g_slist_prepend (active_window_stack, window);
80 pop_active_window (void)
82 gtk_object_unref (active_window_stack->data);
83 active_window_stack = g_slist_delete_link (active_window_stack, active_window_stack);
87 get_active_window (void)
89 if (active_window_stack)
90 return active_window_stack->data;
96 * Filesel utility function
99 typedef gboolean (*FileselOKFunc) (const char *filename, gpointer data);
102 filesel_ok_cb (GtkWidget *button, GtkWidget *filesel)
104 FileselOKFunc ok_func = gtk_object_get_data (GTK_OBJECT (filesel), "ok-func");
105 gpointer data = gtk_object_get_data (GTK_OBJECT (filesel), "ok-data");
106 gint *result = gtk_object_get_data (GTK_OBJECT (filesel), "ok-result");
108 gtk_widget_hide (filesel);
110 if ((*ok_func) (gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel)), data))
112 gtk_widget_destroy (filesel);
116 gtk_widget_show (filesel);
120 filesel_run (GtkWindow *parent,
122 const char *start_file,
126 GtkWidget *filesel = gtk_file_selection_new (title);
127 gboolean result = FALSE;
130 parent = get_active_window ();
133 gtk_window_set_transient_for (GTK_WINDOW (filesel), parent);
136 gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel), start_file);
139 gtk_object_set_data (GTK_OBJECT (filesel), "ok-func", func);
140 gtk_object_set_data (GTK_OBJECT (filesel), "ok-data", data);
141 gtk_object_set_data (GTK_OBJECT (filesel), "ok-result", &result);
143 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
145 GTK_SIGNAL_FUNC (filesel_ok_cb), filesel);
146 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
148 GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel));
150 gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
151 GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
152 gtk_window_set_modal (GTK_WINDOW (filesel), TRUE);
154 gtk_widget_show (filesel);
161 * MsgBox utility functions
165 msgbox_yes_cb (GtkWidget *widget, gboolean *result)
168 gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
172 msgbox_no_cb (GtkWidget *widget, gboolean *result)
175 gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
179 msgbox_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
181 if (event->keyval == GDK_Escape)
183 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
184 gtk_object_destroy (GTK_OBJECT (widget));
192 msgbox_run (GtkWindow *parent,
194 const char *yes_button,
195 const char *no_button,
196 const char *cancel_button,
199 gboolean result = -1;
204 GtkWidget *button_box;
205 GtkWidget *separator;
207 g_return_val_if_fail (message != NULL, FALSE);
208 g_return_val_if_fail (default_index >= 0 && default_index <= 1, FALSE);
211 parent = get_active_window ();
215 dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
216 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
218 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
219 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
221 /* Quit our recursive main loop when the dialog is destroyed.
223 gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
224 GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
226 /* Catch Escape key presses and have them destroy the dialog
228 gtk_signal_connect (GTK_OBJECT (dialog), "key_press_event",
229 GTK_SIGNAL_FUNC (msgbox_key_press_cb), NULL);
231 /* Fill in the contents of the widget
233 vbox = gtk_vbox_new (FALSE, 0);
234 gtk_container_add (GTK_CONTAINER (dialog), vbox);
236 label = gtk_label_new (message);
237 gtk_misc_set_padding (GTK_MISC (label), 12, 12);
238 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
239 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
241 separator = gtk_hseparator_new ();
242 gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
244 button_box = gtk_hbutton_box_new ();
245 gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0);
246 gtk_container_set_border_width (GTK_CONTAINER (button_box), 8);
249 /* When Yes is clicked, call the msgbox_yes_cb
250 * This sets the result variable and destroys the dialog
254 button = gtk_button_new_with_label (yes_button);
255 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
256 gtk_container_add (GTK_CONTAINER (button_box), button);
258 if (default_index == 0)
259 gtk_widget_grab_default (button);
261 gtk_signal_connect (GTK_OBJECT (button), "clicked",
262 GTK_SIGNAL_FUNC (msgbox_yes_cb), &result);
265 /* When No is clicked, call the msgbox_no_cb
266 * This sets the result variable and destroys the dialog
270 button = gtk_button_new_with_label (no_button);
271 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
272 gtk_container_add (GTK_CONTAINER (button_box), button);
274 if (default_index == 0)
275 gtk_widget_grab_default (button);
277 gtk_signal_connect (GTK_OBJECT (button), "clicked",
278 GTK_SIGNAL_FUNC (msgbox_no_cb), &result);
281 /* When Cancel is clicked, destroy the dialog
285 button = gtk_button_new_with_label (cancel_button);
286 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
287 gtk_container_add (GTK_CONTAINER (button_box), button);
289 if (default_index == 1)
290 gtk_widget_grab_default (button);
292 gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
293 GTK_SIGNAL_FUNC (gtk_object_destroy), GTK_OBJECT (dialog));
296 gtk_widget_show_all (dialog);
298 /* Run a recursive main loop until a button is clicked
299 * or the user destroys the dialog through the window mananger */
306 * Example buffer filling code
309 blink_timeout (gpointer data)
312 static gboolean flip = FALSE;
314 tag = GTK_TEXT_TAG (data);
316 gtk_object_set (GTK_OBJECT (tag),
317 "foreground", flip ? "blue" : "purple",
326 tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event,
327 const GtkTextIter *iter, gpointer user_data)
331 char_index = gtk_text_iter_get_offset (iter);
335 case GDK_MOTION_NOTIFY:
336 printf ("Motion event at char %d tag `%s'\n",
337 char_index, tag->name);
340 case GDK_BUTTON_PRESS:
341 printf ("Button press at char %d tag `%s'\n",
342 char_index, tag->name);
345 case GDK_2BUTTON_PRESS:
346 printf ("Double click at char %d tag `%s'\n",
347 char_index, tag->name);
350 case GDK_3BUTTON_PRESS:
351 printf ("Triple click at char %d tag `%s'\n",
352 char_index, tag->name);
355 case GDK_BUTTON_RELEASE:
356 printf ("Button release at char %d tag `%s'\n",
357 char_index, tag->name);
361 case GDK_KEY_RELEASE:
362 printf ("Key event at char %d tag `%s'\n",
363 char_index, tag->name);
366 case GDK_ENTER_NOTIFY:
367 case GDK_LEAVE_NOTIFY:
368 case GDK_PROPERTY_NOTIFY:
369 case GDK_SELECTION_CLEAR:
370 case GDK_SELECTION_REQUEST:
371 case GDK_SELECTION_NOTIFY:
372 case GDK_PROXIMITY_IN:
373 case GDK_PROXIMITY_OUT:
376 case GDK_DRAG_MOTION:
377 case GDK_DRAG_STATUS:
379 case GDK_DROP_FINISHED:
388 setup_tag (GtkTextTag *tag)
391 gtk_signal_connect (GTK_OBJECT (tag),
393 GTK_SIGNAL_FUNC (tag_event_handler),
397 static char *book_closed_xpm[] = {
425 fill_example_buffer (GtkTextBuffer *buffer)
427 GtkTextIter iter, iter2;
435 /* FIXME this is broken if called twice on a buffer, since
436 * we try to create tags a second time.
439 tag = gtk_text_buffer_create_tag (buffer, "fg_blue");
441 /* gtk_timeout_add (1000, blink_timeout, tag); */
445 color.red = color.green = 0;
450 gtk_object_set (GTK_OBJECT (tag),
451 "foreground_gdk", &color,
452 "background_gdk", &color2,
456 tag = gtk_text_buffer_create_tag (buffer, "fg_red");
460 color.blue = color.green = 0;
462 gtk_object_set (GTK_OBJECT (tag),
463 "rise", -4 * PANGO_SCALE,
464 "foreground_gdk", &color,
467 tag = gtk_text_buffer_create_tag (buffer, "bg_green");
471 color.blue = color.red = 0;
472 color.green = 0xffff;
473 gtk_object_set (GTK_OBJECT (tag),
474 "background_gdk", &color,
478 tag = gtk_text_buffer_create_tag (buffer, "strikethrough");
482 gtk_object_set (GTK_OBJECT (tag),
483 "strikethrough", TRUE,
487 tag = gtk_text_buffer_create_tag (buffer, "underline");
491 gtk_object_set (GTK_OBJECT (tag),
492 "underline", PANGO_UNDERLINE_SINGLE,
497 gtk_object_set (GTK_OBJECT (tag),
498 "underline", PANGO_UNDERLINE_SINGLE,
501 tag = gtk_text_buffer_create_tag (buffer, "centered");
503 gtk_object_set (GTK_OBJECT (tag),
504 "justify", GTK_JUSTIFY_CENTER,
507 tag = gtk_text_buffer_create_tag (buffer, "rtl_quote");
509 gtk_object_set (GTK_OBJECT (tag),
510 "wrap_mode", GTK_WRAPMODE_WORD,
511 "direction", GTK_TEXT_DIR_RTL,
517 pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
522 GtkTextMark * temp_mark;
524 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
526 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
528 str = g_strdup_printf ("%d Hello World! blah blah blah blah blah blah blah blah blah blah blah blah\nwoo woo woo woo woo woo woo woo woo woo woo woo woo woo woo\n",
531 gtk_text_buffer_insert (buffer, &iter, str, -1);
535 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 5);
537 gtk_text_buffer_insert (buffer, &iter,
538 "(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line with a significant quantity of text on it. This line really does contain some text. More text! More text! More text!\n"
539 /* This is UTF8 stuff, Emacs doesn't
540 really know how to display it */
541 "German (Deutsch Süd) Grüß Gott Greek (Ελληνικά) Γειά σας Hebrew שלום Japanese (日本語)\n", -1);
544 gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
547 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 6);
548 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 0, 13);
550 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
552 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 10);
553 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 16);
555 gtk_text_buffer_apply_tag_by_name (buffer, "underline", &iter, &iter2);
557 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 14);
558 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 24);
560 gtk_text_buffer_apply_tag_by_name (buffer, "strikethrough", &iter, &iter2);
562 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 9);
563 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 0, 16);
565 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
567 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 4, 2);
568 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 4, 10);
570 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
572 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 4, 8);
573 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 4, 15);
575 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
578 gtk_text_buffer_get_iter_at_mark (buffer, &iter, temp_mark);
579 gtk_text_buffer_insert (buffer, &iter, "Centered text!\n", -1);
581 gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
582 gtk_text_buffer_apply_tag_by_name (buffer, "centered", &iter2, &iter);
584 gtk_text_buffer_move_mark (buffer, temp_mark, &iter);
585 gtk_text_buffer_insert (buffer, &iter, "Word wrapped, Right-to-left Quote\n", -1);
586 gtk_text_buffer_insert (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n", -1);
587 gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
588 gtk_text_buffer_apply_tag_by_name (buffer, "rtl_quote", &iter2, &iter);
593 g_object_unref (G_OBJECT (pixbuf));
595 printf ("%d lines %d chars\n",
596 gtk_text_buffer_get_line_count (buffer),
597 gtk_text_buffer_get_char_count (buffer));
599 /* Move cursor to start */
600 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
601 gtk_text_buffer_place_cursor (buffer, &iter);
603 gtk_text_buffer_set_modified (buffer, FALSE);
607 fill_file_buffer (GtkTextBuffer *buffer, const char *filename)
612 GtkTextIter iter, end;
614 f = fopen (filename, "r");
618 gchar *err = g_strdup_printf ("Cannot open file '%s': %s",
619 filename, g_strerror (errno));
620 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
625 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
629 char *leftover, *next;
630 int to_read = 2047 - remaining;
632 count = fread (buf + remaining, 1, to_read, f);
633 buf[count + remaining] = '\0';
635 leftover = next = buf;
642 next = g_utf8_next_char (next);
643 if (next > buf+count+remaining) {
649 gtk_text_buffer_insert (buffer, &iter, buf, leftover - buf);
651 remaining = buf + remaining + count - leftover;
652 g_memmove (buf, leftover, remaining);
654 if (remaining > 6 || count < to_read)
660 gchar *err = g_strdup_printf ("Invalid UTF-8 data encountered reading file '%s'", filename);
661 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
665 /* We had a newline in the buffer to begin with. (The buffer always contains
666 * a newline, so we delete to the end of the buffer to clean up.
668 gtk_text_buffer_get_last_iter (buffer, &end);
669 gtk_text_buffer_delete (buffer, &iter, &end);
671 gtk_text_buffer_set_modified (buffer, FALSE);
677 delete_event_cb (GtkWidget *window, GdkEventAny *event, gpointer data)
679 View *view = view_from_widget (window);
681 push_active_window (GTK_WINDOW (window));
682 check_close_view (view);
683 pop_active_window ();
693 get_empty_view (View *view)
695 if (!view->buffer->filename &&
696 !gtk_text_buffer_modified (view->buffer->buffer))
699 return create_view (create_buffer ());
703 view_from_widget (GtkWidget *widget)
707 if (GTK_IS_MENU_ITEM (widget))
709 GtkItemFactory *item_factory = gtk_item_factory_from_widget (widget);
710 return gtk_object_get_data (GTK_OBJECT (item_factory), "view");
714 GtkWidget *app = gtk_widget_get_toplevel (widget);
715 return gtk_object_get_data (GTK_OBJECT (app), "view");
720 do_new (gpointer callback_data,
721 guint callback_action,
724 create_view (create_buffer ());
728 do_new_view (gpointer callback_data,
729 guint callback_action,
732 View *view = view_from_widget (widget);
734 create_view (view->buffer);
738 open_ok_func (const char *filename, gpointer data)
741 View *new_view = get_empty_view (view);
743 if (!fill_file_buffer (new_view->buffer->buffer, filename))
745 if (new_view != view)
746 close_view (new_view);
751 g_free (new_view->buffer->filename);
752 new_view->buffer->filename = g_strdup (filename);
753 buffer_filename_set (new_view->buffer);
760 do_open (gpointer callback_data,
761 guint callback_action,
764 View *view = view_from_widget (widget);
766 push_active_window (GTK_WINDOW (view->window));
767 filesel_run (NULL, "Open File", NULL, open_ok_func, view);
768 pop_active_window ();
772 do_save_as (gpointer callback_data,
773 guint callback_action,
776 View *view = view_from_widget (widget);
778 push_active_window (GTK_WINDOW (view->window));
779 save_as_buffer (view->buffer);
780 pop_active_window ();
784 do_save (gpointer callback_data,
785 guint callback_action,
788 View *view = view_from_widget (widget);
790 push_active_window (GTK_WINDOW (view->window));
791 if (!view->buffer->filename)
792 do_save_as (callback_data, callback_action, widget);
794 save_buffer (view->buffer);
795 pop_active_window ();
799 do_close (gpointer callback_data,
800 guint callback_action,
803 View *view = view_from_widget (widget);
805 push_active_window (GTK_WINDOW (view->window));
806 check_close_view (view);
807 pop_active_window ();
811 do_exit (gpointer callback_data,
812 guint callback_action,
815 View *view = view_from_widget (widget);
817 GSList *tmp_list = buffers;
819 push_active_window (GTK_WINDOW (view->window));
822 if (!check_buffer_saved (tmp_list->data))
825 tmp_list = tmp_list->next;
829 pop_active_window ();
833 do_example (gpointer callback_data,
834 guint callback_action,
837 View *view = view_from_widget (widget);
840 new_view = get_empty_view (view);
842 fill_example_buffer (new_view->buffer->buffer);
846 do_wrap_changed (gpointer callback_data,
847 guint callback_action,
850 View *view = view_from_widget (widget);
852 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view), callback_action);
856 do_direction_changed (gpointer callback_data,
857 guint callback_action,
860 View *view = view_from_widget (widget);
862 gtk_widget_set_direction (view->text_view, callback_action);
863 gtk_widget_queue_resize (view->text_view);
868 do_spacing_changed (gpointer callback_data,
869 guint callback_action,
872 View *view = view_from_widget (widget);
876 gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (view->text_view),
878 gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view->text_view),
880 gtk_text_view_set_pixels_inside_wrap (GTK_TEXT_VIEW (view->text_view),
885 gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (view->text_view),
887 gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view->text_view),
889 gtk_text_view_set_pixels_inside_wrap (GTK_TEXT_VIEW (view->text_view),
895 do_editable_changed (gpointer callback_data,
896 guint callback_action,
899 View *view = view_from_widget (widget);
901 gtk_text_view_set_editable (GTK_TEXT_VIEW (view->text_view), callback_action);
905 do_cursor_visible_changed (gpointer callback_data,
906 guint callback_action,
909 View *view = view_from_widget (widget);
911 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), callback_action);
915 do_color_cycle_changed (gpointer callback_data,
916 guint callback_action,
919 View *view = view_from_widget (widget);
921 buffer_set_colors (view->buffer, callback_action);
925 do_apply_editable (gpointer callback_data,
926 guint callback_action,
929 View *view = view_from_widget (widget);
933 if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
938 gtk_text_buffer_remove_tag (view->buffer->buffer,
939 view->buffer->not_editable_tag,
944 gtk_text_buffer_apply_tag (view->buffer->buffer,
945 view->buffer->not_editable_tag,
952 do_apply_invisible (gpointer callback_data,
953 guint callback_action,
956 View *view = view_from_widget (widget);
960 if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
965 gtk_text_buffer_remove_tag (view->buffer->buffer,
966 view->buffer->invisible_tag,
971 gtk_text_buffer_apply_tag (view->buffer->buffer,
972 view->buffer->invisible_tag,
979 do_apply_tabs (gpointer callback_data,
980 guint callback_action,
983 View *view = view_from_widget (widget);
987 if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
992 gtk_text_buffer_remove_tag (view->buffer->buffer,
993 view->buffer->custom_tabs_tag,
998 gtk_text_buffer_apply_tag (view->buffer->buffer,
999 view->buffer->custom_tabs_tag,
1006 do_apply_colors (gpointer callback_data,
1007 guint callback_action,
1010 View *view = view_from_widget (widget);
1011 Buffer *buffer = view->buffer;
1015 if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
1018 if (!callback_action)
1022 tmp = buffer->color_tags;
1025 gtk_text_buffer_remove_tag (view->buffer->buffer,
1028 tmp = g_slist_next (tmp);
1035 tmp = buffer->color_tags;
1039 gboolean done = FALSE;
1042 gtk_text_iter_next_char (&next);
1043 gtk_text_iter_next_char (&next);
1045 if (gtk_text_iter_compare (&next, &end) > 0)
1051 gtk_text_buffer_apply_tag (view->buffer->buffer,
1060 tmp = g_slist_next (tmp);
1062 tmp = buffer->color_tags;
1075 dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
1077 GtkTextBuffer *buffer;
1079 GtkTextIter start, end;
1080 gchar *search_string;
1082 if (response_id != RESPONSE_FORWARD &&
1083 response_id != RESPONSE_BACKWARD)
1085 gtk_widget_destroy (dialog);
1089 buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer");
1091 gtk_text_buffer_get_bounds (buffer, &start, &end);
1093 /* Remove trailing newline */
1094 gtk_text_iter_prev_char (&end);
1096 search_string = gtk_text_iter_get_text (&start, &end);
1098 printf ("Searching for `%s'\n", search_string);
1100 if (response_id == RESPONSE_FORWARD)
1101 buffer_search_forward (view->buffer, search_string, view);
1102 else if (response_id == RESPONSE_BACKWARD)
1103 buffer_search_backward (view->buffer, search_string, view);
1105 g_free (search_string);
1107 gtk_widget_destroy (dialog);
1111 do_search (gpointer callback_data,
1112 guint callback_action,
1115 View *view = view_from_widget (widget);
1117 GtkWidget *search_text;
1118 GtkTextBuffer *buffer;
1120 dialog = gtk_dialog_new_with_buttons ("Search",
1121 GTK_WINDOW (view->window),
1122 GTK_DIALOG_DESTROY_WITH_PARENT,
1123 "Forward", RESPONSE_FORWARD,
1124 "Backward", RESPONSE_BACKWARD,
1125 GTK_STOCK_BUTTON_CANCEL,
1126 GTK_RESPONSE_NONE, NULL);
1129 buffer = gtk_text_buffer_new (NULL);
1131 search_text = gtk_text_view_new_with_buffer (buffer);
1133 g_object_unref (G_OBJECT (buffer));
1135 gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
1139 gtk_object_set_data (GTK_OBJECT (dialog), "buffer", buffer);
1141 gtk_signal_connect (GTK_OBJECT (dialog),
1143 GTK_SIGNAL_FUNC (dialog_response_callback),
1146 gtk_widget_show (search_text);
1148 gtk_widget_grab_focus (search_text);
1150 gtk_widget_show_all (dialog);
1154 view_init_menus (View *view)
1156 GtkTextDirection direction = gtk_widget_get_direction (view->text_view);
1157 GtkWrapMode wrap_mode = gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view->text_view));
1158 GtkWidget *menu_item = NULL;
1162 case GTK_TEXT_DIR_LTR:
1163 menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Left-to-Right");
1165 case GTK_TEXT_DIR_RTL:
1166 menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Right-to-Left");
1173 gtk_menu_item_activate (GTK_MENU_ITEM (menu_item));
1177 case GTK_WRAPMODE_NONE:
1178 menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Wrap Off");
1180 case GTK_WRAPMODE_WORD:
1181 menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Wrap Words");
1188 gtk_menu_item_activate (GTK_MENU_ITEM (menu_item));
1191 static GtkItemFactoryEntry menu_items[] =
1193 { "/_File", NULL, 0, 0, "<Branch>" },
1194 { "/File/_New", "<control>N", do_new, 0, NULL },
1195 { "/File/New _View", NULL, do_new_view, 0, NULL },
1196 { "/File/_Open", "<control>O", do_open, 0, NULL },
1197 { "/File/_Save", "<control>S", do_save, 0, NULL },
1198 { "/File/Save _As...", NULL, do_save_as, 0, NULL },
1199 { "/File/sep1", NULL, 0, 0, "<Separator>" },
1200 { "/File/_Close", "<control>W" , do_close, 0, NULL },
1201 { "/File/E_xit", "<control>Q" , do_exit, 0, NULL },
1203 { "/_Edit", NULL, 0, 0, "<Branch>" },
1204 { "/Edit/Find...", NULL, do_search, 0, NULL },
1206 { "/_Settings", NULL, 0, 0, "<Branch>" },
1207 { "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAPMODE_NONE, "<RadioItem>" },
1208 { "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAPMODE_WORD, "/Settings/Wrap Off" },
1209 { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
1210 { "/Settings/Editable", NULL, do_editable_changed, TRUE, "<RadioItem>" },
1211 { "/Settings/Not editable", NULL, do_editable_changed, FALSE, "/Settings/Editable" },
1212 { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
1214 { "/Settings/Cursor visible", NULL, do_cursor_visible_changed, TRUE, "<RadioItem>" },
1215 { "/Settings/Cursor not visible", NULL, do_cursor_visible_changed, FALSE, "/Settings/Cursor visible" },
1216 { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
1218 { "/Settings/Left-to-Right", NULL, do_direction_changed, GTK_TEXT_DIR_LTR, "<RadioItem>" },
1219 { "/Settings/Right-to-Left", NULL, do_direction_changed, GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
1221 { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
1222 { "/Settings/Sane spacing", NULL, do_spacing_changed, FALSE, "<RadioItem>" },
1223 { "/Settings/Funky spacing", NULL, do_spacing_changed, TRUE, "/Settings/Sane spacing" },
1224 { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
1225 { "/Settings/Don't cycle color tags", NULL, do_color_cycle_changed, FALSE, "<RadioItem>" },
1226 { "/Settings/Cycle colors", NULL, do_color_cycle_changed, TRUE, "/Settings/Don't cycle color tags" },
1227 { "/_Attributes", NULL, 0, 0, "<Branch>" },
1228 { "/Attributes/Editable", NULL, do_apply_editable, TRUE, NULL },
1229 { "/Attributes/Not editable", NULL, do_apply_editable, FALSE, NULL },
1230 { "/Attributes/Invisible", NULL, do_apply_invisible, FALSE, NULL },
1231 { "/Attributes/Visible", NULL, do_apply_invisible, TRUE, NULL },
1232 { "/Attributes/Custom tabs", NULL, do_apply_tabs, FALSE, NULL },
1233 { "/Attributes/Default tabs", NULL, do_apply_tabs, TRUE, NULL },
1234 { "/Attributes/Color cycles", NULL, do_apply_colors, TRUE, NULL },
1235 { "/Attributes/No colors", NULL, do_apply_colors, FALSE, NULL },
1236 { "/_Test", NULL, 0, 0, "<Branch>" },
1237 { "/Test/_Example", NULL, do_example, 0, NULL },
1241 save_buffer (Buffer *buffer)
1243 GtkTextIter start, end;
1245 gboolean result = FALSE;
1246 gboolean have_backup = FALSE;
1247 gchar *bak_filename;
1250 g_return_val_if_fail (buffer->filename != NULL, FALSE);
1252 bak_filename = g_strconcat (buffer->filename, "~", NULL);
1254 if (rename (buffer->filename, bak_filename) != 0)
1256 if (errno != ENOENT)
1258 gchar *err = g_strdup_printf ("Cannot back up '%s' to '%s': %s",
1259 buffer->filename, bak_filename, g_strerror (errno));
1260 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
1268 file = fopen (buffer->filename, "w");
1271 gchar *err = g_strdup_printf ("Cannot back up '%s' to '%s': %s",
1272 buffer->filename, bak_filename, g_strerror (errno));
1273 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
1277 gtk_text_buffer_get_iter_at_offset (buffer->buffer, &start, 0);
1278 gtk_text_buffer_get_last_iter (buffer->buffer, &end);
1280 chars = gtk_text_buffer_get_slice (buffer->buffer, &start, &end, FALSE);
1282 if (fputs (chars, file) == EOF ||
1283 fclose (file) == EOF)
1285 gchar *err = g_strdup_printf ("Error writing to '%s': %s",
1286 buffer->filename, g_strerror (errno));
1287 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
1295 gtk_text_buffer_set_modified (buffer->buffer, FALSE);
1301 if (!result && have_backup)
1303 if (rename (bak_filename, buffer->filename) != 0)
1305 gchar *err = g_strdup_printf ("Error restoring backup file '%s' to '%s': %s\nBackup left as '%s'",
1306 buffer->filename, bak_filename, g_strerror (errno), bak_filename);
1307 msgbox_run (NULL, err, "OK", NULL, NULL, 0);
1312 g_free (bak_filename);
1318 save_as_ok_func (const char *filename, gpointer data)
1320 Buffer *buffer = data;
1321 char *old_filename = buffer->filename;
1323 if (!buffer->filename || strcmp (filename, buffer->filename) != 0)
1325 struct stat statbuf;
1327 if (stat (filename, &statbuf) == 0)
1329 gchar *err = g_strdup_printf ("Ovewrite existing file '%s'?", filename);
1330 gint result = msgbox_run (NULL, err, "Yes", "No", NULL, 1);
1338 buffer->filename = g_strdup (filename);
1340 if (save_buffer (buffer))
1342 g_free (old_filename);
1343 buffer_filename_set (buffer);
1348 g_free (buffer->filename);
1349 buffer->filename = old_filename;
1355 save_as_buffer (Buffer *buffer)
1357 return filesel_run (NULL, "Save File", NULL, save_as_ok_func, buffer);
1361 check_buffer_saved (Buffer *buffer)
1363 if (gtk_text_buffer_modified (buffer->buffer))
1365 char *pretty_name = buffer_pretty_name (buffer);
1366 char *msg = g_strdup_printf ("Save changes to '%s'?", pretty_name);
1369 g_free (pretty_name);
1371 result = msgbox_run (NULL, msg, "Yes", "No", "Cancel", 0);
1375 return save_as_buffer (buffer);
1376 else if (result == 1)
1388 create_buffer (void)
1391 PangoTabArray *tabs;
1394 buffer = g_new (Buffer, 1);
1396 buffer->buffer = gtk_text_buffer_new (NULL);
1398 buffer->refcount = 1;
1399 buffer->filename = NULL;
1400 buffer->untitled_serial = -1;
1402 buffer->color_tags = NULL;
1403 buffer->color_cycle_timeout = 0;
1404 buffer->start_hue = 0.0;
1407 while (i < N_COLORS)
1411 tag = gtk_text_buffer_create_tag (buffer->buffer, NULL);
1413 buffer->color_tags = g_slist_prepend (buffer->color_tags, tag);
1418 buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL);
1419 gtk_object_set (GTK_OBJECT (buffer->invisible_tag),
1423 buffer->not_editable_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL);
1424 gtk_object_set (GTK_OBJECT (buffer->not_editable_tag),
1426 "foreground", "purple", NULL);
1428 buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL);
1429 gtk_object_set (GTK_OBJECT (buffer->found_text_tag),
1430 "foreground", "red", NULL);
1432 tabs = pango_tab_array_new_with_positions (4,
1437 PANGO_TAB_LEFT, 120);
1439 buffer->custom_tabs_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL);
1440 gtk_object_set (GTK_OBJECT (buffer->custom_tabs_tag),
1442 "foreground", "green", NULL);
1444 pango_tab_array_free (tabs);
1446 buffers = g_slist_prepend (buffers, buffer);
1452 buffer_pretty_name (Buffer *buffer)
1454 if (buffer->filename)
1457 char *result = g_path_get_basename (buffer->filename);
1458 p = strchr (result, '/');
1466 if (buffer->untitled_serial == -1)
1467 buffer->untitled_serial = untitled_serial++;
1469 if (buffer->untitled_serial == 1)
1470 return g_strdup ("Untitled");
1472 return g_strdup_printf ("Untitled #%d", buffer->untitled_serial);
1477 buffer_filename_set (Buffer *buffer)
1479 GSList *tmp_list = views;
1483 View *view = tmp_list->data;
1485 if (view->buffer == buffer)
1486 view_set_title (view);
1488 tmp_list = tmp_list->next;
1493 buffer_search (Buffer *buffer,
1499 GtkTextIter start, end;
1503 /* remove tag from whole buffer */
1504 gtk_text_buffer_get_bounds (buffer->buffer, &start, &end);
1505 gtk_text_buffer_remove_tag (buffer->buffer, buffer->found_text_tag,
1508 gtk_text_buffer_get_iter_at_mark (buffer->buffer, &iter,
1509 gtk_text_buffer_get_mark (buffer->buffer,
1515 GtkTextIter match_start, match_end;
1519 while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE,
1520 &match_start, &match_end,
1524 gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
1525 &match_start, &match_end);
1532 while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE,
1533 &match_start, &match_end,
1537 gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
1538 &match_start, &match_end);
1545 dialog = gtk_message_dialog_new (GTK_WINDOW (view->window),
1548 GTK_DIALOG_DESTROY_WITH_PARENT,
1549 "%d strings found and marked in red",
1552 gtk_signal_connect_object (GTK_OBJECT (dialog),
1554 GTK_SIGNAL_FUNC (gtk_widget_destroy),
1555 GTK_OBJECT (dialog));
1557 gtk_widget_show (dialog);
1561 buffer_search_forward (Buffer *buffer, const char *str,
1564 buffer_search (buffer, str, view, TRUE);
1568 buffer_search_backward (Buffer *buffer, const char *str,
1571 buffer_search (buffer, str, view, FALSE);
1575 buffer_ref (Buffer *buffer)
1581 buffer_unref (Buffer *buffer)
1584 if (buffer->refcount == 0)
1586 buffer_set_colors (buffer, FALSE);
1587 buffers = g_slist_remove (buffers, buffer);
1588 gtk_object_unref (GTK_OBJECT (buffer->buffer));
1589 g_free (buffer->filename);
1595 hsv_to_rgb (gdouble *h,
1599 gdouble hue, saturation, value;
1617 f = hue - (int) hue;
1618 p = value * (1.0 - saturation);
1619 q = value * (1.0 - saturation * f);
1620 t = value * (1.0 - saturation * (1.0 - f));
1661 g_assert_not_reached ();
1667 hue_to_color (gdouble hue,
1676 g_return_if_fail (hue <= 1.0);
1678 hsv_to_rgb (&h, &s, &v);
1680 color->red = h * 65535;
1681 color->green = s * 65535;
1682 color->blue = v * 65535;
1687 color_cycle_timeout (gpointer data)
1689 Buffer *buffer = data;
1691 buffer_cycle_colors (buffer);
1697 buffer_set_colors (Buffer *buffer,
1703 if (enabled && buffer->color_cycle_timeout == 0)
1704 buffer->color_cycle_timeout = gtk_timeout_add (200, color_cycle_timeout, buffer);
1705 else if (!enabled && buffer->color_cycle_timeout != 0)
1707 gtk_timeout_remove (buffer->color_cycle_timeout);
1708 buffer->color_cycle_timeout = 0;
1711 tmp = buffer->color_tags;
1718 hue_to_color (hue, &color);
1720 gtk_object_set (GTK_OBJECT (tmp->data),
1721 "foreground_gdk", &color,
1725 gtk_object_set (GTK_OBJECT (tmp->data),
1726 "foreground_set", FALSE,
1729 hue += 1.0 / N_COLORS;
1731 tmp = g_slist_next (tmp);
1736 buffer_cycle_colors (Buffer *buffer)
1739 gdouble hue = buffer->start_hue;
1741 tmp = buffer->color_tags;
1746 hue_to_color (hue, &color);
1748 gtk_object_set (GTK_OBJECT (tmp->data),
1749 "foreground_gdk", &color,
1752 hue += 1.0 / N_COLORS;
1756 tmp = g_slist_next (tmp);
1759 buffer->start_hue += 1.0 / N_COLORS;
1760 if (buffer->start_hue > 1.0)
1761 buffer->start_hue = 0.0;
1765 close_view (View *view)
1767 views = g_slist_remove (views, view);
1768 buffer_unref (view->buffer);
1769 gtk_widget_destroy (view->window);
1770 g_object_unref (G_OBJECT (view->item_factory));
1779 check_close_view (View *view)
1781 if (view->buffer->refcount > 1 ||
1782 check_buffer_saved (view->buffer))
1787 view_set_title (View *view)
1789 char *pretty_name = buffer_pretty_name (view->buffer);
1790 char *title = g_strconcat ("testtext - ", pretty_name, NULL);
1792 gtk_window_set_title (GTK_WINDOW (view->window), title);
1794 g_free (pretty_name);
1799 cursor_set_callback (GtkTextBuffer *buffer,
1800 const GtkTextIter *location,
1804 GtkTextView *text_view;
1806 /* Redraw tab windows if the cursor moves
1807 * on the mapped widget (windows may not exist before realization...
1810 text_view = GTK_TEXT_VIEW (user_data);
1812 if (GTK_WIDGET_MAPPED (text_view) &&
1813 mark == gtk_text_buffer_get_insert (buffer))
1815 GdkWindow *tab_window;
1817 tab_window = gtk_text_view_get_window (text_view,
1818 GTK_TEXT_WINDOW_TOP);
1820 gdk_window_invalidate_rect (tab_window, NULL, FALSE);
1822 tab_window = gtk_text_view_get_window (text_view,
1823 GTK_TEXT_WINDOW_BOTTOM);
1825 gdk_window_invalidate_rect (tab_window, NULL, FALSE);
1830 tab_stops_expose (GtkWidget *widget,
1831 GdkEventExpose *event,
1838 GdkWindow *bottom_win;
1839 GtkTextView *text_view;
1840 GtkTextWindowType type;
1841 GdkDrawable *target;
1842 gint *positions = NULL;
1844 GtkTextAttributes *attrs;
1846 GtkTextBuffer *buffer;
1849 text_view = GTK_TEXT_VIEW (widget);
1851 /* See if this expose is on the tab stop window */
1852 top_win = gtk_text_view_get_window (text_view,
1853 GTK_TEXT_WINDOW_TOP);
1855 bottom_win = gtk_text_view_get_window (text_view,
1856 GTK_TEXT_WINDOW_BOTTOM);
1858 if (event->window == top_win)
1860 type = GTK_TEXT_WINDOW_TOP;
1863 else if (event->window == bottom_win)
1865 type = GTK_TEXT_WINDOW_BOTTOM;
1866 target = bottom_win;
1871 first_x = event->area.x;
1872 last_x = first_x + event->area.width;
1874 gtk_text_view_window_to_buffer_coords (text_view,
1881 gtk_text_view_window_to_buffer_coords (text_view,
1888 buffer = gtk_text_view_get_buffer (text_view);
1890 gtk_text_buffer_get_iter_at_mark (buffer,
1892 gtk_text_buffer_get_mark (buffer,
1895 attrs = gtk_text_attributes_new ();
1897 gtk_text_iter_get_attributes (&insert, attrs);
1901 size = pango_tab_array_get_size (attrs->tabs);
1903 pango_tab_array_get_tabs (attrs->tabs,
1907 in_pixels = pango_tab_array_get_positions_in_pixels (attrs->tabs);
1915 gtk_text_attributes_unref (attrs);
1923 positions[i] = PANGO_PIXELS (positions[i]);
1925 gtk_text_view_buffer_to_window_coords (text_view,
1932 gdk_draw_line (target,
1933 widget->style->fg_gc [widget->state],
1946 get_lines (GtkTextView *text_view,
1949 GArray *buffer_coords,
1957 g_array_set_size (buffer_coords, 0);
1958 g_array_set_size (numbers, 0);
1960 /* Get iter at first y */
1961 gtk_text_view_get_line_at_y (text_view, &iter, first_y, NULL);
1963 /* For each iter, get its location and add it to the arrays.
1964 * Stop when we pass last_y
1969 while (!gtk_text_iter_is_last (&iter))
1974 gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
1976 g_array_append_val (buffer_coords, y);
1977 line_num = gtk_text_iter_get_line (&iter);
1978 g_array_append_val (numbers, line_num);
1982 if ((y + height) >= last_y)
1985 gtk_text_iter_forward_line (&iter);
1992 line_numbers_expose (GtkWidget *widget,
1993 GdkEventExpose *event,
2002 GdkWindow *left_win;
2003 GdkWindow *right_win;
2004 PangoLayout *layout;
2005 GtkTextView *text_view;
2006 GtkTextWindowType type;
2007 GdkDrawable *target;
2009 text_view = GTK_TEXT_VIEW (widget);
2011 /* See if this expose is on the line numbers window */
2012 left_win = gtk_text_view_get_window (text_view,
2013 GTK_TEXT_WINDOW_LEFT);
2015 right_win = gtk_text_view_get_window (text_view,
2016 GTK_TEXT_WINDOW_RIGHT);
2018 if (event->window == left_win)
2020 type = GTK_TEXT_WINDOW_LEFT;
2023 else if (event->window == right_win)
2025 type = GTK_TEXT_WINDOW_RIGHT;
2031 first_y = event->area.y;
2032 last_y = first_y + event->area.height;
2034 gtk_text_view_window_to_buffer_coords (text_view,
2041 gtk_text_view_window_to_buffer_coords (text_view,
2048 numbers = g_array_new (FALSE, FALSE, sizeof (gint));
2049 pixels = g_array_new (FALSE, FALSE, sizeof (gint));
2051 get_lines (text_view,
2058 /* Draw fully internationalized numbers! */
2060 layout = gtk_widget_create_pango_layout (widget, "");
2068 gtk_text_view_buffer_to_window_coords (text_view,
2071 g_array_index (pixels, gint, i),
2075 str = g_strdup_printf ("%d", g_array_index (numbers, gint, i));
2077 pango_layout_set_text (layout, str, -1);
2080 gdk_draw_layout (target,
2081 widget->style->fg_gc [widget->state],
2082 /* 2 is just a random padding */
2091 g_array_free (pixels, TRUE);
2092 g_array_free (numbers, TRUE);
2094 g_object_unref (G_OBJECT (layout));
2100 create_view (Buffer *buffer)
2107 view = g_new0 (View, 1);
2108 views = g_slist_prepend (views, view);
2110 view->buffer = buffer;
2111 buffer_ref (buffer);
2113 view->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2114 gtk_object_set_data (GTK_OBJECT (view->window), "view", view);
2116 gtk_signal_connect (GTK_OBJECT (view->window), "delete_event",
2117 GTK_SIGNAL_FUNC (delete_event_cb), NULL);
2119 view->accel_group = gtk_accel_group_new ();
2120 view->item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", view->accel_group);
2121 gtk_object_set_data (GTK_OBJECT (view->item_factory), "view", view);
2123 gtk_item_factory_create_items (view->item_factory, G_N_ELEMENTS (menu_items), menu_items, view);
2125 gtk_window_add_accel_group (GTK_WINDOW (view->window), view->accel_group);
2127 vbox = gtk_vbox_new (FALSE, 0);
2128 gtk_container_add (GTK_CONTAINER (view->window), vbox);
2130 gtk_box_pack_start (GTK_BOX (vbox),
2131 gtk_item_factory_get_widget (view->item_factory, "<main>"),
2134 sw = gtk_scrolled_window_new (NULL, NULL);
2135 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2136 GTK_POLICY_AUTOMATIC,
2137 GTK_POLICY_AUTOMATIC);
2139 view->text_view = gtk_text_view_new_with_buffer (buffer->buffer);
2140 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view),
2143 /* Draw tab stops in the top and bottom windows. */
2145 gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
2146 GTK_TEXT_WINDOW_TOP,
2149 gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
2150 GTK_TEXT_WINDOW_BOTTOM,
2153 gtk_signal_connect (GTK_OBJECT (view->text_view),
2155 GTK_SIGNAL_FUNC (tab_stops_expose),
2158 gtk_signal_connect (GTK_OBJECT (view->buffer->buffer),
2160 GTK_SIGNAL_FUNC (cursor_set_callback),
2163 /* Draw line numbers in the side windows; we should really be
2164 * more scientific about what width we set them to.
2166 gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
2167 GTK_TEXT_WINDOW_RIGHT,
2170 gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
2171 GTK_TEXT_WINDOW_LEFT,
2174 gtk_signal_connect (GTK_OBJECT (view->text_view),
2176 GTK_SIGNAL_FUNC (line_numbers_expose),
2179 gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
2180 gtk_container_add (GTK_CONTAINER (sw), view->text_view);
2182 gtk_window_set_default_size (GTK_WINDOW (view->window), 500, 500);
2184 gtk_widget_grab_focus (view->text_view);
2186 view_set_title (view);
2187 view_init_menus (view);
2189 gtk_widget_show_all (view->window);
2194 file_exists (const char *filename)
2196 struct stat statbuf;
2198 return stat (filename, &statbuf) == 0;
2203 if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so"))
2205 putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
2206 putenv ("GTK_IM_MODULE_FILE=./gtk.immodules");
2211 main (int argc, char** argv)
2219 gtk_init (&argc, &argv);
2221 buffer = create_buffer ();
2222 view = create_view (buffer);
2223 buffer_unref (buffer);
2225 push_active_window (GTK_WINDOW (view->window));
2226 for (i=1; i < argc; i++)
2230 /* Quick and dirty canonicalization - better should be in GLib
2233 if (!g_path_is_absolute (argv[i]))
2235 char *cwd = g_get_current_dir ();
2236 filename = g_strconcat (cwd, "/", argv[i], NULL);
2242 open_ok_func (filename, view);
2244 if (filename != argv[i])
2247 pop_active_window ();