koreth@ssyx.ucsc.edu (Steven Grimm) (05/20/88)
Submitted-by: egisin@watmath.waterloo.edu (Eric Gisin) Posting-number: Volume 1, Issue 33 Archive-name: vdit This is a partial PD VDI interface with support for loading GDOS fonts. See the file "readme" at the beginning of the shell archive. A set of PD GDOS fonts has been posted to comp.binaries.atari.st. [I don't know which C compiler was used to develop this program, but the code looks fairly non-compiler-specific. -sg] # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by watmath!egisin on Tue May 17 11:30:45 EDT 1988 # Contents: readme gfont.h loadfont.c vdi.c vdi.h vdit.c echo x - readme sed 's/^@//' > "readme" <<'@//E*O*F readme//' This package contains a partial public domain VDI interface. It includes a working interface to the undocumented VDI "load_fonts" and "unload_fonts" functions, which allow you to use other fixed and proportional fonts with GEM's VDI. See vdit.c for documentation and an example. Most of vdi.h/vdi.c is untested, except for the functions used by vdit.c and by my VT200 emulator. If you make any fixes or enhancements to the VDI I'd like to see them. I have also posted a public domain fixed width font family suitable for use with terminal emulators to comp.binaries.atari.st. vdi.h: structure and macro definitions for VDI vdi.c: interface functions for VDI gfont.h: definition of a GDOS font loadfont.c: load GDOS fonts from disk vdit.c: a simple program to load fonts and display them Eric Gisin, egisin@math.UWaterloo.CA @//E*O*F readme// chmod u=rw,g=r,o=r readme echo x - gfont.h sed 's/^@//' > "gfont.h" <<'@//E*O*F gfont.h//' /* * Internal representation of GDOS font. Author unknown. */ typedef struct { short font_id; /* Font face identifier, 1 -> system font */ short size; /* Font size in points */ char name[32]; /* Font name */ short first_ade; /* Lowest ADE value in the face */ short last_ade; /* Highest ADE value in the face */ short top; /* Distance of top line relative to baseline */ short ascent; /* Distance of ascent line relative to baseline */ short half; /* Distance of half line relative to baseline */ short descent; /* Distance of decent line relative to baseline */ short bottom; /* Distance of bottom line relative to baseline */ /* All distances are measured in absolute values */ /* rather than as offsets. They are always +ve */ short max_char_width; /* Width of the widest character in font */ short max_cell_width; /* Width of the widest cell character cell in face */ short loffset; /* Left Offset see Vdi appendix G */ short roffset; /* Right offset " " " */ short thicken; /* Number of pixels by which to thicken characters */ short ul_size; /* Width in pixels of the underline */ short lighten; /* The mask used to lighten characters */ short skew; /* The mask used to determine when to perform */ /* additional rotation on the character to perform skewing */ short flags; /* Flags */ /* $01 default system font */ /* 02 horiz offset table should be used */ /* 04 byte-swap flag (thanks to Motorla idiots) */ /* 08 mono spaced font */ short * hoff_base; /* Offset to horizontal offset table */ short * coff_base; /* Offset to character offset table */ /* font bitmap is byte[width][height], width must be even */ short * form_base; /* Offset to font data */ short form_width; /* Form width (#of bytes/scanline in font data) */ short form_height; /* Form height (#of scanlines in font data) */ char * next_font; /* Pointer to next font in face */ } GFont; @//E*O*F gfont.h// chmod u=rw,g=r,o=r gfont.h echo x - loadfont.c sed 's/^@//' > "loadfont.c" <<'@//E*O*F loadfont.c//' /* * Load GDOS font, Eric Gisin. * loads a font from file name.FED. Tries in ., then $FONTDIR, then A:\FONT. * does not have enough error checking. */ #define NULL 0L #include <gfont.h> #define open(file, mode) gemdos(0x3D, file,mode) #define close(fd) gemdos(0x3E, fd) #define read(fd, buf, size) gemdos(0x3F, fd,(long)size,buf) #define Swapw(v) (v) = ((v)<<8) | ((v)>>8)&0x00FF #define Swapl(v) (v) = ((v)>>24)&0x000000FF | ((v)>>8)&0x0000FF00 char * font_dir = NULL; extern char * malloc(); extern char * getenv(); /* * load GDOS font, return pointer to font. */ GFont * load_font(name) char * name; { int fd, i, n, size; char temp [64], * p = temp; char * q, * tcwd; int swapf; register GFont* fp; if (font_dir == NULL) font_dir = getenv("FONTDIR"); if (font_dir == NULL) font_dir = "A:\\font"; fp = malloc(sizeof(GFont)); if (fp == NULL) return NULL; /* set up font file's path name */ for (q = font_dir; *q; ) *p++ = *q++; *p++ = '\\'; tcwd = p; for (q = name; *q; ) *p++ = *q++; for (q = ".fed"; *q; ) *p++ = *q++; *p = '\0'; /* open font file */ fd = open(tcwd, 0); /* try name.fed */ if (fd < 0) fd = open(temp, 0); if (fd < 0) return (0); /* read header */ size = sizeof(GFont); read(fd, fp, size); /* should (char *)fp */ swapf = !(fp->flags&0x0004); if (swapf) { /* swap header words and longs */ Swapw(fp->font_id); Swapw(fp->size); Swapw(fp->first_ade); Swapw(fp->last_ade); Swapw(fp->top); Swapw(fp->ascent); Swapw(fp->half); Swapw(fp->descent); Swapw(fp->bottom); Swapw(fp->max_char_width); Swapw(fp->max_cell_width); Swapw(fp->loffset); Swapw(fp->roffset); Swapw(fp->thicken); Swapw(fp->ul_size); /* Swapw(fp->flags); */ Swapl(fp->hoff_base); Swapl(fp->coff_base); Swapl(fp->form_base); Swapw(fp->form_width); Swapw(fp->form_height); } /* read offset table */ n = fp->last_ade + 1 - fp->first_ade + 1; size = n * sizeof(short); fp->coff_base = malloc(size); if (fp->coff_base == NULL) return NULL; #if 0 for (i = 0; i < fp->first_ade; i++) fp->coff_base[i] = 0; #endif read(fd, fp->coff_base, size); if (swapf) /* swap offset array words */ for (i = 0; i < n; i++) Swapw(fp->coff_base[i]); /* read bitmap */ size = fp->form_width*fp->form_height; fp->form_base = malloc(size); if (fp->form_base == NULL) return NULL; read(fd, fp->form_base, size); close(fd); return fp; } /* load a set of fonts, linking them for vst_load_font */ GFont * load_fonts(fontv) char **fontv; { int errors = 0; /* should return */ GFont * fhead = NULL; GFont * f, ** fpp = &fhead; /* load fonts, create linked list fhead */ while (*fontv != NULL) { *fpp = f = load_font(*fontv++); if (f != NULL) fpp = &f->next_font; else errors++; } return fhead; } @//E*O*F loadfont.c// chmod u=rw,g=r,o=r loadfont.c echo x - vdi.c sed 's/^@//' > "vdi.c" <<'@//E*O*F vdi.c//' /* * PD mini VDI interface, Eric Gisin */ #include <osbind.h> #include <vdi.h> #include <gfont.h> #define NULL 0L static short ct [12]; /* VDI/AES control block */ static short ii [140]; static short pi [16]; static short io [47]; static short po [16]; struct Params v_ps = {ct, ii, pi, io, po, NULL}; struct Params v_pt = {ct, ii, pi, io, po, NULL}; /* modifiable version of v_ps */ /* VDI operations with no parameters */ vdi_none(h, op) short h, op; { vdi_setup(op, h, 0, 0); vdi(&v_ps); } /* VDI operations with one integer parameter */ vdi_int1(h, op, i) short h, op; short i; { ii[0] = i; vdi_setup(op, h, 1, 0); vdi(&v_ps); return io[0]; } /* VDI operations with one point parameter */ vdi_pnt1(h, op, x, y) short h, op; short x, y; { pi[0] = x, pi[1] = y; vdi_setup(op, h, 0, 1); vdi(&v_ps); } vdi_pnt4v(h, op, fn, pnt) short h; short op, fn; short *pnt; { register int i; for (i = 0; i < 4; i++) pi[i] = pnt[i]; vdi_setup(op, h, 0, 2); ct[5] = fn; vdi(&v_ps); } /* open virtual work */ v_opnvwk(in, hp, out) /* todo: vdi_open */ short in[]; short *hp; short out[]; { v_pt.ii = in; v_pt.io = out; v_pt.pi = pi; v_pt.po = out+34; vdi_setup(100, *hp, 11, 0); vdi(&v_pt); *hp = ct[6]; } vdi_cpyfm(h, op, mode, sdr, src, dst) short h, op; short mode; short *sdr; /* source/dest rectangles */ Form *src, *dst; /* source/dest forms */ { register int i; *((Form**)&ct[7]) = src; *((Form**)&ct[9]) = dst; ii[0] = mode; for (i = 0; i < 8; i++) pi[i] = sdr[i]; /*** *((Rect*)&pi[0]) = sdr[0]; *((Rect*)&pi[4]) = sdr[1]; ***/ vdi_setup(op, h, 1, 4); vdi(&v_ps); } vst_alignment(h, x, y, xp, yp) short h; short x, y; short *xp, *yp; { ii[0] = x, ii[1] = y; vdi_setup(39, h, 2, 0); vdi(&v_ps); *xp = io[0], *yp = io[1]; } v_gtext(h, x, y, s) short h; short x, y; unsigned char *s; { register int i; for (i = 0; *s != 0 && i < 140; i++) ii[i] = *s++; pi[0] = x; pi[1] = y; vdi_setup(8, h, i, 1); vdi(&v_ps); } vqt_attributes(h, at) short *at; /*struct vdi_tattr *at;*/ { v_pt.io = at; v_pt.po = at+6; vdi_setup(38, h, 0, 0); vdi(&v_pt); } static char *vdi_scratch = NULL; /* VDI/LineA scratch buffer */ #if 0 /* load GDOS fonts using user's vx_load_fonts */ vst_load_fonts(h, select) short h, select; { GFont * fp; extern char * malloc(); extern GFont * vx_load_fonts(); /* user routine to load fonts */ if (vdi_scratch == NULL) vdi_scratch = malloc(1024); /* scratch buffer */ *((char **)&ct[7]) = vdi_scratch; ct[9] = 256; /* offset of enlargment buffer */ *((char **)&ct[10]) = fp = vx_load_fonts(select); /* GDOS font list */ if (fp == 0) return 0; vdi_setup(119, h, 0, 0); vdi(&v_ps); return io[0]; /* number of fonts loaded */ } vst_unload_fonts(h) { extern void vx_unload_fonts(); vdi_setup(120, h, 0, 0); vdi(&v_ps); vx_unload_fonts(); } #endif /* load GDOS fonts using fp */ /* make sure your ct array is large enough if you port this */ vstx_load_fonts(h, fp) short h; GFont *fp; { extern char * malloc(); if (vdi_scratch == NULL) vdi_scratch = malloc(1024); /* scratch buffer */ *((char **)&ct[7]) = vdi_scratch; ct[9] = 256; /* offset of enlargment buffer */ *((char **)&ct[10]) = fp; if (fp == NULL) return 0; vdi_setup(119, h, 0, 0); vdi(&v_ps); return io[0]; /* number of fonts loaded */ } vstx_unload_fonts(h) { vdi_setup(120, h, 0, 0); vdi(&v_ps); } #if 0 /* * This code invokes VDI ESC 102 code (page 440 in the July '86 * Abacus ST Internals BIOS listing). I decompiled some library * routines to see how to make it work. It may not work on new ROMS. * Martin Minow, Arlington MA 02174. This routine is in the public domain. */ vt_set_font(fp) register GFont * fp; { (*(GFont**)&ii[0]) = fp; /* Put font info in intin[0] */ vdi_setup(5, 0, 2, 0); ct[5] = 102; vdi(&v_ps); } #endif @//E*O*F vdi.c// chmod u=rw,g=r,o=r vdi.c echo x - vdi.h sed 's/^@//' > "vdi.h" <<'@//E*O*F vdi.h//' /* * PD mini VDI interface, Eric Gisin */ /* Memory Form descriptor */ typedef struct { short * base; short width; short height; short wwidth; short standard; short planes; short resv1, resv2, resv3; } Form; /* Rectangle descriptor */ typedef struct { short x1, y1; /* upper left */ short x2, y2; /* lower right */ } Rect; /* VDI/AES parameter block */ struct Params { short *ct; /* control */ short *ii; /* ints in */ short *pi; /* points in */ short *io; /* ints out */ short *po; /* points out */ short *xx; }; #define vdi(params) bdos(115, params) #define vdi_setup(f, h, ii, pi) {ct[0] = f; ct[6] = h; ct[1] = pi; ct[3] = ii; } #define v_clsvwk(h) vdi_none(h, 101) #define v_clrwk(h) vdi_none(h, 3) #define vro_cpyfm(h, m, r, s, d) vdi_cpyfm(h, 109, m, r, s, d) #define vrt_cpyfm(h, m, r, s, d) vdi_cpyfm(h, 121, m, r, s, d) #define vsf_color(h, c) vdi_int1(h, 25, c) #define vsf_perimeter(h, f) vdi_int1(h, 104, f) #define vsf_interior(h, s) vdi_int1(h, 23, s) #define vsf_style(h, s) vdi_int1(h, 24, s) #define vst_color(h, c) vdi_int1(h, 22, c) #define vst_effects(h, e) vdi_int1(h, 106, e) #define vst_point(h, s) vdi_int1(h, 107, s) #define vst_rotation(h, a) vdi_int1(h, 13, a) #define vst_font(h, f) vdi_int1(h, 21, f) #define vswr_mode(h, m) vdi_int1(h, 32, m) #define vst_height(h, ht) vdi_pnt1(h, 12, 0, ht) #define v_bar(h, p) vdi_pnt4v(h, 11, 1, p) #define v_rbox(h, p) vdi_pnt4v(h, 11, 8, p) #define v_rfbox(h, p) vdi_pnt4v(h, 11, 9, p) #define v_recfl(h, p) vdi_pnt4v(h, 114, 0, p) @//E*O*F vdi.h// chmod u=rw,g=r,o=r vdi.h echo x - vdit.c sed 's/^@//' > "vdit.c" <<'@//E*O*F vdit.c//' /* * Sample program to load fonts, display them. Eric Gisin. * try: vdit -f91 fixed8 fixed9 fixed10 fixed11 fixed12 * * void vstx_load_fonts(short vdi_handle, GFont *fonts); * void vstx_unload_fonts(short vdi_handle); * * These two undocumented VDI functions are used to add fonts * to a virtual screen. Unlike the VDI function vst_load_fonts, * which requires GDOS, it does not load the fonts from disk. * Instead you load them explicitly with load_fonts (or load_font), * and pass the linked list of fonts to vstx_load_fonts as "fonts". * To change the fonts in a virtual screen, unload then load again. * * The fonts must have valid font_id and size information. * The font_id is used by vst_font to select a font family. */ #include <vdi.h> #include <gfont.h> #define NULL 0L extern GFont *load_fonts(); main(argc, argv) char ** argv; { register int i; int font = 1, size = 10; short h = 1; short in [11]; short out [57]; /* parse options */ for (i = 1; i < argc; i ++) { register char * arg = argv[i]; if (arg[0]=='-') { if (arg[1]=='f') font = atoi(&arg[2]); if (arg[1]=='p') size = atoi(&arg[2]); } else break; } /* set up opnvwk parameters */ in[0] = 1; /* device is screen */ in[1] = in[2] = 1; /* line type/color */ in[3] = in[4] = 1; /* marker type/color */ in[5] = in[6] = 1; /* text font/color */ in[7] = in[8] = in[9] = 1; /* fill type/style/color */ in[10] = 2; /* raster coordinates */ v_opnvwk(in, &h, out); vstx_load_fonts(h, load_fonts(&argv[i])); v_clrwk(h); i = vst_font(h, font); for (i = 6; i < 25; i += (i<14) ? 1 : 2) { vst_point(h, i); v_gtext(h, 0, i*16, "A test of load_fonts ?! {123<@>}"); } vstx_unload_fonts(h); v_clsvwk(h); return 0; } @//E*O*F vdit.c// chmod u=rw,g=r,o=r vdit.c exit 0