home *** CD-ROM | disk | FTP | other *** search
- // ┌───────┐
- // ─────────>│ AVNER │
- // ─────────>│ BEN │──────> Software Engineering Method
- // └───────┘
- // 10 Dov-Hoz st. Tel-Aviv 63416 Israel tel. 972-3-221535
-
- // The Screen NAVigator, ver 1.10 April 1990
- // Copyright (c) 1989 by Avner Ben
- // Snav is not, and never was, free software.
- // for conditions for use refer to file "copyrigh.txt"
-
- // The Screen Navigator is an object-oriented device-independent
- // character-graphics driver package, written in the C++ language,
- // distributed in the form of C++ source code.
- // For further information refer to the documentation files.
-
- // The user may not omit this text, from the beginning of the file, to
- // the line of asterisks below.
-
- /***************************************************************************/
-
- // package nucleus part 3 - source code.
- // This file defines the generic "panel" (formatted output medium),
- // and the generic "shape" (character-graphic element to be charted on
- // the former).
-
- // History:
- // 25.10.89 avner ben coded.
- /////// snav v1.1
- // 22.1.90-11.4.90 avner ben:
- // * seperated specific shapes to snav3 * C++ v2.0 upgrade * debugged title
- // centering in enframe * added class square_pos * renamed class point
- // point_pos * developed class point * renamed class curve stroke * in class
- // curve, replaced offset with pendn toggle * moved iterator methods from curve
- // to shape * added last-curve pointer to shape * added "intelligent" curve
- // appending mechanism, resolving redundant strokes * added color to panel *
- // moved some function from implementation screen driver * added to class panel
- // color and cursor processing * added struct color_ind *
-
- // Site history (of this copy):
- // __.__.__ ____________ : __________________.
-
- #ifndef SNAV2_C
- #define SNAV2_C
- #endif
-
- #include <stdio.h>
- #include "snav2.hpp"
- #include "snav2.hpp"
- #include <stdio.h>
-
- ///////////////////// window dimensions:
-
- point_pos :: point_pos(int y, int x, const direction &dir)
- { ypos=y; xpos=x; chg_dir(dir,1); }
-
- point_pos :: point_pos(const direction &dir, const point_pos &other)
- { ypos=other.ypos; xpos=other.xpos; chg_dir(dir,1); }
-
- point_pos & point_pos :: operator+=(const point_pos &offset)
- // shift by user-specified offset
- { ypos+=offset.ypos; xpos+=offset.xpos; return(*this); }
-
- point_pos & point_pos :: operator-=(const point_pos &shifted)
- // shift conter to user-specified offset
- { ypos-=shifted.ypos; xpos-=shifted.xpos; return(*this); }
-
- void point_pos :: move(const direction &dir, int len)
- {
- switch (dir()) {
- case RTDIR : xpos+=len; break;
- case UPDIR : ypos-=len; break;
- case LTDIR : xpos-=len; break;
- case DNDIR : ypos+=len; break;
- }
- }
-
- int point_pos :: how_far(const direction &dir)
- { // only positive result counts
-
- int result=0;
- switch (dir()) {
- case RTDIR : if (xpos>0) result=xpos; break;
- case UPDIR : if (ypos<0) result=-ypos; break;
- case LTDIR : if (xpos<0) result=-xpos; break;
- case DNDIR : if (ypos>0) result=ypos; break;
- }
- return result;
- }
-
- void point_pos :: chg_dir(const direction &dir, int len)
- {
- switch (dir()) {
- case RTDIR : xofst=len; yofst=0; break;
- case UPDIR : xofst=0; yofst=-len; break;
- case LTDIR : xofst=-len; yofst=0; break;
- case DNDIR : xofst=0; yofst=len; break;
- }
- }
-
- char * point_pos :: name()
- {
- static char result[12];
- sprintf(result,"%-d:%-d",ypos,xpos);
- return result;
- }
-
- void square_pos :: move_limit(const direction &dir, int ofst)
- {
- switch (dir()) {
- case RTDIR : bot.xpos+=ofst; break;
- case UPDIR : top.ypos-=ofst; break;
- case LTDIR : top.xpos-=ofst; break;
- case DNDIR : bot.ypos+=ofst; break;
- }
- }
-
- void square_pos :: set_limit(const direction &dir, int pos)
- { // modify window dimensions
-
- switch(dir()) {
- case RTDIR : bot.xpos=pos; break;
- case UPDIR : top.ypos=pos; break;
- case LTDIR : top.xpos=pos; break;
- case DNDIR : bot.ypos=pos; break;
- }
- }
-
- void square_pos :: set_start(const point_pos &start)
- {
- top=start;
- curlen=bot.ypos-top.ypos+1;
- curwd=bot.xpos-top.xpos+1;
- }
-
- void square_pos :: set_end(const point_pos &end)
- {
- bot=end;
- curlen=bot.ypos-top.ypos+1;
- curwd=bot.xpos-top.xpos+1;
- }
-
- void square_pos :: set_end_y(int len)
- {
- bot.sety(top.ypos+len-1);
- curlen=len;
- }
-
- void square_pos :: set_end_x(int wd)
- {
- bot.setx(top.xpos+wd-1);
- curwd=wd;
- }
-
- void square_pos :: move(const direction &dir, int len)
- {
- top.move(dir,len); bot.move(dir,len);
- }
-
- int square_pos :: len(const axis &dim)
- {
- if (dim==vdim) return curlen; else return(curwd);
- }
-
- char * square_pos :: name()
- {
- static char result[24];
- sprintf(result,"%sx%s",top.name(),bot.name());
- return result;
- }
-
- void color_ind :: toggle_attr(vd_attr at)
- { if (ask_attr(at)) attr_off(at); else attr_on(at); }
-
- void color_ind :: set_for_clr(vd_clr color)
- { if (attr==VD_REV) backgnd=color; else forgnd=color; }
-
- void color_ind :: set_back_clr(vd_clr color)
- { if (attr==VD_REV) forgnd=color; else backgnd=color; }
-
- vd_clr color_ind :: ask_for_clr()
- { if (attr==VD_REV) return backgnd; else return forgnd; }
-
- vd_clr color_ind :: ask_back_clr()
- { if (attr==VD_REV) return forgnd; else return backgnd; }
-
- void color_ind :: normalize()
- {
- if (attr==VD_REV) {
- vd_clr t=forgnd;
- forgnd=backgnd; backgnd=t;
- attr_off(VD_REV);
- }
- }
-
- boolean color_ind :: operator()()
- { return attr && (int)backgnd && (int)forgnd; }
-
- boolean color_ind :: operator==(const color_ind &other)
- { return (attr==other.attr && backgnd==other.backgnd && forgnd==other.forgnd); }
-
- boolean color_ind :: operator!=(const color_ind &other)
- { return (attr!=other.attr || backgnd!=other.backgnd || forgnd!=other.forgnd); }
-
- /////////////////////////// the generic panel
-
- static point_pos top_pos(1,1), bot_pos(25,80);
-
- panel :: panel(square_pos *window, color_ind *clr, direction *dir, boolean ingraph, boolean inwrap)
- : win(top_pos,bot_pos)
- {
- lang=0;
- if (window) win=*window;
- if (clr) color=def_color=*clr;
- if (dir) curdir=*dir; // default direction right
- takes_graph=ingraph; wrap_around=inwrap;
- fix();
- }
-
- void panel :: fix(void)
- {
- top=win.start();
- bot=win.end();
- hlen=bot.xpos-top.xpos+1;
- vlen=bot.ypos-top.ypos+1;
- }
-
- boolean panel :: ask_legal(point_pos *pt)
- {
- return(
- pt->xpos>=top.xpos
- && pt->xpos<=bot.xpos
- && pt->ypos>=top.ypos
- && pt->ypos<=bot.ypos
- );
- }
-
- boolean panel :: next(direction *dir, point_pos *pt0)
- { // next cursor position, if movement possible. wrap-around not practiced
-
- if (!dir) dir=&curdir;
- point_pos *pt=(pt0? pt0 : &cursor);
- switch ((*dir)()) {
- case RTDIR : if (pt->xpos>=bot.xpos) return FALSE;
- pt->move(rt); break;
- case UPDIR : if (pt->ypos<=top.ypos) return FALSE;
- pt->move(up); break;
- case LTDIR : if (pt->xpos<=top.xpos) return FALSE;
- pt->move(lt); break;
- case DNDIR : if (pt->ypos>=bot.ypos) return FALSE;
- pt->move(dn); break;
- }
- if (!pt0) posit();
- return TRUE;
- }
-
- boolean panel :: wpnext(direction *dir, point_pos *pt0)
- { // next cursor position. wrap-around is practiced if allowed by panel's setup
- ///////////////// experimental code! //////////////////////////
-
- if (!dir) dir=&curdir;
- point_pos *pt=(pt0? pt0 : &cursor);
- connective dirval=(*dir)();
- if (dirval==RTDIR) {
- if (pt->xpos<bot.xpos) pt->move(rt);
- else if (wrap_around) {
- pt->xpos=top.xpos;
- pt->move(dn);
- if (pt->ypos>bot.ypos) pt->ypos=top.ypos;
- } else return FALSE;
- } else if (dirval==UPDIR) {
- if (pt->ypos>top.ypos) pt->move(up);
- else if (wrap_around) {
- pt->ypos=bot.ypos;
- pt->move(lt);
- if (pt->xpos<top.xpos) pt->xpos=bot.xpos;
- } else return FALSE;
- } else if (dirval==LTDIR) {
- if (pt->xpos>top.xpos) pt->move(lt);
- else if (wrap_around) {
- pt->setx(bot.xpos);
- pt->move(dn);
- if (pt->ypos>bot.ypos) pt->ypos=top.ypos;
- } else return FALSE;
- } else if (dirval==DNDIR) {
- if (pt->ypos<bot.ypos) pt->move(dn);
- else if (wrap_around) {
- pt->ypos=top.ypos;
- pt->move(rt);
- if (pt->xpos>bot.xpos) pt->xpos=top.xpos;
- } else return FALSE;
- }
- if (!pt0) posit();
- return TRUE;
- }
-
- char panel :: next_c(direction *dir, point_pos *pt0)
- { // get neighbour of cursor/specified char
-
- if (!dir) dir=&curdir;
- point_pos pt; if (pt0) pt=*pt0; else pt=cursor;
- if (!next(dir,&pt)) return ' '; // no wrap-around
- return get_c(&pt);
- }
-
- char * panel :: env(point_pos *pt)
- { // returns string made of current char, followed by sorounding chars
-
- static char buf[6];
- buf[0]=get_c(pt);
- for (direction dir; dir(); dir++)
- buf[dir.serial()]=next_c(&dir,pt); // no wrap-around
- buf[5]='\0';
- return(buf);
- }
-
- void panel :: home()
- {
- switch (curdir()) {
- case RTDIR : // going right and down (normal latin)
- cursor.ypos=top.ypos;
- cursor.xpos=top.xpos;
- break;
- ///////////////// experimental code! //////////////////////////
- case UPDIR : // going up and left (whatever that means)
- cursor.ypos=bot.ypos;
- cursor.xpos=bot.xpos;
- break;
- case LTDIR : // going left and down (semitic languages)
- cursor.ypos=top.ypos;
- cursor.xpos=bot.xpos;
- break;
- case DNDIR : // going down and right (asian languages?)
- cursor.ypos=top.ypos;
- cursor.xpos=top.xpos;
- break;
- }
- posit();
- }
-
- void panel :: clr_eol(point_pos *pt0)
- { // erase to end of line
-
- point_pos pt;
- if (pt0) pt=*pt0; else pt=cursor;
- if (!ask_legal(&pt)) return;
- color_ind sav=color; reset_color();
- for (; pt.xpos<=bot.xpos; pt.move(rt))
- put_c(' ',&pt);
- color=sav;
- }
-
- void panel :: clear()
- { // clear whole screen and position home
-
- int maxy=bot.ypos;
- reset_color();
- point_pos pt(dn,top);
- for (; pt.ypos<=maxy; pt++)
- clr_eol(&pt);
- home();
- }
-
- void panel :: put_s(char *s, point_pos *pt0, direction *dir0)
- { // write a string on screen
-
- point_pos *pt=NULL; if (pt0) pt=new point_pos(*pt0);
- direction *dir=NULL; if (dir0) dir=new direction(*dir0);
- for (; *s; s++) {
- put_c(*s,pt,dir);
- // put_c advances panel->cursor (if pt==NULL). otherwise...
- if (pt)
- if (!next(dir,pt)) return; // no wrap-around!
- }
- if (pt) delete pt; if (dir) delete dir;
- }
-
- int panel :: ask_limit(const direction &dir)
- { // beginning/end of window - height/breadth
-
- switch(dir()) {
- case RTDIR : return bot.xpos;
- case UPDIR : return top.ypos;
- case LTDIR : return top.xpos;
- case DNDIR : return bot.ypos;
- }
- return 0;
- }
-
- void panel :: set_limit(const direction &dir, int pos)
- { // modify window dimensions
-
- win.set_limit(dir,pos);
- fix();
- }
-
- void panel :: move_limit(const direction &dir, int ofst)
- {
- win.move_limit(dir,ofst);
- fix();
- }
-
- int panel :: ask_len(const axis &dim)
- {
- if (dim==hdim) return hlen;
- if (dim==vdim) return vlen;
- return 0;
- }
-
- point_pos panel :: ask_corner(const direction &dir)
- { // only top-left or bottom-right
-
- if (dir()==UPDIR || dir()==LTDIR) return top;
- return bot;
- }
-
- void panel :: set_color(const color_ind &clr)
- { color=clr; fix(); }
-
- void panel :: toggle_attr(vd_attr at)
- { color.toggle_attr(at); fix(); }
-
- void panel :: set_def_attr(vd_attr at)
- {
- def_color.toggle_attr(at);
- set_color(def_color);
- }
-
- void panel :: set_def_background(vd_clr colornum)
- {
- def_color.backgnd=colornum;
- set_color(def_color);
- paint_background(colornum);
- }
-
- void panel :: paint_background(vd_clr colornum)
- {
- int maxy=bot.ypos, maxx=bot.xpos;
- for (point_pos ypt(dn,top); ypt.ypos<=maxy; ypt++)
- for (point_pos xpt(rt,ypt); xpt.xpos<=maxx; xpt++)
- put_background(colornum,&xpt);
- }
-
- void panel :: set_def_forground(vd_clr colornum)
- {
- def_color.forgnd=colornum;
- set_color(def_color);
- }
-
- boolean panel :: enframe(const weight_d &wgt, char *intitle, boolean centered)
- { // enclose window in box, and contract
-
- if (hlen<3 || vlen<3) return FALSE;
- (oblong(hlen,vlen,wgt)).list(this,&top);
- if (*intitle) {
- int len=(strlen(intitle)<=hlen-2 ?
- strlen(intitle) : hlen-2);
- char *s=new char[len+1];
- for (int i=0; i<len; i++) s[i]=intitle[i];
- s[len]='\0'; point_pos pt=top;
- switch (curdir()) {
- case RTDIR : if (!centered) pt.move(rt);
- else pt.move(rt,(hlen-2-len)/2);
- put_s(s,&pt);
- break;
- ///////////////// experimental code! //////////////////////////
- case UPDIR : if (centered)
- put_s(s,&point_pos(vlen+1-(vlen-2-len)/2,
- bot.xpos));
- else put_s(s,&point_pos(bot.ypos-1,bot.xpos));
- break;
- case LTDIR : if (centered)
- put_s(s,&point_pos(top.ypos,hlen+1
- -(hlen-2-len)/2));
- else put_s(s,&point_pos(top.ypos,bot.xpos-1));
- break;
- case DNDIR : if (centered)
- put_s(s,&point_pos((vlen-2-len)/2,top.xpos));
- else put_s(s,&point_pos(top.ypos,top.xpos+1));
- break;
- }
- delete s;
- }
- // contract
- move_limit(lt,-1);
- move_limit(rt,-1);
- move_limit(up,-1);
- move_limit(dn,-1);
- home();
- return TRUE;
- }
-
- void panel :: deframe()
- { // expand, checking nothing
-
- move_limit(lt);
- move_limit(rt);
- move_limit(up);
- move_limit(dn);
- (oblong(hlen,vlen)).clear(this,&top);
- }
-
- boolean panel :: twg_c(point_pos *pt)
- { // translate typewriter graphic char to 1h1v semigraphic
- // ("full screen" algorithm)
-
- char *around=env(pt); char c=*around;
- intersection avdir=alph->cdir(c);
- if (!avdir() || (alph->cweight(c))()) return FALSE; // not a twg char
- // ajust to actual connectivity
- intersection actdir=alph->cdir(c);
- char csemi=alph->translate(c,h1v1); // semigraphic self
- char ctwg=alph->translate(csemi,twgwgt); // semigraphic self
- for (direction dir; dir(); dir++)
- if (actdir>=dir
- && !alph->ccont(ctwg,around[dir.serial()],dir) // connects as is?
- && !alph->ccont(csemi,around[dir.serial()],dir)) // connects edited?
- actdir-=dir; // no partner in direction
- if (!actdir()) return FALSE; // lonely char - no arc
- if (actdir.unary()) { // arc terminator
- if (avdir.unary()) { // arrow
- if (ask_grph()) put_c(alph->translate(c,h1v1),pt);
- } else { // not arrow
- // does arc continue from partner?
- direction opsdir(actdir()); opsdir.opposite();
- point_pos ngbr=*pt;
- if (!next(&direction(actdir()),&ngbr)) return FALSE;
- around=env(&ngbr); char c1=*around;
- char c1semi=alph->translate(c1,h1v1);
- char c1twg=alph->translate(c1semi,twgwgt);
- intersection actdir1=alph->cdir(c1);
- for (direction dir; dir(); dir++)
- if (actdir1>=dir && dir!=opsdir
- && (alph->ccont(c1twg,around[dir.serial()],dir)
- || alph->ccont(c1semi,
- around[dir.serial()],dir))) {
- if (avdir.type()==J_CROSS)
- csemi=alph->ctrim(csemi,opsdir);
- put_c(csemi,pt);
- return TRUE; // more than two in arc
- }
- if ((alph->cdir(c1)).unary()) { // other is arrow
- if (avdir.type()==J_CROSS)
- csemi=alph->ctrim(csemi,opsdir);
- put_c(csemi,pt);
- }
- }
- } else put_c(alph->get_c(actdir,h1v1),pt); // middle of arc
- return TRUE;
- }
-
- int panel :: twg()
- { // translate typewriter graphics to 1h1v semigraphics
-
- int changes=0;
- point_pos pt(rt,top);
- for (; pt.ypos<=bot.ypos; pt.move(dn))
- for (pt.setx(top.xpos); pt.xpos<=bot.xpos; pt++)
- changes+=twg_c(&pt);
- return changes;
- }
-
- void panel :: arclist(point_pos *pt0, int len, const direction &dir,
- const weight_d &wgt, boolean tipped, color_ind *color)
- { // draw straight line graphic primitive. interface for arc::list()
-
- point_pos pt(dir,*pt0);
- color_ind savcolor=ask_color();
- if (color) { // forground only!
- color_ind newclr=ask_color();
- newclr.set_for_clr(color->forgnd);
- set_color(newclr);
- }
- for (int i=1; i<=len; ++i) {
- #ifndef ENV_MODIFY // draw current char only
- put_c(alph->carrw(env(&pt),dir,wgt,len,i,tipped),&pt);
- #else // trim excess
- char around[6]; strcpy(around,env(&pt));
- alph->cearrw(around,dir,wgt,len,i,tipped);
- put_c(*around,&pt);
- for (direction tdir; tdir(); tdir++)
- point_pos ngbr; color_ind tclr;
- if (around[tdir.serial()]!=' ') {
- ngbr=pt;
- if (next(&tdir,&ngbr)) {
- tclr=get_color(&ngbr);
- put_c(around[tdir.serial()],&ngbr);
- put_color(tclr,&ngbr);
- }
- }
- #endif
- pt++; // legality of pos ignored
- }
- set_color(savcolor);
- }
-
- void panel :: arcclr(point_pos *pt0, int len, const direction &dir)
- { // clear space formerly occupied by straight line
-
- point_pos pt(dir,*pt0);
- color_ind savcolor=ask_color(); reset_color();
- for (int i=1; i<=len; ++i) {
- put_c(' ',&pt);
- pt++; // legality of pos ignored
- }
- set_color(savcolor);
- }
-
- intersection panel :: gowhere(point_pos *junction, intersection *result)
- { // directions of arcs available from specified point on screen
-
- if (!result) result=new intersection((int)NODIR);
- else *result=intersection((int)NODIR);
- char around[6]; strcpy(around,env(junction));
- for (direction dir; dir(); dir++)
- if (alph->ccont(*around,*(around+dir.serial()),dir))
- *result+=dir;
- return(*result);
- }
-
- square_pos panel :: ask_window(void)
- { return win; }
-
- panel :: ~panel(void)
- { restore(); }
-
- color_ind panel :: ask_color(void)
- { return color; }
-
- color_ind panel :: ask_def_color(void)
- { return def_color; }
-
- boolean panel :: ask_attr(vd_attr at)
- { return color.ask_attr(at); }
-
- void panel :: reset_color(void)
- { set_color(def_color); }
-
- void panel :: set_def_color(const color_ind &clr)
- { def_color=clr; set_color(clr); set_def_background(clr.backgnd); }
-
- boolean panel :: ask_grph(void)
- { return takes_graph; }
-
- boolean panel :: ask_wrap(void)
- { return wrap_around; }
-
- void panel :: set_dir(const direction &dir)
- { curdir=dir; }
-
- void panel :: turn(void)
- { curdir.clockwise(); }
-
- int panel :: ask_lang(void)
- { return lang; }
-
- void panel :: set_lang(int inlang)
- { lang=inlang; }
-
- ////////////////////////// screen type selection /////////////////////
-
- screen_driver_manager :: screen_driver_manager(int def)
- { default_screen=def; }
-
- int screen_driver_manager :: ask_default(void)
- { return default_screen; }
-
- void screen_driver_manager :: set_default(int def)
- { default_screen=def; }
-
- ////////////////////////// line-drawing primitives
-
- void arc :: list(panel *scr, point_pos *pt)
- { scr->arclist(pt,len,dir,wgt,tipped,color); }
-
- void arc :: clear(panel *scr, point_pos *pt)
- { scr->arcclr(pt,len,dir); }
-
- void arc :: contract(void)
- { if (len) len--; }
-
- void arc :: expand(void)
- { len++; }
-
- void arc :: turn(void)
- { dir.clockwise(); }
-
- void arc :: invert(void)
- { dir.opposite(); }
-
- void arc :: toggle_tip(void)
- { tipped=!tipped; }
-
- void arc :: set_len(int inlen)
- { len=inlen; }
-
- void arc :: set_dir(const direction &indir)
- { dir=indir; }
-
- void arc :: set_wgt(const weight_d &inwgt)
- { wgt=inwgt; }
-
- void arc :: mask(const weight_d &other_wgt)
- { wgt.mask(other_wgt); }
-
- stroke :: stroke(arc *src, boolean pen_down) : arc(*src), offset(0,0)
- {
- pendn=pen_down; color=NULL;
- next=NULL;
- }
-
- stroke :: stroke(int inlen, const direction &indir, const weight_d &inwgt,
- boolean intip, color_ind *incolor, boolean pen_down) :
- arc(inlen, indir, inwgt, intip, incolor), offset(1,1)
- {
- pendn=pen_down;
- if (incolor) {
- color=new color_ind;
- *color=*incolor;
- } else *color=NULL;
- next=NULL;
- }
-
- void stroke :: toggle_pen()
- { pendn=!pendn; }
-
- boolean stroke :: pen_is_down()
- { return pendn; }
-
- ///////////////////////////// shape drawing ///////////////////////////////
-
- shape :: shape(stroke *sk, char *inname)
- {
- stsk=ensk=sk;
- sname=new char[strlen(inname)+1]; strcpy(sname,inname);
- }
-
- void shape :: append_stroke(stroke *sk)
- {
- if (!sk) return; // caller's bug
- stroke *lastsk=ensk;
- if (!stsk) stsk=ensk=sk;
- else if (sk->dir==ensk->dir && sk->wgt()==ensk->wgt()
- && (sk->color == ensk->color || sk->color && ensk->color
- && *(sk->color)==*(ensk->color))) // redundant?
- if (sk->len>1)
- if (sk->pendn!=ensk->pendn)
- ensk=ensk->next=sk; // not redundant - accept!
- else ensk->len+=sk->len; // redundant - weld!
- else; // redundant arcs of length 1 are bugs
- else ensk=ensk->next=sk;
- if (sk!=ensk) { delete sk; return; }
- // compute offset from base
- if (lastsk) {
- sk->offset=lastsk->offset;
- (sk->offset).move(sk->dir,sk->len-1);
- }
- // fill-in axis_weight, when scan started in midline (tracing shape)
- if (sk->wgt() && !((sk->wgt).y() && (sk->wgt).x()))
- if (lastsk && lastsk->pen_is_down())
- (sk->wgt).mask(lastsk->wgt);
- else for (stroke *sk0=stsk; sk0; sk0=sk0->next)
- if (sk0->offset==sk->offset)
- { (sk->wgt).mask(sk0->wgt); break; }
- }
-
- void shape :: append_stroke(const point_pos &offset)
- {
- for (direction dir; dir(); dir++)
- if (offset.how_far(dir))
- append_stroke(new stroke(offset.how_far(dir)+1,dir,twgwgt,FALSE,0,FALSE));
- }
-
- shape :: ~shape()
- {
- delete sname;
- if (stsk) {
- stroke *next=stsk->next;
- for (; stsk; stsk=next) {
- next=stsk->next;
- delete stsk;
- }
- }
- }
-
- void shape :: list(panel *scr, point_pos *pt0, boolean stay)
- { // the generic shape lister - used if inherited method not provided
-
- point_pos pt=*pt0;
- for (stroke *sk=stsk; sk; sk=sk->next) {
- if (sk->len && sk->dir()) {
- if (sk->pendn)
- sk->arc::list(scr,&pt);
- pt.move(sk->dir(),sk->len-1);
- }
- }
- if (!stay) *pt0=pt;
- }
-
- void shape :: clear(panel *scr, point_pos *pt0, boolean stay)
- { // the generic shape eraser - used if inherited method not provided
-
- point_pos pt=*pt0;
- for (stroke *sk=stsk; sk; sk=sk->next) {
- if (sk->len && sk->dir()) {
- if (sk->pendn)
- sk->arc::clear(scr,&pt);
- pt.move(sk->dir(),sk->len-1);
- }
- }
- if (!stay) *pt0=pt;
- }
-
-
-