forked from AuroraMiddleware/gtk
c7826b5f63
2001-01-03 Havoc Pennington <hp@redhat.com> * gtk/gtktextbtree.c: Adapt to uscore-ification of gtktextiterprivate * gtk/gtktextdisplay.c (gtk_text_layout_draw): remove use of private functions; remove inclusion of private headers. * gtk/gtktextlayout.c (gtk_text_layout_get_iter_at_line): Add this function, so we don't need private functions in gtktextdisplay.c * gtk/gtktextiterprivate.h: underscore-ification * gtk/gtkwidget.c: Clean up a bunch of docs that said "INTERNAL" to instead say "only useful to implement widgets" * gtk/gtkenums.h (GtkMovementStep): Rename GTK_MOVEMENT_CHARS, GTK_MOVEMENT_POSITIONS to GTK_MOVEMENT_LOGICAL_POSITIONS, GTK_MOVEMENT_VISUAL_POSITIONS. Resolves bug 40249. * gdk/x11/gdkwindow-x11.c (gdk_window_impl_x11_set_colormap): This function was completely broken * gtk/testtext.c (line_numbers_expose): use gtk_paint_layout * gtk/gtkvscale.c (gtk_vscale_draw_value): use gtk_paint_layout * gtk/gtkvruler.c (gtk_vruler_draw_ticks): use gtk_paint_layout * gtk/gtklabel.c (gtk_label_expose): use gtk_paint_layout * gtk/gtkhscale.c (gtk_hscale_draw_value): use gtk_paint_layout * gtk/gtkhruler.c (gtk_hruler_draw_ticks): use gtk_paint_layout * gtk/gtkcellrenderertext.c (gtk_cell_renderer_text_render): use gtk_paint_layout * gtk/gtkaccellabel.c (gtk_accel_label_expose_event): use gtk_paint_layout * gtk/gtkstyle.h: Add draw/paint expander to draw tree expanders. Progress on bug 40103. Add draw_layout to draw a PangoLayout. (struct _GtkStyleClass): Remove draw_cross, draw_oval, draw_ramp, which were not implemented. * gtk/gtktextbuffer.h (struct _GtkTextBufferClass): Add insert_pixbuf signal. Rename delete_text to delete_range since it also deletes pixbufs and child anchors. This almost closes bug 40245 (still need to deal with child anchors) * gtk/gtktextbuffer.c (gtk_text_buffer_class_init): Add insert_pixbuf, change signal names as appropriate, change types of signals taking marks/tags to have the specific type, not just G_TYPE_OBJECT * gtk/gtkmain.c (gtk_get_current_event_state): Add this function; closes bug 40051 * gtk/gtkoptionmenu.c (gtk_option_menu_set_history): clean up unnecessary remove_contents() call (gtk_option_menu_class_init): add a "changed" signal, closes bug 40039 (gtk_option_menu_update_contents): emit "changed" if the active menu item changes * gtk/gdk-pixbuf-loader.c (gdk_pixbuf_loader_frame_done): fix bad cast to GtkObject, reported by Jonas Borgstrom (gdk_pixbuf_loader_finalize): don't close the loader on finalize; we can't do stuff with side effects in finalize. Instead, spew a warning if the loader isn't closed. * gdk/x11/gdkdrawable-x11.c (gdk_drawable_impl_x11_finalize): free colormap in here, non-X ports probably need to sync to this change * gdk/x11/gdkdrawable-x11.c (gdk_x11_set_colormap): remove assertion that colormap != NULL, you can set the colormap to NULL if you like. * Makefile.am: remove gtk-config-2.0 * configure.in: Use pkg-config to locate GLib. Remove separated-out GMODULE_LIBS, GMODULE_CFLAGS; these were not used, and the gmodule libs/cflags were in GLIB_LIBS GLIB_CFLAGS anyhow. Use pkg-config to locate Pango. Output correct Pango libs to gdk-2.0.pc.in. Fix test for FREETYPE_CONFIG (typo fix). * Makefile.am (pkgconfig_DATA): install only target-specific pc files (install-data-local): symlink gtk+-2.0.pc and gdk-2.0.pc to the X11 pc files * gtk+-2.0.pc.in (Requires): require the GDK for the current target unref from here
624 lines
19 KiB
C
624 lines
19 KiB
C
/*
|
|
* gtktextsegment.c --
|
|
*
|
|
* Code for segments in general, and toggle/char segments in particular.
|
|
*
|
|
* Copyright (c) 1992-1994 The Regents of the University of California.
|
|
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
|
|
* Copyright (c) 2000 Red Hat, Inc.
|
|
* Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "gtktextbtree.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "gtktexttag.h"
|
|
#include "gtktexttagtable.h"
|
|
#include "gtktextlayout.h"
|
|
#include "gtktextiterprivate.h"
|
|
#include "gtkdebug.h"
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* split_segment --
|
|
*
|
|
* This procedure is called before adding or deleting
|
|
* segments. It does three things: (a) it finds the segment
|
|
* containing iter; (b) if there are several such
|
|
* segments (because some segments have zero length) then
|
|
* it picks the first segment that does not have left
|
|
* gravity; (c) if the index refers to the middle of
|
|
* a segment then it splits the segment so that the
|
|
* index now refers to the beginning of a segment.
|
|
*
|
|
* Results:
|
|
* The return value is a pointer to the segment just
|
|
* before the segment corresponding to iter (as
|
|
* described above). If the segment corresponding to
|
|
* iter is the first in its line then the return
|
|
* value is NULL.
|
|
*
|
|
* Side effects:
|
|
* The segment referred to by iter is split unless
|
|
* iter refers to its first character.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
GtkTextLineSegment*
|
|
gtk_text_line_segment_split (const GtkTextIter *iter)
|
|
{
|
|
GtkTextLineSegment *prev, *seg;
|
|
GtkTextBTree *tree;
|
|
GtkTextLine *line;
|
|
int count;
|
|
|
|
line = _gtk_text_iter_get_text_line (iter);
|
|
tree = _gtk_text_iter_get_btree (iter);
|
|
|
|
count = gtk_text_iter_get_line_index (iter);
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
_gtk_text_iter_check (iter);
|
|
|
|
prev = NULL;
|
|
seg = line->segments;
|
|
|
|
while (seg != NULL)
|
|
{
|
|
if (seg->byte_count > count)
|
|
{
|
|
if (count == 0)
|
|
{
|
|
return prev;
|
|
}
|
|
else
|
|
{
|
|
g_assert (count != seg->byte_count);
|
|
g_assert (seg->byte_count > 0);
|
|
|
|
_gtk_text_btree_segments_changed (tree);
|
|
|
|
seg = (*seg->type->splitFunc)(seg, count);
|
|
|
|
if (prev == NULL)
|
|
line->segments = seg;
|
|
else
|
|
prev->next = seg;
|
|
|
|
return seg;
|
|
}
|
|
}
|
|
else if ((seg->byte_count == 0) && (count == 0)
|
|
&& !seg->type->leftGravity)
|
|
{
|
|
return prev;
|
|
}
|
|
|
|
count -= seg->byte_count;
|
|
prev = seg;
|
|
seg = seg->next;
|
|
}
|
|
g_error ("split_segment reached end of line!");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* Macros that determine how much space to allocate for new segments:
|
|
*/
|
|
|
|
#define CSEG_SIZE(chars) ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
|
|
+ 1 + (chars)))
|
|
#define TSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
|
|
+ sizeof (GtkTextToggleBody)))
|
|
|
|
/*
|
|
* Type functions
|
|
*/
|
|
|
|
static void
|
|
char_segment_self_check (GtkTextLineSegment *seg)
|
|
{
|
|
/* This function checks the segment itself, but doesn't
|
|
assume the segment has been validly inserted into
|
|
the btree. */
|
|
|
|
g_assert (seg != NULL);
|
|
|
|
if (seg->byte_count <= 0)
|
|
{
|
|
g_error ("char_segment_check_func: segment has size <= 0");
|
|
}
|
|
|
|
if (strlen (seg->body.chars) != seg->byte_count)
|
|
{
|
|
g_error ("char_segment_check_func: segment has wrong size");
|
|
}
|
|
|
|
if (g_utf8_strlen (seg->body.chars, seg->byte_count) != seg->char_count)
|
|
{
|
|
g_error ("char segment has wrong character count");
|
|
}
|
|
}
|
|
|
|
GtkTextLineSegment*
|
|
_gtk_char_segment_new (const gchar *text, guint len)
|
|
{
|
|
GtkTextLineSegment *seg;
|
|
|
|
g_assert (gtk_text_byte_begins_utf8_char (text));
|
|
|
|
seg = g_malloc (CSEG_SIZE (len));
|
|
seg->type = >k_text_char_type;
|
|
seg->next = NULL;
|
|
seg->byte_count = len;
|
|
memcpy (seg->body.chars, text, len);
|
|
seg->body.chars[len] = '\0';
|
|
|
|
seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
char_segment_self_check (seg);
|
|
|
|
return seg;
|
|
}
|
|
|
|
GtkTextLineSegment*
|
|
_gtk_char_segment_new_from_two_strings (const gchar *text1, guint len1,
|
|
const gchar *text2, guint len2)
|
|
{
|
|
GtkTextLineSegment *seg;
|
|
|
|
g_assert (gtk_text_byte_begins_utf8_char (text1));
|
|
g_assert (gtk_text_byte_begins_utf8_char (text2));
|
|
|
|
seg = g_malloc (CSEG_SIZE (len1+len2));
|
|
seg->type = >k_text_char_type;
|
|
seg->next = NULL;
|
|
seg->byte_count = len1 + len2;
|
|
memcpy (seg->body.chars, text1, len1);
|
|
memcpy (seg->body.chars + len1, text2, len2);
|
|
seg->body.chars[len1+len2] = '\0';
|
|
|
|
/* In principle this function could probably take chars1 and chars2
|
|
as args, since it's typically used to merge two char segments */
|
|
seg->char_count = g_utf8_strlen (seg->body.chars, seg->byte_count);
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
char_segment_self_check (seg);
|
|
|
|
return seg;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* char_segment_split_func --
|
|
*
|
|
* This procedure implements splitting for character segments.
|
|
*
|
|
* Results:
|
|
* The return value is a pointer to a chain of two segments
|
|
* that have the same characters as segPtr except split
|
|
* among the two segments.
|
|
*
|
|
* Side effects:
|
|
* Storage for segPtr is freed.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
static GtkTextLineSegment *
|
|
char_segment_split_func (GtkTextLineSegment *seg, int index)
|
|
{
|
|
GtkTextLineSegment *new1, *new2;
|
|
|
|
g_assert (index < seg->byte_count);
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
{
|
|
char_segment_self_check (seg);
|
|
}
|
|
|
|
new1 = _gtk_char_segment_new (seg->body.chars, index);
|
|
new2 = _gtk_char_segment_new (seg->body.chars + index, seg->byte_count - index);
|
|
|
|
g_assert (gtk_text_byte_begins_utf8_char (new1->body.chars));
|
|
g_assert (gtk_text_byte_begins_utf8_char (new2->body.chars));
|
|
g_assert (new1->byte_count + new2->byte_count == seg->byte_count);
|
|
g_assert (new1->char_count + new2->char_count == seg->char_count);
|
|
|
|
new1->next = new2;
|
|
new2->next = seg->next;
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
{
|
|
char_segment_self_check (new1);
|
|
char_segment_self_check (new2);
|
|
}
|
|
|
|
g_free (seg);
|
|
return new1;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* char_segment_cleanup_func --
|
|
*
|
|
* This procedure merges adjacent character segments into
|
|
* a single character segment, if possible.
|
|
*
|
|
* Results:
|
|
* The return value is a pointer to the first segment in
|
|
* the (new) list of segments that used to start with segPtr.
|
|
*
|
|
* Side effects:
|
|
* Storage for the segments may be allocated and freed.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static GtkTextLineSegment *
|
|
char_segment_cleanup_func (segPtr, line)
|
|
GtkTextLineSegment *segPtr; /* Pointer to first of two adjacent
|
|
* segments to join. */
|
|
GtkTextLine *line; /* Line containing segments (not
|
|
* used). */
|
|
{
|
|
GtkTextLineSegment *segPtr2, *newPtr;
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
char_segment_self_check (segPtr);
|
|
|
|
segPtr2 = segPtr->next;
|
|
if ((segPtr2 == NULL) || (segPtr2->type != >k_text_char_type))
|
|
{
|
|
return segPtr;
|
|
}
|
|
|
|
newPtr =
|
|
_gtk_char_segment_new_from_two_strings (segPtr->body.chars, segPtr->byte_count,
|
|
segPtr2->body.chars, segPtr2->byte_count);
|
|
|
|
newPtr->next = segPtr2->next;
|
|
|
|
if (gtk_debug_flags & GTK_DEBUG_TEXT)
|
|
char_segment_self_check (newPtr);
|
|
|
|
g_free (segPtr);
|
|
g_free (segPtr2);
|
|
return newPtr;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* char_segment_delete_func --
|
|
*
|
|
* This procedure is invoked to delete a character segment.
|
|
*
|
|
* Results:
|
|
* Always returns 0 to indicate that the segment was deleted.
|
|
*
|
|
* Side effects:
|
|
* Storage for the segment is freed.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static int
|
|
char_segment_delete_func (segPtr, line, treeGone)
|
|
GtkTextLineSegment *segPtr; /* Segment to delete. */
|
|
GtkTextLine *line; /* Line containing segment. */
|
|
int treeGone; /* Non-zero means the entire tree is
|
|
* being deleted, so everything must
|
|
* get cleaned up. */
|
|
{
|
|
g_free ((char*) segPtr);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* char_segment_check_func --
|
|
*
|
|
* This procedure is invoked to perform consistency checks
|
|
* on character segments.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* If the segment isn't inconsistent then the procedure
|
|
* g_errors.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
static void
|
|
char_segment_check_func (segPtr, line)
|
|
GtkTextLineSegment *segPtr; /* Segment to check. */
|
|
GtkTextLine *line; /* Line containing segment. */
|
|
{
|
|
char_segment_self_check (segPtr);
|
|
|
|
if (segPtr->next != NULL)
|
|
{
|
|
if (segPtr->next->type == >k_text_char_type)
|
|
{
|
|
g_error ("char_segment_check_func: adjacent character segments weren't merged");
|
|
}
|
|
}
|
|
}
|
|
|
|
GtkTextLineSegment*
|
|
_gtk_toggle_segment_new (GtkTextTagInfo *info, gboolean on)
|
|
{
|
|
GtkTextLineSegment *seg;
|
|
|
|
seg = g_malloc (TSEG_SIZE);
|
|
|
|
seg->type = on ? >k_text_toggle_on_type : >k_text_toggle_off_type;
|
|
|
|
seg->next = NULL;
|
|
|
|
seg->byte_count = 0;
|
|
seg->char_count = 0;
|
|
|
|
seg->body.toggle.info = info;
|
|
seg->body.toggle.inNodeCounts = 0;
|
|
|
|
return seg;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* toggle_segment_delete_func --
|
|
*
|
|
* This procedure is invoked to delete toggle segments.
|
|
*
|
|
* Results:
|
|
* Returns 1 to indicate that the segment may not be deleted,
|
|
* unless the entire B-tree is going away.
|
|
*
|
|
* Side effects:
|
|
* If the tree is going away then the toggle's memory is
|
|
* freed; otherwise the toggle counts in GtkTextBTreeNodes above the
|
|
* segment get updated.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
static int
|
|
toggle_segment_delete_func (segPtr, line, treeGone)
|
|
GtkTextLineSegment *segPtr; /* Segment to check. */
|
|
GtkTextLine *line; /* Line containing segment. */
|
|
int treeGone; /* Non-zero means the entire tree is
|
|
* being deleted, so everything must
|
|
* get cleaned up. */
|
|
{
|
|
if (treeGone)
|
|
{
|
|
g_free ((char *) segPtr);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* This toggle is in the middle of a range of characters that's
|
|
* being deleted. Refuse to die. We'll be moved to the end of
|
|
* the deleted range and our cleanup procedure will be called
|
|
* later. Decrement GtkTextBTreeNode toggle counts here, and set a flag
|
|
* so we'll re-increment them in the cleanup procedure.
|
|
*/
|
|
|
|
if (segPtr->body.toggle.inNodeCounts)
|
|
{
|
|
_gtk_change_node_toggle_count (line->parent,
|
|
segPtr->body.toggle.info, -1);
|
|
segPtr->body.toggle.inNodeCounts = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* toggle_segment_cleanup_func --
|
|
*
|
|
* This procedure is called when a toggle is part of a line that's
|
|
* been modified in some way. It's invoked after the
|
|
* modifications are complete.
|
|
*
|
|
* Results:
|
|
* The return value is the head segment in a new list
|
|
* that is to replace the tail of the line that used to
|
|
* start at segPtr. This allows the procedure to delete
|
|
* or modify segPtr.
|
|
*
|
|
* Side effects:
|
|
* Toggle counts in the GtkTextBTreeNodes above the new line will be
|
|
* updated if they're not already. Toggles may be collapsed
|
|
* if there are duplicate toggles at the same position.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
static GtkTextLineSegment *
|
|
toggle_segment_cleanup_func (segPtr, line)
|
|
GtkTextLineSegment *segPtr; /* Segment to check. */
|
|
GtkTextLine *line; /* Line that now contains segment. */
|
|
{
|
|
GtkTextLineSegment *segPtr2, *prevPtr;
|
|
int counts;
|
|
|
|
/*
|
|
* If this is a toggle-off segment, look ahead through the next
|
|
* segments to see if there's a toggle-on segment for the same tag
|
|
* before any segments with non-zero size. If so then the two
|
|
* toggles cancel each other; remove them both.
|
|
*/
|
|
|
|
if (segPtr->type == >k_text_toggle_off_type)
|
|
{
|
|
for (prevPtr = segPtr, segPtr2 = prevPtr->next;
|
|
(segPtr2 != NULL) && (segPtr2->byte_count == 0);
|
|
prevPtr = segPtr2, segPtr2 = prevPtr->next)
|
|
{
|
|
if (segPtr2->type != >k_text_toggle_on_type)
|
|
{
|
|
continue;
|
|
}
|
|
if (segPtr2->body.toggle.info != segPtr->body.toggle.info)
|
|
{
|
|
continue;
|
|
}
|
|
counts = segPtr->body.toggle.inNodeCounts
|
|
+ segPtr2->body.toggle.inNodeCounts;
|
|
if (counts != 0)
|
|
{
|
|
_gtk_change_node_toggle_count (line->parent,
|
|
segPtr->body.toggle.info, -counts);
|
|
}
|
|
prevPtr->next = segPtr2->next;
|
|
g_free ((char *) segPtr2);
|
|
segPtr2 = segPtr->next;
|
|
g_free ((char *) segPtr);
|
|
return segPtr2;
|
|
}
|
|
}
|
|
|
|
if (!segPtr->body.toggle.inNodeCounts)
|
|
{
|
|
_gtk_change_node_toggle_count (line->parent,
|
|
segPtr->body.toggle.info, 1);
|
|
segPtr->body.toggle.inNodeCounts = 1;
|
|
}
|
|
return segPtr;
|
|
}
|
|
|
|
/*
|
|
*--------------------------------------------------------------
|
|
*
|
|
* toggle_segment_line_change_func --
|
|
*
|
|
* This procedure is invoked when a toggle segment is about
|
|
* to move from one line to another.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Toggle counts are decremented in the GtkTextBTreeNodes above the line.
|
|
*
|
|
*--------------------------------------------------------------
|
|
*/
|
|
|
|
static void
|
|
toggle_segment_line_change_func (segPtr, line)
|
|
GtkTextLineSegment *segPtr; /* Segment to check. */
|
|
GtkTextLine *line; /* Line that used to contain segment. */
|
|
{
|
|
if (segPtr->body.toggle.inNodeCounts)
|
|
{
|
|
_gtk_change_node_toggle_count (line->parent,
|
|
segPtr->body.toggle.info, -1);
|
|
segPtr->body.toggle.inNodeCounts = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Virtual tables
|
|
*/
|
|
|
|
|
|
GtkTextLineSegmentClass gtk_text_char_type = {
|
|
"character", /* name */
|
|
0, /* leftGravity */
|
|
char_segment_split_func, /* splitFunc */
|
|
char_segment_delete_func, /* deleteFunc */
|
|
char_segment_cleanup_func, /* cleanupFunc */
|
|
NULL, /* lineChangeFunc */
|
|
char_segment_check_func /* checkFunc */
|
|
};
|
|
|
|
/*
|
|
* Type record for segments marking the beginning of a tagged
|
|
* range:
|
|
*/
|
|
|
|
GtkTextLineSegmentClass gtk_text_toggle_on_type = {
|
|
"toggleOn", /* name */
|
|
0, /* leftGravity */
|
|
NULL, /* splitFunc */
|
|
toggle_segment_delete_func, /* deleteFunc */
|
|
toggle_segment_cleanup_func, /* cleanupFunc */
|
|
toggle_segment_line_change_func, /* lineChangeFunc */
|
|
_gtk_toggle_segment_check_func /* checkFunc */
|
|
};
|
|
|
|
/*
|
|
* Type record for segments marking the end of a tagged
|
|
* range:
|
|
*/
|
|
|
|
GtkTextLineSegmentClass gtk_text_toggle_off_type = {
|
|
"toggleOff", /* name */
|
|
1, /* leftGravity */
|
|
NULL, /* splitFunc */
|
|
toggle_segment_delete_func, /* deleteFunc */
|
|
toggle_segment_cleanup_func, /* cleanupFunc */
|
|
toggle_segment_line_change_func, /* lineChangeFunc */
|
|
_gtk_toggle_segment_check_func /* checkFunc */
|
|
};
|