Implement the side windows.

2000-09-29  Havoc Pennington  <hp@pobox.com>

* gtk/gtktextview.c: Implement the side windows.

* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
This commit is contained in:
Havoc Pennington 2000-09-29 05:47:34 +00:00 committed by Havoc Pennington
parent 85735ec7f5
commit d0cbd57de8
10 changed files with 974 additions and 88 deletions

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1,3 +1,12 @@
2000-09-29 Havoc Pennington <hp@pobox.com>
* gtk/gtktextview.c: Implement the side windows.
* gtk/testtext.c: Implement simple line numbering in the
left side window; seems to make scrolling sloooow. Oops.
Also, cursor blink is for some reason causing redraws
of the line numbers. Should investigate...
2000-09-28 Havoc Pennington <hp@redhat.com>
* gtk/gtktextview.c: Set up infrastructure to deal with lots of

View File

@ -1104,6 +1104,18 @@ gtk_text_view_finalize (GObject *object)
gtk_object_unref (GTK_OBJECT (text_view->vadjustment));
text_window_free (text_view->text_window);
if (text_view->left_window)
text_window_free (text_view->left_window);
if (text_view->top_window)
text_window_free (text_view->top_window);
if (text_view->right_window)
text_window_free (text_view->right_window);
if (text_view->bottom_window)
text_window_free (text_view->bottom_window);
gtk_object_unref (GTK_OBJECT (text_view->im_context));
@ -1192,6 +1204,18 @@ gtk_text_view_size_request (GtkWidget *widget,
requisition->width = text_view->text_window->requisition.width + FOCUS_EDGE_WIDTH * 2;
requisition->height = text_view->text_window->requisition.height + FOCUS_EDGE_WIDTH * 2;
if (text_view->left_window)
requisition->width += text_view->left_window->requisition.width;
if (text_view->right_window)
requisition->width += text_view->right_window->requisition.width;
if (text_view->top_window)
requisition->height += text_view->top_window->requisition.height;
if (text_view->bottom_window)
requisition->height += text_view->bottom_window->requisition.height;
}
static void
@ -1203,7 +1227,12 @@ gtk_text_view_size_allocate (GtkWidget *widget,
gint y;
GtkAdjustment *vadj;
gboolean yoffset_changed = FALSE;
GdkRectangle child_rect;
gint width, height;
GdkRectangle text_rect;
GdkRectangle left_rect;
GdkRectangle right_rect;
GdkRectangle top_rect;
GdkRectangle bottom_rect;
text_view = GTK_TEXT_VIEW (widget);
@ -1215,23 +1244,89 @@ gtk_text_view_size_allocate (GtkWidget *widget,
allocation->x, allocation->y,
allocation->width, allocation->height);
}
/* distribute width/height among child windows. Ensure all
* windows get at least a 1x1 allocation.
*/
width = allocation->width - FOCUS_EDGE_WIDTH * 2;
if (text_view->left_window)
left_rect.width = text_view->left_window->requisition.width;
else
left_rect.width = 1;
width -= left_rect.width;
if (text_view->right_window)
right_rect.width = text_view->right_window->requisition.width;
else
right_rect.width = 1;
width -= right_rect.width;
text_rect.width = MAX (1, width);
top_rect.width = text_rect.width;
bottom_rect.width = text_rect.width;
height = allocation->height - FOCUS_EDGE_WIDTH * 2;
if (text_view->top_window)
top_rect.height = text_view->top_window->requisition.height;
else
top_rect.height = 1;
height -= top_rect.height;
if (text_view->bottom_window)
bottom_rect.height = text_view->bottom_window->requisition.height;
else
bottom_rect.height = 1;
height -= bottom_rect.height;
text_rect.height = MAX (1, height);
left_rect.height = text_rect.height;
right_rect.height = text_rect.height;
/* Origins */
left_rect.x = FOCUS_EDGE_WIDTH;
top_rect.y = FOCUS_EDGE_WIDTH;
text_rect.x = left_rect.x + left_rect.width;
text_rect.y = top_rect.y + top_rect.height;
child_rect = *allocation;
left_rect.y = text_rect.y;
right_rect.y = text_rect.y;
child_rect.x = FOCUS_EDGE_WIDTH;
child_rect.y = FOCUS_EDGE_WIDTH;
child_rect.width -= FOCUS_EDGE_WIDTH * 2;
child_rect.height -= FOCUS_EDGE_WIDTH * 2;
if (child_rect.width < 0 || child_rect.height < 0)
{
/* Write over the other windows with the text window. */
child_rect = *allocation;
}
top_rect.x = text_rect.x;
bottom_rect.x = text_rect.x;
right_rect.x = text_rect.x + text_rect.width;
bottom_rect.y = text_rect.y + text_rect.height;
text_window_size_allocate (text_view->text_window,
&child_rect);
&text_rect);
if (text_view->left_window)
text_window_size_allocate (text_view->left_window,
&left_rect);
if (text_view->right_window)
text_window_size_allocate (text_view->right_window,
&right_rect);
if (text_view->top_window)
text_window_size_allocate (text_view->top_window,
&top_rect);
if (text_view->bottom_window)
text_window_size_allocate (text_view->bottom_window,
&bottom_rect);
gtk_text_view_ensure_layout (text_view);
gtk_text_layout_set_screen_width (text_view->layout,
SCREEN_WIDTH (text_view));
@ -1424,17 +1519,31 @@ gtk_text_view_realize (GtkWidget *widget)
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
&attributes, attributes_mask);
gdk_window_set_user_data (widget->window, widget);
text_window_realize (text_view->text_window, widget->window);
/* must come before text_window_realize calls */
widget->style = gtk_style_attach (widget->style, widget->window);
gdk_window_set_background (widget->window,
&widget->style->base[GTK_WIDGET_STATE (widget)]);
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
gdk_window_set_background (text_view->text_window->bin_window,
&widget->style->base[GTK_WIDGET_STATE (widget)]);
text_window_realize (text_view->text_window, widget->window);
if (text_view->left_window)
text_window_realize (text_view->left_window,
widget->window);
if (text_view->top_window)
text_window_realize (text_view->top_window,
widget->window);
if (text_view->right_window)
text_window_realize (text_view->right_window,
widget->window);
if (text_view->bottom_window)
text_window_realize (text_view->bottom_window,
widget->window);
gtk_text_view_ensure_layout (text_view);
}
@ -1458,6 +1567,18 @@ gtk_text_view_unrealize (GtkWidget *widget)
}
text_window_unrealize (text_view->text_window);
if (text_view->left_window)
text_window_unrealize (text_view->left_window);
if (text_view->top_window)
text_window_unrealize (text_view->top_window);
if (text_view->right_window)
text_window_unrealize (text_view->right_window);
if (text_view->bottom_window)
text_window_unrealize (text_view->bottom_window);
gtk_text_view_destroy_layout (text_view);
@ -1473,12 +1594,29 @@ gtk_text_view_style_set (GtkWidget *widget,
if (GTK_WIDGET_REALIZED (widget))
{
gdk_window_set_background (widget->window,
&widget->style->base[GTK_WIDGET_STATE (widget)]);
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
gdk_window_set_background (text_view->text_window->bin_window,
&widget->style->base[GTK_WIDGET_STATE (widget)]);
gtk_text_view_set_attributes_from_style (text_view, text_view->layout->default_style, widget->style);
if (text_view->left_window)
gdk_window_set_background (text_view->left_window->bin_window,
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
if (text_view->right_window)
gdk_window_set_background (text_view->right_window->bin_window,
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
if (text_view->top_window)
gdk_window_set_background (text_view->top_window->bin_window,
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
if (text_view->bottom_window)
gdk_window_set_background (text_view->bottom_window->bin_window,
&widget->style->bg[GTK_WIDGET_STATE (widget)]);
gtk_text_view_set_attributes_from_style (text_view,
text_view->layout->default_style,
widget->style);
gtk_text_layout_default_style_changed (text_view->layout);
}
}
@ -1844,19 +1982,82 @@ gtk_text_view_paint (GtkWidget *widget, GdkRectangle *area)
area->width, area->height);
}
static void
send_expose (GtkTextView *text_view,
GtkTextWindow *win,
GdkRectangle *area)
{
GdkEventExpose event;
event.type = GDK_EXPOSE;
event.send_event = TRUE;
event.window = win->bin_window;
event.area = *area;
event.count = 0;
/* Fix coordinates (convert widget coords to window coords) */
gtk_text_view_window_to_buffer_coords (text_view,
GTK_TEXT_WINDOW_WIDGET,
event.area.x,
event.area.y,
&event.area.x,
&event.area.y);
gtk_text_view_buffer_to_window_coords (text_view,
win->type,
event.area.x,
event.area.y,
&event.area.x,
&event.area.y);
gdk_window_ref (event.window);
gtk_widget_event (GTK_WIDGET (text_view), (GdkEvent*) &event);
gdk_window_unref (event.window);
}
static void
gtk_text_view_draw (GtkWidget *widget, GdkRectangle *area)
{
{
GdkRectangle intersection;
GtkTextView *text_view;
text_view = GTK_TEXT_VIEW (widget);
gtk_text_view_paint (widget, area);
/* If the area overlaps the "edge" of the widget, draw the focus
* rectangle
*/
if (TRUE || area->x < FOCUS_EDGE_WIDTH ||
if (area->x < FOCUS_EDGE_WIDTH ||
area->y < FOCUS_EDGE_WIDTH ||
(area->x + area->width) > (widget->allocation.width - FOCUS_EDGE_WIDTH) ||
(area->y + area->height) > (widget->allocation.height - FOCUS_EDGE_WIDTH))
gtk_widget_draw_focus (widget);
/* Synthesize expose events for the user-drawn border windows,
* just as we would for a drawing area.
*/
if (text_view->left_window &&
gdk_rectangle_intersect (area, &text_view->left_window->allocation,
&intersection))
send_expose (text_view, text_view->left_window, &intersection);
if (text_view->right_window &&
gdk_rectangle_intersect (area, &text_view->right_window->allocation,
&intersection))
send_expose (text_view, text_view->right_window, &intersection);
if (text_view->top_window &&
gdk_rectangle_intersect (area, &text_view->top_window->allocation,
&intersection))
send_expose (text_view, text_view->top_window, &intersection);
if (text_view->bottom_window &&
gdk_rectangle_intersect (area, &text_view->bottom_window->allocation,
&intersection))
send_expose (text_view, text_view->bottom_window, &intersection);
}
static gint
@ -1872,37 +2073,6 @@ gtk_text_view_expose_event (GtkWidget *widget, GdkEventExpose *event)
return TRUE;
}
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
static void
print_backtrace (void)
{
char **symbols;
void *addresses[50];
int i;
int size;
size = backtrace (addresses, 50);
symbols = backtrace_symbols (addresses, size);
printf ("TRACE\n");
i = 0;
while (i < size)
{
printf (" %s\n", symbols[i]);
++i;
}
free (symbols);
printf ("END\n");
}
static void
gtk_text_view_draw_focus (GtkWidget *widget)
{
@ -3052,6 +3222,27 @@ gtk_text_view_value_changed (GtkAdjustment *adj,
if (dx != 0 || dy != 0)
{
if (dy != 0)
{
if (text_view->left_window)
text_window_scroll (text_view->left_window, 0, dy);
if (text_view->right_window)
text_window_scroll (text_view->right_window, 0, dy);
}
if (dx != 0)
{
if (text_view->top_window)
text_window_scroll (text_view->top_window, dx, 0);
if (text_view->bottom_window)
text_window_scroll (text_view->bottom_window, dx, 0);
}
/* It looks nicer to scroll the main area last, because
* it takes a while, and making the side areas update
* afterward emphasizes the slowness of scrolling the
* main area.
*/
text_window_scroll (text_view->text_window, dx, dy);
}
}
@ -3244,8 +3435,17 @@ text_window_realize (GtkTextWindow *win,
gtk_im_context_set_client_window (GTK_TEXT_VIEW (win->widget)->im_context,
win->window);
}
gdk_window_set_background (win->bin_window,
&win->widget->style->base[GTK_WIDGET_STATE (win->widget)]);
}
else
{
gdk_window_set_background (win->bin_window,
&win->widget->style->bg[GTK_WIDGET_STATE (win->widget)]);
}
g_object_set_qdata (G_OBJECT (win->window),
g_quark_from_static_string ("gtk-text-view-text-window"),
win);
@ -3347,10 +3547,31 @@ gtk_text_view_get_window (GtkTextView *text_view,
break;
case GTK_TEXT_WINDOW_LEFT:
if (text_view->left_window)
return text_view->left_window->bin_window;
else
return NULL;
break;
case GTK_TEXT_WINDOW_RIGHT:
if (text_view->right_window)
return text_view->right_window->bin_window;
else
return NULL;
break;
case GTK_TEXT_WINDOW_TOP:
if (text_view->top_window)
return text_view->top_window->bin_window;
else
return NULL;
break;
case GTK_TEXT_WINDOW_BOTTOM:
return NULL;
if (text_view->bottom_window)
return text_view->bottom_window->bin_window;
else
return NULL;
break;
default:
@ -3385,6 +3606,68 @@ gtk_text_view_get_window_type (GtkTextView *text_view,
}
}
static void
buffer_to_widget (GtkTextView *text_view,
gint buffer_x,
gint buffer_y,
gint *window_x,
gint *window_y)
{
if (window_x)
{
*window_x = buffer_x - text_view->xoffset + FOCUS_EDGE_WIDTH;
if (text_view->left_window)
*window_x += text_view->left_window->allocation.width;
}
if (window_y)
{
*window_y = buffer_y - text_view->yoffset + FOCUS_EDGE_WIDTH;
if (text_view->top_window)
*window_y += text_view->top_window->allocation.height;
}
}
static void
widget_to_text_window (GtkTextWindow *win,
gint widget_x,
gint widget_y,
gint *window_x,
gint *window_y)
{
if (window_x)
*window_x = widget_x - win->allocation.x;
if (window_y)
*window_y = widget_y - win->allocation.y;
}
static void
buffer_to_text_window (GtkTextView *text_view,
GtkTextWindow *win,
gint buffer_x,
gint buffer_y,
gint *window_x,
gint *window_y)
{
if (win == NULL)
{
g_warning ("Attempt to convert text buffer coordinates to coordinates "
"for a nonexistent child window of GtkTextView");
return;
}
buffer_to_widget (text_view,
buffer_x, buffer_y,
window_x, window_y);
widget_to_text_window (win,
window_x ? *window_x : 0,
window_y ? *window_y : 0,
window_x,
window_y);
}
void
gtk_text_view_buffer_to_window_coords (GtkTextView *text_view,
GtkTextWindowType win,
@ -3393,24 +3676,14 @@ gtk_text_view_buffer_to_window_coords (GtkTextView *text_view,
gint *window_x,
gint *window_y)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), NULL);
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
switch (win)
{
case GTK_TEXT_WINDOW_WIDGET:
if (window_x)
{
*window_x = buffer_x - text_view->xoffset + FOCUS_EDGE_WIDTH;
if (text_view->left_window)
*window_x += text_view->left_window->allocation.width;
}
if (window_y)
{
*window_y = buffer_y - text_view->yoffset + FOCUS_EDGE_WIDTH;
if (text_view->top_window)
*window_y += text_view->top_window->allocation.height;
}
buffer_to_widget (text_view,
buffer_x, buffer_y,
window_x, window_y);
break;
case GTK_TEXT_WINDOW_TEXT:
@ -3421,10 +3694,31 @@ gtk_text_view_buffer_to_window_coords (GtkTextView *text_view,
break;
case GTK_TEXT_WINDOW_LEFT:
buffer_to_text_window (text_view,
text_view->left_window,
buffer_x, buffer_y,
window_x, window_y);
break;
case GTK_TEXT_WINDOW_RIGHT:
buffer_to_text_window (text_view,
text_view->right_window,
buffer_x, buffer_y,
window_x, window_y);
break;
case GTK_TEXT_WINDOW_TOP:
buffer_to_text_window (text_view,
text_view->top_window,
buffer_x, buffer_y,
window_x, window_y);
break;
case GTK_TEXT_WINDOW_BOTTOM:
g_warning ("FIXME");
buffer_to_text_window (text_view,
text_view->bottom_window,
buffer_x, buffer_y,
window_x, window_y);
break;
default:
@ -3433,6 +3727,70 @@ gtk_text_view_buffer_to_window_coords (GtkTextView *text_view,
}
}
static void
widget_to_buffer (GtkTextView *text_view,
gint widget_x,
gint widget_y,
gint *buffer_x,
gint *buffer_y)
{
if (buffer_x)
{
*buffer_x = widget_x - FOCUS_EDGE_WIDTH + text_view->xoffset;
if (text_view->left_window)
*buffer_x -= text_view->left_window->allocation.width;
}
if (buffer_y)
{
*buffer_y = widget_y - FOCUS_EDGE_WIDTH + text_view->yoffset;
if (text_view->top_window)
*buffer_y -= text_view->top_window->allocation.height;
}
}
static void
text_window_to_widget (GtkTextWindow *win,
gint window_x,
gint window_y,
gint *widget_x,
gint *widget_y)
{
if (widget_x)
*widget_x = window_x + win->allocation.x;
if (widget_y)
*widget_y = window_y + win->allocation.y;
}
static void
text_window_to_buffer (GtkTextView *text_view,
GtkTextWindow *win,
gint window_x,
gint window_y,
gint *buffer_x,
gint *buffer_y)
{
if (win == NULL)
{
g_warning ("Attempt to convert GtkTextView buffer coordinates into "
"coordinates for a nonexistent child window.");
return;
}
text_window_to_widget (win,
window_x,
window_y,
buffer_x,
buffer_y);
widget_to_buffer (text_view,
buffer_x ? *buffer_x : 0,
buffer_y ? *buffer_y : 0,
buffer_x,
buffer_y);
}
void
gtk_text_view_window_to_buffer_coords (GtkTextView *text_view,
GtkTextWindowType win,
@ -3441,24 +3799,14 @@ gtk_text_view_window_to_buffer_coords (GtkTextView *text_view,
gint *buffer_x,
gint *buffer_y)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), NULL);
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
switch (win)
{
case GTK_TEXT_WINDOW_WIDGET:
if (buffer_x)
{
*buffer_x = window_x - FOCUS_EDGE_WIDTH + text_view->xoffset;
if (text_view->left_window)
*buffer_x -= text_view->left_window->allocation.width;
}
if (buffer_y)
{
*buffer_y = window_y - FOCUS_EDGE_WIDTH + text_view->yoffset;
if (text_view->top_window)
*buffer_y -= text_view->top_window->allocation.height;
}
widget_to_buffer (text_view,
window_x, window_y,
buffer_x, buffer_y);
break;
case GTK_TEXT_WINDOW_TEXT:
@ -3469,10 +3817,31 @@ gtk_text_view_window_to_buffer_coords (GtkTextView *text_view,
break;
case GTK_TEXT_WINDOW_LEFT:
text_window_to_buffer (text_view,
text_view->left_window,
window_x, window_y,
buffer_x, buffer_y);
break;
case GTK_TEXT_WINDOW_RIGHT:
text_window_to_buffer (text_view,
text_view->right_window,
window_x, window_y,
buffer_x, buffer_y);
break;
case GTK_TEXT_WINDOW_TOP:
text_window_to_buffer (text_view,
text_view->top_window,
window_x, window_y,
buffer_x, buffer_y);
break;
case GTK_TEXT_WINDOW_BOTTOM:
g_warning ("FIXME");
text_window_to_buffer (text_view,
text_view->bottom_window,
window_x, window_y,
buffer_x, buffer_y);
break;
default:
@ -3481,3 +3850,113 @@ gtk_text_view_window_to_buffer_coords (GtkTextView *text_view,
}
}
static void
set_window_width (GtkTextView *text_view,
gint width,
GtkTextWindowType type,
GtkTextWindow **winp)
{
if (width == 0)
{
if (*winp)
{
text_window_free (*winp);
*winp = NULL;
gtk_widget_queue_resize (GTK_WIDGET (text_view));
}
}
else
{
if (*winp == NULL)
{
*winp = text_window_new (type,
GTK_WIDGET (text_view),
width, 0);
}
else
{
if ((*winp)->requisition.width == width)
return;
}
gtk_widget_queue_resize (GTK_WIDGET (text_view));
}
}
static void
set_window_height (GtkTextView *text_view,
gint height,
GtkTextWindowType type,
GtkTextWindow **winp)
{
if (height == 0)
{
if (*winp)
{
text_window_free (*winp);
*winp = NULL;
gtk_widget_queue_resize (GTK_WIDGET (text_view));
}
}
else
{
if (*winp == NULL)
{
*winp = text_window_new (type,
GTK_WIDGET (text_view),
0, height);
}
else
{
if ((*winp)->requisition.height == height)
return;
}
gtk_widget_queue_resize (GTK_WIDGET (text_view));
}
}
void
gtk_text_view_set_left_window_width (GtkTextView *text_view,
gint width)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (width >= 0);
set_window_width (text_view, width, GTK_TEXT_WINDOW_LEFT,
&text_view->left_window);
}
void
gtk_text_view_set_right_window_width (GtkTextView *text_view,
gint width)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (width >= 0);
set_window_width (text_view, width, GTK_TEXT_WINDOW_RIGHT,
&text_view->right_window);
}
void
gtk_text_view_set_top_window_height (GtkTextView *text_view,
gint height)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (height >= 0);
set_window_height (text_view, height, GTK_TEXT_WINDOW_TOP,
&text_view->top_window);
}
void
gtk_text_view_set_bottom_window_height (GtkTextView *text_view,
gint height)
{
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (height >= 0);
set_window_height (text_view, height, GTK_TEXT_WINDOW_BOTTOM,
&text_view->bottom_window);
}

View File

@ -1408,6 +1408,154 @@ view_set_title (View *view)
g_free (title);
}
static void
get_lines (GtkTextView *text_view,
gint first_y,
gint last_y,
gint **buffer_coords,
gint **numbers,
gint *countp)
{
GtkTextIter iter;
gint count;
gint size;
if (buffer_coords)
*buffer_coords = NULL;
if (numbers)
*numbers = NULL;
/* Get iter at first y */
gtk_text_view_get_iter_at_location (text_view, &iter, 0, first_y);
/* Move back to start of its paragraph */
gtk_text_iter_set_line_offset (&iter, 0);
/* For each iter, get its location and add it to the arrays.
* Stop when we pass last_y
*/
count = 0;
size = 0;
while (!gtk_text_iter_is_last (&iter))
{
GdkRectangle loc;
gtk_text_view_get_iter_location (text_view, &iter, &loc);
if (loc.y >= last_y)
break;
if (count >= size)
{
size = 2 * size + 2; /* + 2 handles size == 0 case */
if (buffer_coords)
*buffer_coords = g_realloc (*buffer_coords,
size * sizeof (gint));
if (numbers)
*numbers = g_realloc (*numbers,
size * sizeof (gint));
}
if (buffer_coords)
(*buffer_coords)[count] = loc.y;
if (numbers)
(*numbers)[count] = gtk_text_iter_get_line (&iter);
++count;
gtk_text_iter_forward_line (&iter);
}
*countp = count;
}
static gint
line_numbers_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
gint count;
gint *numbers = NULL;
gint *pixels = NULL;
gint first_y;
gint last_y;
gint i;
GdkWindow *left_win;
PangoLayout *layout;
GtkTextView *text_view;
text_view = GTK_TEXT_VIEW (widget);
/* See if this expose is on the line numbers window */
left_win = gtk_text_view_get_window (text_view,
GTK_TEXT_WINDOW_LEFT);
if (event->window != left_win)
return FALSE;
first_y = event->area.y;
last_y = first_y + event->area.height;
gtk_text_view_window_to_buffer_coords (text_view,
GTK_TEXT_WINDOW_LEFT,
first_y,
last_y,
&first_y,
&last_y);
get_lines (text_view,
first_y,
last_y,
&pixels,
&numbers,
&count);
/* Draw fully internationalized numbers! */
layout = gtk_widget_create_pango_layout (widget, "");
i = 0;
while (i < count)
{
gint pos;
gchar *str;
gtk_text_view_buffer_to_window_coords (text_view,
GTK_TEXT_WINDOW_LEFT,
0,
pixels[i],
NULL,
&pos);
str = g_strdup_printf ("%d", numbers[i]);
pango_layout_set_text (layout, str, -1);
gdk_draw_layout (left_win,
widget->style->fg_gc [widget->state],
/* 2 is just a random padding */
2, pos + 2,
layout);
g_free (str);
++i;
}
g_free (pixels);
g_free (numbers);
g_object_unref (G_OBJECT (layout));
return TRUE;
}
static View *
create_view (Buffer *buffer)
{
@ -1449,8 +1597,32 @@ create_view (Buffer *buffer)
GTK_POLICY_AUTOMATIC);
view->text_view = gtk_text_view_new_with_buffer (buffer->buffer);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view), GTK_WRAPMODE_WORD);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view),
GTK_WRAPMODE_WORD);
/* Set sizes on these windows, just for debugging */
gtk_text_view_set_right_window_width (GTK_TEXT_VIEW (view->text_view),
30);
gtk_text_view_set_top_window_height (GTK_TEXT_VIEW (view->text_view),
15);
gtk_text_view_set_bottom_window_height (GTK_TEXT_VIEW (view->text_view),
23);
/* Draw line numbers in the left window; we should really be
* more scientific about what width we set it to.
*/
gtk_text_view_set_left_window_width (GTK_TEXT_VIEW (view->text_view),
30);
gtk_signal_connect (GTK_OBJECT (view->text_view),
"expose_event",
GTK_SIGNAL_FUNC (line_numbers_expose),
NULL);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (sw), view->text_view);

View File

@ -1408,6 +1408,154 @@ view_set_title (View *view)
g_free (title);
}
static void
get_lines (GtkTextView *text_view,
gint first_y,
gint last_y,
gint **buffer_coords,
gint **numbers,
gint *countp)
{
GtkTextIter iter;
gint count;
gint size;
if (buffer_coords)
*buffer_coords = NULL;
if (numbers)
*numbers = NULL;
/* Get iter at first y */
gtk_text_view_get_iter_at_location (text_view, &iter, 0, first_y);
/* Move back to start of its paragraph */
gtk_text_iter_set_line_offset (&iter, 0);
/* For each iter, get its location and add it to the arrays.
* Stop when we pass last_y
*/
count = 0;
size = 0;
while (!gtk_text_iter_is_last (&iter))
{
GdkRectangle loc;
gtk_text_view_get_iter_location (text_view, &iter, &loc);
if (loc.y >= last_y)
break;
if (count >= size)
{
size = 2 * size + 2; /* + 2 handles size == 0 case */
if (buffer_coords)
*buffer_coords = g_realloc (*buffer_coords,
size * sizeof (gint));
if (numbers)
*numbers = g_realloc (*numbers,
size * sizeof (gint));
}
if (buffer_coords)
(*buffer_coords)[count] = loc.y;
if (numbers)
(*numbers)[count] = gtk_text_iter_get_line (&iter);
++count;
gtk_text_iter_forward_line (&iter);
}
*countp = count;
}
static gint
line_numbers_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
gint count;
gint *numbers = NULL;
gint *pixels = NULL;
gint first_y;
gint last_y;
gint i;
GdkWindow *left_win;
PangoLayout *layout;
GtkTextView *text_view;
text_view = GTK_TEXT_VIEW (widget);
/* See if this expose is on the line numbers window */
left_win = gtk_text_view_get_window (text_view,
GTK_TEXT_WINDOW_LEFT);
if (event->window != left_win)
return FALSE;
first_y = event->area.y;
last_y = first_y + event->area.height;
gtk_text_view_window_to_buffer_coords (text_view,
GTK_TEXT_WINDOW_LEFT,
first_y,
last_y,
&first_y,
&last_y);
get_lines (text_view,
first_y,
last_y,
&pixels,
&numbers,
&count);
/* Draw fully internationalized numbers! */
layout = gtk_widget_create_pango_layout (widget, "");
i = 0;
while (i < count)
{
gint pos;
gchar *str;
gtk_text_view_buffer_to_window_coords (text_view,
GTK_TEXT_WINDOW_LEFT,
0,
pixels[i],
NULL,
&pos);
str = g_strdup_printf ("%d", numbers[i]);
pango_layout_set_text (layout, str, -1);
gdk_draw_layout (left_win,
widget->style->fg_gc [widget->state],
/* 2 is just a random padding */
2, pos + 2,
layout);
g_free (str);
++i;
}
g_free (pixels);
g_free (numbers);
g_object_unref (G_OBJECT (layout));
return TRUE;
}
static View *
create_view (Buffer *buffer)
{
@ -1449,8 +1597,32 @@ create_view (Buffer *buffer)
GTK_POLICY_AUTOMATIC);
view->text_view = gtk_text_view_new_with_buffer (buffer->buffer);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view), GTK_WRAPMODE_WORD);
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view),
GTK_WRAPMODE_WORD);
/* Set sizes on these windows, just for debugging */
gtk_text_view_set_right_window_width (GTK_TEXT_VIEW (view->text_view),
30);
gtk_text_view_set_top_window_height (GTK_TEXT_VIEW (view->text_view),
15);
gtk_text_view_set_bottom_window_height (GTK_TEXT_VIEW (view->text_view),
23);
/* Draw line numbers in the left window; we should really be
* more scientific about what width we set it to.
*/
gtk_text_view_set_left_window_width (GTK_TEXT_VIEW (view->text_view),
30);
gtk_signal_connect (GTK_OBJECT (view->text_view),
"expose_event",
GTK_SIGNAL_FUNC (line_numbers_expose),
NULL);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (sw), view->text_view);