Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!sgtp.apple.juice!shin From: shin@sgtp.apple.juice (Shinichirou Sugou) Newsgroups: gnu.gdb.bug Subject: Bug (?) report of gdb-3.1. Message-ID: <8904250540.AA03136@sgtp.apple.juice> Date: 25 Apr 89 05:40:33 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 2342 Dear FSF people: I think it maybe bug, but not sure which causes this bug, gdb or g++. For the present, I report to 'gdb'. My system is, gdb-3.1, g++-1.32, Sun3/60 with OS3.4. Whole program is appended at the last of this letter as shar-format. (0) Please use Sun if possible because this program uses special malloc.o file which is pecurial to Sun. Also, please use GNU's make. Sun's make will result in Makefile error. (1) Make a directory and rebuild whole sources. You know the way how to rebuild the program from shar-file, don't you? :-) (2) Type 'make'. Finally, the object named 'p' will be produced. (3) Type 'gdb p' to invoke gdb. (4) Set break point at grafPort::getPortRect by typing 'b grafPort::getPortRect'. (5) Run the program. (6) This function returns the 'portRect' (see grafPort.h and rect.h about its definition), its value must be... portRect = {left = 0, top = 0, right = 80, bottom = 24} (7) Type 'finish' to get what is retuned. You will see the incorrect return value, Value returned is $2 = {left = 0, top = 152880, right = 80, bottom = 0} What is wrong? Yours sincerely. CAUTION: Reply-command supplied by your mail system may NOT generate my address correctly. Please use the following address instead. shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net --- Shinichirou Sugou shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net Program sources (as shar format) follows... #! /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: # ch.cc # terminal.cc # grafPort.cc # charMap.cc # bitMatrix.cc # misc.cc # region.cc # point.cc # rect.cc # quickDraw.cc # ch.h # terminal.h # grafPort.h # charMap.h # bitMatrix.h # misc.h # region.h # point.h # rect.h # quickDraw.h # global.h # Makefile # .gdbinit # dlist # This archive created: Tue Apr 25 14:16:34 1989 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'ch.cc' then echo shar: "will not over-write existing file 'ch.cc'" else cat << \SHAR_EOF > 'ch.cc' #include #include #include "global.h" #include "quickDraw.h" #include "ch.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ void ch::setOrdinary() /* Clear all shape flag FALSE and set it ordinary character. */ { reverse = underline = blink = doubleBright = halfBright = FALSE; } void ch::setC(uchar c1) { c = c1; } uchar ch::getC() { return c; } bool ch::isReverse() { return reverse; } bool ch::isUnderline() { return underline; } bool ch::isBlink() { return blink; } bool ch::isDoubleBright() { return doubleBright; } bool ch::isHalfBright() { return halfBright; } bool ch::isOrdinary() { return !(this->isReverse() || this->isUnderline() || this->isBlink() || this->isDoubleBright() || this->isHalfBright()); } void ch::setReverse(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); reverse = v; } void ch::setUnderline(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); underline = v; } void ch::setBlink(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); blink = v; } void ch::setDoubleBright(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); doubleBright = v; } void ch::setHalfBright(bool v) { assert((v == TRUE || v == FALSE), "illegal argument"); halfBright = v; } ch::ch(uchar c1) { c = c1; reverse = underline = blink = doubleBright = halfBright = FALSE; } bool ch::isAscii() /* Return TRUE if character is ordinary ascii character (not kanji or hiragana). */ { return isascii(c); } void ch::fprint(ostream& s) /* debugging tool */ { s << ((c != 0) ? form("%c", c) : form("^@")); char *shape; if (this->isOrdinary()) shape = "ordinary"; else if (this->isReverse()) shape = "reverse"; else if (this->isUnderline()) shape = "underline"; else if (this->isBlink()) shape = "blink"; else if (this->isDoubleBright()) shape = "doubleBright"; else if (this->isHalfBright()) shape = "halfBright"; else fatal("can't happen"); if (this->isAscii()) s << form("(%s)", shape); } ostream& operator<<(ostream& s, ch c) /* debugging tool */ { c.fprint(s); return s; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'terminal.cc' then echo shar: "will not over-write existing file 'terminal.cc'" else cat << \SHAR_EOF > 'terminal.cc' #include #include #include "global.h" #include "quickDraw.h" static int ScrWidth, ScrHeight; char PC; /* for tputs() */ char *BC; /* for tgoto */ char *UP; short ospeed; /* for tputs() */ static const int speed[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; /**/ /* Private -top- */ /**/ static fv initScreenSize(int *widthp, int *heightp) /* OK ERROR */ { *widthp = tgetnum("co"); *heightp = tgetnum("li"); return (*widthp >0 && *heightp >0) ? OK : ERROR; } static void initBaudRate(short *ospeedp) { sgttyb sg; ioctl(1, TIOCGETP, (char *)&sg); if (sg.sg_ospeed >= sizeof(speed)/sizeof(speed[0])) /* over the vector range */ fatal("termcap can't get valid baud-rate"); *ospeedp = short(speed[sg.sg_ospeed]); } /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ getScrHeight() { return ScrHeight; } getScrWidth() { return ScrWidth; } void initTermData() { static bool firstTime = TRUE; if (firstTime) firstTime = FALSE; else fatal("don't call initTermData() twice"); char *termType = getenv("TERM"); if (termType == NIL) fatal("specify a terminal type with 'setenv TERM '"); /* get terminal type */ static char termBuf[2048]; int success = tgetent(termBuf, termType); if (success < 0) fatal("could not access the termcap data base"); else if (success == 0) fatal("terminal type '%s' is not defined", termType); /* extract information that termcap functions use */ static char *buf; buf = new char[strlen(termBuf)]; char *tmp = tgetstr("pc", &buf); PC = tmp ? *tmp : 0; BC = tgetstr("le", &buf); UP = tgetstr("up", &buf); initBaudRate(&ospeed); /* extract various terminal information */ if (initScreenSize(&ScrWidth, &ScrHeight) != OK) fatal("terminal type '%s' is not powerful", termType); } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ extern fv initScreenSize(int*, int*); SHAR_EOF fi if test -f 'grafPort.cc' then echo shar: "will not over-write existing file 'grafPort.cc'" else cat << \SHAR_EOF > 'grafPort.cc' #include #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" #include "ch.h" #include "charMap.h" #include "grafPort.h" /* Can't define 'static global' as g++ bug. */ pattern White; pattern Black; pattern Gray; pattern LtGray; pattern DkGray; cursor Arrow; ch *Screen; /* screen bit image */ charMap ScreenBits; long RandSeed; /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ point grafPort::globalToLocal(const point pt) /* grafPort::globalToLocal takes a point expressed in global coordinates (with the top left corner of the charMap as coordinate (0,0)) and converts it into the local coordinates of 'my' grafPort. The global point can be obtained with the grafPort::localToGlobal call. */ { point res = pt; res.add(portBits.getBounds().getTopLeft()); return res; } point grafPort::localToGlobal(const point pt) /* Convert the given point from 'my' grafPort's local coordinate system into a global coordinate system with the origin (0,0) at the top left corner of the port's bit image (such as the screen). This global point can then be compared to other global points, or be changed into the local coordinates of another grafPort. Since a rectangle is defined by two points, you can convert a rectangle into global coordinates by performing two LocalToGlobal calls. You can also convert a rectangle, region, or polygon into global coordinates by calling rect::offset, region::offset, or poly::offset (the last is not implemented yet). */ { point res = pt; res.sub(portBits.getBounds().getTopLeft()); return res; } void grafPort::init() /* Reinitialize the fields of the grafPort. Mac's initPort() does the same thing, and also it make the argument the current port. But because N-window's style is OOPS, the image 'current port' is not supported. */ { grafPort tmp; *this = tmp; } void grafPort::setPortBits(charMap cm) /* Set portBits of 'me' (note that this function deffers from Mac as Mac's function changes the device of 'thePort')to any reviously defined charMap. This allows you to perform all normal drawing and calculations on a buffer other than the screen -- for example, a 640-by-7 output buffer for a C. Itoh printer, or a small off-screen image for later "stamping" onto the screen. Remember to prepare all fields of the charMap before you call grafPort::setPortBits(). */ { portBits = cm; } void grafPort::setDevice(int dv) /* Set device of 'me' (note that this function deffers from Mac as Mac's function changes the device of 'thePort'), which identifies the logical output device for 'me'. The Font Manager uses this information. The initial device number is 0, which represents the screen. */ { device = dv; } void grafPort::portSize(uint w, uint h) /* Change the size of portRect. THIS DOES NOT AFFECT THE SCREEN; it merely changes the size of the "active area" of 'me'. The top left corner of the portRect remains at its same location; the width and height of the portRect are set to the given width and height. In other words, this function moves the bottom right corner of the portRect to a position relative to the top left corner. grafPort::portSize() does not change the clipRgn or the visRgn, nor does it affect the local coordinate system of the grafPort: it changes only the portRect's width and height. Remember that all drawing occurs only in the intersection of the portBits.bounds and the portRect, clipped to the visRgn and the clipRgn. */ { portRect.set(portRect.getLeft(), portRect.getTop(), portRect.getLeft()+w, portRect.getTop()+h); } grafPort::~grafPort() { /* empty body */ } grafPort::grafPort(const grafPort& g) { if (this == &g) fatal("syntax error"); *this = g; } void grafPort::operator=(const grafPort& g) { if (this == &g) /* beware of g=g */ return; device = g.device; portBits = g.portBits; portRect = g.portRect; visRgn = g.visRgn; clipRgn = g.clipRgn; bkPat = g.bkPat; fillPat = g.fillPat; pnLoc = g.pnLoc; pnSize = g.pnSize; pnMode = g.pnMode; pnPat = g.pnPat; pnVis = g.pnVis; txFont = g.txFont; txFace = g.txFace; txMode = g.txMode; txSize = g.txSize; spExtra = g.spExtra; fgColor = g.fgColor; bkColor = g.bkColor; colrbit = g.colrbit; patStretch = g.patStretch; picSave = g.picSave; rgnSave = g.rgnSave; polySave = g.polySave; grafProcs = g.grafProcs; } grafPort::grafPort() { device = 0; /* screen */ portBits = ScreenBits; portRect = ScreenBits.getBounds(); visRgn.rects(ScreenBits.getBounds()); clipRgn.setRect(-300, -300, 300, 300); /* smaller region than Mac library */ // clipRgn.setRect(-30, -30, 30, 30); /* smaller region than Mac library */ bkPat = White; fillPat = Black; pnLoc.set(0, 0); pnSize.set(1, 1); pnMode = PatCopy; pnPat = Black; pnVis = 0; txFont = 0; txFace = NORMAL; txMode = SrcOr; txSize = 0; spExtra = 0; fgColor = BlackColor; bkColor = WhiteColor; colrbit = 0; patStretch = 0; picSave = NIL; rgnSave = NIL; polySave = NIL; grafProcs = NIL; } void initGraf() /* Call initGraf() once and only once at the beginning of your program to initialize QuickDraw. Also, you must call initTermData() preceding initGraf() because two functions in initTermData(), getScrWidth() and getScrHeight(), are used. It initializes the QuickDraw global variables llistd below. ------------------------------------------------------------------------ variable type initial-setting ------------------------------------------------------------------------ White pattern all-white pattern Black pattern all-black pattern Gray pattern 50% gray pattern LtGray pattern 25% gray pattern DkGray pattern 75% gray pattern Arrow cursor inversed space (black square) Screen ch* screen bit image ScreenBits charMap screen, (0, 0, getScrWidth(), getScrHeight()) RandSeed long 1 */ { static bool firstTime = TRUE; if (firstTime) firstTime = FALSE; else fatal("don't call initGraf() twice"); White.setC(SPACE); White.setOrdinary(); Black.setC(SPACE); Black.resetShape(); Black.setReverse(TRUE); Gray.setC(SPACE); Gray.resetShape(); Gray.setReverse(TRUE); /* no suitable char! */ LtGray.setC(SPACE); LtGray.resetShape(); LtGray.setReverse(TRUE); /* no suitable char! */ DkGray.setC(SPACE); DkGray.resetShape(); DkGray.setReverse(TRUE); /* no suitable char! */ Arrow.setC(CARET); Arrow.setOrdinary(); /* no suitable char! */ assert((getScrWidth() > 0 && getScrHeight() > 0), "invoke initTermData()"); Screen = new ch[getScrWidth() * getScrHeight()]; ScreenBits = charMap(Screen, getScrWidth(), rect(0,0,getScrWidth(), getScrHeight())); RandSeed = 1; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ void grafPort::movePortTo(int leftGlobal, int topGlobal) /* Change the position of my grafPort's portRect. THIS DOES NOT AFFECT THE SCREEN; it merely changes the location at which subsequent drawing inside the port will appear. The leftGlobal and topGlobal parameters set the distance between the top left corner of portBits.bounds and the top left corner of the new portRect. For example, g.movePortTo(256,171); will move the top left corner of the portRect to the center of the screen (if portBits is the Macintosh screen) regardless of the local coordinate system. Like PortSize, movePortTo does not change the clipRgn or the visRgn, nor does it affect the local coordinate system of the grafPort. */ { point localPt = this->globalToLocal(point(leftGlobal, topGlobal)); portRect.moveTo(localPt.getH(), localPt.getV()); } mainn() /* grafPort::movePortTo() Use gdb to examine the portRect's coordinates */ { malloc_debug(2); initTermData(); initGraf(); grafPort g1; while (1) { point pt; cin >> pt; g1.movePortTo(pt.getH(), pt.getV()); cout << g1.getPortBits().getBounds() NLN; cout << g1.getPortRect() NLN NLN; } } main() /* grafPort::getPortRect() */ { malloc_debug(2); initTermData(); initGraf(); grafPort g1; g1.getPortRect(); cout << "end" NLN; } SHAR_EOF fi if test -f 'charMap.cc' then echo shar: "will not over-write existing file 'charMap.cc'" else cat << \SHAR_EOF > 'charMap.cc' #include #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" #include "ch.h" #include "charMap.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ charMap::~charMap() { /* empty body */ } void charMap::operator=(const charMap& cm) { if (this == &cm) /* beware of cm = cm */ return; baseAddr = cm.baseAddr; rowBytes = cm.rowBytes; bounds = cm.bounds; updateRgn = cm.updateRgn; } charMap::charMap(const charMap& cm) { if (this == &cm) fatal("syntax error"); baseAddr = cm.baseAddr; rowBytes = cm.rowBytes; bounds = cm.bounds; updateRgn = cm.updateRgn; } charMap::charMap(ch *addr, int row, rect bnd) /* It is user's responsibility to prepare suffifient character-image (bit-image) area. 'ch' vector size of at least 'row*bnd.getHeight()' is needed. 'updateRgn' is initialized to the same size of 'bounds'. */ { assert((addr != NIL && row >= 0), "illegal argument"); assert(row >= bnd.getWidth(), "too large bounds"); baseAddr = addr; rowBytes = row; bounds = bnd; updateRgn.rects(bounds); } charMap::charMap() /* This constructor assigns dummy value. Don't use vanilla. */ { baseAddr = NIL; rowBytes = 0; } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'bitMatrix.cc' then echo shar: "will not over-write existing file 'bitMatrix.cc'" else cat << \SHAR_EOF > 'bitMatrix.cc' #include #include "global.h" #include "quickDraw.h" #include "bitMatrix.h" #include "misc.h" /**/ /* Global -top- */ /**/ bool bitMatrix::colBitIsClear(uint col) /* Return TRUE if all the bits of specified column (scanning vertically) are CLEAR. The empty matrix always returns TRUE. */ { assert((col == 0 || col < width), "lllegal argument"); for (uint i = 0; i < height; i++) if (get(col, i) == SET) return FALSE; return TRUE; } bool bitMatrix::lineBitIsClear(uint line) /* Return TRUE if all the bits of specified line (scanning horizontally) are CLEAR. The empty matrix always returns TRUE. */ { assert((line == 0 || line < height), "lllegal argument"); for (uint i = 0; i < width; i++) if (get(i, line) == SET) return FALSE; return TRUE; } bool bitMatrix::equal(bitMatrix bm) /* Return TRUE if two bitMatrix 'me' and 'bm' are equal or FALSE if not. The two bitMatrixs must have identical sizes and bit status to be considered to be equal. */ { if (width != bm.width || height != bm.height) return FALSE; for (uint w = 0; w < width; w++) for (uint h = 0; h < height; h++) if (mtrx[w][h] != bm.mtrx[w][h]) return FALSE; return TRUE; } istream& operator>>(istream& s, bitMatrix& bm) /* "3 5" will bm.resize(3,5). */ /* For debugging. */ { cout << "bitMatrix size: h v: "; int h = 0, v = 0; s >> h >> v; if (s) bm.resize(h, v); cout << "bit contents: "; for (uint col = 0; col < v; col++) for (uint line = 0; line < h; line++) { int bit; cin >> bit; bit ? bm.set(line, col) : bm.clear(line, col); } return s; } ostream& operator<<(ostream& s, const bitMatrix& m) /* For debugging. */ { return m.fprint(s); } void bitMatrix::print() /* For debugging. */ { if (width == 0 && height == 0) cout << "empty bitMatrix\n"; else for (uint j = 0; j < height; j++) { for (uint i = 0; i < width; i++) cout << mtrx[i][j]; cout << "\n"; } } ostream& bitMatrix::fprint(ostream& s) /* For debugging. */ { if (width == 0 && height == 0) s << "empty bitMatrix\n"; else for (uint j = 0; j < height; j++) { for (uint i = 0; i < width; i++) s << mtrx[i][j]; s << "\n"; } return s; } bitMatrix::bitMatrix(uint w, uint h, bit val) /* Zero sized matrix is also legal. */ { assert((val == CLEAR || val == SET), "Illegal val"); width = w; height = h; mtrx = new bit*[width]; for (uint i = 0; i < width; i++) mtrx[i] = new bit[height]; (val == SET) ? this->set() : this->clear(); } void bitMatrix::resize(uint w, uint h, bit val) { assert((val == CLEAR || val == SET), "Illegal val"); if (width != w || height != h) { /* de-allocate free space */ for (uint i = 0; i < width; i++) delete mtrx[i]; delete mtrx; /* re-initialize; reallocate */ width = w; height = h; mtrx = new bit*[width]; for (i = 0; i < width; i++) mtrx[i] = new bit[height]; } (val == SET) ? this->set() : this->clear(); } bit bitMatrix::get(uint col, uint line) /* Return the bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); return mtrx[col][line]; } void bitMatrix::set(uint col, uint line) /* Set bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); mtrx[col][line] = SET; } void bitMatrix::clear(uint col, uint line) /* Clear bit of 'col/line'. */ { if (col >= width || line >= height) fatal("illegal coordinate"); mtrx[col][line] = CLEAR; } void bitMatrix::set() /* Set all bits. */ { for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = SET; } void bitMatrix::clear() /* Clear all bits. */ { for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = CLEAR; } void bitMatrix::operator=(bitMatrix& m) { if (this == &m) /* beware of m=m */ return; if (width != m.width || height != m.height) fatal("can't assign different size matrix"); for (uint i = 0; i < width; i++) for (uint j = 0; j < height; j++) mtrx[i][j] = m.mtrx[i][j]; } bitMatrix::bitMatrix(const bitMatrix& m) { if (this == &m) fatal("syntax error"); width = m.width; height =m.height; mtrx = new bit*[width]; for (uint i = 0; i < width; i++) mtrx[i] = new bit[height]; *this = m; /* copy bits */ } bitMatrix::~bitMatrix() { for (uint i = 0; i < width; i++) delete mtrx[i]; delete mtrx; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'misc.cc' then echo shar: "will not over-write existing file 'misc.cc'" else cat << \SHAR_EOF > 'misc.cc' #include #include #include #include "global.h" #include "quickDraw.h" const MaxCoordinate = 32767; const MinCoordinate = -32768; /**/ /* Global -top- */ /**/ void fatal(char *fmt...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "fatal error: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); abort(); } bool validCoordinate(int i) /* Return TRUE if 'i' is valid. coordinate valid range is between 'MinCoordinate' and 'MaxCoordinate' inclusive. */ { return MinCoordinate <= i && i <= MaxCoordinate; } bool emptyRect(int left, int top, int right, int bottom) /* Return TRUE if the specified rectangle is empty. */ { assert((validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom)), "illegal argument"); return bottom <= top || right <= left; } bit and(bit a, bit b) /* Return the and of 'a' and 'b'. */ { assert(((a == SET || a == CLEAR) && (b == SET || b == CLEAR)), "illegal argument"); return (a == SET && b == SET) ? SET : CLEAR; } bit or(bit a, bit b) /* Return the or of 'a' and 'b'. */ { assert(((a == SET || a == CLEAR) && (b == SET || b == CLEAR)), "illegal argument"); return (a == SET || b == SET) ? SET : CLEAR; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'region.cc' then echo shar: "will not over-write existing file 'region.cc'" else cat << \SHAR_EOF > 'region.cc' #include #include "global.h" #include "quickDraw.h" #include "misc.h" #include "point.h" #include "rect.h" #include "bitMatrix.h" #include "region.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ region::~region() { /* empty body */ } void region::sect(region a, region b) /* Calculate the intersection of two regions and places the intersection in 'me'. The dstRgn ('me') can be one of the source regions, if desired. If the regions do not intersect, or one of the regions is empty, the destination is set to the empty region (0,0,0,0). */ { bBox.sect(a.bBox, b.bBox); uint w = bBox.getWidth(), h = bBox.getHeight(); bMap.resize(w, h); uint dha = bBox.getLeft() - a.bBox.getLeft(); /* obscure */ uint dva = bBox.getTop() - a.bBox.getTop(); /* obscure */ uint dhb = bBox.getLeft() - b.bBox.getLeft(); /* obscure */ uint dvb = bBox.getTop() - b.bBox.getTop(); /* obscure */ for (int col = 0; col < w; col++) for (int line = 0; line < h; line++) (and(a.bMap.get(col+dha, line+dva), b.bMap.get(col+dhb, line+dvb)) == SET) ? bMap.set(col, line) : bMap.clear(col, line); this->compress(); } void region::unions(region a, region b) /* Calculate the union of two rgions and places the union in 'me'. The dstRgn 'me' can be one of the source regions, if desired. If both regions are empty, the destination 'me' is set to the empty region (0,0,0,0). */ { bBox.unions(a.bBox, b.bBox); bMap.resize(bBox.getWidth(), bBox.getHeight(), CLEAR); /* transfer bits in 'a' as or-mode */ uint dh = a.bBox.getLeft() - bBox.getLeft(); /* obscure */ uint dv = a.bBox.getTop() - bBox.getTop(); /* obscure */ uint w = a.bBox.getWidth(); uint h = a.bBox.getHeight(); for (int col = 0; col < w; col++) for (int line = 0; line < h; line++) (or(bMap.get(col+dh, line+dv), a.bMap.get(col, line)) == SET) ? bMap.set(col+dh, line+dv) : bMap.clear(col+dh, line+dv); /* transfer bits in 'b' as or-mode */ dh = b.bBox.getLeft() - bBox.getLeft(); /* obscure */ dv = b.bBox.getTop() - bBox.getTop(); /* obscure */ w = b.bBox.getWidth(); h = b.bBox.getHeight(); for (col = 0; col < w; col++) for (line = 0; line < h; line++) (or(bMap.get(col+dh, line+dv), b.bMap.get(col, line)) == SET) ? bMap.set(col+dh, line+dv) : bMap.clear(col+dh, line+dv); /* settle */ this->compress(); } void region::diff(region a, region b) /* Subtract srcRgn b from a and place the dirrerence in 'me'. The 'me' can be one of the source regions, if desired. If the first source region is empty, the destination is set to the empty region (0,0,0,0). */ { /* it suffices to re-calculate bits of 'a' restricted to the area of sRect. calculation table follows... -------------+--------- a b | result -------------+--------- SET SET | CLEAR SET CLEAR | SET CLEAR SET | CLEAR CLEAR CLEAR | CLEAR -------------+--------- */ if (a == b) { /* special case */ this->setEmpty(); return; } *this = a; rect sRect; sRect.sect(a.bBox, b.bBox); uint w = sRect.getWidth(); uint h = sRect.getHeight(); uint dha = sRect.getLeft() - a.bBox.getLeft(); uint dva = sRect.getTop() - a.bBox.getTop(); uint dhb = sRect.getLeft() - b.bBox.getLeft(); uint dvb = sRect.getTop() - b.bBox.getTop(); for (uint col = 0; col < w; col++) for (uint line = 0; line < h; line++) if (a.bMap.get(col+dha, line+dva) == SET && b.bMap.get(col+dhb, line+dvb) == SET) bMap.clear(col+dha, line+dva); this->compress(); } void region::xor(region a, region b) /* Calculate the difference between the union and the intersection of two regions and places the result in 'me'. The dstRgn 'me' can be one of the source regions, if desired. If the regions are coincident, the destination is set to the empty region (0,0,0,0). */ { region unions; unions.unions(a, b); region sect; sect.sect(a, b); this->diff(unions, sect); } void region::inset(int dh, int dv) /* Shrink or expand the region. All points on the resion boundary are moved inwards a distance of dv vertically and dh horizontally; if dh or dv is negative, the points are moved outwards in that direction. region::inset() leaves the region "centered" at the same position, but moves the outline in (for positive values of dh and dv) or out (for negative values of dh and dv). region::inset() of a rectangular region works just like rect::inset(). */ { region tmp = *this; /* resize */ this->bBox.inset(dh, dv); this->bMap.resize(bBox.getWidth(), bBox.getHeight(), SET); /* clear the bit within intersection rectangle 'r' where original's bit was clear */ rect r; r.sect(tmp.bBox, bBox); uint w = r.getWidth(); uint h = r.getHeight(); for (uint i = 0; i < w; i++) for (uint j = 0; j < h; j++) if (tmp.bMap.get(i+max(dh,0), j+max(dv,0)) == CLEAR) /* obscure */ bMap.clear(i-min(dh,0), j-min(dv,0)); /* obscure */ this->compress(); } void region::compress() /* Compress region data. Suppose the region is defined like this... (0, 0, 6, 6) 000000 001100 001100 001100 001100 000000 As stripping outerward zeroz doesn't change the region object, region::compress() will redefine the region data like this... (2, 1, 3, 4) 11 11 11 11 */ { if (this->empty()) { if (!bBox.empty()) this->setEmpty(); return; } else if (bMap.lineBitIsClear(0) && bMap.lineBitIsClear(bBox.getHeight() - 1)) { this->inset(0, 1); this->compress(); } else if (bMap.colBitIsClear(0) && bMap.colBitIsClear(bBox.getWidth() - 1)) { this->inset(1, 0); this->compress(); } } istream& operator>>(istream& s, region& rgn) /* For debugging. */ { s >> rgn.bBox; rgn.bMap.resize(rgn.bBox.getWidth(), rgn.bBox.getHeight()); cout << form("bit contents (hor = %u ver = %u): \n", rgn.bBox.getWidth(), rgn.bBox.getHeight()); for (uint col = 0; col < rgn.bBox.getHeight(); col++) for (uint line = 0; line < rgn.bBox.getWidth(); line++) { int bit; cin >> bit; bit ? rgn.bMap.set(line, col) : rgn.bMap.clear(line, col); } return s; } bool region::rectIn(rect r) /* Check whether the given rectangle intersects 'me', and return TRUE if the intersection encloses at least one bit or FALSE if not. */ { region rgn; rgn.rects(r); rgn.sect(rgn, *this); return !rgn.empty(); } bool region::empty() /* Return TRUE if the region is an empty region or FALSE if not. Some of the circumstances in which an empty region can be created are: a region::new() call; a region::copy() of an empty region; a region::setRect() or region::rect() with an empty rectangle as an argument; region::open(); region::offset() of an empty region; region::inset() with an empty region or too large an inset; region::sect() of nonintersecting regions; region::unions() of two empty regions; and region::diff() or region::xor() of two identical or nonintersecting regions. */ { uint w = bBox.getWidth(); uint h = bBox.getHeight(); for (uint i = 0; i < w; i++) for (uint j = 0; j < h; j++) if (bMap.get(i, j) == SET) return FALSE; return TRUE; } bool region::ptIn(point pt) /* Check whether the pixel below and to the right of the given coordinate point is within 'me', and return TRUE if so or FALSE if not. */ { return bBox.ptIn(pt) && bMap.get(pt.getH(), pt.getV()) == SET; } bool operator==(region a, region b) { return a.equal(b); } bool region::equal(region rgn) /* Compare the two regions, 'me' and 'rgn', and return TRUE if they are equal or FALSE if not. The two regions must have identical sizes, shapes, and locations to be considered equal. Any two empty regions are always equal. */ { return bBox.equal(rgn.bBox) && bMap.equal(rgn.bMap); } void region::print() /* For debugging. */ { cout << this->bBox NLN << this->bMap; } ostream& region::fprint(ostream& s) /* For debugging. */ { return s << this->bBox NLN << this->bMap; } ostream& operator<<(ostream& s, const region& rgn) /* For debugging. */ { return rgn.fprint(s); } void region::offset(int dh, int dv) /* Move the region on the coordinate plane, a distance of dh horizontally and dv vertically. This does not affect the screen unless you subsequently call a routine to draw the region. If dh and dv are positive, the movement is to the right and down; if either is negative, the corresponding movement is in the opposite direction. The region retain its size and shape. */ { bBox.offset(dh, dv); } void region::rects(rect r) /* Destroys the previous structure, then set the new structure to the rectangle specified by 'r'. This is operationally synonymous with region::setRect(), except the input rectangle is defined by a rectangle rather than by four boundary coordinates. */ { this->setRect(r.getLeft(), r.getTop(), r.getRight(), r.getBottom()); } void region::setEmpty() /* Destroy the previous structure, then set 'me' to the empty region (0,0,0,0). */ { this->setRect(0,0,0,0); } void region::copy(region rgn) /* Copy the mathematical structure of 'rgn'. */ { *this = rgn; } void region::operator=(const region& rgn) { if (this == &rgn) /* beware of rgn=rgn */ return; if (bBox.getWidth() != rgn.bBox.getWidth() || bBox.getHeight() != rgn.bBox.getHeight()) bMap.resize(rgn.bBox.getWidth(), rgn.bBox.getHeight()); bBox = rgn.bBox; bMap = rgn.bMap; } region::region(const region& rgn) : bBox(0, 0, 0, 0), bMap(0, 0, SET) { if (this == &rgn) fatal("syntax error"); bBox = rgn.bBox; bMap.resize(rgn.bMap.getWidth(), rgn.bMap.getHeight()); bMap = rgn.bMap; } void region::setRect(int left, int top, int right, int bottom) /* Destroy the previous structure of 'me', then sets the the new structure to the rectangle specified by left, top, right, and bottom. If the specified rectangle is empty (i.e., left>=right or top>=bottom), the rgion is set to the empty region (0,0,0,0). */ { assert((validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom)), "illegal argument"); if (emptyRect(left, top, right, bottom)) left = top = right = bottom = 0; bBox.set(left, top, right, bottom); bMap.resize(right-left, bottom-top, SET); } region::region() : bBox(0, 0, 0, 0), bMap(0, 0, SET) /* Create the empty region (0, 0, 0, 0). This function corresponds to NewRgn() in Mac. */ { /* empty body */ } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'point.cc' then echo shar: "will not over-write existing file 'point.cc'" else cat << \SHAR_EOF > 'point.cc' #include #include "global.h" #include "quickDraw.h" #include "point.h" #include "misc.h" /**/ /* Global -top- */ /**/ point::point() { h = v = 0; } point::point(int hc, int vc) { assert((validCoordinate(hc) && validCoordinate(vc)), "Illegal argument"); h = hc; v = vc; } istream& operator>>(istream& s, point& p) /* "3 5" will p.set(3,5). */ { cout << "point: h v: "; int h = 0, v = 0; s >> h >> v; if (s) p.set(h, v); return s; } ostream& operator<<(ostream& s, point p) { return s << form("(%d,%d)", p.h, p.v); } bool point::ok() { return validCoordinate(h) && validCoordinate(v); } void point::add(point pt) /* Add the coordinates of 'pt'. */ { assert(pt.ok(), "Illegal argument"); h += pt.h; v += pt.v; assert(this->ok(), "Illegal result"); } void point::sub(point pt) /* Subtract the coordinates of 'pt'. */ { assert(pt.ok(), "Illegal argument"); h -= pt.h; v -= pt.v; assert(this->ok(), "Illegal result"); } void point::set(int hc, int vc) /* Assign two integer coordinates. */ { assert((validCoordinate(hc) && validCoordinate(vc)), "Illegal argument"); h = hc; v = vc; } bool point::equal(point pt) /* Compare the 'pt' with 'this' and return TRUE if they are equal or FALSE if not. */ { assert(pt.ok(), "Illegal argument"); return h == pt.h && v == pt.v; } /**/ /* Global -bottom- */ /**/ /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'rect.cc' then echo shar: "will not over-write existing file 'rect.cc'" else cat << \SHAR_EOF > 'rect.cc' #include #include "global.h" #include "quickDraw.h" #include "point.h" #include "rect.h" #include "misc.h" /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ void rect::moveTo(int left, int top) /* Move the top left cornet to the point (left,top). This function merely moves the rect posion, but not its shape. */ { this->offset(left - this->getLeft(), top - this->getTop()); } bool rect::sect(rect a, rect b) /* Calculate the rectangle that is the intersection of the two input input rectangles, and returns TRUE if they indeed intersect or FALSE if they do not. Rectangles that "touch" at a line or a point are not considered intersecting, because their intersection rectangle (really, in this case, an intersection line or point) does not enclose any bits on the bitMap. If the rectangles do not intersect, the destination rectangle is set to (0,0,0,0). This function works correctly even if one of the source rectangles (argument) is also 'me'. */ { if (a.empty() || b.empty() || a.bottom <= b.top || b.bottom <= a.top || a.right <= b.left || b.right <= a.left) { /* not intersect */ this->set(0, 0, 0, 0); return FALSE; } left = max(a.left, b.left); top = max(a.top, b.top); right = min(a.right, b.right); bottom = min(a.bottom, b.bottom); return TRUE; } bool rect::equal(rect r) /* Compare 'r' with 'me' and return TRUE if they are equal or FALSE if not. The two rectangles must have identical boundary coordinates to be considered equal. */ { return left == r.left && top == r.top && right == r.right && bottom == r.bottom; } void rect::pt2(point a, point b) /* Set 'me' the smallest rectangle which encloses the two input points. */ { int ah = a.getH(), av = a.getV(), bh = b.getH(), bv = b.getV(); left = min(ah, bh); right = max(ah, bh); top = min(av, bv); bottom = max(av, bv); } bool rect::ptIn(point pt) /* Determine whether the pixel below and to the right of the given coordinate point is enclosed in the specified rectangle 'me', and return TRUE if so or FALSE if not. */ { if (this->empty()) return FALSE; int h = pt.getH(); int v = pt.getV(); return left <= h && h < right && top <= v && v < bottom; } void rect::unions(rect a, rect b) /* Calculate the smallest rectangle which encloses both input rectangles. It works correctly even if one of the source rectangles is also 'me'. */ { left = min(a.left, b.left); top = min(a.top, b.top); right = max(a.right, b.right); bottom = max(a.bottom, b.bottom); } istream& operator>>(istream& s, rect& r) /* "3 5 2 9" will r.set(3,5,2,9). */ { cout << "rect: left top right bottom: "; int left = 0, top = 0, right = 0, bottom = 0; s >> left >> top >> right >> bottom; if (s) r.set(left, top, right, bottom); return s; } bool rect::empty() /* Return TRUE if 'me' is an empty rectangle. A rectangle is considered empty if the bottom coordinate is equal to or less than the top or the right coordinate is equal to or less than the left. */ { return bottom <= top || right <= left; } void rect::inset(int dh, int dv) /* Shrink or expand the rectangle (me). The left and right sides are moved in by the amount specified by 'dh'; the top and bottom are moved towards the center by the amount specified by 'dv'. If 'dh' or 'dv' is negative, the appropriate pair of sides is moved outwards instead of inwards. If the resulting width or height becomes less than 1, the rectangle is set to the empty rectangle (0,0,0,0). */ { left += dh; top += dv; right -= dh; bottom -= dv; if (top >= bottom || left >= right) top = bottom = left = right = 0; assert(this->ok(), "Illegal rectangle data"); } ostream& operator<<(ostream& s, rect r) { return s << form("(%d,%d,%d,%d)", r.left, r.top, r.right, r.bottom); } void rect::offset(int dh, int dv) /* Move the rectangle (me) by adding 'dh' to each horizontal coordinate and 'dv' to each vertical coordinate. If 'dh' and 'dv' are positive, the movement is to the right and down; if either is negative, the corresponding movement is in the opposite direction. The rectangle retains its shape and size; it's merely moved on the coordinate plane. */ { left += dh; right += dh; top += dv; bottom += dv; assert(this->ok(), "Illegal coordinate"); } void rect::set(int left, int top, int right, int bottom) /* Assign four boundary coordinates. */ { assert(rect::ok(top, left, bottom, right), "Illegal argument"); this->left = left; this->top = top; this->right = right; this->bottom = bottom; } bool rect::ok() { return validCoordinate(this->top) && validCoordinate(this->left) && validCoordinate(this->bottom) && validCoordinate(this->right); } rect::rect() /* Generate empty rectangle. See the comment of 'rect.h' about empty rectangle. */ { this->left = this->top = this->right = this->bottom = 0; } rect::rect(int left, int top, int right, int bottom) /* See the comment of 'rect.h' about empty rectangle. Assign the four boundary coordinates. */ { assert(rect::ok(left, top, right, bottom), "Illegal argument"); this->left = left; this->top = top; this->right = right; this->bottom = bottom; } bool rect::ok(int left, int top, int right, int bottom) { return validCoordinate(left) && validCoordinate(top) && validCoordinate(right) && validCoordinate(bottom); } /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'quickDraw.cc' then echo shar: "will not over-write existing file 'quickDraw.cc'" else cat << \SHAR_EOF > 'quickDraw.cc' #include #include "global.h" #include "quickDraw.h" const SrcCopy = 0; const SrcOr = 1; const SrcXor = 2; const SrcBic = 3; const NotSrcCopy = 4; const NotSrcOr = 5; const NotSrcxor = 6; const NotSrcbic = 7; const PatCopy = 8; const PatOr = 9; const PatXor = 10; const PatBic = 11; const NotPatCopy = 12; const NotPatOr = 13; const NotPatXor = 14; const NotPatBic = 15; const BlackColor = 33; const WhiteColor = 30; const RedColor = 205; const GreenColor = 341; const BlueColor = 409; const CyanColor = 273; const MagentaColor = 137; const YellowColor = 69; const PicLParen = 0; const PicRParen = -1; /**/ /* Private -top- */ /**/ /**/ /* Private -bottom- */ /**/ /**/ /* Global -top- */ /**/ mainxz() {} /**/ /* Global -bottom- */ /**/ /**/ /* Debug -top- */ /**/ /**/ /* Debug -bottom- */ /**/ SHAR_EOF fi if test -f 'ch.h' then echo shar: "will not over-write existing file 'ch.h'" else cat << \SHAR_EOF > 'ch.h' class ch { uchar c; /* shape */ bool reverse; bool underline; bool blink; bool doubleBright; bool halfBright; public: /* constructor etc */ ch(uchar c = 0); /* general */ uchar getC(); void setC(uchar); void setOrdinary(); void setReverse(bool); void setUnderline(bool); void setBlink(bool); void setDoubleBright(bool); void setHalfBright(bool); void resetShape() { this->setOrdinary(); } bool isOrdinary(); bool isReverse(); bool isUnderline(); bool isBlink(); bool isDoubleBright(); bool isHalfBright(); bool isAscii(); /* for debugging */ friend ostream& operator<<(ostream&, ch); void fprint(ostream&); }; SHAR_EOF fi if test -f 'terminal.h' then echo shar: "will not over-write existing file 'terminal.h'" else cat << \SHAR_EOF > 'terminal.h' extern void initTermData(); extern getScrWidth(); extern getScrHeight(); extern char PC; extern char *BC; extern char *UP; extern short ospeed; SHAR_EOF fi if test -f 'grafPort.h' then echo shar: "will not over-write existing file 'grafPort.h'" else cat << \SHAR_EOF > 'grafPort.h' typedef ch pattern; typedef ch cursor; extern void initGraf(); /* different from Mac; void argument */ /* Macintosh 'thePort' variable is not need in N-window. */ /* Can't define 'static global' as g++ bug. */ extern pattern White; extern pattern Black; extern pattern Gray; extern pattern LtGray; extern pattern DkGray; extern cursor Arrow; extern charMap ScreenBits; extern long RandSeed; class grafPort { int device; charMap portBits; rect portRect; region visRgn; region clipRgn; pattern bkPat; pattern fillPat; point pnLoc; point pnSize; int pnMode; pattern pnPat; int pnVis; int txFont; style txFace; int txMode; int txSize; int spExtra; long fgColor; long bkColor; int colrbit; int patStretch; void *picSave; void *rgnSave; void *polySave; void *grafProcs; public: /* constructor etc */ grafPort(); /* initial value is the same as Mac library OpenPort() */ grafPort(const grafPort&); ~grafPort(); void operator=(const grafPort&); /* Mac library */ void init(); void open(); /* not implemented */ void close(); /* not implemented */ void setPort(grafPort gp); /* not implemented */ void getPort(grafPort &gpp); /* not implemented */ void setDevice(int); void setPortBits(charMap); void portSize(uint w, uint h); point localToGlobal(const point pt); point globalToLocal(const point pt); void movePortTo(int leftGlobal, int topGlobal); /* general */ charMap getPortBits() { return portBits; }; rect getPortRect() { return portRect; }; }; SHAR_EOF fi if test -f 'charMap.h' then echo shar: "will not over-write existing file 'charMap.h'" else cat << \SHAR_EOF > 'charMap.h' class charMap { ch *baseAddr; int rowBytes; rect bounds; region updateRgn; /* peculiar to N-window;show newly described region since last updated */ public: /* constructor etc */ charMap(ch *baseAddr, int rowBytes, rect bounds); charMap(); charMap(const charMap&); ~charMap(); void operator=(const charMap&); /* general */ rect getBounds() { return bounds; }; }; SHAR_EOF fi if test -f 'bitMatrix.h' then echo shar: "will not over-write existing file 'bitMatrix.h'" else cat << \SHAR_EOF > 'bitMatrix.h' class bitMatrix { uint width; uint height; bit **mtrx; /* matrix size is 'mtrx[width][height]' */ public: /* constructer etc */ bitMatrix(uint width, uint height, bit val=CLEAR); bitMatrix(const bitMatrix&); ~bitMatrix(); void operator=(bitMatrix&); /* general */ void set(); void set(uint col, uint line); void clear(); void clear(uint col, uint line); bit get(uint col, uint line); void resize(uint width, uint height, bit val=CLEAR); uint getWidth() { return width; } uint getHeight() { return height; } bool equal(bitMatrix); bool lineBitIsClear(uint line); bool colBitIsClear(uint col); /* for debugging */ friend istream& operator>>(istream&, bitMatrix&); friend ostream& operator<<(ostream&, const bitMatrix&); ostream& fprint(ostream&); void print(); }; SHAR_EOF fi if test -f 'misc.h' then echo shar: "will not over-write existing file 'misc.h'" else cat << \SHAR_EOF > 'misc.h' extern void fatal(char*...); extern bool validCoordinate(int); extern bool emptyRect(int, int, int, int); extern bit or(bit, bit); extern bit and(bit, bit); SHAR_EOF fi if test -f 'region.h' then echo shar: "will not over-write existing file 'region.h'" else cat << \SHAR_EOF > 'region.h' /* NewRgn() and DisposeRgn() in Mac are not supported because constructor and destructor play role. */ class region { rect bBox; /* boundary */ bitMatrix bMap; /* CLEAR bit represents the hole */ public: /* constructor etc */ region(); region(const region&); ~region(); void operator=(const region&); /* Mac library */ void copy(region); void setEmpty(); void setRect(int left, int top, int right, int bottom); void rects(rect); /* modify name to overcome g++ bug */ void open(); /* not implemented */ void close(); /* not implemented */ void offset(int dh, int dv); void inset(int dh, int dv); void sect(region a, region b); void unions(region a, region b); void diff(region a, region b); void xor(region a, region b); bool ptIn(point); bool rectIn(rect); bool equal(region); bool empty(); void frame(); void paint(); void erase(); void invert(); void fill(); /* general */ void compress(); friend bool operator==(region, region); /* for debugging */ friend ostream& operator<<(ostream&, const region&); friend istream& operator>>(istream&, region&); ostream& fprint(ostream&); void print(); }; SHAR_EOF fi if test -f 'point.h' then echo shar: "will not over-write existing file 'point.h'" else cat << \SHAR_EOF > 'point.h' /* Both horizontal and vertical coordinate reside in MaxCoordinate and MinCoordinate inclusive. */ class point { int h; /* horizontal coordinate */ int v; /* vertical coordinate */ public: /* constructor etc */ point(int h, int v); point(); /* general */ getH() { return h; } getV() { return v; } bool ok(); /* Mac library */ void add(point); void sub(point); void set(int h, int v); bool equal(point); /* for debugging */ friend ostream& operator<<(ostream&, point); friend istream& operator>>(istream&, point&); }; SHAR_EOF fi if test -f 'rect.h' then echo shar: "will not over-write existing file 'rect.h'" else cat << \SHAR_EOF > 'rect.h' /* Following four coordinate value must be 'validCoordinate(int)'. If the bottom coordinate of a rectangle is equal to or less than the top, or the right coordinate is equal to or less than the left, the rectangle is an empty rectangle (i.e., one that contains no bits). */ class rect { int left; int top; int right; int bottom; public: /* constructor etc */ rect(int left, int top, int right, int bottom); rect(); /* Mac library */ void set(int left, int top, int right, int bottom); void offset(int dh, int dv); void inset(int dh, int dv); bool sect(rect a, rect b); void unions(rect a, rect b); bool ptIn(point); void pt2(point, point); void ptToAngle(point, int*); /* not implemented */ bool equal(rect); bool empty(); void frame(); void paint(); void erase(); void invert(); void fill(); /* general */ bool ok(); bool ok(int left, int top, int right, int bottom); uint getWidth() { return max(0, right-left); }; uint getHeight() { return max(0, bottom-top); }; int getLeft() { return left; }; int getTop() { return top; }; int getRight() { return right; }; int getBottom() { return bottom; }; point getTopLeft() { point pt(left, top); return pt; }; void moveTo(int left, int top); /* for debugging */ friend ostream& operator<<(ostream&, rect); friend istream& operator>>(istream&, rect&); }; SHAR_EOF fi if test -f 'quickDraw.h' then echo shar: "will not over-write existing file 'quickDraw.h'" else cat << \SHAR_EOF > 'quickDraw.h' extern const SrcCopy; extern const SrcOr; extern const SrcXor; extern const SrcBic; extern const NotSrcCopy; extern const NotSrcOr; extern const NotSrcxor; extern const NotSrcbic; extern const PatCopy; extern const PatOr; extern const PatXor; extern const PatBic; extern const NotPatCopy; extern const NotPatOr; extern const NotPatXor; extern const NotPatBic; extern const BlackColor; extern const WhiteColor; extern const RedColor; extern const GreenColor; extern const BlueColor; extern const CyanColor; extern const MagentaColor; extern const YellowColor; extern const PicLParen; extern const PicRParen; enum bit { CLEAR = 0, SET = 1 }; enum style { NORMAL, BOLD, ITALIC, UNDERLINE, OUTLINE, SHADOW, CONDENSE, EXTEND }; SHAR_EOF fi if test -f 'global.h' then echo shar: "will not over-write existing file 'global.h'" else cat << \SHAR_EOF > 'global.h' #define max(A,B) ((A)>(B) ? (A):(B)) #define min(A,B) ((A)<(B) ? (A):(B)) #define until(A) while (!(A)) #define forever() while (1) #ifndef NO_DEBUG # define _assert(ex,msg) {if (!(ex)) fatal(msg);} # define assert(ex,msg) {if (!(ex)) fatal(msg);} #else # define _assert(ex,msg) ; # define assert(ex,msg) ; #endif NDEBUG #define NLN << "\n" #define NIL 0 #define SPACE ' ' #define CARET '^' typedef unsigned int uint; typedef unsigned char uchar; enum fv { OK, ERROR }; extern const MaxCoordinate; extern const MinCoordinate; /* make lint silent */ void malloc_debug(int); SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' C++ = g++ C++FLAGS = -g CPPFLAGS = LDFLAGS = LINT = /usr/bin/lint LINTFLAGS = -h LIBS = /usr/lib/debug/malloc.o -ltermlib -lm SRC =\ ch.cc\ terminal.cc\ grafPort.cc\ charMap.cc\ bitMatrix.cc\ misc.cc\ region.cc\ point.cc\ rect.cc\ quickDraw.cc OBJ := $(subst .cc,.o, $(SRC)) HDR = $(subst .cc,.h, $(SRC)) global.h PRG = p $(PRG): $(OBJ) $(C++) $(C++FLAGS) $(OBJ) -o $(PRG) $(LIBS) clean: \rm -rf $(OBJ) core mon.out gmon.out tags: $(SRC) Makefile etags -et $(HDR) $(SRC) main.cc dbg.cc trash.cc touch tags dlist: $(HDR) $(C++) -MM $(SRC) > dlist shar: shar $(SRC) $(HDR) Makefile .gdbinit dlist > shar.file # # implicit rules # .cc .o: $(C++) $(C++FLAGS) -o $@ $< $(LIBS) %:%.sh cp $< $@ chmod +x $@ # # misc # .PRECIOUS: tags # # dependency-list. # include dlist SHAR_EOF fi if test -f '.gdbinit' then echo shar: "will not over-write existing file '.gdbinit'" else cat << \SHAR_EOF > '.gdbinit' # Initialization for N-window unset env TERMCAP set env TERM vt100 printf "Caution: environment TERM is set to vt100. Modify '.gdbinit' as you wish.\n" # Switch to the file 'p' define dbgp exec p sym p core end document dbgp Switchs to the file 'p'. Core infomation is discarded, too. end # Print the next node define nn p $->next end document nn Print the next node of linear list. end # Print the previous node define pn p $->prev end document pn Print the previous node of linear list. end # Print the next track define nt p $->littleBr end document nt Print the next track. end # Print the previous track define pt p $->bigBr end document pt Print the previous track. end # Print the current node define cn p $ end document cn Print the current node of linear list. end # Print the content of the next node define nc p *$->next end document nc Print the content of the next node end # Print the content of the previous node define pc p *$->prev end document pc Print the content of the previous node end # Print the content of the current node define cc p *$ end document cc Print the content of the current node end # Lpr Cell and SymTable data. define prall set $tmp = lprCellAll() set $tmp = lprNl(5) set $tmp = lprSymTable() set $tmp = lprPage() end document prall Lpr Cell and SymTable data. end # Lpr Cell. define prcell set $tmp = lprCellAll() set $tmp = lprNl(5) end document prcell Lpr Cell data. end # Lpr Symtable. define prsym set $tmp = lprSymTable() set $tmp = lprPage() end document prsym Lpr all Symtable data. end SHAR_EOF fi if test -f 'dlist' then echo shar: "will not over-write existing file 'dlist'" else cat << \SHAR_EOF > 'dlist' ch.o : ch.cc global.h quickDraw.h ch.h terminal.o : terminal.cc global.h quickDraw.h grafPort.o : grafPort.cc global.h quickDraw.h point.h \ rect.h bitMatrix.h region.h ch.h charMap.h grafPort.h charMap.o : charMap.cc global.h quickDraw.h point.h \ rect.h bitMatrix.h region.h ch.h charMap.h bitMatrix.o : bitMatrix.cc global.h quickDraw.h bitMatrix.h \ misc.h misc.o : misc.cc global.h quickDraw.h region.o : region.cc global.h quickDraw.h misc.h point.h \ rect.h bitMatrix.h region.h point.o : point.cc global.h quickDraw.h point.h misc.h rect.o : rect.cc global.h quickDraw.h point.h rect.h \ misc.h quickDraw.o : quickDraw.cc global.h quickDraw.h SHAR_EOF fi exit 0 # End of shell archive