the script used to extract a release
[nvi.git] / gtk / gtkviscreen.c
blob31cdf9ff4799400e7dcb57f4b391f110e1498da9
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 #include "../common/conv.h"
11 void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n));
13 #define DEFAULT_VI_SCREEN_WIDTH_CHARS 80
14 #define DEFAULT_VI_SCREEN_HEIGHT_LINES 25
15 #define VI_SCREEN_BORDER_ROOM 1
17 enum {
18 ARG_0,
19 ARG_VADJUSTMENT,
22 enum {
23 RESIZED,
24 LAST_SIGNAL
27 static void gtk_vi_screen_class_init (GtkViScreenClass *klass);
28 static void gtk_vi_screen_set_arg (GtkObject *object,
29 GtkArg *arg,
30 guint arg_id);
31 static void gtk_vi_screen_get_arg (GtkObject *object,
32 GtkArg *arg,
33 guint arg_id);
34 static void gtk_vi_screen_init (GtkViScreen *vi);
35 static void gtk_vi_screen_destroy (GtkObject *object);
36 static void gtk_vi_screen_realize (GtkWidget *widget);
38 static void gtk_vi_screen_map (GtkWidget *widget);
39 static void gtk_vi_screen_unmap (GtkWidget *widget);
41 static void gtk_vi_screen_size_request (GtkWidget *widget,
42 GtkRequisition *requisition);
43 static void gtk_vi_screen_size_allocate (GtkWidget *widget,
44 GtkAllocation *allocation);
46 static void gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
47 GtkViScreen *text);
50 static void gtk_vi_screen_draw (GtkWidget *widget,
51 GdkRectangle *area);
52 static gint gtk_vi_screen_expose (GtkWidget *widget,
53 GdkEventExpose *event);
55 static void recompute_geometry (GtkViScreen* vi);
56 static void expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor);
57 static void draw_lines(GtkViScreen *vi, gint y, gint x, gint ymax, gint xmax);
58 static void mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax);
60 static GtkWidgetClass *parent_class = NULL;
61 static guint vi_screen_signals[LAST_SIGNAL] = { 0 };
63 static GdkFont *gb_font;
64 static GdkFont *tfn;
65 static GdkFont *tfw;
67 #define CharAt(scr,y,x) scr->chars + (y) * scr->cols + x
68 #define FlagAt(scr,y,x) (scr->reverse + (y) * scr->cols + x)
69 #define ColAt(scr,y,x) (scr->endcol + (y) * scr->cols + x)
71 #define COLOR_STANDARD 0x00
72 #define COLOR_STANDOUT 0x01
74 /* XXX */
75 enum { SA_ALTERNATE, SA_INVERSE };
77 void
78 gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on)
80 switch (attribute) {
81 case SA_INVERSE:
82 vi->color = on ? COLOR_STANDOUT : COLOR_STANDARD;
83 break;
87 /* col is screen column */
88 void
89 gtk_vi_screen_move(GtkViScreen *vi, gint row, gint col)
91 gint x;
92 guchar *endcol;
94 endcol = vi->endcol + row*vi->cols;
95 for (x = 0; col > endcol[x]; ++x);
96 vi->curx = x;
97 vi->cury = row;
100 static void
101 cleartoel (GtkViScreen *vi, guint row, guint col)
103 CHAR_T *p, *e;
105 if (MEMCMP(p = CharAt(vi,row,col), e = CharAt(vi,vi->rows,0),
106 vi->cols - col)) {
107 MEMMOVE(p, e, vi->cols - col);
108 memset(FlagAt(vi,row,col), COLOR_STANDARD, vi->cols - col);
109 mark_lines(vi, row, col, row+1, vi->cols);
113 void
114 gtk_vi_screen_clrtoel (GtkViScreen *vi)
116 cleartoel(vi, vi->cury, vi->curx);
119 void
120 gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len)
122 CHAR_T *p, *end;
123 CHAR_T *line;
124 guchar *endcol;
125 gint col, startcol;
126 gint x;
128 line = vi->chars + vi->cury*vi->cols;
129 endcol = vi->endcol + vi->cury*vi->cols;
130 x = vi->curx;
131 startcol = x ? endcol[x-1] : -1;
132 for (p = CharAt(vi,vi->cury,vi->curx), end = p + len, col = startcol;
133 p < end; ++x) {
134 *p++ = *str++;
135 endcol[x] = ++col;
137 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
139 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
141 if (endcol[x-1] >= vi->cols) {
142 if (++vi->cury >= vi->rows) {
143 vi->cury = vi->rows-1;
144 vi->curx = x-1;
145 } else {
146 vi->curx = 0;
148 } else vi->curx += len;
149 if (x < vi->cols) endcol[x] = vi->cols;
152 void
153 gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len)
155 CHAR_T *p, *end;
156 CHAR_T *line;
157 guchar *endcol;
158 gint col, startcol;
159 gint x;
161 MEMMOVE(CharAt(vi,vi->cury,vi->curx),str,len);
162 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
164 line = vi->chars + vi->cury*vi->cols;
165 endcol = vi->endcol + vi->cury*vi->cols;
166 x = vi->curx;
167 startcol = x ? endcol[x-1] : -1;
168 for (col = startcol; x < vi->curx + len; ++x)
169 endcol[x] = col += CHAR_WIDTH(NULL, *(line+x));
171 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
173 if (endcol[x-1] >= vi->cols) {
174 if (++vi->cury >= vi->rows) {
175 vi->cury = vi->rows-1;
176 vi->curx = x-1;
177 } else {
178 vi->curx = 0;
180 } else vi->curx += len;
181 if (x < vi->cols) endcol[x] = vi->cols;
184 void
185 gtk_vi_screen_deleteln(GtkViScreen *vi)
187 gint y = vi->cury;
188 gint rows = vi->rows - (y+1);
190 MEMMOVE(CharAt(vi,y,0), CharAt(vi,y+1,0), rows * vi->cols);
191 cleartoel(vi,vi->rows-1,0);
192 memmove(FlagAt(vi,y,0), FlagAt(vi,y+1,0), rows * vi->cols);
193 memmove(ColAt(vi,y,0), ColAt(vi,y+1,0), rows * vi->cols);
194 mark_lines(vi, y, 0, vi->rows-1, vi->cols);
197 void
198 gtk_vi_screen_insertln(GtkViScreen *vi)
200 gint y = vi->cury;
201 gint rows = vi->rows - (y+1);
203 MEMMOVE(CharAt(vi,y+1,0), CharAt(vi,y,0), rows * vi->cols);
204 cleartoel(vi,y,0);
205 memmove(FlagAt(vi,y+1,0), FlagAt(vi,y,0), rows * vi->cols);
206 memmove(ColAt(vi,y+1,0), ColAt(vi,y,0), rows * vi->cols);
207 mark_lines(vi, y+1, 0, vi->rows, vi->cols);
210 void
211 gtk_vi_screen_refresh(GtkViScreen *vi)
213 if (vi->lastx != vi->curx || vi->lasty != vi-> cury) {
214 mark_lines(vi, vi->lasty,
215 vi->lastx ? *ColAt(vi,vi->lasty,vi->lastx-1) + 1 : 0,
216 vi->lasty+1, *ColAt(vi,vi->lasty,vi->lastx)+1);
217 mark_lines(vi, vi->cury,
218 vi->curx ? *ColAt(vi,vi->cury,vi->curx-1) + 1 : 0,
219 vi->cury+1, *ColAt(vi,vi->cury,vi->curx)+1);
221 if (vi->marked_maxy == 0)
222 return;
223 draw_lines(vi, vi->marked_y, vi->marked_x, vi->marked_maxy, vi->marked_maxx);
224 vi->marked_x = vi->cols;
225 vi->marked_y = vi->rows;
226 vi->marked_maxx = 0;
227 vi->marked_maxy = 0;
228 vi->lastx = vi->curx;
229 vi->lasty = vi->cury;
232 void
233 gtk_vi_screen_rewrite(GtkViScreen *vi, gint row)
235 memset(FlagAt(vi,row,0), COLOR_STANDARD, vi->cols);
236 mark_lines(vi, row, 0, row+1, vi->cols);
239 GtkType
240 gtk_vi_screen_get_type (void)
242 static GtkType vi_screen_type = 0;
244 if (!vi_screen_type)
246 static const GtkTypeInfo vi_screen_info =
248 "GtkViScreen",
249 sizeof (GtkViScreen),
250 sizeof (GtkViScreenClass),
251 (GtkClassInitFunc) gtk_vi_screen_class_init,
252 (GtkObjectInitFunc) gtk_vi_screen_init,
253 /* reserved_1 */ NULL,
254 /* reserved_2 */ NULL,
255 (GtkClassInitFunc) NULL,
258 vi_screen_type = gtk_type_unique (GTK_TYPE_WIDGET, &vi_screen_info);
261 return vi_screen_type;
264 static void
265 gtk_vi_screen_class_init (GtkViScreenClass *class)
267 GtkObjectClass *object_class;
268 GtkWidgetClass *widget_class;
270 object_class = (GtkObjectClass*) class;
271 widget_class = (GtkWidgetClass*) class;
272 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
274 vi_screen_signals[RESIZED] =
275 gtk_signal_new ("resized",
276 GTK_RUN_FIRST,
277 object_class->type,
278 GTK_SIGNAL_OFFSET (GtkViScreenClass, resized),
279 gtk_marshal_NONE__INT_INT,
280 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT, 0);
282 gtk_object_class_add_signals(object_class, vi_screen_signals, LAST_SIGNAL);
284 gtk_object_add_arg_type ("GtkViScreen::vadjustment",
285 GTK_TYPE_ADJUSTMENT,
286 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
287 ARG_VADJUSTMENT);
289 object_class->set_arg = gtk_vi_screen_set_arg;
290 object_class->get_arg = gtk_vi_screen_get_arg;
291 object_class->destroy = gtk_vi_screen_destroy;
293 widget_class->realize = gtk_vi_screen_realize;
295 widget_class->map = gtk_vi_screen_map;
296 widget_class->unmap = gtk_vi_screen_unmap;
298 widget_class->size_request = gtk_vi_screen_size_request;
299 widget_class->size_allocate = gtk_vi_screen_size_allocate;
300 widget_class->draw = gtk_vi_screen_draw;
301 widget_class->expose_event = gtk_vi_screen_expose;
303 class->rename = NULL;
304 class->resized = NULL;
306 gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*");
308 tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*");
310 tfn = gdk_font_load ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646");
311 tfw = gdk_font_load ("-Misc-Fixed-Medium-R-*-*-13-120-75-75-C-120-ISO10646-1");
314 static void
315 gtk_vi_screen_set_arg (GtkObject *object,
316 GtkArg *arg,
317 guint arg_id)
319 GtkViScreen *vi_screen;
321 vi_screen = GTK_VI_SCREEN (object);
323 switch (arg_id)
325 case ARG_VADJUSTMENT:
326 gtk_vi_screen_set_adjustment (vi_screen, GTK_VALUE_POINTER (*arg));
327 break;
328 default:
329 break;
333 static void
334 gtk_vi_screen_get_arg (GtkObject *object,
335 GtkArg *arg,
336 guint arg_id)
338 GtkViScreen *vi_screen;
340 vi_screen = GTK_VI_SCREEN (object);
342 switch (arg_id)
344 case ARG_VADJUSTMENT:
345 GTK_VALUE_POINTER (*arg) = vi_screen->vadj;
346 break;
347 default:
348 arg->type = GTK_TYPE_INVALID;
349 break;
353 static void
354 gtk_vi_screen_init (GtkViScreen *vi)
356 GtkStyle *style;
358 GTK_WIDGET_SET_FLAGS (vi, GTK_CAN_FOCUS);
360 vi->text_area = NULL;
361 vi->chars = 0;
362 vi->reverse = 0;
363 vi->cols = 0;
364 vi->color = COLOR_STANDARD;
365 vi->cols = 0;
366 vi->rows = 0;
368 vi->conx = NULL;
370 style = gtk_style_copy(GTK_WIDGET(vi)->style);
371 gdk_font_unref(style->font);
372 style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*");
373 GTK_WIDGET(vi)->style = style;
376 static void
377 gtk_vi_screen_destroy (GtkObject *object)
379 GtkViScreen *vi_screen;
381 g_return_if_fail (object != NULL);
382 g_return_if_fail (GTK_IS_VI_SCREEN (object));
384 vi_screen = (GtkViScreen*) object;
387 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
390 GTK_OBJECT_CLASS(parent_class)->destroy (object);
393 GtkWidget*
394 gtk_vi_screen_new (GtkAdjustment *vadj)
396 GtkWidget *vi;
398 vi = gtk_widget_new (GTK_TYPE_VI_SCREEN,
399 "vadjustment", vadj,
400 NULL);
403 return vi;
406 void
407 gtk_vi_screen_set_adjustment (GtkViScreen *vi_screen,
408 GtkAdjustment *vadj)
410 g_return_if_fail (vi_screen != NULL);
411 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
412 if (vadj)
413 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
414 else
415 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0, 1.0, 0.0, 0.0));
417 if (vi_screen->vadj && (vi_screen->vadj != vadj))
419 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
420 gtk_object_unref (GTK_OBJECT (vi_screen->vadj));
423 if (vi_screen->vadj != vadj)
425 vi_screen->vadj = vadj;
426 gtk_object_ref (GTK_OBJECT (vi_screen->vadj));
427 gtk_object_sink (GTK_OBJECT (vi_screen->vadj));
430 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "changed",
431 (GtkSignalFunc) gtk_vi_screen_adjustment,
432 vi_screen);
433 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "value_changed",
434 (GtkSignalFunc) gtk_vi_screen_adjustment,
435 vi_screen);
436 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "disconnect",
437 (GtkSignalFunc) gtk_vi_screen_disconnect,
438 vi_screen);
439 gtk_vi_screen_adjustment (vadj, vi_screen);
444 static void
445 gtk_vi_screen_realize (GtkWidget *widget)
447 GtkViScreen *vi;
448 GdkWindowAttr attributes;
449 gint attributes_mask;
451 g_return_if_fail (widget != NULL);
452 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
454 vi = GTK_VI_SCREEN (widget);
455 GTK_WIDGET_SET_FLAGS (vi, GTK_REALIZED);
457 attributes.window_type = GDK_WINDOW_CHILD;
458 attributes.x = widget->allocation.x;
459 attributes.y = widget->allocation.y;
460 attributes.width = widget->allocation.width;
461 attributes.height = widget->allocation.height;
462 attributes.wclass = GDK_INPUT_OUTPUT;
463 attributes.visual = gtk_widget_get_visual (widget);
464 attributes.colormap = gtk_widget_get_colormap (widget);
465 attributes.event_mask = gtk_widget_get_events (widget);
466 attributes.event_mask |= (GDK_EXPOSURE_MASK |
467 GDK_BUTTON_PRESS_MASK |
468 GDK_BUTTON_RELEASE_MASK |
469 GDK_BUTTON_MOTION_MASK |
470 GDK_ENTER_NOTIFY_MASK |
471 GDK_LEAVE_NOTIFY_MASK |
472 GDK_KEY_PRESS_MASK);
473 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
475 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
476 gdk_window_set_user_data (widget->window, vi);
478 attributes.x = (widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM);
479 attributes.y = (widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM);
480 attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
481 attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
483 vi->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
484 gdk_window_set_user_data (vi->text_area, vi);
486 widget->style = gtk_style_attach (widget->style, widget->window);
488 /* Can't call gtk_style_set_background here because it's handled specially */
489 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
490 gdk_window_set_background (vi->text_area, &widget->style->base[GTK_STATE_NORMAL]);
492 vi->gc = gdk_gc_new (vi->text_area);
493 /* What's this ? */
494 gdk_gc_set_exposures (vi->gc, TRUE);
495 gdk_gc_set_foreground (vi->gc, &widget->style->text[GTK_STATE_NORMAL]);
497 vi->reverse_gc = gdk_gc_new (vi->text_area);
498 gdk_gc_set_foreground (vi->reverse_gc, &widget->style->base[GTK_STATE_NORMAL]);
500 gdk_window_show (vi->text_area);
502 recompute_geometry (vi);
505 static void
506 gtk_vi_screen_size_request (GtkWidget *widget,
507 GtkRequisition *requisition)
509 gint xthickness;
510 gint ythickness;
511 gint char_height;
512 gint char_width;
513 GtkViScreen *vi;
515 g_return_if_fail (widget != NULL);
516 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
517 g_return_if_fail (requisition != NULL);
519 vi = GTK_VI_SCREEN (widget);
521 xthickness = widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM;
522 ythickness = widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM;
524 vi->ch_ascent = widget->style->font->ascent;
525 vi->ch_height = (widget->style->font->ascent + widget->style->font->descent) + 1;
526 vi->ch_width = gdk_text_width (widget->style->font, "A", 1);
527 char_height = DEFAULT_VI_SCREEN_HEIGHT_LINES * vi->ch_height;
528 char_width = DEFAULT_VI_SCREEN_WIDTH_CHARS * vi->ch_width;
530 requisition->width = char_width + xthickness * 2;
531 requisition->height = char_height + ythickness * 2;
534 static void
535 gtk_vi_screen_size_allocate (GtkWidget *widget,
536 GtkAllocation *allocation)
538 GtkViScreen *vi;
540 g_return_if_fail (widget != NULL);
541 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
542 g_return_if_fail (allocation != NULL);
544 vi = GTK_VI_SCREEN (widget);
546 widget->allocation = *allocation;
547 if (GTK_WIDGET_REALIZED (widget))
549 gdk_window_move_resize (widget->window,
550 allocation->x, allocation->y,
551 allocation->width, allocation->height);
553 gdk_window_move_resize (vi->text_area,
554 widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM,
555 widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM,
556 MAX (1, (gint)widget->allocation.width - (gint)(widget->style->klass->xthickness +
557 (gint)VI_SCREEN_BORDER_ROOM) * 2),
558 MAX (1, (gint)widget->allocation.height - (gint)(widget->style->klass->ythickness +
559 (gint)VI_SCREEN_BORDER_ROOM) * 2));
561 recompute_geometry (vi);
566 static void
567 gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
568 GtkViScreen *vi_screen)
570 g_return_if_fail (adjustment != NULL);
571 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
572 g_return_if_fail (vi_screen != NULL);
573 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
578 static void
579 gtk_vi_screen_draw (GtkWidget *widget,
580 GdkRectangle *area)
582 g_return_if_fail (widget != NULL);
583 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
584 g_return_if_fail (area != NULL);
586 if (GTK_WIDGET_DRAWABLE (widget))
588 expose_text (GTK_VI_SCREEN (widget), area, TRUE);
589 gtk_widget_draw_focus (widget);
593 static gint
594 gtk_vi_screen_expose (GtkWidget *widget,
595 GdkEventExpose *event)
597 g_return_val_if_fail (widget != NULL, FALSE);
598 g_return_val_if_fail (GTK_IS_VI_SCREEN (widget), FALSE);
599 g_return_val_if_fail (event != NULL, FALSE);
601 if (event->window == GTK_VI_SCREEN (widget)->text_area)
603 expose_text (GTK_VI_SCREEN (widget), &event->area, TRUE);
605 else if (event->count == 0)
607 gtk_widget_draw_focus (widget);
610 return FALSE;
613 static void
614 recompute_geometry (GtkViScreen* vi)
616 //gint xthickness;
617 //gint ythickness;
618 gint height;
619 gint width;
620 gint rows, cols;
621 gint i;
623 //xthickness = widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM;
624 //ythickness = widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM;
626 gdk_window_get_size (vi->text_area, &width, &height);
628 rows = height / vi->ch_height;
629 cols = width / vi->ch_width;
631 if (rows == vi->rows && cols == vi->cols)
632 return;
634 vi->marked_x = vi->cols = cols;
635 vi->marked_y = vi->rows = rows;
636 vi->marked_maxx = 0;
637 vi->marked_maxy = 0;
639 g_free(vi->chars);
640 vi->chars = (CHAR_T*)g_new(gchar, (vi->rows+1)*vi->cols * sizeof(CHAR_T));
641 STRSET(vi->chars, ' ', (vi->rows+1)*vi->cols);
642 g_free(vi->endcol);
643 vi->endcol = g_new(guchar, vi->rows*vi->cols);
644 g_free(vi->reverse);
645 vi->reverse = g_new(guchar, vi->rows*vi->cols);
646 memset(vi->reverse, 0, vi->rows*vi->cols);
648 gtk_signal_emit(GTK_OBJECT(vi), vi_screen_signals[RESIZED], vi->rows, vi->cols);
651 static void
652 expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor)
654 gint ymax;
655 gint xmax, xmin;
657 gdk_window_clear_area (vi->text_area, area->x, area->y,
658 area->width, area->height);
659 ymax = MIN((area->y + area->height + vi->ch_height - 1) / vi->ch_height,
660 vi->rows);
661 xmin = area->x / vi->ch_width;
662 xmax = MIN((area->x + area->width + vi->ch_width - 1) / vi->ch_width,
663 vi->cols);
664 draw_lines(vi, area->y / vi->ch_height, xmin, ymax, xmax);
667 #define Inverse(screen,y,x) \
668 ((*FlagAt(screen,y,x) == COLOR_STANDOUT) ^ \
669 (screen->cury == y && screen->curx == x))
671 static void
672 draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
674 gint y, x, len, blen, xpos;
675 CHAR_T *line;
676 GdkGC *fg, *bg;
677 GdkFont *font;
678 gchar buf[2];
679 gchar *p;
680 gboolean pango;
682 for (y = ymin, line = vi->chars + y*vi->cols;
683 y < ymax; ++y, line += vi->cols) {
684 for (x = 0, xpos = 0; xpos <= xmin; ++x)
685 xpos += CHAR_WIDTH(NULL, *(line+x));
686 --x;
687 xpos -= CHAR_WIDTH(NULL, *(line+x));
688 for (; xpos < xmax; x+=len, xpos+= blen) {
689 gchar inverse;
690 inverse = Inverse(vi,y,x);
691 len = 1;
692 if (sizeof(CHAR_T) == sizeof(gchar))
693 for (; x+len < xmax &&
694 Inverse(vi,y,x+len) == inverse; ++len);
695 if (inverse) {
696 fg = vi->reverse_gc;
697 bg = vi->gc;
698 } else {
699 bg = vi->reverse_gc;
700 fg = vi->gc;
702 pango = 0;
703 if (INTIS9494(*(line+x))) {
704 font = gb_font;
705 buf[0] = INT9494R(*(line+x));
706 buf[1] = INT9494C(*(line+x));
707 p = buf;
708 blen = 2;
709 } else if (INTISUCS(*(line+x))) {
710 #ifdef HAVE_PANGO
711 if (!vi->conx) {
712 PangoFontDescription font_description;
714 font_description.family_name = g_strdup ("monospace");
715 font_description.style = PANGO_STYLE_NORMAL;
716 font_description.variant = PANGO_VARIANT_NORMAL;
717 font_description.weight = 500;
718 font_description.stretch = PANGO_STRETCH_NORMAL;
719 font_description.size = 15000;
721 vi->conx = pango_x_get_context (GDK_DISPLAY ());
722 pango_context_set_font_description (vi->conx,
723 &font_description);
724 vi->alist = pango_attr_list_new();
726 blen = CHAR_WIDTH(NULL, *(line+x));
727 pango = 1;
728 if (0)
729 #endif
731 font = tfw;
732 buf[0] = *(line+x) >> 8;
733 buf[1] = (*(line+x)) & 0xFF;
734 p = buf;
735 blen = 2;
737 } else {
738 font = GTK_WIDGET(vi)->style->font;
739 if (sizeof(CHAR_T) == sizeof(gchar))
740 p = (gchar*)line+x;
741 else {
742 buf[0] = *(line+x);
743 p = buf;
745 blen = len;
747 gdk_draw_rectangle(vi->text_area, bg, 1, xpos * vi->ch_width,
748 y * vi->ch_height, blen * vi->ch_width,
749 vi->ch_height);
750 /* hack to not display half a wide character that wasn't
751 * removed.
753 if (!pango)
754 gdk_draw_text (vi->text_area, font, fg,
755 xpos * vi->ch_width,
756 y * vi->ch_height + vi->ch_ascent,
757 p, blen);
758 #ifdef HAVE_PANGO
759 else {
760 PangoGlyphString *gs;
761 GList *list;
762 PangoItem *item;
763 char buf[3];
764 int len;
766 len = ucs2utf8(line+x, 1, buf);
767 list = pango_itemize(vi->conx, buf, len, vi->alist);
768 item = list->data;
769 gs = pango_glyph_string_new ();
770 pango_shape(buf, len, &item->analysis, gs);
772 pango_x_render(GDK_DISPLAY (),
773 GDK_WINDOW_XWINDOW(vi->text_area), GDK_GC_XGC(fg),
774 item->analysis.font, gs, xpos * vi->ch_width,
775 y * vi->ch_height + vi->ch_ascent);
777 #endif
782 static void
783 mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
785 if (ymin < vi->marked_y) vi->marked_y = ymin;
786 if (xmin < vi->marked_x) vi->marked_x = xmin;
787 if (ymax > vi->marked_maxy) vi->marked_maxy = ymax;
788 if (xmax > vi->marked_maxx) vi->marked_maxx = xmax;