untrusted comment: verify with signify key from exoticsilicon.com RWRn5d3Yx35u07CgrZGC9RwqbsEGh/cbkiTYYd68HO575lgjBS05vS+g79k/EM66kkqditx8SClWOTkE14p87aMkjrUqrltjRQ4= --- sys/dev/rasops/rasops.c Mon Apr 7 04:25:22 2025 +++ sys/dev/rasops/rasops.c Wed Jun 4 13:36:39 2025 @@ -133,7 +133,7 @@ uint32_t rs_defattr; int rs_sbscreens; -#define RS_SCROLLBACK_SCREENS 5 +#define RS_SCROLLBACK_SCREENS 20 int rs_dispoffset; /* rs_bs index, start of our actual screen */ int rs_visibleoffset; /* rs_bs index, current scrollback screen */ }; @@ -446,6 +446,10 @@ WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; } + if (ri->ri_depth == 32) { + ri->ri_caps |= WSSCREEN_256COL; + } + switch (ri->ri_depth) { #if NRASOPS1 > 0 case 1: @@ -557,7 +561,7 @@ if ((flg & WSATTR_HILIT) != 0 && fg < 8) fg += 8; - *attr = (bg << 16) | (fg << 24) | (flg & WSATTR_UNDERLINE); + *attr = (bg << 16) | (fg << 24) | flg; return (0); } @@ -581,7 +585,7 @@ bg = swap; } - *attr = (bg << 16) | (fg << 24) | (flg & WSATTR_UNDERLINE); + *attr = (bg << 16) | (fg << 24) | flg; return (0); } @@ -863,6 +867,24 @@ ri->ri_devcmap[i] = c; #endif } + /* Define colours 16-255 if we are running in 32bpp or 16bpp */ + #define EBCOL_BLUE(x) ((48*((x-16)%6) >> (8 - ri->ri_bnum)) << ri->ri_bpos) + #define EBCOL_GREEN(x) (((48*(((x-16)/6)%6)) >> (8 - ri->ri_gnum)) << ri->ri_gpos) + #define EBCOL_RED(x) (((48*(((x-16)/36)%6)) >> (8 - ri->ri_rnum)) << ri->ri_rpos) + #define EBCOL(x) EBCOL_RED(x) | EBCOL_GREEN(x) | EBCOL_BLUE(x) + #define EBGREY_CHANNEL(x) (int)(1+((i-232)*11)) + #define EBGREY_R(x)(( EBGREY_CHANNEL(x) >> (8 - ri->ri_rnum)) << ri->ri_rpos) + #define EBGREY_G(x)(( EBGREY_CHANNEL(x) >> (8 - ri->ri_gnum)) << ri->ri_gpos) + #define EBGREY_B(x)(( EBGREY_CHANNEL(x) >> (8 - ri->ri_bnum)) << ri->ri_bpos) + #define EBGREY(x) EBGREY_R(x) | EBGREY_G(x) | EBGREY_B(x) + if (ri->ri_depth == 32 || ri->ri_depth==16) { + for (i=16 ; i<256; i++) { + c = (i < 232 ? EBCOL(i) : EBGREY(i)); + if (ri->ri_flg & RI_BSWAP) + c = (ri->ri_depth==16 ? swap16(c) : swap32(c)); + ri->ri_devcmap[i] = c; + } + } #endif } @@ -872,8 +894,8 @@ void rasops_unpack_attr(void *cookie, uint32_t attr, int *fg, int *bg, int *underline) { - *fg = ((u_int)attr >> 24) & 0xf; - *bg = ((u_int)attr >> 16) & 0xf; + *fg = ((u_int)attr >> 24) & 0xff; + *bg = ((u_int)attr >> 16) & 0xff; if (underline != NULL) *underline = (u_int)attr & WSATTR_UNDERLINE; } @@ -903,7 +925,7 @@ return 0; #endif - clr = ri->ri_devcmap[(attr >> 16) & 0xf]; + clr = ri->ri_devcmap[(attr >> 16) & 0xff]; /* * XXX The wsdisplay_emulops interface seems a little deficient in @@ -1243,9 +1265,20 @@ else col = ri->ri_cols - col - 1; - /* Do rotated char sans (side)underline */ - rc = ri->ri_real_ops.putchar(cookie, col, row, uc, - attr & ~WSATTR_UNDERLINE); + /* + * For rotated characters, attributes such as underline and double + * underline need to be painted in a different way. The generic putchar + * routines know nothing about this, so we clear the corresponding bits + * of attr before calling putchar, then deal with painting the + * missing attributes the required custom way here instead. + * + * Not all attributes are affected. Dim can be passed through and + * handled as normal by putchar, since the placement of individual + * pixels does not change the way that the effect is applied. + */ +#define BITMASK_UNSAFE_FOR_ROTATION (WSATTR_UNDERLINE | WSATTR_DOUBLE_UNDERLINE | WSATTR_STRIKE | WSATTR_ITALIC) + rc = ri->ri_real_ops.putchar(cookie, col, row, uc, attr & ~(BITMASK_UNSAFE_FOR_ROTATION)); + if (rc != 0) return rc; @@ -1257,7 +1290,7 @@ /* XXX this assumes 16-bit color depth */ if ((attr & WSATTR_UNDERLINE) != 0) { - int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf]; + int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xff]; while (height--) { *(int16_t *)rp = c; @@ -1785,8 +1818,8 @@ attr = ri->ri_bs[off].attr; if ((ri->ri_flg & RI_CURSOR) == 0) { - fg = ((u_int)attr >> 24) & 0xf; - bg = ((u_int)attr >> 16) & 0xf; + fg = ((u_int)attr >> 24) & 0xff; + bg = ((u_int)attr >> 16) & 0xff; attr &= ~0x0ffff0000; attr |= (fg << 16) | (bg << 24); } --- sys/dev/rasops/rasops.h Mon Apr 7 04:25:22 2025 +++ sys/dev/rasops/rasops.h Wed Jun 4 13:36:39 2025 @@ -106,7 +106,7 @@ u_char *ri_origbits; /* where screen bits actually start */ int ri_xorigin; /* where ri_bits begins (x) */ int ri_yorigin; /* where ri_bits begins (y) */ - int32_t ri_devcmap[16]; /* color -> framebuffer data */ + int32_t ri_devcmap[256]; /* color -> framebuffer data */ /* The emulops you need to use, and the screen caps for wscons */ struct wsdisplay_emulops ri_ops; --- sys/dev/rasops/rasops32.c Mon Apr 7 04:25:22 2025 +++ sys/dev/rasops/rasops32.c Wed Jun 4 13:39:11 2025 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,10 @@ } u; u_char *fr; + int i, j; + uint64_t row_data; + u_char * font_dataset; + ri = (struct rasops_info *)cookie; #ifdef RASOPS_CLIPPING @@ -91,13 +96,46 @@ width = ri->ri_font->fontwidth; step = ri->ri_stride >> 3; - b = ri->ri_devcmap[(attr >> 16) & 0xf]; - f = ri->ri_devcmap[(attr >> 24) & 0xf]; + b = ri->ri_devcmap[(attr >> 16) & 0xff]; + f = ri->ri_devcmap[(attr >> 24) & 0xff]; + + /* + * Implement dim by shifting each of the red, green and blue values by + * one bit. + * + * Since we are shifting each channel equally, this works for both RGB + * and byte-swapped BGR formats with exactly 8 bits per channel, + * I.E. 0xXXRRGGBB, and 0xBBGGRRXX. + * + * The unused byte is always set to 0x00 for 32bpp in + * rasops_init_devcmap, so will be unaffected by the shift. + * + * XXX If we ever support 32-bit devices that are not 8 bits per channel + * then this code will need to change. + */ + + if ((attr & WSATTR_DIM)!=0) { + f=(f>>1) & 0x7F7F7F7F; + } + u.d[0][0] = b; u.d[0][1] = b; u.d[1][0] = b; u.d[1][1] = f; u.d[2][0] = f; u.d[2][1] = b; u.d[3][0] = f; u.d[3][1] = f; + /* + * Implement 'invisible' attribute by changing the character to a space. + * + * We need to do this rather than just ignoring the character or filling + * the bits with 0x00 and returning as a special case, because effects + * such as underline and strikethrough are still rendered on invisible + * characters, (at least they are in xterm). + */ + + if ((attr & WSATTR_INVISIBLE)!=0) { + uc=' '; + } + if (uc == ' ') { while (height--) { /* the general, pixel-at-a-time case is fast enough */ @@ -107,7 +145,74 @@ } } else { uc -= ri->ri_font->firstchar; - fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale; + + /* + * Choose font data based on bold and italic attributes. + * + * If the pointer to the alternative font data is NULL, then + * the alternative font has not been generated yet. In this + * case, we allocate sufficient memory and generate it here. + * + * To produce the bold effect, we simply duplicate the set bits + * of the pixel data offset one pixel to the right, effectively + * 'overprinting' the glyph. Better algorithms probably exist. + * + * For the italic effect, pixel data is increasingly offset to + * the left as we progress down the rows from the top of each + * glyph. To minimise the overall visual shift to the left, we + * also shift back a fixed one bit to the right on each row. + */ + +#define FONT_MEM (ri->ri_font->fontheight * ri->ri_font->stride * ri->ri_font->numchars) +#define FONT_DATA(x) (unsigned char *)ri->ri_font->data + x +#define FONT_BOLD(x) (unsigned char *)ri->ri_font->data_bold + x +#define FONT_ITALIC(x) (unsigned char *)ri->ri_font->data_italic + x +#define FONT_BOLDITALIC(x) (unsigned char *)ri->ri_font->data_bolditalic + x +#define RIFONT ri->ri_font +#define SLANT_FACTOR(x) ((x % (RIFONT->stride * RIFONT->fontheight)) / (RIFONT->stride * RIFONT->fontheight / 4)) + switch (attr & (WSATTR_HILIT | WSATTR_ITALIC)) { + case WSATTR_HILIT: + if (RIFONT->data_bold == NULL) { + RIFONT->data_bold = malloc(FONT_MEM, M_TEMP, M_WAITOK); + for (i = 0; i < FONT_MEM; i++) + *(FONT_BOLD(i)) = *(FONT_DATA(i)) | (*(FONT_DATA(i)) >> 1); + } + font_dataset=(u_char *)RIFONT->data_bold; + break; + case WSATTR_ITALIC: + if (RIFONT->data_italic == NULL) { + RIFONT->data_italic = malloc(FONT_MEM, M_TEMP, M_WAITOK); + for (i = 0; i < FONT_MEM; i += RIFONT->stride) { + row_data = 0; + for (j = 0; j < RIFONT->stride; j++) + row_data |= (*(FONT_DATA(i+j))) << (8 * ((RIFONT->stride) - j - 1)); + row_data = row_data << SLANT_FACTOR(i) >> 1; + for (j = 0; j < RIFONT->stride; j++) + *(FONT_ITALIC(i + j)) = (row_data >> (8 * ((RIFONT->stride) - j - 1))) & 0xFF; + } + } + font_dataset=(u_char *)ri->ri_font->data_italic; + break; + case (WSATTR_HILIT | WSATTR_ITALIC): + if (RIFONT->data_bolditalic == NULL) { + RIFONT->data_bolditalic = malloc(FONT_MEM, M_TEMP, M_WAITOK); + for (i = 0; i < FONT_MEM; i += RIFONT->stride) { + row_data = 0; + for (j = 0; j < RIFONT->stride; j++) + row_data |= (*(FONT_DATA(i+j))) << (8 * ((RIFONT->stride) - j - 1)); + row_data = row_data << SLANT_FACTOR(i) >> 1; + row_data |= (row_data >> 1); + for (j = 0; j < RIFONT->stride; j++) + *(FONT_BOLDITALIC(i + j)) = (row_data >> (8 * ((RIFONT->stride) - j - 1))) & 0xFF; + } + } + font_dataset=(u_char *)ri->ri_font->data_bolditalic; + break; + default: + font_dataset=(u_char *)ri->ri_font->data; + } + + fr = (font_dataset + uc * ri->ri_fontscale); fs = ri->ri_font->stride; /* double-pixel special cases for the common widths */ @@ -214,11 +319,46 @@ } /* Do underline a pixel at a time */ - if ((attr & WSATTR_UNDERLINE) != 0) { + if ((attr & (WSATTR_UNDERLINE | WSATTR_DOUBLE_UNDERLINE)) != 0) { rp -= step; for (cnt = 0; cnt < width; cnt++) ((int *)rp)[cnt] = f; } + + /* + * Double underline now just needs to paint the second underline a few + * rows up. The exact height is relative to the font height, to create + * a visually pleasing effect regardless of display resolution. + */ + +#define FONT_HEIGHT ri->ri_font->fontheight +#define DOUBLE_UL_SHIFT (FONT_HEIGHT < 12 ? 0 : (FONT_HEIGHT <= 32 ? 1 : 2)) + + if ((attr & WSATTR_DOUBLE_UNDERLINE)!=0) { + rp-=(step << DOUBLE_UL_SHIFT); + for (cnt=0; cnt< width; cnt++) + ((int *)rp)[cnt]=f; + /* + * Reset row pointer to ensure that strikethough appears at a + * consistent height if combined with double underlining. + */ + + rp+=(step << DOUBLE_UL_SHIFT); + } + + /* + * Reset pointer to ensure that strikethough appears at a consistent + * height if combined with single underlining. + */ + + if ((attr & WSATTR_STRIKE)!=0) { + if ((attr & WSATTR_UNDERLINE) != 0) { + rp+=step ; + } + rp -= (1+ri->ri_font->fontheight/2)*step; + for (cnt=0; cnt< width; cnt++) + ((int *)rp)[cnt]=f; + } return 0; } --- sys/dev/wscons/wsconsio.h Mon Apr 7 04:42:48 2025 +++ sys/dev/wscons/wsconsio.h Wed Jun 4 13:36:39 2025 @@ -549,6 +549,9 @@ #define WSDISPLAY_FONTORDER_R2L 2 void *cookie; void *data; + void *data_bold; + void *data_italic; + void *data_bolditalic; }; #define WSDISPLAYIO_LDFONT _IOW ('W', 77, struct wsdisplay_font) #define WSDISPLAYIO_LSFONT _IOWR('W', 78, struct wsdisplay_font) --- sys/dev/wscons/wsdisplayvar.h Mon Apr 7 04:25:23 2025 +++ sys/dev/wscons/wsdisplayvar.h Wed Jun 4 13:36:39 2025 @@ -94,11 +94,16 @@ #define WSCOL_CYAN 6 #define WSCOL_WHITE 7 /* flag values: */ -#define WSATTR_REVERSE 1 -#define WSATTR_HILIT 2 -#define WSATTR_BLINK 4 -#define WSATTR_UNDERLINE 8 -#define WSATTR_WSCOLORS 16 +#define WSATTR_REVERSE 1 +#define WSATTR_HILIT 2 +#define WSATTR_BLINK 4 +#define WSATTR_UNDERLINE 8 +#define WSATTR_WSCOLORS 16 +#define WSATTR_DIM 32 +#define WSATTR_STRIKE 64 +#define WSATTR_DOUBLE_UNDERLINE 128 +#define WSATTR_INVISIBLE 256 +#define WSATTR_ITALIC 512 }; #define WSSCREEN_NAME_SIZE 16 @@ -114,6 +119,7 @@ #define WSSCREEN_HILIT 4 /* can highlight (however) */ #define WSSCREEN_BLINK 8 /* can blink */ #define WSSCREEN_UNDERLINE 16 /* can underline */ +#define WSSCREEN_256COL 32 /* supports 256 colours */ }; /* --- sys/dev/wscons/wsemul_vt100_keys.c Mon Apr 7 04:25:23 2025 +++ sys/dev/wscons/wsemul_vt100_keys.c Wed Jun 4 13:36:39 2025 @@ -37,11 +37,9 @@ #include #include +#define vt100_fkeys_len(x) (5+(x>=8)+(x>=12)) + static const u_char *vt100_fkeys[] = { - "\033[11~", /* F1 */ - "\033[12~", - "\033[13~", /* F1-F5 normally don't send codes */ - "\033[14~", "\033[15~", /* F5 */ "\033[17~", /* F6 */ "\033[18~", @@ -50,18 +48,18 @@ "\033[21~", "\033[23~", /* VT100: ESC */ "\033[24~", /* VT100: BS */ - "\033[25~", /* VT100: LF */ - "\033[26~", - "\033[28~", /* help */ - "\033[29~", /* do */ - "\033[31~", - "\033[32~", - "\033[33~", - "\033[34~", /* F20 */ - "\033[35~", - "\033[36~", - "\033[37~", - "\033[38~" + "\033[1;2P", /* VT100: LF */ + "\033[1;2Q", + "\033[1;2R", /* help */ + "\033[1;2S", /* do */ + "\033[15;2~", + "\033[17;2~", + "\033[18;2~", + "\033[19;2~", /* F20 */ + "\033[20;2~", + "\033[21;2~", + "\033[23;2~", + "\033[24;2~" }; static const u_char *vt100_pfkeys[] = { @@ -96,14 +94,22 @@ edp->translatebuf, edp->flags & VTFL_UTF8)); } - if (in >= KS_f1 && in <= KS_f24) { - *out = vt100_fkeys[in - KS_f1]; - return (5); + if (in >= KS_f1 && in <= KS_f4) { + *out = vt100_pfkeys[in - KS_f1]; + return (3); } - if (in >= KS_F1 && in <= KS_F24) { - *out = vt100_fkeys[in - KS_F1]; - return (5); + if (in >= KS_F1 && in <= KS_F4) { + *out = vt100_pfkeys[in - KS_F1]; + return (3); } + if (in >= KS_f5 && in <= KS_f24) { + *out = vt100_fkeys[in - KS_f5]; + return vt100_fkeys_len(in - KS_f5); + } + if (in >= KS_F5 && in <= KS_F24) { + *out = vt100_fkeys[in - KS_F5]; + return vt100_fkeys_len(in - KS_F5); + } if (in >= KS_KP_F1 && in <= KS_KP_F4) { *out = vt100_pfkeys[in - KS_KP_F1]; return (3); @@ -148,12 +154,12 @@ } switch (in) { case KS_Help: - *out = vt100_fkeys[15 - 1]; + *out = vt100_fkeys[15 - 1 + 4]; /* vt100_fkeys starts at F5 */ return (5); case KS_Execute: /* "Do" */ - *out = vt100_fkeys[16 - 1]; + *out = vt100_fkeys[16 - 1 + 4]; /* vt100_fkeys starts at F5 */ return (5); - case KS_Find: + case KS_Find: /* Not defined in xterm terminfo */ *out = "\033[1~"; return (4); case KS_Insert: @@ -163,7 +169,7 @@ case KS_KP_Delete: *out = "\033[3~"; return (4); - case KS_Select: + case KS_Select: /* Not defined in xterm terminfo */ *out = "\033[4~"; return (4); case KS_Prior: @@ -177,14 +183,24 @@ case KS_Backtab: *out = "\033[Z"; return (3); + /* + * Unlike insert, delete, page up, and page down, we purposely don't + * send the same sequence of \033OE for the non-keypad 'begin' key. + * + * This is because the terminfo xterm entry is mapping this to kb2, + * which is defined as 'centre of keypad'. + */ + case KS_KP_Begin: + *out = "\033OE"; + return (3); case KS_Home: case KS_KP_Home: - *out = "\033[7~"; - return (4); + *out = "\033OH"; + return (3); case KS_End: case KS_KP_End: - *out = "\033[8~"; - return (4); + *out = "\033OF"; + return (3); case KS_Up: case KS_KP_Up: if (edp->flags & VTFL_APPLCURSOR) --- sys/dev/wscons/wsemul_vt100_subr.c Mon Apr 7 04:42:48 2025 +++ sys/dev/wscons/wsemul_vt100_subr.c Wed Jun 4 13:36:39 2025 @@ -603,6 +603,12 @@ case 1: /* bold */ flags |= WSATTR_HILIT; break; + case 2: /* dim */ + flags |= WSATTR_DIM; + break; + case 3: /* italic */ + flags |= WSATTR_ITALIC; + break; case 4: /* underline */ flags |= WSATTR_UNDERLINE; break; @@ -612,11 +618,31 @@ case 7: /* reverse */ flags |= WSATTR_REVERSE; break; - case 22: /* ~bold VT300 only */ + /* + * Invisible text only makes the _glyph_ invisible. + * + * Other active attributes such as underlining and + * strikeout are still displayed in the character cell. + */ + case 8: /* invisible */ + flags |= WSATTR_INVISIBLE; + break; + case 9: /* strike */ + flags |= WSATTR_STRIKE; + break; + case 21: /* double underline */ + flags |= WSATTR_DOUBLE_UNDERLINE; + break; + case 22: /* ~bold ~dim VT300 only */ flags &= ~WSATTR_HILIT; + flags &= ~WSATTR_DIM; break; + case 23: /* ~italic */ + flags &= ~WSATTR_ITALIC; + break; case 24: /* ~underline VT300 only */ flags &= ~WSATTR_UNDERLINE; + flags &= ~WSATTR_DOUBLE_UNDERLINE; break; case 25: /* ~blink VT300 only */ flags &= ~WSATTR_BLINK; @@ -624,12 +650,76 @@ case 27: /* ~reverse VT300 only */ flags &= ~WSATTR_REVERSE; break; + case 28: /* ~invisible */ + flags &= ~WSATTR_INVISIBLE; + break; + case 29: /* ~strike */ + flags &= ~WSATTR_STRIKE; + break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: /* fg color */ flags |= WSATTR_WSCOLORS; fgcol = ARG(n) - 30; break; + /* + * Sequences starting CSI 38 escape to a larger + * colourspace, typically either 256 colours or 24-bit. + * + * We support CSI 38;5;X;m to set colour X from a + * palette of 256. + */ +#define EXIST_ARG2(i) ((edp->nargs-n)>=3) +#define ARG2_OR_DEF(i) (EXIST_ARG2(i) ? ARG(i+2) : 0) + case 38: + /* + * 38 followed by zero arguments is meaningless. + */ + if (edp->nargs == n+1) { + break ; + } + /* + * 5 should normally be followed by a single + * argument, but zero arguments is also valid to + * set colour zero. + */ + if (ARG(n+1)==5) { + flags |= WSATTR_WSCOLORS; + if (edp->scrcapabilities & + WSSCREEN_256COL) { + fgcol = ARG2_OR_DEF(n); + } else { + fgcol = (ARG2_OR_DEF(n) < 8 ? ARG2_OR_DEF(n) + : fgcol ); + } + n+=(EXIST_ARG2(n) ? 2 : 1); + break; + } + /* + * 2 should introduce a sequence of three + * arguments, specifying RGB. + * + * We don't, (yet!), support setting colours by + * 24-bit RGB arguments and don't want to + * interpret these as regular SGR codes. + * + * If there are more then three, skip just + * three, otherwise skip all of them. + */ + if (ARG(n+1)==2) { + n=(edp->nargs-n > 5 ? n+4 : + edp->nargs); + break; + } + /* + * Invalid code, I.E. not 2 or 5. + * + * We do what xterm does and just skip the + * single unrecognised argument, then allow any + * following arguments to be interpreted as SGR. + */ + n++; + break; case 39: /* reset fg color */ fgcol = WSCOL_WHITE; @@ -642,6 +732,29 @@ flags |= WSATTR_WSCOLORS; bgcol = ARG(n) - 40; break; + case 48: /* set 8-bit background colour */ + if (edp->nargs == n+1) { + break ; + } + if (ARG(n+1)==5) { + flags |= WSATTR_WSCOLORS; + if (edp->scrcapabilities & + WSSCREEN_256COL) { + bgcol = ARG2_OR_DEF(n); + } else { + bgcol = (ARG2_OR_DEF(n) < 8 ? ARG2_OR_DEF(n) + : bgcol ); + } + n+=(EXIST_ARG2(n) ? 2 : 1); + break; + } + if (ARG(n+1)==2) { + n=(edp->nargs-n > 5 ? n+4 : + edp->nargs); + break; + } + n++; + break; case 49: /* reset bg color */ bgcol = WSCOL_BLACK; --- sys/dev/wsfont/wsfont.c Mon Apr 7 04:25:23 2025 +++ sys/dev/wsfont/wsfont.c Wed Jun 4 13:36:39 2025 @@ -578,6 +578,9 @@ lc = ++ent->lockcount; *ptr = ent->font; + (*ptr)->data_bold = NULL; + (*ptr)->data_italic = NULL; + (*ptr)->data_bolditalic = NULL; } else lc = -1; @@ -592,6 +595,7 @@ wsfont_unlock(int cookie) { struct font *ent; + struct wsdisplay_font *ptr; int s, lc; s = splhigh(); @@ -599,6 +603,10 @@ if ((ent = wsfont_find0(cookie)) != NULL) { if (ent->lockcount == 0) panic("wsfont_unlock: font not locked"); + ptr = ent->font; + free (ptr->data_bold, M_TEMP, 0); + free (ptr->data_italic, M_TEMP, 0); + free (ptr->data_bolditalic, M_TEMP, 0); lc = --ent->lockcount; } else lc = -1;