From a291b0be4c5e90f7e1a15c6de8e8f451c70773d1 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 26 Oct 2000 23:05:43 +0000 Subject: [PATCH] add new marshallers used by the text widget 2000-10-26 Havoc Pennington * gtk/gtkmarshal.list: add new marshallers used by the text widget * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller types * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix marshaller types * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, gtk/gtktextdisplay.c: We need to preserve Tk copyrights and license on these files. * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this work. * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to runtime random number different for each tree, instead of a constant I made up. --- ChangeLog | 21 +++ ChangeLog.pre-2-0 | 21 +++ ChangeLog.pre-2-10 | 21 +++ ChangeLog.pre-2-2 | 21 +++ ChangeLog.pre-2-4 | 21 +++ ChangeLog.pre-2-6 | 21 +++ ChangeLog.pre-2-8 | 21 +++ gtk/gtkmarshal.list | 3 + gtk/gtkmarshalers.list | 3 + gtk/gtktextbtree.c | 8 +- gtk/gtktextbuffer.c | 4 +- gtk/gtktextdisplay.c | 28 +++- gtk/gtktextdisplay.h | 57 ++++++- gtk/gtktextiter.c | 364 +++++++++++++++++++++++++++++++++++++++-- gtk/gtktextiter.h | 23 +-- gtk/gtktextlayout.c | 31 +++- gtk/gtktextlayout.h | 57 ++++++- gtk/gtktexttagtable.c | 2 +- gtk/gtktextview.c | 2 +- gtk/testtext.c | 78 +++++++-- tests/testtext.c | 78 +++++++-- 21 files changed, 816 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81d80908ef..0656e8624a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 81d80908ef..0656e8624a 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,24 @@ +2000-10-26 Havoc Pennington + + * gtk/gtkmarshal.list: add new marshallers used by the text widget + + * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): fix marshaller + types + + * gtk/gtktexttagtable.c (gtk_text_tag_table_class_init): fix + marshaller types + + * gtk/gtktextlayout.h, gtk/gtktextlayout.c, gtk/gtktextdisplay.h, + gtk/gtktextdisplay.c: We need to preserve Tk copyrights and + license on these files. + + * gtk/gtktextiter.c (gtk_text_iter_backward_search): Make this + work. + + * gtk/gtktextbtree.c (gtk_text_btree_new): init stamps to + runtime random number different for each tree, instead of + a constant I made up. + Thu Oct 26 07:36:16 2000 Tim Janik * gtk/Makefile.am: buncha cleanups, kludged build sources diff --git a/gtk/gtkmarshal.list b/gtk/gtkmarshal.list index 1395f1da18..bebc4ff36c 100644 --- a/gtk/gtkmarshal.list +++ b/gtk/gtkmarshal.list @@ -49,11 +49,14 @@ VOID:INT,INT,INT,INT VOID:INT,INT,POINTER VOID:OBJECT VOID:POINTER +VOID:POINTER,BOOLEAN VOID:POINTER,INT VOID:POINTER,INT,INT,POINTER,UINT,UINT VOID:POINTER,INT,POINTER VOID:POINTER,POINTER +VOID:POINTER,POINTER,BOOLEAN VOID:POINTER,POINTER,INT +VOID:POINTER,POINTER,INT,BOOLEAN VOID:POINTER,POINTER,INT,INT VOID:POINTER,POINTER,POINTER VOID:POINTER,POINTER,UINT,UINT diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list index 1395f1da18..bebc4ff36c 100644 --- a/gtk/gtkmarshalers.list +++ b/gtk/gtkmarshalers.list @@ -49,11 +49,14 @@ VOID:INT,INT,INT,INT VOID:INT,INT,POINTER VOID:OBJECT VOID:POINTER +VOID:POINTER,BOOLEAN VOID:POINTER,INT VOID:POINTER,INT,INT,POINTER,UINT,UINT VOID:POINTER,INT,POINTER VOID:POINTER,POINTER +VOID:POINTER,POINTER,BOOLEAN VOID:POINTER,POINTER,INT +VOID:POINTER,POINTER,INT,BOOLEAN VOID:POINTER,POINTER,INT,INT VOID:POINTER,POINTER,POINTER VOID:POINTER,POINTER,UINT,UINT diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 5b1f98430b..59c00824e9 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -394,9 +394,11 @@ gtk_text_btree_new (GtkTextTagTable *table, tree->views = NULL; /* Set these to values that are unlikely to be found - in random memory garbage. */ - tree->chars_changed_stamp = 49; - tree->segments_changed_stamp = 243; + * in random memory garbage, and also avoid + * duplicates between tree instances. + */ + tree->chars_changed_stamp = g_random_int (); + tree->segments_changed_stamp = g_random_int (); tree->end_iter_line_stamp = tree->chars_changed_stamp - 1; tree->end_iter_line = NULL; diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 739cfe69b4..dc43d0389d 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -137,7 +137,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass) GTK_RUN_LAST, GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkTextBufferClass, insert_text), - gtk_marshal_VOID__POINTER_POINTER_INT_INT, + gtk_marshal_VOID__POINTER_POINTER_INT_BOOLEAN, GTK_TYPE_NONE, 4, GTK_TYPE_POINTER, @@ -150,7 +150,7 @@ gtk_text_buffer_class_init (GtkTextBufferClass *klass) GTK_RUN_LAST, GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkTextBufferClass, delete_text), - gtk_marshal_VOID__POINTER_POINTER_INT, + gtk_marshal_VOID__POINTER_POINTER_BOOLEAN, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, diff --git a/gtk/gtktextdisplay.c b/gtk/gtktextdisplay.c index d5cd2ed336..fd0499de43 100644 --- a/gtk/gtktextdisplay.c +++ b/gtk/gtktextdisplay.c @@ -5,6 +5,26 @@ * Copyright (c) 2000 Red Hat, Inc. * Tk->Gtk port by Havoc Pennington * + * This file can be used under your choice of two licenses, the LGPL + * and the original Tk license. + * + * LGPL: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Original Tk license: * * This software is copyrighted by the Regents of the University of * California, Sun Microsystems, Inc., and other parties. The @@ -45,7 +65,13 @@ * foregoing, the authors grant the U.S. Government and others acting * in its behalf permission to use and distribute the software in * accordance with the terms specified in this license. - * + * + */ +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtktextdisplay.h" diff --git a/gtk/gtktextdisplay.h b/gtk/gtktextdisplay.h index 84504c692a..acbc5f9727 100644 --- a/gtk/gtktextdisplay.h +++ b/gtk/gtktextdisplay.h @@ -1,6 +1,15 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald +/* gtktextdisplay.c - display layed-out text * + * Copyright (c) 1992-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 2000 Red Hat, Inc. + * Tk->Gtk port by Havoc Pennington + * + * This file can be used under your choice of two licenses, the LGPL + * and the original Tk license. + * + * LGPL: + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -14,8 +23,50 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Original Tk license: + * + * This software is copyrighted by the Regents of the University of + * California, Sun Microsystems, Inc., and other parties. The + * following terms apply to all files associated with the software + * unless explicitly disclaimed in individual files. + * + * The authors hereby grant permission to use, copy, modify, + * distribute, and license this software and its documentation for any + * purpose, provided that existing copyright notices are retained in + * all copies and that this notice is included verbatim in any + * distributions. No written agreement, license, or royalty fee is + * required for any of the authorized uses. Modifications to this + * software may be copyrighted by their authors and need not follow + * the licensing terms described here, provided that the new terms are + * clearly indicated on the first page of each file where they apply. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL + * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, + * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, + * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf of the + * U.S. government, the Government shall have only "Restricted Rights" + * in the software and related documentation as defined in the Federal + * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + * are acquiring the software on behalf of the Department of Defense, + * the software shall be classified as "Commercial Computer Software" + * and the Government shall have only "Restricted Rights" as defined + * in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others acting + * in its behalf permission to use and distribute the software in + * accordance with the terms specified in this license. + * */ - /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog diff --git a/gtk/gtktextiter.c b/gtk/gtktextiter.c index 32f85be9a2..d4aefe3ef4 100644 --- a/gtk/gtktextiter.c +++ b/gtk/gtktextiter.c @@ -2172,7 +2172,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter) check_invariants(iter); - new_line = gtk_text_line_previous(real->line); + new_line = gtk_text_line_previous (real->line); offset_will_change = FALSE; if (real->line_char_offset > 0) @@ -2182,7 +2182,7 @@ gtk_text_iter_backward_line(GtkTextIter *iter) { real->line = new_line; - adjust_line_number(real, -1); + adjust_line_number (real, -1); } else { @@ -2200,19 +2200,18 @@ gtk_text_iter_backward_line(GtkTextIter *iter) /* Find first segment in line */ real->any_segment = real->line->segments; - real->segment = gtk_text_line_byte_to_segment(real->line, - 0, &offset); + real->segment = gtk_text_line_byte_to_segment (real->line, + 0, &offset); g_assert(offset == 0); - /* Note that if we are on the first line, we snap to the start - of the first line and return TRUE, so TRUE means the - iterator changed, not that the line changed; this is maybe - a bit weird. I'm not sure there's an obvious right thing - to do though. - */ + /* Note that if we are on the first line, we snap to the start of + * the first line and return TRUE, so TRUE means the iterator + * changed, not that the line changed; this is maybe a bit + * weird. I'm not sure there's an obvious right thing to do though. + */ - check_invariants(iter); + check_invariants (iter); return TRUE; } @@ -3048,7 +3047,20 @@ gtk_text_iter_forward_search (const GtkTextIter *iter, g_return_val_if_fail (str != NULL, FALSE); if (*str == '\0') - return TRUE; /* we found the empty string */ + { + /* If we can move one char, return the empty string there */ + match = *iter; + if (gtk_text_iter_next_char (&match)) + { + if (match_start) + *match_start = match; + if (match_end) + *match_end = match; + return TRUE; + } + else + return FALSE; + } /* locate all lines */ @@ -3085,17 +3097,332 @@ gtk_text_iter_forward_search (const GtkTextIter *iter, return retval; } -gboolean -gtk_text_iter_backward_search (GtkTextIter *iter, - const char *str, - gboolean visible_only, - gboolean slice) +static gboolean +vectors_equal_ignoring_trailing (gchar **vec1, + gchar **vec2) { + /* Ignores trailing chars in vec2's last line */ + + gchar **i1, **i2; + + i1 = vec1; + i2 = vec2; + + while (*i1 && *i2) + { + if (strcmp (*i1, *i2) != 0) + { + if (*(i2 + 1) == NULL) /* if this is the last line */ + { + gint len1 = strlen (*i1); + gint len2 = strlen (*i2); + + if (len2 >= len1 && + strncmp (*i1, *i2, len1) == 0) + { + /* We matched ignoring the trailing stuff in vec2 */ + return TRUE; + } + else + { + return FALSE; + } + } + else + { + return FALSE; + } + } + ++i1; + ++i2; + } + + if (*i1 || *i2) + { + return FALSE; + } + else + return TRUE; +} + +typedef struct _LinesWindow LinesWindow; + +struct _LinesWindow +{ + gint n_lines; + gchar **lines; + GtkTextIter first_line_start; + GtkTextIter first_line_end; + gboolean slice; + gboolean visible_only; +}; + +static void +lines_window_init (LinesWindow *win, + const GtkTextIter *start) +{ + gint i; + GtkTextIter line_start; + GtkTextIter line_end; + + /* If we start on line 1, there are 2 lines to search (0 and 1), so + * n_lines can be 2. + */ + if (gtk_text_iter_is_first (start) || + gtk_text_iter_get_line (start) + 1 < win->n_lines) + { + /* Already at the end, or not enough lines to match */ + win->lines = g_new0 (gchar*, 1); + *win->lines = NULL; + return; + } + + line_start = *start; + line_end = *start; + + /* Move to start iter to start of line */ + gtk_text_iter_set_line_offset (&line_start, 0); + + if (gtk_text_iter_equal (&line_start, &line_end)) + { + /* we were already at the start; so go back one line */ + gtk_text_iter_backward_line (&line_start); + } + + win->first_line_start = line_start; + win->first_line_end = line_end; + + win->lines = g_new0 (gchar*, win->n_lines + 1); + + i = win->n_lines - 1; + while (i >= 0) + { + gchar *line_text; + + if (win->slice) + { + if (win->visible_only) + line_text = gtk_text_iter_get_visible_slice (&line_start, &line_end); + else + line_text = gtk_text_iter_get_slice (&line_start, &line_end); + } + else + { + if (win->visible_only) + line_text = gtk_text_iter_get_visible_text (&line_start, &line_end); + else + line_text = gtk_text_iter_get_text (&line_start, &line_end); + } + + win->lines[i] = line_text; + + line_end = line_start; + gtk_text_iter_backward_line (&line_start); + + --i; + } +} + +static gboolean +lines_window_back (LinesWindow *win) +{ + GtkTextIter new_start; + gchar *line_text; + + new_start = win->first_line_start; + + if (!gtk_text_iter_backward_line (&new_start)) + return FALSE; + else + { + win->first_line_start = new_start; + win->first_line_end = new_start; + + gtk_text_iter_forward_line (&win->first_line_end); + } + + if (win->slice) + { + if (win->visible_only) + line_text = gtk_text_iter_get_visible_slice (&win->first_line_start, + &win->first_line_end); + else + line_text = gtk_text_iter_get_slice (&win->first_line_start, + &win->first_line_end); + } + else + { + if (win->visible_only) + line_text = gtk_text_iter_get_visible_text (&win->first_line_start, + &win->first_line_end); + else + line_text = gtk_text_iter_get_text (&win->first_line_start, + &win->first_line_end); + } + + /* Move lines to make room for first line. */ + g_memmove (win->lines + 1, win->lines, win->n_lines * sizeof (gchar*)); + + *win->lines = line_text; + + /* Free old last line and NULL-terminate */ + g_free (win->lines[win->n_lines]); + win->lines[win->n_lines] = NULL; + + return TRUE; +} + +static void +lines_window_free (LinesWindow *win) +{ + g_strfreev (win->lines); +} + +static gchar* +my_strrstr (const gchar *haystack, + const gchar *needle) +{ + /* FIXME GLib should have a nice implementation in it, this + * is slow-ass crap. + */ + + gint haystack_len = strlen (haystack); + gint needle_len = strlen (needle); + const gchar *needle_end = needle + needle_len; + const gchar *haystack_rend = haystack - 1; + const gchar *needle_rend = needle - 1; + const gchar *p; + + p = haystack + haystack_len; + while (p != haystack) + { + const gchar *n = needle_end - 1; + const gchar *s = p - 1; + while (s != haystack_rend && + n != needle_rend && + *s == *n) + { + --n; + --s; + } + + if (n == needle_rend) + return ++s; + + --p; + } + + return NULL; +} + +gboolean +gtk_text_iter_backward_search (const GtkTextIter *iter, + const gchar *str, + gboolean visible_only, + gboolean slice, + GtkTextIter *match_start, + GtkTextIter *match_end) +{ + gchar **lines = NULL; + gchar **l; + gint n_lines; + LinesWindow win; + gboolean retval = FALSE; + g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (str != NULL, FALSE); + if (*str == '\0') + { + /* If we can move one char, return the empty string there */ + GtkTextIter match = *iter; + + if (gtk_text_iter_prev_char (&match)) + { + if (match_start) + *match_start = match; + if (match_end) + *match_end = match; + return TRUE; + } + else + return FALSE; + } + /* locate all lines */ + + lines = strbreakup (str, "\n", -1); + + l = lines; + n_lines = 0; + while (*l) + { + ++n_lines; + ++l; + } + + win.n_lines = n_lines; + win.slice = slice; + win.visible_only = visible_only; + lines_window_init (&win, iter); + + if (*win.lines == NULL) + goto out; + + do + { + gchar *first_line_match; + + /* If there are multiple lines, the first line will + * end in '\n', so this will only match at the + * end of the first line, which is correct. + */ + first_line_match = my_strrstr (*win.lines, *lines); + + if (first_line_match && + vectors_equal_ignoring_trailing (lines + 1, win.lines + 1)) + { + /* Match! */ + gint offset; + GtkTextIter next; + + /* Offset to start of search string */ + offset = g_utf8_strlen (*win.lines, first_line_match - *win.lines); + + next = win.first_line_start; + if (match_start) + { + *match_start = next; + forward_chars_with_skipping (match_start, offset, + visible_only, !slice); + } + + /* Go to end of search string */ + l = lines; + while (*l) + { + offset += g_utf8_strlen (*l, -1); + ++l; + } + + forward_chars_with_skipping (&next, offset, + visible_only, !slice); + + if (match_end) + *match_end = next; + + retval = TRUE; + goto out; + } + } + while (lines_window_back (&win)); + + out: + lines_window_free (&win); + g_strfreev (lines); + + return retval; } /* @@ -3103,7 +3430,8 @@ gtk_text_iter_backward_search (GtkTextIter *iter, */ gboolean -gtk_text_iter_equal(const GtkTextIter *lhs, const GtkTextIter *rhs) +gtk_text_iter_equal (const GtkTextIter *lhs, + const GtkTextIter *rhs) { GtkTextRealIter *real_lhs; GtkTextRealIter *real_rhs; diff --git a/gtk/gtktextiter.h b/gtk/gtktextiter.h index 9a49dfbfab..f9b9202840 100644 --- a/gtk/gtktextiter.h +++ b/gtk/gtktextiter.h @@ -185,17 +185,20 @@ gboolean gtk_text_iter_backward_find_char (GtkTextIter *iter, GtkTextCharPredicate pred, gpointer user_data); -gboolean gtk_text_iter_forward_search (const GtkTextIter *iter, - const gchar *str, - gboolean visible_only, - gboolean slice, - GtkTextIter *match_start, - GtkTextIter *match_end); +gboolean gtk_text_iter_forward_search (const GtkTextIter *iter, + const gchar *str, + gboolean visible_only, + gboolean slice, + GtkTextIter *match_start, + GtkTextIter *match_end); +gboolean gtk_text_iter_backward_search (const GtkTextIter *iter, + const gchar *str, + gboolean visible_only, + gboolean slice, + GtkTextIter *match_start, + GtkTextIter *match_end); + -gboolean gtk_text_iter_backward_search (GtkTextIter *iter, - const char *str, - gboolean visible_only, - gboolean slice); /* * Comparisons diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c index 363aafbcad..bcb8e693d5 100644 --- a/gtk/gtktextlayout.c +++ b/gtk/gtktextlayout.c @@ -1,4 +1,5 @@ -/* gtktextlayout.c - calculate the layout of the text +/* GTK - The GIMP Toolkit + * gtktextlayout.c - calculate the layout of the text * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. @@ -6,6 +7,26 @@ * Tk->Gtk port by Havoc Pennington * Pango support by Owen Taylor * + * This file can be used under your choice of two licenses, the LGPL + * and the original Tk license. + * + * LGPL: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Original Tk license: * * This software is copyrighted by the Regents of the University of * California, Sun Microsystems, Inc., and other parties. The @@ -46,7 +67,13 @@ * foregoing, the authors grant the U.S. Government and others acting * in its behalf permission to use and distribute the software in * accordance with the terms specified in this license. - * + * + */ +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "gtksignal.h" diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h index 1fb499e63b..cfa7c88f4b 100644 --- a/gtk/gtktextlayout.h +++ b/gtk/gtktextlayout.h @@ -1,6 +1,17 @@ /* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * gtktextlayout.h * + * Copyright (c) 1992-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 2000 Red Hat, Inc. + * Tk->Gtk port by Havoc Pennington + * Pango support by Owen Taylor + * + * This file can be used under your choice of two licenses, the LGPL + * and the original Tk license. + * + * LGPL: + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -14,8 +25,50 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Original Tk license: + * + * This software is copyrighted by the Regents of the University of + * California, Sun Microsystems, Inc., and other parties. The + * following terms apply to all files associated with the software + * unless explicitly disclaimed in individual files. + * + * The authors hereby grant permission to use, copy, modify, + * distribute, and license this software and its documentation for any + * purpose, provided that existing copyright notices are retained in + * all copies and that this notice is included verbatim in any + * distributions. No written agreement, license, or royalty fee is + * required for any of the authorized uses. Modifications to this + * software may be copyrighted by their authors and need not follow + * the licensing terms described here, provided that the new terms are + * clearly indicated on the first page of each file where they apply. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY + * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL + * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, + * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND + * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, + * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf of the + * U.S. government, the Government shall have only "Restricted Rights" + * in the software and related documentation as defined in the Federal + * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + * are acquiring the software on behalf of the Department of Defense, + * the software shall be classified as "Commercial Computer Software" + * and the Government shall have only "Restricted Rights" as defined + * in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others acting + * in its behalf permission to use and distribute the software in + * accordance with the terms specified in this license. + * */ - /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog diff --git a/gtk/gtktexttagtable.c b/gtk/gtktexttagtable.c index 3d3d436f2f..c137b6c25d 100644 --- a/gtk/gtktexttagtable.c +++ b/gtk/gtktexttagtable.c @@ -63,7 +63,7 @@ gtk_text_tag_table_class_init (GtkTextTagTableClass *klass) GTK_RUN_LAST, GTK_CLASS_TYPE (object_class), GTK_SIGNAL_OFFSET (GtkTextTagTableClass, tag_changed), - gtk_marshal_VOID__POINTER_INT, + gtk_marshal_VOID__POINTER_BOOLEAN, GTK_TYPE_NONE, 2, GTK_TYPE_OBJECT, diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index bab192c873..cb84049445 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -835,7 +835,7 @@ set_adjustment_clamped (GtkAdjustment *adj, gfloat val) gtk_adjustment_set_value (adj, val); } -gboolean +static gboolean gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view, GtkTextMark *mark, gint margin, diff --git a/gtk/testtext.c b/gtk/testtext.c index f2237d2ae4..d62545f7ae 100644 --- a/gtk/testtext.c +++ b/gtk/testtext.c @@ -47,6 +47,9 @@ static void buffer_filename_set (Buffer *buffer); static void buffer_search_forward (Buffer *buffer, const char *str, View *view); +static void buffer_search_backward (Buffer *buffer, + const char *str, + View *view); static View *view_from_widget (GtkWidget *widget); @@ -930,6 +933,12 @@ do_apply_tabs (gpointer callback_data, } } +enum +{ + RESPONSE_FORWARD, + RESPONSE_BACKWARD +}; + static void dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) { @@ -937,6 +946,13 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) View *view = data; GtkTextIter start, end; gchar *search_string; + + if (response_id != RESPONSE_FORWARD && + response_id != RESPONSE_BACKWARD) + { + gtk_widget_destroy (dialog); + return; + } buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer"); @@ -948,9 +964,12 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) search_string = gtk_text_iter_get_text (&start, &end); printf ("Searching for `%s'\n", search_string); - - buffer_search_forward (view->buffer, search_string, view); + if (response_id == RESPONSE_FORWARD) + buffer_search_forward (view->buffer, search_string, view); + else if (response_id == RESPONSE_BACKWARD) + buffer_search_backward (view->buffer, search_string, view); + g_free (search_string); gtk_widget_destroy (dialog); @@ -969,7 +988,9 @@ do_search (gpointer callback_data, dialog = gtk_dialog_new_with_buttons ("Search", GTK_WINDOW (view->window), GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_BUTTON_CLOSE, + "Forward", RESPONSE_FORWARD, + "Backward", RESPONSE_BACKWARD, + GTK_STOCK_BUTTON_CANCEL, GTK_RESPONSE_NONE, NULL); @@ -1303,8 +1324,10 @@ buffer_filename_set (Buffer *buffer) } static void -buffer_search_forward (Buffer *buffer, const char *str, - View *view) +buffer_search (Buffer *buffer, + const char *str, + View *view, + gboolean forward) { GtkTextIter iter; GtkTextIter start, end; @@ -1324,15 +1347,30 @@ buffer_search_forward (Buffer *buffer, const char *str, if (*str != '\0') { GtkTextIter match_start, match_end; - - while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) - { - ++i; - gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, - &match_start, &match_end); - iter = match_end; + if (forward) + { + while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, + &match_start, &match_end)) + { + ++i; + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &match_start, &match_end); + + iter = match_end; + } + } + else + { + while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE, + &match_start, &match_end)) + { + ++i; + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &match_start, &match_end); + + iter = match_start; + } } } @@ -1351,6 +1389,20 @@ buffer_search_forward (Buffer *buffer, const char *str, gtk_widget_show (dialog); } +static void +buffer_search_forward (Buffer *buffer, const char *str, + View *view) +{ + buffer_search (buffer, str, view, TRUE); +} + +static void +buffer_search_backward (Buffer *buffer, const char *str, + View *view) +{ + buffer_search (buffer, str, view, FALSE); +} + static void buffer_ref (Buffer *buffer) { diff --git a/tests/testtext.c b/tests/testtext.c index f2237d2ae4..d62545f7ae 100644 --- a/tests/testtext.c +++ b/tests/testtext.c @@ -47,6 +47,9 @@ static void buffer_filename_set (Buffer *buffer); static void buffer_search_forward (Buffer *buffer, const char *str, View *view); +static void buffer_search_backward (Buffer *buffer, + const char *str, + View *view); static View *view_from_widget (GtkWidget *widget); @@ -930,6 +933,12 @@ do_apply_tabs (gpointer callback_data, } } +enum +{ + RESPONSE_FORWARD, + RESPONSE_BACKWARD +}; + static void dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) { @@ -937,6 +946,13 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) View *view = data; GtkTextIter start, end; gchar *search_string; + + if (response_id != RESPONSE_FORWARD && + response_id != RESPONSE_BACKWARD) + { + gtk_widget_destroy (dialog); + return; + } buffer = gtk_object_get_data (GTK_OBJECT (dialog), "buffer"); @@ -948,9 +964,12 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data) search_string = gtk_text_iter_get_text (&start, &end); printf ("Searching for `%s'\n", search_string); - - buffer_search_forward (view->buffer, search_string, view); + if (response_id == RESPONSE_FORWARD) + buffer_search_forward (view->buffer, search_string, view); + else if (response_id == RESPONSE_BACKWARD) + buffer_search_backward (view->buffer, search_string, view); + g_free (search_string); gtk_widget_destroy (dialog); @@ -969,7 +988,9 @@ do_search (gpointer callback_data, dialog = gtk_dialog_new_with_buttons ("Search", GTK_WINDOW (view->window), GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_BUTTON_CLOSE, + "Forward", RESPONSE_FORWARD, + "Backward", RESPONSE_BACKWARD, + GTK_STOCK_BUTTON_CANCEL, GTK_RESPONSE_NONE, NULL); @@ -1303,8 +1324,10 @@ buffer_filename_set (Buffer *buffer) } static void -buffer_search_forward (Buffer *buffer, const char *str, - View *view) +buffer_search (Buffer *buffer, + const char *str, + View *view, + gboolean forward) { GtkTextIter iter; GtkTextIter start, end; @@ -1324,15 +1347,30 @@ buffer_search_forward (Buffer *buffer, const char *str, if (*str != '\0') { GtkTextIter match_start, match_end; - - while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, - &match_start, &match_end)) - { - ++i; - gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, - &match_start, &match_end); - iter = match_end; + if (forward) + { + while (gtk_text_iter_forward_search (&iter, str, TRUE, FALSE, + &match_start, &match_end)) + { + ++i; + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &match_start, &match_end); + + iter = match_end; + } + } + else + { + while (gtk_text_iter_backward_search (&iter, str, TRUE, FALSE, + &match_start, &match_end)) + { + ++i; + gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag, + &match_start, &match_end); + + iter = match_start; + } } } @@ -1351,6 +1389,20 @@ buffer_search_forward (Buffer *buffer, const char *str, gtk_widget_show (dialog); } +static void +buffer_search_forward (Buffer *buffer, const char *str, + View *view) +{ + buffer_search (buffer, str, view, TRUE); +} + +static void +buffer_search_backward (Buffer *buffer, const char *str, + View *view) +{ + buffer_search (buffer, str, view, FALSE); +} + static void buffer_ref (Buffer *buffer) {