X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcer%2Fsrc%2Fxtext.c;fp=apps%2Fsilcer%2Fsrc%2Fxtext.c;h=0000000000000000000000000000000000000000;hb=72c2de619079457f7a68100eb13385275a424a23;hp=74e84522d28b60353d0b03e3b009eb074f28ab79;hpb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;p=runtime.git diff --git a/apps/silcer/src/xtext.c b/apps/silcer/src/xtext.c deleted file mode 100644 index 74e84522..00000000 --- a/apps/silcer/src/xtext.c +++ /dev/null @@ -1,3033 +0,0 @@ -/* X-Chat - * Copyright (C) 1998 Peter Zelezny. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * ========================================================================= - * - * xtext, the text widget used by X-Chat. - * - * By Peter Zelezny . - * Some functions used from Zvt and Eterm (transparency stuff). - * - */ - -#define USE_XLIB /* turn this ON for non-xchat use. */ -#undef XCHAT /* using xchat */ -#define REFRESH_TIMEOUT 20 -#define WORDWRAP_LIMIT 24 -#define TINT_VALUE 195 /* 195/255 of the brightness. */ -#define MOTION_MONITOR 1 /* URL hilights. */ -#define MARGIN 2 /* dont touch. */ - -#include /* can define USE_XLIB here */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef USE_XLIB -#include -#include -#include -#endif - -#include "xtext.h" - -#ifdef USE_GDK_PIXBUF -#include -#endif - -#undef GTK_WIDGET -#define GTK_WIDGET(n) ((GtkWidget*)n) -#undef GTK_OBJECT -#define GTK_OBJECT(n) ((GtkObject*)n) -#undef GTK_OBJECT_CLASS -#define GTK_OBJECT_CLASS(n) ((GtkObjectClass*)n) - -static GtkWidgetClass *parent_class = NULL; - -enum -{ - WORD_CLICK, - LAST_SIGNAL -}; -static guint xtext_signals[LAST_SIGNAL] = { 0 }; - -#ifdef XCHAT -char *nocasestrstr (char *text, char *tofind); /* util.c */ -#endif -static void gtk_xtext_render_page (GtkXText * xtext); -static void gtk_xtext_calc_lines (GtkXText * xtext, int); -#ifdef USE_XLIB -static void gtk_xtext_load_trans (GtkXText * xtext); -static void gtk_xtext_free_trans (GtkXText * xtext); -#endif -static textentry *gtk_xtext_nth (GtkXText * xtext, textentry * start_ent, - int line, int width, int *subline); -static gint gtk_xtext_selection_kill (GtkWidget * widget, - GdkEventSelection * event); -static void gtk_xtext_selection_get (GtkWidget * widget, - GtkSelectionData * selection_data_ptr, - guint info, guint time); -static int gtk_xtext_text_width (GtkXText * xtext, unsigned char *text, - int len); -static void gtk_xtext_adjustment_changed (GtkAdjustment * adj, - GtkXText * xtext); -static void gtk_xtext_draw_sep (GtkXText * xtext, int height); -static void gtk_xtext_render_ents (GtkXText * xtext, textentry *, textentry *, - int); -static void gtk_xtext_recalc_widths (GtkXText * xtext, int); -static void gtk_xtext_fix_indent (GtkXText * xtext); - -/* some utility functions first */ - -#ifndef XCHAT /* xchat has this in util.c */ - -static char * -nocasestrstr (char *s, char *wanted) -{ - register const size_t len = strlen (wanted); - - if (len == 0) - return (char *)s; - while (toupper(*s) != toupper(*wanted) || strncasecmp (s, wanted, len)) - if (*s++ == '\0') - return (char *)NULL; - return (char *)s; -} - -#endif - -static int -is_del (char c) -{ - switch (c) - { - case ' ': - case 0: - case '\n': - /*case '[': - case ']': */ - case ')': - case '(': - case '>': - case '<': - return 1; - } - return 0; -} - -static void -xtext_set_fg (GdkGC *gc, gulong pixel) -{ - GdkColor col; - - col.pixel = pixel; - gdk_gc_set_foreground (gc, &col); -} - -static void -xtext_set_bg (GdkGC *gc, gulong pixel) -{ - GdkColor col; - - col.pixel = pixel; - gdk_gc_set_background (gc, &col); -} - -static void -gtk_xtext_init (GtkXText * xtext) -{ - xtext->old_value = -1; - xtext->pixmap = NULL; - xtext->text_first = NULL; - xtext->text_last = NULL; - xtext->io_tag = -1; - xtext->add_io_tag = -1; - xtext->scroll_tag = -1; -/* xtext->frozen = 0;*/ - xtext->num_lines = 0; - xtext->max_lines = 0; - xtext->col_back = 19; - xtext->col_fore = 18; - xtext->nc = 0; - xtext->scrollbar_down = TRUE; - xtext->bold = FALSE; - xtext->underline = FALSE; - xtext->reverse = FALSE; - xtext->time_stamp = FALSE; - xtext->font = NULL; - xtext->error_function = NULL; - xtext->urlcheck_function = NULL; - xtext->color_paste = FALSE; - xtext->skip_fills = FALSE; - xtext->skip_border_fills = FALSE; - xtext->do_underline_fills_only = FALSE; - xtext->tint_red = xtext->tint_green = xtext->tint_blue = TINT_VALUE; - - xtext->adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 0, 1, 0, 0); - gtk_object_ref ((GtkObject *) xtext->adj); - gtk_object_sink ((GtkObject *) xtext->adj); - - gtk_signal_connect (GTK_OBJECT (xtext->adj), "value_changed", - GTK_SIGNAL_FUNC (gtk_xtext_adjustment_changed), xtext); - gtk_signal_connect (GTK_OBJECT (xtext), "selection_clear_event", - GTK_SIGNAL_FUNC (gtk_xtext_selection_kill), xtext); - gtk_selection_add_target (GTK_WIDGET (xtext), - GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, 1); - gtk_signal_connect (GTK_OBJECT (xtext), "selection_get", - GTK_SIGNAL_FUNC (gtk_xtext_selection_get), xtext); -} - -static void -gtk_xtext_adjustment_set (GtkXText * xtext, int fire_signal) -{ - GtkAdjustment *adj = xtext->adj; - - adj->lower = 0; - adj->upper = xtext->num_lines; - - adj->page_size = - (GTK_WIDGET (xtext)->allocation.height - - xtext->font->descent) / xtext->fontsize; - adj->page_increment = adj->page_size; - - if (adj->value > adj->upper - adj->page_size) - adj->value = adj->upper - adj->page_size; - - if (fire_signal) - gtk_adjustment_changed (adj); -} - -static gint -gtk_xtext_adjustment_timeout (GtkXText * xtext) -{ - gtk_xtext_render_page (xtext); - xtext->io_tag = -1; - return 0; -} - -static void -gtk_xtext_adjustment_changed (GtkAdjustment * adj, GtkXText * xtext) -{ -/* if (xtext->frozen) - return;*/ - - if ((int) xtext->old_value != (int) xtext->adj->value) - { - if (xtext->adj->value >= xtext->adj->upper - xtext->adj->page_size) - xtext->scrollbar_down = TRUE; - else - xtext->scrollbar_down = FALSE; - - if (xtext->adj->value + 1 == xtext->old_value || - xtext->adj->value - 1 == xtext->old_value) /* clicked an arrow? */ - { - if (xtext->io_tag != -1) - { - gtk_timeout_remove (xtext->io_tag); - xtext->io_tag = -1; - } - gtk_xtext_render_page (xtext); - } else - { - if (xtext->io_tag == -1) - xtext->io_tag = gtk_timeout_add (REFRESH_TIMEOUT, - (GtkFunction) - gtk_xtext_adjustment_timeout, - xtext); - } - } - xtext->old_value = adj->value; -} - -GtkWidget * -gtk_xtext_new (int indent, int separator) -{ - GtkXText *xtext; - - xtext = gtk_type_new (gtk_xtext_get_type ()); - xtext->indent = indent; - xtext->separator = separator; - xtext->wordwrap = FALSE; - xtext->double_buffer = FALSE; - - return GTK_WIDGET (xtext); -} - -static void -gtk_xtext_destroy (GtkObject * object) -{ - GtkXText *xtext = GTK_XTEXT (object); - textentry *ent, *next; - - if (xtext->add_io_tag != -1) - { - gtk_timeout_remove (xtext->add_io_tag); - xtext->add_io_tag = -1; - } - - if (xtext->scroll_tag != -1) - { - gtk_timeout_remove (xtext->scroll_tag); - xtext->scroll_tag = -1; - } - - if (xtext->io_tag != -1) - { - gtk_timeout_remove (xtext->io_tag); - xtext->io_tag = -1; - } - - if (xtext->pixmap) - { -#ifdef USE_XLIB - if (xtext->transparent) - gtk_xtext_free_trans (xtext); - else -#endif - gdk_pixmap_unref (xtext->pixmap); - xtext->pixmap = NULL; - } - - if (xtext->font) - { - gdk_font_unref (xtext->font); - xtext->font = NULL; - } - - if (xtext->adj) - { - gtk_signal_disconnect_by_data (GTK_OBJECT (xtext->adj), xtext); - gtk_object_unref (GTK_OBJECT (xtext->adj)); - xtext->adj = NULL; - } - - if (xtext->bgc) - { - gdk_gc_destroy (xtext->bgc); - xtext->bgc = NULL; - } - - if (xtext->fgc) - { - gdk_gc_destroy (xtext->fgc); - xtext->fgc = NULL; - } - - if (xtext->light_gc) - { - gdk_gc_destroy (xtext->light_gc); - xtext->light_gc = NULL; - } - - if (xtext->dark_gc) - { - gdk_gc_destroy (xtext->dark_gc); - xtext->dark_gc = NULL; - } - - if (xtext->hand_cursor) - { - gdk_cursor_destroy (xtext->hand_cursor); - xtext->hand_cursor = NULL; - } - - ent = xtext->text_first; - while (ent) - { - next = ent->next; - free (ent); - ent = next; - } - xtext->text_first = NULL; - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (*GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - -static void -gtk_xtext_realize (GtkWidget * widget) -{ - GtkXText *xtext; - GdkWindowAttr attributes; - GdkGCValues val; - GdkColor col; - GdkColormap *cmap; - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - xtext = GTK_XTEXT (widget); - - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.event_mask = gtk_widget_get_events (widget) | - GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK -#ifdef MOTION_MONITOR - | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK; -#else - | GDK_POINTER_MOTION_MASK; -#endif - - cmap = gtk_widget_get_colormap (widget); - attributes.colormap = cmap; - attributes.visual = gtk_widget_get_visual (widget); - - widget->window = gdk_window_new (widget->parent->window, &attributes, - GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | - GDK_WA_COLORMAP); - - gdk_window_set_user_data (widget->window, widget); - - xtext->depth = gdk_window_get_visual (widget->window)->depth; - - val.subwindow_mode = GDK_INCLUDE_INFERIORS; - val.graphics_exposures = 0; - - xtext->bgc = gdk_gc_new_with_values (widget->window, &val, - GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW); - xtext->fgc = gdk_gc_new_with_values (widget->window, &val, - GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW); - xtext->light_gc = gdk_gc_new_with_values (widget->window, &val, - GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW); - xtext->dark_gc = gdk_gc_new_with_values (widget->window, &val, - GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW); - - /* for the separator bar (light) */ - col.red = 0xffff; col.green = 0xffff; col.blue = 0xffff; - /* is setting the pixel necessary (or even correct) ?? */ - col.pixel = (gulong)((col.red & 0xff00) * 256 + - (col.green & 0xff00) + - (col.blue & 0xff00) / 256); - gdk_color_alloc (cmap, &col); - gdk_gc_set_foreground (xtext->light_gc, &col); - - /* for the separator bar (dark) */ - col.red = 0x8e38; col.green = 0x8e38; col.blue = 0x9f38; - col.pixel = (gulong)((col.red & 0xff00) * 256 + - (col.green & 0xff00) + - (col.blue & 0xff00) / 256); - gdk_color_alloc (cmap, &col); - gdk_gc_set_foreground (xtext->dark_gc, &col); - - if (xtext->fonttype != FONT_SET && xtext->font != NULL) - gdk_gc_set_font (xtext->fgc, xtext->font); - - xtext_set_fg (xtext->fgc, xtext->palette[18]); - xtext_set_bg (xtext->fgc, xtext->palette[19]); - xtext_set_fg (xtext->bgc, xtext->palette[19]); - -#ifdef USE_XLIB - if (xtext->transparent) - { - gtk_xtext_load_trans (xtext); - } else if (xtext->pixmap) - { - gdk_gc_set_tile (xtext->bgc, xtext->pixmap); - gdk_gc_set_ts_origin (xtext->bgc, 0, 0); - gdk_gc_set_fill (xtext->bgc, GDK_TILED); - } -#else - if (xtext->pixmap) - { - gdk_gc_set_tile (xtext->bgc, xtext->pixmap); - gdk_gc_set_ts_origin (xtext->bgc, 0, 0); - gdk_gc_set_fill (xtext->bgc, GDK_TILED); - } -#endif - - xtext->hand_cursor = gdk_cursor_new (GDK_HAND1); - - gdk_window_set_back_pixmap (widget->window, NULL, FALSE); - - /* if not doublebuffer, draw directly to window */ - if (!xtext->double_buffer) - xtext->draw_buf = widget->window; - - if (xtext->auto_indent) - xtext->indent = 1; -} - -static void -gtk_xtext_size_request (GtkWidget * widget, GtkRequisition * requisition) -{ - requisition->width = GTK_XTEXT (widget)->fontwidth['Z'] * 20; - requisition->height = (GTK_XTEXT (widget)->fontsize * 10) + 3; -} - -static void -gtk_xtext_size_allocate (GtkWidget * widget, GtkAllocation * allocation) -{ - GtkXText *xtext = GTK_XTEXT (widget); - - if (allocation->width == widget->allocation.width && - allocation->height == widget->allocation.height && - allocation->x == widget->allocation.x && - allocation->y == widget->allocation.y) - return; - - widget->allocation = *allocation; - if (GTK_WIDGET_REALIZED (widget)) - { - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - gtk_xtext_calc_lines (xtext, FALSE); - } -} - -static void -gtk_xtext_draw (GtkWidget * widget, GdkRectangle * area) -{ - int x, y; - GtkXText *xtext = GTK_XTEXT (widget); - -#ifdef USE_XLIB - if (xtext->transparent) - { - gdk_window_get_origin (widget->window, &x, &y); - /* update transparency only if it moved */ - if (xtext->last_win_x != x || xtext->last_win_y != y) - { - xtext->last_win_x = x; - xtext->last_win_y = y; - gtk_xtext_free_trans (xtext); - gtk_xtext_load_trans (xtext); - } - } -#endif - - if (xtext->scrollbar_down) - gtk_adjustment_set_value (xtext->adj, - xtext->adj->upper - xtext->adj->page_size); - gtk_xtext_render_page (xtext); -} - -static int -gtk_xtext_selection_clear (GtkXText * xtext) -{ - textentry *ent; - int ret = 0; - - ent = xtext->last_ent_start; - while (ent) - { - if (ent->mark_start != -1) - ret = 1; - ent->mark_start = -1; - ent->mark_end = -1; - if (ent == xtext->last_ent_end) - break; - ent = ent->next; - } - - return ret; -} - -static int -find_x_8bit (GtkXText *xtext, textentry *ent, char *text, int x, int indent) -{ - int xx = indent; - int i = 0; - int col = FALSE; - int nc = 0; - char *orig = text; - int a; - - while (*text) - { - if ((col && isdigit (*text) && nc < 2) || - (col && *text == ',' && nc < 3)) - { - nc++; - if (*text == ',') - nc = 0; - } else - { - col = FALSE; - switch (*text) - { - case ATTR_COLOR: - col = TRUE; - nc = 0; - break; - case ATTR_BEEP: - case ATTR_RESET: - case ATTR_REVERSE: - case ATTR_BOLD: - case ATTR_UNDERLINE: - break; - default: - a = *((unsigned char *)text); - xx += xtext->fontwidth[a]; - if (xx >= x) - return i + (orig - ent->str); - } - } - text++; - i++; - if (text - orig >= ent->str_len) - return ent->str_len; - } - - return ent->str_len; -} - -static int -find_x_general (GtkXText * xtext, textentry * ent, char *str, int x, int indent) -{ - int str_width; - int len = 1; - - while (1) - { - str_width = gtk_xtext_text_width (xtext, str, len); - if (str_width + indent >= x) - return (str + len) - ent->str; - len++; - if (len + (str - ent->str) > ent->str_len) - return ent->str_len; - if (str_width + indent + 40 < x) - len += 2; - } -} - -static int -find_x (GtkXText * xtext, textentry * ent, char *str, int x, int indent) -{ - if (xtext->fonttype == FONT_1BYTE) - return find_x_8bit (xtext, ent, str, x, indent); - - return find_x_general (xtext, ent, str, x, indent); -} - -static int -gtk_xtext_find_x (GtkXText * xtext, int x, textentry * ent, int offset, - int line, int win_width, int *out_of_bounds) -{ - int indent; - char *str; - - if (offset < 1) - indent = ent->indent; - else - indent = xtext->indent; - - if (line > xtext->adj->page_size || line < 0) - return 0; - - if (xtext->grid_offset[line] > ent->str_len) - return 0; - - if (xtext->grid_offset[line] < 0) - return 0; - - str = ent->str + xtext->grid_offset[line]; - - if (x < indent) - { - *out_of_bounds = 1; - return (str - ent->str); - } - - *out_of_bounds = 0; - - return find_x (xtext, ent, str, x, indent); -} - -static textentry * -gtk_xtext_find_char (GtkXText * xtext, int x, int y, int *off, - int *out_of_bounds) -{ - textentry *ent; - int line; - int subline; - int win_width; - - gdk_window_get_size (GTK_WIDGET (xtext)->window, &win_width, 0); - win_width -= MARGIN; - - line = (y - xtext->font->descent) / xtext->fontsize; - - subline = xtext->pagetop_subline; - ent = gtk_xtext_nth (xtext, xtext->pagetop_ent, line, win_width, &subline); - if (!ent) - return 0; - - if (off) - *off = gtk_xtext_find_x (xtext, x, ent, subline, line, win_width, - out_of_bounds); - - return ent; -} - -static gint -gtk_xtext_expose (GtkWidget * widget, GdkEventExpose * event) -{ - GtkXText *xtext = GTK_XTEXT (widget); - textentry *ent_start, *ent_end; - - if (xtext->double_buffer) - { - gtk_xtext_render_page (xtext); - return FALSE; - } - - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, - event->area.x, event->area.y, - event->area.width, event->area.height); - - ent_start = gtk_xtext_find_char (xtext, event->area.x, event->area.y, - NULL, NULL); - ent_end = gtk_xtext_find_char (xtext, event->area.x + event->area.width, - event->area.y + event->area.height, NULL, NULL); - - xtext->skip_fills = TRUE; - xtext->skip_border_fills = TRUE; - - gtk_xtext_render_ents (xtext, ent_start, ent_end, TRUE); - - xtext->skip_fills = FALSE; - xtext->skip_border_fills = FALSE; - - return FALSE; -} - -static void -gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event) -{ - textentry *ent; - textentry *ent_end; - textentry *ent_start; - int offset_start; - int offset_end; - int low_x; - int low_y; - int high_x; - int high_y; - int tmp; - - if (xtext->select_start_y > xtext->select_end_y) - { - low_x = xtext->select_end_x; - low_y = xtext->select_end_y; - high_x = xtext->select_start_x; - high_y = xtext->select_start_y; - } else - { - low_x = xtext->select_start_x; - low_y = xtext->select_start_y; - high_x = xtext->select_end_x; - high_y = xtext->select_end_y; - } - - ent_start = gtk_xtext_find_char (xtext, low_x, low_y, &offset_start, &tmp); - ent_end = gtk_xtext_find_char (xtext, high_x, high_y, &offset_end, &tmp); - - if (ent_start && !ent_end) - { - ent_end = xtext->text_last; - offset_end = ent_end->str_len; - } - - if (!ent_start || !ent_end) - { - if (xtext->adj->value != xtext->old_value) - gtk_xtext_render_page (xtext); - return; - } - - gtk_xtext_selection_clear (xtext); - - /* marking less than a complete line? */ - if (ent_start == ent_end) - { - ent_start->mark_start = MIN (offset_start, offset_end); - ent_start->mark_end = MAX (offset_end, offset_start); - if (offset_start == offset_end) - ent_start->mark_end++; - } else - { - ent_start->mark_start = offset_start; - ent_start->mark_end = ent_start->str_len; - - if (offset_end != 0) - { - ent_end->mark_start = 0; - ent_end->mark_end = offset_end; - } - } - - if (ent_start != ent_end) - { - ent = ent_start->next; - while (ent && ent != ent_end) - { - ent->mark_start = 0; - ent->mark_end = ent->str_len; - ent = ent->next; - } - } - - /* has the selection changed? Dont render unless necessary */ - if (xtext->last_ent_start == ent_start && - xtext->last_ent_end == ent_end && - xtext->last_offset_start == offset_start && - xtext->last_offset_end == offset_end) - return; - - gtk_selection_owner_set (GTK_WIDGET (xtext), GDK_SELECTION_PRIMARY, - event->time); - - if (xtext->double_buffer) - { - if (xtext->io_tag == -1) - xtext->io_tag = gtk_timeout_add (REFRESH_TIMEOUT, - (GtkFunction) - gtk_xtext_adjustment_timeout, - xtext); - } else - { - ent = xtext->last_ent_end; - if (ent) - if (ent->next == ent_end) - ent = ent_end; - xtext->skip_border_fills = TRUE; - gtk_xtext_render_ents (xtext, xtext->last_ent_start, ent, TRUE); - xtext->skip_border_fills = FALSE; - xtext->old_ent_start = xtext->last_ent_start; - xtext->old_ent_end = xtext->last_ent_end; - } - - xtext->last_ent_start = ent_start; - xtext->last_ent_end = ent_end; - xtext->last_offset_start = offset_start; - xtext->last_offset_end = offset_end; -} - -static gint -gtk_xtext_scrolldown_timeout (GtkXText * xtext) -{ - int p_y, win_height; - - gdk_window_get_pointer (GTK_WIDGET (xtext)->window, 0, &p_y, 0); - gdk_window_get_size (GTK_WIDGET (xtext)->window, 0, &win_height); - - if (p_y > win_height && - xtext->adj->value < (xtext->adj->upper - xtext->adj->page_size)) - { - xtext->adj->value++; - gtk_adjustment_changed (xtext->adj); - gtk_xtext_render_page (xtext); - return 1; - } - - xtext->scroll_tag = -1; - return 0; -} - -static gint -gtk_xtext_scrollup_timeout (GtkXText * xtext) -{ - int p_y; - - gdk_window_get_pointer (GTK_WIDGET (xtext)->window, 0, &p_y, 0); - - if (p_y < 0 && xtext->adj->value > 0.0) - { - xtext->adj->value--; - gtk_adjustment_changed (xtext->adj); - gtk_xtext_render_page (xtext); - return 1; - } - - xtext->scroll_tag = -1; - return 0; -} - -static void -gtk_xtext_selection_update (GtkXText * xtext, GdkEventMotion * event, int p_y) -{ - int win_height; - int moved; - - gdk_window_get_size (GTK_WIDGET (xtext)->window, 0, &win_height); - - /* selecting past top of window, scroll up! */ - if (p_y < 0 && xtext->adj->value >= 0) - { - if (xtext->scroll_tag == -1) - xtext->scroll_tag = gtk_timeout_add (100, - (GtkFunction) - gtk_xtext_scrollup_timeout, - xtext); - return; - } - - /* selecting past bottom of window, scroll down! */ - if (p_y > win_height && - xtext->adj->value < (xtext->adj->upper - xtext->adj->page_size)) - { - if (xtext->scroll_tag == -1) - xtext->scroll_tag = gtk_timeout_add (100, - (GtkFunction) - gtk_xtext_scrolldown_timeout, - xtext); - return; - } - - moved = xtext->adj->value - xtext->select_start_adj; - xtext->select_start_y -= (moved * xtext->fontsize); - xtext->select_start_adj = xtext->adj->value; - gtk_xtext_selection_draw (xtext, event); -} - -static char * -gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, - int *ret_off, int *ret_len) -{ - textentry *ent; - int offset; - char *str; - char *word; - int len; - int out_of_bounds; - - ent = gtk_xtext_find_char (xtext, x, y, &offset, &out_of_bounds); - if (!ent) - return 0; - - if (out_of_bounds) - return 0; - - if (offset == ent->str_len) - return 0; - - if (offset < 1) - return 0; - - offset--; - - str = ent->str + offset; - - while (!is_del (*str) && str != ent->str) - str--; - word = str + 1; - - len = 0; - str = word; - while (!is_del (*str) && len != ent->str_len) - { - str++; - len++; - } - - if (ret_ent) - *ret_ent = ent; - if (ret_off) - *ret_off = word - ent->str; - if (ret_len) - *ret_len = str - word; - - word = gtk_xtext_strip_color (word, len, NULL, NULL); - - return word; -} - -static gint -gtk_xtext_leave_notify (GtkWidget * widget, GdkEventCrossing * event) -{ -#ifdef MOTION_MONITOR - GtkXText *xtext = GTK_XTEXT (widget); - - if (xtext->cursor_hand) - { - xtext->hilight_start = -1; - xtext->hilight_end = -1; - xtext->cursor_hand = FALSE; - gdk_window_set_cursor (widget->window, 0); - xtext->skip_border_fills = TRUE; - xtext->do_underline_fills_only = TRUE; - gtk_xtext_render_ents (xtext, xtext->hilight_ent, NULL, FALSE); - xtext->skip_border_fills = FALSE; - xtext->do_underline_fills_only = FALSE; - xtext->hilight_ent = NULL; - } -#endif - return FALSE; -} - -static gint -gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event) -{ - GtkXText *xtext = GTK_XTEXT (widget); - int tmp, x, y, offset, len; - char *word; - textentry *word_ent, *old_ent; - - gdk_window_get_pointer (widget->window, &x, &y, 0); - - if (xtext->moving_separator) - { - if (x < (3 * widget->allocation.width) / 5 && x > 15) - { - tmp = xtext->indent; - xtext->indent = x; - gtk_xtext_fix_indent (xtext); - if (tmp != xtext->indent) - { - gtk_xtext_recalc_widths (xtext, FALSE); - if (xtext->scrollbar_down) - gtk_adjustment_set_value (xtext->adj, xtext->adj->upper - - xtext->adj->page_size); - if (xtext->io_tag == -1) - xtext->io_tag = gtk_timeout_add (REFRESH_TIMEOUT, - (GtkFunction) - gtk_xtext_adjustment_timeout, - xtext); - } - } - return FALSE; - } - - if (xtext->button_down) - { - gtk_grab_add (widget); - /*gdk_pointer_grab (widget->window, TRUE, - GDK_BUTTON_RELEASE_MASK | - GDK_BUTTON_MOTION_MASK, NULL, NULL, 0);*/ - xtext->select_end_x = x; - xtext->select_end_y = y; - gtk_xtext_selection_update (xtext, event, y); - return FALSE; - } -#ifdef MOTION_MONITOR - - if (xtext->urlcheck_function == NULL) - return FALSE; - - word = gtk_xtext_get_word (xtext, x, y, &word_ent, &offset, &len); - if (word) - { - if (xtext->urlcheck_function (xtext, word) > 0) - { - free (word); - if (!xtext->cursor_hand || - xtext->hilight_ent != word_ent || - xtext->hilight_start != offset || - xtext->hilight_end != offset + len) - { - if (!xtext->cursor_hand) - { - gdk_window_set_cursor (GTK_WIDGET (xtext)->window, - xtext->hand_cursor); - xtext->cursor_hand = TRUE; - } - old_ent = xtext->hilight_ent; - xtext->hilight_ent = word_ent; - xtext->hilight_start = offset; - xtext->hilight_end = offset + len; - xtext->skip_border_fills = TRUE; - xtext->do_underline_fills_only = TRUE; - gtk_xtext_render_ents (xtext, old_ent, word_ent, FALSE); - xtext->skip_border_fills = FALSE; - xtext->do_underline_fills_only = FALSE; - } - return FALSE; - } - free (word); - } - - gtk_xtext_leave_notify (widget, NULL); - -#endif - - return FALSE; -} - -static gint -gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event) -{ - GtkXText *xtext = GTK_XTEXT (widget); - char *word; - - if (xtext->moving_separator) - { - xtext->moving_separator = FALSE; - if (event->x < (4 * widget->allocation.width) / 5 && event->x > 15) - { - xtext->indent = event->x; - } - gtk_xtext_fix_indent (xtext); - gtk_xtext_recalc_widths (xtext, FALSE); - gtk_xtext_adjustment_set (xtext, TRUE); - gtk_xtext_render_page (xtext); - return FALSE; - } - - if (xtext->word_or_line_select) - { - xtext->word_or_line_select = FALSE; - xtext->button_down = FALSE; - return FALSE; - } - - if (event->button == 1) - { - xtext->button_down = FALSE; - - gtk_grab_remove (widget); - /*gdk_pointer_ungrab (0);*/ - - if (xtext->select_start_x == event->x && - xtext->select_start_y == event->y) - { - if (gtk_xtext_selection_clear (xtext)) - gtk_xtext_render_page (xtext); - } else - { - word = gtk_xtext_get_word (xtext, event->x, event->y, 0, 0, 0); - if (word) - { - gtk_signal_emit (GTK_OBJECT (xtext), xtext_signals[WORD_CLICK], - word, event); - free (word); - return FALSE; - } - } - } - - return FALSE; -} - -static gint -gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event) -{ - GtkXText *xtext = GTK_XTEXT (widget); - textentry *ent; - char *word; - int line_x, x, y, offset, len; - gfloat new_value; - - gdk_window_get_pointer (widget->window, &x, &y, 0); - - if (event->button == 3) /* right click */ - { - word = gtk_xtext_get_word (xtext, x, y, 0, 0, 0); - if (word) - { - gtk_signal_emit (GTK_OBJECT (xtext), xtext_signals[WORD_CLICK], - word, event); - free (word); - } else - gtk_signal_emit (GTK_OBJECT (xtext), xtext_signals[WORD_CLICK], - "", event); - return FALSE; - } - - if (event->button == 4) /* mouse wheel pageUp */ - { - new_value = xtext->adj->value - xtext->adj->page_increment; - if (new_value < xtext->adj->lower) - new_value = xtext->adj->lower; - gtk_adjustment_set_value (xtext->adj, new_value); - return FALSE; - } - - if (event->button == 5) /* mouse wheel pageDn */ - { - new_value = xtext->adj->value + xtext->adj->page_increment; - if (new_value > (xtext->adj->upper - xtext->adj->page_size)) - new_value = xtext->adj->upper - xtext->adj->page_size; - gtk_adjustment_set_value (xtext->adj, new_value); - return FALSE; - } - - if (event->button == 2) - { - gtk_signal_emit (GTK_OBJECT (xtext), xtext_signals[WORD_CLICK], "", event); - return FALSE; - } - - if (event->button != 1) /* we only want left button */ - return FALSE; - - if (event->type == GDK_2BUTTON_PRESS) /* WORD select */ - { - word = gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len); - if (word) - { - free (word); - if (len == 0) - return FALSE; - gtk_xtext_selection_clear (xtext); - ent->mark_start = offset; - ent->mark_end = offset + len; - xtext->last_ent_start = ent; - xtext->last_ent_end = ent; - gtk_xtext_render_page (xtext); - xtext->word_or_line_select = TRUE; - gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time); - } - - return FALSE; - } - - if (event->type == GDK_3BUTTON_PRESS) /* LINE select */ - { - word = gtk_xtext_get_word (xtext, x, y, &ent, 0, 0); - if (word) - { - free (word); - gtk_xtext_selection_clear (xtext); - ent->mark_start = 0; - ent->mark_end = ent->str_len; - xtext->last_ent_start = ent; - xtext->last_ent_end = ent; - gtk_xtext_render_page (xtext); - xtext->word_or_line_select = TRUE; - gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time); - } - - return FALSE; - } - - /* check if it was a separator-bar click */ - if (xtext->separator && xtext->indent) - { - line_x = xtext->indent - ((xtext->space_width + 1) / 2); - if (line_x == x || line_x == x + 1 || line_x == x - 1) - { - xtext->moving_separator = TRUE; - gtk_xtext_render_page (xtext); - return FALSE; - } - } - - xtext->button_down = TRUE; - - xtext->select_start_x = x; - xtext->select_start_y = y; - - xtext->select_start_adj = xtext->adj->value; - - return FALSE; -} - -/* another program has claimed the selection */ - -static gint -gtk_xtext_selection_kill (GtkWidget * widget, GdkEventSelection * event) -{ - if (gtk_xtext_selection_clear (GTK_XTEXT (widget))) - gtk_xtext_render_page (GTK_XTEXT (widget)); - return TRUE; -} - -/* another program is asking for our selection */ - -static void -gtk_xtext_selection_get (GtkWidget * widget, - GtkSelectionData * selection_data_ptr, - guint info, guint time) -{ - GtkXText *xtext = GTK_XTEXT (widget); - textentry *ent; - char *txt; - char *pos; - char *stripped; - int len; - int first = TRUE; - - /* first find out how much we need to malloc ... */ - len = 0; - ent = xtext->text_first; - while (ent) - { - if (ent->mark_start != -1) - { - if (ent->mark_end - ent->mark_start > 0) - len += (ent->mark_end - ent->mark_start) + 1; - else - len++; - } - ent = ent->next; - } - - /* now allocate mem and copy buffer */ - pos = txt = malloc (len); - ent = xtext->text_first; - while (ent) - { - if (ent->mark_start != -1) - { - if (!first) - { - *pos = '\n'; - pos++; - } - first = FALSE; - if (ent->mark_end - ent->mark_start > 0) - { - memcpy (pos, ent->str + ent->mark_start, - ent->mark_end - ent->mark_start); - pos += ent->mark_end - ent->mark_start; - } - } - ent = ent->next; - } - *pos = 0; - - if (xtext->color_paste) - { - gtk_selection_data_set (selection_data_ptr, GDK_SELECTION_TYPE_STRING, - 8, txt, strlen (txt)); - } else - { - stripped = gtk_xtext_strip_color (txt, strlen (txt), NULL, NULL); - gtk_selection_data_set (selection_data_ptr, GDK_SELECTION_TYPE_STRING, - 8, stripped, strlen (stripped)); - free (stripped); - } - - free (txt); -} - -static void -gtk_xtext_class_init (GtkXTextClass * class) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkXTextClass *xtext_class; - - object_class = (GtkObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - xtext_class = (GtkXTextClass *) class; - - parent_class = gtk_type_class (gtk_widget_get_type ()); - - xtext_signals[WORD_CLICK] = - gtk_signal_new (/*name*/"word_click", - /*GtkSignalRunType*/GTK_RUN_FIRST, - /*GtkType*/object_class->type, - /*funcoffset*/GTK_SIGNAL_OFFSET (GtkXTextClass, word_click), - /*GtkSignalMarshaller*/gtk_marshal_NONE__POINTER_POINTER, - /*returnval*/GTK_TYPE_NONE, - /*num args*/2, /*args*/GTK_TYPE_POINTER, GTK_TYPE_POINTER); - gtk_object_class_add_signals (object_class, xtext_signals, LAST_SIGNAL); - - object_class->destroy = gtk_xtext_destroy; - - widget_class->realize = gtk_xtext_realize; - widget_class->size_request = gtk_xtext_size_request; - widget_class->size_allocate = gtk_xtext_size_allocate; - widget_class->button_press_event = gtk_xtext_button_press; - widget_class->button_release_event = gtk_xtext_button_release; - widget_class->motion_notify_event = gtk_xtext_motion_notify; - widget_class->leave_notify_event = gtk_xtext_leave_notify; - widget_class->draw = gtk_xtext_draw; - widget_class->expose_event = gtk_xtext_expose; - - xtext_class->word_click = NULL; -} - -guint gtk_xtext_get_type () -{ - static guint xtext_type = 0; - - if (!xtext_type) - { - GtkTypeInfo xtext_info = { - "GtkXText", - sizeof (GtkXText), - sizeof (GtkXTextClass), - (GtkClassInitFunc) gtk_xtext_class_init, - (GtkObjectInitFunc) gtk_xtext_init, - (GtkArgSetFunc) NULL, - (GtkArgGetFunc) NULL, - }; - - xtext_type = gtk_type_unique (gtk_widget_get_type (), &xtext_info); - } - - return xtext_type; -} - -/*void -gtk_xtext_thaw (GtkXText *xtext) -{ - if (xtext->frozen > 0) - xtext->frozen--; - - if (xtext->frozen == 0) - gtk_xtext_render_page (xtext); -} - -void -gtk_xtext_freeze (GtkXText *xtext) -{ - xtext->frozen++; -}*/ - -/* strip MIRC colors and other attribs. */ - -char * -gtk_xtext_strip_color (unsigned char *text, int len, char *outbuf, int *newlen) -{ - int nc = 0; - int i = 0; - int col = FALSE; - char *new_str; - - if (outbuf == NULL) - new_str = malloc (len + 2); - else - new_str = outbuf; - - while (len > 0) - { - if ((col && isdigit (*text) && nc < 2) || - (col && *text == ',' && nc < 3)) - { - nc++; - if (*text == ',') - nc = 0; - } else - { - if (col) - col = FALSE; - switch (*text) - { - case ATTR_COLOR: - col = TRUE; - nc = 0; - break; - case ATTR_BEEP: - case ATTR_RESET: - case ATTR_REVERSE: - case ATTR_BOLD: - case ATTR_UNDERLINE: - break; - default: - new_str[i] = *text; - i++; - } - } - text++; - len--; - } - - new_str[i] = 0; - - if (newlen != NULL) - *newlen = i; - - return new_str; -} - -/* gives width of a 8bit string - with no mIRC codes in it */ - -static int -gtk_xtext_text_width_simple (GtkXText * xtext, unsigned char *str, int len) -{ - int width = 0; - - if (xtext->fixed_width_font) - return (xtext->space_width * len); - - while (len) - { - width += xtext->fontwidth[*str]; - len--; - str++; - } - - return width; -} - -/* gives width of a string, excluding the mIRC codes */ - -static int -gtk_xtext_text_width (GtkXText * xtext, unsigned char *text, int len) -{ - unsigned char *tmp, *new_buf; - int width, new_len; - - new_buf = gtk_xtext_strip_color (text, len, xtext->scratch_buffer, &new_len); - - if (xtext->fonttype == FONT_1BYTE) - { - if (xtext->fixed_width_font) - { - width = xtext->space_width * new_len; - } else - { - width = 0; - tmp = new_buf; - while (*tmp) - { - width += xtext->fontwidth[*tmp]; - tmp++; - } - } - } else - { - width = gdk_text_width (xtext->font, new_buf, new_len); - } - - return width; -} - -/* actually draw text to screen */ - -static int -gtk_xtext_render_flush (GtkXText * xtext, int x, int y, char *str, int len, - GdkGC *gc) -{ - int str_width; - int dofill; -#ifdef USE_XLIB - XFontStruct *xfont; - GC xgc; - Drawable xdraw_buf; - Display *xdisplay; -#endif - - if (xtext->dont_render) - return 0; - - if (xtext->fonttype == FONT_1BYTE) - str_width = gtk_xtext_text_width_simple (xtext, str, len); - else - str_width = gdk_text_width (xtext->font, str, len); - - if (str_width < 1) - return 0; - - if (!xtext->backcolor && xtext->pixmap) - { - dofill = FALSE; - /* draw the background pixmap behind the text - CAUSES FLICKER HERE !! */ - if (!xtext->double_buffer && !xtext->skip_fills) - { - if (xtext->do_underline_fills_only) - { - gdk_draw_rectangle (GTK_WIDGET (xtext)->window, xtext->bgc, 1, - x, y + 1, str_width, 1); - if (xtext->underline) /* optimization */ - goto dounder; - } else - { - gdk_draw_rectangle (GTK_WIDGET (xtext)->window, xtext->bgc, 1, - x, y - xtext->font->ascent, str_width, - xtext->fontsize); - } - } - } else - { - dofill = TRUE; - if (xtext->skip_fills && !xtext->backcolor) - dofill = FALSE; - } - -#ifdef USE_XLIB - - xgc = GDK_GC_XGC (gc); - xdraw_buf = GDK_WINDOW_XWINDOW (xtext->draw_buf); - xdisplay = GDK_WINDOW_XDISPLAY (GTK_WIDGET (xtext)->window); - xfont = GDK_FONT_XFONT (xtext->font); - - switch (xtext->fonttype) - { - case FONT_1BYTE: - if (dofill) - XDrawImageString (xdisplay, xdraw_buf, xgc, x, y, str, len); - else - XDrawString (xdisplay, xdraw_buf, xgc, x, y, str, len); - if (xtext->bold) - XDrawString (xdisplay, xdraw_buf, xgc, x + 1, y, str, len); - break; - - case FONT_2BYTE: - len /= 2; - if (dofill) - XDrawImageString16 (xdisplay, xdraw_buf, - xgc, x, y, (XChar2b *) str, len); - else - XDrawString16 (xdisplay, xdraw_buf, - xgc, x, y, (XChar2b *) str, len); - if (xtext->bold) - XDrawString16 (xdisplay, xdraw_buf, - xgc, x + 1, y, (XChar2b *) str, len); - break; - - case FONT_SET: - if (dofill) - XmbDrawImageString (xdisplay, xdraw_buf, - (XFontSet) xfont, xgc, x, y, str, len); - else - XmbDrawString (xdisplay, xdraw_buf, - (XFontSet) xfont, xgc, x, y, str, len); - if (xtext->bold) - XmbDrawString (xdisplay, xdraw_buf, - (XFontSet) xfont, xgc, x + 1, y, str, len); - } - -#else - - /* don't have Xlib, gdk version --- */ - if (dofill) - { - GdkGCValues val; - gdk_gc_get_values (gc, &val); - xtext_set_fg (gc, val.background.pixel); - gdk_draw_rectangle (xtext->draw_buf, gc, 1, - x, y - xtext->font->ascent, str_width, - xtext->fontsize); - xtext_set_fg (gc, val.foreground.pixel); - } - gdk_draw_text (xtext->draw_buf, xtext->font, gc, x, y, str, len); - if (xtext->bold) - gdk_draw_text (xtext->draw_buf, xtext->font, gc, x + 1, y, str, len); - -#endif - - if (xtext->underline) -dounder: - gdk_draw_line (xtext->draw_buf, gc, x, y+1, x+str_width-1, y+1); - - return str_width; -} - -static void -gtk_xtext_reset (GtkXText * xtext, int mark, int attribs) -{ - if (attribs) - { - xtext->underline = FALSE; - xtext->bold = FALSE; - } - if (!mark) - { - xtext->backcolor = FALSE; - if (xtext->col_fore != 18) - xtext_set_fg (xtext->fgc, xtext->palette[18]); - if (xtext->col_back != 19) - xtext_set_bg (xtext->fgc, xtext->palette[19]); - } - xtext->col_fore = 18; - xtext->col_back = 19; -} - -/* render a single line, which WONT wrap, and parse mIRC colors */ - -static void -gtk_xtext_render_str (GtkXText * xtext, int y, textentry * ent, char *str, - int len, int win_width, int indent, int line) -{ - GdkGC *gc; - int i = 0, x = indent, j = 0; - char *pstr = str; - int col_num, tmp; - int offset; - int mark = FALSE; - int hilight = FALSE; - - offset = str - ent->str; - - if (line < 255 && line >= 0) - xtext->grid_offset[line] = offset; - - gc = xtext->fgc; /* our foreground GC */ - - if (ent->mark_start != -1 && - ent->mark_start <= i + offset && ent->mark_end > i + offset) - { - xtext_set_bg (gc, xtext->palette[16]); - xtext_set_fg (gc, xtext->palette[17]); - xtext->backcolor = TRUE; - mark = TRUE; - } -#ifdef MOTION_MONITOR - if (xtext->hilight_ent == ent && - xtext->hilight_start <= i + offset && xtext->hilight_end > i + offset) - { - xtext->underline = TRUE; -/* xtext->bold = TRUE;*/ - hilight = TRUE; - } -#endif - - if (!xtext->double_buffer) - { - /* draw background to the left of the text */ - if (str == ent->str && indent && xtext->time_stamp) - { - /* don't overwrite the timestamp */ - if (indent > xtext->stamp_width) - { - if (!xtext->skip_border_fills) - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, - xtext->stamp_width, y - xtext->font->ascent, - indent - xtext->stamp_width, xtext->fontsize); - } - } else - { - /* fill the indent area with background gc */ - if (!xtext->skip_border_fills) - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, - 0, y - xtext->font->ascent, indent, xtext->fontsize); - } - } - - while (i < len) - { - -#ifdef MOTION_MONITOR - if (xtext->hilight_ent == ent && xtext->hilight_start == (i + offset)) - { - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j; - j = 0; - xtext->underline = TRUE; -/* xtext->bold = TRUE;*/ - hilight = TRUE; - } -#endif - - if (!mark && ent->mark_start == (i + offset)) - { - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j; - j = 0; - xtext_set_bg (gc, xtext->palette[16]); - xtext_set_fg (gc, xtext->palette[17]); - xtext->backcolor = TRUE; - mark = TRUE; - } - - if ((xtext->parsing_color && isdigit (str[i]) && xtext->nc < 2) || - (xtext->parsing_color && str[i] == ',' && xtext->nc < 3)) - { - pstr++; - if (str[i] == ',') - { - xtext->parsing_backcolor = TRUE; - if (xtext->nc) - { - xtext->num[xtext->nc] = 0; - xtext->nc = 0; - col_num = atoi (xtext->num) % 16; - xtext->col_fore = col_num; - if (!mark) - xtext_set_fg (gc, xtext->palette[col_num]); - } - } else - { - xtext->num[xtext->nc] = str[i]; - if (xtext->nc < 7) - xtext->nc++; - } - } else - { - if (xtext->parsing_color) - { - xtext->parsing_color = FALSE; - if (xtext->nc) - { - xtext->num[xtext->nc] = 0; - xtext->nc = 0; - col_num = atoi (xtext->num); - if (col_num == 99) /* mIRC lameness */ - col_num = 19; - else - col_num = col_num % 16; - if (xtext->parsing_backcolor) - { - if (col_num == 1) - xtext->backcolor = FALSE; - else - xtext->backcolor = TRUE; - if (!mark) - xtext_set_bg (gc, xtext->palette[col_num]); - xtext->col_back = col_num; - } else - { - if (!mark) - xtext_set_fg (gc, xtext->palette[col_num]); - xtext->col_fore = col_num; - } - xtext->parsing_backcolor = FALSE; - } else - { - /* got a \003... i.e. reset colors */ - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j; - j = 0; - gtk_xtext_reset (xtext, mark, FALSE); - } - } - - switch (str[i]) - { - case '\t': - str[i] = ' '; - j++; - break; - case '\n': - case ATTR_BEEP: - break; - case ATTR_REVERSE: - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j + 1; - j = 0; - tmp = xtext->col_fore; - xtext->col_fore = xtext->col_back; - xtext->col_back = tmp; - if (!mark) - { - xtext_set_fg (gc, xtext->palette[xtext->col_fore]); - xtext_set_bg (gc, xtext->palette[xtext->col_back]); - } - if (xtext->col_back != 19) - xtext->backcolor = TRUE; - else - xtext->backcolor = FALSE; - break; - case ATTR_BOLD: - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - xtext->bold = !xtext->bold; - pstr += j + 1; - j = 0; - break; - case ATTR_UNDERLINE: - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - xtext->underline = !xtext->underline; - pstr += j + 1; - j = 0; - break; - case ATTR_RESET: - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j + 1; - j = 0; - gtk_xtext_reset (xtext, mark, !hilight); - break; - case ATTR_COLOR: - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - xtext->parsing_color = TRUE; - pstr += j + 1; - j = 0; - break; - default: - j++; - } - } - i++; - -#ifdef MOTION_MONITOR - if (xtext->hilight_ent == ent && xtext->hilight_end == (i + offset)) - { - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j; - j = 0; - xtext->underline = FALSE; -/* xtext->bold = FALSE;*/ - hilight = FALSE; - } -#endif - - if (mark && ent->mark_end == (i + offset)) - { - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - pstr += j; - j = 0; - xtext_set_bg (gc, xtext->palette[xtext->col_back]); - xtext_set_fg (gc, xtext->palette[xtext->col_fore]); - if (xtext->col_back != 19) - xtext->backcolor = TRUE; - else - xtext->backcolor = FALSE; - mark = FALSE; - } - } - - if (j) - x += gtk_xtext_render_flush (xtext, x, y, pstr, j, gc); - - if (!xtext->double_buffer) - { - /* draw separator now so it doesn't appear to flicker */ - gtk_xtext_draw_sep (xtext, y + 1); - /* draw background to the right of the text */ - if (!xtext->skip_border_fills) - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, - x, y - xtext->font->ascent, (win_width + MARGIN) - x, - xtext->fontsize); - } -} - -#ifdef USE_XLIB - -/* get the desktop/root window - thanks Eterm */ - -static Window desktop_window = None; - -Window -get_desktop_window (Window the_window) -{ - Atom prop, type, prop2; - int format; - unsigned long length, after; - unsigned char *data; - unsigned int nchildren; - Window w, root, *children, parent; - - prop = XInternAtom (GDK_DISPLAY (), "_XROOTPMAP_ID", True); - prop2 = XInternAtom (GDK_DISPLAY (), "_XROOTCOLOR_PIXEL", True); - - if (prop == None && prop2 == None) - return None; - - for (w = the_window; w; w = parent) - { - if ((XQueryTree (GDK_DISPLAY (), w, &root, &parent, &children, - &nchildren)) == False) - return None; - - if (nchildren) - XFree (children); - - if (prop != None) - { - XGetWindowProperty (GDK_DISPLAY (), w, prop, 0L, 1L, False, - AnyPropertyType, &type, &format, &length, &after, - &data); - } else - { - XGetWindowProperty (GDK_DISPLAY (), w, prop2, 0L, 1L, False, - AnyPropertyType, &type, &format, &length, &after, - &data); - } - - if (data) - XFree (data); - - if (type != None) - { - return (desktop_window = w); - } - } - - return (desktop_window = None); -} - -/* stolen from zvt, which was stolen from Eterm */ - -static Pixmap -get_pixmap_prop (Window the_window) -{ - Atom prop, type; - int format; - unsigned long length, after; - unsigned char *data; - Pixmap pix = None; - - if (desktop_window == None) - desktop_window = get_desktop_window (the_window); - if (desktop_window == None) - desktop_window = GDK_ROOT_WINDOW (); - - prop = XInternAtom (GDK_DISPLAY (), "_XROOTPMAP_ID", True); - if (prop == None) - return None; - - XGetWindowProperty (GDK_DISPLAY (), desktop_window, prop, 0L, 1L, False, - AnyPropertyType, &type, &format, &length, &after, - &data); - if (data) - { - if (type == XA_PIXMAP) - pix = *((Pixmap *) data); - - XFree (data); - } - - return pix; -} - -#ifdef USE_GDK_PIXBUF - -static GdkPixmap * -create_shaded_pixmap (GtkXText * xtext, Pixmap p, int x, int y, int w, int h) -{ - GdkPixmap *pp, *tmp, *shaded_pixmap; - GdkPixbuf *pixbuf; - GdkColormap *cmap; - GdkGC *tgc; - unsigned char *buf; - unsigned char *pbuf; - int width, height, depth; - int rowstride; - int pbwidth; - int pbheight; - int i, j; - int offset; - int r, g, b, a; - - pp = gdk_pixmap_foreign_new (p); - cmap = gtk_widget_get_colormap (GTK_WIDGET (xtext)); - gdk_window_get_geometry (pp, NULL, NULL, &width, &height, &depth); - - if (width < x + w || height < y + h || x < 0 || y < 0) - { - tgc = gdk_gc_new (pp); - tmp = gdk_pixmap_new (pp, w, h, depth); - gdk_gc_set_tile (tgc, pp); - gdk_gc_set_fill (tgc, GDK_TILED); - gdk_gc_set_ts_origin (tgc, -x, -y); - gdk_draw_rectangle (tmp, tgc, TRUE, 0, 0, w, h); - gdk_gc_destroy (tgc); - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, tmp, cmap, - 0, 0, 0, 0, w, h); - gdk_pixmap_unref (tmp); - } else - { - pixbuf = gdk_pixbuf_get_from_drawable (NULL, pp, cmap, - x, y, 0, 0, w, h); - } - gdk_xid_table_remove (GDK_WINDOW_XWINDOW (pp)); - g_dataset_destroy (pp); - g_free (pp); - - if (!pixbuf) - return NULL; - - buf = gdk_pixbuf_get_pixels (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - pbwidth = gdk_pixbuf_get_width (pixbuf); - pbheight = gdk_pixbuf_get_height (pixbuf); - - a = 128; /* alpha */ - r = xtext->tint_red; - g = xtext->tint_green; - b = xtext->tint_blue; - - if (gdk_pixbuf_get_has_alpha (pixbuf)) - offset = 4; - else - offset = 3; - - for (i=0;i> 8); - pbuf[1] = ((pbuf[1] * g) >> 8); - pbuf[2] = ((pbuf[2] * b) >> 8); - pbuf+=offset; - } - buf+=rowstride; - } - - gdk_pixbuf_render_pixmap_and_mask (pixbuf, &shaded_pixmap, NULL, 0); - gdk_pixbuf_unref (pixbuf); - - return shaded_pixmap; -} - -#endif - -/* free transparency xtext->pixmap */ - -static void -gtk_xtext_free_trans (GtkXText * xtext) -{ - if (xtext->pixmap) - { - if (xtext->shaded) - { - gdk_pixmap_unref (xtext->pixmap); - } else - { - gdk_xid_table_remove (GDK_WINDOW_XWINDOW (xtext->pixmap)); - g_dataset_destroy (xtext->pixmap); - g_free (xtext->pixmap); - } - xtext->pixmap = NULL; - } -} - -/* grab pixmap from root window and set xtext->pixmap */ - -static void -gtk_xtext_load_trans (GtkXText * xtext) -{ - Pixmap rootpix; - Window childret; - GtkWidget *widget = GTK_WIDGET (xtext); - int x, y; - - rootpix = get_pixmap_prop (GDK_WINDOW_XWINDOW (widget->window)); - if (rootpix == None) - { - if (xtext->error_function) - xtext->error_function ("Unable to get root window pixmap!\n\n" - "You may need to use Esetroot or Gnome\n" - "control-center to set your background.\n"); - xtext->transparent = FALSE; - return; - } - - XTranslateCoordinates (GDK_WINDOW_XDISPLAY (widget->window), - GDK_WINDOW_XWINDOW (widget->window), - GDK_ROOT_WINDOW (), 0, 0, &x, &y, &childret); - -#ifdef USE_GDK_PIXBUF - if (xtext->shaded) - { - int width, height; - gdk_window_get_size (GTK_WIDGET (xtext)->window, &width, &height); - xtext->pixmap = - create_shaded_pixmap (xtext, rootpix, x, y, width, height); - gdk_gc_set_tile (xtext->bgc, xtext->pixmap); - gdk_gc_set_ts_origin (xtext->bgc, 0, 0); - } else - { -#endif - xtext->pixmap = gdk_pixmap_foreign_new (rootpix); - gdk_gc_set_tile (xtext->bgc, xtext->pixmap); - gdk_gc_set_ts_origin (xtext->bgc, -x, -y); -#ifdef USE_GDK_PIXBUF - } -#endif - gdk_gc_set_fill (xtext->bgc, GDK_TILED); -} - -#endif - -/* render a single line, which may wrap to more lines */ - -static int -gtk_xtext_render_line (GtkXText * xtext, textentry * ent, char *str, int len, - int line, int lines_max, int subline, int indent, - int str_width) -{ - char *time_str; - int y; - int width; - int orig_len; - int ret = 1; - int tmp; - - if (!str) - return 0; - - if (len == -1) - len = strlen (str); - orig_len = len; - - gdk_window_get_size (GTK_WIDGET (xtext)->window, &width, 0); - width -= MARGIN; - - if (xtext->time_stamp) - { - time_str = ctime (&ent->stamp) + 10; - time_str[0] = '['; - time_str[9] = ']'; - time_str[10] = 0; - y = (xtext->fontsize * line) + xtext->font->ascent; - gtk_xtext_render_str (xtext, y, ent, time_str, 10, width, 2, line); - } - - startrl: - - y = (xtext->fontsize * line) + xtext->font->ascent; - - if (str_width == -1) - str_width = gtk_xtext_text_width (xtext, str, len); - - str_width += indent; - - tmp = 0; - while (str_width > width || (!is_del (str[len]) && xtext->wordwrap)) - { - if (str_width <= width && !tmp) - tmp = len; - len--; - if (xtext->wordwrap && tmp - len > WORDWRAP_LIMIT) - { - len = tmp; - str_width = gtk_xtext_text_width (xtext, str, len) + indent; - break; - } - if (len == 0) - return 1; - - /* this is quite a HACK but it speeds things up! */ - if (str_width > width + 256) - len -= 10; - /* -- */ - - str_width = gtk_xtext_text_width (xtext, str, len) + indent; - } - - if (!subline) - { - gtk_xtext_render_str (xtext, y, ent, str, len, width, indent, line); - } else - { - xtext->dont_render = TRUE; - gtk_xtext_render_str (xtext, y, ent, str, len, width, indent, line); - xtext->dont_render = FALSE; - subline--; - line--; - ret--; - } - - if (xtext->wordwrap && str[len] == ' ') - len++; - - if (len != orig_len && lines_max > line + 1) - { /* FIXME: recursion sux! */ -/* ret += gtk_xtext_render_line (xtext, ent, str + len, -1, line+1, lines_max, subline, xtext->indent, -1);*/ - ret++; - str += len; - len = orig_len = strlen (str); - line++; - indent = xtext->indent; - str_width = -1; - /* FIXME: gotos suck! */ - goto startrl; - } - - return ret; -} - -void -gtk_xtext_set_palette (GtkXText * xtext, GdkColor palette[]) -{ - int i; - - for (i = 0; i < 20; i++) - xtext->palette[i] = palette[i].pixel; - - if (GTK_WIDGET_REALIZED (xtext)) - { - xtext_set_fg (xtext->fgc, xtext->palette[18]); - xtext_set_bg (xtext->fgc, xtext->palette[19]); - xtext_set_fg (xtext->bgc, xtext->palette[19]); - } - xtext->col_fore = 18; - xtext->col_back = 19; -} - -static void -gtk_xtext_fix_indent (GtkXText * xtext) -{ - int j; - - if (xtext->indent) /* make indent a multiple of the space width */ - { - j = 0; - while (j < xtext->indent) - { - j += xtext->space_width; - } - xtext->indent = j; - } -} - -static void -gtk_xtext_recalc_widths (GtkXText * xtext, int do_str_width) -{ - textentry *ent; - - /* since we have a new font, we have to recalc the text widths */ - ent = xtext->text_first; - while (ent) - { - if (do_str_width) - { - ent->str_width = - gtk_xtext_text_width (xtext, ent->str, ent->str_len); - } - if (ent->left_len != -1) - { - ent->indent = - (xtext->indent - - gtk_xtext_text_width (xtext, ent->str, - ent->left_len)) - xtext->space_width; - if (ent->indent < MARGIN) - ent->indent = MARGIN; - } - ent = ent->next; - } - - gtk_xtext_calc_lines (xtext, FALSE); -} - -void -gtk_xtext_set_font (GtkXText * xtext, GdkFont * font, char *name) -{ -#ifdef USE_XLIB - unsigned char i; - XFontStruct *xfont; -#endif - - if (xtext->font) - gdk_font_unref (xtext->font); - - if (font) - { - xtext->font = font; - gdk_font_ref (font); - } else - font = xtext->font = gdk_font_load (name); - - if (!font) - font = xtext->font = gdk_font_load ("fixed"); - - switch (font->type) - { - case GDK_FONT_FONT: - xtext->fontsize = font->ascent + font->descent; -#ifdef USE_XLIB - xfont = GDK_FONT_XFONT (font); - if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0)) - { - xtext->fonttype = FONT_1BYTE; - for (i = 0; i < 255; i++) - { - xtext->fontwidth[i] = gdk_char_width (font, i); - } - xtext->space_width = xtext->fontwidth[' ']; - } else - { -#endif - /* without X11 pretend they are all 2BYTE- This is ok, just - a bit slower. */ - xtext->fonttype = FONT_2BYTE; - xtext->space_width = gdk_char_width (font, ' '); -#ifdef USE_XLIB - } -#endif - break; - - case GDK_FONT_FONTSET: - xtext->fontsize = gdk_text_height (font, " ", 1); - xtext->fonttype = FONT_SET; - xtext->space_width = gdk_char_width (font, ' '); - break; - } - -#ifdef USE_XLIB - xfont = GDK_FONT_XFONT (font); - /* check if it's a fixed width font */ - if (xfont->min_bounds.width == xfont->max_bounds.width) - xtext->fixed_width_font = TRUE; - else - xtext->fixed_width_font = FALSE; -#else - /* kudgy fixed-width font checking */ - if (xtext->space_width == gdk_char_width (xtext->font, 'Z')) - xtext->fixed_width_font = TRUE; - else - xtext->fixed_width_font = FALSE; -#endif - - xtext->stamp_width = - gtk_xtext_text_width (xtext, "[88:88:88]", 10) + MARGIN; - - gtk_xtext_fix_indent (xtext); - - if (GTK_WIDGET_REALIZED (xtext)) - { - if (xtext->fonttype != FONT_SET) - gdk_gc_set_font (xtext->fgc, xtext->font); - - gtk_xtext_recalc_widths (xtext, TRUE); - } -} - -void -gtk_xtext_set_background (GtkXText * xtext, GdkPixmap * pixmap, int trans, - int shaded) -{ - GdkGCValues val; - -#ifndef USE_GDK_PIXBUF - shaded = FALSE; -#endif - -#ifndef USE_XLIB - shaded = FALSE; - trans = FALSE; -#endif - - if (xtext->pixmap) - { -#ifdef USE_XLIB - if (xtext->transparent) - gtk_xtext_free_trans (xtext); - else -#endif - gdk_pixmap_unref (xtext->pixmap); - xtext->pixmap = NULL; - } - - xtext->transparent = trans; - -#ifdef USE_XLIB - if (trans) - { - xtext->shaded = shaded; - if (GTK_WIDGET_REALIZED (xtext)) - gtk_xtext_load_trans (xtext); - return; - } -#endif - - xtext->pixmap = pixmap; - - if (pixmap != 0) - { - gdk_pixmap_ref (pixmap); - if (GTK_WIDGET_REALIZED (xtext)) - { - gdk_gc_set_tile (xtext->bgc, pixmap); - gdk_gc_set_ts_origin (xtext->bgc, 0, 0); - gdk_gc_set_fill (xtext->bgc, GDK_TILED); - } - } else - { - if (GTK_WIDGET_REALIZED (xtext)) - { - gdk_gc_destroy (xtext->bgc); - val.subwindow_mode = GDK_INCLUDE_INFERIORS; - val.graphics_exposures = 0; - xtext->bgc = gdk_gc_new_with_values (GTK_WIDGET (xtext)->window, - &val, GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW); - xtext_set_fg (xtext->bgc, xtext->palette[19]); - } - } -} - -gchar * -gtk_xtext_get_chars (GtkXText * xtext) -{ - int lenght = 0; - gchar *chars; - textentry *tentry = xtext->text_first; - while (tentry != NULL) - { - lenght += tentry->str_len + 1; - tentry = tentry->next; - } - if (lenght == 0) - return NULL; - chars = g_malloc (lenght + 1); - *chars = 0; - - tentry = xtext->text_first; - while (tentry != NULL) - { - strcat (chars, tentry->str); - strcat (chars, "\n"); - tentry = tentry->next; - } - - return chars; -} - -static int -gtk_xtext_lines_taken (GtkXText * xtext, textentry * ent) -{ - int tmp, orig_len, indent, len, win_width, str_width, lines = 0; - char *str; - - str = ent->str; - len = orig_len = ent->str_len; - indent = ent->indent; - - if (len < 2) - return 1; - - win_width = GTK_WIDGET (xtext)->allocation.width - MARGIN; - str_width = ent->str_width + indent; - - while (1) - { - lines++; - if (str_width <= win_width) - break; - tmp = 0; - while (str_width > win_width || (!is_del (str[len]) && xtext->wordwrap)) - { - if (str_width <= win_width && !tmp) - tmp = len; - len--; - if (xtext->wordwrap && tmp - len > WORDWRAP_LIMIT) - { - len = tmp; - str_width = gtk_xtext_text_width (xtext, str, len) + indent; - break; - } - if (len == 0) - return 1; - if (str_width > win_width + 256) /* this might not work 100% but it */ - len -= 10; /* sure speeds things up ALOT! */ - str_width = gtk_xtext_text_width (xtext, str, len) + indent; - } - - if (len == orig_len) - break; - - if (xtext->wordwrap && str[len] == ' ') - len++; - - str += len; - indent = xtext->indent; - len = strlen (str); - str_width = gtk_xtext_text_width (xtext, str, len) + indent; - } - return lines; -} - -/* Calculate number of actual lines (with wraps), to set adj->lower. * - * This should only be called when the window resizes. */ - -static void -gtk_xtext_calc_lines (GtkXText * xtext, int fire_signal) -{ - textentry *ent; - int width; - int height; - int lines; - - width = GTK_WIDGET (xtext)->allocation.width - MARGIN; - height = GTK_WIDGET (xtext)->allocation.height; - - if (width < 30 || height < xtext->fontsize || width < xtext->indent + 30) - return; - - lines = 0; - ent = xtext->text_first; - while (ent) - { - ent->lines_taken = gtk_xtext_lines_taken (xtext, ent); - lines += ent->lines_taken; - ent = ent->next; - } - - xtext->pagetop_ent = NULL; - xtext->num_lines = lines; - gtk_xtext_adjustment_set (xtext, fire_signal); -} - -/* find the n-th line in the linked list, this includes wrap calculations */ - -static textentry * -gtk_xtext_nth (GtkXText * xtext, textentry * ent, int line, int width, - int *subline) -{ - int lines = 0; - - if (ent == NULL) - { - ent = xtext->text_first; - line += xtext->adj->value; - } else - { - lines -= *subline; - } - - while (ent) - { - lines += ent->lines_taken; - if (lines > line) - { - *subline = ent->lines_taken - (lines - line); - return ent; - } - ent = ent->next; - } - return 0; -} - -static void -gtk_xtext_draw_sep (GtkXText * xtext, int y) -{ - int x, height; - GdkGC *light, *dark; - - if (y == -1) - { - y = 2; - height = GTK_WIDGET (xtext)->allocation.height - 2; - } else - { - height = xtext->fontsize; - } - - /* draw the separator line */ - if (xtext->separator && xtext->indent) - { - light = xtext->light_gc; - dark = xtext->dark_gc; - - x = xtext->indent - ((xtext->space_width + 1) / 2); - if (x < 1) - return; - - if (xtext->thinline) - { - if (xtext->moving_separator) - gdk_draw_line (xtext->draw_buf, light, x, y, x, height); - else - gdk_draw_line (xtext->draw_buf, dark, x, y, x, height); - } else - { - if (xtext->moving_separator) - { - gdk_draw_line (xtext->draw_buf, light, x - 1, y, x - 1, height); - gdk_draw_line (xtext->draw_buf, dark, x, y, x, height); - } else - { - gdk_draw_line (xtext->draw_buf, dark, x - 1, y, x - 1, height); - gdk_draw_line (xtext->draw_buf, light, x, y, x, height); - } - } - } -} - -/* render 2 ents (or an inclusive range) */ - -static void -gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb, - int inclusive) -{ - textentry *ent, *orig_ent, *tmp_ent; - int line; - int lines_taken; - int lines_max; - int width; - int height; - int subline; - int drawing = FALSE; - - if (xtext->double_buffer) - { - gtk_xtext_render_page (xtext); - return; - } - - if (xtext->indent < MARGIN) - xtext->indent = MARGIN; /* 2 pixels is our left margin */ - - gdk_window_get_size (GTK_WIDGET (xtext)->window, &width, &height); - width -= MARGIN; - - if (width < 32 || height < xtext->fontsize || width < xtext->indent + 30) - return; - - lines_max = (height - xtext->font->descent) / xtext->fontsize; - line = 0; - orig_ent = xtext->pagetop_ent; - subline = xtext->pagetop_subline; - - /* check if enta is before the start of this page */ - if (inclusive) - { - tmp_ent = orig_ent; - while (tmp_ent) - { - if (tmp_ent == enta) - break; - if (tmp_ent == entb) - { - drawing = TRUE; - break; - } - tmp_ent = tmp_ent->next; - } - } - - line = 0; - - ent = orig_ent; - while (ent) - { - if (inclusive && ent == enta) - drawing = TRUE; - - if (drawing || ent == entb || ent == enta) - { - gtk_xtext_reset (xtext, FALSE, TRUE); - lines_taken = gtk_xtext_render_line (xtext, ent, ent->str, - ent->str_len, line, lines_max, - subline, ent->indent, - ent->str_width); - line += ent->lines_taken; - line -= subline; - if (ent == orig_ent) - subline = 0; - } else - { - if (ent == orig_ent) - { - line -= subline; - subline = 0; - } - line += ent->lines_taken; - } - - if (inclusive && ent == entb) - break; - - if (line >= lines_max) - break; - - ent = ent->next; - } - - /* draw the separator line */ - gtk_xtext_draw_sep (xtext, -1); -} - -/* render a whole page/window, starting from 'startline' */ - -static void -gtk_xtext_render_page (GtkXText * xtext) -{ - textentry *ent; - int line; - int lines_max; - int width; - int height; - int subline; - int startline = xtext->adj->value; - - if (xtext->indent < MARGIN) - xtext->indent = MARGIN; /* 2 pixels is our left margin */ - - gdk_window_get_size (GTK_WIDGET (xtext)->window, &width, &height); - width -= MARGIN; - - if (width < 32 || height < xtext->fontsize || width < xtext->indent + 30) - return; - - lines_max = (height - xtext->font->descent) / xtext->fontsize; - - subline = line = 0; - ent = xtext->text_first; - - if (startline > 0) - ent = gtk_xtext_nth (xtext, ent, startline, width, &subline); - - xtext->pagetop_ent = ent; - xtext->pagetop_subline = subline; - - if (xtext->double_buffer) - { - xtext->tmp_pix = gdk_pixmap_new (((GtkWidget*)xtext)->window, - width + MARGIN, height, xtext->depth); - xtext->draw_buf = xtext->tmp_pix; - /* render the backdrop */ - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, 0, 0, - width + MARGIN, height); - } - - while (ent) - { - gtk_xtext_reset (xtext, FALSE, TRUE); - line += - gtk_xtext_render_line (xtext, ent, ent->str, ent->str_len, line, - lines_max, subline, ent->indent, - ent->str_width); - subline = 0; - - if (line >= lines_max) - break; - - ent = ent->next; - } - - if (!xtext->double_buffer) - { - line = (xtext->fontsize * line); - /* fill any space below the last line with our background GC */ - gdk_draw_rectangle (xtext->draw_buf, xtext->bgc, 1, - 0, line, width + MARGIN, height - line); - } - - /* draw the separator line */ - gtk_xtext_draw_sep (xtext, -1); - - if (xtext->double_buffer) - { - /* send our double buffer to the actual window */ - gdk_draw_pixmap (((GtkWidget*)xtext)->window, xtext->fgc, xtext->tmp_pix, - 0, 0, 0, 0, width + MARGIN, height); - gdk_pixmap_unref (xtext->tmp_pix); - } -} - -void -gtk_xtext_refresh (GtkXText * xtext, int do_trans) -{ - if (GTK_WIDGET_REALIZED (GTK_WIDGET (xtext))) - { -#ifdef USE_XLIB - if (xtext->transparent && do_trans) - { - gtk_xtext_free_trans (xtext); - gtk_xtext_load_trans (xtext); - } -#endif - gtk_xtext_render_page (xtext); - } -} - -/* remove the topline from the list */ - -static void -gtk_xtext_remove_top (GtkXText * xtext) -{ - textentry *ent; - - ent = xtext->text_first; - xtext->num_lines -= ent->lines_taken; - xtext->pagetop_ent = NULL; - xtext->text_first = ent->next; - free (ent); -} - -void -gtk_xtext_remove_lines (GtkXText * xtext, int lines, int refresh) -{ - textentry *next; - - while (xtext->text_first && lines) - { - next = xtext->text_first->next; - free (xtext->text_first); - xtext->text_first = next; - lines--; - } - if (!xtext->text_first) - xtext->text_last = NULL; - - if (refresh) - { - gtk_xtext_calc_lines (xtext, TRUE); - gtk_xtext_refresh (xtext, 0); - } -} - -void * -gtk_xtext_search (GtkXText * xtext, char *text, void *start) -{ - textentry *ent, *fent; - char *str; - int line; - - gtk_xtext_selection_clear (xtext); - - if (start) - ent = ((textentry *) start)->next; - else - ent = xtext->text_first; - while (ent) - { - if ((str = nocasestrstr (ent->str, text))) - { - ent->mark_start = str - ent->str; - ent->mark_end = ent->mark_start + strlen (text); - break; - } - ent = ent->next; - } - - fent = ent; - ent = xtext->text_first; - line = 0; - while (ent) - { - line += ent->lines_taken; - ent = ent->next; - if (ent == fent) - break; - } - while (line > xtext->adj->upper - xtext->adj->page_size) - line--; - - if (fent != 0) - { - xtext->adj->value = line; - xtext->scrollbar_down = FALSE; - gtk_adjustment_changed (xtext->adj); - } - gtk_xtext_render_page (xtext); - - return fent; -} - -static int -gtk_xtext_render_page_timeout (GtkXText * xtext) -{ - GtkAdjustment *adj = xtext->adj; - gfloat val; - - if (xtext->scrollbar_down) - { - gtk_xtext_adjustment_set (xtext, FALSE); - gtk_adjustment_set_value (adj, adj->upper - adj->page_size); - } else - { - val = adj->value; - gtk_xtext_adjustment_set (xtext, TRUE); - gtk_adjustment_set_value (adj, val); - } - - if (adj->value >= adj->upper - adj->page_size || adj->value < 1) - gtk_xtext_render_page (xtext); - - xtext->add_io_tag = -1; - - return 0; -} - -/* append a textentry to our linked list */ - -static void -gtk_xtext_append_entry (GtkXText * xtext, textentry * ent) -{ - ent->stamp = time (0); - ent->str_width = gtk_xtext_text_width (xtext, ent->str, ent->str_len); - ent->mark_start = -1; - ent->mark_end = -1; - ent->next = NULL; - - if (ent->indent < MARGIN) - ent->indent = MARGIN; /* 2 pixels is the left margin */ - - /* append to our linked list */ - if (xtext->text_last) - xtext->text_last->next = ent; - else - xtext->text_first = ent; - xtext->text_last = ent; - - ent->lines_taken = gtk_xtext_lines_taken (xtext, ent); - xtext->num_lines += ent->lines_taken; - - if (xtext->max_lines > 2 && xtext->max_lines < xtext->num_lines) - { - gtk_xtext_remove_top (xtext); - } - -/* if (xtext->frozen == 0 && xtext->add_io_tag == -1)*/ - if (xtext->add_io_tag == -1) - { - xtext->add_io_tag = gtk_timeout_add (REFRESH_TIMEOUT * 2, - (GtkFunction) - gtk_xtext_render_page_timeout, - xtext); - } -} - -/* the main two public functions */ - -void -gtk_xtext_append_indent (GtkXText * xtext, - char *left_text, int left_len, - char *right_text, int right_len) -{ - textentry *ent; - char *str; - int space; - - if (left_len == -1) - left_len = strlen (left_text); - - if (right_len == -1) - right_len = strlen (right_text); - - ent = malloc (left_len + right_len + 2 + sizeof (textentry)); - str = (char *) ent + sizeof (textentry); - - space = xtext->indent - gtk_xtext_text_width (xtext, left_text, left_len); - - memcpy (str, left_text, left_len); - str[left_len] = ' '; - memcpy (str + left_len + 1, right_text, right_len); - str[left_len + 1 + right_len] = 0; - - ent->left_len = left_len; - ent->str = str; - ent->str_len = left_len + 1 + right_len; - ent->indent = space - xtext->space_width; - - if (xtext->time_stamp) - space = xtext->stamp_width; - else - space = 0; - - /* do we need to auto adjust the separator position? */ - if (xtext->auto_indent && ent->indent < MARGIN + space) - { - xtext->indent -= ent->indent; - xtext->indent += MARGIN; - xtext->indent += space; - if (xtext->indent > xtext->max_auto_indent) - xtext->indent = xtext->max_auto_indent; - gtk_xtext_fix_indent (xtext); - gtk_xtext_recalc_widths (xtext, FALSE); - space = - xtext->indent - gtk_xtext_text_width (xtext, left_text, left_len); - ent->indent = space - xtext->space_width; - } - - gtk_xtext_append_entry (xtext, ent); -} - -void -gtk_xtext_append (GtkXText * xtext, char *text, int len) -{ - textentry *ent; - - if (len == -1) - len = strlen (text); - - ent = malloc (len + 1 + sizeof (textentry)); - ent->str = (char *) ent + sizeof (textentry); - ent->str_len = len; - if (len) - memcpy (ent->str, text, len); - ent->str[len] = 0; - ent->indent = 0; - ent->left_len = -1; - - gtk_xtext_append_entry (xtext, ent); -}