CHAR_T is now wchar_t if --enable-widechar; a lot code still needs to be adapted...
[nvi.git] / gtk / gtkviscreen.c
blob08b6dc59663f4b8dd28082f4a135b2daa2264567
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 F_GB 'A'
11 #define INT9494(f,r,c) ((f) << 16) | ((r) << 8) | (c)
12 #define INTIS9494(c) !!(((c) >> 16) & 0x7F)
13 #define INTISUCS(c) ((c & ~0x7F) && !(((c) >> 16) & 0x7F))
14 #define INTUCS(c) (c)
15 #define INT9494F(c) ((c) >> 16) & 0x7F
16 #define INT9494R(c) ((c) >> 8) & 0x7F
17 #define INT9494C(c) (c) & 0x7F
18 #define INTILL(c) (1 << 23) | (c)
19 #ifdef USE_WIDECHAR
20 #define INTISWIDE(c) (!!(c >> 8))
21 #define CHAR_WIDTH(sp, ch) \
22 (INTISUCS(ch) && ucswidth(ch) > 0 ? ucswidth(ch) : INTISWIDE(ch) ? 2 : 1)
23 #else
24 #define INTISWIDE(c) 0
25 #define CHAR_WIDTH(sp, ch) 1
26 #endif
28 void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n));
30 #define DEFAULT_VI_SCREEN_WIDTH_CHARS 80
31 #define DEFAULT_VI_SCREEN_HEIGHT_LINES 25
32 #define VI_SCREEN_BORDER_ROOM 1
34 enum {
35 ARG_0,
36 ARG_VADJUSTMENT,
39 enum {
40 RESIZED,
41 LAST_SIGNAL
44 static void gtk_vi_screen_class_init (GtkViScreenClass *klass);
45 static void gtk_vi_screen_set_arg (GtkObject *object,
46 GtkArg *arg,
47 guint arg_id);
48 static void gtk_vi_screen_get_arg (GtkObject *object,
49 GtkArg *arg,
50 guint arg_id);
51 static void gtk_vi_screen_init (GtkViScreen *vi);
52 static void gtk_vi_screen_destroy (GtkObject *object);
53 static void gtk_vi_screen_realize (GtkWidget *widget);
55 static void gtk_vi_screen_map (GtkWidget *widget);
56 static void gtk_vi_screen_unmap (GtkWidget *widget);
58 static void gtk_vi_screen_size_request (GtkWidget *widget,
59 GtkRequisition *requisition);
60 static void gtk_vi_screen_size_allocate (GtkWidget *widget,
61 GtkAllocation *allocation);
63 static void gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
64 GtkViScreen *text);
67 static void gtk_vi_screen_draw (GtkWidget *widget,
68 GdkRectangle *area);
69 static gint gtk_vi_screen_expose (GtkWidget *widget,
70 GdkEventExpose *event);
72 static void recompute_geometry (GtkViScreen* vi);
73 static void expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor);
74 static void draw_lines(GtkViScreen *vi, gint y, gint x, gint ymax, gint xmax);
75 static void mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax);
77 static GtkWidgetClass *parent_class = NULL;
78 static guint vi_screen_signals[LAST_SIGNAL] = { 0 };
80 static GdkFont *gb_font;
81 static GdkFont *tfn;
82 static GdkFont *tfw;
84 #define CharAt(scr,y,x) scr->chars + (y) * scr->cols + x
85 #define FlagAt(scr,y,x) (scr->reverse + (y) * scr->cols + x)
86 #define ColAt(scr,y,x) (scr->endcol + (y) * scr->cols + x)
88 #define COLOR_STANDARD 0x00
89 #define COLOR_STANDOUT 0x01
91 /* XXX */
92 enum { SA_ALTERNATE, SA_INVERSE };
94 void
95 gtk_vi_screen_attribute(GtkViScreen *vi, gint attribute, gint on)
97 switch (attribute) {
98 case SA_INVERSE:
99 vi->color = on ? COLOR_STANDOUT : COLOR_STANDARD;
100 break;
104 /* col is screen column */
105 void
106 gtk_vi_screen_move(GtkViScreen *vi, gint row, gint col)
108 gint x;
109 guchar *endcol;
111 endcol = vi->endcol + row*vi->cols;
112 for (x = 0; col > endcol[x]; ++x);
113 vi->curx = x;
114 vi->cury = row;
117 static void
118 cleartoel (GtkViScreen *vi, guint row, guint col)
120 CHAR_T *p, *e;
122 if (MEMCMP(p = CharAt(vi,row,col), e = CharAt(vi,vi->rows,0),
123 vi->cols - col)) {
124 MEMMOVE(p, e, vi->cols - col);
125 memset(FlagAt(vi,row,col), COLOR_STANDARD, vi->cols - col);
126 mark_lines(vi, row, col, row+1, vi->cols);
130 void
131 gtk_vi_screen_clrtoel (GtkViScreen *vi)
133 cleartoel(vi, vi->cury, vi->curx);
136 void
137 gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len)
139 CHAR_T *p, *end;
140 CHAR_T *line;
141 guchar *endcol;
142 gint col, startcol;
143 gint x;
145 line = vi->chars + vi->cury*vi->cols;
146 endcol = vi->endcol + vi->cury*vi->cols;
147 x = vi->curx;
148 startcol = x ? endcol[x-1] : -1;
149 for (p = CharAt(vi,vi->cury,vi->curx), end = p + len, col = startcol;
150 p < end; ++x) {
151 *p++ = *str++;
152 endcol[x] = ++col;
154 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
156 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
158 if (endcol[x-1] >= vi->cols) {
159 if (++vi->cury >= vi->rows) {
160 vi->cury = vi->rows-1;
161 vi->curx = x-1;
162 } else {
163 vi->curx = 0;
165 } else vi->curx += len;
166 if (x < vi->cols) endcol[x] = vi->cols;
169 void
170 gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len)
172 CHAR_T *p, *end;
173 CHAR_T *line;
174 guchar *endcol;
175 gint col, startcol;
176 gint x;
178 MEMMOVE(CharAt(vi,vi->cury,vi->curx),str,len);
179 memset(FlagAt(vi,vi->cury,vi->curx), vi->color, len);
181 line = vi->chars + vi->cury*vi->cols;
182 endcol = vi->endcol + vi->cury*vi->cols;
183 x = vi->curx;
184 startcol = x ? endcol[x-1] : -1;
185 for (col = startcol; x < vi->curx + len; ++x)
186 endcol[x] = col += CHAR_WIDTH(NULL, *(line+x));
188 mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1);
190 if (endcol[x-1] >= vi->cols) {
191 if (++vi->cury >= vi->rows) {
192 vi->cury = vi->rows-1;
193 vi->curx = x-1;
194 } else {
195 vi->curx = 0;
197 } else vi->curx += len;
198 if (x < vi->cols) endcol[x] = vi->cols;
201 void
202 gtk_vi_screen_deleteln(GtkViScreen *vi)
204 gint y = vi->cury;
205 gint rows = vi->rows - (y+1);
207 MEMMOVE(CharAt(vi,y,0), CharAt(vi,y+1,0), rows * vi->cols);
208 cleartoel(vi,vi->rows-1,0);
209 memmove(FlagAt(vi,y,0), FlagAt(vi,y+1,0), rows * vi->cols);
210 memmove(ColAt(vi,y,0), ColAt(vi,y+1,0), rows * vi->cols);
211 mark_lines(vi, y, 0, vi->rows-1, vi->cols);
214 void
215 gtk_vi_screen_insertln(GtkViScreen *vi)
217 gint y = vi->cury;
218 gint rows = vi->rows - (y+1);
220 MEMMOVE(CharAt(vi,y+1,0), CharAt(vi,y,0), rows * vi->cols);
221 cleartoel(vi,y,0);
222 memmove(FlagAt(vi,y+1,0), FlagAt(vi,y,0), rows * vi->cols);
223 memmove(ColAt(vi,y+1,0), ColAt(vi,y,0), rows * vi->cols);
224 mark_lines(vi, y+1, 0, vi->rows, vi->cols);
227 void
228 gtk_vi_screen_refresh(GtkViScreen *vi)
230 if (vi->lastx != vi->curx || vi->lasty != vi-> cury) {
231 mark_lines(vi, vi->lasty,
232 vi->lastx ? *ColAt(vi,vi->lasty,vi->lastx-1) + 1 : 0,
233 vi->lasty+1, *ColAt(vi,vi->lasty,vi->lastx)+1);
234 mark_lines(vi, vi->cury,
235 vi->curx ? *ColAt(vi,vi->cury,vi->curx-1) + 1 : 0,
236 vi->cury+1, *ColAt(vi,vi->cury,vi->curx)+1);
238 if (vi->marked_maxy == 0)
239 return;
240 draw_lines(vi, vi->marked_y, vi->marked_x, vi->marked_maxy, vi->marked_maxx);
241 vi->marked_x = vi->cols;
242 vi->marked_y = vi->rows;
243 vi->marked_maxx = 0;
244 vi->marked_maxy = 0;
245 vi->lastx = vi->curx;
246 vi->lasty = vi->cury;
249 void
250 gtk_vi_screen_rewrite(GtkViScreen *vi, gint row)
252 memset(FlagAt(vi,row,0), COLOR_STANDARD, vi->cols);
253 mark_lines(vi, row, 0, row+1, vi->cols);
256 GtkType
257 gtk_vi_screen_get_type (void)
259 static GtkType vi_screen_type = 0;
261 if (!vi_screen_type)
263 static const GtkTypeInfo vi_screen_info =
265 "GtkViScreen",
266 sizeof (GtkViScreen),
267 sizeof (GtkViScreenClass),
268 (GtkClassInitFunc) gtk_vi_screen_class_init,
269 (GtkObjectInitFunc) gtk_vi_screen_init,
270 /* reserved_1 */ NULL,
271 /* reserved_2 */ NULL,
272 (GtkClassInitFunc) NULL,
275 vi_screen_type = gtk_type_unique (GTK_TYPE_WIDGET, &vi_screen_info);
278 return vi_screen_type;
281 static void
282 gtk_vi_screen_class_init (GtkViScreenClass *class)
284 GtkObjectClass *object_class;
285 GtkWidgetClass *widget_class;
287 object_class = (GtkObjectClass*) class;
288 widget_class = (GtkWidgetClass*) class;
289 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
291 vi_screen_signals[RESIZED] =
292 gtk_signal_new ("resized",
293 GTK_RUN_FIRST,
294 object_class->type,
295 GTK_SIGNAL_OFFSET (GtkViScreenClass, resized),
296 gtk_marshal_NONE__INT_INT,
297 GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT, 0);
299 gtk_object_class_add_signals(object_class, vi_screen_signals, LAST_SIGNAL);
301 gtk_object_add_arg_type ("GtkViScreen::vadjustment",
302 GTK_TYPE_ADJUSTMENT,
303 GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
304 ARG_VADJUSTMENT);
306 object_class->set_arg = gtk_vi_screen_set_arg;
307 object_class->get_arg = gtk_vi_screen_get_arg;
308 object_class->destroy = gtk_vi_screen_destroy;
310 widget_class->realize = gtk_vi_screen_realize;
312 widget_class->map = gtk_vi_screen_map;
313 widget_class->unmap = gtk_vi_screen_unmap;
315 widget_class->size_request = gtk_vi_screen_size_request;
316 widget_class->size_allocate = gtk_vi_screen_size_allocate;
317 widget_class->draw = gtk_vi_screen_draw;
318 widget_class->expose_event = gtk_vi_screen_expose;
320 class->rename = NULL;
321 class->resized = NULL;
323 gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*");
325 tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*");
327 tfn = gdk_font_load ("-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646");
328 tfw = gdk_font_load ("-Misc-Fixed-Medium-R-*-*-13-120-75-75-C-120-ISO10646-1");
331 static void
332 gtk_vi_screen_set_arg (GtkObject *object,
333 GtkArg *arg,
334 guint arg_id)
336 GtkViScreen *vi_screen;
338 vi_screen = GTK_VI_SCREEN (object);
340 switch (arg_id)
342 case ARG_VADJUSTMENT:
343 gtk_vi_screen_set_adjustment (vi_screen, GTK_VALUE_POINTER (*arg));
344 break;
345 default:
346 break;
350 static void
351 gtk_vi_screen_get_arg (GtkObject *object,
352 GtkArg *arg,
353 guint arg_id)
355 GtkViScreen *vi_screen;
357 vi_screen = GTK_VI_SCREEN (object);
359 switch (arg_id)
361 case ARG_VADJUSTMENT:
362 GTK_VALUE_POINTER (*arg) = vi_screen->vadj;
363 break;
364 default:
365 arg->type = GTK_TYPE_INVALID;
366 break;
370 static void
371 gtk_vi_screen_init (GtkViScreen *vi)
373 GtkStyle *style;
375 GTK_WIDGET_SET_FLAGS (vi, GTK_CAN_FOCUS);
377 vi->text_area = NULL;
378 vi->chars = 0;
379 vi->reverse = 0;
380 vi->cols = 0;
381 vi->color = COLOR_STANDARD;
382 vi->cols = 0;
383 vi->rows = 0;
385 vi->conx = NULL;
387 style = gtk_style_copy(GTK_WIDGET(vi)->style);
388 gdk_font_unref(style->font);
389 style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*");
390 GTK_WIDGET(vi)->style = style;
393 static void
394 gtk_vi_screen_destroy (GtkObject *object)
396 GtkViScreen *vi_screen;
398 g_return_if_fail (object != NULL);
399 g_return_if_fail (GTK_IS_VI_SCREEN (object));
401 vi_screen = (GtkViScreen*) object;
404 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
407 GTK_OBJECT_CLASS(parent_class)->destroy (object);
410 GtkWidget*
411 gtk_vi_screen_new (GtkAdjustment *vadj)
413 GtkWidget *vi;
415 vi = gtk_widget_new (GTK_TYPE_VI_SCREEN,
416 "vadjustment", vadj,
417 NULL);
420 return vi;
423 void
424 gtk_vi_screen_set_adjustment (GtkViScreen *vi_screen,
425 GtkAdjustment *vadj)
427 g_return_if_fail (vi_screen != NULL);
428 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
429 if (vadj)
430 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
431 else
432 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 0.0, 1.0, 0.0, 0.0));
434 if (vi_screen->vadj && (vi_screen->vadj != vadj))
436 gtk_signal_disconnect_by_data (GTK_OBJECT (vi_screen->vadj), vi_screen);
437 gtk_object_unref (GTK_OBJECT (vi_screen->vadj));
440 if (vi_screen->vadj != vadj)
442 vi_screen->vadj = vadj;
443 gtk_object_ref (GTK_OBJECT (vi_screen->vadj));
444 gtk_object_sink (GTK_OBJECT (vi_screen->vadj));
447 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "changed",
448 (GtkSignalFunc) gtk_vi_screen_adjustment,
449 vi_screen);
450 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "value_changed",
451 (GtkSignalFunc) gtk_vi_screen_adjustment,
452 vi_screen);
453 gtk_signal_connect (GTK_OBJECT (vi_screen->vadj), "disconnect",
454 (GtkSignalFunc) gtk_vi_screen_disconnect,
455 vi_screen);
456 gtk_vi_screen_adjustment (vadj, vi_screen);
461 static void
462 gtk_vi_screen_realize (GtkWidget *widget)
464 GtkViScreen *vi;
465 GdkWindowAttr attributes;
466 gint attributes_mask;
468 g_return_if_fail (widget != NULL);
469 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
471 vi = GTK_VI_SCREEN (widget);
472 GTK_WIDGET_SET_FLAGS (vi, GTK_REALIZED);
474 attributes.window_type = GDK_WINDOW_CHILD;
475 attributes.x = widget->allocation.x;
476 attributes.y = widget->allocation.y;
477 attributes.width = widget->allocation.width;
478 attributes.height = widget->allocation.height;
479 attributes.wclass = GDK_INPUT_OUTPUT;
480 attributes.visual = gtk_widget_get_visual (widget);
481 attributes.colormap = gtk_widget_get_colormap (widget);
482 attributes.event_mask = gtk_widget_get_events (widget);
483 attributes.event_mask |= (GDK_EXPOSURE_MASK |
484 GDK_BUTTON_PRESS_MASK |
485 GDK_BUTTON_RELEASE_MASK |
486 GDK_BUTTON_MOTION_MASK |
487 GDK_ENTER_NOTIFY_MASK |
488 GDK_LEAVE_NOTIFY_MASK |
489 GDK_KEY_PRESS_MASK);
490 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
492 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
493 gdk_window_set_user_data (widget->window, vi);
495 attributes.x = (widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM);
496 attributes.y = (widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM);
497 attributes.width = MAX (1, (gint)widget->allocation.width - (gint)attributes.x * 2);
498 attributes.height = MAX (1, (gint)widget->allocation.height - (gint)attributes.y * 2);
500 vi->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
501 gdk_window_set_user_data (vi->text_area, vi);
503 widget->style = gtk_style_attach (widget->style, widget->window);
505 /* Can't call gtk_style_set_background here because it's handled specially */
506 gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
507 gdk_window_set_background (vi->text_area, &widget->style->base[GTK_STATE_NORMAL]);
509 vi->gc = gdk_gc_new (vi->text_area);
510 /* What's this ? */
511 gdk_gc_set_exposures (vi->gc, TRUE);
512 gdk_gc_set_foreground (vi->gc, &widget->style->text[GTK_STATE_NORMAL]);
514 vi->reverse_gc = gdk_gc_new (vi->text_area);
515 gdk_gc_set_foreground (vi->reverse_gc, &widget->style->base[GTK_STATE_NORMAL]);
517 gdk_window_show (vi->text_area);
519 recompute_geometry (vi);
522 static void
523 gtk_vi_screen_size_request (GtkWidget *widget,
524 GtkRequisition *requisition)
526 gint xthickness;
527 gint ythickness;
528 gint char_height;
529 gint char_width;
530 GtkViScreen *vi;
532 g_return_if_fail (widget != NULL);
533 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
534 g_return_if_fail (requisition != NULL);
536 vi = GTK_VI_SCREEN (widget);
538 xthickness = widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM;
539 ythickness = widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM;
541 vi->ch_ascent = widget->style->font->ascent;
542 vi->ch_height = (widget->style->font->ascent + widget->style->font->descent) + 1;
543 vi->ch_width = gdk_text_width (widget->style->font, "A", 1);
544 char_height = DEFAULT_VI_SCREEN_HEIGHT_LINES * vi->ch_height;
545 char_width = DEFAULT_VI_SCREEN_WIDTH_CHARS * vi->ch_width;
547 requisition->width = char_width + xthickness * 2;
548 requisition->height = char_height + ythickness * 2;
551 static void
552 gtk_vi_screen_size_allocate (GtkWidget *widget,
553 GtkAllocation *allocation)
555 GtkViScreen *vi;
557 g_return_if_fail (widget != NULL);
558 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
559 g_return_if_fail (allocation != NULL);
561 vi = GTK_VI_SCREEN (widget);
563 widget->allocation = *allocation;
564 if (GTK_WIDGET_REALIZED (widget))
566 gdk_window_move_resize (widget->window,
567 allocation->x, allocation->y,
568 allocation->width, allocation->height);
570 gdk_window_move_resize (vi->text_area,
571 widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM,
572 widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM,
573 MAX (1, (gint)widget->allocation.width - (gint)(widget->style->klass->xthickness +
574 (gint)VI_SCREEN_BORDER_ROOM) * 2),
575 MAX (1, (gint)widget->allocation.height - (gint)(widget->style->klass->ythickness +
576 (gint)VI_SCREEN_BORDER_ROOM) * 2));
578 recompute_geometry (vi);
583 static void
584 gtk_vi_screen_adjustment (GtkAdjustment *adjustment,
585 GtkViScreen *vi_screen)
587 g_return_if_fail (adjustment != NULL);
588 g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
589 g_return_if_fail (vi_screen != NULL);
590 g_return_if_fail (GTK_IS_VI_SCREEN (vi_screen));
595 static void
596 gtk_vi_screen_draw (GtkWidget *widget,
597 GdkRectangle *area)
599 g_return_if_fail (widget != NULL);
600 g_return_if_fail (GTK_IS_VI_SCREEN (widget));
601 g_return_if_fail (area != NULL);
603 if (GTK_WIDGET_DRAWABLE (widget))
605 expose_text (GTK_VI_SCREEN (widget), area, TRUE);
606 gtk_widget_draw_focus (widget);
610 static gint
611 gtk_vi_screen_expose (GtkWidget *widget,
612 GdkEventExpose *event)
614 g_return_val_if_fail (widget != NULL, FALSE);
615 g_return_val_if_fail (GTK_IS_VI_SCREEN (widget), FALSE);
616 g_return_val_if_fail (event != NULL, FALSE);
618 if (event->window == GTK_VI_SCREEN (widget)->text_area)
620 expose_text (GTK_VI_SCREEN (widget), &event->area, TRUE);
622 else if (event->count == 0)
624 gtk_widget_draw_focus (widget);
627 return FALSE;
630 static void
631 recompute_geometry (GtkViScreen* vi)
633 //gint xthickness;
634 //gint ythickness;
635 gint height;
636 gint width;
637 gint rows, cols;
638 gint i;
640 //xthickness = widget->style->klass->xthickness + VI_SCREEN_BORDER_ROOM;
641 //ythickness = widget->style->klass->ythickness + VI_SCREEN_BORDER_ROOM;
643 gdk_window_get_size (vi->text_area, &width, &height);
645 rows = height / vi->ch_height;
646 cols = width / vi->ch_width;
648 if (rows == vi->rows && cols == vi->cols)
649 return;
651 vi->marked_x = vi->cols = cols;
652 vi->marked_y = vi->rows = rows;
653 vi->marked_maxx = 0;
654 vi->marked_maxy = 0;
656 g_free(vi->chars);
657 vi->chars = (CHAR_T*)g_new(gchar, (vi->rows+1)*vi->cols * sizeof(CHAR_T));
658 STRSET(vi->chars, ' ', (vi->rows+1)*vi->cols);
659 g_free(vi->endcol);
660 vi->endcol = g_new(guchar, vi->rows*vi->cols);
661 g_free(vi->reverse);
662 vi->reverse = g_new(guchar, vi->rows*vi->cols);
663 memset(vi->reverse, 0, vi->rows*vi->cols);
665 gtk_signal_emit(GTK_OBJECT(vi), vi_screen_signals[RESIZED], vi->rows, vi->cols);
668 static void
669 expose_text (GtkViScreen* vi, GdkRectangle *area, gboolean cursor)
671 gint ymax;
672 gint xmax, xmin;
674 gdk_window_clear_area (vi->text_area, area->x, area->y,
675 area->width, area->height);
676 ymax = MIN((area->y + area->height + vi->ch_height - 1) / vi->ch_height,
677 vi->rows);
678 xmin = area->x / vi->ch_width;
679 xmax = MIN((area->x + area->width + vi->ch_width - 1) / vi->ch_width,
680 vi->cols);
681 draw_lines(vi, area->y / vi->ch_height, xmin, ymax, xmax);
684 #define Inverse(screen,y,x) \
685 ((*FlagAt(screen,y,x) == COLOR_STANDOUT) ^ \
686 (screen->cury == y && screen->curx == x))
688 static void
689 draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
691 gint y, x, len, blen, xpos;
692 CHAR_T *line;
693 GdkGC *fg, *bg;
694 GdkFont *font;
695 gchar buf[2];
696 gchar *p;
697 gboolean pango;
699 for (y = ymin, line = vi->chars + y*vi->cols;
700 y < ymax; ++y, line += vi->cols) {
701 for (x = 0, xpos = 0; xpos <= xmin; ++x)
702 xpos += CHAR_WIDTH(NULL, *(line+x));
703 --x;
704 xpos -= CHAR_WIDTH(NULL, *(line+x));
705 for (; xpos < xmax; x+=len, xpos+= blen) {
706 gchar inverse;
707 inverse = Inverse(vi,y,x);
708 len = 1;
709 if (sizeof(CHAR_T) == sizeof(gchar))
710 for (; x+len < xmax &&
711 Inverse(vi,y,x+len) == inverse; ++len);
712 if (inverse) {
713 fg = vi->reverse_gc;
714 bg = vi->gc;
715 } else {
716 bg = vi->reverse_gc;
717 fg = vi->gc;
719 pango = 0;
720 if (INTIS9494(*(line+x))) {
721 font = gb_font;
722 buf[0] = INT9494R(*(line+x));
723 buf[1] = INT9494C(*(line+x));
724 p = buf;
725 blen = 2;
726 } else if (INTISUCS(*(line+x))) {
727 #ifdef HAVE_PANGO
728 if (!vi->conx) {
729 PangoFontDescription font_description;
731 font_description.family_name = g_strdup ("monospace");
732 font_description.style = PANGO_STYLE_NORMAL;
733 font_description.variant = PANGO_VARIANT_NORMAL;
734 font_description.weight = 500;
735 font_description.stretch = PANGO_STRETCH_NORMAL;
736 font_description.size = 15000;
738 vi->conx = pango_x_get_context (GDK_DISPLAY ());
739 pango_context_set_font_description (vi->conx,
740 &font_description);
741 vi->alist = pango_attr_list_new();
743 blen = CHAR_WIDTH(NULL, *(line+x));
744 pango = 1;
745 if (0)
746 #endif
748 font = tfw;
749 buf[0] = *(line+x) >> 8;
750 buf[1] = (*(line+x)) & 0xFF;
751 p = buf;
752 blen = 2;
754 } else {
755 font = GTK_WIDGET(vi)->style->font;
756 if (sizeof(CHAR_T) == sizeof(gchar))
757 p = (gchar*)line+x;
758 else {
759 buf[0] = *(line+x);
760 p = buf;
762 blen = len;
764 gdk_draw_rectangle(vi->text_area, bg, 1, xpos * vi->ch_width,
765 y * vi->ch_height, blen * vi->ch_width,
766 vi->ch_height);
767 /* hack to not display half a wide character that wasn't
768 * removed.
770 if (!pango)
771 gdk_draw_text (vi->text_area, font, fg,
772 xpos * vi->ch_width,
773 y * vi->ch_height + vi->ch_ascent,
774 p, blen);
775 #ifdef HAVE_PANGO
776 else {
777 PangoGlyphString *gs;
778 GList *list;
779 PangoItem *item;
780 char buf[3];
781 int len;
783 len = ucs2utf8(line+x, 1, buf);
784 list = pango_itemize(vi->conx, buf, len, vi->alist);
785 item = list->data;
786 gs = pango_glyph_string_new ();
787 pango_shape(buf, len, &item->analysis, gs);
789 pango_x_render(GDK_DISPLAY (),
790 GDK_WINDOW_XWINDOW(vi->text_area), GDK_GC_XGC(fg),
791 item->analysis.font, gs, xpos * vi->ch_width,
792 y * vi->ch_height + vi->ch_ascent);
794 #endif
799 static void
800 mark_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax)
802 if (ymin < vi->marked_y) vi->marked_y = ymin;
803 if (xmin < vi->marked_x) vi->marked_x = xmin;
804 if (ymax > vi->marked_maxy) vi->marked_maxy = ymax;
805 if (xmax > vi->marked_maxx) vi->marked_maxx = xmax;