rs@uunet.UU.NET (Rich Salz) (08/06/87)
Submitted-by: "Alan W. Paeth" <awpaeth%watcgl.waterloo.edu@RELAY.CS.NET> Posting-number: Volume 10, Issue 92 Archive-name: lemming/Part02 #!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # lemmain.c # lemmark.c # lemmisc.c # lemobj.c # lemobjsup.c # lemop.c # lempic.c # lemrc.c # lemselect.c # lemspecial.c # lemstart.c # lemstop.c # lemtext.c # lemtick.c # lemundo.c # lemvec.c # lemx.c # This archive created: Fri Jun 12 18:35:10 1987 # By: watcgl!awpaethexport PATH; PATH=/bin:$PATH if test -f 'lemmain.c' then echo shar: over-writing existing file "'lemmain.c'" fi cat << \SHAR_EOF > 'lemmain.c' /* * lemmain.c - little editor for mice and other furry rodents (aka lemming) * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" main(argc, argv) char **argv; { int x, y, xup, yup, mup; int event, near, drag, dragdist; char ch; startup(argc, argv); while(1) { event = getevent(&x, &y, &xup, &yup, &ch); if (event != NOEVT) msgclear(); switch(event) { case NOEVT: idle(); break; case ALPHA: charadd(line, ch); break; case CNTRL: switch(ch) { case C(Q): if (quitconfirm()) break; case C(A): all(SELECT, 0); break; case C(B): remake(BOX); break; case C(C): copysel(); break; case C(D): objcompress(); all(DELETE, 0); undo=UNDODEL; break; case C(E): remake(ELLI); break; case C(F): forceattr(); break; case C(G): addgroup(); break; case '\177': /* <DEL> */ case C(H): chardel(line,1); break; /* <BS> */ case C(I): cycleselect(); markdelete(); break; /* <TAB> */ case C(J): /* <LF>, */ case C(M): if (markon) stringadd(); break; /* <CR> */ /* case C(K): curveify(); break; */ case C(L): redraw(); break; case C(N): all(DESELECT, 0); break; case C(O): writepic(); break; case C(P): removegroup(); break; case C(R): readfile(); break; case C(S): specialfunc(); break; case C(T): tickset(); break; case C(U): undocmd(); break; case C(V): remake(LINE); break; case C(W): writefile(); break; case C(X): cutlines(); break; case C([): all(DESELECT, 0); markdelete(); break; /* <ESC> */ case C(^): help(); break; /* ^^ */ default: break; } break; case MOUSE: markobj = objnearany(x, y); near = markon && (dist(x, y, markx, marky) < MARKTOL); dragdist = near ? (anysel ? 0 : MARKTOL) : DRAGTOL; drag = dist(x,y,xup,yup) > dragdist; if (markobj) objectalign(markobj, &x, &y); else spacealign(&x, &y); if (drag) /* drag stuff */ { if (near) { markhide(); /* for cleaner update */ mup = objnearany(xup, yup); if (mup && (mup != markobj)) objectalign(mup, &xup, &yup); else spacealign(&xup, &yup); if (anysel) moveselect(xup-markx, yup-marky); else if (markobj) tugunselect(markx, marky, xup, yup); markupdate(xup, yup); } else rectselect(x, y, xup, yup); } else /* draw (move mark) cases */ { if (near) markdelete(); else { markhide(); /* for cleaner update */ if (markon && !anysel) lineadd(markx, marky, x, y); markupdate(x, y); } } break; } } } SHAR_EOF if test -f 'lemmark.c' then echo shar: over-writing existing file "'lemmark.c'" fi cat << \SHAR_EOF > 'lemmark.c' /* * lemmark.c - mark control * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" markadd(x, y) { markdraw(x, y, markobj ? MARKONOBJCOL : MARKONREGCOL); markx = x; marky = y; markon = 1; } markdelete() { markhide(); markon = 0; } markhide() { if (markon) markdraw(markx, marky, MARKOFFCOL); } markupdate(x, y) { markdelete(); markobj = objnearany(x, y); markadd(x, y); } markdraw(x, y, col) { drawvec(x-MARKSIZE, y, x+MARKSIZE, y, col, 1, EMPHNONE); drawvec(x, y-MARKSIZE, x, y+MARKSIZE, col, 1, EMPHNONE); } SHAR_EOF if test -f 'lemmisc.c' then echo shar: over-writing existing file "'lemmisc.c'" fi cat << \SHAR_EOF > 'lemmisc.c' /* * lemmisc.c - low-level routines * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" redraw() { int i; erase(); if (tickflag) tickdraw(); forobjects { objectop(i, UNDEL, UNDEL); objectop(i, SEL, SEL); } if (markon) markadd(markx, marky); } idle() { } SHAR_EOF if test -f 'lemobj.c' then echo shar: over-writing existing file "'lemobj.c'" fi cat << \SHAR_EOF > 'lemobj.c' /* * lemobj.c - object dispatch * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" objresize(i) { switch(Otype) { case LINE: lineresize(i); break; case TEXT: textresize(i); break; case BOX: boxresize(i); break; case ELLI: elliresize(i); break; } } objnearpt(i, x, y) { switch(Otype) { case LINE: return(linenearpt(i, x, y)); break; case TEXT: return(textnearpt(i, x, y)); break; case BOX: return( boxnearpt(i, x, y)); break; case ELLI: return(ellinearpt(i, x, y)); break; } } objinrect(i, xl, yl, xh, yh) { switch(Otype) { case TEXT: return(textinrect(i, xl, yl, xh, yh)); break; case LINE: return(lineinrect(i, xl, yl, xh, yh)); break; case BOX: return( boxinrect(i, xl, yl, xh, yh)); break; case ELLI: return(elliinrect(i, xl, yl, xh, yh)); break; } } objcantug(i, x, y) { switch(Otype) { case TEXT: return(textcantug(i, x, y)); break; case LINE: return(linecantug(i, x, y)); break; case BOX: return( boxcantug(i, x, y)); break; case ELLI: return(ellicantug(i, x, y)); break; } } objtug(i, xs, ys, xe, ye) { switch(Otype) { case TEXT: texttug(i, xs, ys, xe, ye); break; case LINE: linetug(i, xs, ys, xe, ye); break; case BOX: boxtug(i, xs, ys, xe, ye); break; case ELLI: ellitug(i, xs, ys, xe, ye); break; } } objectalign(i, x, y) int *x, *y; { switch(Otype) { case TEXT: textalign(i, x, y); break; case BOX: boxalign(i, x, y); break; case LINE: linealign(i, x, y); break; case ELLI: ellialign(i, x, y); break; } } objmove(i, x, y) { switch(Otype) { case LINE: linemove(i, x, y); break; case TEXT: textmove(i, x, y); break; case BOX: boxmove(i, x, y); break; case ELLI: ellimove(i, x, y); break; } } objaffine(i, m11, m12, m21, m22) float m11, m12, m21, m22; { switch(Otype) { case LINE: lineaffine(i, m11, m12, m21, m22); break; case TEXT: textaffine(i, m11, m12, m21, m22); break; case BOX: boxaffine(i, m11, m12, m21, m22); break; case ELLI: elliaffine(i, m11, m12, m21, m22); break; } } objdraw(i, col) { switch(Otype) { case LINE: linedraw(i, col); break; case TEXT: textdraw(i, col); break; case BOX: boxdraw(i, col); break; case ELLI: ellidraw(i, col); break; } } SHAR_EOF if test -f 'lemobjsup.c' then echo shar: over-writing existing file "'lemobjsup.c'" fi cat << \SHAR_EOF > 'lemobjsup.c' /* * lemobjsup.c - superclass for generic object operations * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include <math.h> /* to define "double floor()" */ #include "lem.h" objsupnearpt(i, x, y) { if (ptinrect(x, y, Oxl, Oyl, Oxh, Oyh, LINETOL) == 0) return(0); return(1); } objsupinrect(i, xl, yl, xh, yh) { return(ptinrect(Oxl, Oyl, xl, yl, xh, yh, LINETOL) && ptinrect(Oxh, Oyh, xl, yl, xh, yh, LINETOL)); } objsupcantug(i, x, y) { return(objnearpt(i, x, y)); } objsuptug(i, xs, ys, xe, ye) { if (dist(Oxs, Oys, xs, ys) < TUGPROX) objmove(i, xe-xs, ye-ys); } objsupalign(i, x, y) int *x, *y; { if (dist(Oxs, Oys, *x, *y) < ENDTOL) { *x = Oxs; *y = Oys; } } objsupmove(i, x, y) { Oxs += x; Oxe += x; Oys += y; Oye += y; } objsupaffine(i, m11, m12, m21, m22, both) float m11, m12, m21, m22; { float x1, y1; if (both) { x1 = floor((m11*Oxs + m12*Oys) + 0.5); y1 = floor((m21*Oxs + m22*Oys) + 0.5); Oxs = x1; Oys = y1; x1 = floor((m11*Oxe + m12*Oye) + 0.5); y1 = floor((m21*Oxe + m22*Oye) + 0.5); Oxe = x1; Oye = y1; } else { x1 = floor((m11*Oxcen + m12*Oycen) + 0.5); y1 = floor((m21*Oxcen + m22*Oycen) + 0.5); /* * move only the center point, don't the other endpoint * (presumably object dimensions -- this is a text element). */ objmove(i, (int)(x1-Oxcen), (int)(y1-Oycen)); } } SHAR_EOF if test -f 'lemop.c' then echo shar: over-writing existing file "'lemop.c'" fi cat << \SHAR_EOF > 'lemop.c' /* * lemop.c - operate on objects (and update the display) * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" objectop(i, instatus, outstatus) { int col; if (i && (Ostat == instatus)) { if ( instatus == SEL) anysel--; if (outstatus == SEL) anysel++; Ostat = outstatus; switch(Ostat) { case DEL: col = ERASECOL; break; case UNDEL: col = DRAWCOL; break; case SEL: col = SELECTCOL; break; } objdraw(i, col); if (Odel && (i == markobj)) markobj = 0; changes |= ( (instatus == DEL) || (outstatus == DEL) ); if ( instatus == DEL) return(1); } return(0); } any(i, opcode) { if (Ogroup) all(opcode, Ogroup); else switch(opcode) { case SELECT: objectop(i, UNDEL, SEL); break; case DESELECT: objectop(i, SEL, UNDEL); break; case DELETE: objectop(i, SEL, DEL); break; case UNDELETE: objectop(i, DEL, SEL); break; } } all(opcode, group) { int i, saveg; forobjects { if (!group || Ogroup == group) { saveg = Ogroup; Ogroup = 0; any(i, opcode); Ogroup = saveg; } } } SHAR_EOF if test -f 'lempic.c' then echo shar: over-writing existing file "'lempic.c'" fi cat << \SHAR_EOF > 'lempic.c' /* * lempic.c - PIC output processor * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #define PTSSCALE 96.0 #define PENSCALE 12 /* ln03 dimp troff drivers like 13 (!a common PntSz) */ int curx, cury, curw, curh, ps, pemph; FILE *f; writepicint(fname) char *fname; { int i; f = (fname && (strlen(fname) > 1)) ? fopen(fname, "w") : 0; if (f) { curx = cury = curw = curh = ps = pemph= -1; fprintf(f, ".PS\n"); forobjects { if (Odel) continue; switch (Otype) { case TEXT: ptext(i); at(Oxs, Oys); break; case LINE: thick(i); pline(i); em(i); from(Oxs, Oys); to(Oxe, Oye); break; case BOX: thick(i); fprintf(f, "box"); em(i); at(Ox, Oy); size(Ow, Oh); break; case ELLI: thick(i); fprintf(f, "ellipse"); em(i); at(Ox, Oy); size(Ow,Oh); break; } fprintf(f, ";\n"); } fprintf(f, ".PE\n"); fclose(f); msgpost("pic output done"); } else msgpost("pic output failed"); free(fname); } writepic() { char *fname; fname = prompt("pic file: "); writepicint(fname); free(fname); } thick(i) { if (ps != lemfont[Osizer].thick) { ps = lemfont[Osizer].thick; fprintf(f, ".ps %d\n", ps*PENSCALE); } } pt(x, y) { fprintf(f, " %.3fi,%.3fi", (float)(x)/PTSSCALE, (float)(y)/PTSSCALE); } at(x, y) { fprintf(f, " at"); pt(x, y); } from(x, y) { if ((x == curx) && (y == cury)) return; fprintf(f, " from"); pt(x, y); curx = x; cury = y; } to(x, y) { fprintf(f, " to"); pt(x,y); curx = x; cury = y; } size(w, h) { w = ABS(w); h = ABS(h); if ((w == curw) && (h == curh)) fprintf(f, " same"); else { fprintf(f, " wid %.3fi ht %.3fi", (float)(w)/PTSSCALE, (float)(h)/PTSSCALE); curw = w; curh = h; } } ptext(i) { int fontflag; char *ft; fontflag = ((Oemph != pemph) || (lemfont[Osizer].psize != ps)); pemph = Oemph; ps = lemfont[Osizer].psize; fprintf(f, "\""); if (fontflag) { switch(Oemph) { case EMPHNONE: ft = lemfont[Osizer].tyr; break; case EMPHBOLD: ft = lemfont[Osizer].tyb; break; case EMPHITAL: ft = lemfont[Osizer].tyi; break; } fprintf(f, "\\f%s%s", strlen(ft) > 1 ? "(" : "", ft ); } fprintf(f, "\\s%d%s\"",lemfont[Osizer].psize, Otext); switch(Oalign) { case ALIGNLEFT: fprintf(f, " ljust"); break; case ALIGNRGHT: fprintf(f, " rjust"); break; case ALIGNCENT: default: break; } } pline(i) { fprintf(f, "line"); switch(Oalign) { case ALIGNLEFT: fprintf(f, " <-"); break; case ALIGNRGHT: fprintf(f, " ->"); break; case ALIGNCENT: default: break; } } em(i) { switch(Oemph) { case EMPHBOLD: fprintf(f, " dashed"); break; case EMPHITAL: fprintf(f, " dotted"); break; case EMPHNONE: default: break; } } SHAR_EOF if test -f 'lemrc.c' then echo shar: over-writing existing file "'lemrc.c'" fi cat << \SHAR_EOF > 'lemrc.c' /* * lemrc.c - get default fonts from local file. * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #include "lemfont.h" #define FONTPATH "/usr/local/lib/BFont/" #define FONTEXTN ".bf" char *getenv(); leminit() { char rcname[100], rcline[RCLINE]; FILE *f; int i, items; /* * generate local and global names */ sprintf(rcname, "./%s", RCNAME); f = fopen(rcname, "r"); if (!f) { sprintf(rcname, "%s/%s", getenv("HOME"), RCNAME); f = fopen(rcname, "r"); } if (!f) { /* err("no %s file exists", RCGLOBAL); */ lemfont[1].psize = DEFPSIZEFT; lemfont[1].thick = DEFDENSEFT; lemfont[1].dsp = DEFIKRFT; lemfont[1].tyr = DEFTYRFT; lemfont[1].tyb = DEFTYBFT; lemfont[1].tyi = DEFTYIFT; lemfont[1].psr = DEFPSRFT; lemfont[1].psb = DEFPSBFT; lemfont[1].psi = DEFPSIFT; rclen = 1; } else { while(1) { char dsp[20], tyr[20], tyb[20], tyi[20]; char psr[20], psb[20], psi[20]; fgets(rcline, RCLINE, f); if (feof(f)) break; if ((rcline[0] >= '0') && (rcline[0] <= '9')) { rclen++; if (rclen >= RCLEN) err(".rc file too long"); items = sscanf(rcline, "%d %d %s %s %s %s %s %s %s", &lemfont[rclen].psize, &lemfont[rclen].thick, dsp, tyr, tyb, tyi, psr, psb, psi); if (items != RCWIDTH) err("wrong line length in .rc file"); lemfont[rclen].dsp = salloc(dsp); lemfont[rclen].tyr = salloc(tyr); lemfont[rclen].tyb = salloc(tyb); lemfont[rclen].tyi = salloc(tyi); lemfont[rclen].psr = salloc(psr); lemfont[rclen].psb = salloc(psb); lemfont[rclen].psi = salloc(psi); } } if (rclen == 0) err(".lemrc file was empty"); } rclen++; if (f) fclose(f); /* * now set up default display fonts */ for (i=1; i<rclen; i++) { char fontname[100]; sprintf(fontname, "%s%s%d%s", FONTPATH, lemfont[i].dsp, lemfont[i].psize, FONTEXTN); bfont[i] = fontload(fontname); if (!bfont[i]) err("can't load font \"%s\"", fontname); } } SHAR_EOF if test -f 'lemselect.c' then echo shar: over-writing existing file "'lemselect.c'" fi cat << \SHAR_EOF > 'lemselect.c' /* * lemselect.c - object selection and proximity testing * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" cycleselect() { if (markobj) { if (objs[markobj]->stat == UNDEL) any(markobj, SELECT); else if (objs[markobj]->stat == SEL) any(markobj, DESELECT); } } rectselect(x0, y0, x1, y1) { int i, mode, xl, yl, xh, yh; xl = MIN(x0, x1); yl = MIN(y0, y1); xh = MAX(x0, x1); yh = MAX(y0, y1); mode = (y0 < y1) ? DESELECT : SELECT; forobjects { if (objinrect(i, xl, yl, xh, yh)) any(i, mode); } } objnearany(x, y) { int i; if (i = objnear(x, y, UNDEL)) return(i); return(objnear(x, y, SEL)); } objnear(x, y, stat) { int i; forobjsrev /* reverse order search - most recent appears first */ { if (Ostat == stat) { if (objnearpt(i, x, y)) return(i); } } return(0); } SHAR_EOF if test -f 'lemspecial.c' then echo shar: over-writing existing file "'lemspecial.c'" fi cat << \SHAR_EOF > 'lemspecial.c' /* * lemspecial.c - extra functions for random applications * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #include <math.h> specialfunc() { char ch; msgpost("<F>lip <C>cw <M>agnify <R>otate <S>tretch <A>lign: "); ch = getstroke(); switch(UC(ch)) { case 'F': flip(); break; case 'C': ccw(); break; case 'M': magnify(); break; case 'R': rotate(); break; case 'S': stretch(); break; case 'A': align(); break; default: msgpost("unknown transformation"); break; } } transform(m11, m12, m21, m22) float m11, m12, m21, m22; { int i; /* * record inverse transformation and set undo flag for undoing */ undo = UNDOAFF; unx = markx; uny = marky; un11 = m11; un12 = m12; un21 = m21; un22 = m22; /* * now do the transformations */ forobjects { if (Osel) { objectop(i, SEL, DEL); objmove(i, -markx, -marky); objaffine(i, m11, m12, m21, m22); objmove(i, markx, marky); objresize(i); objectop(i, DEL, SEL); } } } flip() { if (markon) { transform(-1.0, 0.0, 0.0, 1.0, 1); msgpost("flip done"); } else msgpost("flip -- no mark present"); } ccw() { if (markon) { transform(0.0, -1.0, 1.0, 0.0, 0); msgpost("ccw turn done"); } else msgpost("ccw -- no mark present"); } magnify() { int x1, y1, x2, y2, xs, ys, xe, ye; float mag, outlen; if (findmark(&x1, &y1, &x2, &y2)) { xs = x2-markx; ys = y2-marky; xe = x1-markx; ye = y1-marky; outlen = xs*xs+ys*ys; if (outlen != 0.0) { mag = sqrt((float)(xe*xe+ye*ye)/outlen); mag = (mag < 0.1) ? 0.1 : (mag > 10.0 ? 10.0 : mag); transform(mag, 0.0, 0.0, mag, 1); msgpost("magnify done"); } msgpost("null magnify ignored"); } } stretch() { int x1, y1, x2, y2, xs, ys, xe, ye; float xmag, ymag; if (findmark(&x1, &y1, &x2, &y2)) { xs = x2-markx; ys = y2-marky; xe = x1-markx; ye = y1-marky; xmag = (xs == 0) ? 1.0 : (float)(xe)/xs; ymag = (ys == 0) ? 1.0 : (float)(ye)/ys; xmag = (xmag < 0.1) ? 0.1 : (xmag > 10.0 ? 10.0 : xmag); ymag = (ymag < 0.1) ? 0.1 : (ymag > 10.0 ? 10.0 : ymag); transform(xmag, 0.0, 0.0, ymag, 1); msgpost("stretch done"); } } rotate() { int x1, y1, x2, y2, xs, ys, xe, ye; float s, c, hy; if (findmark(&x1, &y1, &x2, &y2)) { xs = x2-markx; ys = y2-marky; xe = x1-markx; ye = y1-marky; hy = sqrt((float)( (xs*xs + ys*ys) * (xe*xe + ye*ye) )); if (hy != 0.0) { c = (xs*xe+ys*ye)/hy; s = (xs*ye-xe*ys)/hy; transform(c, -s, s, c, 0); msgpost("rotate done"); } else msgpost("null rotation ignored"); } } align() { int x1, y1, x2, y2, xs, ys, xe, ye, scale; float m11, m12, m21, m22, det; if (findmark(&x1, &y1, &x2, &y2)) { xs = x2-markx; ys = y2-marky; xe = x1-markx; ye = y1-marky; scale = MAX(MAX(ABS(xs),ABS(ys)),MAX(ABS(xe),ABS(ye))); det = xe*ys - xs*ye; m11 = (float)( ys*scale)/det; m12 = (float)(-xs*scale)/det; m21 = (float)(-ye*scale)/det; m22 = (float)( xe*scale)/det; transform(m11, m12, m21, m22, 1); msgpost("align done"); } } findmark(x1, y1, x2, y2) int *x1, *y1, *x2, *y2; { int i, s, e, arrow, straight; arrow = straight = 0; if (!markon) { msgpost("transform: no mark present"); return(0); } else { forobjects { if (Otype != LINE) continue; s = (Oxs == markx) && (Oys == marky); e = (Oxe == markx) && (Oye == marky); if (s || e) { switch (Oalign) { case ALIGNCENT: *x1 = s ? Oxe : Oxs; *y1 = s ? Oye : Oys; straight++; break; case ALIGNLEFT: if (s) { msgpost("transform: arrowhead at origin"); return(0); } *x2 = Oxs; *y2 = Oys; arrow++; break; case ALIGNRGHT: if (e) { msgpost("transform: arrowhead at origin"); return(0); } *x2 = Oxe; *y2 = Oye; arrow++; break; } } } } if ((arrow == 1) && (straight == 1)) return(1); /* * errors */ if (arrow+straight == 0) msgpost("transform: no basis vectors at mark"); else if (arrow != 1) msgpost("transform: exactly one arrow basis vector needed"); else if (straight != 1) msgpost("transform: exactly one non-arrow basis vector needed"); return(0); } SHAR_EOF if test -f 'lemstart.c' then echo shar: over-writing existing file "'lemstart.c'" fi cat << \SHAR_EOF > 'lemstart.c' /* * lemstart.c - check command line, plus some housecleaning * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" startup(argc, argv) char **argv; { int i, plotmode; plotmode = 0; /* * initialize based on probable .rc file */ leminit(); /* * set up object defaults */ lastobj = 1; /* no objects */ setattr('0'); /* default attr's (as if '0' typed) */ gtype = LINE; /* draw lines by default */ undo = UNDONONE; /* no operation to undo */ /* * start user code and refresh the display */ start(); redraw(); /* * command line prompt */ msgpost("lemming ver 1 -- 'ctrl ^' for help"); /* * possible file name on cmd line */ changes = 0; /* no changes at present */ /* * do all command line parsing */ for(i=1; i<argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { case 'p': case 'P': plotmode = 1; break; default: err("unknown command line flag"); break; } } else { if (!firstfile) firstfile = argv[i]; /* record first input file */ readfileint(argv[i]); } } if (plotmode) { char outname[80]; sprintf(outname, "%s.pic", firstfile); writepicint(outname); stop(); exit(0); } } SHAR_EOF if test -f 'lemstop.c' then echo shar: over-writing existing file "'lemstop.c'" fi cat << \SHAR_EOF > 'lemstop.c' /* * lemstop.c - quit and error returns from lemming. * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" quitconfirm() { char c; if (changes) { msgpost("quit: [y] to confirm: "); c = getstroke(); if (UC(c) != 'Y') { msgpost("quit aborted."); return(1); } } markdelete(); stop(); exit(0); } err(msg, arg) char *msg; { fprintf(stderr, "\nlem: ", msg, arg); fprintf(stderr, msg, arg); fprintf(stderr, "\n"); exit(1); } SHAR_EOF if test -f 'lemtext.c' then echo shar: over-writing existing file "'lemtext.c'" fi cat << \SHAR_EOF > 'lemtext.c' /* * lemtext.c - text primitives * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #include "lemfont.h" textadd(x0, y0, s) char *s; { int i; if ((!s) || (strlen(s) == 0)) return; i = objalloc(TEXT); Otext = salloc(s); Oxs = x0; Oys = y0; textresize(i); objnew(i); } textresize(i) { Oxe = fontmeasure(bfont[Osizer], Otext, Oemph); Oye = lemfont[Osizer].psize; } textnearpt(i, x, y) { return(ptinrect(x, y, Oxlt, Oylt, Oxht, Oyht, TEXTTOL)); /* must be ON the text */ } textinrect(i, xl, yl, xh, yh) { return(ptinrect(Oxlt, Oylt, xl, yl, xh, yh, TEXTTOL) && ptinrect(Oxht, Oyht, xl, yl, xh, yh, TEXTTOL) ); } textcantug(i, x, y) { return(textnearpt(i, x, y)); } texttug(i, xs, ys, xe, ye) { Oxs += xe-xs; Oys += ye-ys; } textalign(i, x, y) int *x, *y; { *x = Oxs; *y = Oys; } textmove(i, x, y) { Oxs += x; Oys += y; } textaffine(i, m11, m12, m21, m22) float m11, m12, m21, m22; { objsupaffine(i, m11, m12, m21, m22, 0); } textdraw(i, col) { fontwrite(Osizer, Oxlt, Oys, Otext, Oemph, col); } SHAR_EOF if test -f 'lemtick.c' then echo shar: over-writing existing file "'lemtick.c'" fi cat << \SHAR_EOF > 'lemtick.c' /* * lemtick.c - perform ticking * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #include "lemfont.h" tickalign(x, y) int *x, *y; { if (tickflag && (ticksize < 6)) { tx = 1<<ticksize; ty = 1<<ticksize; *x = ((*x-txoff+tx/2) / tx) * tx + txoff; *y = ((*y-tyoff+ty/2) / ty) * ty + tyoff; } if (tickflag && (ticksize >= 6)) { int xl, yi, yl, d1, d2, d3, d4; tx = 1<<(ticksize-3); ty = (tx*14+7)/16; yi = ((*y-tyoff)/ty); yl = yi*ty + tyoff; xl = (((*x-txoff+((yi&0x1)?tx/2:0))/tx)*tx-((yi&0x1)?tx/2:0))+txoff; d1 = dist(*x,*y,xl ,yl); d2 = dist(*x,*y,xl+tx/2 ,yl+ty); d3 = dist(*x,*y,xl+tx ,yl); d4 = dist(*x,*y,xl+3*tx/2,yl+ty); if ((d1<=d2) && (d1<=d3) && (d1<=d4)) { *x = xl; *y = yl; } if ((d2<=d1) && (d2<=d3) && (d2<=d4)) { *x = xl+tx/2; *y = yl+ty; } if ((d3<=d1) && (d3<=d2) && (d3<=d4)) { *x = xl+tx; *y = yl; } if ((d4<=d1) && (d4<=d2) && (d4<=d3)) { *x = xl+3*tx/2; *y = yl+ty; } } } tickset() { char ch; int tmpx, tmpy; tickflag = !tickflag; if (tickflag) { msgpost("ticksize[1-5/6-9]: "); ch = getstroke(); msgclear(); if ((ch < '0') || (ch > '9')) { tickflag = 0; return; } ticksize = ch - '0'; tmpx = markon ? markx : 0; tmpy = markon ? marky : 0; txoff = 0; tyoff = 0; tickalign(&tmpx, &tmpy); /* sets tx and ty as well */ txoff = (markon ? markx : 0) - tmpx; tyoff = (markon ? marky : 0) - tmpy; while (tyoff > 0) tyoff -= ty; while (tyoff < 0) tyoff += ty; while (txoff > 0) txoff -= tx; while (txoff < 0) txoff += tx; } tickdraw(); if (!tickflag) { txoff = 0; tyoff = 0; } } tickdraw() { int x, y, xstep, ystep; xstep = tx; ystep = ty; while (xstep<MINTICK) xstep *= 2; while (ystep<MINTICK) ystep *= 2; if (ticksize < 6) { for(y = tyoff ; y<screenh; y+=ystep) for (x = txoff; x<screenw; x+=xstep) { drawvec(x, y, x + tickdot, y, tickflag ? TICKONCOL:TICKOFFCOL, 1,EMPHNONE); /* tickdot sets 0/1 width dot */ } } else { int ylim, iy; ylim = screenh/ty; y = tyoff; for(iy=0; iy<ylim; iy++) { y += ty; for (x = txoff + ((iy&0x1) ? 0 : (tx/2)); x<screenw; x+=tx) if ((x>0) && (y>0)) drawvec(x, y, x + tickdot, y, tickflag ? TICKONCOL:TICKOFFCOL,1,EMPHNONE); } } } SHAR_EOF if test -f 'lemundo.c' then echo shar: over-writing existing file "'lemundo.c'" fi cat << \SHAR_EOF > 'lemundo.c' /* * lemundo.c - undo last operation * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" undocmd() { float d; switch(undo) { case UNDOMOVE: moveselect(-unx, -uny); break; case UNDOTUG: tugunselect(unxe, unye, unx, uny); break; case UNDOAFF: d = (un11 * un22) - (un21 * un12); if (d == 0.0) return; /* no-op if singular */ transform(un22/d, -un12/d, -un21/d, un11/d); break; case UNDODEL: all(UNDELETE, 0); undo = UNDONONE; break; default: undo = UNDONONE; case UNDONONE: msgpost("cannot undo last operation"); break; } } SHAR_EOF if test -f 'lemvec.c' then echo shar: over-writing existing file "'lemvec.c'" fi cat << \SHAR_EOF > 'lemvec.c' /* * lemvec.c - line to point scan conversion * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ /* * * Programmed by Alan Paeth, University of Waterloo, January, 1984 * * This code rasterizes vectors. A call of the form: * * drawline(x0, y0, x1, y1, wid, val, emph) * * with val the output color, and emph one of EMPHITAL, EMPHBOLD, (otherwise) * generates a vector of specified which is dotted, dashed, or plain, * respectively. * * output pixels are set by calls to: * * setpixelrun(x, y, wid, val, parity) * * which should set pixels (x,y) through (x+wid-1,y) to color (val) if * parity is 0 (as it is at endpoints and some intermediate locations). * * viewport clipping is done (using integer math) to the dimensions specified * in the globals "screenw" and "screenh" * */ #include "lem.h" #define Nextflag { mask>>=1; if (++flag >= 16) { flag = 0; mask = emph; } } #define SOLID 0xffffffff /* only solid should have sign bit set */ #define DASHES 0x00ff00ff #define DOTS 0x03030303 #define ONE 0x4000 #define POINT_FIVE 0x2000 #define SCALEUP 14 #define TOPFLAG 8 #define BOTTOMFLAG 4 #define LEFTFLAG 2 #define RIGHTFLAG 1 code(x, y) float x, y; { int c = 0; if (x < 0) c |= LEFTFLAG; else if (x >= screenw) c |= RIGHTFLAG; if (y < 0) c |= BOTTOMFLAG; else if (y >= screenh) c |= TOPFLAG; return c; } drawline(x1, y1, x2, y2, wid, val, emph) /* generic brand clipped line code */ { int c, c1, c2; long x, y; if ((x1==x2) && (y1==y2)) return; /* no motion -- fast return */ c1 = code((float)(x1), (float)(y1)); c2 = code((float)(x2), (float)(y2)); while (c1 || c2) { if (c1 & c2) return; /* bitwise AND, not statement AND */ c = c1 ? c1 : c2; if (c & LEFTFLAG) y = y1 + ((y2 - y1) * ( (x = 0) - x1)) / (x2 - x1); else if (c & RIGHTFLAG) y = y1 + ((y2 - y1) * ( (x = screenw) - x1)) / (x2 - x1); else if (c & TOPFLAG) x = x1 + ((x2 - x1) * ( (y = screenh) - y1)) / (y2 - y1); else if (c & BOTTOMFLAG) x = x1 + ((x2 - x1) * ( (y = 0) - y1)) / (y2 - y1); if (c == c1) { x1 = x; y1 = y; c1 = code(x, y); } else { x2 = x; y2 = y; c2 = code(x, y); } } fastdrawline(x1, y1, x2, y2, wid, val, emph); } fastdrawline(x1, y1, x2, y2, wid, val, emph) /* * * Draws a line of pixels=val from (x1, y1) to (x2, y2) very fast. * * This is algorithm A1 from "Filtering Edges for Grey-Scale Displays" by * Gupta & Sproull (Computer Graphics 15,3 August 1981). No anti-aliasing * is being done here. However the variable 'v' can be * used to turn on * pixels to the left and right (above and below) the line since v is * horizontal distance from the center of the line to the pixel at (x, y). * * Last Hacked by: Alan Paeth */ int x1, y1, x2, y2, val, emph; { register x, y; /* current position in line */ int incr; /* y increment = + or - 1 */ int dx, dy; /* change in x, y */ int m; /* slope of line ( * 2 ** 14 ) */ int s; /* threshold for diagonal move */ register v; /* dist from line to pixel */ int mm1; /* m - (1 << 9) */ int mask; int flag; flag = 0; emph = (emph == EMPHITAL) ? DOTS : ((emph == EMPHBOLD) ? DASHES : SOLID); mask = emph; if (y2 > y1) /* make y1 > y2 by symmetries */ { x = x1; x1 = x2; x2 = x; y = y1; y1 = y2; y2 = y; } incr = 1; dy = y1 - y2; if ((dx = x2 - x1) < 0) { dx = -dx; incr = -1; } v = 0; if (dx > dy) { m = ((long)dy << SCALEUP) / (long)dx; s = POINT_FIVE - m; mm1 = m - ONE; y = y1; for( x = x1; x != x2; x += incr ) { if (mask & 0x1) setpixelrunv(x, y, wid, val, flag & 0x1); Nextflag; if( v >= s ) { --y; v += mm1; } /* diagonal move */ else v += m; /* horizontal move */ } setpixelrunv(x, y, wid, val, 0); } else { if( dy > 0 ) { m = ((long)dx << SCALEUP) / (long)dy; s = POINT_FIVE - m; mm1 = m - ONE; } x = x1; for( y = y1; y > y2; --y ) { if (mask & 0x1) setpixelrunh(x, y, wid, val, flag&0x1); Nextflag; if ( v >= s ) { x += incr; v += mm1; } /* diagonal move */ else v += m; /* vertical move */ } setpixelrunh(x, y, wid, val, 0); } } SHAR_EOF if test -f 'lemx.c' then echo shar: over-writing existing file "'lemx.c'" fi cat << \SHAR_EOF > 'lemx.c' /* * lemx.c - lemming driver for X window software * * copyright (c) by Alan W. Paeth, 1987. All rights reserved. */ #include "lem.h" #include <X/Xlib.h> #define EV (ButtonPressed | ButtonReleased | KeyPressed | ExposeWindow | ExposeRegion) Window win; int xsave, ysave, drawcol, erasecol, selectcol, markoncol, markoffcol, lut; int sysmsgloc; char sysmsg[120]; unsigned char maptab[256]; /* bit reversing table */ start() { screenw = 512; screenh = 512; if ((XOpenDisplay("")) == NULL) err("display open failed"); win = XCreateWindow(RootWindow, screenw/2, screenh/2, screenw, screenh, 2, WhitePixmap, BlackPixmap); if (win == NULL) err("window open failed"); lut = DisplayCells() > 2; XMapWindow(win); XSelectInput(win, EV); if (lut) { cblack = findcolor(0,0,0); cwhite = findcolor(1,1,1); cred = findcolor(1,0,0); cgreen = findcolor(0,1,0); tickdot = 0; } else { cwhite = 1; cblack = 0; cred = 2; cgreen = 1; tickdot = 1; } setcursor(); } stop() { } getevent(xdn, ydn, xup, yup, ch) int *xdn, *ydn, *xup, *yup; char *ch; { int ret, count; XEvent ev; XWindowEvent(win, EV, &ev); ret = NOEVT; switch(ev.type) { case ButtonPressed: xsave = mx(&ev); ysave = my(&ev); break; case ButtonReleased: *xdn = xsave; *ydn = ysave; *xup = mx(&ev); *yup = my(&ev); ret = MOUSE; break; case KeyPressed: *ch = *XLookupMapping(&ev, &count); if (*ch) { if ((*ch >= ' ') && (*ch != '\177')) ret = ALPHA; else if (*ch > 0) ret = CNTRL; } break; case ExposeRegion: case ExposeWindow: checkwindowsize(); redraw(); break; } XFlush(); return(ret); } checkwindowsize() { WindowInfo winfo; XQueryWindow(win, &winfo); screenw = winfo.width; screenh = winfo.height; } setcursor() { Cursor c; static short cur_bgnd[] = { 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x03e0, 0x0630, 0x7c1f, 0x7c1f, 0x7c1f, 0x0630, 0x03e0, 0x01c0, 0x01c0, 0x01c0, 0x01c0, 0x0000 }; static short cur_fgnd[] = { 0x0080, 0x0080, 0x0080, 0x0080, 0x03e0, 0x0630, 0x0410, 0x7c1f, 0x0410, 0x0630, 0x03e0, 0x0080, 0x0080, 0x0080, 0x0080, 0x0000 }; c = XCreateCursor(16, 16, cur_fgnd, cur_bgnd, 7,7,cwhite,cblack,GXcopy); XDefineCursor(win, c); } setpixelrunh(x0, y0, wid, col, dotflag) { if (col == cred) { col = (dotflag) ? cblack: cwhite; /* checkerboard select */ } XPixSet(win, x0, (screenh-1)-y0, wid, 1, col); } setpixelrunv(x0, y0, wid, col, dotflag) { if (col == cred) { col = (dotflag) ? cblack: cwhite; /* checkerboard select */ } XPixSet(win, x0, (screenh-1)-y0, 1, wid, col); } drawvec(x0, y0, x1, y1, col, wid, emph) { #define SOLID SolidLine #define DASHES XMakePattern(0x00ff,16,1) #define DOTS XMakePattern(0x0303,16,1) Vertex chain[2]; int pattern; if (lut) { /* XLine(win,x0,screenh-y0,x1,screenh-y1,wid,wid,col,GXcopy,AllPlanes); */ chain[0].x = x0 - wid/2; chain[0].y = screenh-y0 - wid/2; chain[0].flags = VertexDrawLastPoint; chain[1].x = x1 - wid/2; chain[1].y = screenh-y1 - wid/2; chain[1].flags = VertexDrawLastPoint; pattern = (emph==EMPHNONE) ? SOLID : ((emph==EMPHBOLD) ? DASHES : DOTS); XDrawDashed(win, chain, 2, wid, wid, col, pattern, GXcopy, AllPlanes); } else drawline(x0-wid/2, y0+wid/2, x1-wid/2, y1+wid/2, wid, col, emph); /* SUN version does not understand dots and dashes -- we must do it all */ } charshow(str) char *str; { int i; for(i=0; i<strlen(str); i++) sysmsg[sysmsgloc++] = str[i]; sysmsg[sysmsgloc] = '\0'; fontwrite(SYSFONT, 10, 10, sysmsg, EMPHNONE, cgreen); XFlush(); } charunshow(n) { fontwrite(SYSFONT, 10, 10, sysmsg, EMPHNONE, cblack); while (n--) { if (sysmsgloc) sysmsg[--sysmsgloc] = '\0'; } fontwrite(SYSFONT, 10, 10, sysmsg, EMPHNONE, cgreen); XFlush(); } erase() { XPixSet(win, 0, 0, screenw, screenh, cblack); fontwrite(SYSFONT, 10, 10, sysmsg, EMPHNONE, cgreen); XFlush(); } /* * internal stuff */ findcolor(r, g, b) int r, g, b; { Color c; c.red = r*65535; c.green= g*65535; c.blue = b*65535; if (!XGetHardwareColor(&c)) { /* err("no more room in color table"); */ return(b*4+g*2+r); } return(c.pixel); } mx(ev) XKeyEvent *ev; { return(ev->x); } my(ev) XKeyEvent *ev; { return(screenh - ev->y + 1); } writescan(x, y, pixels, outaddr, color) int x, y, pixels, *outaddr, color; { if (pixels <= 0) return; /* PARANOIA: should not ever happen */ if (!lut && color == cred) { register int i, lim; lim = (pixels+31)/32; if ((x^y) & 0x1) for(i=0; i<lim; i++) outaddr[i] &= 0x55555555; else for(i=0; i<lim; i++) outaddr[i] &= 0xaaaaaaaa; color = cwhite; } swapshorts(outaddr, (pixels+31)/8); XBitmapBitsPut(win, x, y, pixels, 1, outaddr, color, cblack, 0, GXcopy, AllPlanes); } swapshorts(buf, len) register unsigned char *buf; { unsigned char c1, c2, c3, c4; register int count, i; if (!maptab[1]) maptabinit(); count = len/4; for (i=0; i<count; i++) { c1 = *buf++; c2 = *buf++; c3 = *buf++; c4 = *buf; *buf-- = maptab[c1]; *buf-- = maptab[c2]; *buf-- = maptab[c3]; *buf = maptab[c4]; buf += 4; } } maptabinit() { register int i, j; unsigned char mask; for(i = 0; i<256; i++) { mask = 0; for(j = 0; j < 8; j++) if (i & (1<<j)) mask |= 1<<(7-j); maptab[i] = mask; } } SHAR_EOF # End of shell archive exit 0 -- Rich $alz "Anger is an energy" Cronus Project, BBN Labs rsalz@bbn.com Moderator, comp.sources.unix sources@uunet.c c cs)