1 /* gtkedit.c - front end for gtk/gnome version
2 
3    Copyright (C) 1996-2000 the Free Software Foundation
4 
5    Authors: 1996, 1997 Paul Sheer
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 of the License, or
10    (at your option) 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., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307, USA.
21 */
22 
23 #define _GTK_EDIT_C
24 
25 #include <config.h>
26 #include <gnome.h>
27 #include <ctype.h>
28 #include <string.h>
29 #include <pwd.h>
30 #include "gdk/gdkkeysyms.h"
31 #include "gtk/gtkmain.h"
32 #include "gtk/gtkselection.h"
33 #include "gtk/gtksignal.h"
34 #include "edit.h"
35 #include "mousemark.h"
36 #include "mad.h"
37 
38 #define EDIT_BORDER_ROOM         1
39 #define MIN_EDIT_WIDTH_LINES     20
40 #define MIN_EDIT_HEIGHT_LINES    10
41 
42 #define GDK_FONT_XFONT(font) (((GdkFontPrivate*) font)->xfont)
43 
44 int edit_key_emulation = 0;
45 
46 static GtkWidgetClass *parent_class = NULL;
47 
48 WEdit *edit_init (WEdit * edit, int lines, int columns, const char *filename, const char *text, const char *dir, unsigned long text_size);
49 void edit_destroy_callback (CWidget * w);
50 int edit_translate_key (unsigned int x_keycode, long x_key, int x_state, int *cmd, int *ch);
51 void gtk_edit_alloc_colors (GtkEdit *edit, GdkColormap *colormap);
52 static void gtk_edit_set_position (GtkEditable *editable, gint position);
53 void edit_mouse_mark (WEdit * edit, XEvent * event, int double_click);
54 void edit_move_to_prev_col (WEdit * edit, long p);
55 int edit_load_file_from_filename (WEdit *edit, char *exp);
56 
57 
58 guchar gtk_edit_font_width_per_char[256];
59 int gtk_edit_option_text_line_spacing;
60 int gtk_edit_option_font_ascent;
61 int gtk_edit_option_font_descent;
62 int gtk_edit_option_font_mean_width;
63 int gtk_edit_fixed_font;
64 
clear_focus_area(GtkEdit * edit,gint area_x,gint area_y,gint area_width,gint area_height)65 static void clear_focus_area (GtkEdit *edit, gint area_x, gint area_y, gint area_width, gint area_height)
66 {
67     return;
68 }
69 
gtk_edit_freeze(GtkEdit * edit)70 void gtk_edit_freeze (GtkEdit *edit)
71 {
72     return;
73 }
74 
gtk_edit_insert(GtkEdit * edit,GdkFont * font,GdkColor * fore,GdkColor * back,const char * chars,gint length)75 void       gtk_edit_insert          (GtkEdit       *edit,
76 				     GdkFont       *font,
77 				     GdkColor      *fore,
78 				     GdkColor      *back,
79 				     const char    *chars,
80 				     gint           length)
81 {
82     while (length-- > 0)
83 	edit_insert (GTK_EDIT (edit)->editor, *chars++);
84 }
85 
gtk_edit_set_editable(GtkEdit * text,gint editable)86 void       gtk_edit_set_editable    (GtkEdit       *text,
87 				     gint           editable)
88 {
89     return;
90 }
91 
gtk_edit_thaw(GtkEdit * text)92 void       gtk_edit_thaw            (GtkEdit       *text)
93 {
94     return;
95 }
96 
97 
gtk_edit_configure_font_dimensions(GtkEdit * edit)98 void gtk_edit_configure_font_dimensions (GtkEdit * edit)
99 {
100     XFontStruct *f;
101     XCharStruct s;
102     char *p;
103     char q[256];
104     unsigned char t;
105     int i, direction;
106     f = GDK_FONT_XFONT (edit->editable.widget.style->font);
107     p = _ ("The Quick Brown Fox Jumps Over The Lazy Dog");
108     for (i = ' '; i <= '~'; i++)
109 	q[i - ' '] = i;
110     if (XmbTextEscapement (f, "M", 1) == XmbTextEscapement (f, "M", 1))
111 	gtk_edit_fixed_font = 1;
112     else
113 	gtk_edit_fixed_font = 0;
114     XTextExtents (f, q, '~' - ' ', &direction, &gtk_edit_option_font_ascent, &gtk_edit_option_font_descent, &s);
115     gtk_edit_option_font_mean_width = XmbTextEscapement (f, p, strlen (p)) / strlen (p);
116     for (i = 0; i < 256; i++) {
117 	t = (unsigned char) i;
118 	if (i > f->max_char_or_byte2 || i < f->min_char_or_byte2) {
119 	    gtk_edit_font_width_per_char[i] = 0;
120 	} else {
121 	    gtk_edit_font_width_per_char[i] = XmbTextEscapement (f, (char *) &t, 1);
122 	}
123     }
124 }
125 
gtk_edit_set_adjustments(GtkEdit * edit,GtkAdjustment * hadj,GtkAdjustment * vadj)126 void gtk_edit_set_adjustments (GtkEdit * edit,
127 			       GtkAdjustment * hadj,
128 			       GtkAdjustment * vadj)
129 {
130     g_return_if_fail (edit != NULL);
131     g_return_if_fail (GTK_IS_EDIT (edit));
132 
133     if (edit->hadj && (edit->hadj != hadj)) {
134 	gtk_signal_disconnect_by_data (GTK_OBJECT (edit->hadj), edit);
135 	gtk_object_unref (GTK_OBJECT (edit->hadj));
136     }
137     if (edit->vadj && (edit->vadj != vadj)) {
138 	gtk_signal_disconnect_by_data (GTK_OBJECT (edit->vadj), edit);
139 	gtk_object_unref (GTK_OBJECT (edit->vadj));
140     }
141     if (!hadj)
142 	hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
143 
144     if (!vadj)
145 	vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
146 
147     if (edit->hadj != hadj) {
148 	edit->hadj = hadj;
149 	gtk_object_ref (GTK_OBJECT (edit->hadj));
150 	gtk_object_sink (GTK_OBJECT (edit->hadj));
151 
152 #if 0
153 	gtk_signal_connect (GTK_OBJECT (edit->hadj), "changed",
154 			    (GtkSignalFunc) gtk_edit_adjustment,
155 			    edit);
156 	gtk_signal_connect (GTK_OBJECT (edit->hadj), "value_changed",
157 			    (GtkSignalFunc) gtk_edit_adjustment,
158 			    edit);
159 	gtk_signal_connect (GTK_OBJECT (edit->hadj), "disconnect",
160 			    (GtkSignalFunc) gtk_edit_disconnect,
161 			    edit);
162 #endif
163     }
164     if (edit->vadj != vadj) {
165 	edit->vadj = vadj;
166 	gtk_object_ref (GTK_OBJECT (edit->vadj));
167 	gtk_object_sink (GTK_OBJECT (edit->vadj));
168 
169 #if 0
170 	gtk_signal_connect (GTK_OBJECT (edit->vadj), "changed",
171 			    (GtkSignalFunc) gtk_edit_adjustment,
172 			    edit);
173 	gtk_signal_connect (GTK_OBJECT (edit->vadj), "value_changed",
174 			    (GtkSignalFunc) gtk_edit_adjustment,
175 			    edit);
176 	gtk_signal_connect (GTK_OBJECT (edit->vadj), "disconnect",
177 			    (GtkSignalFunc) gtk_edit_disconnect,
178 			    edit);
179 #endif
180     }
181 }
182 
gtk_edit_new(GtkAdjustment * hadj,GtkAdjustment * vadj)183 GtkWidget *gtk_edit_new (GtkAdjustment * hadj,
184 			 GtkAdjustment * vadj)
185 {
186     GtkEdit *edit;
187     edit = gtk_type_new (gtk_edit_get_type ());
188     gtk_edit_set_adjustments (edit, hadj, vadj);
189     gtk_edit_configure_font_dimensions (edit);
190     return GTK_WIDGET (edit);
191 }
192 
gtk_edit_realize(GtkWidget * widget)193 static void gtk_edit_realize (GtkWidget * widget)
194 {
195     GtkEdit *edit;
196     GtkEditable *editable;
197     GdkWindowAttr attributes;
198     GdkColormap *colormap;
199     gint attributes_mask;
200 
201     g_return_if_fail (widget != NULL);
202     g_return_if_fail (GTK_IS_EDIT (widget));
203 
204     edit = GTK_EDIT (widget);
205     editable = GTK_EDITABLE (widget);
206     GTK_WIDGET_SET_FLAGS (edit, GTK_REALIZED);
207 
208     attributes.window_type = GDK_WINDOW_CHILD;
209     attributes.x = widget->allocation.x;
210     attributes.y = widget->allocation.y;
211     attributes.width = widget->allocation.width;
212     attributes.height = widget->allocation.height;
213     attributes.wclass = GDK_INPUT_OUTPUT;
214     attributes.visual = gtk_widget_get_visual (widget);
215     colormap = attributes.colormap = gtk_widget_get_colormap (widget);
216     attributes.event_mask = gtk_widget_get_events (widget);
217     attributes.event_mask |= (GDK_EXPOSURE_MASK |
218 			      GDK_BUTTON_PRESS_MASK |
219 			      GDK_BUTTON_RELEASE_MASK |
220 			      GDK_BUTTON_MOTION_MASK |
221 			      GDK_ENTER_NOTIFY_MASK |
222 			      GDK_LEAVE_NOTIFY_MASK |
223 			      GDK_KEY_RELEASE_MASK |
224 			      GDK_KEY_PRESS_MASK);
225     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
226 
227     widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
228     gdk_window_set_user_data (widget->window, edit);
229 
230     attributes.x = (widget->style->klass->xthickness + EDIT_BORDER_ROOM);
231     attributes.y = (widget->style->klass->ythickness + EDIT_BORDER_ROOM);
232     attributes.width = widget->allocation.width - attributes.x * 2;
233     attributes.height = widget->allocation.height - attributes.y * 2;
234 
235     edit->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
236     gdk_window_set_user_data (edit->text_area, edit);
237 
238     widget->style = gtk_style_attach (widget->style, widget->window);
239 
240     gtk_edit_alloc_colors (edit, colormap);
241 
242     /* Can't call gtk_style_set_background here because it's handled specially */
243     gdk_window_set_background (widget->window, &edit->color[1]);
244     gdk_window_set_background (edit->text_area, &edit->color[1]);
245 
246     edit->gc = gdk_gc_new (edit->text_area);
247     gdk_gc_set_exposures (edit->gc, TRUE);
248     gdk_gc_set_foreground (edit->gc, &edit->color[26]);
249     gdk_gc_set_background (edit->gc, &edit->color[1]);
250 
251 
252     gdk_window_show (edit->text_area);
253 
254     if (editable->selection_start_pos != editable->selection_end_pos)
255 	gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
256 
257 #if 0
258     if ((widget->allocation.width > 1) || (widget->allocation.height > 1))
259 	recompute_geometry (edit);
260 #endif
261 }
262 
gtk_edit_unrealize(GtkWidget * widget)263 static void gtk_edit_unrealize (GtkWidget * widget)
264 {
265     GtkEdit *edit;
266 
267     g_return_if_fail (widget != NULL);
268     g_return_if_fail (GTK_IS_EDIT (widget));
269 
270     edit = GTK_EDIT (widget);
271 
272     gdk_window_set_user_data (edit->text_area, NULL);
273     gdk_window_destroy (edit->text_area);
274     edit->text_area = NULL;
275 
276     gdk_gc_destroy (edit->gc);
277     edit->gc = NULL;
278 
279     if (GTK_WIDGET_CLASS (parent_class)->unrealize)
280 	(*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
281 }
282 
gtk_edit_destroy(GtkObject * object)283 static void gtk_edit_destroy (GtkObject * object)
284 {
285     GtkEdit *edit;
286 
287     g_return_if_fail (object != NULL);
288     g_return_if_fail (GTK_IS_EDIT (object));
289 
290     edit = (GtkEdit *) object;
291     if (edit->hadj) {
292 	gtk_object_unref (GTK_OBJECT (edit->hadj));
293 	edit->hadj = NULL;
294     }
295     if (edit->vadj) {
296 	gtk_object_unref (GTK_OBJECT (edit->vadj));
297 	edit->vadj = NULL;
298     }
299     if (edit->timer) {
300 	gtk_timeout_remove (edit->timer);
301 	edit->timer = 0;
302     }
303     if (edit->funcs) {
304 	free (edit->funcs);
305     }
306     edit_destroy_callback (edit);
307 
308     GTK_OBJECT_CLASS (parent_class)->destroy (object);
309 }
310 
gtk_edit_style_set(GtkWidget * widget,GtkStyle * previous_style)311 static void gtk_edit_style_set (GtkWidget * widget,
312 				GtkStyle * previous_style)
313 {
314     GtkEdit *edit;
315 
316     g_return_if_fail (widget != NULL);
317     g_return_if_fail (GTK_IS_EDIT (widget));
318 
319     edit = GTK_EDIT (widget);
320     if (GTK_WIDGET_REALIZED (widget)) {
321 	gdk_window_set_background (widget->window, &edit->color[1]);
322 	gdk_window_set_background (edit->text_area, &edit->color[1]);
323 
324 #if 0
325 	if ((widget->allocation.width > 1) || (widget->allocation.height > 1))
326 	    recompute_geometry (edit);
327 #endif
328     }
329     if (GTK_WIDGET_DRAWABLE (widget))
330 	gdk_window_clear (widget->window);
331 }
332 
gtk_edit_draw_focus(GtkWidget * widget)333 static void gtk_edit_draw_focus (GtkWidget * widget)
334 {
335     GtkEdit *edit;
336     gint width, height;
337     gint x, y;
338 
339     g_return_if_fail (widget != NULL);
340     g_return_if_fail (GTK_IS_EDIT (widget));
341 
342     edit = GTK_EDIT (widget);
343 
344     if (GTK_WIDGET_DRAWABLE (widget)) {
345 	gint ythick = widget->style->klass->ythickness;
346 	gint xthick = widget->style->klass->xthickness;
347 	gint xextra = EDIT_BORDER_ROOM;
348 	gint yextra = EDIT_BORDER_ROOM;
349 
350 /*      TDEBUG (("in gtk_edit_draw_focus\n")); */
351 
352 	x = 0;
353 	y = 0;
354 	width = widget->allocation.width;
355 	height = widget->allocation.height;
356 
357 	if (GTK_WIDGET_HAS_FOCUS (widget)) {
358 	    x += 1;
359 	    y += 1;
360 	    width -= 2;
361 	    height -= 2;
362 	    xextra -= 1;
363 	    yextra -= 1;
364 
365 	    gdk_draw_rectangle (widget->window,
366 				widget->style->fg_gc[GTK_STATE_NORMAL],
367 				FALSE, 0, 0,
368 				widget->allocation.width - 1,
369 				widget->allocation.height - 1);
370 	}
371 	gtk_draw_shadow (widget->style, widget->window,
372 			 GTK_STATE_NORMAL, GTK_SHADOW_IN,
373 			 x, y, width, height);
374 
375 	x += xthick;
376 	y += ythick;
377 	width -= 2 * xthick;
378 	height -= 2 * ythick;
379 
380 	if (widget->style->bg_pixmap[GTK_STATE_NORMAL]) {
381 	    /* top rect */
382 	    clear_focus_area (edit, x, y, width, yextra);
383 	    /* left rect */
384 	    clear_focus_area (edit, x, y + yextra,
385 			      xextra, y + height - 2 * yextra);
386 	    /* right rect */
387 	    clear_focus_area (edit, x + width - xextra, y + yextra,
388 			      xextra, height - 2 * ythick);
389 	    /* bottom rect */
390 	    clear_focus_area (edit, x, x + height - yextra, width, yextra);
391 	} else if (!GTK_WIDGET_HAS_FOCUS (widget)) {
392 	    gdk_draw_rectangle (widget->window,
393 			 widget->style->base_gc[GTK_STATE_NORMAL], FALSE,
394 				x, y,
395 				width - 1,
396 				height - 1);
397 	}
398     }
399 #if 0
400     else {
401 	TDEBUG (("in gtk_edit_draw_focus (undrawable !!!)\n"));
402     }
403 #endif
404 }
405 
gtk_edit_size_request(GtkWidget * widget,GtkRequisition * requisition)406 static void gtk_edit_size_request (GtkWidget * widget,
407 				   GtkRequisition * requisition)
408 {
409     gint xthickness;
410     gint ythickness;
411     gint char_height;
412     gint char_width;
413 
414     g_return_if_fail (widget != NULL);
415     g_return_if_fail (GTK_IS_EDIT (widget));
416     g_return_if_fail (requisition != NULL);
417 
418     xthickness = widget->style->klass->xthickness + EDIT_BORDER_ROOM;
419     ythickness = widget->style->klass->ythickness + EDIT_BORDER_ROOM;
420 
421     char_height = MIN_EDIT_HEIGHT_LINES * (widget->style->font->ascent +
422 					   widget->style->font->descent);
423 
424     char_width = MIN_EDIT_WIDTH_LINES * (gdk_text_width (widget->style->font,
425 					    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
426 							 26)
427 					 / 26);
428 
429     requisition->width = char_width + xthickness * 2;
430     requisition->height = char_height + ythickness * 2;
431 }
432 
gtk_edit_size_allocate(GtkWidget * widget,GtkAllocation * allocation)433 static void gtk_edit_size_allocate (GtkWidget * widget,
434 				    GtkAllocation * allocation)
435 {
436     GtkEdit *edit;
437     GtkEditable *editable;
438 
439     g_return_if_fail (widget != NULL);
440     g_return_if_fail (GTK_IS_EDIT (widget));
441     g_return_if_fail (allocation != NULL);
442 
443     edit = GTK_EDIT (widget);
444     editable = GTK_EDITABLE (widget);
445 
446     widget->allocation = *allocation;
447     if (GTK_WIDGET_REALIZED (widget)) {
448 	gdk_window_move_resize (widget->window,
449 				allocation->x, allocation->y,
450 				allocation->width, allocation->height);
451 
452 	gdk_window_move_resize (edit->text_area,
453 		     widget->style->klass->xthickness + EDIT_BORDER_ROOM,
454 		     widget->style->klass->ythickness + EDIT_BORDER_ROOM,
455 	   widget->allocation.width - (widget->style->klass->xthickness +
456 				       EDIT_BORDER_ROOM) * 2,
457 	  widget->allocation.height - (widget->style->klass->ythickness +
458 				       EDIT_BORDER_ROOM) * 2);
459 
460 #if 0
461 	recompute_geometry (edit);
462 #endif
463     }
464 }
465 
gtk_edit_draw(GtkWidget * widget,GdkRectangle * area)466 static void gtk_edit_draw (GtkWidget * widget,
467 			   GdkRectangle * area)
468 {
469     GtkEdit *edit;
470     g_return_if_fail (widget != NULL);
471     g_return_if_fail (GTK_IS_EDIT (widget));
472     g_return_if_fail (area != NULL);
473 
474     if (GTK_WIDGET_DRAWABLE (widget)) {
475 /* convert the gtk expose to a coolwidget expose */
476 	XExposeEvent xexpose;
477 	xexpose.x = area->x;
478 	xexpose.y = area->y;
479 	xexpose.width = area->width;
480 	xexpose.height = area->height;
481 	edit = GTK_EDIT (widget);
482 	edit_render_expose (edit->editor, &xexpose);
483 	edit_status (edit->editor);
484     }
485 }
486 
gtk_edit_set_colors(GtkEdit * win)487 void gtk_edit_set_colors (GtkEdit *win)
488 {
489     edit_set_foreground_colors (
490 				 color_palette (option_editor_fg_normal),
491 				   color_palette (option_editor_fg_bold),
492 				   color_palette (option_editor_fg_italic)
493 	);
494     edit_set_background_colors (
495 				 color_palette (option_editor_bg_normal),
496 			       color_palette (option_editor_bg_abnormal),
497 				 color_palette (option_editor_bg_marked),
498 			color_palette (option_editor_bg_marked_abnormal),
499 			     color_palette (option_editor_bg_highlighted)
500 	);
501     edit_set_cursor_color (
502 			      color_palette (option_editor_fg_cursor)
503 	);
504 }
505 
506 static gint
gtk_edit_expose(GtkWidget * widget,GdkEventExpose * event)507  gtk_edit_expose (GtkWidget * widget,
508 		  GdkEventExpose * event)
509 {
510     GtkEdit *edit;
511     g_return_val_if_fail (widget != NULL, FALSE);
512     g_return_val_if_fail (GTK_IS_EDIT (widget), FALSE);
513     g_return_val_if_fail (event != NULL, FALSE);
514 
515     if (GTK_WIDGET_DRAWABLE (widget)) {
516 /* convert the gtk expose to a coolwidget expose */
517 	XExposeEvent xexpose;
518 	xexpose.x = event->area.x;
519 	xexpose.y = event->area.y;
520 	xexpose.width = event->area.width;
521 	xexpose.height = event->area.height;
522 	edit = GTK_EDIT (widget);
523 	gtk_edit_set_colors (edit);
524 	edit_render_expose (edit->editor, &xexpose);
525 	edit_status (edit->editor);
526     }
527     return FALSE;
528 }
529 
530 static gint
gtk_edit_button_press_release(GtkWidget * widget,GdkEventButton * event)531  gtk_edit_button_press_release (GtkWidget * widget,
532 				GdkEventButton * event)
533 {
534     int double_click = 0;
535     XEvent xevent;
536     GtkEdit *edit;
537     GtkEditable *editable;
538     static GdkAtom ctext_atom = GDK_NONE;
539 
540     g_return_val_if_fail (widget != NULL, FALSE);
541     g_return_val_if_fail (GTK_IS_EDIT (widget), FALSE);
542     g_return_val_if_fail (event != NULL, FALSE);
543 
544     if (ctext_atom == GDK_NONE)
545 	ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
546 
547     edit = GTK_EDIT (widget);
548     editable = GTK_EDITABLE (widget);
549 
550     if (!GTK_WIDGET_HAS_FOCUS (widget))
551 	if (!(event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)))
552 	    gtk_widget_grab_focus (widget);
553 
554     switch (event->type) {
555     case GDK_MOTION_NOTIFY:
556 	xevent.type = MotionNotify;
557 	break;
558     case GDK_BUTTON_PRESS:
559 	xevent.type = ButtonPress;
560 	break;
561     case GDK_2BUTTON_PRESS:
562 	xevent.type = ButtonPress;
563 	double_click = 1;
564 	break;
565     case GDK_BUTTON_RELEASE:
566 	xevent.type = ButtonRelease;
567 	break;
568     case GDK_3BUTTON_PRESS:
569     default:
570 	return FALSE;
571 	break;
572     }
573     xevent.xbutton.window = (guint32) event->window;
574     xevent.xbutton.x = event->x;
575     xevent.xbutton.y = event->y;
576     xevent.xbutton.state = event->state;
577 
578     edit_mouse_mark (edit->editor, &xevent, double_click);
579     return FALSE;
580 }
581 
582 static gint
gtk_edit_button_motion(GtkWidget * widget,GdkEventMotion * event)583  gtk_edit_button_motion (GtkWidget * widget,
584 			 GdkEventMotion * event)
585 {
586     return gtk_edit_button_press_release (widget, (GdkEventButton *) event);
587 }
588 
toggle_bit(guint x,guint mask)589 static guint toggle_bit (guint x, guint mask)
590 {
591     unsigned long m = -1;
592     if ((x & mask))
593 	return x & (m - mask);
594     else
595 	return x | mask;
596 }
597 
mod_type_key(guint x)598 int mod_type_key (guint x)
599 {
600     switch ((guint) x) {
601     case GDK_Shift_L:
602     case GDK_Shift_R:
603     case GDK_Control_L:
604     case GDK_Control_R:
605     case GDK_Caps_Lock:
606     case GDK_Shift_Lock:
607     case GDK_Meta_L:
608     case GDK_Meta_R:
609     case GDK_Alt_L:
610     case GDK_Alt_R:
611     case GDK_Super_L:
612     case GDK_Super_R:
613     case GDK_Hyper_L:
614     case GDK_Hyper_R:
615 	return 1;
616     }
617     return 0;
618 }
619 
620 /* get a 15 bit "almost unique" key sym that includes keyboard modifier
621    info in the top 3 bits */
key_sym_mod(gint key,gint state)622 short key_sym_mod (gint key, gint state)
623 {
624     if (key && !mod_type_key (key)) {
625 	key = toggle_bit (key, 0x1000 * ((state & GDK_SHIFT_MASK) != 0));
626 	key = toggle_bit (key, 0x2000 * ((state & GDK_CONTROL_MASK) != 0));
627 	key = toggle_bit (key, 0x4000 * ((state & GDK_MOD1_MASK) != 0));
628 	key &= 0x7FFF;
629     } else
630 	key = 0;
631     return key;
632 }
633 
634 static gint
gtk_edit_key_press(GtkWidget * widget,GdkEventKey * event)635  gtk_edit_key_press (GtkWidget * widget,
636 		     GdkEventKey * event)
637 {
638     GtkEdit *edit;
639     GtkEditable *editable;
640     gint command = 0, insert = -1, r = 0;
641     guint key, state;
642 
643     g_return_val_if_fail (widget != NULL, FALSE);
644     g_return_val_if_fail (GTK_IS_EDIT (widget), FALSE);
645     g_return_val_if_fail (event != NULL, FALSE);
646 
647     edit = GTK_EDIT (widget);
648     editable = GTK_EDITABLE (widget);
649 
650     if (!edit_translate_key (0, event->keyval, event->state, &command, &insert)) {
651 	return FALSE;
652     }
653     key = event->keyval;
654     state = event->state;
655     if (!command && insert < 0) {	/* no translation took place, so lets see if we have a macro */
656 	if ((key == GDK_r || key == GDK_R) && (state & ControlMask)) {
657 	    command = edit->editor->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
658 	} else {
659 	    command = key_sym_mod (key, state);
660 	    if (command > 0)
661 		command = CK_Macro (command);
662 	}
663     }
664     r = edit_execute_key_command (edit->editor, command, insert);
665     if (r)
666 	edit_update_screen (edit->editor);
667 
668     return r;
669 }
670 
671 /**********************************************************************/
672 /*                              Widget Crap                           */
673 /**********************************************************************/
674 
675 char *home_dir = 0;
676 
get_home_dir(void)677 static void get_home_dir (void)
678 {
679     if (home_dir)		/* already been set */
680 	return;
681     home_dir = getenv ("HOME");
682     if (home_dir)
683 	if (*home_dir) {
684 	    home_dir = strdup (home_dir);
685 	    return;
686 	}
687     home_dir = (getpwuid (geteuid ()))->pw_dir;
688     if (home_dir)
689 	if (*home_dir) {
690 	    home_dir = strdup (home_dir);
691 	    return;
692 	}
693     fprintf (stderr, _("gtkedit.c: HOME environment variable not set and no passwd entry - aborting\n"));
694     abort ();
695 }
696 
697 
gtk_edit_class_init(GtkEditClass * class)698 static void gtk_edit_class_init (GtkEditClass * class)
699 {
700     GtkObjectClass *object_class;
701     GtkWidgetClass *widget_class;
702     GtkEditableClass *editable_class;
703 
704     object_class = (GtkObjectClass *) class;
705     widget_class = (GtkWidgetClass *) class;
706     editable_class = (GtkEditableClass *) class;
707 
708     parent_class = gtk_type_class (gtk_editable_get_type ());
709 
710     object_class->destroy = gtk_edit_destroy;
711 
712     widget_class->realize = gtk_edit_realize;
713     widget_class->unrealize = gtk_edit_unrealize;
714     widget_class->style_set = gtk_edit_style_set;
715     widget_class->draw_focus = gtk_edit_draw_focus;
716     widget_class->size_request = gtk_edit_size_request;
717     widget_class->size_allocate = gtk_edit_size_allocate;
718     widget_class->draw = gtk_edit_draw;
719     widget_class->expose_event = gtk_edit_expose;
720     widget_class->button_press_event = gtk_edit_button_press_release;
721     widget_class->button_release_event = gtk_edit_button_press_release;
722     widget_class->motion_notify_event = gtk_edit_button_motion;
723 
724     widget_class->key_press_event = gtk_edit_key_press;
725 #if 0
726     widget_class->focus_in_event = gtk_edit_focus_in;
727     widget_class->focus_out_event = gtk_edit_focus_out;
728 #endif
729     widget_class->focus_in_event = 0;
730     widget_class->focus_out_event = 0;
731 
732 #if 0
733     editable_class->insert_text = gtk_edit_insert_text;
734     editable_class->delete_text = gtk_edit_delete_text;
735     editable_class->update_text = gtk_edit_update_text;
736     editable_class->get_chars = gtk_edit_get_chars;
737     editable_class->set_selection = gtk_edit_set_selection;
738 #endif
739     editable_class->set_position = gtk_edit_set_position;
740 
741     editable_class->insert_text = 0;
742     editable_class->delete_text = 0;
743     editable_class->update_text = 0;
744     editable_class->get_chars = 0;
745 
746 #if 0
747     editable_class->set_position = 0;
748 #endif
749 
750     get_home_dir ();
751 }
752 
753 extern struct mouse_funcs edit_mouse_funcs;
754 
gtk_edit_init(GtkEdit * edit)755 static void gtk_edit_init (GtkEdit * edit)
756 {
757     static made_directory = 0;
758 
759     GTK_WIDGET_SET_FLAGS (edit, GTK_CAN_FOCUS);
760 
761     edit->editor = edit_init (0, 80, 25, 0, "", "/", 0);
762     edit->editor->macro_i = -1;
763     edit->editor->widget = edit;
764     edit->timer = 0;
765     edit->menubar = 0;
766     edit->status = 0;
767     edit->options = 0;
768     edit->funcs = mouse_funcs_new (edit->editor, &edit_mouse_funcs);
769 
770     gtk_edit_configure_font_dimensions (edit);
771 
772     if (!made_directory) {
773 	mkdir (catstrs (home_dir, EDIT_DIR, NULL), 0700);
774 	made_directory = 1;
775     }
776     GTK_EDITABLE (edit)->editable = TRUE;
777 }
778 
779 guint
gtk_edit_get_type(void)780 gtk_edit_get_type (void)
781 {
782     static guint edit_type = 0;
783 
784     if (!edit_type) {
785 	GtkTypeInfo edit_info =
786 	{
787 	    "GtkEdit",
788 	    sizeof (GtkEdit),
789 	    sizeof (GtkEditClass),
790 	    (GtkClassInitFunc) gtk_edit_class_init,
791 	    (GtkObjectInitFunc) gtk_edit_init,
792 	    (GtkArgSetFunc) NULL,
793 	    (GtkArgGetFunc) NULL,
794 	};
795 
796 	edit_type = gtk_type_unique (gtk_editable_get_type (), &edit_info);
797     }
798     return edit_type;
799 }
800 
801 #include <libgnomeui/gtkcauldron.h>
802 #include <libgnomeui/gnome-stock.h>
803 
gtk_edit_dialog_get_save_file(guchar * dir,guchar * def,guchar * title)804 char *gtk_edit_dialog_get_save_file (guchar * dir, guchar * def, guchar * title)
805 {
806     char *s;
807     s = gtk_dialog_cauldron (
808 				title, GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_GRAB,
809 	    " ( ( (Filename:)d | %Fgxf )f )xf / ( %Bxfgrq || %Bxfgq )f ",
810 				&def, "filename", title,
811 				GNOME_STOCK_BUTTON_OK,
812 				GNOME_STOCK_BUTTON_CANCEL
813 	);
814     if (s == GTK_CAULDRON_ESCAPE || !s || s == GNOME_STOCK_BUTTON_CANCEL)
815 	return 0;
816     return def;
817 }
818 
gtk_edit_dialog_get_load_file(guchar * dir,guchar * def,guchar * title)819 char *gtk_edit_dialog_get_load_file (guchar * dir, guchar * def, guchar * title)
820 {
821     char *s;
822     s = gtk_dialog_cauldron (
823 				title, GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_GRAB,
824 	    " ( ( (Filename:)d | %Fgxf )f )xf / ( %Bxfgrq || %Bxfgq )f ",
825 				&def, "filename", title,
826 				GNOME_STOCK_BUTTON_OK,
827 				GNOME_STOCK_BUTTON_CANCEL
828 	);
829     if (s == GTK_CAULDRON_ESCAPE || !s || s == GNOME_STOCK_BUTTON_CANCEL)
830 	return 0;
831     return def;
832 }
833 
gtk_edit_dialog_message(guchar * heading,char * fmt,...)834 void gtk_edit_dialog_message (guchar * heading, char *fmt,...)
835 {
836     gchar s[8192];
837     va_list ap;
838     va_start (ap, fmt);
839     vsprintf (s, fmt, ap);
840     va_end (ap);
841     gtk_dialog_cauldron (
842 			    heading, GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_GRAB,
843 			    " [ ( %Ld )xf ]xf / ( %Bxfgq )f ",
844 			    s,
845 			    GNOME_STOCK_BUTTON_CANCEL
846 	);
847     return;
848 }
849 
gtk_edit_dialog_query(guchar * heading,guchar * first,...)850 int gtk_edit_dialog_query (guchar * heading, guchar * first,...)
851 {
852     char *buttons[16];
853     char s[1024], *r;
854     int n;
855     va_list ap;
856     va_start (ap, first);
857     n = 0;
858     while ((buttons[n++] = va_arg (ap, char *)) && n < 15);
859     va_end (ap);
860     buttons[n] = 0;
861     strcpy (s, " [ ( %Lxf )xf ]xf / ( ");
862     n = 0;
863     while (buttons[n]) {
864 	strcat (s, " %Bqxf ");
865 	if (!buttons[n])
866 	    break;
867 	strcat (s, " ||");
868 	n++;
869     }
870     strcat (s, " )f");
871     r = gtk_dialog_cauldron (heading, GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_IGNOREENTER | GTK_CAULDRON_GRAB, s, first,
872 			  buttons[0], buttons[1], buttons[2], buttons[3],
873 			  buttons[4], buttons[5], buttons[6], buttons[7],
874 			buttons[8], buttons[9], buttons[10], buttons[11],
875 		      buttons[12], buttons[13], buttons[14], buttons[15]
876 	);
877     n = 0;
878     if (r == GTK_CAULDRON_ESCAPE || !r || r == GNOME_STOCK_BUTTON_CANCEL)
879 	return -1;
880     while (buttons[n]) {
881 	if (!strcmp (buttons[n], r))
882 	    return n;
883 	n++;
884     }
885     return -1;
886 }
887 
gtk_edit_dialog_error(guchar * heading,char * fmt,...)888 void gtk_edit_dialog_error (guchar * heading, char *fmt, ...)
889 {
890     gchar s[8192];
891     va_list ap;
892     va_start (ap, fmt);
893     vsprintf (s, fmt, ap);
894     va_end (ap);
895     gtk_dialog_cauldron (
896 			    heading, GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_GRAB,
897 			    " [ ( %Ld )xf ]xf / ( %Bxfgq )f",
898 			    s,
899 			    GNOME_STOCK_BUTTON_CANCEL
900 	);
901     return;
902 }
903 
904 
905 
906 struct color_matrix_struct {
907     unsigned int R, G, B;
908 } color_matrix[27] =
909 {
910     {0, 0, 0},
911     {0, 0, 128},
912     {0, 0, 255},
913     {0, 139, 0},
914     {0, 139, 139},
915     {0, 154, 205},
916     {0, 255, 0},
917     {0, 250, 154},
918     {0, 255, 255},
919     {139, 37, 0},
920     {139, 0, 139},
921     {125, 38, 205},
922     {139, 117, 0},
923     {127, 127, 127},
924     {123, 104, 238},
925     {127, 255, 0},
926     {135, 206, 235},
927     {127, 255, 212},
928     {238, 0, 0},
929     {238, 18, 137},
930     {238, 0, 238},
931     {205, 102, 0},
932     {248, 183, 183},
933     {224, 102, 255},
934     {238, 238, 0},
935     {238, 230, 133},
936     {248, 248, 255}
937 };
938 
gtk_edit_alloc_colors(GtkEdit * edit,GdkColormap * colormap)939 void gtk_edit_alloc_colors (GtkEdit *edit, GdkColormap *colormap)
940 {
941     int i;
942     for (i = 0; i < 27; i++) {
943 	edit->color[i].red = (gushort) color_matrix[i].R << 8;
944 	edit->color[i].green = (gushort) color_matrix[i].G << 8;
945 	edit->color[i].blue = (gushort) color_matrix[i].B << 8;
946 	if (!gdk_color_alloc (colormap, &edit->color[i]))
947 	    g_warning ("cannot allocate color");
948     }
949     edit->color_last_pixel = 27;
950 }
951 
allocate_color(WEdit * edit,gchar * color)952 int allocate_color (WEdit *edit, gchar *color)
953 {
954     GtkEdit *win;
955     win = (GtkEdit *) edit->widget;
956     if (!color)
957 	return NO_COLOR;
958     if (*color >= '0' && *color <= '9') {
959 	return atoi (color);
960     } else {
961 	int i;
962 	GdkColor c;
963 	if (!color)
964 	    return NO_COLOR;
965 	if (!gdk_color_parse (color, &c))
966 	    return NO_COLOR;
967 	if (!gdk_color_alloc (gtk_widget_get_colormap(GTK_WIDGET (edit->widget)), &c))
968 	    return NO_COLOR;
969 	for (i = 0; i < (GTK_EDIT (edit->widget))->color_last_pixel; i++)
970 	    if (color_palette (i) == c.pixel)
971 		return i;
972 	GTK_EDIT (edit->widget)->color[(GTK_EDIT (edit->widget))->color_last_pixel].pixel = c.pixel;
973 	return (GTK_EDIT (edit->widget))->color_last_pixel++;
974     }
975 }
976 
gtk_edit_set_position(GtkEditable * editable,gint position)977 static void gtk_edit_set_position (GtkEditable * editable, gint position)
978 {
979     WEdit *edit;
980     edit = GTK_EDIT(editable)->editor;
981     edit_cursor_move (edit, position - edit->curs1);
982     edit_move_to_prev_col (edit, 0);
983     edit->force |= REDRAW_PAGE;
984     edit->search_start = 0;
985     edit_update_curs_row (edit);
986 }
987 
988 
989 /* returns 1 on error */
gtk_edit_load_file_from_filename(GtkWidget * edit,const gchar * filename)990 gint gtk_edit_load_file_from_filename (GtkWidget * edit, const gchar * filename)
991 {
992     return edit_load_file_from_filename (GTK_EDIT (edit)->editor, (char *) filename);
993 }
994 
gtk_edit_set_top_line(GtkWidget * e,int line)995 void gtk_edit_set_top_line (GtkWidget * e, int line)
996 {
997     WEdit *edit;
998     edit = GTK_EDIT (e)->editor;
999     edit_move_display (edit, line - edit->num_widget_lines / 2 - 1);
1000     edit->force |= REDRAW_COMPLETELY;
1001 }
1002 
gtk_edit_set_cursor_line(GtkWidget * e,int line)1003 void gtk_edit_set_cursor_line (GtkWidget * e, int line)
1004 {
1005     WEdit *edit;
1006     edit = GTK_EDIT (e)->editor;
1007     edit_move_to_line (edit, line - 1);
1008     edit->force |= REDRAW_COMPLETELY;
1009 }
1010 
about_cb(GtkWidget * widget,void * data)1011 void about_cb (GtkWidget * widget, void *data)
1012 {
1013     gtk_dialog_cauldron ("About", GTK_CAULDRON_TOPLEVEL | GTK_CAULDRON_GRAB, " [ (Mcedit - an editor for the midnight commander\n\
1014 ported from Cooledit - a user friendly text editor for the X Window System.)xf ]xf / ( %Bgqxf )f ", GNOME_STOCK_BUTTON_OK);
1015     return;
1016 }
1017 
gtk_edit_command(GtkEdit * edit,gint command)1018 void gtk_edit_command (GtkEdit * edit, gint command)
1019 {
1020     int r;
1021     gtk_widget_grab_focus (GTK_WIDGET (edit));
1022     r = edit_execute_key_command (edit->editor, command, -1);
1023     if (r)
1024 	edit_update_screen (edit->editor);
1025 }
1026 
gtk_edit_quit(GtkEdit * widget,void * data)1027 void gtk_edit_quit (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Exit); }
1028 
gtk_edit_load_file(GtkEdit * widget,void * data)1029 void gtk_edit_load_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Load); }
gtk_edit_new_file(GtkEdit * widget,void * data)1030 void gtk_edit_new_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_New); }
gtk_edit_save_file(GtkEdit * widget,void * data)1031 void gtk_edit_save_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Save); }
gtk_edit_save_as_file(GtkEdit * widget,void * data)1032 void gtk_edit_save_as_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Save_As); }
gtk_edit_insert_file(GtkEdit * widget,void * data)1033 void gtk_edit_insert_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Insert_File); }
gtk_edit_copy_to_file(GtkEdit * widget,void * data)1034 void gtk_edit_copy_to_file (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Save_Block); }
1035 
gtk_edit_clip_cut(GtkEdit * widget,void * data)1036 void gtk_edit_clip_cut (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_XCut); }
gtk_edit_clip_copy(GtkEdit * widget,void * data)1037 void gtk_edit_clip_copy (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_XStore); }
gtk_edit_clip_paste(GtkEdit * widget,void * data)1038 void gtk_edit_clip_paste (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_XPaste); }
1039 
gtk_edit_toggle_mark(GtkEdit * widget,void * data)1040 void gtk_edit_toggle_mark (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Mark); }
gtk_edit_search(GtkEdit * widget,void * data)1041 void gtk_edit_search (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Find); }
gtk_edit_search_again(GtkEdit * widget,void * data)1042 void gtk_edit_search_again (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Find_Again); }
gtk_edit_replace(GtkEdit * widget,void * data)1043 void gtk_edit_replace (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Replace); }
gtk_edit_copy(GtkEdit * widget,void * data)1044 void gtk_edit_copy (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Copy); }
gtk_edit_move(GtkEdit * widget,void * data)1045 void gtk_edit_move (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Move); }
gtk_edit_delete(GtkEdit * widget,void * data)1046 void gtk_edit_delete (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Remove); }
gtk_edit_undo(GtkEdit * widget,void * data)1047 void gtk_edit_undo (GtkEdit * widget, void *data) { GtkEdit *edit = (GtkEdit *) data ; gtk_edit_command (edit, CK_Undo); }
1048 
1049 #if 0
1050 struct _GnomeUIInfo {
1051     GnomeUIInfoType type;
1052     gchar *label;
1053     gchar *hint;		/* For toolbar items, the tooltip. For menu items, the status bar message */
1054 
1055     /* For an item, toggleitem, or radioitem, procedure to call when activated.
1056        For a subtree, point to the GnomeUIInfo array for that subtree.
1057        For a radioitem lead entry, point to the GnomeUIInfo array for
1058        the radio item group.  For the radioitem array, procedure to
1059        call when activated. For a help item, specifies the help node to load
1060        (or NULL for main prog's name)
1061        For builder data, point to the GnomeUIBuilderData structure for the following items */
1062     gpointer moreinfo;
1063     gpointer user_data;
1064     gpointer unused_data;
1065     GnomeUIPixmapType pixmap_type;
1066     /* Either
1067      * a pointer to the char for the pixmap (GNOME_APP_PIXMAP_DATA),
1068      * a char* for the filename (GNOME_APP_PIXMAP_FILENAME),
1069      * or a char* for the stock pixmap name (GNOME_APP_PIXMAP_STOCK).
1070      */
1071     gpointer pixmap_info;
1072     guint accelerator_key;	/* Accelerator key... Set to 0 to ignore */
1073     GdkModifierType ac_mods;	/* An OR of the masks for the accelerator */
1074     GtkWidget *widget;		/* Filled in by gnome_app_create* */
1075 };
1076 
1077 #endif
1078 
1079 typedef struct _TbItems TbItems;
1080 struct _TbItems {
1081 	char *key, *text, *tooltip, *icon;
1082 	void (*cb) (GtkEdit *, void *);
1083 	GtkWidget *widget; /* will be filled in */
1084 };
1085 
1086 #define TB_PROP 7
1087 
1088 static TbItems tb_items[] =
1089 {
1090     {"F1", "Help", "Interactive help browser", GNOME_STOCK_MENU_BLANK, 0, NULL},
1091     {"F2", "Save", "Save to current file name", GNOME_STOCK_MENU_SAVE, gtk_edit_save_file, NULL},
1092     {"F3", "Mark", "Toggle In/Off invisible marker to highlight text", GNOME_STOCK_MENU_BLANK, gtk_edit_toggle_mark, NULL},
1093     {"F4", "Replc", "Find and replace strings/regular expressions", GNOME_STOCK_MENU_SRCHRPL, gtk_edit_replace, NULL},
1094     {"F5", "Copy", "Copy highlighted block to cursor postition", GNOME_STOCK_MENU_COPY, gtk_edit_copy, NULL},
1095 
1096     {"F6", "Move", "Copy highlighted block to cursor postition", GNOME_STOCK_MENU_BLANK, gtk_edit_move, NULL},
1097     {"F7", "Find", "Find strings/regular expressions", GNOME_STOCK_MENU_SEARCH, gtk_edit_search, NULL},
1098     {"F8", "Dlete", "Delete highlighted text", GNOME_STOCK_MENU_BLANK, gtk_edit_delete, NULL},
1099     {"F9", "Menu", "Pull down menu", GNOME_STOCK_MENU_BLANK, /* gtk_edit_menu*/ 0, NULL},
1100     {"F10", "Quit", "Exit editor", GNOME_STOCK_MENU_QUIT, gtk_edit_quit, NULL},
1101     {0, 0, 0, 0, 0, 0}
1102 };
1103 
create_toolbar(GtkWidget * window,GtkEdit * edit)1104 static GtkWidget *create_toolbar (GtkWidget * window, GtkEdit * edit)
1105 {
1106     GtkWidget *toolbar;
1107     TbItems *t;
1108     toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
1109     for (t = &tb_items[0]; t->text; t++) {
1110 	t->widget = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1111 					     t->text,
1112 					     t->tooltip,
1113 					     0,
1114 			     gnome_stock_pixmap_widget (window, t->icon),
1115 					     t->cb,
1116 					     t->cb ? edit : 0);
1117     }
1118     return toolbar;
1119 }
1120 
1121 /* returns 1 on error */
edit(const char * file,int line)1122 int edit (const char *file, int line)
1123 {
1124     GtkWidget *app;
1125     GtkWidget *edit, *statusbar;
1126 
1127     edit = gtk_edit_new (NULL, NULL);
1128     app = gnome_app_new ("mcedit", (char *) (file ? file : "Mcedit"));
1129 
1130     {
1131 	GnomeUIInfo file_menu[] =
1132 	{
1133 	    {
1134 		GNOME_APP_UI_ITEM, N_ ("Open/Load"), N_ ("Load a different/new file"), gtk_edit_load_file, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN, 'O', GDK_CONTROL_MASK, 0
1135 	    },
1136 	    {
1137 		GNOME_APP_UI_ITEM, N_ ("New"), N_ ("Clear the edit buffer"), gtk_edit_new_file, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_NEW, 'N', GDK_CONTROL_MASK, 0
1138 	    },
1139 	    GNOMEUIINFO_SEPARATOR,
1140 	    {
1141 		GNOME_APP_UI_ITEM, N_ ("Save"), N_ ("Save the current edit buffer to filename"), gtk_edit_save_file, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE, 'S', GDK_CONTROL_MASK, 0
1142 	    },
1143 	    {
1144 		GNOME_APP_UI_ITEM, N_ ("Save As"), N_ ("Save the current edit buffer as filename"), gtk_edit_save_as_file, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE_AS, 'A', GDK_CONTROL_MASK, 0
1145 	    },
1146 	    GNOMEUIINFO_SEPARATOR,
1147 	    {
1148 		GNOME_APP_UI_ITEM, N_ ("Insert File"), N_ ("Insert text from a file"), gtk_edit_insert_file, edit, 0, 0, 0, 'I', GDK_CONTROL_MASK, 0
1149 	    },
1150 	    {
1151 		GNOME_APP_UI_ITEM, N_ ("Copy to file"), N_ ("copy a block to a file"), gtk_edit_copy_to_file, edit, 0, 0, 0, 'C', GDK_CONTROL_MASK, 0
1152 	    },
1153 	    GNOMEUIINFO_SEPARATOR,
1154 	    {
1155 		GNOME_APP_UI_ITEM, N_ ("Exit"), N_ ("Quit editor"), gtk_edit_quit, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_QUIT, 'Q', GDK_CONTROL_MASK, NULL
1156 	    },
1157 	    GNOMEUIINFO_END
1158 	};
1159 
1160 	GnomeUIInfo edit_menu[] =
1161 	{
1162 	    {
1163 		GNOME_APP_UI_ITEM, N_ ("Copy"), N_ ("Copy selection to clipboard"), gtk_edit_clip_copy, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_COPY, 'C', GDK_CONTROL_MASK, 0
1164 	    },
1165 	    {
1166 		GNOME_APP_UI_ITEM, N_ ("Cut"), N_ ("Cut selection to clipboard"), gtk_edit_clip_cut, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CUT, 'X', GDK_CONTROL_MASK, 0
1167 	    },
1168 	    {
1169 		GNOME_APP_UI_ITEM, N_ ("Paste"), N_ ("Paste clipboard"), gtk_edit_clip_paste, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PASTE, 'V', GDK_CONTROL_MASK, 0
1170 	    },
1171 	    GNOMEUIINFO_SEPARATOR,
1172 	    {
1173 		GNOME_APP_UI_ITEM, N_ ("Undo"), N_ ("Go back in time one key press"), gtk_edit_undo, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PASTE, 'U', GDK_CONTROL_MASK, 0
1174 	    },
1175 	    GNOMEUIINFO_END
1176 	};
1177 
1178 	GnomeUIInfo search_menu[] =
1179 	{
1180 	    {
1181 		GNOME_APP_UI_ITEM, N_ ("Find"), N_ ("Find string/regular expression"), gtk_edit_search, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN, 'F', GDK_MOD1_MASK, 0
1182 	    },
1183 	    {
1184 		GNOME_APP_UI_ITEM, N_ ("Find again"), N_ ("Repeat most recent search"), gtk_edit_search_again, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_NEW, 'A', GDK_MOD1_MASK, 0
1185 	    },
1186 	    {
1187 		GNOME_APP_UI_ITEM, N_ ("Search/Replace"), N_ ("Find and replace text/regular expressions"), gtk_edit_replace, edit, 0, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE, 'R', GDK_MOD1_MASK, 0
1188 	    },
1189 	    GNOMEUIINFO_END
1190 	};
1191 
1192 	GnomeUIInfo help_menu[] =
1193 	{
1194 	    {
1195 		GNOME_APP_UI_ITEM,
1196 		N_ ("About..."), N_ ("Info about GNOME hello"),
1197 		about_cb, NULL, NULL,
1198 		GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_ABOUT,
1199 		0, (GdkModifierType) 0, NULL
1200 	    },
1201 #if 0
1202 	    GNOMEUIINFO_SEPARATOR,
1203 	    GNOMEUIINFO_HELP ("hello"),
1204 #endif
1205 	    GNOMEUIINFO_END
1206 	};
1207 
1208 	GnomeUIInfo main_menu[] =
1209 	{
1210 	    GNOMEUIINFO_SUBTREE (N_ ("File"), file_menu),
1211 	    GNOMEUIINFO_SUBTREE (N_ ("Edit"), edit_menu),
1212 	    GNOMEUIINFO_SUBTREE (N_ ("Search/Replace"), search_menu),
1213 	    GNOMEUIINFO_SUBTREE (N_ ("Help"), help_menu),
1214 	    GNOMEUIINFO_END
1215 	};
1216 
1217 	gtk_widget_realize (app);
1218 	statusbar = gtk_label_new (file ? file : "<no-filename>");
1219 	gtk_widget_set_usize (app, 400, 400);
1220 	gnome_app_create_menus (GNOME_APP (app), main_menu);
1221 	gnome_app_set_contents (GNOME_APP (app), edit);
1222 	gnome_app_set_statusbar (GNOME_APP (app), GTK_WIDGET (statusbar));
1223 	GTK_EDIT (edit)->menubar = GNOME_APP (app)->menubar;
1224 	GTK_EDIT (edit)->status = statusbar;
1225 	gnome_app_set_toolbar(GNOME_APP (app), GTK_TOOLBAR(create_toolbar(app, GTK_EDIT (edit))));
1226 	GTK_EDIT(edit)->destroy_me = gtk_widget_destroy;
1227 	GTK_EDIT(edit)->destroy_me_user_data = app;
1228 
1229 	gtk_widget_show (edit);
1230 	gtk_widget_realize (edit);
1231 	if (file)
1232 	    if (*file)
1233 		if (gtk_edit_load_file_from_filename (edit, file)) {
1234 		    gtk_widget_destroy (app);
1235 		    return 1;
1236 		}
1237 	gtk_edit_set_cursor_line (edit, line);
1238 	gtk_widget_show (app);
1239 	gtk_widget_grab_focus (edit);
1240     }
1241     return 0;
1242 }
1243