From 407d4f3888db1194fd75a3d6d1b94d0d558f5ac5 Mon Sep 17 00:00:00 2001 From: skimo Date: Sun, 27 Aug 2000 17:15:04 +0000 Subject: [PATCH] Preliminary Unicode displaying. Assumes pango for now and assumes every unicode character is wide. Will need some cleaning up. --- common/conv.c | 54 ++++++++++++++++++++++++++++++++++++++++++-- common/conv.h | 2 ++ common/util2.c | 20 +++++++++++++++++ dist/acconfig.h | 5 ++++- dist/config.h.in | 3 +++ dist/configure.in | 7 ++++++ gtk/gtkviscreen.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++------- gtk/gtkviscreen.h | 4 ++++ 8 files changed, 151 insertions(+), 11 deletions(-) diff --git a/common/conv.c b/common/conv.c index 3e479164..6d8dc3d8 100644 --- a/common/conv.c +++ b/common/conv.c @@ -10,7 +10,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "$Id: conv.c,v 1.6 2000/07/23 17:32:16 skimo Exp $ (Berkeley) $Date: 2000/07/23 17:32:16 $"; +static const char sccsid[] = "$Id: conv.c,v 1.7 2000/08/27 17:15:04 skimo Exp $ (Berkeley) $Date: 2000/08/27 17:15:04 $"; #endif /* not lint */ #include @@ -82,7 +82,7 @@ gb2int(CONV *conv, const char * str, ssize_t len, CHAR_T **tostr, size_t *tolen, for (i = 0, j = 0; i < len; ++i) { if (str[i] & 0x80) { - if (i+1 < len && str[i] & 0x80) { + if (i+1 < len && str[i+1] & 0x80) { (*tostr)[j++] = INT9494(F_GB,str[i]&0x7F,str[i+1]&0x7F); ++i; } else { @@ -116,10 +116,56 @@ int2gb(CONV *conv, const CHAR_T * str, ssize_t len, char **tostr, size_t *tolen, return 0; } +int +utf82int(CONV *conv, const char * str, ssize_t len, CHAR_T **tostr, size_t *tolen, size_t *blen) +{ + int i, j; + CHAR_T c; + + BINC_RETW(NULL, *tostr, *blen, len); + + for (i = 0, j = 0; i < len; ++i) { + if (str[i] & 0x80) { + if ((str[i] & 0xe0) == 0xc0 && i+1 < len && str[i+1] & 0x80) { + c = (str[i] & 0x1f) << 6; + c |= (str[i+1] & 0x3f); + (*tostr)[j++] = c; + ++i; + } else if ((str[i] & 0xf0) == 0xe0 && i+2 < len && + str[i+1] & 0x80 && str[i+2] & 0x80) { + c = (str[i] & 0xf) << 12; + c |= (str[i+1] & 0x3f) << 6; + c |= (str[i+2] & 0x3f); + (*tostr)[j++] = c; + i += 2; + } else { + (*tostr)[j++] = INTILL(str[i]); + } + } else + (*tostr)[j++] = str[i]; + } + *tolen = j; + + return 0; +} + +int +int2utf8(CONV *conv, const CHAR_T * str, ssize_t len, char **tostr, size_t *tolen, size_t *blen) +{ + BINC_RET(NULL, *tostr, *blen, len * 3); + + *tolen = ucs2utf8(str, len, *tostr); + + return 0; +} + + CONV default_conv = { 0, 0, default_char2int, default_int2char, default_char2int, default_int2char, default_int2disp }; CONV gb_conv = { 0, 0, default_char2int, default_int2char, gb2int, int2gb, default_int2disp }; +CONV utf8_conv = { 0, 0, default_char2int, default_int2char, + utf82int, int2utf8, default_int2disp }; void conv_init (SCR *orig, SCR *sp) @@ -141,6 +187,10 @@ conv_enc (SCR *sp, char *enc) sp->conv = &gb_conv; return 0; } + if (!strcmp(enc,"UTF-8")) { + sp->conv = &utf8_conv; + return 0; + } return 1; } diff --git a/common/conv.h b/common/conv.h index dbf9cbc6..270056f3 100644 --- a/common/conv.h +++ b/common/conv.h @@ -8,6 +8,8 @@ #define INT9494(f,r,c) ((f) << 16) | ((r) << 8) | (c) #define INTIS9494(c) !!(((c) >> 16) & 0x7F) +#define INTISUCS(c) ((c & ~0x7F) && !(((c) >> 16) & 0x7F)) +#define INTUCS(c) (c) #define INT9494F(c) ((c) >> 16) & 0x7F #define INT9494R(c) ((c) >> 8) & 0x7F #define INT9494C(c) (c) & 0x7F diff --git a/common/util2.c b/common/util2.c index 5b22b550..7f98825b 100644 --- a/common/util2.c +++ b/common/util2.c @@ -26,3 +26,23 @@ v_strset(CHAR_T *s, CHAR_T c, size_t n) return ss; } +int +ucs2utf8(const CHAR_T *src, size_t len, char *dst) +{ + int i, j; + + for (i = 0, j = 0; i < len; ++i) { + if (src[i] < 0x80) + dst[j++] = src[i]; + else if (src[i] < 0x800) { + dst[j++] = (src[i] >> 6) | 0xc0; + dst[j++] = (src[i] & 0x3f) | 0x80; + } else { + dst[j++] = (src[i] >> 12) | 0xe0; + dst[j++] = ((src[i] >> 6) & 0x3f) | 0x80; + dst[j++] = (src[i] & 0x3f) | 0x80; + } + } + + return j; +} diff --git a/dist/acconfig.h b/dist/acconfig.h index 3e73008e..d317f5f2 100644 --- a/dist/acconfig.h +++ b/dist/acconfig.h @@ -1,4 +1,4 @@ -/* $Id: acconfig.h,v 8.23 2000/07/14 14:29:18 skimo Exp $ (Berkeley) $Date: 2000/07/14 14:29:18 $ */ +/* $Id: acconfig.h,v 8.24 2000/08/27 17:15:05 skimo Exp $ (Berkeley) $Date: 2000/08/27 17:15:05 $ */ /* Define to `int' if doesn't define. */ #undef ssize_t @@ -54,6 +54,9 @@ /* Define if you have flock(2) style locking. */ #undef HAVE_LOCK_FLOCK +/* Define is appropriate pango is available */ +#undef HAVE_PANGO + /* Define if you want to compile in the Perl interpreter. */ #undef HAVE_PERL_INTERP diff --git a/dist/config.h.in b/dist/config.h.in index ab2e9a0a..997a38e1 100644 --- a/dist/config.h.in +++ b/dist/config.h.in @@ -88,6 +88,9 @@ /* Define if you have flock(2) style locking. */ #undef HAVE_LOCK_FLOCK +/* Define is appropriate pango is available */ +#undef HAVE_PANGO + /* Define if you want to compile in the Perl interpreter. */ #undef HAVE_PERL_INTERP diff --git a/dist/configure.in b/dist/configure.in index 3b3f6ebc..64570bb0 100644 --- a/dist/configure.in +++ b/dist/configure.in @@ -215,6 +215,7 @@ AC_ARG_ENABLE(widechar, if test "$vi_cv_widechar" = "yes"; then AC_DEFINE(USE_WIDECHAR) fi +AC_MSG_RESULT($vi_cv_widechar) dnl If the user wants a Gtk IPC front-end for nvi, build it. AC_SUBST(vi_ipc) @@ -242,6 +243,12 @@ if test "$vi_cv_gtk" = "yes"; then AC_DEFINE(HAVE_ZVT) fi LIBS="$SAVELIBS" + AC_PATH_PROG(vi_cv_pango_config, pango-config, no) + if test "$vi_cv_pango_config" != "no"; then + PANGOLIBS=`$vi_cv_pango_config --libs pangox` + GTKLIBS="$PANGOLIBS $GTKLIBS" + AC_DEFINE(HAVE_PANGO) + fi # AC_PATH_PROG(vi_cv_gnome_config, gnome-config, no) # if test "$vi_cv_gnome_config" != "no"; then # ZVTLIBS=`$vi_cv_gnome_config zvt --libs` diff --git a/gtk/gtkviscreen.c b/gtk/gtkviscreen.c index 718be793..ca976b02 100644 --- a/gtk/gtkviscreen.c +++ b/gtk/gtkviscreen.c @@ -4,6 +4,11 @@ #include #include #include "gtkviscreen.h" +#include + +#include +#include + #include "../common/conv.h" void * v_strset __P((CHAR_T *s, CHAR_T c, size_t n)); @@ -59,6 +64,7 @@ static GtkWidgetClass *parent_class = NULL; static guint vi_screen_signals[LAST_SIGNAL] = { 0 }; static GdkFont *gb_font; +static GdkFont *tf; #define CharAt(scr,y,x) scr->chars + (y) * scr->cols + x #define FlagAt(scr,y,x) (scr->reverse + (y) * scr->cols + x) @@ -142,6 +148,7 @@ gtk_vi_screen_addstr(GtkViScreen *vi, const char *str, int len) vi->curx = 0; } } else vi->curx += len; + if (x < vi->cols) endcol[x] = vi->cols; } void @@ -161,7 +168,7 @@ gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len) x = vi->curx; startcol = x ? endcol[x-1] : -1; for (col = startcol; x < vi->curx + len; ++x) - endcol[x] = col += INTIS9494(*(line+x)) ? 2 : 1; + endcol[x] = col += CHAR_WIDTH(NULL, *(line+x)); mark_lines(vi, vi->cury, startcol+1, vi->cury+1, endcol[x-1]+1); @@ -173,6 +180,7 @@ gtk_vi_screen_waddstr(GtkViScreen *vi, const CHAR_T *str, int len) vi->curx = 0; } } else vi->curx += len; + if (x < vi->cols) endcol[x] = vi->cols; } void @@ -298,6 +306,7 @@ gtk_vi_screen_class_init (GtkViScreenClass *class) class->resized = NULL; gb_font = gdk_font_load ("-*-*-*-*-*-*-16-*-*-*-*-*-gb2312.1980-*"); + tf = gdk_font_load ("-misc-fixed-*-*-*-*-16-*-*-*-*-*-iso10646-*"); } static void @@ -354,6 +363,8 @@ gtk_vi_screen_init (GtkViScreen *vi) vi->cols = 0; vi->rows = 0; + vi->conx = NULL; + style = gtk_style_copy(GTK_WIDGET(vi)->style); gdk_font_unref(style->font); style->font = gdk_font_load("-*-fixed-*-*-*-*-16-*-*-*-*-*-iso8859-*"); @@ -664,12 +675,13 @@ draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax) GdkFont *font; gchar buf[2]; gchar *p; + gboolean pango; for (y = ymin, line = vi->chars + y*vi->cols; y < ymax; ++y, line += vi->cols) { for (x = 0, xpos = 0; xpos <= xmin; ++x) - xpos += INTIS9494(*(line+x)) ? 2 : 1; - xpos -= INTIS9494(*(line+--x)) ? 2 : 1; + xpos += CHAR_WIDTH(NULL, *(line+x)); + xpos -= CHAR_WIDTH(NULL, *(line+--x)); for (; xpos < xmax; x+=len, xpos+= blen) { gchar inverse; inverse = Inverse(vi,y,x); @@ -684,12 +696,31 @@ draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax) bg = vi->reverse_gc; fg = vi->gc; } + pango = 0; if (INTIS9494(*(line+x))) { font = gb_font; buf[0] = INT9494R(*(line+x)); buf[1] = INT9494C(*(line+x)); p = buf; blen = 2; + } else if (INTISUCS(*(line+x))) { + if (!vi->conx) { + PangoFontDescription font_description; + + font_description.family_name = g_strdup ("monospace"); + font_description.style = PANGO_STYLE_NORMAL; + font_description.variant = PANGO_VARIANT_NORMAL; + font_description.weight = 500; + font_description.stretch = PANGO_STRETCH_NORMAL; + font_description.size = 16000; + + vi->conx = pango_x_get_context (GDK_DISPLAY ()); + pango_context_set_font_description (vi->conx, + &font_description); + vi->alist = pango_attr_list_new(); + } + blen = CHAR_WIDTH(NULL, *(line+x)); + pango = 1; } else { font = GTK_WIDGET(vi)->style->font; if (sizeof(CHAR_T) == sizeof(gchar)) @@ -706,11 +737,31 @@ draw_lines(GtkViScreen *vi, gint ymin, gint xmin, gint ymax, gint xmax) /* hack to not display half a wide character that wasn't * removed. */ - if (xpos + blen <= vi->cols) - gdk_draw_text (vi->text_area, font, fg, - xpos * vi->ch_width, - y * vi->ch_height + vi->ch_ascent, - p, blen); + if (xpos + blen <= vi->cols) { + if (!pango) + gdk_draw_text (vi->text_area, font, fg, + xpos * vi->ch_width, + y * vi->ch_height + vi->ch_ascent, + p, blen); + else { + PangoGlyphString *gs; + GList *list; + PangoItem *item; + char buf[3]; + int len; + + len = ucs2utf8(line+x, 1, buf); + list = pango_itemize(vi->conx, buf, len, vi->alist); + item = list->data; + gs = pango_glyph_string_new (); + pango_shape(buf, len, &item->analysis, gs); + + pango_x_render(GDK_DISPLAY (), + GDK_WINDOW_XWINDOW(vi->text_area), GDK_GC_XGC(fg), + item->analysis.font, gs, xpos * vi->ch_width, + y * vi->ch_height + vi->ch_ascent); + } + } } } } diff --git a/gtk/gtkviscreen.h b/gtk/gtkviscreen.h index bc7ed92c..06ba110b 100644 --- a/gtk/gtkviscreen.h +++ b/gtk/gtkviscreen.h @@ -4,6 +4,7 @@ #include "config.h" #include "port.h" #include "../common/multibyte.h" +#include #define GTK_TYPE_VI_SCREEN (gtk_vi_screen_get_type ()) #define GTK_VI_SCREEN(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_VI_SCREEN, GtkViScreen)) @@ -35,6 +36,9 @@ struct _GtkViScreen gint curx, cury; /* character position */ gint lastx, lasty; gint marked_x, marked_y, marked_maxx, marked_maxy; + + PangoContext *conx; + PangoAttrList* alist; }; struct _GtkViScreenClass -- 2.11.4.GIT