From e64307644dec3440bae9020b8d922457389541cc Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Sat, 27 May 2000 03:41:22 +0000 Subject: [PATCH] Fri May 26 20:43:03 PDT 2000 Michael Jennings Okay, there are a few changes here. First off, I made multi-byte font support the default now, as long as you have ISO 10646 fonts. In order to do this, I made the default encoding type "Latin1" so as not to interfere with 8-bit ISO 8859-1 characters. This means that if you relied on the default multi-byte encoding method to be SJIS, you'll need to update your theme files. I also set it up so that Eterm will ignore SIGHUP, at least until I do something with it (like reloading the theme or something). I fixed the proportional font size algorithm. If there is more than a 3-pixel variance between the minimum and maximum sizes for glyphs in a proportional font, Eterm will set the size to 2 standard deviations above the average width. This is so that they won't look so spread out and ugly, but it still doesn't look perfect. Not much I can do on that front...terminals must have fixed-width columns. And then there's the biggie. I put in the ability to configure the now-infamous font effects. I left a black drop shadow in as the default, but you can now customize it via the --font-fx option or in the config file using "font effects " in the attributes context. You can even use "fx" instead of "effects" for short. So what goes in the part? Well, you have several options. To use a single-color outline, say "outline ". Likewise, a single-color drop shadow is "shadow [corner] "; "bottom_right" is the default corner if you don't specify one. For a 3-D embossed look, "emboss ". The opposite, a carved- out look, can be had with "carved ". (Of course, with those last two, the 3-D look will only work if you choose the colors wisely.) Those are all the shortcuts. The long way is to specify a series of corner/color pairs, like "tl blue" for top-left blue, or "bottom_right green". You can abbreviate using "tl," "tr," "bl," or "br," or you can spell out "top_left," "top_right," "bottom_left," or "bottom_right." If you omit a corner name, the first one defaults to top-left, the second to top-right, and so on as listed above. SVN revision: 2714 --- ChangeLog | 42 +++++++++ configure.in | 146 +++++++++++++++--------------- libmej/strings.c | 6 +- libmej/strings.h | 2 +- src/command.c | 20 ++--- src/font.c | 173 ++++++++++++++++++++++++++++++++++-- src/font.h | 16 ++++ src/menus.h | 1 - src/options.c | 22 +++++ src/pixmap.h | 4 +- src/screen.c | 225 ++++++++++++++++++++++++++++++++++------------- src/screen.h | 3 + src/scrollbar.h | 2 +- 13 files changed, 510 insertions(+), 152 deletions(-) diff --git a/ChangeLog b/ChangeLog index 255d8d3..af0f3c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3560,3 +3560,45 @@ Thu May 4 00:32:45 PDT 2000 Michael Jennings to be faster than the old stuff, probably by quite a bit. ------------------------------------------------------------------------------- +Fri May 26 20:43:03 PDT 2000 Michael Jennings + + Okay, there are a few changes here. First off, I made multi-byte font + support the default now, as long as you have ISO 10646 fonts. In + order to do this, I made the default encoding type "Latin1" so as not + to interfere with 8-bit ISO 8859-1 characters. This means that if you + relied on the default multi-byte encoding method to be SJIS, you'll + need to update your theme files. + + I also set it up so that Eterm will ignore SIGHUP, at least until I do + something with it (like reloading the theme or something). + + I fixed the proportional font size algorithm. If there is more than + a 3-pixel variance between the minimum and maximum sizes for glyphs in + a proportional font, Eterm will set the size to 2 standard deviations + above the average width. This is so that they won't look so spread + out and ugly, but it still doesn't look perfect. Not much I can do on + that front...terminals must have fixed-width columns. + + And then there's the biggie. I put in the ability to configure the + now-infamous font effects. I left a black drop shadow in as the + default, but you can now customize it via the --font-fx option or in + the config file using "font effects " in the attributes + context. You can even use "fx" instead of "effects" for short. + + So what goes in the part? Well, you have several options. + To use a single-color outline, say "outline ". Likewise, a + single-color drop shadow is "shadow [corner] "; "bottom_right" + is the default corner if you don't specify one. For a 3-D embossed + look, "emboss ". The opposite, a carved- + out look, can be had with "carved ". (Of + course, with those last two, the 3-D look will only work if you + choose the colors wisely.) + + Those are all the shortcuts. The long way is to specify a series of + corner/color pairs, like "tl blue" for top-left blue, or + "bottom_right green". You can abbreviate using "tl," "tr," "bl," or + "br," or you can spell out "top_left," "top_right," "bottom_left," or + "bottom_right." If you omit a corner name, the first one defaults to + top-left, the second to top-right, and so on as listed above. + +------------------------------------------------------------------------------- diff --git a/configure.in b/configure.in index 4e32aec..150b448 100644 --- a/configure.in +++ b/configure.in @@ -424,76 +424,84 @@ AC_ARG_WITH(end, MULTICHAR_ENCODING="" AC_MSG_CHECKING(for multi-charset support) AC_ARG_ENABLE(multi-charset, -[ --enable-multi-charset compile with multi-charset support], - if test "$enableval" = "yes" -o "$enableval" = "kanji"; then - AC_MSG_RESULT(kanji) - AC_DEFINE(MULTI_CHARSET) - DEF_FONT_IDX=0 - MULTICHAR_ENCODING="eucj" - FONT0="fixed" - FONT1="8x16" - FONT2="9x18" - FONT3="12x24" - FONT4="13x26" - MFONT0="k14" - MFONT1="jiskan16" - MFONT2="jiskan18" - MFONT3="jiskan24" - MFONT4="jiskan26" - elif test "$enableval" = "euc-kr" -o "$enableval" = "euckr"; then - AC_MSG_RESULT(euckr) - AC_DEFINE(MULTI_CHARSET) - DEF_FONT_IDX=1 - MULTICHAR_ENCODING="euckr" - FONT0="7x14" - FONT1="8x16" - FONT2="9x18" - FONT3="10x20" - FONT4="12x24" - MFONT0="-*-gulim-medium-r-normal--14-*-*-*-*-140-ksc5601.1987-0" - MFONT1="-*-gulim-medium-r-normal--16-*-*-*-*-160-ksc5601.1987-0" - MFONT2="-*-gulim-medium-r-normal--18-*-*-*-*-180-ksc5601.1987-0" - MFONT3="-*-gulim-medium-r-normal--20-*-*-*-*-200-ksc5601.1987-0" - MFONT4="-*-gulim-medium-r-normal--24-*-*-*-*-240-ksc5601.1987-0" - elif test "$enableval" = "utf-8" -o "$enableval" = "utf8"; then - AC_MSG_RESULT(utf-8) - AC_DEFINE(MULTI_CHARSET) - DEF_FONT_IDX=2 - MULTICHAR_ENCODING="utf8" - MFONT0="-misc-fixed-medium-r-normal--7-70-75-75-c-50-iso10646-1" - MFONT1="-misc-fixed-medium-r-normal--10-100-75-75-c-60-iso10646-1" - MFONT2="-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1" - MFONT3="-misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1" - MFONT4="-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1" - FONT0="5x7" - FONT1="6x10" - FONT2="fixed" - FONT3="8x13" - FONT4="9x15" - elif test "$enableval" = "no"; then - AC_MSG_RESULT(no) - DEF_FONT_IDX=2 - FONT0="5x7" - FONT1="6x10" - FONT2="fixed" - FONT3="8x13" - FONT4="9x15" +[ --enable-multi-charset compile with multibyte font support], + if test "$enableval" = "no"; then + MULTI_CHARSET_TYPE="" else - AC_ERROR(invalid value for --enable-multi-charset) - fi, AC_MSG_RESULT(no) - DEF_FONT_IDX=2 - MULTICHAR_ENCODING=none - MFONT0=none - MFONT1=none - MFONT2=none - MFONT3=none - MFONT4=none - FONT0="5x7" - FONT1="6x10" - FONT2="fixed" - FONT3="8x13" - FONT4="9x15" -) + MULTI_CHARSET_TYPE="$enableval" + fi, + if (xlsfonts | grep 10646 >/dev/null 2>&1); then + MULTI_CHARSET_TYPE="unicode" + else + MULTI_CHARSET_TYPE="" + fi + ) + +if test "x$MULTI_CHARSET_TYPE" != "x"; then + if test "$MULTI_CHARSET_TYPE" = "kanji"; then + AC_MSG_RESULT(kanji) + AC_DEFINE(MULTI_CHARSET) + DEF_FONT_IDX=0 + MULTICHAR_ENCODING="eucj" + FONT0="fixed" + FONT1="8x16" + FONT2="9x18" + FONT3="12x24" + FONT4="13x26" + MFONT0="k14" + MFONT1="jiskan16" + MFONT2="jiskan18" + MFONT3="jiskan24" + MFONT4="jiskan26" + elif test "$MULTI_CHARSET_TYPE" = "euc-kr" -o "$MULTI_CHARSET_TYPE" = "euckr"; then + AC_MSG_RESULT(euckr) + AC_DEFINE(MULTI_CHARSET) + DEF_FONT_IDX=1 + MULTICHAR_ENCODING="euckr" + FONT0="7x14" + FONT1="8x16" + FONT2="9x18" + FONT3="10x20" + FONT4="12x24" + MFONT0="-*-gulim-medium-r-normal--14-*-*-*-*-140-ksc5601.1987-0" + MFONT1="-*-gulim-medium-r-normal--16-*-*-*-*-160-ksc5601.1987-0" + MFONT2="-*-gulim-medium-r-normal--18-*-*-*-*-180-ksc5601.1987-0" + MFONT3="-*-gulim-medium-r-normal--20-*-*-*-*-200-ksc5601.1987-0" + MFONT4="-*-gulim-medium-r-normal--24-*-*-*-*-240-ksc5601.1987-0" + elif test "$MULTI_CHARSET_TYPE" = "unicode" -o "$MULTI_CHARSET_TYPE" = "utf-8" -o "$MULTI_CHARSET_TYPE" = "utf8"; then + AC_MSG_RESULT(ISO-10646) + AC_DEFINE(MULTI_CHARSET) + DEF_FONT_IDX=2 + MULTICHAR_ENCODING="iso-10646" + MFONT0="-misc-fixed-medium-r-normal--7-70-75-75-c-50-iso10646-1" + MFONT1="-misc-fixed-medium-r-normal--10-100-75-75-c-60-iso10646-1" + MFONT2="-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1" + MFONT3="-misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1" + MFONT4="-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1" + FONT0="5x7" + FONT1="6x10" + FONT2="fixed" + FONT3="8x13" + FONT4="9x15" + else + MULTI_CHARSET_TYPE="" + fi +fi +if test "x$MULTI_CHARSET_TYPE" = "x"; then + AC_MSG_RESULT(no) + DEF_FONT_IDX=2 + MULTICHAR_ENCODING=none + MFONT0=none + MFONT1=none + MFONT2=none + MFONT3=none + MFONT4=none + FONT0="5x7" + FONT1="6x10" + FONT2="fixed" + FONT3="8x13" + FONT4="9x15" +fi AC_DEFINE_UNQUOTED(DEF_FONT_IDX, $DEF_FONT_IDX) AC_DEFINE_UNQUOTED(FONT0, "$FONT0") diff --git a/libmej/strings.c b/libmej/strings.c index 7aaaad3..cfdad44 100644 --- a/libmej/strings.c +++ b/libmej/strings.c @@ -240,10 +240,10 @@ Word(unsigned long index, const char *str) /* Return pointer into str to index-th word in str. "..." counts as 1 word. */ char * -PWord(unsigned long index, char *str) +PWord(unsigned long index, const char *str) { - register char *tmpstr = str; + register const char *tmpstr = str; register unsigned long j; if (!str) @@ -262,7 +262,7 @@ PWord(unsigned long index, char *str) return ((char *) NULL); } else { D_STRINGS(("PWord(%lu, %s) returning \"%s\"\n", index, str, tmpstr)); - return tmpstr; + return (char *) tmpstr; } } diff --git a/libmej/strings.h b/libmej/strings.h index 0bb3fad..74fc98b 100644 --- a/libmej/strings.h +++ b/libmej/strings.h @@ -75,7 +75,7 @@ extern char *RightStr(const char *, unsigned long); extern unsigned char Match(const char *, const char *); #endif extern char *Word(unsigned long, const char *); -extern char *PWord(unsigned long, char *); +extern char *PWord(unsigned long, const char *); extern unsigned long NumWords(const char *); extern char *StripWhitespace(char *); extern char *LowerStr(char *); diff --git a/src/command.c b/src/command.c index 49dc727..b8855d9 100644 --- a/src/command.c +++ b/src/command.c @@ -1090,25 +1090,23 @@ handle_crash(int sig) void install_handlers(void) { - signal(SIGHUP, handle_exit_signal); + /* Ignore SIGHUP */ + /* signal(SIGHUP, handle_exit_signal); */ #ifndef __svr4__ - signal(SIGINT, handle_exit_signal); + signal(SIGINT, handle_exit_signal); #endif - signal(SIGQUIT, handle_crash); signal(SIGTERM, handle_exit_signal); signal(SIGCHLD, handle_child_signal); + signal(SIGQUIT, handle_crash); signal(SIGSEGV, handle_crash); - signal(SIGBUS, handle_crash); + signal(SIGBUS, handle_crash); signal(SIGABRT, handle_crash); - signal(SIGFPE, handle_crash); - signal(SIGILL, handle_crash); - signal(SIGSYS, handle_crash); + signal(SIGFPE, handle_crash); + signal(SIGILL, handle_crash); + signal(SIGSYS, handle_crash); } -/* - * Exit gracefully, clearing the utmp entry and restoring tty attributes - * TODO: Also free up X resources, etc., if possible - */ +/* Exit gracefully, clearing the utmp entry and restoring tty attributes */ void clean_exit(void) { diff --git a/src/font.c b/src/font.c index 8ac2c36..467252a 100644 --- a/src/font.c +++ b/src/font.c @@ -30,6 +30,7 @@ static const char cvs_ident[] = "$Id$"; #include #include #include +#include #include "../libmej/debug.h" #include "../libmej/mem.h" @@ -53,12 +54,14 @@ const char *def_mfontName[] = {MFONT0, MFONT1, MFONT2, MFONT3, MFONT4}; #endif const char *def_fontName[] = {FONT0, FONT1, FONT2, FONT3, FONT4}; unsigned char font_chg = 0; +fontshadow_t fshadow = { { 0, 0, 0, 0 }, { 0, 0, 0, 1 }, 1 }; static cachefont_t *font_cache = NULL, *cur_font = NULL; static void font_cache_add(const char *name, unsigned char type, void *info); static void font_cache_del(const void *info); static cachefont_t *font_cache_find(const char *name, unsigned char type); static void *font_cache_find_info(const char *name, unsigned char type); +static unsigned char get_corner(const char *corner); void eterm_font_add(char ***plist, const char *fontname, unsigned char idx) { @@ -427,20 +430,45 @@ change_font(int init, const char *fontname) fw = TermWin.font->min_bounds.width; fh = TermWin.font->ascent + TermWin.font->descent + rs_line_space; - D_FONT(("Font information: Ascent == %hd, Descent == %hd\n", TermWin.font->ascent, TermWin.font->descent)); + D_FONT(("Font information: Ascent == %hd, Descent == %hd, width min/max %d/%d\n", TermWin.font->ascent, TermWin.font->descent, + TermWin.font->min_bounds.width, TermWin.font->max_bounds.width)); if (TermWin.font->min_bounds.width == TermWin.font->max_bounds.width) TermWin.fprop = 0; /* Mono-spaced (fixed width) font */ else TermWin.fprop = 1; /* Proportional font */ - LOWER_BOUND(fw, TermWin.font->max_bounds.width); - if (TermWin.fprop) { - fw = (fw << 1) / 3; + if (TermWin.fprop && TermWin.font->per_char && (TermWin.font->max_bounds.width - TermWin.font->min_bounds.width >= 3)) { + int cw, n = 0, sum = 0, sumsq = 0, min_w, max_w; + unsigned int i; + double dev; + + min_w = fw; + max_w = TermWin.font->max_bounds.width; + for (i = TermWin.font->min_char_or_byte2; i <= TermWin.font->max_char_or_byte2; i++) { + cw = TermWin.font->per_char[i].width; + if (cw >= min_w && cw <= max_w) { + sum += cw; + sumsq += (cw * cw); + n++; + } + } + if (n) { + dev = sqrt((sumsq - (sum * sum) / n) / n); + /* Final font width is the average width plus 2 standard + deviations, but no larger than the font's max width */ + fw = ((sum / n) + (((int) dev) << 1)); + D_FONT(("Proportional font optimizations: Average width %d, standard deviation %3.2f, new width %d\n", (sum / n), dev, fw)); + UPPER_BOUND(fw, max_w); + } else { + LOWER_BOUND(fw, TermWin.font->max_bounds.width); + } + } else { + LOWER_BOUND(fw, TermWin.font->max_bounds.width); } /* not the first time thru and sizes haven't changed */ if (fw == TermWin.fwidth && fh == TermWin.fheight) - return; /* TODO: not return; check MULTI_CHARSET if needed */ + return; TermWin.fwidth = fw; TermWin.fheight = fh; @@ -488,3 +516,138 @@ change_font(int init, const char *fontname) } return; } + +static unsigned char +get_corner(const char *corner) +{ + if (!BEG_STRCASECMP(corner, "tl ") || !BEG_STRCASECMP(corner, "top_left")) { + return SHADOW_TOP_LEFT; + } else if (!BEG_STRCASECMP(corner, "tr ") || !BEG_STRCASECMP(corner, "top_right")) { + return SHADOW_TOP_RIGHT; + } else if (!BEG_STRCASECMP(corner, "bl ") || !BEG_STRCASECMP(corner, "bottom_left")) { + return SHADOW_BOTTOM_LEFT; + } else if (!BEG_STRCASECMP(corner, "br ") || !BEG_STRCASECMP(corner, "bottom_right")) { + return SHADOW_BOTTOM_RIGHT; + } else { + return 255; + } +} + +void +set_shadow_color_by_name(unsigned char which, const char *color_name) +{ + Pixel p; + + ASSERT(which <= 4); + + p = get_color_by_name(color_name, "#000000"); + fshadow.color[which] = p; + fshadow.shadow[which] = fshadow.do_shadow = 1; +} + +void +set_shadow_color_by_pixel(unsigned char which, Pixel p) +{ + ASSERT(which <= 4); + + fshadow.color[which] = p; + fshadow.shadow[which] = fshadow.do_shadow = 1; +} + +/* Possible syntax for the font effects line: + font fx + font fx outline + font fx shadow + font fx emboss + font fx carved + ^^^^^^^ + | + \- This part is not included in the contents of the line variable. +*/ +unsigned char +parse_font_fx(const char *line) +{ + char *color, *corner; + unsigned char which, n; + Pixel p; + + ASSERT(line != NULL); + + n = NumWords(line); + + if (!BEG_STRCASECMP(line, "none")) { + MEMSET(&fshadow, 0, sizeof(fontshadow_t)); + } else if (!BEG_STRCASECMP(line, "outline")) { + if (n != 2) { + return 0; + } + color = Word(2, line); + p = get_color_by_name(color, "black"); + FREE(color); + for (which = 0; which < 4; which++) { + set_shadow_color_by_pixel(which, p); + } + } else if (!BEG_STRCASECMP(line, "shadow")) { + if (n == 2) { + which = SHADOW_BOTTOM_RIGHT; + color = Word(2, line); + } else if (n == 3) { + color = Word(3, line); + corner = PWord(2, line); + which = get_corner(corner); + if (which >= 4) { + return 0; + } + } else { + return 0; + } + set_shadow_color_by_name(which, color); + FREE(color); + } else if (!BEG_STRCASECMP(line, "emboss")) { + if (n != 3) { + return 0; + } + color = Word(2, line); + p = get_color_by_name(color, "black"); + set_shadow_color_by_pixel(SHADOW_BOTTOM_RIGHT, p); + FREE(color); + + color = Word(3, line); + p = get_color_by_name(color, "white"); + set_shadow_color_by_pixel(SHADOW_TOP_LEFT, p); + FREE(color); + } else if (!BEG_STRCASECMP(line, "carved")) { + if (n != 3) { + return 0; + } + color = Word(2, line); + p = get_color_by_name(color, "black"); + set_shadow_color_by_pixel(SHADOW_TOP_LEFT, p); + FREE(color); + + color = Word(3, line); + p = get_color_by_name(color, "white"); + set_shadow_color_by_pixel(SHADOW_BOTTOM_RIGHT, p); + FREE(color); + } else { + unsigned char i; + + for (i = 0; i < 4; i++) { + which = get_corner(line); + if (which >= 4) { + which = i; + color = Word(1, line); + line = PWord(2, line); + } else { + color = Word(2, line); + line = PWord(3, line); + } + set_shadow_color_by_name(which, color); + FREE(color); + if (line == NULL) { + break; + } + } + } + return 1; +} diff --git a/src/font.h b/src/font.h index 0e335c7..b96956c 100644 --- a/src/font.h +++ b/src/font.h @@ -40,6 +40,12 @@ #define BIGGER_FONT "#+" #define SMALLER_FONT "#-" +/* These are subscripts for the arrays in a fontshadow_t */ +#define SHADOW_TOP_LEFT 0 +#define SHADOW_TOP_RIGHT 1 +#define SHADOW_BOTTOM_LEFT 2 +#define SHADOW_BOTTOM_RIGHT 3 + #define NEXT_FONT(i) do { if (font_idx + ((i)?(i):1) >= font_cnt) {font_idx = font_cnt - 1;} else {font_idx += ((i)?(i):1);} \ while (!etfonts[font_idx]) {if (font_idx == font_cnt) {font_idx--; break;} font_idx++;} } while (0) #define PREV_FONT(i) do { if (font_idx - ((i)?(i):1) < 0) {font_idx = 0;} else {font_idx -= ((i)?(i):1);} \ @@ -58,11 +64,18 @@ typedef struct cachefont_struct { struct cachefont_struct *next; } cachefont_t; +typedef struct fontshadow_struct { + Pixel color[4]; + unsigned char shadow[4]; + unsigned char do_shadow; +} fontshadow_t; + /************ Variables ************/ extern unsigned char font_idx, def_font_idx, font_cnt, font_chg; extern const char *def_fontName[]; extern char *rs_font[NFONTS]; extern char **etfonts, **etmfonts; +extern fontshadow_t fshadow; # ifdef MULTI_CHARSET extern const char *def_mfontName[]; extern char *rs_mfont[NFONTS]; @@ -76,6 +89,9 @@ extern void eterm_font_delete(char **flist, unsigned char idx); extern void *load_font(const char *, const char *, unsigned char); extern void free_font(const void *); extern void change_font(int, const char *); +extern void set_shadow_color_by_name(unsigned char, const char *); +extern void set_shadow_color_by_pixel(unsigned char, Pixel); +extern unsigned char parse_font_fx(const char *line); _XFUNCPROTOEND diff --git a/src/menus.h b/src/menus.h index e96f661..5ee557c 100644 --- a/src/menus.h +++ b/src/menus.h @@ -25,7 +25,6 @@ # define _MENUS_H # include -# include # include "events.h" # include "pixmap.h" diff --git a/src/options.c b/src/options.c index 7f3698e..824ddd3 100644 --- a/src/options.c +++ b/src/options.c @@ -94,6 +94,7 @@ static char *rs_pipe_name = NULL; static int rs_shade = 0; static char *rs_tint = NULL; static unsigned long rs_buttonbars = 1; +static char *rs_font_effects = NULL; #if defined (HOTKEY_CTRL) || defined (HOTKEY_META) static char *rs_bigfont_key = NULL; static char *rs_smallfont_key = NULL; @@ -253,6 +254,7 @@ static const struct { OPT_LONG("font2", "font 2", &rs_font[2]), OPT_LONG("font3", "font 3", &rs_font[3]), OPT_LONG("font4", "font 4", &rs_font[4]), + OPT_LONG("font-fx", "specify font effects for the terminal fonts", &rs_font_effects), /* =======[ Pixmap options ]======= */ #ifdef PIXMAP_SUPPORT @@ -2020,6 +2022,11 @@ parse_attributes(char *buff, void *state) } else if (!BEG_STRCASECMP(tmp, "default ")) { def_font_idx = strtoul(PWord(2, tmp), (char **) NULL, 0); + } else if (!BEG_STRCASECMP(tmp, "fx ") || !BEG_STRCASECMP(tmp, "effect")) { + if (parse_font_fx(PWord(2, tmp)) != 1) { + print_error("Parse error in file %s, line %lu: Syntax error in font effects specification", + file_peek_path(), file_peek_line()); + } } else { tmp = Word(1, tmp); print_error("Parse error in file %s, line %lu: Invalid font index \"%s\"", @@ -3687,6 +3694,12 @@ post_parse(void) } #endif } + if (rs_font_effects) { + if (parse_font_fx(rs_font_effects) != 1) { + print_error("Syntax error in the font effects specified on the command line."); + } + RESET_AND_ASSIGN(rs_font_effects, NULL); + } /* Clean up image stuff */ for (i = 0; i < image_max; i++) { @@ -3713,6 +3726,9 @@ post_parse(void) load_image(rs_pixmaps[i], images[i].norm); FREE(rs_pixmaps[i]); /* These are created by StrDup() */ } +#else + /* Right now, solid mode is the only thing we can do without pixmap support. */ + images[i].mode = MODE_SOLID & ALLOW_SOLID; #endif if (images[i].selected) { /* If we have a bevel but no border, use the bevel as a border. */ @@ -3965,6 +3981,12 @@ post_parse(void) } #endif +#ifdef MULTI_CHARSET + if (rs_multichar_encoding != NULL) { + set_multichar_encoding(rs_multichar_encoding); + } +#endif + if (rs_pipe_name) { struct stat fst; diff --git a/src/pixmap.h b/src/pixmap.h index 658001d..8096935 100644 --- a/src/pixmap.h +++ b/src/pixmap.h @@ -25,7 +25,9 @@ # define _PIXMAP_H #include -#include +#ifdef PIXMAP_SUPPORT +# include +#endif #include "misc.h" diff --git a/src/screen.c b/src/screen.c index 4883a7b..0b5f146 100644 --- a/src/screen.c +++ b/src/screen.c @@ -36,6 +36,7 @@ static const char cvs_ident[] = "$Id$"; #include "buttons.h" #include "command.h" #include "debug.h" +#include "font.h" #include "startup.h" #include "screen.h" #include "scrollbar.h" @@ -94,8 +95,8 @@ unsigned char refresh_all = 0; #ifdef MULTI_CHARSET static short multi_byte = 0; static enum { - EUCJ, EUCKR = EUCJ, GB = EUCJ, SJIS, BIG5 -} encoding_method = EUCJ; + EUCJ, EUCKR = EUCJ, GB = EUCJ, SJIS, BIG5, LATIN1 +} encoding_method = LATIN1; static enum { SBYTE, WBYTE } chstat = SBYTE; @@ -738,51 +739,56 @@ scr_add_lines(const unsigned char *str, int nlines, int len) for (i = 0; i < len;) { c = str[i++]; #ifdef MULTI_CHARSET - if (chstat == WBYTE) { + if ((encoding_method != LATIN1) && (chstat == WBYTE)) { rstyle |= RS_multiMask; /* multibyte 2nd byte */ chstat = SBYTE; - if (encoding_method == EUCJ) + if (encoding_method == EUCJ) { c |= 0x80; /* maybe overkill, but makes it selectable */ - } else if (chstat == SBYTE) - if (multi_byte || (c & 0x80)) { /* multibyte 1st byte */ + } + } else if (chstat == SBYTE) { + if ((encoding_method != LATIN1) && (multi_byte || (c & 0x80))) { /* multibyte 1st byte */ rstyle &= ~RS_multiMask; rstyle |= RS_multi1; chstat = WBYTE; - if (encoding_method == EUCJ) + if (encoding_method == EUCJ) { c |= 0x80; /* maybe overkill, but makes it selectable */ + } } else #endif - switch (c) { - case 127: - continue; /* ummmm..... */ - case '\t': - scr_tab(1); - continue; - case '\n': - MAX_IT(stp[last_col], screen.col); - screen.flags &= ~Screen_WrapNext; - if (screen.row == screen.bscroll) { - scroll_text(screen.tscroll, screen.bscroll, 1, 0); - j = screen.bscroll + TermWin.saveLines; + switch (c) { + case 127: + continue; /* ummmm..... */ + case '\t': + scr_tab(1); + continue; + case '\n': + MAX_IT(stp[last_col], screen.col); + screen.flags &= ~Screen_WrapNext; + if (screen.row == screen.bscroll) { + scroll_text(screen.tscroll, screen.bscroll, 1, 0); + j = screen.bscroll + TermWin.saveLines; blank_screen_mem(screen.text, screen.rend, j, DEFAULT_RSTYLE | ((rstyle & RS_RVid) ? (RS_RVid) : (0))); - } else if (screen.row < (TermWin.nrow - 1)) { - screen.row++; - row = screen.row + TermWin.saveLines; - } - stp = screen.text[row]; /* _must_ refresh */ - srp = screen.rend[row]; /* _must_ refresh */ - continue; - case '\r': - MAX_IT(stp[last_col], screen.col); - screen.flags &= ~Screen_WrapNext; - screen.col = 0; - continue; - default: + } else if (screen.row < (TermWin.nrow - 1)) { + screen.row++; + row = screen.row + TermWin.saveLines; + } + stp = screen.text[row]; /* _must_ refresh */ + srp = screen.rend[row]; /* _must_ refresh */ + continue; + case '\r': + MAX_IT(stp[last_col], screen.col); + screen.flags &= ~Screen_WrapNext; + screen.col = 0; + continue; + default: #ifdef MULTI_CHARSET - rstyle &= ~RS_multiMask; + rstyle &= ~RS_multiMask; +#endif + break; + } +#ifdef MULTI_CHARSET + } #endif - break; - } if (screen.flags & Screen_WrapNext) { stp[last_col] = WRAP_CHAR; if (screen.row == screen.bscroll) { @@ -1381,11 +1387,20 @@ scr_charset_set(int set, unsigned int ch) #ifdef MULTI_CHARSET +static void latin1(unsigned char *str, int len); static void eucj2jis(unsigned char *str, int len); static void sjis2jis(unsigned char *str, int len); static void big5dummy(unsigned char *str, int len); -static void (*multichar_decode) (unsigned char *str, int len) = eucj2jis; +static void (*multichar_decode) (unsigned char *str, int len) = latin1; + +static void +latin1(unsigned char *str, int len) +{ + return; + str = NULL; + len = 0; +} static void eucj2jis(unsigned char *str, int len) @@ -1431,16 +1446,18 @@ set_multichar_encoding(const char *str) { #ifdef MULTI_CHARSET if (str && *str) { - if (!strcmp(str, "sjis")) { + if (!strcasecmp(str, "sjis")) { encoding_method = SJIS; multichar_decode = sjis2jis; - } else if (!strcmp(str, "eucj") || !strcmp(str, "euckr") - || !strcmp(str, "gb")) { + } else if (!strcasecmp(str, "eucj") || !strcasecmp(str, "euckr") || !strcasecmp(str, "gb")) { encoding_method = EUCJ; multichar_decode = eucj2jis; - } else if (!strcmp(str, "big5")) { + } else if (!strcasecmp(str, "big5")) { encoding_method = BIG5; multichar_decode = big5dummy; + } else { + encoding_method = LATIN1; + multichar_decode = latin1; } } #else @@ -1734,7 +1751,7 @@ scr_refresh(int type) drp[col] = srp[col]; buffer[len++] = stp[col]; col++; - if ((col == ncols) || (srp[col] != rend)) + if ((col == ncols) || (srp[col] != (unsigned int) rend)) break; if ((stp[col] == dtp[col]) && (srp[col] == drp[col]) @@ -1779,7 +1796,7 @@ scr_refresh(int type) dtp[col] = stp[col]; drp[col] = srp[col]; buffer[len++] = stp[col]; - } /* for (; ++col < TermWin.ncol - 1;) */ + } col--; wlen = len; #ifdef MULTI_CHARSET @@ -1908,44 +1925,101 @@ scr_refresh(int type) UPDATE_BOX(xpixel + 1, ypixel - TermWin.font->ascent, xpixel + 1 + Width2Pixel(1), ypixel + Height2Pixel(1)); } #endif - } else + } else { #ifdef PIXMAP_SUPPORT - if (background_is_pixmap() && (back == bgColor)) { - CLEAR_CHARS(xpixel, ypixel - TermWin.font->ascent, len); - DRAW_STRING(draw_string, xpixel, ypixel, buffer, wlen); - UPDATE_BOX(xpixel, ypixel - TermWin.font->ascent, xpixel + Width2Pixel(len), ypixel + Height2Pixel(1)); - } else + if (background_is_pixmap() && (back == bgColor)) { + if (fshadow.do_shadow) { + Pixel tmp; + int xx, yy, ww, hh; + + tmp = gcvalue.foreground; + xx = xpixel; + yy = ypixel - TermWin.font->ascent; + ww = Width2Pixel(wlen); + hh = Height2Pixel(1); + CLEAR_CHARS(xpixel, ypixel - TermWin.font->ascent, wlen); + if (fshadow.shadow[SHADOW_TOP_LEFT] || fshadow.shadow[SHADOW_TOP_RIGHT]) { + yy--; + hh++; + } + if (fshadow.shadow[SHADOW_BOTTOM_LEFT] || fshadow.shadow[SHADOW_BOTTOM_RIGHT]) { + hh++; + if (row < nrows - 1) { + int ii; + + for (ii = col - len + 1; ii <= col; ii++) { + drawn_text[row + 1][ii] = 0; + } + } + } + if (fshadow.shadow[SHADOW_TOP_LEFT]) { + XSetForeground(Xdisplay, TermWin.gc, fshadow.color[SHADOW_TOP_LEFT]); + DRAW_STRING(draw_string, xpixel - 1, ypixel - 1, buffer, wlen); + if (col) { + dtp[col - 1] = 0; + } + } + if (fshadow.shadow[SHADOW_TOP_RIGHT]) { + XSetForeground(Xdisplay, TermWin.gc, fshadow.color[SHADOW_TOP_RIGHT]); + DRAW_STRING(draw_string, xpixel + 1, ypixel - 1, buffer, wlen); + if (col < ncols - 1) { + dtp[col + 1] = 0; + } + } + if (fshadow.shadow[SHADOW_BOTTOM_LEFT]) { + XSetForeground(Xdisplay, TermWin.gc, fshadow.color[SHADOW_BOTTOM_LEFT]); + DRAW_STRING(draw_string, xpixel - 1, ypixel + 1, buffer, wlen); + if (col) { + dtp[col - 1] = 0; + } + } + if (fshadow.shadow[SHADOW_BOTTOM_RIGHT]) { + XSetForeground(Xdisplay, TermWin.gc, fshadow.color[SHADOW_BOTTOM_RIGHT]); + DRAW_STRING(draw_string, xpixel + 1, ypixel + 1, buffer, wlen); + if (col < ncols - 1) { + dtp[col + 1] = 0; + } + } + XSetForeground(Xdisplay, TermWin.gc, tmp); + DRAW_STRING(draw_string, xpixel, ypixel, buffer, wlen); + UPDATE_BOX(xx, yy, xx + ww, yy + hh); + } else { + CLEAR_CHARS(xpixel, ypixel - TermWin.font->ascent, wlen); + DRAW_STRING(draw_string, xpixel, ypixel, buffer, wlen); + UPDATE_BOX(xpixel, ypixel - TermWin.font->ascent, xpixel + Width2Pixel(wlen), ypixel + Height2Pixel(1)); + } + } else #endif - { + { #ifdef FORCE_CLEAR_CHARS - CLEAR_CHARS(xpixel, ypixel - TermWin.font->ascent, len); + CLEAR_CHARS(xpixel, ypixel - TermWin.font->ascent, wlen); #endif - DRAW_STRING(draw_image_string, xpixel, ypixel, buffer, wlen); - UPDATE_BOX(xpixel, ypixel - TermWin.font->ascent, xpixel + Width2Pixel(len), ypixel + Height2Pixel(1)); + DRAW_STRING(draw_image_string, xpixel, ypixel, buffer, wlen); + UPDATE_BOX(xpixel, ypixel - TermWin.font->ascent, xpixel + Width2Pixel(wlen), ypixel + Height2Pixel(1)); + } } /* do the convoluted bold overstrike */ #ifndef NO_BOLDOVERSTRIKE if (MONO_BOLD(rend)) { DRAW_STRING(draw_string, xpixel + 1, ypixel, buffer, wlen); - UPDATE_BOX(xpixel + 1, ypixel - TermWin.font->ascent, xpixel + 1 + Width2Pixel(len), ypixel + Height2Pixel(1)); + UPDATE_BOX(xpixel + 1, ypixel - TermWin.font->ascent, xpixel + 1 + Width2Pixel(wlen), ypixel + Height2Pixel(1)); } #endif if ((rend & RS_Uline) && (TermWin.font->descent > 1)) { - XDrawLine(Xdisplay, draw_buffer, TermWin.gc, xpixel, ypixel + 1, xpixel + Width2Pixel(len) - 1, ypixel + 1); - UPDATE_BOX(xpixel, ypixel + 1, xpixel + Width2Pixel(len) - 1, ypixel + 1); + XDrawLine(Xdisplay, draw_buffer, TermWin.gc, xpixel, ypixel + 1, xpixel + Width2Pixel(wlen) - 1, ypixel + 1); + UPDATE_BOX(xpixel, ypixel + 1, xpixel + Width2Pixel(wlen) - 1, ypixel + 1); } if (is_cursor == 1) { #ifndef NO_CURSORCOLOR if (PixColors[cursorColor] != PixColors[bgColor]) { - gcvalue.foreground = PixColors[cursorColor]; - gcmask |= GCForeground; - XChangeGC(Xdisplay, TermWin.gc, gcmask, &gcvalue); + XSetForeground(Xdisplay, TermWin.gc, PixColors[cursorColor]); } #endif XDrawRectangle(Xdisplay, draw_buffer, TermWin.gc, xpixel, ypixel - TermWin.font->ascent, Width2Pixel(1 + wbyte) - 1, Height2Pixel(1) - 1); UPDATE_BOX(xpixel, ypixel - TermWin.font->ascent, Width2Pixel(1 + wbyte) - 1, Height2Pixel(1) - 1); + XSetForeground(Xdisplay, TermWin.gc, PixColors[fgColor]); } if (gcmask) { /* restore normal colors */ gcvalue.foreground = PixColors[fgColor]; @@ -1975,10 +2049,41 @@ scr_refresh(int type) #endif } if (buffer_pixmap) { + D_SCREEN(("Update box dimensions: from (%d, %d) to (%d, %d). Dimensions %dx%d\n", low_x, low_y, high_x, high_y, + high_x - low_x + 1, high_y - low_y + 1)); XClearArea(Xdisplay, TermWin.vt, low_x, low_y, high_x - low_x + 1, high_y - low_y + 1, False); + if (fshadow.shadow[SHADOW_TOP_LEFT] || fshadow.shadow[SHADOW_BOTTOM_LEFT]) { + XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, TermWin.internalBorder - 1, 0, + 1, TermWin_TotalHeight() - 1, TermWin.internalBorder - 1, 0); + XClearArea(Xdisplay, TermWin.vt, TermWin.internalBorder - 1, 0, 1, TermWin_TotalHeight() - 1, False); + } + if (fshadow.shadow[SHADOW_TOP_RIGHT] || fshadow.shadow[SHADOW_BOTTOM_RIGHT] || boldlast) { + XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, TermWin_TotalWidth() - 2, 0, + 1, TermWin_TotalHeight() - 1, TermWin_TotalWidth() - 2, 0); + XClearArea(Xdisplay, TermWin.vt, TermWin_TotalWidth() - 2, 0, 1, TermWin_TotalHeight() - 1, False); + } + if (fshadow.shadow[SHADOW_TOP_LEFT] || fshadow.shadow[SHADOW_TOP_RIGHT]) { + XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, 0, TermWin.internalBorder - 1, + TermWin_TotalWidth() - 1, 1, 0, TermWin.internalBorder - 1); + XClearArea(Xdisplay, TermWin.vt, 0, TermWin.internalBorder - 1, TermWin_TotalWidth() - 1, 1, False); + } + if (fshadow.shadow[SHADOW_BOTTOM_LEFT] || fshadow.shadow[SHADOW_BOTTOM_RIGHT]) { + XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, 0, TermWin_TotalHeight() - TermWin.internalBorder, + TermWin_TotalWidth() - 1, 1, 0, TermWin_TotalHeight() - TermWin.internalBorder); + XClearArea(Xdisplay, TermWin.vt, 0, TermWin_TotalHeight() - TermWin.internalBorder, TermWin_TotalWidth() - 1, 1, False); + } } else { - if (boldlast) { - XClearArea(Xdisplay, TermWin.vt, TermWin_TotalWidth() - 2, 0, 1, TermWin_TotalHeight() - 1, 0); + if (fshadow.shadow[SHADOW_TOP_LEFT] || fshadow.shadow[SHADOW_BOTTOM_LEFT]) { + XClearArea(Xdisplay, TermWin.vt, TermWin.internalBorder - 1, 0, 1, TermWin_TotalHeight() - 1, False); + } + if ((fshadow.shadow[SHADOW_TOP_RIGHT] || fshadow.shadow[SHADOW_BOTTOM_RIGHT] || boldlast) && TermWin.internalBorder) { + XClearArea(Xdisplay, TermWin.vt, TermWin_TotalWidth() - 2, 0, 1, TermWin_TotalHeight() - 1, False); + } + if (fshadow.shadow[SHADOW_TOP_LEFT] || fshadow.shadow[SHADOW_TOP_RIGHT]) { + XClearArea(Xdisplay, TermWin.vt, 0, TermWin.internalBorder - 1, TermWin_TotalWidth() - 1, 1, False); + } + if (fshadow.shadow[SHADOW_BOTTOM_LEFT] || fshadow.shadow[SHADOW_BOTTOM_RIGHT]) { + XClearArea(Xdisplay, TermWin.vt, 0, TermWin_TotalHeight() - TermWin.internalBorder, TermWin_TotalWidth() - 1, 1, False); } } if (type == SLOW_REFRESH) { diff --git a/src/screen.h b/src/screen.h index d4dc306..8b443bf 100644 --- a/src/screen.h +++ b/src/screen.h @@ -51,6 +51,9 @@ #define CLEAR_CHARS(x, y, num) ((buffer_pixmap) \ ? (XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, x, y, Width2Pixel(num), Height2Pixel(1), x, y)) \ : (XClearArea(Xdisplay, TermWin.vt, x, y, Width2Pixel(num), Height2Pixel(1), 0))) +#define CLEAR_RECT(x, y, w, h) ((buffer_pixmap) \ + ? (XCopyArea(Xdisplay, pmap, buffer_pixmap, TermWin.gc, x, y, w, h, x, y)) \ + : (XClearArea(Xdisplay, TermWin.vt, x, y, w, h, 0))) #define UPDATE_BOX(x1, y1, x2, y2) do {if (buffer_pixmap) {if (x1 < low_x) low_x = x1; if (x2 > high_x) high_x = x2; \ if (y1 < low_y) low_y = y1; if (y2 > high_y) high_y = y2;}} while (0) #define ERASE_ROWS(row, num) do {XFillRectangle(Xdisplay, draw_buffer, TermWin.gc, Col2Pixel(0), Row2Pixel(row), TermWin.width, Height2Pixel(num)); \ diff --git a/src/scrollbar.h b/src/scrollbar.h index 932bc2e..08642eb 100644 --- a/src/scrollbar.h +++ b/src/scrollbar.h @@ -26,8 +26,8 @@ #include #include -#include #include "events.h" +#include "pixmap.h" /************ Macros and Definitions ************/ /* Scrollbar types we support */