an old saddle
This commit is contained in:
parent
24c02865d8
commit
020c80587a
7 changed files with 1559 additions and 0 deletions
372
src/cmd/proof/font.c
Normal file
372
src/cmd/proof/font.c
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <event.h>
|
||||
#include <bio.h>
|
||||
#include "proof.h"
|
||||
|
||||
char fname[NFONT][20]; /* font names */
|
||||
char lastload[NFONT][20]; /* last file name prefix loaded for this font */
|
||||
Font *fonttab[NFONT][NSIZE]; /* pointers to fonts */
|
||||
int fmap[NFONT]; /* what map to use with this font */
|
||||
|
||||
static void loadfont(int, int);
|
||||
static void fontlookup(int, char *);
|
||||
static void buildxheight(Biobuf*);
|
||||
static void buildmap(Biobuf*);
|
||||
static void buildtroff(char *);
|
||||
static void addmap(int, char *, int);
|
||||
static char *map(Rune*, int);
|
||||
static void scanstr(char *, char *, char **);
|
||||
|
||||
int specfont; /* somehow, number of special font */
|
||||
|
||||
#define NMAP 5
|
||||
#define QUICK 2048 /* char values less than this are quick to look up */
|
||||
#define eq(s,t) strcmp((char *) s, (char *) t) == 0
|
||||
|
||||
int curmap = -1; /* what map are we working on */
|
||||
|
||||
typedef struct Link Link;
|
||||
struct Link /* link names together */
|
||||
{
|
||||
uchar *name;
|
||||
int val;
|
||||
Link *next;
|
||||
};
|
||||
|
||||
typedef struct Map Map;
|
||||
struct Map /* holds a mapping from uchar name to index */
|
||||
{
|
||||
double xheight;
|
||||
Rune quick[QUICK]; /* low values get special treatment */
|
||||
Link *slow; /* other stuff goes into a link list */
|
||||
};
|
||||
|
||||
Map charmap[5];
|
||||
|
||||
typedef struct Fontmap Fontmap;
|
||||
struct Fontmap /* mapping from troff name to filename */
|
||||
{
|
||||
char *troffname;
|
||||
char *prefix;
|
||||
int map; /* which charmap to use for this font */
|
||||
char *fallback; /* font to look in if can't find char here */
|
||||
};
|
||||
|
||||
Fontmap fontmap[100];
|
||||
int pos2fontmap[NFONT]; /* indexed by troff font position, gives Fontmap */
|
||||
int nfontmap = 0; /* how many are there */
|
||||
|
||||
|
||||
void
|
||||
dochar(Rune r[])
|
||||
{
|
||||
char *s, *fb;
|
||||
Font *f;
|
||||
Point p;
|
||||
int fontno, fm, i;
|
||||
char buf[10];
|
||||
|
||||
fontno = curfont;
|
||||
if((s = map(r, curfont)) == 0){ /* not on current font */
|
||||
if ((s = map(r, specfont)) != 0) /* on special font */
|
||||
fontno = specfont;
|
||||
else{
|
||||
/* look for fallback */
|
||||
fm = pos2fontmap[curfont];
|
||||
fb = fontmap[fm].fallback;
|
||||
if(fb){
|
||||
/* see if fallback is mounted */
|
||||
for(i = 0; i < NFONT; i++){
|
||||
if(eq(fb, fontmap[pos2fontmap[i]].troffname)){
|
||||
s = map(r, i);
|
||||
if(s){
|
||||
fontno = i;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* no such char; use name itself on defont */
|
||||
/* this is not a general solution */
|
||||
p.x = hpos/DIV + xyoffset.x + offset.x;
|
||||
p.y = vpos/DIV + xyoffset.y + offset.y;
|
||||
p.y -= font->ascent;
|
||||
sprint(buf, "%S", r);
|
||||
string(screen, p, display->black, ZP, font, buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
found:
|
||||
p.x = hpos/DIV + xyoffset.x + offset.x;
|
||||
p.y = vpos/DIV + xyoffset.y + offset.y;
|
||||
while ((f = fonttab[fontno][cursize]) == 0)
|
||||
loadfont(fontno, cursize);
|
||||
p.y -= f->ascent;
|
||||
dprint(2, "putting %S at %d,%d font %d, size %d\n", r, p.x, p.y, fontno, cursize);
|
||||
string(screen, p, display->black, ZP, f, s);
|
||||
}
|
||||
|
||||
static int drawlog2[] = {
|
||||
0, 0,
|
||||
1, 1,
|
||||
2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5
|
||||
};
|
||||
|
||||
static void
|
||||
loadfont(int n, int s)
|
||||
{
|
||||
char file[100];
|
||||
int i, fd, t, deep;
|
||||
static char *try[3] = {"", "times/R.", "pelm/"};
|
||||
Subfont *f;
|
||||
Font *ff;
|
||||
|
||||
try[0] = fname[n];
|
||||
dprint(2, "loadfont %d %d\n", n, s);
|
||||
for (t = 0; t < 3; t++){
|
||||
i = s * mag * charmap[fmap[n]].xheight/0.72; /* a pixel is 0.72 points */
|
||||
if (i < MINSIZE)
|
||||
i = MINSIZE;
|
||||
dprint(2, "size %d, i %d, mag %g\n", s, i, mag);
|
||||
for(; i >= MINSIZE; i--){
|
||||
/* if .font file exists, take that */
|
||||
sprint(file, "%s/%s%d.font", libfont, try[t], i);
|
||||
ff = openfont(display, file);
|
||||
if(ff != 0){
|
||||
fonttab[n][s] = ff;
|
||||
dprint(2, "using %s for font %d %d\n", file, n, s);
|
||||
return;
|
||||
}
|
||||
/* else look for a subfont file */
|
||||
for (deep = drawlog2[screen->depth]; deep >= 0; deep--){
|
||||
sprint(file, "%s/%s%d.%d", libfont, try[t], i, deep);
|
||||
dprint(2, "trying %s for %d\n", file, i);
|
||||
if ((fd = open(file, 0)) >= 0){
|
||||
f = readsubfont(display, file, fd, 0);
|
||||
if (f == 0) {
|
||||
fprint(2, "can't rdsubfontfile %s: %r\n", file);
|
||||
exits("rdsubfont");
|
||||
}
|
||||
close(fd);
|
||||
ff = mkfont(f, 0);
|
||||
if(ff == 0){
|
||||
fprint(2, "can't mkfont %s: %r\n", file);
|
||||
exits("rdsubfont");
|
||||
}
|
||||
fonttab[n][s] = ff;
|
||||
dprint(2, "using %s for font %d %d\n", file, n, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprint(2, "can't find font %s.%d or substitute, quitting\n", fname[n], s);
|
||||
exits("no font");
|
||||
}
|
||||
|
||||
void
|
||||
loadfontname(int n, char *s)
|
||||
{
|
||||
int i;
|
||||
Font *f, *g = 0;
|
||||
|
||||
if (strcmp(s, fname[n]) == 0)
|
||||
return;
|
||||
if(fname[n] && fname[n][0]){
|
||||
if(lastload[n] && strcmp(lastload[n], fname[n]) == 0)
|
||||
return;
|
||||
strcpy(lastload[n], fname[n]);
|
||||
}
|
||||
fontlookup(n, s);
|
||||
for (i = 0; i < NSIZE; i++)
|
||||
if (f = fonttab[n][i]){
|
||||
if (f != g) {
|
||||
freefont(f);
|
||||
g = f;
|
||||
}
|
||||
fonttab[n][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
allfree(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NFONT; i++)
|
||||
loadfontname(i, "??");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
readmapfile(char *file)
|
||||
{
|
||||
Biobuf *fp;
|
||||
char *p, cmd[100];
|
||||
|
||||
if ((fp=Bopen(file, OREAD)) == 0){
|
||||
fprint(2, "proof: can't open map file %s\n", file);
|
||||
exits("urk");
|
||||
}
|
||||
while((p=Brdline(fp, '\n')) != 0) {
|
||||
p[Blinelen(fp)-1] = 0;
|
||||
scanstr(p, cmd, 0);
|
||||
if(p[0]=='\0' || eq(cmd, "#")) /* skip comments, empty */
|
||||
continue;
|
||||
else if(eq(cmd, "xheight"))
|
||||
buildxheight(fp);
|
||||
else if(eq(cmd, "map"))
|
||||
buildmap(fp);
|
||||
else if(eq(cmd, "special"))
|
||||
buildtroff(p);
|
||||
else if(eq(cmd, "troff"))
|
||||
buildtroff(p);
|
||||
else
|
||||
fprint(2, "weird map line %s\n", p);
|
||||
}
|
||||
Bterm(fp);
|
||||
}
|
||||
|
||||
static void
|
||||
buildxheight(Biobuf *fp) /* map goes from char name to value to print via *string() */
|
||||
{
|
||||
char *line;
|
||||
|
||||
line = Brdline(fp, '\n');
|
||||
if(line == 0){
|
||||
fprint(2, "proof: bad map file\n");
|
||||
exits("map");
|
||||
}
|
||||
charmap[curmap].xheight = atof(line);
|
||||
}
|
||||
|
||||
static void
|
||||
buildmap(Biobuf *fp) /* map goes from char name to value to print via *string() */
|
||||
{
|
||||
uchar *p, *line, ch[100];
|
||||
int val;
|
||||
Rune r;
|
||||
|
||||
curmap++;
|
||||
if(curmap >= NMAP){
|
||||
fprint(2, "proof: out of char maps; recompile\n");
|
||||
exits("charmap");
|
||||
}
|
||||
while ((line = Brdline(fp, '\n'))!= 0){
|
||||
if (line[0] == '\n')
|
||||
return;
|
||||
line[Blinelen(fp)-1] = 0;
|
||||
scanstr((char *) line, (char *) ch, (char **)(void*)&p);
|
||||
if (ch[0] == '\0') {
|
||||
fprint(2, "bad map file line '%s'\n", (char*)line);
|
||||
continue;
|
||||
}
|
||||
val = strtol((char *) p, 0, 10);
|
||||
dprint(2, "buildmap %s (%x %x) %s %d\n", (char*)ch, ch[0], ch[1], (char*)p, val);
|
||||
chartorune(&r, (char*)ch);
|
||||
if(utflen((char*)ch)==1 && r<QUICK)
|
||||
charmap[curmap].quick[r] = val;
|
||||
else
|
||||
addmap(curmap, strdup((char *) ch), val); /* put somewhere else */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
addmap(int n, char *s, int val) /* stick a new link on */
|
||||
{
|
||||
Link *p = (Link *) malloc(sizeof(Link));
|
||||
Link *prev = charmap[n].slow;
|
||||
|
||||
if(p == 0)
|
||||
exits("out of memory in addmap");
|
||||
p->name = (uchar *) s;
|
||||
p->val = val;
|
||||
p->next = prev;
|
||||
charmap[n].slow = p;
|
||||
}
|
||||
|
||||
static void
|
||||
buildtroff(char *buf) /* map troff names into bitmap filenames */
|
||||
{ /* e.g., R -> times/R., I -> times/I., etc. */
|
||||
char *p, cmd[100], name[200], prefix[400], fallback[100];
|
||||
|
||||
scanstr(buf, cmd, &p);
|
||||
scanstr(p, name, &p);
|
||||
scanstr(p, prefix, &p);
|
||||
while(*p!=0 && isspace(*p))
|
||||
p++;
|
||||
if(*p != 0){
|
||||
scanstr(p, fallback, &p);
|
||||
fontmap[nfontmap].fallback = strdup(fallback);
|
||||
}else
|
||||
fontmap[nfontmap].fallback = 0;
|
||||
fontmap[nfontmap].troffname = strdup(name);
|
||||
fontmap[nfontmap].prefix = strdup(prefix);
|
||||
fontmap[nfontmap].map = curmap;
|
||||
dprint(2, "troff name %s is bitmap %s map %d in slot %d fallback %s\n", name, prefix, curmap, nfontmap, fontmap[nfontmap].fallback? fontmap[nfontmap].fallback : "<null>");
|
||||
nfontmap++;
|
||||
}
|
||||
|
||||
static void
|
||||
fontlookup(int n, char *s) /* map troff name of s into position n */
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nfontmap; i++)
|
||||
if (eq(s, fontmap[i].troffname)) {
|
||||
strcpy(fname[n], fontmap[i].prefix);
|
||||
fmap[n] = fontmap[i].map;
|
||||
pos2fontmap[n] = i;
|
||||
if (eq(s, "S"))
|
||||
specfont = n;
|
||||
dprint(2, "font %d %s is %s\n", n, s, fname[n]);
|
||||
return;
|
||||
}
|
||||
/* god help us if this font isn't there */
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
map(Rune rp[], int font) /* figure out mapping for char in this font */
|
||||
{
|
||||
static char s[100];
|
||||
char c[10];
|
||||
Link *p;
|
||||
Rune r;
|
||||
|
||||
if(rp[1]==0 && rp[0]<QUICK) /* fast lookup */
|
||||
r = charmap[fmap[font]].quick[rp[0]];
|
||||
else { /* high-valued or compound character name */
|
||||
sprint(c, "%S", rp);
|
||||
r = 0;
|
||||
for (p = charmap[fmap[font]].slow; p; p = p->next)
|
||||
if(eq(c, p->name)){
|
||||
r = p->val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(r == 0){ /* not there */
|
||||
dprint(2, "didn't find %S font# %d\n", rp, font);
|
||||
return 0;
|
||||
}
|
||||
dprint(2, "map %S to %s font# %d\n", rp, s, font);
|
||||
s[runetochar(s, &r)] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
scanstr(char *s, char *ans, char **ep)
|
||||
{
|
||||
for (; isspace((uchar) *s); s++)
|
||||
;
|
||||
for (; *s!=0 && !isspace((uchar) *s); )
|
||||
*ans++ = *s++;
|
||||
*ans = 0;
|
||||
if (ep)
|
||||
*ep = s;
|
||||
}
|
||||
579
src/cmd/proof/htroff.c
Normal file
579
src/cmd/proof/htroff.c
Normal file
|
|
@ -0,0 +1,579 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <cursor.h>
|
||||
#include <event.h>
|
||||
#include <bio.h>
|
||||
#include "proof.h"
|
||||
|
||||
int res;
|
||||
int hpos;
|
||||
int vpos;
|
||||
int DIV = 11;
|
||||
|
||||
Point offset;
|
||||
Point xyoffset = { 0,0 };
|
||||
|
||||
Rectangle view[MAXVIEW];
|
||||
Rectangle bound[MAXVIEW]; /* extreme points */
|
||||
int nview = 1;
|
||||
|
||||
int lastp; /* last page number we were on */
|
||||
|
||||
#define NPAGENUMS 200
|
||||
struct pagenum {
|
||||
int num;
|
||||
long adr;
|
||||
} pagenums[NPAGENUMS];
|
||||
int npagenums;
|
||||
|
||||
int curfont, cursize;
|
||||
|
||||
char *getcmdstr(void);
|
||||
|
||||
static void initpage(void);
|
||||
static void view_setup(int);
|
||||
static Point scale(Point);
|
||||
static void clearview(Rectangle);
|
||||
static int addpage(int);
|
||||
static void spline(Image *, int, Point *);
|
||||
static int skipto(int, int);
|
||||
static void wiggly(int);
|
||||
static void devcntrl(void);
|
||||
static void eatline(void);
|
||||
static int getn(void);
|
||||
static int botpage(int);
|
||||
static void getstr(char *);
|
||||
/*
|
||||
static void getutf(char *);
|
||||
*/
|
||||
|
||||
#define Do screen->r.min
|
||||
#define Dc screen->r.max
|
||||
|
||||
/* declarations and definitions of font stuff are in font.c and main.c */
|
||||
|
||||
static void
|
||||
initpage(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
view_setup(nview);
|
||||
for (i = 0; i < nview-1; i++)
|
||||
draw(screen, view[i], screen, nil, view[i+1].min);
|
||||
clearview(view[nview-1]);
|
||||
offset = view[nview-1].min;
|
||||
vpos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
view_setup(int n)
|
||||
{
|
||||
int i, j, v, dx, dy, r, c;
|
||||
|
||||
switch (n) {
|
||||
case 1: r = 1; c = 1; break;
|
||||
case 2: r = 1; c = 2; break;
|
||||
case 3: r = 1; c = 3; break;
|
||||
case 4: r = 2; c = 2; break;
|
||||
case 5: case 6: r = 2; c = 3; break;
|
||||
case 7: case 8: case 9: r = 3; c = 3; break;
|
||||
default: r = (n+2)/3; c = 3; break; /* finking out */
|
||||
}
|
||||
dx = (Dc.x - Do.x) / c;
|
||||
dy = (Dc.y - Do.y) / r;
|
||||
v = 0;
|
||||
for (i = 0; i < r && v < n; i++)
|
||||
for (j = 0; j < c && v < n; j++) {
|
||||
view[v] = screen->r;
|
||||
view[v].min.x = Do.x + j * dx;
|
||||
view[v].max.x = Do.x + (j+1) * dx;
|
||||
view[v].min.y = Do.y + i * dy;
|
||||
view[v].max.y = Do.y + (i+1) * dy;
|
||||
v++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clearview(Rectangle r)
|
||||
{
|
||||
draw(screen, r, display->white, nil, r.min);
|
||||
}
|
||||
|
||||
int resized;
|
||||
void eresized(int new)
|
||||
{
|
||||
/* this is called if we are resized */
|
||||
if(new && getwindow(display, Refnone) < 0)
|
||||
drawerror(display, "can't reattach to window");
|
||||
initpage();
|
||||
resized = 1;
|
||||
}
|
||||
|
||||
static Point
|
||||
scale(Point p)
|
||||
{
|
||||
p.x /= DIV;
|
||||
p.y /= DIV;
|
||||
return addpt(xyoffset, addpt(offset,p));
|
||||
}
|
||||
|
||||
static int
|
||||
addpage(int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < npagenums; i++)
|
||||
if (n == pagenums[i].num)
|
||||
return i;
|
||||
if (npagenums < NPAGENUMS-1) {
|
||||
pagenums[npagenums].num = n;
|
||||
pagenums[npagenums].adr = offsetc();
|
||||
npagenums++;
|
||||
}
|
||||
return npagenums;
|
||||
}
|
||||
|
||||
void
|
||||
readpage(void)
|
||||
{
|
||||
int c, i, a, alpha, phi;
|
||||
static int first = 0;
|
||||
int m, n, gonow = 1;
|
||||
Rune r[32], t;
|
||||
Point p,q,qq;
|
||||
|
||||
offset = screen->clipr.min;
|
||||
esetcursor(&deadmouse);
|
||||
while (gonow)
|
||||
{
|
||||
c = getc();
|
||||
switch (c)
|
||||
{
|
||||
case -1:
|
||||
esetcursor(0);
|
||||
if (botpage(lastp+1)) {
|
||||
initpage();
|
||||
break;
|
||||
}
|
||||
exits(0);
|
||||
case 'p': /* new page */
|
||||
lastp = getn();
|
||||
addpage(lastp);
|
||||
if (first++ > 0) {
|
||||
esetcursor(0);
|
||||
botpage(lastp);
|
||||
esetcursor(&deadmouse);
|
||||
}
|
||||
initpage();
|
||||
break;
|
||||
case '\n': /* when input is text */
|
||||
case ' ':
|
||||
case 0: /* occasional noise creeps in */
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
/* two motion digits plus a character */
|
||||
hpos += (c-'0')*10 + getc()-'0';
|
||||
|
||||
/* FALLS THROUGH */
|
||||
case 'c': /* single ascii character */
|
||||
r[0] = getrune();
|
||||
r[1] = 0;
|
||||
dochar(r);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
for(i=0; ; i++){
|
||||
t = getrune();
|
||||
if(isspace(t))
|
||||
break;
|
||||
r[i] = t;
|
||||
}
|
||||
r[i] = 0;
|
||||
dochar(r);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
r[0] = getn();
|
||||
r[1] = 0;
|
||||
dochar(r);
|
||||
break;
|
||||
|
||||
case 'D': /* draw function */
|
||||
switch (getc())
|
||||
{
|
||||
case 'l': /* draw a line */
|
||||
n = getn();
|
||||
m = getn();
|
||||
p = Pt(hpos,vpos);
|
||||
q = addpt(p, Pt(n,m));
|
||||
hpos += n;
|
||||
vpos += m;
|
||||
line(screen, scale(p), scale(q), 0, 0, 0, display->black, ZP);
|
||||
break;
|
||||
case 'c': /* circle */
|
||||
/*nop*/
|
||||
m = getn()/2;
|
||||
p = Pt(hpos+m,vpos);
|
||||
hpos += 2*m;
|
||||
ellipse(screen, scale(p), m/DIV, m/DIV, 0, display->black, ZP);
|
||||
/* p=currentpt; p.x+=dmap(m/2);circle bp,p,a,ONES,Mode*/
|
||||
break;
|
||||
case 'e': /* ellipse */
|
||||
/*nop*/
|
||||
m = getn()/2;
|
||||
n = getn()/2;
|
||||
p = Pt(hpos+m,vpos);
|
||||
hpos += 2*m;
|
||||
ellipse(screen, scale(p), m/DIV, n/DIV, 0, display->black, ZP);
|
||||
break;
|
||||
case 'a': /* arc */
|
||||
p = scale(Pt(hpos,vpos));
|
||||
n = getn();
|
||||
m = getn();
|
||||
hpos += n;
|
||||
vpos += m;
|
||||
q = scale(Pt(hpos,vpos));
|
||||
n = getn();
|
||||
m = getn();
|
||||
hpos += n;
|
||||
vpos += m;
|
||||
qq = scale(Pt(hpos,vpos));
|
||||
/*
|
||||
* tricky: convert from 3-point clockwise to
|
||||
* center, angle1, delta-angle counterclockwise.
|
||||
*/
|
||||
a = hypot(qq.x-q.x, qq.y-q.y);
|
||||
phi = atan2(q.y-p.y, p.x-q.x)*180./PI;
|
||||
alpha = atan2(q.y-qq.y, qq.x-q.x)*180./PI - phi;
|
||||
if(alpha < 0)
|
||||
alpha += 360;
|
||||
arc(screen, q, a, a, 0, display->black, ZP, phi, alpha);
|
||||
break;
|
||||
case '~': /* wiggly line */
|
||||
wiggly(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
eatline();
|
||||
break;
|
||||
case 's':
|
||||
n = getn(); /* ignore fractional sizes */
|
||||
if (cursize == n)
|
||||
break;
|
||||
cursize = n;
|
||||
if (cursize >= NFONT)
|
||||
cursize = NFONT-1;
|
||||
break;
|
||||
case 'f':
|
||||
curfont = getn();
|
||||
break;
|
||||
case 'H': /* absolute horizontal motion */
|
||||
hpos = getn();
|
||||
break;
|
||||
case 'h': /* relative horizontal motion */
|
||||
hpos += getn();
|
||||
break;
|
||||
case 'w': /* word space */
|
||||
break;
|
||||
case 'V':
|
||||
vpos = getn();
|
||||
break;
|
||||
case 'v':
|
||||
vpos += getn();
|
||||
break;
|
||||
case '#': /* comment */
|
||||
case 'n': /* end of line */
|
||||
eatline();
|
||||
break;
|
||||
case 'x': /* device control */
|
||||
devcntrl();
|
||||
break;
|
||||
default:
|
||||
fprint(2, "unknown input character %o %c at offset %lud\n", c, c, offsetc());
|
||||
exits("bad char");
|
||||
}
|
||||
}
|
||||
esetcursor(0);
|
||||
}
|
||||
|
||||
static void
|
||||
spline(Image *b, int n, Point *pp)
|
||||
{
|
||||
long w, t1, t2, t3, fac=1000;
|
||||
int i, j, steps=10;
|
||||
Point p, q;
|
||||
|
||||
for (i = n; i > 0; i--)
|
||||
pp[i] = pp[i-1];
|
||||
pp[n+1] = pp[n];
|
||||
n += 2;
|
||||
p = pp[0];
|
||||
for(i = 0; i < n-2; i++)
|
||||
{
|
||||
for(j = 0; j < steps; j++)
|
||||
{
|
||||
w = fac * j / steps;
|
||||
t1 = w * w / (2 * fac);
|
||||
w = w - fac/2;
|
||||
t2 = 3*fac/4 - w * w / fac;
|
||||
w = w - fac/2;
|
||||
t3 = w * w / (2*fac);
|
||||
q.x = (t1*pp[i+2].x + t2*pp[i+1].x +
|
||||
t3*pp[i].x + fac/2) / fac;
|
||||
q.y = (t1*pp[i+2].y + t2*pp[i+1].y +
|
||||
t3*pp[i].y + fac/2) / fac;
|
||||
line(b, p, q, 0, 0, 0, display->black, ZP);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Have to parse skipped pages, to find out what fonts are loaded. */
|
||||
static int
|
||||
skipto(int gotop, int curp)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (gotop == curp)
|
||||
return 1;
|
||||
for (i = 0; i < npagenums; i++)
|
||||
if (pagenums[i].num == gotop) {
|
||||
if (seekc(pagenums[i].adr) == Beof) {
|
||||
fprint(2, "can't rewind input\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (gotop <= curp) {
|
||||
restart:
|
||||
if (seekc(0) == Beof) {
|
||||
fprint(2, "can't rewind input\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(;;){
|
||||
p = rdlinec();
|
||||
if (p == 0) {
|
||||
if(gotop>curp){
|
||||
gotop = curp;
|
||||
goto restart;
|
||||
}
|
||||
return 0;
|
||||
} else if (*p == 'p') {
|
||||
lastp = curp = atoi(p+1);
|
||||
addpage(lastp); /* maybe 1 too high */
|
||||
if (curp>=gotop)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wiggly(int skip)
|
||||
{
|
||||
Point p[300];
|
||||
int c,i,n;
|
||||
for (n = 1; (c = getc()) != '\n' && c>=0; n++) {
|
||||
ungetc();
|
||||
p[n].x = getn();
|
||||
p[n].y = getn();
|
||||
}
|
||||
p[0] = Pt(hpos, vpos);
|
||||
for (i = 1; i < n; i++)
|
||||
p[i] = addpt(p[i],p[i-1]);
|
||||
hpos = p[n-1].x;
|
||||
vpos = p[n-1].y;
|
||||
for (i = 0; i < n; i++)
|
||||
p[i] = scale(p[i]);
|
||||
if (!skip)
|
||||
spline(screen,n,p);
|
||||
}
|
||||
|
||||
static void
|
||||
devcntrl(void) /* interpret device control functions */
|
||||
{
|
||||
char str[80];
|
||||
int n;
|
||||
|
||||
getstr(str);
|
||||
switch (str[0]) { /* crude for now */
|
||||
case 'i': /* initialize */
|
||||
break;
|
||||
case 'T': /* device name */
|
||||
getstr(devname);
|
||||
break;
|
||||
case 't': /* trailer */
|
||||
break;
|
||||
case 'p': /* pause -- can restart */
|
||||
break;
|
||||
case 's': /* stop */
|
||||
break;
|
||||
case 'r': /* resolution assumed when prepared */
|
||||
res=getn();
|
||||
DIV = floor(.5 + res/(100.0*mag));
|
||||
if (DIV < 1)
|
||||
DIV = 1;
|
||||
mag = res/(100.0*DIV); /* adjust mag according to DIV coarseness */
|
||||
break;
|
||||
case 'f': /* font used */
|
||||
n = getn();
|
||||
getstr(str);
|
||||
loadfontname(n, str);
|
||||
break;
|
||||
/* these don't belong here... */
|
||||
case 'H': /* char height */
|
||||
break;
|
||||
case 'S': /* slant */
|
||||
break;
|
||||
case 'X':
|
||||
break;
|
||||
}
|
||||
eatline();
|
||||
}
|
||||
|
||||
int
|
||||
isspace(int c)
|
||||
{
|
||||
return c==' ' || c=='\t' || c=='\n';
|
||||
}
|
||||
|
||||
static void
|
||||
getstr(char *is)
|
||||
{
|
||||
uchar *s = (uchar *) is;
|
||||
|
||||
for (*s = getc(); isspace(*s); *s = getc())
|
||||
;
|
||||
for (; !isspace(*s); *++s = getc())
|
||||
;
|
||||
ungetc();
|
||||
*s = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
getutf(char *s) /* get next utf char, as bytes */
|
||||
{
|
||||
int c, i;
|
||||
|
||||
for (i=0;;) {
|
||||
c = getc();
|
||||
if (c < 0)
|
||||
return;
|
||||
s[i++] = c;
|
||||
|
||||
if (fullrune(s, i)) {
|
||||
s[i] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
eatline(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c=getc()) != '\n' && c >= 0)
|
||||
;
|
||||
}
|
||||
|
||||
static int
|
||||
getn(void)
|
||||
{
|
||||
int n, c, sign;
|
||||
|
||||
while (c = getc())
|
||||
if (!isspace(c))
|
||||
break;
|
||||
if(c == '-'){
|
||||
sign = -1;
|
||||
c = getc();
|
||||
}else
|
||||
sign = 1;
|
||||
for (n = 0; '0'<=c && c<='9'; c = getc())
|
||||
n = n*10 + c - '0';
|
||||
while (c == ' ')
|
||||
c = getc();
|
||||
ungetc();
|
||||
return(n*sign);
|
||||
}
|
||||
|
||||
static int
|
||||
botpage(int np) /* called at bottom of page np-1 == top of page np */
|
||||
{
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
while (p = getcmdstr()) {
|
||||
if (*p == '\0')
|
||||
return 0;
|
||||
if (*p == 'q')
|
||||
exits(p);
|
||||
if (*p == 'c') /* nop */
|
||||
continue;
|
||||
if (*p == 'm') {
|
||||
mag = atof(p+1);
|
||||
if (mag <= .1 || mag >= 10)
|
||||
mag = DEFMAG;
|
||||
allfree(); /* zap fonts */
|
||||
DIV = floor(.5 + res/(100.0*mag));
|
||||
if (DIV < 1)
|
||||
DIV = 1;
|
||||
mag = res/(100.0*DIV);
|
||||
return skipto(np-1, np); /* reprint the page */
|
||||
}
|
||||
if (*p == 'x') {
|
||||
xyoffset.x += atoi(p+1)*100;
|
||||
skipto(np-1, np);
|
||||
return 1;
|
||||
}
|
||||
if (*p == 'y') {
|
||||
xyoffset.y += atoi(p+1)*100;
|
||||
skipto(np-1, np);
|
||||
return 1;
|
||||
}
|
||||
if (*p == '/') { /* divide into n pieces */
|
||||
nview = atoi(p+1);
|
||||
if (nview < 1)
|
||||
nview = 1;
|
||||
else if (nview > MAXVIEW)
|
||||
nview = MAXVIEW;
|
||||
return skipto(np-1, np);
|
||||
}
|
||||
if (*p == 'p') {
|
||||
if (p[1] == '\0'){ /* bare 'p' */
|
||||
if(skipto(np-1, np))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if ('0'<=*p && *p<='9') {
|
||||
n = atoi(p);
|
||||
if(skipto(n, np))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
if (*p == '-' || *p == '+') {
|
||||
n = atoi(p);
|
||||
if (n == 0)
|
||||
n = *p == '-' ? -1 : 1;
|
||||
if(skipto(np - 1 + n, np))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
if (*p == 'd') {
|
||||
dbg = 1 - dbg;
|
||||
continue;
|
||||
}
|
||||
|
||||
fprint(2, "illegal; try q, 17, +2, -1, p, m.7, /2, x1, y-.5 or return\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
226
src/cmd/proof/main.c
Normal file
226
src/cmd/proof/main.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <event.h>
|
||||
#include <bio.h>
|
||||
#include "proof.h"
|
||||
|
||||
Rectangle rpage = { 0, 0, 850, 1150 };
|
||||
char devname[64];
|
||||
double mag = DEFMAG;
|
||||
int dbg = 0;
|
||||
char *track = 0;
|
||||
Biobuf bin;
|
||||
char *libfont = "#9/font";
|
||||
char *mapfile = "MAP";
|
||||
char *mapname = "MAP";
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: proof [-m mag] [-/ nview] [-x xoff] [-y yoff] [-M mapfile] [-F fontdir] [-dt] file...\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
double
|
||||
getnum(char *s)
|
||||
{
|
||||
if(s == nil)
|
||||
usage();
|
||||
return atof(s);
|
||||
}
|
||||
|
||||
char*
|
||||
getstr(char *s)
|
||||
{
|
||||
if(s == nil)
|
||||
usage();
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char c;
|
||||
int dotrack = 0;
|
||||
|
||||
libfont = unsharp(libfont);
|
||||
ARGBEGIN{
|
||||
case 'm': /* magnification */
|
||||
mag = getnum(ARGF());
|
||||
if (mag < 0.1 || mag > 10){
|
||||
fprint(2, "ridiculous mag argument ignored\n");
|
||||
mag = DEFMAG;
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
nview = getnum(ARGF());
|
||||
if (nview < 1 || nview > MAXVIEW)
|
||||
nview = 1;
|
||||
break;
|
||||
case 'x':
|
||||
xyoffset.x += getnum(ARGF()) * 100;
|
||||
break;
|
||||
case 'y':
|
||||
xyoffset.y += getnum(ARGF()) * 100;
|
||||
break;
|
||||
case 'M': /* change MAP file */
|
||||
mapname = EARGF(usage());
|
||||
break;
|
||||
case 'F': /* change /lib/font/bit directory */
|
||||
libfont = EARGF(usage());
|
||||
break;
|
||||
case 'd':
|
||||
dbg = 1;
|
||||
break;
|
||||
case 't':
|
||||
dotrack = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
if (argc > 0) {
|
||||
close(0);
|
||||
if (open(argv[0], 0) != 0) {
|
||||
sysfatal("can't open %s: %r\n", argv[0]);
|
||||
exits("open failure");
|
||||
}
|
||||
if(dotrack)
|
||||
track = argv[0];
|
||||
}
|
||||
Binit(&bin, 0, OREAD);
|
||||
mapfile = smprint("%s/%s", libfont, mapname);
|
||||
readmapfile(mapfile);
|
||||
for (c = 0; c < NFONT; c++)
|
||||
loadfontname(c, "??");
|
||||
mapscreen();
|
||||
clearscreen();
|
||||
readpage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Input buffer to allow us to back up
|
||||
*/
|
||||
#define SIZE 100000 /* 8-10 pages, typically */
|
||||
|
||||
char bufc[SIZE];
|
||||
char *inc = bufc; /* where next input character goes */
|
||||
char *outc = bufc; /* next character to be read from buffer */
|
||||
int off; /* position of outc in total input stream */
|
||||
|
||||
void
|
||||
addc(int c)
|
||||
{
|
||||
*inc++ = c;
|
||||
if(inc == &bufc[SIZE])
|
||||
inc = &bufc[0];
|
||||
}
|
||||
|
||||
int
|
||||
getc(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
if(outc == inc){
|
||||
c = Bgetc(&bin);
|
||||
if(c == Beof)
|
||||
return Beof;
|
||||
addc(c);
|
||||
}
|
||||
off++;
|
||||
c = *outc++;
|
||||
if(outc == &bufc[SIZE])
|
||||
outc = &bufc[0];
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
getrune(void)
|
||||
{
|
||||
int c, n;
|
||||
Rune r;
|
||||
char buf[UTFmax];
|
||||
|
||||
for(n=0; !fullrune(buf, n); n++){
|
||||
c = getc();
|
||||
if(c == Beof)
|
||||
return Beof;
|
||||
buf[n] = c;
|
||||
}
|
||||
chartorune(&r, buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
nbuf(void) /* return number of buffered characters */
|
||||
{
|
||||
int ini, outi;
|
||||
|
||||
ini = inc-bufc;
|
||||
outi = outc-bufc;
|
||||
if(ini < outi)
|
||||
ini += SIZE;
|
||||
return ini-outi;
|
||||
}
|
||||
|
||||
ulong
|
||||
seekc(ulong o)
|
||||
{
|
||||
ulong avail;
|
||||
long delta;
|
||||
|
||||
delta = off-o;
|
||||
if(delta < 0)
|
||||
return Beof;
|
||||
avail = SIZE-nbuf();
|
||||
if(delta < avail){
|
||||
off = o;
|
||||
outc -= delta;
|
||||
if(outc < &bufc[0])
|
||||
outc += SIZE;
|
||||
return off;
|
||||
}
|
||||
return Beof;
|
||||
}
|
||||
|
||||
void
|
||||
ungetc(void)
|
||||
{
|
||||
if(off == 0)
|
||||
return;
|
||||
if(nbuf() == SIZE){
|
||||
fprint(2, "backup buffer overflow\n");
|
||||
return;
|
||||
}
|
||||
if(outc == &bufc[0])
|
||||
outc = &bufc[SIZE];
|
||||
--outc;
|
||||
--off;
|
||||
}
|
||||
|
||||
ulong
|
||||
offsetc(void)
|
||||
{
|
||||
return off;
|
||||
}
|
||||
|
||||
char*
|
||||
rdlinec(void)
|
||||
{
|
||||
static char buf[2048];
|
||||
int c, i;
|
||||
|
||||
for(i=0; i<sizeof buf; ){
|
||||
c = getc();
|
||||
if(c == Beof)
|
||||
break;
|
||||
buf[i++] = c;
|
||||
if(c == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == 0)
|
||||
return nil;
|
||||
return buf;
|
||||
}
|
||||
14
src/cmd/proof/mkfile
Normal file
14
src/cmd/proof/mkfile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=proof
|
||||
OFILES=main.$O\
|
||||
font.$O\
|
||||
htroff.$O\
|
||||
screen.$O\
|
||||
|
||||
HFILES=proof.h
|
||||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
$O.pout: $OFILES
|
||||
$LD -o $O.pout -p $OFILES
|
||||
5
src/cmd/proof/portdate
Normal file
5
src/cmd/proof/portdate
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
font.c 2004/1225
|
||||
htroff.c 2004/1225
|
||||
main.c 2004/1225
|
||||
proof.h 2004/1225
|
||||
screen.c 2004/1225
|
||||
48
src/cmd/proof/proof.h
Normal file
48
src/cmd/proof/proof.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <cursor.h>
|
||||
#undef isspace
|
||||
#define NPAGES 500
|
||||
#define NFONT 33
|
||||
#define NSIZE 40
|
||||
#define MINSIZE 4
|
||||
#define DEFMAG (10.0/11.0) /* was (10.0/11.0), then 1 */
|
||||
#define MAXVIEW 40
|
||||
|
||||
#define ONES ~0
|
||||
|
||||
extern char devname[];
|
||||
extern double mag;
|
||||
extern int nview;
|
||||
extern int hpos, vpos, curfont, cursize;
|
||||
extern int DIV, res;
|
||||
extern int Mode;
|
||||
|
||||
extern Point offset; /* for small pages within big page */
|
||||
extern Point xyoffset; /* for explicit x,y move */
|
||||
extern Cursor deadmouse;
|
||||
|
||||
extern char *libfont;
|
||||
|
||||
void mapscreen(void);
|
||||
void clearscreen(void);
|
||||
char *getcmdstr(void);
|
||||
|
||||
void readmapfile(char *);
|
||||
void dochar(Rune*);
|
||||
void bufput(void);
|
||||
void loadfontname(int, char *);
|
||||
void allfree(void);
|
||||
void readpage(void);
|
||||
int isspace(int);
|
||||
|
||||
extern int getc(void);
|
||||
extern int getrune(void);
|
||||
extern void ungetc(void);
|
||||
extern ulong offsetc(void);
|
||||
extern ulong seekc(ulong);
|
||||
extern char* rdlinec(void);
|
||||
|
||||
|
||||
#define dprint if (dbg) fprint
|
||||
|
||||
extern int dbg;
|
||||
extern int resized;
|
||||
315
src/cmd/proof/screen.c
Normal file
315
src/cmd/proof/screen.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <cursor.h>
|
||||
#include <event.h>
|
||||
#include <bio.h>
|
||||
#include "proof.h"
|
||||
|
||||
static int checkmouse(void);
|
||||
/* static int buttondown(void); */
|
||||
static char *getmousestr(void);
|
||||
static char *getkbdstr(int);
|
||||
|
||||
extern Cursor blot;
|
||||
extern char *track;
|
||||
|
||||
Mouse mouse;
|
||||
|
||||
void
|
||||
mapscreen(void)
|
||||
{
|
||||
if(initdraw(0, 0, "proof") < 0){
|
||||
fprint(2, "proof: initdraw failed: %r\n");
|
||||
exits("initdraw");
|
||||
}
|
||||
einit(Ekeyboard|Emouse);
|
||||
}
|
||||
|
||||
void
|
||||
clearscreen(void)
|
||||
{
|
||||
draw(screen, screen->r, display->black, nil, ZP);
|
||||
}
|
||||
|
||||
void
|
||||
screenprint(char *fmt, ...)
|
||||
{
|
||||
char buf[100];
|
||||
Point p;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vseprint(buf, &buf[sizeof buf], fmt, args);
|
||||
va_end(args);
|
||||
p = Pt(screen->clipr.min.x+40, screen->clipr.max.y-40);
|
||||
string(screen, p, display->black, ZP, font, buf);
|
||||
}
|
||||
|
||||
#define Viewkey 0xb2
|
||||
#define etimer(x, y) 0
|
||||
|
||||
char *
|
||||
getcmdstr(void)
|
||||
{
|
||||
Event ev;
|
||||
int e;
|
||||
static ulong timekey = 0;
|
||||
ulong tracktm = 0;
|
||||
Dir *dir;
|
||||
|
||||
if(track){
|
||||
if(timekey == 0)
|
||||
timekey = etimer(0, 5000);
|
||||
dir = dirstat(track);
|
||||
if(dir != nil){
|
||||
tracktm = dir->mtime;
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
e = event(&ev);
|
||||
if(resized){
|
||||
resized = 0;
|
||||
return "p";
|
||||
}
|
||||
if ((e & Emouse) && ev.mouse.buttons) {
|
||||
mouse = ev.mouse;
|
||||
return getmousestr();
|
||||
} else if (e & Ekeyboard)
|
||||
return getkbdstr(ev.kbdc); /* sadly, no way to unget */
|
||||
else if (e & timekey) {
|
||||
if((dir = dirstat(track)) != nil){
|
||||
if(tracktm < dir->mtime){
|
||||
free(dir);
|
||||
return "q";
|
||||
}
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
getkbdstr(int c0)
|
||||
{
|
||||
static char buf[100];
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
if (c0 == '\n')
|
||||
return "";
|
||||
buf[0] = c0;
|
||||
buf[1] = 0;
|
||||
screenprint("%s", buf);
|
||||
for (p = buf+1; (c = ekbd()) != '\n' && c != '\r' && c != -1 && c != Viewkey; ) {
|
||||
if (c == '\b' && p > buf) {
|
||||
*--p = ' ';
|
||||
} else {
|
||||
*p++ = c;
|
||||
*p = 0;
|
||||
}
|
||||
screenprint("%s", buf);
|
||||
}
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
#define button3(b) ((b) & 4)
|
||||
#define button2(b) ((b) & 2)
|
||||
#define button1(b) ((b) & 1)
|
||||
#define button23(b) ((b) & 6)
|
||||
#define button123(b) ((b) & 7)
|
||||
|
||||
#define butcvt(b) (1 << ((b) - 1))
|
||||
|
||||
#if 0
|
||||
static int buttondown(void) /* report state of buttons, if any */
|
||||
{
|
||||
if (!ecanmouse()) /* no event pending */
|
||||
return 0;
|
||||
mouse = emouse(); /* something, but it could be motion */
|
||||
return mouse.buttons & 7;
|
||||
}
|
||||
#endif
|
||||
|
||||
int waitdown(void) /* wait until some button is down */
|
||||
{
|
||||
while (!(mouse.buttons & 7))
|
||||
mouse = emouse();
|
||||
return mouse.buttons & 7;
|
||||
}
|
||||
|
||||
int waitup(void)
|
||||
{
|
||||
while (mouse.buttons & 7)
|
||||
mouse = emouse();
|
||||
return mouse.buttons & 7;
|
||||
}
|
||||
|
||||
char *m3[] = { "next", "prev", "page n", "again", "bigger", "smaller", "pan", "quit?", 0 };
|
||||
char *m2[] = { 0 };
|
||||
|
||||
enum { Next = 0, Prev, Page, Again, Bigger, Smaller, Pan, Quit };
|
||||
|
||||
Menu mbut3 = { m3, 0, 0 };
|
||||
Menu mbut2 = { m2, 0, 0 };
|
||||
|
||||
int last_hit;
|
||||
int last_but;
|
||||
|
||||
char *pan(void)
|
||||
{
|
||||
Point dd, xy, lastxy, min, max;
|
||||
|
||||
esetcursor(&blot);
|
||||
waitdown();
|
||||
xy = mouse.xy;
|
||||
do{
|
||||
lastxy = mouse.xy;
|
||||
mouse = emouse();
|
||||
dd = subpt(mouse.xy, lastxy);
|
||||
min = addpt(screen->clipr.min, dd);
|
||||
max = addpt(screen->clipr.max, dd);
|
||||
draw(screen, rectaddpt(screen->r, subpt(mouse.xy, lastxy)),
|
||||
screen, nil, screen->r.min);
|
||||
if(mouse.xy.x < lastxy.x) /* moved left, clear right */
|
||||
draw(screen, Rect(max.x, screen->r.min.y, screen->r.max.x, screen->r.max.y),
|
||||
display->white, nil, ZP);
|
||||
else /* moved right, clear left*/
|
||||
draw(screen, Rect(screen->r.min.x, screen->r.min.y, min.x, screen->r.max.y),
|
||||
display->white, nil, ZP);
|
||||
if(mouse.xy.y < lastxy.y) /* moved up, clear down */
|
||||
draw(screen, Rect(screen->r.min.x, max.y, screen->r.max.x, screen->r.max.y),
|
||||
display->white, nil, ZP);
|
||||
else /* moved down, clear up */
|
||||
draw(screen, Rect(screen->r.min.x, screen->r.min.y, screen->r.max.x, min.y),
|
||||
display->white, nil, ZP);
|
||||
flushimage(display, 1);
|
||||
}while(mouse.buttons);
|
||||
|
||||
xyoffset = addpt(xyoffset, subpt(mouse.xy, xy));
|
||||
|
||||
esetcursor(0);
|
||||
return "p";
|
||||
}
|
||||
|
||||
static char *getmousestr(void)
|
||||
{
|
||||
static char buf[20];
|
||||
|
||||
checkmouse();
|
||||
if (last_but == 1)
|
||||
return "p"; /* repaint after panning */
|
||||
if (last_but == 2) {
|
||||
return "c";
|
||||
} else if (last_but == 3) {
|
||||
switch (last_hit) {
|
||||
case Next:
|
||||
return "";
|
||||
case Prev:
|
||||
return "-1";
|
||||
case Page:
|
||||
screenprint("page? ");
|
||||
return "c";
|
||||
case Again:
|
||||
return "p";
|
||||
case Bigger:
|
||||
sprint(buf, "m%g", mag * 1.1);
|
||||
return buf;
|
||||
case Smaller:
|
||||
sprint(buf, "m%g", mag / 1.1);
|
||||
return buf;
|
||||
case Pan:
|
||||
return pan();
|
||||
case Quit:
|
||||
return "q";
|
||||
default:
|
||||
return "c";
|
||||
}
|
||||
} else { /* button 1 or bail out */
|
||||
return "c";
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
checkmouse(void) /* return button touched if any */
|
||||
{
|
||||
int c, b;
|
||||
char *p;
|
||||
extern int confirm(int);
|
||||
|
||||
b = waitdown();
|
||||
last_but = 0;
|
||||
last_hit = -1;
|
||||
c = 0;
|
||||
if (button3(b)) {
|
||||
last_hit = emenuhit(3, &mouse, &mbut3);
|
||||
last_but = 3;
|
||||
} else if (button2(b)) {
|
||||
last_hit = emenuhit(2, &mouse, &mbut2);
|
||||
last_but = 2;
|
||||
} else { /* button1() */
|
||||
pan();
|
||||
last_but = 1;
|
||||
}
|
||||
waitup();
|
||||
if (last_but == 3 && last_hit >= 0) {
|
||||
p = m3[last_hit];
|
||||
c = p[strlen(p) - 1];
|
||||
}
|
||||
if (c == '?' && !confirm(last_but))
|
||||
last_hit = -1;
|
||||
return last_but;
|
||||
}
|
||||
|
||||
Cursor deadmouse = {
|
||||
{ 0, 0}, /* offset */
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
|
||||
0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
|
||||
0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0C, 0x00, 0x82, 0x04, 0x41,
|
||||
0xFF, 0xE1, 0x5F, 0xF1, 0x3F, 0xFE, 0x17, 0xF0,
|
||||
0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
|
||||
};
|
||||
|
||||
Cursor blot ={
|
||||
{ 0, 0 },
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }
|
||||
};
|
||||
|
||||
Cursor skull ={
|
||||
{ 0, 0 },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
|
||||
0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
|
||||
0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
|
||||
0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03,
|
||||
0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0,
|
||||
0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27,
|
||||
0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
|
||||
};
|
||||
|
||||
int
|
||||
confirm(int but) /* ask for confirmation if menu item ends with '?' */
|
||||
{
|
||||
int c;
|
||||
static int but_cvt[8] = { 0, 1, 2, 0, 3, 0, 0, 0 };
|
||||
|
||||
esetcursor(&skull);
|
||||
c = waitdown();
|
||||
waitup();
|
||||
esetcursor(0);
|
||||
return but == but_cvt[c];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue