common/log.c: minor whitespace change
[nvi.git] / gtk / gtkviscreen.c
blobfbc50ea7c657281b5ac5013529c8a1da61d6f1c5
1 #include <stdio.h>
2 #include <string.h>
4 #include <gtk/gtkmain.h>
5 #include <gtk/gtksignal.h>
6 #include "gtkviscreen.h"
7 #include <gdk/gdkx.h>
9 #define INTISUCS(c) ((c & ~0x7F) && !(((c) >> 16) & 0x7F))
10 #define INTUCS(c) (c)
11 #ifdef USE_WIDECHAR
12 #define CHAR_WIDTH(sp, ch) wcwidth(ch)
13 #else
14 #define CHAR_WIDTH(sp, ch) 1
15 #endif
17 void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n));
19 #define DEFAULT_VI_SCREEN_WIDTH_CHARS 80
20 #define DEFAULT_VI_SCREEN_HEIGHT_LINES 25
21 #define VI_SCREEN_BORDER_ROOM 1
23 enum {
24 ARG_0,
25 ARG_VADJUSTMENT,
28 enum {
29 RESIZED,
30 LAST_SIGNAL
33 static void gtk_vi_screen_class_init (GtkViScreenClass *klass);
34 static void gtk_vi_screen_set_arg (GtkObject *object,
35 GtkArg *arg,
36 guint arg_id);
37 static void gtk_vi_screen_get_arg (GtkObject *object,
38 GtkArg *arg,
39 guint arg_id);
40 static void gtk_vi_screen_init (GtkViScreen *vi);
41 static void gtk_vi_screen_destroy (GtkObject *object);
42 static void gtk_vi_screen_realize (GtkWidget *widget);
44 static void gtk_vi_screen_map (GtkWidget *widget);
45 static void gtk_vi_screen_unmap (GtkWidget *widget);
47 static void gtk_vi_screen_size_request (GtkWidget *widget,
48 GtkRequisition *requisition);
49 static void gtk_vi_screen_size_allocate (GtkWidget *widget,
50 GtkAllocation *allocation);
52 static void gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
53 GtkViScreen *text);
56 static gint gtk_vi_screen_expose (GtkWidget *widget,
57 GdkEventExpose *event);
59 static void recompute_geometry (GtkViScreen* vi);
60 static void expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor);
61 static void draw_lines(GtkViScreen *vi, gint y, gint x, gint ymax, gint xmax);
62 static void mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax);
64 static GtkWidgetClass *parent_class = NULL;
65 static guint vi_screen_signals[LAST_SIGNAL] = { 0 };
67 static GdkFont *gb_font;
68 static GdkFont *tfn;
69 static GdkFont *tfw;
71 #define CharAt(scr,y,x) scr->chars + (y) * scr->cols + x
72 #define FlagAt(scr,y,x) (scr->reverse + (y) * scr->cols + x)
73 #define ColAt(scr,y,x) (scr->endcol + (y) * scr->cols + x)
75 #define COLOR_STANDARD 0x00
76 #define COLOR_STANDOUT 0x01
78 /* XXX */
79 enum { SA_ALTERNATE, SA_INVERSE };
81 void
82 gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on)
84 switch (attribute) {
85 case SA_INVERSE:
86 vi->color = on ? COLOR_STANDOUT : COLOR_STANDARD;
87 break;
91 /* col is screen column */
92 void
93 gtk_vi_screen_move(GtkViScreen *vi, gint row, gint col)
95 gint x;
96 guchar *endcol;
98 endcol = vi->endcol + row*vi->cols;
99 for (x = 0; col > endcol[x]; ++x);
100 vi->curx = x;
101 vi->cury = row;
104 static void
105 cleartoel (GtkViScreen *vi, guint row, guint col)
107 CHAR_T *p, *e;
109 if (MEMCMP(p = CharAt(vi,row,col), e = CharAt(vi,vi->rows,0),
110 vi->cols - col)) {
111 MEMMOVE(p, e, vi->cols - col);
112 memset(FlagAt(vi,row,col), COLOR_STANDARD, vi->cols - col);
113 mark_lines(vi, row, col, row+1, vi->cols);
117 void
118 gtk_vi_screen_clrtoel (GtkViScreen *vi)
120 cleartoel(vi, vi->cury, vi->curx);
123 void
124 gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len)
126 CHAR_T *p, *end;
127 CHAR_T *line;
128 guchar *endcol;
129 gint col, startcol;
130 gint x;
132 line = vi->chars + vi->cury*vi->cols;
133 endcol = vi->endcol + vi->cury*vi->cols;
134 x = vi->curx;
135 startcol = x ? endcol[x-1] : -1;
136 for (p = CharAt(vi,vi->cury,vi->curx), end = p + len, col = startcol;
137 p < end; ++x) {
138 *p++ = *str++;
139 endcol[x] = ++col;
141 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
143 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
145 if (endcol[x-1] >= vi->cols) {
146 if (++vi->cury >= vi->rows) {
147 vi->cury = vi->rows-1;
148 vi->curx = x-1;
149 } else {
150 vi->curx = 0;
152 } else vi->curx += len;
153 if (x < vi->cols) endcol[x] = vi->cols;
156 void
157 gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len)
159 CHAR_T *p, *end;
160 CHAR_T *line;
161 guchar *endcol;
162 gint col, startcol;
163 gint x;
165 MEMMOVE(CharAt(vi,vi->cury,vi->curx),str,len);
166 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
168 line = vi->chars + vi->cury*vi->cols;
169 endcol = vi->endcol + vi->cury*vi->cols;
170 x = vi->curx;
171 startcol = x ? endcol[x-1] : -1;
172 for (col = startcol; x < vi->curx + len; ++x)
173 endcol[x] = col += CHAR_WIDTH(NULL, *(line+x));
175 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
177 if (endcol[x-1] >= vi->cols) {
178 if (++vi->cury >= vi->rows) {
179 vi->cury = vi->rows-1;
180 vi->curx = x-1;
181 } else {
182 vi->curx = 0;
184 } else vi->curx += len;
185 if (x < vi->cols) endcol[x] = vi->cols;
188 void
189 gtk_vi_screen_deleteln(GtkViScreen *vi)
191 gint y = vi->cury;
192 gint rows = vi->rows - (y+1);
194 MEMMOVE(CharAt(vi,y,0), CharAt(vi,y+1,0), rows * vi->cols);
195 cleartoel(vi,vi->rows-1,0);
196 memmove(FlagAt(vi,y,0), FlagAt(vi,y+1,0), rows * vi->cols);
197 memmove(ColAt(vi,y,0), ColAt(vi,y+1,0), rows * vi->cols);
198 mark_lines(vi, y, 0, vi->rows-1, vi->cols);
201 void
202 gtk_vi_screen_insertln(GtkViScreen *vi)
204 gint y = vi->cury;
205 gint rows = vi->rows - (y+1);
207 MEMMOVE(CharAt(vi,y+1,0), CharAt(vi,y,0), rows * vi->cols);
208 cleartoel(vi,y,0);
209 memmove(FlagAt(vi,y+1,0), FlagAt(vi,y,0), rows * vi->cols);
210 memmove(ColAt(vi,y+1,0), ColAt(vi,y,0), rows * vi->cols);
211 mark_lines(vi, y+1, 0, vi->rows, vi->cols);
214 void
215 gtk_vi_screen_refresh(GtkViScreen *vi)
217 if (vi->lastx != vi->curx || vi->lasty != vi-> cury) {
218 mark_lines(vi, vi->lasty,
219 vi->lastx ? *ColAt(vi,vi->lasty,vi->lastx-1) + 1 : 0,
220 vi->lasty+1, *ColAt(vi,vi->lasty,vi->lastx)+1);
221 mark_lines(vi, vi->cury,
222 vi->curx ? *ColAt(vi,vi->cury,vi->curx-1) + 1 : 0,
223 vi->cury+1, *ColAt(vi,vi->cury,vi->curx)+1);
225 if (vi->marked_maxy == 0)
226 return;
227 draw_lines(vi, vi->marked_y, vi->marked_x, vi->marked_maxy, vi->marked_maxx);
228 vi->marked_x = vi->cols;
229 vi->marked_y = vi->rows;
230 vi->marked_maxx = 0;
231 vi->marked_maxy = 0;
232 vi->lastx = vi->curx;
233 vi->lasty = vi->cury;
236 void
237 gtk_vi_screen_rewrite(GtkViScreen *vi, gint row)
239 memset(FlagAt(vi,row,0), COLOR_STANDARD, vi->cols);
240 mark_lines(vi, row, 0, row+1, vi->cols);
243 GtkType
244 gtk_vi_screen_get_type (void)
246 static GtkType vi_screen_type = 0;
248 if (!vi_screen_type)
250 static const GtkTypeInfo vi_screen_info =
252 "GtkViScreen",
253 sizeof (GtkViScreen),
254 sizeof (GtkViScreenClass),
255 (GtkClassInitFunc) gtk_vi_screen_class_init,
256 (GtkObjectInitFunc) gtk_vi_screen_init,
257 /* reserved_1 */ NULL,
258 /* reserved_2 */ NULL,
259 (GtkClassInitFunc) NULL,
262 vi_screen_type = gtk_type_unique (GTK_TYPE_WIDGET, &vi_screen_info);
265 return vi_screen_type;
268 static void
269 gtk_vi_screen_class_init (GtkViScreenClass *class)
271 GtkObjectClass *object_class;
272 GtkWidgetClass *widget_class;
274 object_class = (GtkObjectClass*) class;
275 widget_class = (GtkWidgetClass*) class;
276 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
278 vi_screen_signals[RESIZED] =
279 gtk_signal_new ("resized",
280 GTK_RUN_FIRST,
281 GTK_CLASS_TYPE(object_class),
282 GTK_SIGNAL_OFFSET (GtkViScreenClass, resized),
283 gtk_marshal_NONE__INT_INT,
284 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT, 0);
286 #ifndef HAVE_PANGO
287 gtk_object_class_add_signals(object_class, vi_screen_signals, LAST_SIGNAL);
288 #endif
290 gtk_object_add_arg_type ("GtkViScreen::vadjustment",
291 GTK_TYPE_ADJUSTMENT,
292 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
293 ARG_VADJUSTMENT);
295 object_class->set_arg = gtk_vi_screen_set_arg;
296 object_class->get_arg = gtk_vi_screen_get_arg;
297 object_class->destroy = gtk_vi_screen_destroy;
299 widget_class->realize = gtk_vi_screen_realize;
301 widget_class->map = gtk_vi_screen_map;
302 widget_class->unmap = gtk_vi_screen_unmap;
304 widget_class->size_request = gtk_vi_screen_size_request;
305 widget_class->size_allocate = gtk_vi_screen_size_allocate;
306 widget_class->expose_event = gtk_vi_screen_expose;
308 class->rename = NULL;
309 class->resized = NULL;
311 gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*");
313 tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*");
315 tfn = gdk_font_load ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646");
316 tfw = gdk_font_load ("-Misc-Fixed-Medium-R-*-*-13-120-75-75-C-120-ISO10646-1");
319 static void
320 gtk_vi_screen_set_arg (GtkObject *object,
321 GtkArg *arg,
322 guint arg_id)
324 GtkViScreen *vi_screen;
326 vi_screen = GTK_VI_SCREEN (object);
328 switch (arg_id)
330 case ARG_VADJUSTMENT:
331 gtk_vi_screen_set_adjustment (vi_screen, GTK_VALUE_POINTER (*arg));
332 break;
333 default:
334 break;
338 static void
339 gtk_vi_screen_get_arg (GtkObject *object,
340 GtkArg *arg,
341 guint arg_id)
343 GtkViScreen *vi_screen;
345 vi_screen = GTK_VI_SCREEN (object);
347 switch (arg_id)
349 case ARG_VADJUSTMENT:
350 GTK_VALUE_POINTER (*arg) = vi_screen->vadj;
351 break;
352 default:
353 arg->type = GTK_TYPE_INVALID;
354 break;
358 static void
359 gtk_vi_screen_init (GtkViScreen *vi)
361 GtkStyle *style;
363 GTK_WIDGET_SET_FLAGS (vi, GTK_CAN_FOCUS);
365 vi->text_area = NULL;
366 vi->chars = 0;
367 vi->reverse = 0;
368 vi->cols = 0;
369 vi->color = COLOR_STANDARD;
370 vi->cols = 0;
371 vi->rows = 0;
373 #ifdef HAVE_PANGO
374 vi->conx = NULL;
375 #endif
377 style = gtk_style_copy(GTK_WIDGET(vi)->style);
378 gdk_font_unref(style->font);
379 style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*");
380 GTK_WIDGET(vi)->style = style;
383 static void
384 gtk_vi_screen_destroy (GtkObject *object)
386 GtkViScreen *vi_screen;
388 g_return_if_fail (object != NULL);
389 g_return_if_fail (GTK_IS_VI_SCREEN (object));
391 vi_screen = (GtkViScreen*) object;
394 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
397 GTK_OBJECT_CLASS(parent_class)->destroy (object);
400 GtkWidget*
401 gtk_vi_screen_new (GtkAdjustment *vadj)
403 GtkWidget *vi;
405 vi = gtk_widget_new (GTK_TYPE_VI_SCREEN,
406 "vadjustment", vadj,
407 NULL);
410 return vi;
413 void
414 gtk_vi_screen_set_adjustment (GtkViScreen *vi_screen,
415 GtkAdjustment *vadj)
417 g_return_if_fail (vi_screen != NULL);
418 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
419 if (vadj)
420 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
421 else
422 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0, 1.0, 0.0, 0.0));
424 if (vi_screen->vadj && (vi_screen->vadj != vadj))
426 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
427 gtk_object_unref (GTK_OBJECT (vi_screen->vadj));
430 if (vi_screen->vadj != vadj)
432 vi_screen->vadj = vadj;
433 gtk_object_ref (GTK_OBJECT (vi_screen->vadj));
434 gtk_object_sink (GTK_OBJECT (vi_screen->vadj));
437 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "changed",
438 (GtkSignalFunc) gtk_vi_screen_adjustment,
439 vi_screen);
440 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "value_changed",
441 (GtkSignalFunc) gtk_vi_screen_adjustment,
442 vi_screen);
443 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "disconnect",
444 (GtkSignalFunc) gtk_vi_screen_disconnect,
445 vi_screen);
446 gtk_vi_screen_adjustment (vadj, vi_screen);
451 static void
452 gtk_vi_screen_realize (GtkWidget *widget)
454 GtkViScreen *vi;
455 GdkWindowAttr attributes;
456 gint attributes_mask;
458 g_return_if_fail (widget != NULL);
459 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
461 vi = GTK_VI_SCREEN (widget);
462 GTK_WIDGET_SET_FLAGS (vi, GTK_REALIZED);
464 attributes.window_type = GDK_WINDOW_CHILD;
465 attributes.x = widget->allocation.x;
466 attributes.y = widget->allocation.y;
467 attributes.width = widget->allocation.width;
468 attributes.height = widget->allocation.height;
469 attributes.wclass = GDK_INPUT_OUTPUT;
470 attributes.visual = gtk_widget_get_visual (widget);
471 attributes.colormap = gtk_widget_get_colormap (widget);
472 attributes.event_mask = gtk_widget_get_events (widget);
473 attributes.event_mask |= (GDK_EXPOSURE_MASK |
474 GDK_BUTTON_PRESS_MASK |
475 GDK_BUTTON_RELEASE_MASK |
476 GDK_BUTTON_MOTION_MASK |
477 GDK_ENTER_NOTIFY_MASK |
478 GDK_LEAVE_NOTIFY_MASK |
479 GDK_KEY_PRESS_MASK);
480 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
482 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
483 gdk_window_set_user_data (widget->window, vi);
485 attributes.x = (widget->style->xthickness + VI_SCREEN_BORDER_ROOM);
486 attributes.y = (widget->style->ythickness + VI_SCREEN_BORDER_ROOM);
487 attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
488 attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
490 vi->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
491 gdk_window_set_user_data (vi->text_area, vi);
493 widget->style = gtk_style_attach (widget->style, widget->window);
495 /* Can't call gtk_style_set_background here because it's handled specially */
496 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
497 gdk_window_set_background (vi->text_area, &widget->style->base[GTK_STATE_NORMAL]);
499 vi->gc = gdk_gc_new (vi->text_area);
500 /* What's this ? */
501 gdk_gc_set_exposures (vi->gc, TRUE);
502 gdk_gc_set_foreground (vi->gc, &widget->style->text[GTK_STATE_NORMAL]);
504 vi->reverse_gc = gdk_gc_new (vi->text_area);
505 gdk_gc_set_foreground (vi->reverse_gc, &widget->style->base[GTK_STATE_NORMAL]);
507 gdk_window_show (vi->text_area);
509 recompute_geometry (vi);
512 static void
513 gtk_vi_screen_size_request (GtkWidget *widget,
514 GtkRequisition *requisition)
516 gint xthick;
517 gint ythick;
518 gint char_height;
519 gint char_width;
520 GtkViScreen *vi;
522 g_return_if_fail (widget != NULL);
523 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
524 g_return_if_fail (requisition != NULL);
526 vi = GTK_VI_SCREEN (widget);
528 xthick = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
529 ythick = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
531 vi->ch_ascent = widget->style->font->ascent;
532 vi->ch_height = (widget->style->font->ascent + widget->style->font->descent) + 1;
533 vi->ch_width = gdk_text_width (widget->style->font, "A", 1);
534 char_height = DEFAULT_VI_SCREEN_HEIGHT_LINES * vi->ch_height;
535 char_width = DEFAULT_VI_SCREEN_WIDTH_CHARS * vi->ch_width;
537 requisition->width = char_width + xthick * 2;
538 requisition->height = char_height + ythick * 2;
541 static void
542 gtk_vi_screen_size_allocate (GtkWidget *widget,
543 GtkAllocation *allocation)
545 GtkViScreen *vi;
547 g_return_if_fail (widget != NULL);
548 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
549 g_return_if_fail (allocation != NULL);
551 vi = GTK_VI_SCREEN (widget);
553 widget->allocation = *allocation;
554 if (GTK_WIDGET_REALIZED (widget))
556 gdk_window_move_resize (widget->window,
557 allocation->x, allocation->y,
558 allocation->width, allocation->height);
560 gdk_window_move_resize (vi->text_area,
561 widget->style->xthickness + VI_SCREEN_BORDER_ROOM,
562 widget->style->ythickness + VI_SCREEN_BORDER_ROOM,
563 MAX (1, (gint)widget->allocation.width - (gint)(widget->style->xthickness +
564 (gint)VI_SCREEN_BORDER_ROOM) * 2),
565 MAX (1, (gint)widget->allocation.height - (gint)(widget->style->ythickness +
566 (gint)VI_SCREEN_BORDER_ROOM) * 2));
568 recompute_geometry (vi);
573 static void
574 gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
575 GtkViScreen *vi_screen)
577 g_return_if_fail (adjustment != NULL);
578 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
579 g_return_if_fail (vi_screen != NULL);
580 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
585 static gint
586 gtk_vi_screen_expose (GtkWidget *widget,
587 GdkEventExpose *event)
589 g_return_val_if_fail (widget != NULL, FALSE);
590 g_return_val_if_fail (GTK_IS_VI_SCREEN (widget), FALSE);
591 g_return_val_if_fail (event != NULL, FALSE);
593 if (event->window == GTK_VI_SCREEN (widget)->text_area)
595 expose_text (GTK_VI_SCREEN (widget), &event->area, TRUE);
598 return FALSE;
601 static void
602 recompute_geometry (GtkViScreen* vi)
604 //gint xthickness;
605 //gint ythickness;
606 gint height;
607 gint width;
608 gint rows, cols;
609 gint i;
611 //xthickness = widget->style->xthickness + VI_SCREEN_BORDER_ROOM;
612 //ythickness = widget->style->ythickness + VI_SCREEN_BORDER_ROOM;
614 gdk_window_get_size (vi->text_area, &width, &height);
616 rows = height / vi->ch_height;
617 cols = width / vi->ch_width;
619 if (rows == vi->rows && cols == vi->cols)
620 return;
622 vi->marked_x = vi->cols = cols;
623 vi->marked_y = vi->rows = rows;
624 vi->marked_maxx = 0;
625 vi->marked_maxy = 0;
627 g_free(vi->chars);
628 vi->chars = (CHAR_T*)g_new(gchar, (vi->rows+1)*vi->cols * sizeof(CHAR_T));
629 STRSET(vi->chars, L(' '), (vi->rows+1)*vi->cols);
630 g_free(vi->endcol);
631 vi->endcol = g_new(guchar, vi->rows*vi->cols);
632 g_free(vi->reverse);
633 vi->reverse = g_new(guchar, vi->rows*vi->cols);
634 memset(vi->reverse, 0, vi->rows*vi->cols);
636 gtk_signal_emit(GTK_OBJECT(vi), vi_screen_signals[RESIZED], vi->rows, vi->cols);
639 static void
640 expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor)
642 gint ymax;
643 gint xmax, xmin;
645 gdk_window_clear_area (vi->text_area, area->x, area->y,
646 area->width, area->height);
647 ymax = MIN((area->y + area->height + vi->ch_height - 1) / vi->ch_height,
648 vi->rows);
649 xmin = area->x / vi->ch_width;
650 xmax = MIN((area->x + area->width + vi->ch_width - 1) / vi->ch_width,
651 vi->cols);
652 draw_lines(vi, area->y / vi->ch_height, xmin, ymax, xmax);
655 #define Inverse(screen,y,x) \
656 ((*FlagAt(screen,y,x) == COLOR_STANDOUT) ^ \
657 (screen->cury == y && screen->curx == x))
659 static void
660 draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
662 gint y, x, len, blen, xpos;
663 CHAR_T *line;
664 GdkGC *fg, *bg;
665 GdkFont *font;
666 gchar buf[2];
667 gchar *p;
668 gboolean pango;
670 for (y = ymin, line = vi->chars + y*vi->cols;
671 y < ymax; ++y, line += vi->cols) {
672 for (x = 0, xpos = 0; xpos <= xmin; ++x)
673 xpos += CHAR_WIDTH(NULL, *(line+x));
674 --x;
675 xpos -= CHAR_WIDTH(NULL, *(line+x));
676 for (; xpos < xmax; x+=len, xpos+= blen) {
677 gchar inverse;
678 inverse = Inverse(vi,y,x);
679 len = 1;
680 if (sizeof(CHAR_T) == sizeof(gchar))
681 for (; x+len < xmax &&
682 Inverse(vi,y,x+len) == inverse; ++len);
683 if (inverse) {
684 fg = vi->reverse_gc;
685 bg = vi->gc;
686 } else {
687 bg = vi->reverse_gc;
688 fg = vi->gc;
690 pango = 0;
691 #ifdef HAVE_PANGO
692 if (INTISUCS(*(line+x))) {
693 if (!vi->conx) {
694 PangoFontDescription font_description;
696 font_description.family_name = g_strdup ("monospace");
697 font_description.style = PANGO_STYLE_NORMAL;
698 font_description.variant = PANGO_VARIANT_NORMAL;
699 font_description.weight = 500;
700 font_description.stretch = PANGO_STRETCH_NORMAL;
701 font_description.size = 15000;
703 vi->conx = gdk_pango_context_get();
704 pango_context_set_font_description (vi->conx,
705 &font_description);
706 pango_context_set_lang(vi->conx, "en_US");
707 vi->alist = pango_attr_list_new();
709 blen = CHAR_WIDTH(NULL, *(line+x));
710 pango = 1;
711 } else
712 #endif
714 font = GTK_WIDGET(vi)->style->font;
715 if (sizeof(CHAR_T) == sizeof(gchar))
716 p = (gchar*)line+x;
717 else {
718 buf[0] = *(line+x);
719 p = buf;
721 blen = len;
723 gdk_draw_rectangle(vi->text_area, bg, 1, xpos * vi->ch_width,
724 y * vi->ch_height, blen * vi->ch_width,
725 vi->ch_height);
726 /* hack to not display half a wide character that wasn't
727 * removed.
729 if (!pango)
730 gdk_draw_text (vi->text_area, font, fg,
731 xpos * vi->ch_width,
732 y * vi->ch_height + vi->ch_ascent,
733 p, blen);
734 #ifdef HAVE_PANGO
735 else {
736 PangoGlyphString *gs;
737 GList *list;
738 PangoItem *item;
739 char buf[3];
740 int len;
742 len = ucs2utf8(line+x, 1, buf);
743 list = pango_itemize(vi->conx, buf, 0, len, vi->alist, NULL);
744 item = list->data;
745 gs = pango_glyph_string_new ();
746 pango_shape(buf, len, &item->analysis, gs);
748 gdk_draw_glyphs (vi->text_area, fg, item->analysis.font,
749 xpos * vi->ch_width,
750 y * vi->ch_height + vi->ch_ascent, gs);
752 #endif
757 static void
758 mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
760 if (ymin < vi->marked_y) vi->marked_y = ymin;
761 if (xmin < vi->marked_x) vi->marked_x = xmin;
762 if (ymax > vi->marked_maxy) vi->marked_maxy = ymax;
763 if (xmax > vi->marked_maxx) vi->marked_maxx = xmax;