Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / nvi / gtk / gtkviscreen.c
blobfabc719faafde16e36fa5e33f4025334b62d4757
1 /* $NetBSD$ */
3 #include <stdio.h>
4 #include <string.h>
6 #include <gtk/gtkmain.h>
7 #include <gtk/gtksignal.h>
8 #include "gtkviscreen.h"
9 #include <gdk/gdkx.h>
11 #define INTISUCS(c) ((c & ~0x7F) && !(((c) >> 16) & 0x7F))
12 #define INTUCS(c) (c)
13 #ifdef USE_WIDECHAR
14 #define CHAR_WIDTH(sp, ch) wcwidth(ch)
15 #else
16 #define CHAR_WIDTH(sp, ch) 1
17 #endif
19 void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n));
21 #define DEFAULT_VI_SCREEN_WIDTH_CHARS 80
22 #define DEFAULT_VI_SCREEN_HEIGHT_LINES 25
23 #define VI_SCREEN_BORDER_ROOM 1
25 enum {
26 ARG_0,
27 ARG_VADJUSTMENT,
30 enum {
31 RESIZED,
32 LAST_SIGNAL
35 static void gtk_vi_screen_class_init (GtkViScreenClass *klass);
36 static void gtk_vi_screen_set_arg (GtkObject *object,
37 GtkArg *arg,
38 guint arg_id);
39 static void gtk_vi_screen_get_arg (GtkObject *object,
40 GtkArg *arg,
41 guint arg_id);
42 static void gtk_vi_screen_init (GtkViScreen *vi);
43 static void gtk_vi_screen_destroy (GtkObject *object);
44 static void gtk_vi_screen_realize (GtkWidget *widget);
46 static void gtk_vi_screen_map (GtkWidget *widget);
47 static void gtk_vi_screen_unmap (GtkWidget *widget);
49 static void gtk_vi_screen_size_request (GtkWidget *widget,
50 GtkRequisition *requisition);
51 static void gtk_vi_screen_size_allocate (GtkWidget *widget,
52 GtkAllocation *allocation);
54 static void gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
55 GtkViScreen *text);
58 static gint gtk_vi_screen_expose (GtkWidget *widget,
59 GdkEventExpose *event);
61 static void recompute_geometry (GtkViScreen* vi);
62 static void expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor);
63 static void draw_lines(GtkViScreen *vi, gint y, gint x, gint ymax, gint xmax);
64 static void mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax);
66 static GtkWidgetClass *parent_class = NULL;
67 static guint vi_screen_signals[LAST_SIGNAL] = { 0 };
69 static GdkFont *gb_font;
70 static GdkFont *tfn;
71 static GdkFont *tfw;
73 #define CharAt(scr,y,x) scr->chars + (y) * scr->cols + x
74 #define FlagAt(scr,y,x) (scr->reverse + (y) * scr->cols + x)
75 #define ColAt(scr,y,x) (scr->endcol + (y) * scr->cols + x)
77 #define COLOR_STANDARD 0x00
78 #define COLOR_STANDOUT 0x01
80 /* XXX */
81 enum { SA_ALTERNATE, SA_INVERSE };
83 void
84 gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on)
86 switch (attribute) {
87 case SA_INVERSE:
88 vi->color = on ? COLOR_STANDOUT : COLOR_STANDARD;
89 break;
93 /* col is screen column */
94 void
95 gtk_vi_screen_move(GtkViScreen *vi, gint row, gint col)
97 gint x;
98 guchar *endcol;
100 endcol = vi->endcol + row*vi->cols;
101 for (x = 0; col > endcol[x]; ++x);
102 vi->curx = x;
103 vi->cury = row;
106 static void
107 cleartoel (GtkViScreen *vi, guint row, guint col)
109 CHAR_T *p, *e;
111 if (MEMCMP(p = CharAt(vi,row,col), e = CharAt(vi,vi->rows,0),
112 vi->cols - col)) {
113 MEMMOVE(p, e, vi->cols - col);
114 memset(FlagAt(vi,row,col), COLOR_STANDARD, vi->cols - col);
115 mark_lines(vi, row, col, row+1, vi->cols);
119 void
120 gtk_vi_screen_clrtoel (GtkViScreen *vi)
122 cleartoel(vi, vi->cury, vi->curx);
125 void
126 gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len)
128 CHAR_T *p, *end;
129 CHAR_T *line;
130 guchar *endcol;
131 gint col, startcol;
132 gint x;
134 line = vi->chars + vi->cury*vi->cols;
135 endcol = vi->endcol + vi->cury*vi->cols;
136 x = vi->curx;
137 startcol = x ? endcol[x-1] : -1;
138 for (p = CharAt(vi,vi->cury,vi->curx), end = p + len, col = startcol;
139 p < end; ++x) {
140 *p++ = *str++;
141 endcol[x] = ++col;
143 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
145 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
147 if (endcol[x-1] >= vi->cols) {
148 if (++vi->cury >= vi->rows) {
149 vi->cury = vi->rows-1;
150 vi->curx = x-1;
151 } else {
152 vi->curx = 0;
154 } else vi->curx += len;
155 if (x < vi->cols) endcol[x] = vi->cols;
158 void
159 gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len)
161 CHAR_T *p, *end;
162 CHAR_T *line;
163 guchar *endcol;
164 gint col, startcol;
165 gint x;
167 MEMMOVE(CharAt(vi,vi->cury,vi->curx),str,len);
168 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
170 line = vi->chars + vi->cury*vi->cols;
171 endcol = vi->endcol + vi->cury*vi->cols;
172 x = vi->curx;
173 startcol = x ? endcol[x-1] : -1;
174 for (col = startcol; x < vi->curx + len; ++x)
175 endcol[x] = col += CHAR_WIDTH(NULL, *(line+x));
177 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
179 if (endcol[x-1] >= vi->cols) {
180 if (++vi->cury >= vi->rows) {
181 vi->cury = vi->rows-1;
182 vi->curx = x-1;
183 } else {
184 vi->curx = 0;
186 } else vi->curx += len;
187 if (x < vi->cols) endcol[x] = vi->cols;
190 void
191 gtk_vi_screen_deleteln(GtkViScreen *vi)
193 gint y = vi->cury;
194 gint rows = vi->rows - (y+1);
196 MEMMOVE(CharAt(vi,y,0), CharAt(vi,y+1,0), rows * vi->cols);
197 cleartoel(vi,vi->rows-1,0);
198 memmove(FlagAt(vi,y,0), FlagAt(vi,y+1,0), rows * vi->cols);
199 memmove(ColAt(vi,y,0), ColAt(vi,y+1,0), rows * vi->cols);
200 mark_lines(vi, y, 0, vi->rows-1, vi->cols);
203 void
204 gtk_vi_screen_insertln(GtkViScreen *vi)
206 gint y = vi->cury;
207 gint rows = vi->rows - (y+1);
209 MEMMOVE(CharAt(vi,y+1,0), CharAt(vi,y,0), rows * vi->cols);
210 cleartoel(vi,y,0);
211 memmove(FlagAt(vi,y+1,0), FlagAt(vi,y,0), rows * vi->cols);
212 memmove(ColAt(vi,y+1,0), ColAt(vi,y,0), rows * vi->cols);
213 mark_lines(vi, y+1, 0, vi->rows, vi->cols);
216 void
217 gtk_vi_screen_refresh(GtkViScreen *vi)
219 if (vi->lastx != vi->curx || vi->lasty != vi-> cury) {
220 mark_lines(vi, vi->lasty,
221 vi->lastx ? *ColAt(vi,vi->lasty,vi->lastx-1) + 1 : 0,
222 vi->lasty+1, *ColAt(vi,vi->lasty,vi->lastx)+1);
223 mark_lines(vi, vi->cury,
224 vi->curx ? *ColAt(vi,vi->cury,vi->curx-1) + 1 : 0,
225 vi->cury+1, *ColAt(vi,vi->cury,vi->curx)+1);
227 if (vi->marked_maxy == 0)
228 return;
229 draw_lines(vi, vi->marked_y, vi->marked_x, vi->marked_maxy, vi->marked_maxx);
230 vi->marked_x = vi->cols;
231 vi->marked_y = vi->rows;
232 vi->marked_maxx = 0;
233 vi->marked_maxy = 0;
234 vi->lastx = vi->curx;
235 vi->lasty = vi->cury;
238 void
239 gtk_vi_screen_rewrite(GtkViScreen *vi, gint row)
241 memset(FlagAt(vi,row,0), COLOR_STANDARD, vi->cols);
242 mark_lines(vi, row, 0, row+1, vi->cols);
245 GtkType
246 gtk_vi_screen_get_type (void)
248 static GtkType vi_screen_type = 0;
250 if (!vi_screen_type)
252 static const GtkTypeInfo vi_screen_info =
254 "GtkViScreen",
255 sizeof (GtkViScreen),
256 sizeof (GtkViScreenClass),
257 (GtkClassInitFunc) gtk_vi_screen_class_init,
258 (GtkObjectInitFunc) gtk_vi_screen_init,
259 /* reserved_1 */ NULL,
260 /* reserved_2 */ NULL,
261 (GtkClassInitFunc) NULL,
264 vi_screen_type = gtk_type_unique (GTK_TYPE_WIDGET, &vi_screen_info);
267 return vi_screen_type;
270 static void
271 gtk_vi_screen_class_init (GtkViScreenClass *class)
273 GtkObjectClass *object_class;
274 GtkWidgetClass *widget_class;
276 object_class = (GtkObjectClass*) class;
277 widget_class = (GtkWidgetClass*) class;
278 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
280 vi_screen_signals[RESIZED] =
281 gtk_signal_new ("resized",
282 GTK_RUN_FIRST,
283 GTK_CLASS_TYPE(object_class),
284 GTK_SIGNAL_OFFSET (GtkViScreenClass, resized),
285 gtk_marshal_NONE__INT_INT,
286 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT, 0);
288 #ifndef HAVE_PANGO
289 gtk_object_class_add_signals(object_class, vi_screen_signals, LAST_SIGNAL);
290 #endif
292 gtk_object_add_arg_type ("GtkViScreen::vadjustment",
293 GTK_TYPE_ADJUSTMENT,
294 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
295 ARG_VADJUSTMENT);
297 object_class->set_arg = gtk_vi_screen_set_arg;
298 object_class->get_arg = gtk_vi_screen_get_arg;
299 object_class->destroy = gtk_vi_screen_destroy;
301 widget_class->realize = gtk_vi_screen_realize;
303 widget_class->map = gtk_vi_screen_map;
304 widget_class->unmap = gtk_vi_screen_unmap;
306 widget_class->size_request = gtk_vi_screen_size_request;
307 widget_class->size_allocate = gtk_vi_screen_size_allocate;
308 widget_class->expose_event = gtk_vi_screen_expose;
310 class->rename = NULL;
311 class->resized = NULL;
313 gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*");
315 tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*");
317 tfn = gdk_font_load ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646");
318 tfw = gdk_font_load ("-Misc-Fixed-Medium-R-*-*-13-120-75-75-C-120-ISO10646-1");
321 static void
322 gtk_vi_screen_set_arg (GtkObject *object,
323 GtkArg *arg,
324 guint arg_id)
326 GtkViScreen *vi_screen;
328 vi_screen = GTK_VI_SCREEN (object);
330 switch (arg_id)
332 case ARG_VADJUSTMENT:
333 gtk_vi_screen_set_adjustment (vi_screen, GTK_VALUE_POINTER (*arg));
334 break;
335 default:
336 break;
340 static void
341 gtk_vi_screen_get_arg (GtkObject *object,
342 GtkArg *arg,
343 guint arg_id)
345 GtkViScreen *vi_screen;
347 vi_screen = GTK_VI_SCREEN (object);
349 switch (arg_id)
351 case ARG_VADJUSTMENT:
352 GTK_VALUE_POINTER (*arg) = vi_screen->vadj;
353 break;
354 default:
355 arg->type = GTK_TYPE_INVALID;
356 break;
360 static void
361 gtk_vi_screen_init (GtkViScreen *vi)
363 GtkStyle *style;
365 GTK_WIDGET_SET_FLAGS (vi, GTK_CAN_FOCUS);
367 vi->text_area = NULL;
368 vi->chars = 0;
369 vi->reverse = 0;
370 vi->cols = 0;
371 vi->color = COLOR_STANDARD;
372 vi->cols = 0;
373 vi->rows = 0;
375 #ifdef HAVE_PANGO
376 vi->conx = NULL;
377 #endif
379 style = gtk_style_copy(GTK_WIDGET(vi)->style);
380 gdk_font_unref(style->font);
381 style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*");
382 GTK_WIDGET(vi)->style = style;
385 static void
386 gtk_vi_screen_destroy (GtkObject *object)
388 GtkViScreen *vi_screen;
390 g_return_if_fail (object != NULL);
391 g_return_if_fail (GTK_IS_VI_SCREEN (object));
393 vi_screen = (GtkViScreen*) object;
396 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
399 GTK_OBJECT_CLASS(parent_class)->destroy (object);
402 GtkWidget*
403 gtk_vi_screen_new (GtkAdjustment *vadj)
405 GtkWidget *vi;
407 vi = gtk_widget_new (GTK_TYPE_VI_SCREEN,
408 "vadjustment", vadj,
409 NULL);
412 return vi;
415 void
416 gtk_vi_screen_set_adjustment (GtkViScreen *vi_screen,
417 GtkAdjustment *vadj)
419 g_return_if_fail (vi_screen != NULL);
420 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
421 if (vadj)
422 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
423 else
424 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0, 1.0, 0.0, 0.0));
426 if (vi_screen->vadj && (vi_screen->vadj != vadj))
428 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
429 gtk_object_unref (GTK_OBJECT (vi_screen->vadj));
432 if (vi_screen->vadj != vadj)
434 vi_screen->vadj = vadj;
435 gtk_object_ref (GTK_OBJECT (vi_screen->vadj));
436 gtk_object_sink (GTK_OBJECT (vi_screen->vadj));
439 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "changed",
440 (GtkSignalFunc) gtk_vi_screen_adjustment,
441 vi_screen);
442 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "value_changed",
443 (GtkSignalFunc) gtk_vi_screen_adjustment,
444 vi_screen);
445 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "disconnect",
446 (GtkSignalFunc) gtk_vi_screen_disconnect,
447 vi_screen);
448 gtk_vi_screen_adjustment (vadj, vi_screen);
453 static void
454 gtk_vi_screen_realize (GtkWidget *widget)
456 GtkViScreen *vi;
457 GdkWindowAttr attributes;
458 gint attributes_mask;
460 g_return_if_fail (widget != NULL);
461 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
463 vi = GTK_VI_SCREEN (widget);
464 GTK_WIDGET_SET_FLAGS (vi, GTK_REALIZED);
466 attributes.window_type = GDK_WINDOW_CHILD;
467 attributes.x = widget->allocation.x;
468 attributes.y = widget->allocation.y;
469 attributes.width = widget->allocation.width;
470 attributes.height = widget->allocation.height;
471 attributes.wclass = GDK_INPUT_OUTPUT;
472 attributes.visual = gtk_widget_get_visual (widget);
473 attributes.colormap = gtk_widget_get_colormap (widget);
474 attributes.event_mask = gtk_widget_get_events (widget);
475 attributes.event_mask |= (GDK_EXPOSURE_MASK |
476 GDK_BUTTON_PRESS_MASK |
477 GDK_BUTTON_RELEASE_MASK |
478 GDK_BUTTON_MOTION_MASK |
479 GDK_ENTER_NOTIFY_MASK |
480 GDK_LEAVE_NOTIFY_MASK |
481 GDK_KEY_PRESS_MASK);
482 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
484 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
485 gdk_window_set_user_data (widget->window, vi);
487 attributes.x = (widget->style->xthickness + VI_SCREEN_BORDER_ROOM);
488 attributes.y = (widget->style->ythickness + VI_SCREEN_BORDER_ROOM);
489 attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
490 attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
492 vi->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
493 gdk_window_set_user_data (vi->text_area, vi);
495 widget->style = gtk_style_attach (widget->style, widget->window);
497 /* Can't call gtk_style_set_background here because it's handled specially */
498 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
499 gdk_window_set_background (vi->text_area, &widget->style->base[GTK_STATE_NORMAL]);
501 vi->gc = gdk_gc_new (vi->text_area);
502 /* What's this ? */
503 gdk_gc_set_exposures (vi->gc, TRUE);
504 gdk_gc_set_foreground (vi->gc, &widget->style->text[GTK_STATE_NORMAL]);
506 vi->reverse_gc = gdk_gc_new (vi->text_area);
507 gdk_gc_set_foreground (vi->reverse_gc, &widget->style->base[GTK_STATE_NORMAL]);
509 gdk_window_show (vi->text_area);
511 recompute_geometry (vi);
514 static void
515 gtk_vi_screen_size_request (GtkWidget *widget,
516 GtkRequisition *requisition)
518 gint xthick;
519 gint ythick;
520 gint char_height;
521 gint char_width;
522 GtkViScreen *vi;
524 g_return_if_fail (widget != NULL);
525 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
526 g_return_if_fail (requisition != NULL);
528 vi = GTK_VI_SCREEN (widget);
530 xthick = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
531 ythick = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
533 vi->ch_ascent = widget->style->font->ascent;
534 vi->ch_height = (widget->style->font->ascent + widget->style->font->descent) + 1;
535 vi->ch_width = gdk_text_width (widget->style->font, "A", 1);
536 char_height = DEFAULT_VI_SCREEN_HEIGHT_LINES * vi->ch_height;
537 char_width = DEFAULT_VI_SCREEN_WIDTH_CHARS * vi->ch_width;
539 requisition->width = char_width + xthick * 2;
540 requisition->height = char_height + ythick * 2;
543 static void
544 gtk_vi_screen_size_allocate (GtkWidget *widget,
545 GtkAllocation *allocation)
547 GtkViScreen *vi;
549 g_return_if_fail (widget != NULL);
550 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
551 g_return_if_fail (allocation != NULL);
553 vi = GTK_VI_SCREEN (widget);
555 widget->allocation = *allocation;
556 if (GTK_WIDGET_REALIZED (widget))
558 gdk_window_move_resize (widget->window,
559 allocation->x, allocation->y,
560 allocation->width, allocation->height);
562 gdk_window_move_resize (vi->text_area,
563 widget->style->xthickness + VI_SCREEN_BORDER_ROOM,
564 widget->style->ythickness + VI_SCREEN_BORDER_ROOM,
565 MAX (1, (gint)widget->allocation.width - (gint)(widget->style->xthickness +
566 (gint)VI_SCREEN_BORDER_ROOM) * 2),
567 MAX (1, (gint)widget->allocation.height - (gint)(widget->style->ythickness +
568 (gint)VI_SCREEN_BORDER_ROOM) * 2));
570 recompute_geometry (vi);
575 static void
576 gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
577 GtkViScreen *vi_screen)
579 g_return_if_fail (adjustment != NULL);
580 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
581 g_return_if_fail (vi_screen != NULL);
582 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
587 static gint
588 gtk_vi_screen_expose (GtkWidget *widget,
589 GdkEventExpose *event)
591 g_return_val_if_fail (widget != NULL, FALSE);
592 g_return_val_if_fail (GTK_IS_VI_SCREEN (widget), FALSE);
593 g_return_val_if_fail (event != NULL, FALSE);
595 if (event->window == GTK_VI_SCREEN (widget)->text_area)
597 expose_text (GTK_VI_SCREEN (widget), &event->area, TRUE);
600 return FALSE;
603 static void
604 recompute_geometry (GtkViScreen* vi)
606 //gint xthickness;
607 //gint ythickness;
608 gint height;
609 gint width;
610 gint rows, cols;
611 gint i;
613 //xthickness = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
614 //ythickness = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
616 gdk_window_get_size (vi->text_area, &width, &height);
618 rows = height / vi->ch_height;
619 cols = width / vi->ch_width;
621 if (rows == vi->rows && cols == vi->cols)
622 return;
624 vi->marked_x = vi->cols = cols;
625 vi->marked_y = vi->rows = rows;
626 vi->marked_maxx = 0;
627 vi->marked_maxy = 0;
629 g_free(vi->chars);
630 vi->chars = (CHAR_T*)g_new(gchar, (vi->rows+1)*vi->cols * sizeof(CHAR_T));
631 STRSET(vi->chars, L(' '), (vi->rows+1)*vi->cols);
632 g_free(vi->endcol);
633 vi->endcol = g_new(guchar, vi->rows*vi->cols);
634 g_free(vi->reverse);
635 vi->reverse = g_new(guchar, vi->rows*vi->cols);
636 memset(vi->reverse, 0, vi->rows*vi->cols);
638 gtk_signal_emit(GTK_OBJECT(vi), vi_screen_signals[RESIZED], vi->rows, vi->cols);
641 static void
642 expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor)
644 gint ymax;
645 gint xmax, xmin;
647 gdk_window_clear_area (vi->text_area, area->x, area->y,
648 area->width, area->height);
649 ymax = MIN((area->y + area->height + vi->ch_height - 1) / vi->ch_height,
650 vi->rows);
651 xmin = area->x / vi->ch_width;
652 xmax = MIN((area->x + area->width + vi->ch_width - 1) / vi->ch_width,
653 vi->cols);
654 draw_lines(vi, area->y / vi->ch_height, xmin, ymax, xmax);
657 #define Inverse(screen,y,x) \
658 ((*FlagAt(screen,y,x) == COLOR_STANDOUT) ^ \
659 (screen->cury == y && screen->curx == x))
661 static void
662 draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
664 gint y, x, len, blen, xpos;
665 CHAR_T *line;
666 GdkGC *fg, *bg;
667 GdkFont *font;
668 gchar buf[2];
669 gchar *p;
670 gboolean pango;
672 for (y = ymin, line = vi->chars + y*vi->cols;
673 y < ymax; ++y, line += vi->cols) {
674 for (x = 0, xpos = 0; xpos <= xmin; ++x)
675 xpos += CHAR_WIDTH(NULL, *(line+x));
676 --x;
677 xpos -= CHAR_WIDTH(NULL, *(line+x));
678 for (; xpos < xmax; x+=len, xpos+= blen) {
679 gchar inverse;
680 inverse = Inverse(vi,y,x);
681 len = 1;
682 if (sizeof(CHAR_T) == sizeof(gchar))
683 for (; x+len < xmax &&
684 Inverse(vi,y,x+len) == inverse; ++len);
685 if (inverse) {
686 fg = vi->reverse_gc;
687 bg = vi->gc;
688 } else {
689 bg = vi->reverse_gc;
690 fg = vi->gc;
692 pango = 0;
693 #ifdef HAVE_PANGO
694 if (INTISUCS(*(line+x))) {
695 if (!vi->conx) {
696 PangoFontDescription font_description;
698 font_description.family_name = g_strdup ("monospace");
699 font_description.style = PANGO_STYLE_NORMAL;
700 font_description.variant = PANGO_VARIANT_NORMAL;
701 font_description.weight = 500;
702 font_description.stretch = PANGO_STRETCH_NORMAL;
703 font_description.size = 15000;
705 vi->conx = gdk_pango_context_get();
706 pango_context_set_font_description (vi->conx,
707 &font_description);
708 pango_context_set_lang(vi->conx, "en_US");
709 vi->alist = pango_attr_list_new();
711 blen = CHAR_WIDTH(NULL, *(line+x));
712 pango = 1;
713 } else
714 #endif
716 font = GTK_WIDGET(vi)->style->font;
717 if (sizeof(CHAR_T) == sizeof(gchar))
718 p = (gchar*)line+x;
719 else {
720 buf[0] = *(line+x);
721 p = buf;
723 blen = len;
725 gdk_draw_rectangle(vi->text_area, bg, 1, xpos * vi->ch_width,
726 y * vi->ch_height, blen * vi->ch_width,
727 vi->ch_height);
728 /* hack to not display half a wide character that wasn't
729 * removed.
731 if (!pango)
732 gdk_draw_text (vi->text_area, font, fg,
733 xpos * vi->ch_width,
734 y * vi->ch_height + vi->ch_ascent,
735 p, blen);
736 #ifdef HAVE_PANGO
737 else {
738 PangoGlyphString *gs;
739 GList *list;
740 PangoItem *item;
741 char buf[3];
742 int len;
744 len = ucs2utf8(line+x, 1, buf);
745 list = pango_itemize(vi->conx, buf, 0, len, vi->alist, NULL);
746 item = list->data;
747 gs = pango_glyph_string_new ();
748 pango_shape(buf, len, &item->analysis, gs);
750 gdk_draw_glyphs (vi->text_area, fg, item->analysis.font,
751 xpos * vi->ch_width,
752 y * vi->ch_height + vi->ch_ascent, gs);
754 #endif
759 static void
760 mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
762 if (ymin < vi->marked_y) vi->marked_y = ymin;
763 if (xmin < vi->marked_x) vi->marked_x = xmin;
764 if (ymax > vi->marked_maxy) vi->marked_maxy = ymax;
765 if (xmax > vi->marked_maxx) vi->marked_maxx = xmax;