#include "xlisp.h"
#include "xlstat.h"
#include "xlgraph.h"
/* forward declarations */
LOCAL VOID BufferMarkPoint _((unsigned x, unsigned y, unsigned sym, unsigned color));
LOCAL VOID make_picture _((StGWWinInfo *gwinfo, char *fname));
LOCAL VOID SetDrawingPort _((WindowPtr w));
LOCAL VOID MakeSymbols _((void));
/**************************************************************************/
/** **/
/** Global Variables **/
/** **/
/**************************************************************************/
static CGrafPort CWP;
static CGrafPtr CWorkPort;
static GrafPort WP;
static GrafPtr WorkPort;
static char **WorkRowStarts;
static int WorkPortWidth, WorkPortHeight;
static int buffering = FALSE;
static int copying_to_clip = FALSE;
static int bufflevel = 0;
static WindowPtr get_port() { return(thePort); }
static VOID set_port(WindowPtr port)
{
if (port != thePort) SetPort(port);
}
VOID reset_clip_rect(StGWWinInfo *gwinfo)
{
WindowPtr w;
GrafPtr savePort;
Rect r;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
GetPort(&savePort);
SetPort(w);
r = w->portRect;
r.right -= 15;
if (gwinfo->hasHscroll) r.bottom -= 15;
if (gwinfo->clipped) {
gwinfo->clip_rect.right = min(gwinfo->clip_rect.right, r.right);
gwinfo->clip_rect.bottom = min(gwinfo->clip_rect.bottom, r.bottom);
r = gwinfo->clip_rect;
}
ClipRect(&r);
if (buffering) {
SetDrawingPort(w);
ClipRect(&r);
}
SetPort(savePort);
}
/**************************************************************************/
/** **/
/** Initialization Functions **/
/** **/
/**************************************************************************/
VOID initialize_static_globals(void)
{
int portSize;
long i; /* long to force row start calculation to be done long */
WorkPort = ℘
OpenPort(WorkPort);
WorkPort->portBits = screenBits;
portSize = WorkPort->portBits.bounds.bottom
- WorkPort->portBits.bounds.top;
WorkPort->portBits.baseAddr =
StCalloc(portSize, WorkPort->portBits.rowBytes);
if (WorkPort->portBits.baseAddr == nil) {
xlfail("Buffer allocation failed");
exit(1);
}
WorkPortWidth = WorkPort->portBits.bounds.right
- WorkPort->portBits.bounds.left;
WorkPortHeight = WorkPort->portBits.bounds.bottom
- WorkPort->portBits.bounds.top;
WorkRowStarts = (char **) StCalloc(sizeof(char *), portSize);
for (i = 0; i < portSize; i++)
WorkRowStarts[i] = WorkPort->portBits.baseAddr
+ i * WorkPort->portBits.rowBytes;
MakeSymbols();
CWorkPort = (CGrafPtr) WorkPort;
if (StScreenHasColor()) {
char *p;
Rect r;
struct row_bytes {
unsigned int flags : 3;
unsigned int data : 13;
} *rowBytes;
int size;
CWorkPort = &CWP;
OpenCPort(CWorkPort);
r = (*CWorkPort->portPixMap)->bounds;
rowBytes = (struct row_bytes *) &(*CWorkPort->portPixMap)->rowBytes;
portSize = r.bottom - r.top;
size = portSize * rowBytes->data;
if ((nnodes < 20000 && FreeMem() < size + 900000) || /* no workspace */
(nnodes >= 20000 && FreeMem() < size + 500000)) {
xoserror("not enough memory to allocate color port");
CWorkPort = (CGrafPtr) WorkPort;
}
else {
HLock((Handle) CWorkPort->portPixMap);
/* I do't know why I need this two-step business */
p = StCalloc(portSize, rowBytes->data);
(*CWorkPort->portPixMap)->baseAddr = p;
HUnlock((Handle) CWorkPort->portPixMap);
}
}
}
VOID adjust_graph_workport(StGWWinInfo *gwinfo)
{
GrafPtr savePort, workPort;
WindowPtr w;
if (buffering && gwinfo != nil && (w = gwinfo->window) != nil) {
workPort = (StGWUseColor(gwinfo)) ? (GrafPtr) CWorkPort : WorkPort;
GetPort(&savePort);
SetPort(workPort);
if (gwinfo->lineType != 0) PenPat(&gray);
else PenPat(&black);
PenMode(w->pnMode);
TextMode(w->txMode);
PenSize(w->pnSize.h, w->pnSize.h);
set_fore_color(gwinfo);
set_back_color(gwinfo);
SetPort(savePort);
}
}
/**************************************************************************/
/** **/
/** Line and Rectangle Drawing Functions **/
/** **/
/**************************************************************************/
LOCAL VOID SetDrawingPort(WindowPtr w)
{
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(w);
set_port((buffering) ? ((gwinfo->use_color) ? (GrafPtr) CWorkPort: WorkPort) : w);
}
static VOID draw_object(StGWWinInfo *gwinfo, int what, int how, int a, int b, int c, int d)
{
GrafPtr savePort;
Rect r;
WindowPtr w;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
savePort = get_port();
SetDrawingPort(w);
switch (what) {
case 'L': MoveTo(a, b); LineTo(c, d); break;
case 'P': MoveTo(a, b); Line(0, 0); break;
case 'R':
SetRect(&r, a, b, a + c, b + d);
switch (how) {
case 'E': EraseRect(&r); break;
case 'F': FrameRect(&r); break;
case 'P': PaintRect(&r); break;
}
break;
case 'O':
SetRect(&r, a, b, a + c, b + d);
switch (how) {
case 'E': EraseOval(&r); break;
case 'F': FrameOval(&r); break;
case 'P': PaintOval(&r); break;
}
break;
}
set_port(savePort);
}
static VOID draw_arc(StGWWinInfo *gwinfo, int how, int a, int b, int c, int d,
double angle1, double angle2)
{
GrafPtr savePort;
Rect r;
int a1, a2;
WindowPtr w;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
savePort = get_port();
SetDrawingPort(w);
SetRect(&r, a, b, a + c, b + d);
a1 = 90 - angle1;
a2 = -angle2;
switch (how) {
case 'E': EraseArc(&r, a1, a2); break;
case 'F': FrameArc(&r, a1, a2); break;
case 'P': PaintArc(&r, a1, a2); break;
}
set_port(savePort);
}
static VOID draw_poly(StGWWinInfo *gwinfo, int how, int n, short *p, int from_origin)
{
GrafPtr savePort;
int i;
WindowPtr w;
PolyHandle poly;
if (gwinfo == nil || (w = gwinfo->window) == nil || n <= 0) return;
savePort = get_port();
SetDrawingPort(w);
poly = OpenPoly();
MoveTo((int) p[0], (int) p[1]);
for (i = 1; i < n; i++) {
if (from_origin) LineTo((int) p[2 * i], (int) p[2 * i + 1]);
else Line((int) p[2 * i], (int) p[2 * i + 1]);
}
ClosePoly();
switch (how) {
case 'E': ErasePoly(poly); break;
case 'F': FramePoly(poly); break;
case 'P': PaintPoly(poly); break;
}
KillPoly(poly);
set_port(savePort);
}
VOID StGWDrawLine(StGWWinInfo *gwinfo, int x1, int y1, int x2, int y2)
{
draw_object(gwinfo, 'L', '0', x1, y1, x2, y2);
}
VOID StGWDrawPoint(StGWWinInfo *gwinfo, int x, int y)
{
draw_object(gwinfo, 'P', '0', x, y, 0, 0);
}
VOID StGWEraseRect(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'R', 'E', left, top, width, height);
}
VOID StGWFrameRect(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'R', 'F', left, top, width, height);
}
VOID StGWPaintRect(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'R', 'P', left, top, width, height);
}
VOID StGWEraseOval(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'O', 'E', left, top, width, height);
}
VOID StGWFrameOval(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'O', 'F', left, top, width, height);
}
VOID StGWPaintOval(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
draw_object(gwinfo, 'O', 'P', left, top, width, height);
}
VOID StGWEraseArc(StGWWinInfo *gwinfo, int left, int top, int width, int height,
double angle1, double angle2)
{
draw_arc(gwinfo, 'E', left, top, width, height, angle1, angle2);
}
VOID StGWFrameArc(StGWWinInfo *gwinfo, int left, int top, int width, int height,
double angle1, double angle2)
{
draw_arc(gwinfo, 'F', left, top, width, height, angle1, angle2);
}
VOID StGWPaintArc(StGWWinInfo *gwinfo, int left, int top, int width, int height,
double angle1, double angle2)
{
draw_arc(gwinfo, 'P', left, top, width, height, angle1, angle2);
}
VOID StGWErasePoly(StGWWinInfo *gwinfo, int n, short *p, int from_origin)
{
draw_poly(gwinfo, 'E', n, p, from_origin);
}
VOID StGWFramePoly(StGWWinInfo *gwinfo, int n, short *p, int from_origin)
{
draw_poly(gwinfo, 'F', n, p, from_origin);
}
VOID StGWPaintPoly(StGWWinInfo *gwinfo, int n, short *p, int from_origin)
{
draw_poly(gwinfo, 'P', n, p, from_origin);
}
/**************************************************************************/
/** **/
/** Text Functions **/
/** **/
/**************************************************************************/
static text_size(StGWWinInfo *gwinfo, int ascent)
{
WindowPtr w;
GrafPtr savePort;
FontInfo info;
if (gwinfo == nil || (w = gwinfo->window) == nil)
w = (StGWUseColor(gwinfo)) ? (WindowPtr) CWorkPort : (WindowPtr) WorkPort;
savePort = get_port();
set_port(w);
GetFontInfo(&info);
set_port(savePort);
return((ascent) ? info.ascent : info.descent);
}
int StGWTextAscent(StGWWinInfo *gwinfo) { return(text_size(gwinfo, TRUE)); }
int StGWTextDescent(StGWWinInfo *gwinfo) { return(text_size(gwinfo, FALSE)); }
int StGWTextWidth(StGWWinInfo *gwinfo, char *text)
{
WindowPtr w;
GrafPtr savePort;
int string_width;
Str255 pbuf;
if (gwinfo == nil || (w = gwinfo->window) == nil)
w = (StGWUseColor(gwinfo)) ? (WindowPtr) CWorkPort : (WindowPtr) WorkPort;
savePort = get_port();
set_port(w);
CintoPstring(text, pbuf, sizeof pbuf, FALSE);
string_width = StringWidth(pbuf);
set_port(savePort);
return(string_width);
}
VOID StGWDrawString(StGWWinInfo *gwinfo, char *s, int x, int y)
{
GrafPtr savePort;
WindowPtr w;
Str255 pbuf;
if (s == nil || gwinfo == nil || (w = gwinfo->window) == nil) return;
savePort = get_port();
SetDrawingPort(w);
MoveTo(x, y);
CintoPstring(s, pbuf, sizeof pbuf, FALSE);
DrawString(pbuf);
set_port(savePort);
}
VOID StGWDrawText(StGWWinInfo *gwinfo, char *text, int x, int y, int h, int v)
{
int FontAscent, string_width;
if (text == nil || gwinfo == nil) return;
FontAscent = StGWTextAscent(gwinfo);
string_width = StGWTextWidth(gwinfo, text);
if (v == 1) y += FontAscent;
if (h == 1) x -= string_width / 2;
if (h == 2) x -= string_width;
StGWDrawString(gwinfo, text, x, y);
}
static VOID DrawCharUp(WindowPtr w, char myChar, int x, int y)
{
static GrafPort gp;
static GrafPtr charPort;
static is_open = FALSE;
char myImage[32], myTarget[32];
BitMap myMap, saveBits;
GrafPtr savePort;
Rect r;
register int i, j;
savePort = get_port();
if (! is_open) {
charPort = &gp;
OpenPort(charPort);
is_open = TRUE;
}
set_port(charPort);
charPort->txFont = w->txFont;
charPort->txFace = w->txFace;
charPort->txMode = w->txMode;
charPort->txSize = w->txSize;
charPort->spExtra = w->spExtra;
myMap.baseAddr = myImage;
myMap.rowBytes = 2;
SetRect(&myMap.bounds, 0, 0, 15, 15);
for (i = 0; i < 32; i++) {
myImage[i] = '\0';
myTarget[i] = '\0';
}
saveBits = charPort->portBits;
charPort->portBits = myMap;
MoveTo(3, 12);
DrawChar(myChar);
charPort->portBits = saveBits;
set_port(savePort);
for (i = 0; i < 16; i++)
for (j = 0; j < 16; j++)
if (BitTst(myImage, 16 * i + j)) BitSet(myTarget, i + (16 - j) * 16);
r = myMap.bounds;
OffsetRect(&r, x - 12, y + 3 - (r.bottom - r.top));
myMap.baseAddr = myTarget;
SetDrawingPort(w);
CopyBits(&myMap, &thePort->portBits, &myMap.bounds, &r, w->txMode, nil);
set_port(savePort);
}
VOID StGWDrawStringUp(StGWWinInfo *gwinfo, char *s, int x, int y)
{
WindowPtr w;
char str[2];
int n;
if (s == nil || gwinfo == nil || (w = gwinfo->window) == nil) return;
str[1] = '\0';
for (n = strlen(s); n > 0; n--, s++) {
DrawCharUp(w, *s, x, y);
str[0] = *s;
y -= StGWTextWidth(gwinfo, str);
}
}
VOID StGWDrawTextUp(StGWWinInfo *gwinfo, char *text, int x, int y, int h, int v)
{
int FontAscent, string_width;
if (text == nil || gwinfo == nil) return;
FontAscent = StGWTextAscent(gwinfo);
string_width = StGWTextWidth(gwinfo, text);
if (v == 1) x += FontAscent;
if (h == 1) y += string_width / 2;
if (h == 2) y += string_width;
StGWDrawStringUp(gwinfo, text, x, y);
}
/**************************************************************************/
/** **/
/** Symbol Functions **/
/** **/
/**************************************************************************/
#define NUMSYMBOLS 18
#define SYMROWS 5
typedef struct {
unsigned bit0 :1;
unsigned bit1 :1;
unsigned bit2 :1;
unsigned bit3 :1;
unsigned bit4 :1;
} SymBits;
typedef struct {
BitMap map;
int left, top;
short image[SYMROWS];
long refcon;
} Symbol;
static Symbol Symbols[NUMSYMBOLS];
VOID StGWSetSymRefCon(unsigned int index, long rc)
{
if (index < NUMSYMBOLS) Symbols[index].refcon = rc;
}
long StGWGetSymRefCon(unsigned int index)
{
if (index < NUMSYMBOLS) return(Symbols[index].refcon);
else return((long) nil);
}
static VOID InitSymbol(int sym, int left, int top, int width, int height)
{
SetRect(&Symbols[sym].map.bounds, 0, 0, width, height);
Symbols[sym].map.rowBytes = 2;
Symbols[sym].map.baseAddr = (Ptr) &Symbols[sym].image;
Symbols[sym].left = left;
Symbols[sym].top = top;
}
VOID StGWGetSymbolSize(int sym, int *width, int *height)
{
*width = Symbols[sym].map.bounds.right;
*height = Symbols[sym].map.bounds.bottom;
}
static VOID SetSymbolData(int sym, int row, int bit0, int bit1, int bit2, int bit3, int bit4)
{
SymBits *d = (SymBits *) &(Symbols[sym].image[row]);
d->bit0 = bit0;
d->bit1 = bit1;
d->bit2 = bit2;
d->bit3 = bit3;
d->bit4 = bit4;
}
static VOID MakeSymbols(void)
{
InitSymbol(0, 0, 0, 2, 2);
SetSymbolData(0, 0, 1, 0, 0, 0, 0);
SetSymbolData(0, 1, 0, 0, 0, 0, 0);
SetSymbolData(0, 2, 0, 0, 0, 0, 0);
SetSymbolData(0, 3, 0, 0, 0, 0, 0);
SetSymbolData(0, 4, 0, 0, 0, 0, 0);
InitSymbol(1, 0, 0, 2, 2);
SetSymbolData(1, 0, 1, 1, 0, 0, 0);
SetSymbolData(1, 1, 0, 0, 0, 0, 0);
SetSymbolData(1, 2, 0, 0, 0, 0, 0);
SetSymbolData(1, 3, 0, 0, 0, 0, 0);
SetSymbolData(1, 4, 0, 0, 0, 0, 0);
InitSymbol(2, 0, 0, 2, 2);
SetSymbolData(2, 0, 1, 1, 0, 0, 0);
SetSymbolData(2, 1, 1, 0, 0, 0, 0);
SetSymbolData(2, 2, 0, 0, 0, 0, 0);
SetSymbolData(2, 3, 0, 0, 0, 0, 0);
SetSymbolData(2, 4, 0, 0, 0, 0, 0);
InitSymbol(3, 0, 0, 2, 2);
SetSymbolData(3, 0, 1, 1, 0, 0, 0);
SetSymbolData(3, 1, 1, 1, 0, 0, 0);
SetSymbolData(3, 2, 0, 0, 0, 0, 0);
SetSymbolData(3, 3, 0, 0, 0, 0, 0);
SetSymbolData(3, 4, 0, 0, 0, 0, 0);
InitSymbol(4, 2, 2, 4, 4);
SetSymbolData(4, 0, 0, 1, 1, 0, 0);
SetSymbolData(4, 1, 1, 0, 0, 1, 0);
SetSymbolData(4, 2, 1, 0, 0, 1, 0);
SetSymbolData(4, 3, 0, 1, 1, 0, 0);
SetSymbolData(4, 4, 0, 0, 0, 0, 0);
InitSymbol(5, 2, 2, 4, 4);
SetSymbolData(5, 0, 0, 1, 1, 0, 0);
SetSymbolData(5, 1, 1, 1, 1, 1, 0);
SetSymbolData(5, 2, 1, 1, 1, 1, 0);
SetSymbolData(5, 3, 0, 1, 1, 0, 0);
SetSymbolData(5, 4, 0, 0, 0, 0, 0);
InitSymbol(6, 3, 3, 5, 5);
SetSymbolData(6, 0, 0, 0, 1, 0, 0);
SetSymbolData(6, 1, 0, 1, 0, 1, 0);
SetSymbolData(6, 2, 1, 0, 0, 0, 1);
SetSymbolData(6, 3, 0, 1, 0, 1, 0);
SetSymbolData(6, 4, 0, 0, 1, 0, 0);
InitSymbol(7, 3, 3, 5, 5);
SetSymbolData(7, 0, 0, 0, 1, 0, 0);
SetSymbolData(7, 1, 0, 1, 1, 1, 0);
SetSymbolData(7, 2, 1, 1, 1, 1, 1);
SetSymbolData(7, 3, 0, 1, 1, 1, 0);
SetSymbolData(7, 4, 0, 0, 1, 0, 0);
InitSymbol(8, 3, 3, 5, 5);
SetSymbolData(8, 0, 0, 0, 1, 0, 0);
SetSymbolData(8, 1, 0, 0, 1, 0, 0);
SetSymbolData(8, 2, 1, 1, 1, 1, 1);
SetSymbolData(8, 3, 0, 0, 1, 0, 0);
SetSymbolData(8, 4, 0, 0, 1, 0, 0);
InitSymbol(9, 3, 3, 5, 5);
SetSymbolData(9, 0, 0, 1, 1, 1, 0);
SetSymbolData(9, 1, 1, 0, 1, 0, 1);
SetSymbolData(9, 2, 1, 1, 1, 1, 1);
SetSymbolData(9, 3, 1, 0, 1, 0, 1);
SetSymbolData(9, 4, 0, 1, 1, 1, 0);
InitSymbol(10, 2, 2, 4, 4);
SetSymbolData(10, 0, 1, 1, 1, 1, 0);
SetSymbolData(10, 1, 1, 0, 0, 1, 0);
SetSymbolData(10, 2, 1, 0, 0, 1, 0);
SetSymbolData(10, 3, 1, 1, 1, 1, 0);
SetSymbolData(10, 4, 0, 0, 0, 0, 0);
InitSymbol(11, 2, 2, 4, 4);
SetSymbolData(11, 0, 1, 1, 1, 1, 0);
SetSymbolData(11, 1, 1, 1, 1, 1, 0);
SetSymbolData(11, 2, 1, 1, 1, 1, 0);
SetSymbolData(11, 3, 1, 1, 1, 1, 0);
SetSymbolData(11, 4, 0, 0, 0, 0, 0);
InitSymbol(12, 3, 3, 5, 5);
SetSymbolData(12, 0, 0, 1, 1, 1, 0);
SetSymbolData(12, 1, 1, 0, 0, 0, 1);
SetSymbolData(12, 2, 1, 0, 0, 0, 1);
SetSymbolData(12, 3, 0, 1, 0, 1, 0);
SetSymbolData(12, 4, 0, 0, 1, 0, 0);
InitSymbol(13, 3, 3, 5, 5);
SetSymbolData(13, 0, 0, 1, 1, 1, 0);
SetSymbolData(13, 1, 1, 1, 1, 1, 1);
SetSymbolData(13, 2, 1, 1, 1, 1, 1);
SetSymbolData(13, 3, 0, 1, 1, 1, 0);
SetSymbolData(13, 4, 0, 0, 1, 0, 0);
InitSymbol(14, 3, 3, 5, 5);
SetSymbolData(14, 0, 0, 0, 1, 0, 0);
SetSymbolData(14, 1, 0, 1, 0, 1, 0);
SetSymbolData(14, 2, 1, 0, 0, 0, 1);
SetSymbolData(14, 3, 1, 0, 0, 0, 1);
SetSymbolData(14, 4, 0, 1, 1, 1, 0);
InitSymbol(15, 3, 3, 5, 5);
SetSymbolData(15, 0, 0, 0, 1, 0, 0);
SetSymbolData(15, 1, 0, 1, 1, 1, 0);
SetSymbolData(15, 2, 1, 1, 1, 1, 1);
SetSymbolData(15, 3, 1, 1, 1, 1, 1);
SetSymbolData(15, 4, 0, 1, 1, 1, 0);
InitSymbol(16, 3, 3, 5, 5);
SetSymbolData(16, 0, 1, 0, 0, 0, 1);
SetSymbolData(16, 1, 0, 1, 0, 1, 0);
SetSymbolData(16, 2, 0, 0, 1, 0, 0);
SetSymbolData(16, 3, 0, 1, 0, 1, 0);
SetSymbolData(16, 4, 1, 0, 0, 0, 1);
InitSymbol(17, 3, 3, 5, 5);
SetSymbolData(17, 0, 1, 1, 0, 1, 1);
SetSymbolData(17, 1, 1, 1, 0, 1, 1);
SetSymbolData(17, 2, 0, 0, 1, 0, 0);
SetSymbolData(17, 3, 1, 1, 0, 1, 1);
SetSymbolData(17, 4, 1, 1, 0, 1, 1);
}
VOID StGWDrawSymbol(StGWWinInfo *gwinfo, int sym, int x, int y)
{
WindowPtr w;
GrafPtr savePort;
Rect r;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
savePort = get_port();
SetDrawingPort(w);
if (! copying_to_clip && buffering && sym < 4 && ! gwinfo->use_color) {
BufferMarkPoint(x - gwinfo->view_h, y - gwinfo->view_v,
sym, gwinfo->drawColor);
return;
}
if (sym < 0 || sym >= NUMSYMBOLS) return;
x -= Symbols[sym].left;
y -= Symbols[sym].top;
r = Symbols[sym].map.bounds;
OffsetRect(&r, x, y);
CopyBits(&Symbols[sym].map, &thePort->portBits,
&Symbols[sym].map.bounds, &r, gwinfo->symbolMode, nil);
set_port(savePort);
}
static VOID BufferMarkPoint(unsigned x, unsigned y, unsigned sym, unsigned color)
{
if (x >= WorkPortWidth || y >= WorkPortHeight) return;
if (color != 0) {
BitSet(WorkRowStarts[y], x); if (sym == 0) return;
BitSet(WorkRowStarts[y], x + 1); if (sym == 1) return;
BitSet(WorkRowStarts[y + 1], x); if (sym == 2) return;
BitSet(WorkRowStarts[y + 1], x + 1);
}
else {
BitClr(WorkRowStarts[y], x); if (sym == 0) return;
BitClr(WorkRowStarts[y], x + 1); if (sym == 1) return;
BitClr(WorkRowStarts[y + 1], x); if (sym == 2) return;
BitClr(WorkRowStarts[y + 1], x + 1);
}
}
VOID StGWReplaceSymbol(StGWWinInfo *gwinfo, unsigned oldsym, unsigned newsym, int x, int y)
{
int oldwidth, oldheight, newwidth, newheight;
if (oldsym >= NUMSYMBOLS || newsym >= NUMSYMBOLS) return;
StGWGetSymbolSize(oldsym, &oldwidth, &oldheight);
StGWGetSymbolSize(newsym, &newwidth, &newheight);
if (oldwidth > newwidth || oldheight > newheight)
StGWEraseRect(gwinfo, x - Symbols[oldsym].left, y - Symbols[oldsym].top,
oldwidth, oldheight);
StGWDrawSymbol(gwinfo, newsym, x, y);
}
/**************************************************************************/
/** **/
/** Bitmap Functions **/
/** **/
/**************************************************************************/
static make_bitmap(int width, int height, char *image, BitMap *pbm)
{
int i, j;
char *rowdata;
pbm->rowBytes = 2 * ((width % 16 == 0) ? width / 16 : width / 16 + 1);
if (pbm->rowBytes * height <= 0) return(FALSE);
pbm->baseAddr = StCalloc(pbm->rowBytes * height, 1);
if (pbm->baseAddr == nil) return(FALSE);
for (i = 0; i < height; i++) {
rowdata = pbm->baseAddr + i * pbm->rowBytes;
for (j = 0; j < width; j++)
if (image[i * width + j] != 0) BitSet(rowdata, j);
}
pbm->bounds.left = 0; pbm->bounds.top = 0;
pbm->bounds.right = width; pbm->bounds.bottom = height;
return(TRUE);
}
static VOID free_bitmap(BitMap *pbm)
{
if (pbm->baseAddr != nil) StFree(pbm->baseAddr);
}
VOID StGWDrawBitmap(StGWWinInfo *gwinfo, int left, int top, int width, int height, char *image)
{
WindowPtr w;
BitMap bm;
GrafPtr savePort;
Rect r;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
savePort = get_port();
SetDrawingPort(w);
if (make_bitmap(width, height, image, &bm)) {
r = bm.bounds;
OffsetRect(&r, left, top);
CopyBits(&bm, &thePort->portBits, &bm.bounds, &r, gwinfo->symbolMode, nil);
free_bitmap(&bm);
}
set_port(savePort);
}
/**************************************************************************/
/** **/
/** Buffering Functions **/
/** **/
/**************************************************************************/
VOID StGWStartBuffering(StGWWinInfo *gwinfo)
{
WindowPtr w;
GrafPtr savePort;
Rect r;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
bufflevel++;
if (buffering) return;
buffering = TRUE;
GetPort(&savePort);
SetPort((StGWUseColor(gwinfo)) ? (GrafPtr) CWorkPort : WorkPort);
set_fore_color(gwinfo);
set_back_color(gwinfo);
if (gwinfo->lineType != 0) PenPat(&gray);
else PenPat(&black);
PenMode(w->pnMode);
TextFont(w->txFont);
TextFace(w->txFace);
TextMode(w->txMode);
TextSize(w->txSize);
SpaceExtra(w->spExtra);
SetOrigin(gwinfo->view_h, gwinfo->view_v);
r = w->portRect;
r.right -= 15;
if (gwinfo->hasHscroll) r.bottom -= 15;
ClipRect(&r);
CopyRgn(w->visRgn, thePort->visRgn);
CopyRgn(w->clipRgn, thePort->clipRgn);
SetPort(savePort);
}
VOID StGWBufferToScreen(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
WindowPtr w;
GrafPtr savePort, workPort;
Rect r;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
if (bufflevel > 0) bufflevel--;
if (bufflevel > 0) return;
if (! buffering) return;
buffering = FALSE;
workPort = (StGWUseColor(gwinfo)) ? (GrafPtr) CWorkPort : WorkPort;
GetPort(&savePort);
SetPort(w);
ForeColor(blackColor);
BackColor(whiteColor);
SetRect(&r, left, top, left + width, top + height);
if (SectRect(&r, &w->portRect, &r))
CopyBits(&workPort->portBits,&w->portBits, &r, &r, srcCopy, nil);
set_fore_color(gwinfo);
set_back_color(gwinfo);
SetPort(savePort);
}
/**************************************************************************/
/** **/
/** Miscelaneous Functions **/
/** **/
/**************************************************************************/
VOID StGWCopyToClip(StGWWinInfo *gwinfo)
{
make_picture(gwinfo, nil);
}
VOID StGWDumpImage(StGWWinInfo *gwinfo, char *fname, double scale)
{
make_picture(gwinfo, fname);
}
static VOID make_picture(StGWWinInfo *gwinfo, char *fname)
{
PicHandle pic;
Rect r;
long result, mytype;
GrafPtr savePort, workPort;
LVAL object;
WindowPtr w;
/* int vRefNum, i;
FILE *fptr; */
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
object = StGWGetObject(gwinfo);
workPort = (StGWUseColor(gwinfo)) ? (GrafPtr) CWorkPort : WorkPort;
StGWStartBuffering(gwinfo);
r = w->portRect;
r.right -= 15;
if (StGWHasHscroll(gwinfo)) r.bottom -= 15;
copying_to_clip = TRUE;
GetPort(&savePort);
SetPort(workPort);
pic = OpenPicture(&r);
SetPort(savePort);
StGWObRedraw(object);
GetPort(&savePort);
SetPort(workPort);
ClosePicture();
SetPort(savePort);
StGWBufferToScreen(gwinfo, 0, 0, 0, 0);
if (fname == nil) {
ZeroScrap();
mytype = 'PICT';
HLock((Handle) pic);
result = PutScrap(GetHandleSize((Handle) pic), mytype, (Ptr) *pic);
HUnlock((Handle) pic);
}
else {
/* if ((fptr = fopen(fname, "w")) == nil)
xlfail("can't open file");
GetPort(&savePort);
SetPort(WorkPort);
DrawPicture(pic, &r);
SetPort(savePort);
writemacp(fptr, WorkRowStarts, r.right - r.left, r.bottom - r.top);
xlfail("operation not supported");
spoolpict(fname, pic, WorkPort);*/
}
KillPicture(pic);
copying_to_clip = FALSE;
}
VOID StGWResetBuffer(void)
{
copying_to_clip = FALSE;
bufflevel = 0;
buffering = FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1