#include "xlisp.h"
#include "xlstat.h"
#include "xlgraph.h"
/* forward declarations */
LOCAL VOID DoCursor _((StGWWinInfo *gwinfo));
StGWWinInfo *IViewWindowWinInfo(WindowPtr w)
{
return((w != nil) ? (StGWWinInfo *) GetWRefCon(w) : nil);
}
/**************************************************************************/
/** **/
/** Initialization Functions **/
/** **/
/**************************************************************************/
VOID StInitGraphics()
{
initialize_static_globals();
init_mac_colors();
init_mac_cursors();
}
/**************************************************************************/
/** **/
/** Window Creation Functions **/
/** **/
/**************************************************************************/
Rect scroll_bar_bounds(WindowPtr w, int which)
{
Rect r;
r = w->portRect;
switch(which) {
case 'H':
r.top = r.bottom - 15; r.right -= 14; r.left--; r.bottom++; break;
case 'V':
r.left = r.right - 15; r.bottom -= 14; r.top--; r.right++; break;
}
return(r);
}
static int which_scroll, old_view_h, old_view_v;
static pascal void scroll_action(ControlHandle theCtl, short part)
{
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(thePort);
int value = GetControlValue(theCtl);
int left, top, width, height, inc, pageInc;
WindowPtr w = thePort;
LVAL object;
object = StGWGetObject(gwinfo);
if (gwinfo == nil) return;
switch (which_scroll) {
case 'H':
inc = gwinfo->h_scroll_inc[0];
pageInc = gwinfo->h_scroll_inc[1];
break;
case 'V':
inc = gwinfo->v_scroll_inc[0];
pageInc = gwinfo->v_scroll_inc[1];
break;
}
switch(part) {
case kControlUpButtonPart: value -= inc; break;
case kControlDownButtonPart: value += inc; break;
case kControlPageUpPart: value -= pageInc; break;
case kControlPageDownPart: value += pageInc; break;
}
switch (which_scroll) {
case 'H': StGWSetScroll(gwinfo, value, gwinfo->view_v, FALSE); break;
case 'V': StGWSetScroll(gwinfo, gwinfo->view_h, value, FALSE); break;
}
reset_clip_rect(gwinfo);
StGWGetViewRect(gwinfo, &left, &top, &width, &height);
StGWStartBuffering(gwinfo);
StGWObRedraw(object);
StGWBufferToScreen(gwinfo, left, top, width, height);
SetPort(w);
SetOrigin(old_view_h, old_view_v);
ClipRect(&w->portRect);
}
static ControlActionUPP scroll_actionUPP = NULL;
static pascal void mouse_action(Point pt, long t, short mods)
{
WindowPtr w = FrontWindow();
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(w);
ControlHandle theCtl;
int part, h, v, option, extend;
Rect r;
LVAL object;
object = StGWGetObject(gwinfo);
if (gwinfo == nil) return;
if ((part = FindControl(pt, w, &theCtl)) != 0) {
if (theCtl == gwinfo->hscroll) which_scroll = 'H';
else which_scroll = 'V';
ClipRect(&w->portRect);
if (part != 0 && part != kControlIndicatorPart) {
old_view_h = GetControlValue(gwinfo->hscroll);
old_view_v = GetControlValue(gwinfo->vscroll);
if (! scroll_actionUPP)
scroll_actionUPP = NewControlActionProc((ProcPtr) scroll_action);
TrackControl(theCtl, pt, scroll_actionUPP);
SetPort(w);
SetOrigin(gwinfo->view_h, gwinfo->view_v);
SetRect(&r, 0, 0, 0, 0);
ClipRect(&r);
r = scroll_bar_bounds(w, 'H');
MoveControl(gwinfo->hscroll, r.left, r.top);
r = scroll_bar_bounds(w, 'V');
MoveControl(gwinfo->vscroll, r.left, r.top);
}
else if (part == kControlIndicatorPart)
if (TrackControl(theCtl, pt, nil) == kControlIndicatorPart) {
h = GetControlValue(gwinfo->hscroll);
v = GetControlValue(gwinfo->vscroll);
StGWSetScroll(gwinfo, h, v, TRUE);
reset_clip_rect(gwinfo);
StGWObRedraw(object);
}
reset_clip_rect(gwinfo);
}
else {
extend = BitAnd(mods, shiftKey);
option = BitAnd(mods, optionKey);
mods = (extend) ? ExtendModifier : NoModifiers;
if (option) mods += 2;
StGWObDoMouse(gwinfo->Object, pt.h, pt.v, MouseClick, (MouseClickModifier) mods);
}
SetPort(w); /* I don't know why this is here - maybe it is needed */
/* ValidRect(&w->portRect);*//* This definitely causes problems */
}
static pascal void key_action(short key, short code, short mods)
{
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(FrontWindow());
LVAL object;
int shift, opt;
if (gwinfo == nil) return;
object = StGWGetObject(gwinfo);
shift = BitAnd(mods, shiftKey);
opt = BitAnd(mods, optionKey);
if (key == '\r') key = '\n';
StGWObDoKey(object, key, shift, opt);
}
VOID graph_update_action(StGWWinInfo *gwinfo, int resized)
{
WindowPtr w;
int width, height;
GrafPtr savePort;
Rect r;
LVAL object;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
object = StGWGetObject(gwinfo);
GetPort(&savePort);
SetPort(w);
if (! gwinfo->initialized) {
resized = TRUE;
gwinfo->initialized = TRUE;
}
if (resized) {
reset_clip_rect(gwinfo);
EraseRect(&w->portRect);
StGWGetViewRect(gwinfo, nil, nil, &width, &height);
if (gwinfo->hasHscroll) {
HideControl(gwinfo->hscroll);
width = (gwinfo->canvasWidth > width) ? gwinfo->canvasWidth - width : 0;
SetControlMaximum(gwinfo->hscroll, width);
SetControlValue(gwinfo->hscroll, gwinfo->view_h);
gwinfo->view_h = GetControlValue(gwinfo->hscroll);
}
if (gwinfo->hasVscroll) {
HideControl(gwinfo->vscroll);
height = (gwinfo->canvasHeight > height) ? gwinfo->canvasHeight - height : 0;
SetControlMaximum(gwinfo->vscroll, height);
SetControlValue(gwinfo->vscroll, gwinfo->view_v);
gwinfo->view_v = GetControlValue(gwinfo->vscroll);
}
SetOrigin(gwinfo->view_h, gwinfo->view_v);
r = scroll_bar_bounds(w, 'H');
MoveControl(gwinfo->hscroll, r.left, r.top);
SizeControl(gwinfo->hscroll, r.right - r.left, r.bottom - r.top);
r = scroll_bar_bounds(w, 'V');
MoveControl(gwinfo->vscroll, r.left, r.top);
SizeControl(gwinfo->vscroll, r.right - r.left, r.bottom - r.top);
ClipRect(&w->portRect);
if (gwinfo->hasHscroll) ShowControl(gwinfo->hscroll);
if (gwinfo->hasVscroll) ShowControl(gwinfo->vscroll);
reset_clip_rect(gwinfo);
}
if (resized && gwinfo != nil) {
if (! gwinfo->hasHscroll)
gwinfo->canvasWidth = w->portRect.right
- w->portRect.left - 15;
if (! gwinfo->hasVscroll) {
gwinfo->canvasHeight = w->portRect.bottom
- w->portRect.top;
if (gwinfo->hasHscroll) gwinfo->canvasHeight -= 15;
}
StGWObResize(object);
}
StGWObRedraw(object);
DrawGWGrowBox(gwinfo);
SetPort(w);
ClipRect(&w->portRect);
DrawControls(w);
reset_clip_rect(gwinfo);
SetHardwareState(gwinfo);
SetPort(w);
}
VOID DrawGWGrowBox(StGWWinInfo *gwinfo)
{
WindowPtr w;
Rect r;
GrafPtr savePort;
int reverse;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
reverse = (StGWBackColor(gwinfo) != 0);
GetPort(&savePort);
SetPort(w);
r = w->portRect;
r.left = r.right - 15;
ClipRect(&r);
ForeColor(blackColor);
BackColor(whiteColor);
if (! StGWHasVscroll(gwinfo)) EraseRect(&r);
DrawGrowIcon(w);
if (reverse) {
r = w->portRect;
r.left = r.right - 15;
if (StGWHasVscroll(gwinfo)) r.top = r.bottom - 15;
if (! StGWHasVscroll(gwinfo)) InvertRect(&r);
}
set_fore_color(gwinfo);
set_back_color(gwinfo);
reset_clip_rect(gwinfo);
SetHardwareState(gwinfo);
SetPort(savePort);
}
VOID graph_activate_action(StGWWinInfo *gwinfo, int active)
{
WindowPtr w;
Point pt;
int value;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
if (active) DoCursor(gwinfo);
else SetCursor(&arrow);
GetMouse(&pt);
gwinfo->mouse_x = pt.h; gwinfo->mouse_y = pt.v;
DrawGWGrowBox(gwinfo);
SetPort(w);
ClipRect(&w->portRect);
value = (active) ? 0 : 255;
HiliteControl(gwinfo->hscroll, value);
HiliteControl(gwinfo->vscroll, value);
reset_clip_rect(gwinfo);
}
static pascal void clobber_action(void)
{
WindowPtr wind = thePort;
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(thePort);
if (IViewInternalIsLinked(wind)) IViewUnlinkWindow(wind);
StGWObDoClobber(gwinfo->Object);
if (gwinfo != nil && gwinfo->FreeMem != nil) (*gwinfo->FreeMem)(wind);
gwinfo->window = nil;
DisposeWindow(wind);
}
static pascal void idle_action(void)
{
WindowPtr wind = thePort;
StGWWinInfo *gwinfo = (StGWWinInfo *) GetWRefCon(wind);
Point pt;
int old_x, old_y;
if (gwinfo != nil && wind == FrontWindow()) {
DoCursor(gwinfo);
old_x = gwinfo->mouse_x; old_y = gwinfo->mouse_y;
GetMouse(&pt);
gwinfo->mouse_x = pt.h; gwinfo->mouse_y = pt.v;
if ((abs(gwinfo->mouse_x - old_x) > MOUSE_TOLERANCE
|| abs(gwinfo->mouse_y - old_y) > MOUSE_TOLERANCE)) {
GetMouse(&pt);
gwinfo->mouse_x = pt.h; gwinfo->mouse_y = pt.v;
StGWObDoMouse(gwinfo->Object, pt.h, pt.v, MouseMove, NoModifiers);
}
}
if (gwinfo != nil && gwinfo->idleOn) StGWObDoIdle(gwinfo->Object);
}
int StGWWinInfoSize(void) { return(sizeof(StGWWinInfo)); }
VOID StGWInitWinInfo(LVAL object)
{
StGWWinInfo *gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
gwinfo->Object = object;
gwinfo->initialized = FALSE;
gwinfo->symbolMode = srcCopy;
gwinfo->canvasWidth = 0;
gwinfo->canvasHeight = 0;
gwinfo->hasHscroll = FALSE;
gwinfo->hasVscroll = FALSE;
gwinfo->view_h = 0;
gwinfo->view_v = 0;
gwinfo->h_scroll_inc[0] = 1; gwinfo->h_scroll_inc[1] = 50;
gwinfo->v_scroll_inc[0] = 1; gwinfo->v_scroll_inc[1] = 50;
gwinfo->lineType = 0;
gwinfo->drawMode = 0;
gwinfo->backColor = 0;
gwinfo->drawColor = 1;
gwinfo->lineWidth = 1;
gwinfo->window = nil;
gwinfo->idleOn = FALSE;
gwinfo->use_color = FALSE;
gwinfo->cursor = 0;
gwinfo->RefCon = (long) nil;
}
WindowPtr IViewWindowNew(LVAL object, int is_GW)
{
char *title;
int left, top, width, height, goAway;
StGWWinInfo *gwinfo;
WindowPtr wind;
Rect r;
Str255 pbuf;
StGWGetAllocInfo(object, &title, &left, &top, &width, &height, &goAway);
if (title == nil || strlen(title) <= 0) title = "Graph Window";
top += GetMBarHeight();
SetRect(&r, left, top, left + width + 15, top + height);
CintoPstring(title, pbuf, sizeof pbuf, FALSE);
if (StScreenHasColor())
wind = NewCWindow(nil, &r, pbuf, FALSE, 8, (WindowPtr) -1L, goAway, 0L);
else
wind = NewWindow(nil, &r, pbuf, FALSE, 8, (WindowPtr) -1L, goAway, 0L);
if (wind == nil) xlfail("allocation Failed");
if (! SkelWindow(wind, mouse_action, key_action, mac_update_action,
mac_activate_action, mac_close_action, clobber_action,
idle_action, FALSE))
xlfail("allocation Failed");
SetPort(wind);
if (graphFontNum)
TextFont(graphFontNum);
TextSize(graphFontSize);
TextFace(graphFontStyle);
TextMode(srcXor);
gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
r = wind->portRect;
r.top = r.bottom - 15; r.right -= 14; r.left--; r.bottom++;
gwinfo->hscroll = NewControl(wind, &r, "\p", FALSE, 0, 0, 0,
scrollBarProc, 0L);
r = wind->portRect;
r.left = r.right - 15; r.bottom -= 14; r.top--; r.right++;
gwinfo->vscroll = NewControl(wind, &r, "\p", FALSE, 0, 0, 0,
scrollBarProc, 0L);
gwinfo->window = wind;
if (! gwinfo->hasHscroll) gwinfo->canvasWidth = width;
if (! gwinfo->hasVscroll) gwinfo->canvasHeight = height;
gwinfo->initialized = FALSE;
SetWRefCon(wind, (long) gwinfo);
SetHardwareState(gwinfo);
StGWEraseRect(gwinfo, 0, 0, width, height);
StGWSetClipRect(gwinfo, FALSE, 0, 0, 0, 0);
if (is_GW) set_iview_window_address((CPTR) wind, object);
else set_iview_address((CPTR) wind, object);
return(wind);
}
/**************************************************************************/
/** **/
/** Clipping Functions **/
/** **/
/**************************************************************************/
VOID StGWSetClipRect(StGWWinInfo *gwinfo, int clipped, int left, int top, int width, int height)
{
if (gwinfo == nil) return;
gwinfo->clipped = clipped;
if (clipped) {
SetRect(&gwinfo->clip_rect, left, top, left + width, top + height);
}
reset_clip_rect(gwinfo);
}
int StGWGetClipRect(StGWWinInfo *gwinfo, int *left, int *top, int *width, int *height)
{
if (gwinfo == nil) return(FALSE);
if (gwinfo->clipped) {
if (left != nil) *left = gwinfo->clip_rect.left;
if (top != nil) *top = gwinfo->clip_rect.top;
if (width != nil) *width = gwinfo->clip_rect.right - gwinfo->clip_rect.left;
if (height != nil) *height = gwinfo->clip_rect.bottom - gwinfo->clip_rect.top;
}
return(gwinfo->clipped);
}
/**************************************************************************/
/** **/
/** Miscelaneous Functions **/
/** **/
/**************************************************************************/
#define NumBasicCursors 9
static int NumCursors;
typedef struct {
CursHandle curs;
long refcon;
} cursor_entry;
static cursor_entry *curstab;
VOID init_mac_cursors(void)
{
NumCursors = NumBasicCursors;
curstab = (cursor_entry *) StCalloc(NumCursors, sizeof(cursor_entry));
}
VOID StGWSetCursRefCon(unsigned int index, long rc)
{
if (index < NumCursors) curstab[index].refcon = rc;
}
long StGWGetCursRefCon(unsigned int index)
{
if (index < NumCursors) return(curstab[index].refcon);
else return((long) nil);
}
static VOID set_image_bits(int n, char *bits, char *image)
{
int i;
for (i = 0; i < n; i++) {
if (image[i] == 0) BitClr(bits, i);
else BitSet(bits, i);
}
}
static VOID clear_image_bits(int n, char *bits)
{
int i;
for (i = 0; i < n; i++) BitClr(bits, i);
}
int StGWMakeCursor(int n, char *image, char *mask, int h, int v, long refcon)
{
int index;
char *temp;
CursHandle curs;
if (n != 16 || image == nil) return(-1);
for (index = 0; index < NumCursors && StGWGetCursRefCon(index) != (long) nil; index++);
if (index >= NumCursors) {
temp = realloc(curstab, (NumCursors + 1) * sizeof(cursor_entry));
if (temp == nil) return(-1);
curstab = (cursor_entry *) temp;
NumCursors++;
curstab[index].curs = nil;
curstab[index].refcon = (long) nil;
}
if (curstab[index].curs != nil) DisposeHandle((Handle) curstab[index].curs);
curs = (CursHandle) NewHandle(sizeof(Cursor));
if (curs == nil) return(-1);
if (mask == nil) clear_image_bits(n * n, (char *) (*curs)->mask);
else set_image_bits(n * n, (char *) (*curs)->mask, mask);
set_image_bits(n * n, (char *) (*curs)->data, image);
(*curs)->hotSpot.h = h;
(*curs)->hotSpot.v = v;
curstab[index].curs = curs;
curstab[index].refcon = refcon;
return(index);
}
int StGWMakeResCursor(char *name, int num, long refcon)
{
int index;
char *temp;
CursHandle curs, curs_copy;
for (index = 0; index < NumCursors && StGWGetCursRefCon(index) != (long) nil; index++);
if (index >= NumCursors) {
temp = realloc(curstab, (NumCursors + 1) * sizeof(cursor_entry));
if (temp == nil) return(-1);
curstab = (cursor_entry *) temp;
NumCursors++;
curstab[index].curs = nil;
curstab[index].refcon = (long) nil;
}
if (curstab[index].curs != nil) DisposeHandle((Handle) curstab[index].curs);
if (name != nil) {
Str255 pbuf;
CintoPstring(name, pbuf, sizeof pbuf, FALSE);
curs = (CursHandle) GetNamedResource('CURS', pbuf);
}
else curs = GetCursor(num);
if (curs == nil) return(-1);
curs_copy = (CursHandle) NewHandle(sizeof(Cursor));
if (curs_copy == nil) return(-1);
**curs_copy = **curs;
curstab[index].curs = curs_copy;
curstab[index].refcon = refcon;
return(index);
}
VOID StGWFreeCursor(unsigned int index)
{
if (index < NumCursors && index >= NumBasicCursors) {
if (curstab[index].curs != nil)
DisposeHandle((Handle) curstab[index].curs);
curstab[index].curs = nil;
curstab[index].refcon = (long) nil;
}
else xlfail("can't free standard cursor");
}
static CursHandle get_cursor(unsigned int index)
{
CursHandle curs = nil;
if (index < NumBasicCursors) {
switch (index) {
case ARROW_CURSOR: curs = nil; break;
case WATCH_CURSOR: curs = GetCursor(watchCursor); break;
case CROSS_CURSOR: curs = GetCursor(crossCursor); break;
case BRUSH_CURSOR: curs = GetCursor(BRUSH_RES); break;
case HAND_CURSOR: curs = GetCursor(HAND_RES); break;
case FINGER_CURSOR: curs = GetCursor(FINGER_RES); break;
case HOUR_GLASS_CURSOR: curs = GetCursor(GLASS_RES); break;
case TRASH_BAG_CURSOR: curs = GetCursor(BAG_RES); break;
case TRASH_CAN_CURSOR: curs = GetCursor(CAN_RES); break;
}
}
else if (index < NumCursors)
curs = curstab[index].curs;
return(curs);
}
VOID mac_do_cursor(StGWWinInfo *gwinfo) { DoCursor(gwinfo); }
LOCAL VOID DoCursor(StGWWinInfo *gwinfo)
{
int left, top, width, height;
Point pt;
CursHandle curs = nil;
WindowPtr w;
if (gwinfo == nil || (w = gwinfo->window) == nil) return;
GetMouse(&pt);
StGWGetViewRect(gwinfo, &left, &top, &width, &height);
if (w == FrontWindow()
&& pt.h > left && pt.h < left + width
&& pt.v > top && pt.v < top + height)
curs = get_cursor(StGWCursor(gwinfo));
if (curs != nil) SetCursor(*curs);
else SetCursor(&arrow);
}
VOID StGWSetCursor(StGWWinInfo *gwinfo, int cursor)
{
if (gwinfo == nil) return;
gwinfo->cursor = cursor;
}
int StGWCursor(StGWWinInfo *gwinfo)
{
if (gwinfo == nil) return(FALSE);
return(gwinfo->cursor);
}
syntax highlighted by Code2HTML, v. 0.9.1