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