× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



On Tue, May 15, 2001 at 03:33:31PM -0400, Jay 'Eraserhead' Felice wrote:

> The idea was to perfect the Python bindings in tn5250, add Python bindings
> for the Gtk5250Terminal widget (compatible with pygtk/pygnome), then you
> could script all sorts of CA-like features in a very high level language
> with built in support for the 5250 data stream and Gnome.

I wrote gnome-5250 referring to the package, but like you I'm
more interested in developing the Gtk5250Terminal widget.  I find your
idea to implement the terminal using python very promising.

Anyway here are my patches trying mainly to fix the problem of garbage
on top and bottom of the screen.  Ideas for this work are drawn from
the gnome terminal widget zvt.

  === Changelog entry ===
2001-05-16  Gabriele Favalessa  <favalex@libero.it>

        * gtk5250terminal.c: Uses real font metrics.

        Text containing chars with same attributes is drawn in one step
        instead that char by char.

        Avoid erasing background before painting text by using
        XDrawImageText.

        Added mapping for function keys from GDK_F13 to GDK_F24.
  =======================
  
Ciao
   Gabriele

--- ../gnome-5250/gtk5250terminal.c     Mon May 22 18:37:28 2000
+++ gtk5250terminal.c   Wed May 16 10:54:30 2001
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
 #include "gtk5250terminal.h"
 
 #define DEFAULT_FONT "fixed"
@@ -54,7 +55,8 @@
     GtkAllocation *allocation);
 static gint gtk5250_terminal_expose (GtkWidget *widget, GdkEventExpose *event);
 static void gtk5250_terminal_destroy (GtkObject *object);
-static void gtk5250_terminal_draw_char (Gtk5250Terminal *term, gint y, gint x, 
guint ch);
+static void gtk5250_terminal_draw_chars (Gtk5250Terminal *term, gint y, 
+                                        gint x, const gint* chars, gint len);
 static void gtk5250_terminal_blink_timeout (Gtk5250Terminal *term);
 static void gtk5250_terminal_map (GtkWidget *widget);
 static void gtk5250_terminal_unmap (GtkWidget *widget);
@@ -75,6 +77,7 @@
 static int gtkterm_getkey (Tn5250Terminal *This);
 static void gtkterm_beep (Tn5250Terminal *This);
 static int gtkterm_config (Tn5250Terminal *This, Tn5250Config *config);
+static void draw_text_with_bg (GdkDrawable* drawable, GdkFont* font, GdkGC* 
+gc, gint x, gint y, const gchar* text, gint text_length);
 
 static GtkWidgetClass *parent_class = NULL;
 
@@ -171,23 +174,25 @@
  */
 static void gtk5250_terminal_init (Gtk5250Terminal *term)
 {
+  XFontStruct *xfont;
   gint n;
 
   /* FIXME: Do we have to load our fonts here? */
   term->font_80 = gdk_font_load (DEFAULT_FONT);
   gdk_font_ref (term->font_80);
-  term->font_80_w = gdk_char_width (term->font_80, 'M') + 1;
-  term->font_80_h = gdk_char_height (term->font_80, 'M');
+  xfont = (XFontStruct *)GDK_FONT_XFONT(term->font_80);
+  term->font_80_w = xfont->max_bounds.width;
+  term->font_80_h = term->font_80->ascent + term->font_80->descent;
 
   term->font_132 = gdk_font_load (DEFAULT_FONT);
   gdk_font_ref (term->font_132);
-  term->font_132_w = gdk_char_width (term->font_132, 'M') + 1;
-  term->font_132_h = gdk_char_height (term->font_132, 'M');
+  xfont = (XFontStruct *)GDK_FONT_XFONT(term->font_132);
+  term->font_132_w = xfont->max_bounds.width;
+  term->font_132_h = term->font_132->ascent + term->font_132->descent;
 
   term->config = NULL;
   term->store = NULL;
   term->client_window = NULL;
-  term->bg_gc = NULL;
   term->fg_gc = NULL;
   term->color_ctx = NULL;
   term->blink_timeout = 0;
@@ -288,7 +293,6 @@
   term->client_window = gdk_window_new (widget->window, &attributes, 
attributes_mask);
   gdk_window_set_user_data (term->client_window, term);
 
-  term->bg_gc = gdk_gc_new (term->client_window);
   term->fg_gc = gdk_gc_new (term->client_window);
   term->color_ctx = gdk_color_context_new (gtk_widget_get_visual (widget),
        gtk_widget_get_colormap (widget));
@@ -300,7 +304,7 @@
       term->colors, &nallocated);
 
   term->store = gdk_pixmap_new (term->client_window, term->font_80_w * 80,
-      (term->font_80_h + 4) * 26, -1);
+      term->font_80_h * 26, -1);
 
   term->blink_timeout = gtk_timeout_add (500,
       (GtkFunction)gtk5250_terminal_blink_timeout, term);
@@ -330,9 +334,6 @@
   gdk_color_context_free (term->color_ctx);
   term->color_ctx = NULL;
 
-  gdk_gc_destroy (term->bg_gc);
-  term->bg_gc = NULL;
-
   gdk_gc_destroy (term->fg_gc);
   term->fg_gc = NULL;
 
@@ -357,13 +358,13 @@
   if (term->w != 132)
     {
       requisition->width = term->font_80_w * term->w + (2 * BORDER_WIDTH);
-      requisition->height = (term->font_80_h + 4) * (term->h + 2) +
+      requisition->height = term->font_80_h * (term->h + 1) +
        (2 * BORDER_WIDTH);
     }
   else
     {
       requisition->width = term->font_132_w * term->w + (2 * BORDER_WIDTH);
-      requisition->height = (term->font_132_h + 4) * (term->h + 2) +
+      requisition->height = term->font_132_h * (term->h + 1) +
        (2 * BORDER_WIDTH);
     }
 }
@@ -401,7 +402,7 @@
 static gint gtk5250_terminal_expose (GtkWidget *widget, GdkEventExpose *event)
 {
   Gtk5250Terminal *term;
-  GdkColor pen;
+  GdkColor pen, black;
   gint y, x;
   GdkFont *font;
   gint font_w, font_h;
@@ -433,37 +434,76 @@
   pen.pixel = term->colors[(A_5250_TURQ >> 8) - 1];
   gdk_gc_set_foreground (term->fg_gc, &pen);
   gdk_draw_line (term->store,
-      term->fg_gc,
-      0, (font_h + 4) * term->h + 4, 
-      widget->allocation.width - (2 * BORDER_WIDTH),
-      (font_h + 4) * term->h + 4 );
+                term->fg_gc,
+                0, font_h * term->h, 
+                widget->allocation.width - (2 * BORDER_WIDTH),
+                font_h * term->h);
 
   for (y = 0; y < 27; y++)
     {
+      int span_start = -1;
+      int span_flag; 
+      int span_len;
+
       for (x = 0; x < 132; x++)
        {
-         if (((term->cells[y][x] & A_5250_DIRTYFLAG) != 0) ||
-           ((term->cells[y][x] & A_5250_BLINK) != 0) ||
-           (term->cy == y && term->cx == x))
+         int c = term->cells[y][x];
+
+         if (((c & A_5250_DIRTYFLAG) != 0) ||
+             ((c & A_5250_BLINK) != 0) ||
+             (term->cy == y && term->cx == x))
            {
-             gtk5250_terminal_draw_char (term, y, x, term->cells[y][x]);
-             term->cells[y][x] &= ~((guint)A_5250_DIRTYFLAG);
+             if (span_start == -1)
+               {
+                 span_start = x;
+                 span_flag = c & 0xff00;
+                 span_len = 1;
+               }
+             else if ((x == (span_start + span_len)) 
+                      && (span_flag == (c & ~0xff)))
+               span_len++;
+             else
+               {
+                 int i;
+
+                 gtk5250_terminal_draw_chars (term, 
+                                              y, span_start, 
+                                              &term->cells[y][span_start],
+                                              span_len);
+                 for (i = 0; i < span_len; i++)
+                   term->cells[y][span_start+i] &= ~((guint)A_5250_DIRTYFLAG);
+
+                 span_start = x;
+                 span_flag = c & 0xff00;
+                 span_len = 1;
+               }
            }
        }
+
+      if (span_start != -1 && span_len > 0)
+       {
+         int i;
+
+         gtk5250_terminal_draw_chars (term, 
+                                      y, span_start, 
+                                      &term->cells[y][span_start],
+                                      span_len);
+
+         for (i = 0; i < span_len; i++)
+           term->cells[y][span_start+i] &= ~((guint)A_5250_DIRTYFLAG);
+       }
     }
 
   if (GTK_WIDGET_DRAWABLE (widget))
     {
       /* Draw indicators. */
-       gdk_draw_rectangle (term->store, term->bg_gc, 1,
-         0, term->h * (font_h + 4) + 5,
-         (term->w * font_w), font_h + 4);
-
        pen.pixel = term->colors[(A_5250_WHITE >> 8) - 1];
+       black.pixel = term->colors[(A_5250_BLACK >> 8) - 1];
        gdk_gc_set_foreground (term->fg_gc, &pen);
-       gdk_draw_text (term->store, font, term->fg_gc,
-          1, (term->h + 1) * (font_h + 4) + 4,
-          term->ind_buf, 80);
+       gdk_gc_set_background (term->fg_gc, &black);
+       draw_text_with_bg (term->store, font, term->fg_gc,
+                         1, term->h * font_h + font->ascent + 1,
+                         term->ind_buf, 80);
 
       gdk_draw_pixmap (term->client_window, term->fg_gc,
          term->store,
@@ -476,16 +516,22 @@
   return FALSE;
 }
 
-static void gtk5250_terminal_draw_char (Gtk5250Terminal *term, gint y, gint x, 
guint ch)
+static void gtk5250_terminal_draw_chars (Gtk5250Terminal *term, gint y, 
+                                        gint x, const gint* chars, gint len)
 {
-  GdkColor pen;
+  GdkColor pen, black;
   GtkWidget *widget;
-  GdkGC *fg, *bg;
   gint color_idx;
-  gchar c;
   GdkFont *font;
   gint font_w, font_h;
 
+  GdkGC* gc;
+
+  gint i;
+  gchar buf[132];
+
+  gint ch = chars[0];
+
   if (term->w != 132)
     {
       font_w = term->font_80_w;
@@ -516,8 +562,10 @@
        color_idx = (A_5250_BLUE >> 8) - 1;
     }
 
+  gc = term->fg_gc;
+
   pen.pixel = term->colors[color_idx];
-  gdk_gc_set_foreground (term->fg_gc, &pen);
+  black.pixel = term->colors[(A_5250_BLACK >> 8) - 1];
 
   if ((ch & A_5250_BLINK) != 0 && !term->blink_state)
     {
@@ -527,36 +575,35 @@
   
   if ((ch & A_5250_REVERSE) != 0)
     {
-      bg = term->fg_gc;
-      fg = term->bg_gc;
+      gdk_gc_set_foreground (gc, &black);
+      gdk_gc_set_background (gc, &pen);
     }
   else
     {
-      fg = term->fg_gc;
-      bg = term->bg_gc;
+      gdk_gc_set_foreground (gc, &pen);
+      gdk_gc_set_background (gc, &black);
     }
 
-  gdk_draw_rectangle (term->store, bg, 1,
-      x * font_w, y * (font_h + 4) + 4,
-      font_w, font_h + 4);
-
-  c = (ch & 0x00ff);
-  gdk_draw_text (term->store, font, fg,
-      x * font_w + 1, (y + 1) * (font_h + 4) + 1,
-      &c, 1);
+  for (i = 0; i < len; i++)
+    buf[i] = chars[i] & 0xff;
+
+  draw_text_with_bg (term->store, font, gc,
+                    x*font_w, y*font_h + font->ascent,
+                    buf, len);
 
   if ((ch & A_5250_UNDERLINE) != 0)
     {
-      gdk_draw_line (term->store, fg,
-         x * font_w, (y + 1) * (font_h + 4) + 3,
-         (x + 1) * font_w - 1, (y + 1) * (font_h + 4) + 3);
+      gdk_draw_line (term->store, gc,
+                    x * font_w, (y+1)*font_h - font->descent + 1,
+                    (x + len) * font_w - 1, (y+1)*font_h - font->descent + 1);
     }
 
   if ((ch & A_5250_VERTICAL) != 0)
     {
-      gdk_draw_line (term->store, fg,
-         x * font_w, y * (font_h + 4) + 4,
-         x * font_w, (y + 1) * (font_h + 4) + 3);
+      for (i = 0; i < len; i++)
+       gdk_draw_line (term->store, gc,
+                      (x+i) * font_w, y*font_h,
+                      (x+i) * font_w, (y + 1) * font_h - 1);
     }
 }
 
@@ -747,6 +794,42 @@
     case GDK_F12:
       term->next_keyval = (event->state & GDK_SHIFT_MASK) ? K_F24 : K_F12;
       break;
+    case GDK_F13:
+      term->next_keyval = K_F13;
+      break;
+    case GDK_F14:
+      term->next_keyval = K_F14;
+      break;
+    case GDK_F15:
+      term->next_keyval = K_F15;
+      break;
+    case GDK_F16:
+      term->next_keyval = K_F16;
+      break;
+    case GDK_F17:
+      term->next_keyval = K_F17;
+      break;
+    case GDK_F18:
+      term->next_keyval = K_F18;
+      break;
+    case GDK_F19:
+      term->next_keyval = K_F19;
+      break;
+    case GDK_F20:
+      term->next_keyval = K_F20;
+      break;
+    case GDK_F21:
+      term->next_keyval = K_F21;
+      break;
+    case GDK_F22:
+      term->next_keyval = K_F22;
+      break;
+    case GDK_F23:
+      term->next_keyval = K_F23;
+      break;
+    case GDK_F24:
+      term->next_keyval = K_F24;
+      break;
 
     case GDK_Escape:
       term->next_keyval = (event->state & GDK_SHIFT_MASK) ? K_SYSREQ :
@@ -784,9 +867,11 @@
     case GDK_3270_Enter:    term->next_keyval = K_ENTER; break;
 
     default:
+#if 0
       if (term->next_keyval >= 127)
        g_warning("unhandled key 0x%04X (%s)", term->next_keyval,
            gdk_keyval_name(term->next_keyval));
+#endif
     }
 
   gtk_main_quit();
@@ -904,11 +989,10 @@
       if (This->store)
        gdk_pixmap_unref (This->store);
       This->store = gdk_pixmap_new (This->client_window,
-         font_w * This->w, (font_h + 4) * (This->h + 1) + 10,
-         -1);
+         font_w * This->w, font_h * (This->h + 1) + 1, -1);
       gtk_widget_set_usize ((GtkWidget*) This,
          font_w * This->w + BORDER_WIDTH*2,
-         (font_h + 4) * (This->h + 1) + 10 + BORDER_WIDTH*2);
+         font_h * (This->h + 1) + 1 + BORDER_WIDTH*2);
     }
 
   for(y = 0; y < This->h; y++)
@@ -1049,6 +1133,7 @@
 
 static void gtk5250_terminal_update_from_config (Gtk5250Terminal *This)
 {
+  XFontStruct *xfont;
   const gchar *s;
   
   /* Set the font, width and height, etc. */
@@ -1068,9 +1153,9 @@
     This->font_80 = gdk_font_load (DEFAULT_FONT);
   gdk_font_ref (This->font_80);
 
-  /* FIXME: Get some real font metrics. */
-  This->font_80_w = gdk_char_width (This->font_80, 'M') + 1;
-  This->font_80_h = gdk_char_height (This->font_80, 'M');
+  xfont = (XFontStruct *)GDK_FONT_XFONT(This->font_80);
+  This->font_80_w = xfont->max_bounds.width;
+  This->font_80_h = This->font_80->ascent + This->font_80->descent;
 
   if (This->font_132 != NULL)
     gdk_font_unref (This->font_132);
@@ -1088,9 +1173,61 @@
     This->font_132 = gdk_font_load (DEFAULT_FONT);
 
   gdk_font_ref (This->font_132);
-  /* FIXME: Get some real font metrics. */
-  This->font_132_w = gdk_char_width (This->font_132, 'M') + 1;
-  This->font_132_h = gdk_char_height (This->font_132, 'M');
+
+  xfont = (XFontStruct *)GDK_FONT_XFONT(This->font_132);
+  This->font_132_w = xfont->max_bounds.width;
+  This->font_132_h = This->font_132->ascent + This->font_132->descent;
+}
+
+/* Fill with background color and draw text with foreground color.
+   This is gdk_draw_text with XDrawString replaced by
+   XDrawImageString. */
+static void
+draw_text_with_bg (GdkDrawable *drawable, GdkFont *font, GdkGC *gc, 
+                  gint x, gint y, const gchar *text, gint text_length)
+{
+  GdkWindowPrivate *drawable_private;
+  GdkFontPrivate *font_private;
+  GdkGCPrivate *gc_private;
+
+  g_return_if_fail (drawable != NULL);
+  g_return_if_fail (font != NULL);
+  g_return_if_fail (gc != NULL);
+  g_return_if_fail (text != NULL);
+
+  drawable_private = (GdkWindowPrivate*) drawable;
+  if (drawable_private->destroyed)
+    return;
+  gc_private = (GdkGCPrivate*) gc;
+  font_private = (GdkFontPrivate*) font;
+
+  if (font->type == GDK_FONT_FONT)
+    {
+      XFontStruct *xfont = (XFontStruct *) font_private->xfont;
+      XSetFont(drawable_private->xdisplay, gc_private->xgc, xfont->fid);
+      if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
+       {
+         XDrawImageString (drawable_private->xdisplay, 
+                           drawable_private->xwindow,
+                           gc_private->xgc, x, y, text, text_length);
+       }
+      else
+       {
+         XDrawImageString16 (drawable_private->xdisplay, 
+                             drawable_private->xwindow,
+                             gc_private->xgc, x, y, (XChar2b *) text, 
+                             text_length / 2);
+       }
+    }
+  else if (font->type == GDK_FONT_FONTSET)
+    {
+      XFontSet fontset = (XFontSet) font_private->xfont;
+      XmbDrawImageString (drawable_private->xdisplay, 
+                         drawable_private->xwindow,
+                         fontset, gc_private->xgc, x, y, text, text_length);
+    }
+  else
+    g_error("undefined font type\n");
 }
 
 /* vi:set ts=8 sts=2 sw=2 cindent cinoptions=^-2,p8,{.75s,f0,>4,n-2,:0: */

As an Amazon Associate we earn from qualifying purchases.

This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.