From 1941bf4cbf30ba6a0b63ae2f881a6f7d6c13a677 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sat, 7 Mar 1998 03:05:36 +0000 Subject: [PATCH] Disallow pasting into non-editable widgets. Fri Mar 6 21:30:05 1998 Owen Taylor * gtk/gtkeditable.c: Disallow pasting into non-editable widgets. * gtk/gtktext.[ch]: -Added scrolling when dragging the selection paste the top/bottom. -Fix some of the problems with displaying the selection state before mouse release. -Disallow pasting into non-editable widgets -Fixed segfault when changing window size -Update the cursor correctly when switching between editable and non-editable * testgtk.c: Added a toggle button for editability for the text widget. --- ChangeLog | 25 ++++- ChangeLog.pre-2-0 | 25 ++++- ChangeLog.pre-2-10 | 25 ++++- ChangeLog.pre-2-2 | 25 ++++- ChangeLog.pre-2-4 | 25 ++++- ChangeLog.pre-2-6 | 25 ++++- ChangeLog.pre-2-8 | 25 ++++- TODO | 9 +- gtk/gtkeditable.c | 15 ++- gtk/gtktext.c | 269 +++++++++++++++++++++++++++++++-------------- gtk/gtktext.h | 2 + gtk/testgtk.c | 79 ++++++------- tests/testgtk.c | 79 ++++++------- 13 files changed, 443 insertions(+), 185 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 3f90d9a839..d3584159f0 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,26 @@ +Fri Mar 6 21:30:05 1998 Owen Taylor + + * gtk/gtkeditable.c: Disallow pasting into non-editable + widgets. + + * gtk/gtktext.[ch]: + + -Added scrolling when dragging the selection + paste the top/bottom. + + -Fix some of the problems with displaying the selection + state before mouse release. + + -Disallow pasting into non-editable widgets + + -Fixed segfault when changing window size + + -Update the cursor correctly when switching between + editable and non-editable + + * testgtk.c: Added a toggle button for editability for + the text widget. + Fri Mar 6 14:47:33 PST 1998 Shawn T. Amundson * Applied gtk-matsu-980205-0 (oops, should be 980305) @@ -45,7 +68,7 @@ Thu Mar 5 01:22:06 1998 Owen Taylor on unparent, to force reallocation if we get adding back to a new parent which is already size-allocated. - * gtk/gtktreeitem.c: Keep track of separate +/- pixmaps + * gtk/gtktreeitem.[ch]: Keep track of separate +/- pixmaps for each colormap, removed the idle hack. * gdk/gdk.c: Don't warn when unable to open XIM method, diff --git a/TODO b/TODO index ca64560fcb..658055a2d4 100644 --- a/TODO +++ b/TODO @@ -168,21 +168,26 @@ TODO AFTER GTK 1.0 - When selecting on a Text or Entry widget, the selection isn't claimed until you release the button, and that shows by the color of the selection. (Which is the real problem - it probably - is OK/better to delay claiming the selection) + is OK/better to delay claiming the selection) [fixed] - Related to the above, when you Shift/arrow to select text, the selected text doesn't show that you have the selection immediately. - - Selecting an entire line with triple-click doesn't work write - + - Selecting an entire line with triple-click doesn't work right - it should select the wrapped portion too. - Selecting an entire line should probably select the newline as well, so when the selection is cut/deleted, the newline goes along. + - Inserting text in a different property - problems? Shouldn't + split the last position off in any case. + - Do something about the bg pixmap situation. (It will produce garbage when editing is enabled) + - "Copy" removes selection + Improvements: - Finish making the key bindings consistent between the Entry diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c index 31628a408c..4a5ec13f22 100644 --- a/gtk/gtkeditable.c +++ b/gtk/gtkeditable.c @@ -577,8 +577,14 @@ gtk_editable_selection_received (GtkWidget *widget, void gtk_editable_delete_selection (GtkEditable *editable) { - guint start = editable->selection_start_pos; - guint end = editable->selection_end_pos; + guint start; + guint end; + + if (!editable->editable) + return; + + start = editable->selection_start_pos; + end = editable->selection_end_pos; editable->selection_start_pos = 0; editable->selection_end_pos = 0; @@ -655,8 +661,9 @@ gtk_editable_copy_clipboard (GtkEditable *editable, guint32 time) void gtk_editable_paste_clipboard (GtkEditable *editable, guint32 time) { - gtk_selection_convert (GTK_WIDGET(editable), - clipboard_atom, ctext_atom, time); + if (editable->editable) + gtk_selection_convert (GTK_WIDGET(editable), + clipboard_atom, ctext_atom, time); } void diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 06ade9a05c..edb56c39b1 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -40,6 +40,7 @@ #define DEFAULT_TAB_STOP_WIDTH 4 #define SCROLL_PIXELS 5 #define KEY_SCROLL_PIXELS 10 +#define SCROLL_TIME 100 #define SET_PROPERTY_MARK(m, p, o) do { \ (m)->property = (p); \ @@ -154,7 +155,7 @@ struct _LineParams static void gtk_text_class_init (GtkTextClass *klass); static void gtk_text_init (GtkText *text); -static void gtk_text_finalize (GtkObject *object); +static void gtk_text_destroy (GtkObject *object); static void gtk_text_realize (GtkWidget *widget); static void gtk_text_unrealize (GtkWidget *widget); static void gtk_text_draw_focus (GtkWidget *widget); @@ -218,7 +219,8 @@ static void decrement_mark_n (GtkPropertyMark* mark, gint n); static void move_mark_n (GtkPropertyMark* mark, gint n); static GtkPropertyMark find_mark (GtkText* text, guint mark_position); static GtkPropertyMark find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near); -static void find_line_containing_point (GtkText* text, guint point); +static void find_line_containing_point (GtkText* text, guint point, + gboolean scroll); static TextProperty* new_text_property (GdkFont* font, GdkColor* fore, GdkColor* back, guint length); /* Display */ @@ -251,7 +253,8 @@ static gint drawn_cursor_max (GtkText* text); static void expose_text (GtkText* text, GdkRectangle *area, gboolean cursor); /* Search and Placement. */ -static void find_cursor (GtkText* text); +static void find_cursor (GtkText* text, + gboolean scroll); static void find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_height); @@ -443,7 +446,7 @@ gtk_text_class_init (GtkTextClass *class) parent_class = gtk_type_class (gtk_editable_get_type ()); - object_class->finalize = gtk_text_finalize; + object_class->destroy = gtk_text_destroy; widget_class->realize = gtk_text_realize; widget_class->unrealize = gtk_text_unrealize; @@ -487,6 +490,9 @@ gtk_text_init (GtkText *text) text->tab_stops = g_list_prepend (text->tab_stops, (void*)8); text->line_wrap = TRUE; + + text->timer = 0; + GTK_EDITABLE(text)->editable = FALSE; } @@ -511,6 +517,11 @@ gtk_text_set_editable (GtkText *text, g_return_if_fail (GTK_IS_TEXT (text)); GTK_EDITABLE(text)->editable = (editable != FALSE); + + if (editable) + draw_cursor (text, TRUE); + else + undraw_cursor (text, TRUE); } void @@ -644,16 +655,14 @@ gtk_text_insert (GtkText *text, g_return_if_fail (text != NULL); g_return_if_fail (GTK_IS_TEXT (text)); - g_assert (GTK_WIDGET_REALIZED (text)); + /* This must be because we need to have the style set up. */ + g_assert (GTK_WIDGET_REALIZED(text)); if (fore == NULL) fore = >K_WIDGET (text)->style->text[GTK_STATE_NORMAL]; if (back == NULL) back = >K_WIDGET (text)->style->base[GTK_STATE_NORMAL]; - /* This must be because we need to have the style set up. */ - g_assert (GTK_WIDGET_REALIZED(text)); - if (length < 0) length = strlen (chars); @@ -662,7 +671,7 @@ gtk_text_insert (GtkText *text, if (!text->freeze && (text->line_start_cache != NULL)) { - find_line_containing_point (text, text->point.index); + find_line_containing_point (text, text->point.index, TRUE); old_height = total_line_height (text, text->current_line, 1); for (i=0; ifreeze && (text->line_start_cache != NULL)) { - find_line_containing_point (text, text->point.index); + find_line_containing_point (text, text->point.index, TRUE); compute_lines_pixels (text, nchars, &old_lines, &old_height); } @@ -813,7 +822,7 @@ gtk_text_get_chars (GtkEditable *editable, static void -gtk_text_finalize (GtkObject *object) +gtk_text_destroy (GtkObject *object) { GtkText *text; @@ -822,19 +831,22 @@ gtk_text_finalize (GtkObject *object) text = (GtkText *)object; if (text->hadj) - gtk_object_unref (GTK_OBJECT (text->hadj)); - if (text->vadj) - gtk_object_unref (GTK_OBJECT (text->vadj)); - -#ifdef USE_XIM - if (GTK_EDITABLE(text)->ic) { - gdk_ic_destroy (GTK_EDITABLE(text)->ic); - GTK_EDITABLE(text)->ic = NULL; + gtk_object_unref (GTK_OBJECT (text->hadj)); + text->hadj = NULL; + } + if (text->vadj) + { + gtk_object_unref (GTK_OBJECT (text->vadj)); + text->vadj = NULL; + } + if (text->timer) + { + gtk_timeout_remove (text->timer); + text->timer = 0; } -#endif - GTK_OBJECT_CLASS(parent_class)->finalize (object); + GTK_OBJECT_CLASS(parent_class)->destroy (object); } static void @@ -1229,6 +1241,35 @@ gtk_text_expose (GtkWidget *widget, return FALSE; } +static gint +gtk_text_scroll_timeout (gpointer data) +{ + GtkText *text; + GdkEventMotion event; + + gint x, y; + GdkModifierType mask; + + g_return_val_if_fail (GTK_IS_TEXT (data), FALSE); + + text = GTK_TEXT (data); + + text->timer = 0; + gdk_window_get_pointer (text->text_area, &x, &y, &mask); + + if (!(mask & (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK))) + return FALSE; + + event.is_hint = 0; + event.x = x; + event.y = y; + event.state = mask; + + gtk_text_motion_notify (GTK_WIDGET (text), &event); + + return FALSE; +} + static gint gtk_text_button_press (GtkWidget *widget, GdkEventButton *event) @@ -1262,9 +1303,13 @@ gtk_text_button_press (GtkWidget *widget, find_mouse_cursor (text, event->x, event->y); draw_cursor (text, FALSE); + /* Set it now, so we display things right. We'll unset it + * later if things don't work out */ + editable->has_selection = TRUE; gtk_text_set_selection (GTK_EDITABLE(text), text->cursor_mark.index, text->cursor_mark.index); + break; case GDK_2BUTTON_PRESS: @@ -1281,7 +1326,7 @@ gtk_text_button_press (GtkWidget *widget, } else if (event->type == GDK_BUTTON_PRESS) { - if (event->button == 2) + if ((event->button == 2) && editable->editable) { if (editable->selection_start_pos == editable->selection_end_pos || editable->has_selection) @@ -1304,6 +1349,10 @@ gtk_text_button_press (GtkWidget *widget, gtk_text_set_selection (GTK_EDITABLE(text), text->cursor_mark.index, text->cursor_mark.index); + + editable->has_selection = FALSE; + if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) + gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time); } } @@ -1321,7 +1370,13 @@ gtk_text_button_release (GtkWidget *widget, g_return_val_if_fail (event != NULL, FALSE); text = GTK_TEXT (widget); - + + if (text->timer) + { + gtk_timeout_remove (text->timer); + text->timer = 0; + } + if (event->button == 1) { text = GTK_TEXT (widget); @@ -1335,11 +1390,10 @@ gtk_text_button_release (GtkWidget *widget, if (gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time)) - { - editable->has_selection = TRUE; - gtk_text_update_text (editable, editable->selection_start_pos, - editable->selection_end_pos); - } + editable->has_selection = TRUE; + else + gtk_text_update_text (editable, editable->selection_start_pos, + editable->selection_end_pos); } else { @@ -1350,19 +1404,23 @@ gtk_text_button_release (GtkWidget *widget, else if (event->button == 3) { gtk_grab_remove (widget); - if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window) - gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time); } + undraw_cursor (text, FALSE); + find_cursor (text, TRUE); + draw_cursor (text, FALSE); + return FALSE; } static gint gtk_text_motion_notify (GtkWidget *widget, - GdkEventMotion *event) + GdkEventMotion *event) { GtkText *text; - gint x; + gint x, y; + gint height; + GdkModifierType mask; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE); @@ -1371,11 +1429,37 @@ gtk_text_motion_notify (GtkWidget *widget, text = GTK_TEXT (widget); x = event->x; + y = event->y; + mask = event->state; if (event->is_hint || (text->text_area != event->window)) - gdk_window_get_pointer (text->text_area, &x, NULL, NULL); + { + gdk_window_get_pointer (text->text_area, &x, &y, &mask); + } + + if (!(mask & (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK))) + return FALSE; + + gdk_window_get_size (text->text_area, NULL, &height); + + if ((y < 0) || (y > height)) + { + if (text->timer == 0) + { + text->timer = gtk_timeout_add (SCROLL_TIME, + gtk_text_scroll_timeout, + text); + + if (y < 0) + scroll_int (text, y/2); + else + scroll_int (text, (y - height)/2); + } + else + return FALSE; + } undraw_cursor (GTK_TEXT (widget), FALSE); - find_mouse_cursor (GTK_TEXT (widget), event->x, event->y); + find_mouse_cursor (GTK_TEXT (widget), x, y); draw_cursor (GTK_TEXT (widget), FALSE); gtk_text_set_selection (GTK_EDITABLE(text), @@ -1404,7 +1488,11 @@ gtk_text_insert_text (GtkEditable *editable, GtkText *text = GTK_TEXT (editable); gtk_text_set_point (text, *position); - gtk_text_insert (text, NULL, NULL, NULL, new_text, new_text_length); + gtk_text_insert (text, + MARK_CURRENT_FONT (&text->point), + MARK_CURRENT_FORE (&text->point), + MARK_CURRENT_BACK (&text->point), + new_text, new_text_length); *position = text->point.index; } @@ -2067,7 +2155,7 @@ delete_expose (GtkText* text, gint nchars, guint old_lines, guint old_pixels) text->cursor_mark = text->point; - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); @@ -2173,7 +2261,7 @@ insert_expose (GtkText* text, guint old_pixels, gint nchars, text->cursor_mark = text->point; - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); @@ -2380,8 +2468,8 @@ insert_text_property (GtkText* text, GdkFont* font, forward_prop->length = MARK_OFFSET(mark); new_prop_forward->data = new_text_property(forward_prop->font->gdk_font, - fore, - back, + &forward_prop->fore_color, + &forward_prop->back_color, old_length - forward_prop->length); new_prop->data = new_text_property(font, fore, back, len); @@ -2593,8 +2681,13 @@ find_mark_near (GtkText* text, guint mark_position, const GtkPropertyMark* near) return mark; } +/* This routine must be called with scroll == FALSE, only when + * point is at least partially on screen + */ + static void -find_line_containing_point (GtkText* text, guint point) +find_line_containing_point (GtkText* text, guint point, + gboolean scroll) { GList* cache; gint height; @@ -2608,7 +2701,7 @@ find_line_containing_point (GtkText* text, guint point) return; } - while ( ( (text->first_cut_pixels != 0) && + while ( ( scroll && (text->first_cut_pixels != 0) && (CACHE_DATA(text->line_start_cache->next).start.index > point) ) || ( (text->first_cut_pixels == 0) && (CACHE_DATA(text->line_start_cache).start.index > point) ) ) @@ -2634,14 +2727,20 @@ find_line_containing_point (GtkText* text, guint point) TEXT_SHOW_LINE (text, cache, "cache"); - lph = pixel_height_of (text, cache->next); + if (cache->next == NULL) + fetch_lines_forward (text, 1); - while (lph > height || lph == 0) + if (scroll) { - TEXT_SHOW_LINE (text, cache, "cache"); - TEXT_SHOW_LINE (text, cache->next, "cache->next"); - scroll_int (text, LINE_HEIGHT(CACHE_DATA(cache->next))); lph = pixel_height_of (text, cache->next); + + while (lph > height || lph == 0) + { + TEXT_SHOW_LINE (text, cache, "cache"); + TEXT_SHOW_LINE (text, cache->next, "cache->next"); + scroll_int (text, LINE_HEIGHT(CACHE_DATA(cache->next))); + lph = pixel_height_of (text, cache->next); + } } } @@ -2769,12 +2868,12 @@ find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_hei } static void -find_cursor (GtkText* text) +find_cursor (GtkText* text, gboolean scroll) { if (!text->has_cursor) return; - find_line_containing_point (text, text->cursor_mark.index); + find_line_containing_point (text, text->cursor_mark.index, scroll); g_assert (text->cursor_mark.index >= text->first_line_start_index); @@ -2794,8 +2893,8 @@ find_mouse_cursor_at_line (GtkText *text, const LineParams* lp, GtkPropertyMark mark = lp->start; TabStopMark tab_mark = lp->tab_cont.tab_start; - guint char_width = find_char_width(text, &mark, &tab_mark); - guint pixel_width = LINE_START_PIXEL (*lp) + (char_width+1)/2; + gint char_width = find_char_width(text, &mark, &tab_mark); + gint pixel_width = LINE_START_PIXEL (*lp) + (char_width+1)/2; text->cursor_pos_y = line_pixel_height; @@ -2831,29 +2930,26 @@ find_mouse_cursor_at_line (GtkText *text, const LineParams* lp, static void find_mouse_cursor (GtkText* text, gint x, gint y) { - if (GTK_EDITABLE(text)->editable) + gint pixel_height; + GList* cache = text->line_start_cache; + + g_assert (cache); + + pixel_height = - text->first_cut_pixels; + + text->has_cursor = 1; + + for (; cache; cache = cache->next) { - gint pixel_height; - GList* cache = text->line_start_cache; - - g_assert (cache); - - pixel_height = - text->first_cut_pixels; - - text->has_cursor = 1; - - for (; cache; cache = cache->next) + pixel_height += LINE_HEIGHT(CACHE_DATA(cache)); + + if (y < pixel_height || !cache->next) { - pixel_height += LINE_HEIGHT(CACHE_DATA(cache)); - - if (y < pixel_height || !cache->next) - { - find_mouse_cursor_at_line (text, &CACHE_DATA(cache), pixel_height, x); - - find_cursor (text); - - return; - } + find_mouse_cursor_at_line (text, &CACHE_DATA(cache), pixel_height, x); + + find_cursor (text, FALSE); + + return; } } } @@ -2967,7 +3063,7 @@ move_cursor_ver (GtkText *text, int count) text->cursor_mark = mark; - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -2990,7 +3086,7 @@ move_cursor_hor (GtkText *text, int count) move_mark_n (&text->cursor_mark, count); - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -3020,7 +3116,7 @@ gtk_text_move_forward_word (GtkText *text) isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index))) advance_mark (&text->cursor_mark); - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -3037,7 +3133,7 @@ gtk_text_move_backward_word (GtkText *text) isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index-1))) decrement_mark (&text->cursor_mark); - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -3046,7 +3142,7 @@ gtk_text_move_beginning_of_line (GtkText *text) { undraw_cursor (text, FALSE); text->cursor_mark = CACHE_DATA(text->current_line).start; - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -3055,7 +3151,7 @@ gtk_text_move_end_of_line (GtkText *text) { undraw_cursor (text, FALSE); text->cursor_mark = CACHE_DATA(text->current_line).end; - find_cursor (text); + find_cursor (text, TRUE); draw_cursor (text, FALSE); } @@ -3869,13 +3965,17 @@ draw_line_wrap (GtkText* text, guint height /* baseline height */) static void undraw_cursor (GtkText* text, gint absolute) { + GtkEditable *editable = (GtkEditable *)text; + TDEBUG (("in undraw_cursor\n")); if (absolute) text->cursor_drawn_level = 0; - if (text->has_cursor && (text->cursor_drawn_level ++ == 0) && - (GTK_EDITABLE(text)->selection_start_pos == GTK_EDITABLE(text)->selection_end_pos)) + if ((text->cursor_drawn_level ++ == 0) && + text->has_cursor && + (editable->selection_start_pos == editable->selection_end_pos) && + GTK_WIDGET_DRAWABLE (text)) { GdkFont* font; @@ -3960,13 +4060,18 @@ drawn_cursor_max (GtkText* text) static void draw_cursor (GtkText* text, gint absolute) { + GtkEditable *editable = (GtkEditable *)text; + TDEBUG (("in draw_cursor\n")); if (absolute) text->cursor_drawn_level = 1; - if (text->has_cursor && (--text->cursor_drawn_level == 0) && - (GTK_EDITABLE(text)->selection_start_pos == GTK_EDITABLE(text)->selection_end_pos)) + if ((--text->cursor_drawn_level == 0) && + text->has_cursor && + editable->editable && + (editable->selection_start_pos == editable->selection_end_pos) && + GTK_WIDGET_DRAWABLE (text)) { GdkFont* font; @@ -4145,7 +4250,7 @@ recompute_geometry (GtkText* text) FetchLinesPixels, height + text->first_cut_pixels); - find_cursor (text); + find_cursor (text, TRUE); } /**********************************************************************/ diff --git a/gtk/gtktext.h b/gtk/gtktext.h index b35d129cfa..19c507a1ee 100644 --- a/gtk/gtktext.h +++ b/gtk/gtktext.h @@ -144,6 +144,8 @@ struct _GtkText GList *tab_stops; gint default_tab_width; + /* Timer used for auto-scrolling off ends */ + guint32 timer; }; struct _GtkTextClass diff --git a/gtk/testgtk.c b/gtk/testgtk.c index f8068bee5a..4978c6d1e3 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -2175,7 +2175,7 @@ create_entry () gtk_widget_show (cb); editable_check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (box2), editable_check, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", GTK_SIGNAL_FUNC(entry_toggle_editable), entry); gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(editable_check), TRUE); @@ -3288,7 +3288,6 @@ text_toggle_editable (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } - /* * GtkText */ @@ -3306,10 +3305,14 @@ create_text () GtkWidget *vscrollbar; GtkWidget *text; + FILE *infile; + if (!window) { window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (window, "text window"); + gtk_widget_set_usize (window, 500, 500); + gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC(destroy_window), @@ -3341,70 +3344,56 @@ create_text () text = gtk_text_new (NULL, NULL); gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1); + gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); gtk_widget_show (text); hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj); gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0); gtk_widget_show (hscrollbar); vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, - GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); gtk_widget_show (vscrollbar); gtk_text_freeze (GTK_TEXT (text)); gtk_widget_realize (text); + infile = fopen("testgtk.c", "r"); + + if (infile) + { + char buffer[1024]; + int nchars; + + while (1) + { + nchars = fread(buffer, 1, 1024, infile); + gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, + NULL, buffer, nchars); + + if (nchars < 1024) + break; + } + + fclose (infile); + } + gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "spencer blah blah blah\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "kimball\n", -1); + "And even ", -1); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, - "is\n", -1); + "colored", -1); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "a\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "wuss.\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "but\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "josephine\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "(his\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "girlfriend\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "is\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "not).\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "why?\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "because\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "spencer\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "puked\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "last\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "night\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "but\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "josephine\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "did\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "not", -1); + "text", -1); gtk_text_thaw (GTK_TEXT (text)); editable_check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (box2), editable_check, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", GTK_SIGNAL_FUNC(text_toggle_editable), text); gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(editable_check), TRUE); diff --git a/tests/testgtk.c b/tests/testgtk.c index f8068bee5a..4978c6d1e3 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -2175,7 +2175,7 @@ create_entry () gtk_widget_show (cb); editable_check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (box2), editable_check, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", GTK_SIGNAL_FUNC(entry_toggle_editable), entry); gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(editable_check), TRUE); @@ -3288,7 +3288,6 @@ text_toggle_editable (GtkWidget *checkbutton, GTK_TOGGLE_BUTTON(checkbutton)->active); } - /* * GtkText */ @@ -3306,10 +3305,14 @@ create_text () GtkWidget *vscrollbar; GtkWidget *text; + FILE *infile; + if (!window) { window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_set_name (window, "text window"); + gtk_widget_set_usize (window, 500, 500); + gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC(destroy_window), @@ -3341,70 +3344,56 @@ create_text () text = gtk_text_new (NULL, NULL); gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1); + gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); gtk_widget_show (text); hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj); gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0); gtk_widget_show (hscrollbar); vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj); gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1, - GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); + GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); gtk_widget_show (vscrollbar); gtk_text_freeze (GTK_TEXT (text)); gtk_widget_realize (text); + infile = fopen("testgtk.c", "r"); + + if (infile) + { + char buffer[1024]; + int nchars; + + while (1) + { + nchars = fread(buffer, 1, 1024, infile); + gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, + NULL, buffer, nchars); + + if (nchars < 1024) + break; + } + + fclose (infile); + } + gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "spencer blah blah blah\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "kimball\n", -1); + "And even ", -1); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->bg[GTK_STATE_NORMAL], NULL, - "is\n", -1); + "colored", -1); gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "a\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "wuss.\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "but\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "josephine\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "(his\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "girlfriend\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "is\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "not).\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "why?\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "because\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "spencer\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "puked\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "last\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "night\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "but\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "josephine\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "did\n", -1); - gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL, - "not", -1); + "text", -1); gtk_text_thaw (GTK_TEXT (text)); editable_check = gtk_check_button_new_with_label("Editable"); - gtk_box_pack_start (GTK_BOX (box2), editable_check, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (box2), editable_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(editable_check), "toggled", GTK_SIGNAL_FUNC(text_toggle_editable), text); gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(editable_check), TRUE);