home *** CD-ROM | disk | FTP | other *** search
- /*
- ** font.c: hterm soft font driver
- *
- * Author: HIRANO Satoshi
- * (C) 1989 Halca Computer Science Laboratory TM
- * University of Tokyo
- *
- * Edition History:
- * 1.1 90/06/18 Halca.Hirano creation
- * 1.2 90/07/12 Halca.Hirano limit font cache size 64K
- *
- * $Header: font.cv 1.5 90/07/04 05:52:06 hirano Exp $
- *
- */
-
- #include "option.h"
- #ifdef SOFT_FONT
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <stdlib.h>
- #include "config.h"
- #include "hterm.h"
- #include "default.h"
- #include "global.h"
- #include "font.h"
-
- /*
- ** static variables
- */
- /*
- * physical line number to graphic VRAM address convertion table
- * index = physical line number
- * contents = VRAM address
- */
- static int ltopTab[MAX_LINE_25_MODE];
- /*
- * logical line number to VRAM address conversion function
- */
- #define ltop(y) (ltopTab[y])
-
- static FontDesc asciiFont;
- static FontDesc kanjiFont;
- static u_char FAR *vram;
- static char softCursor; /* soft cursor has been displayed or not */
- static int oldX = 0; /* old soft cursor position */
- static int oldY = 0;
- static char blinkState;
- static u_char FAR *kanjiFontCache; /* font cache buffer */
- static u_short FAR *fontHashTable; /* pointer to font cache hash table */
- static int kanjiFontSize; /* kanji font size in bytes */
- static int kanjiPath = 0; /* font file path number */
-
- void fontUnLoad(void);
- void reverseFont(int x,int y);
- u_char FAR *loadOneChar(u_short);
- char *fontRead(int path,FontDesc *fontDesc);
-
- /*
- ** void fontInit()
- *
- * initialize font driver; called once just after hterm startup
- */
- void fontInit()
- {
- char *p, *getenv();
-
- /*
- * J3100 note: GVRAM segment can't be determined here
- */
- FP_SEG(vram) = gvramSegment;
- FP_OFF(vram) = 0;
- softCursor = NO;
- if ((p = getenv("HTFONTCACHE")) == NULL) {
- fontCacheSize = DEFAULT_HIST_LINES;
- } else {
- fontCacheSize = atoi(p);
- if (fontCacheSize == 0)
- fontCacheSize = 20;
- }
- }
-
- /*
- ** void fontEnd()
- *
- * terminate soft font driver
- */
- void fontEnd()
- {
- fontUnLoad();
- }
-
- /*
- ** void softFontLocate(register short x, register short y)
- *
- * erase old soft cursor and write new soft cursor on position (x, y)
- */
- void softFontLocate(x, y)
- register short x, y;
- {
- if (softCursor && blinkState)
- reverseFont(oldX, oldY);
- reverseFont(x, y);
- blinkState = softCursor = YES;
- blinkTimer = BLINK_ON_INTERVAL;
- oldX = x; oldY = y;
- }
-
- /*
- ** void softCursorOnOff(register int onOff)
- *
- * erase or write soft cursor
- *
- * write cursor if old state is Off and new state is On
- * erase cursor if old state is On and new state is Off
- */
- void softCursorOnOff(onOff)
- register int onOff;
- {
- if ((softCursor && (onOff == NO) && blinkState) /* turn OFF condition */
- || ((softCursor == NO) && onOff && (blinkState == NO))) /* turn ON condition */
- reverseFont(oldX, oldY);
- blinkState = softCursor = onOff;
- blinkTimer = BLINK_ON_INTERVAL;
- }
-
- /*
- ** void blinkSoftCursor()
- *
- * blink cursor
- */
- void blinkSoftCursor()
- {
- if (softCursor) {
- reverseFont(oldX, oldY); /* erase or write cursor */
- blinkTimer = blinkState ? BLINK_ON_INTERVAL : BLINK_OFF_INTERVAL;
- blinkState = !blinkState;
- }
- }
-
- /*
- ** static void reverseFont(int x, int y)
- *
- * reverse a character at position (x, y)
- */
- static void reverseFont(x, y)
- int x, y;
- {
- register u_char FAR *p;
- register int d, w;
- int len, offset;
-
- /*
- * determine character size to reverse by VRAM backing store
- * If backing store is not supported, use
- * #define isKanjiOnVRAM(x,y) (0)
- */
- len = isKanjiOnVRAM(x, y) ? kanjiFont.wwidth : asciiFont.wwidth;
- /*
- * OK, reverse the character
- */
- p = vram + ltop(y) + x;
- offset = MAX_X_DOT/8;
- if (blockCursor) {
- p = p + (offset*1);
- d = asciiFont.dwidth-2;
- } else {
- p = p + offset*(asciiFont.dwidth - 2);
- d = 2;
- }
- for (; d > 0; --d) {
- for (w = len; w > 0; --w, p++)
- *p = ~*p;
- p = p + offset - len;
- }
- }
-
- /*
- ** void softFontPutChar(u_short c)
- *
- * put a character c on position (cursorX, cursorY) using attribute 'attrib'
- * c is hterm kanji code
- * currently reverse and underline attribute are supported.
- *
- * Just only this function touches font buffer.
- */
- void softFontPutChar(c)
- u_short c;
- {
- register u_char FAR *p;
- register u_char FAR *f;
- register int d, w;
- FontDesc *fnt;
- int offset;
-
- /*
- * cursor has already erased by conWrite()
- */
-
- if (c & 0xff00) {
- fnt = &kanjiFont;
- f = loadOneChar(c);
- } else {
- fnt = &asciiFont;
- if (c < fnt->startChar || fnt->endChar < c ||
- (f = (u_char FAR *)*(fnt->indexTab+(c-fnt->startChar))) == 0)
- f = (u_char FAR *)*(fnt->indexTab);
- }
-
- p = vram + ltop(cursorY) + cursorX;
- offset = MAX_X_DOT/8;
- #ifdef PC98
- if (attrib & B_REVER) {
- #endif
- #ifdef IBMPC
- if (attrib & 0x10) {
- #endif
- #ifdef J3100
- if (attrib & _REVER) {
- #endif
- for (d = fnt->dwidth; d > 0; --d) {
- for (w = fnt->wwidth; w > 0; --w)
- *p++ = ~*f++;
- p = p + offset - fnt->wwidth;
- }
- } else {
- for (d = fnt->dwidth; d > 0; --d) {
- for (w = fnt->wwidth; w > 0; --w)
- *p++ = *f++;
- p = p + offset - fnt->wwidth;
- }
- }
- #ifdef PC98
- if (attrib & B_UNDER) {
- #endif
- #if defined(IBMPC) || defined(J3100)
- if (attrib & _UNDER) {
- #endif
- p -= offset;
- for (w = fnt->wwidth; w > 0; --w)
- #ifdef PC98
- *p++ = (attrib & B_REVER) ? 0x00 : 0xff;
- #endif
- #ifdef IBMPC
- *p++ = (attrib & 0x10) ? 0x00 : 0xff;
- #endif
- #ifdef J3100
- *p++ = (attrib & _REVER) ? 0x00 : 0xff;
- #endif
- }
- /*
- * we must not rewrite cursor because backing store has not
- * been updated.
- */
- }
-
- /*
- ** void softFontInsertLine(int num)
- *
- * insert num lines at cursorY
- * filling of new blank lines are done in another place.
- */
- void softFontInsertLine(num)
- int num;
- {
- u_short vramSegmentSave = vramSegment;
-
- vramSegment = gvramSegment;
- moveBackward((u_short *)(ltop(cursorY+num)), (u_short *)(ltop(cursorY)),
- (lowScrRegion+1-cursorY-num)*(MAX_X_DOT/8*asciiFont.dwidth)/2, NO);
- vramSegment = vramSegmentSave;
- }
-
- /*
- ** softFontDeleteLine(int num)
- *
- * void delete num lines at cursorY
- * filling of new blank lines are done in another place.
- */
- void softFontDeleteLine(num)
- int num;
- {
- u_short vramSegmentSave = vramSegment;
-
- vramSegment = gvramSegment;
- moveForward((u_short *)(ltop(cursorY)), (u_short *)(ltop(cursorY+num)),
- (lowScrRegion+1-cursorY-num)*(MAX_X_DOT/8*asciiFont.dwidth)/2, NO);
- vramSegment = vramSegmentSave;
- }
-
- /*
- ** void softFontInsertChar(int at, int n)
- *
- * insert n blanks at 'at' on cursorY
- */
- void softFontInsertChar(at, n)
- int at;
- int n;
- {
- register int i;
- register int p;
- int offset;
- int moveNum = MAX_COLUMN-at-n;
-
- if (moveNum > 0) {
- p = ltop(cursorY)+at;
- offset = MAX_X_DOT/8;
- for (i = 0; i < kanjiFont.dwidth; i++) {
- moveBackByte((u_short *)(p+n), (u_short *)p, moveNum*asciiFont.wwidth);
- p += offset;
- }
- } else
- n = MAX_COLUMN-at;
- softFontClearColumn(at, at+n);
- }
-
- /*
- ** void softFontDeleteChar(int at, int n)
- *
- * delete n blanks at 'at' on cursorY
- */
- void softFontDeleteChar(at, n)
- int at;
- int n;
- {
- register int i;
- register int p;
- int offset;
- int moveNum = MAX_COLUMN-at-n;
-
- if (moveNum > 0) {
- p = ltop(cursorY)+at;
- offset = MAX_X_DOT/8;
- for (i = 0; i < kanjiFont.dwidth; i++) {
- moveForByte((u_short *)p, (u_short *)(p+n), moveNum*asciiFont.wwidth);
- p += offset;
- }
- } else
- n = MAX_COLUMN-at;
- softFontClearColumn(MAX_COLUMN-n, MAX_COLUMN);
- }
-
- /*
- ** void softFontClearColumn(register u_shrot from, register u_short to)
- *
- * clear column 'from' to 'to'-1 on cursorY line,
- */
- void softFontClearColumn(from, to)
- u_short from, to;
- {
- register u_char FAR *p, FAR *q;
- register int i, d, w;
- int offset;
- u_char filler;
-
- q = p = vram + ltop(cursorY) + from;
- offset = MAX_X_DOT/8;
- #ifdef PC98
- filler = (eraseAttr & B_REVER) ? 0xff : 0;
- #endif
- #ifdef IBMPC
- filler = (eraseAttr & 0x10) ? 0xff : 0;
- #endif
- #ifdef J3100
- filler = (eraseAttr & _REVER) ? 0xff : 0;
- #endif
- for (i = to-from; i > 0; --i) {
- for (d = asciiFont.dwidth; d > 0; --d) {
- for (w = asciiFont.wwidth; w > 0; --w)
- *p++ = filler;
- p = p + offset - asciiFont.wwidth;
- }
- p = ++q;
- }
- }
-
- /*
- ** void softFontClearLine(y)
- *
- * clear line
- */
- void softFontClearLine(y)
- int y;
- {
- register u_long FAR *p = (u_long FAR *)(vram + ltop(y));
- register int i;
- u_long filler;
-
- #ifdef PC98
- filler = (eraseAttr & B_REVER) ? 0xffffffffL : 0L;
- #endif
- #ifdef IBMPC
- filler = (eraseAttr & 0x10) ? 0xffffffffL : 0L;
- #endif
- #ifdef J3100
- filler = (eraseAttr & _REVER) ? 0xffffffffL : 0L;
- #endif
- for (i = asciiFont.dwidth*((MAX_X_DOT/8)/sizeof(long)); i > 0; --i)
- *p++ = filler;
- }
-
- /*
- ** void softFontReverseScreen()
- *
- * reverse GVRAM screen
- */
- void softFontReverseScreen()
- {
- long FAR *p;
- int i, j;
-
- FP_SEG(p) = gvramSegment;
- FP_OFF(p) = 0;
- for (i = MAX_Y_DOT; i > 0; --i)
- for (j = (MAX_X_DOT/8)/sizeof(long); j > 0; --j, p++)
- *p = ~*p;
- }
-
- /*
- ** static u_char FAR *loadOneChar(u_short code)
- *
- * return pointer to font body by code
- * NOTE: code must be JIS kanji code
- */
- static u_char FAR *loadOneChar(code)
- register u_short code;
- {
- register int rehashValue;
- register int hashValue;
- u_char FAR *f;
- static u_char fontTempBuf[100];
- int i;
- u_short val;
-
- /*
- * check code validity
- */
- if (code < kanjiFont.startChar || kanjiFont.endChar < code)
- code = JIS_SPACE;
-
- /*
- * check font existence
- */
- if ((f = (u_char FAR *)*(kanjiFont.indexTab+(code - kanjiFont.startChar))) == 0) {
- f = (u_char FAR *)*(kanjiFont.indexTab); /* return SPACE */
- return(f);
- }
-
- /*
- * first look at parmanent cache
- */
- if (code <= kanjiFont.onMemEndChar) { /* certainly on memory */
- return(f);
- }
-
- /*
- * next look at cache
- */
- rehashValue = hashValue = (code*13) % fontCacheSize;
- #define MAX_REHASH 10
- for (i = MAX_REHASH; i > 0; --i) {
- if ((val = fontHashTable[rehashValue]) == code) { /* found in hash table */
- f = (u_char FAR *)&kanjiFontCache[rehashValue*kanjiFontSize];
- return(f);
- } else if (val == 0) { /* found empty slot */
- hashValue = rehashValue;
- break;
- } else
- rehashValue = (rehashValue + 17) % fontCacheSize;
- }
- /*
- * while replacing algorithm is not so good, this code will
- * macth first at next time.
- */
- fontHashTable[hashValue] = code;
- lseek(kanjiPath, (long)f, 0);
- f = (u_char FAR *)&kanjiFontCache[hashValue*kanjiFontSize];
- read(kanjiPath, fontTempBuf, kanjiFontSize);
- moveData(f, (u_char FAR *)fontTempBuf, kanjiFontSize);
- return(f);
- }
-
- /*
- ** char *fontLoad(fontName)
- *
- * load font file
- *
- * search font file named 'fontName' on current directory, HOME directory
- * and PATH directory.
- * return a poitner to error message string
- */
- char *fontLoad(fontName)
- char *fontName;
- {
- FontFile fontFile;
- char *fontPath;
- int i, p;
- char *errmsg;
- char *fontRead();
-
- if (fontFileLoaded)
- return((char *)NULL);
-
- if ((fontPath = searchPath(fontName)) == NULL)
- goto err;
- if ((kanjiPath = open(fontPath, O_RDONLY|O_BINARY)) == ERR ||
- read(kanjiPath, (char *)&fontFile, sizeof(FontFile)) == ERR) {
- (void)close(kanjiPath);
- kanjiPath = 0;
- err:
- return("can't find font file");
- }
- asciiFont = fontFile.ascii;
- kanjiFont = fontFile.kanji;
- errmsg = fontRead(kanjiPath, &(asciiFont));
- if (errmsg) {
- goto err2;
- }
- errmsg = fontRead(kanjiPath, &(kanjiFont));
- if (errmsg) {
- err2: fontUnLoad();
- return(errmsg);
- }
-
- /*
- * build line number conversion table
- */
- p = 0;
- for (i = 0; i < MAX_LINE_25_MODE; i++) {
- /* physical line no to GRAPHIC VRAM address conversion table */
- ltopTab[i] = p;
- p += (MAX_X_DOT/8)*asciiFont.dwidth;
- }
-
- /*
- * clear cache
- */
- for (i = 0; i < fontCacheSize; i++)
- fontHashTable[i] = 0;
-
- fontFileLoaded = YES;
- return((char *)NULL);
- }
-
- /*
- ** static void fontUnLoad()
- *
- * unload font; free font memory
- */
- static void fontUnLoad()
- {
- freeMem((void FAR *)asciiFont.indexTab);
- freeMem((void FAR *)asciiFont.fontBuf);
- freeMem((void FAR *)kanjiFont.indexTab);
- freeMem((void FAR *)kanjiFont.fontBuf);
- freeMem((void FAR *)kanjiFontCache);
- freeMem((void FAR *)fontHashTable);
- asciiFont.indexTab = kanjiFont.indexTab = (long HUGE *)0;
- asciiFont.fontBuf = kanjiFont.fontBuf = (char FAR *)0;
- kanjiFontCache = (u_char FAR *)0;
- fontHashTable = (u_short FAR *)0;
- fontFileLoaded = NO;
- if (kanjiPath) {
- close(kanjiPath);
- kanjiPath = 0;
- }
- }
-
- /*
- ** static char *fontRead(FILE *ifp, FontDesc *fontDesc, int hashMode)
- *
- * read one font file into memory
- *
- * NOTE:
- * Font file consists of font body part and index part.
- *
- * Fonts in font part are able to separate on memory part and
- * off memory part. While on memory part is stored in fontBuf[],
- * off memory part is not stored. On memory part is defined
- * by fontDesc->onMemEndChar and number of font is fontDesc->numOnMemFont.
- *
- * All of index part is stored on memory indexTable[]. Index points
- * font body in fontBuf[] for on memory partial of font body.
- * And index points address in the font file for off memory partial
- * respectively.
- *
- */
- static char *fontRead(path, fontDesc)
- int path;
- FontDesc *fontDesc;
- {
- long fontSize;
- long indexSize;
- register long HUGE *indexp;
- register char FAR *fontp;
- register char *p;
- short offset;
- short *q;
- int size;
- u_short code;
-
- /*
- * calculate font body size and font index size
- */
- kanjiFontSize = fontDesc->wwidth * fontDesc->dwidth;
- fontSize = (long)(fontDesc->numOnMemFont) * (long)kanjiFontSize;
- indexSize = (long)(fontDesc->numIndex) * sizeof(long);
-
- #ifdef DEBUG
- printf("\nfontSize %ld, indexSize %ld\n", fontSize, indexSize);
- #endif
- /*
- * allocate index table memory
- * allocate font memory
- */
- fontDesc->indexTab = (long HUGE *)allocMem(indexSize);
- fontDesc->fontBuf = (char FAR *)allocMem(fontSize);
- if (fontDesc->indexTab == 0 || fontDesc->fontBuf == 0)
- goto memErr;
- /*
- * allocate font cache memory
- */
- if (fontDesc->onMemEndChar < fontDesc->endChar) {
- if ((long)kanjiFontSize*fontCacheSize > 0x10000L)
- fontCacheSize = 0xff00L / (long)kanjiFontSize;
- kanjiFontCache = (u_char FAR *)allocMem((long)kanjiFontSize*fontCacheSize);
- fontHashTable = (u_short FAR *)allocMem((long)fontCacheSize*sizeof(u_short));
- if (kanjiFontCache == 0 || fontHashTable == 0) {
- memErr:
- return("Can't allocate font memory, check $HTFONTCACHE");
- }
- }
-
- /*
- * read font body part
- */
- lseek(path, fontDesc->fontAddress, 0);
- #ifdef DEBUG
- printf("body address in file %ld, real %ld\n", fontDesc->fontAddress, tell(path));
- #endif
- fontp = fontDesc->fontBuf;
- while (fontSize > 0) {
- size = (int)(fontSize < MAX_XFER_BUF ? fontSize : MAX_XFER_BUF);
- if ((size = read(path, XFerBuffer, size)) == ERR) {
- goto fontErr;
- }
- fontSize -= size;
- for (p = XFerBuffer; size > 0; --size)
- *fontp++ = *p++;
- }
-
- /*
- * read font index part
- */
- lseek(path, fontDesc->indexAddress, 0);
- #ifdef DEBUG
- printf("index address in file %ld, real %ld\n", fontDesc->indexAddress, tell(path));
- #endif
- indexSize = (long)(fontDesc->numIndex);
- indexp = fontDesc->indexTab;
- /*
- * first char; extra treatment because offset is always 0
- */
- code = fontDesc->startChar;
- read(path, (char *)&offset, sizeof(short));
- *indexp++ = (long)(fontDesc->fontBuf);
- indexSize--;
- code++;
-
- /*
- * read and store index
- */
- while (indexSize > 0) {
- size = (int)(indexSize < (MAX_XFER_BUF/sizeof(short)) ? indexSize : (MAX_XFER_BUF/sizeof(short)));
- if ((size = read(path, XFerBuffer, size*sizeof(short))) == ERR) {
- fontErr:
- return("unexpected EOF in font file");
- }
- size /= 2;
- indexSize -= size;
- for (q = (short *)XFerBuffer; size > 0; --size, q++, code++) {
- if (*q == 0)
- /*
- * font for not defined font
- */
- *indexp++ = 0L;
- else if (code <= fontDesc->onMemEndChar)
- /*
- * on memory font; store index to font body in fontBuf[]
- */
- *indexp++ = (long)(fontDesc->fontBuf) + (long)(*q)*(long)kanjiFontSize;
- else
- /*
- * off memory font; store address of font body in the font file
- */
- *indexp++ = (long)(fontDesc->fontAddress) + (long)(*q)*(long)kanjiFontSize;
- }
- }
- #if DEBUG
- printf("load done\n");
- #endif
- return((char *)NULL);
- }
-
-
- #else /* SOFT_FONT */
- void fontInit(){}
- void fontEnd(){}
- void softFontLocate(){}
- void softCursorOnOff(){}
- void softFontPutChar(){}
- void softFontInsertLine(){}
- void softFontDeleteLine(){}
- void softFontInsertChar(){}
- void softFontDeleteChar(){}
- void softFontClearColumn(){}
- void softFontClearLine(){}
- char *fontLoad(){return((char *)0);}
- void fontUnLoad(){}
- #endif /* SOFT_FONT */
-