executor/src/ctlStddef.c

458 lines
10 KiB
C

/* Copyright 1986 - 1996 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_ctlStddef[] =
"$Id: ctlStddef.c 63 2004-12-24 18:19:43Z ctm $";
#endif
#include "rsys/common.h"
#include "WindowMgr.h"
#include "ControlMgr.h"
#include "QuickDraw.h"
#include "CQuickDraw.h"
#include "WindowMgr.h"
#include "ControlMgr.h"
#include "ToolboxUtil.h"
#include "MemoryMgr.h"
#include "rsys/ctl.h"
#include "rsys/cquick.h"
enum
{
frame_color,
body_color,
text_color,
n_ctl_colors,
};
static RGBColor current_control_colors[n_ctl_colors];
static int text_mode;
static Pattern frame_pattern;
void
validate_colors_for_control (ControlHandle ctl)
{
RGBColor ctl_ctab_colors[n_ctl_colors];
AuxCtlHandle t_aux_c;
int hilited_p, active_p;
int i;
hilited_p = (CTL_HILITE_X (ctl) != 255);
active_p = (CTL_HILITE_X (ctl) == inButton);
for (i = 0; i < n_ctl_colors; i ++)
ctl_ctab_colors[i] = default_ctl_colors[i].rgb;
#if 0
{
int def_ctl_ctab_size;
ColorSpec *def_ctl_ctab_table;
def_ctl_ctab_size = CTAB_SIZE (default_ctl_ctab);
def_ctl_ctab_table = CTAB_TABLE (default_ctl_ctab);
for (i = 0; i < n_ctl_colors; i ++)
{
int j;
for (j = 0; j < def_ctl_ctab_size; j ++)
if (CW (def_ctl_ctab_table[j].value) == i)
ctl_ctab_colors[i] = def_ctl_ctab_table[j].rgb;
}
}
#endif
t_aux_c = MR (*lookup_aux_ctl (ctl));
if (t_aux_c && HxX (t_aux_c, acCTable))
{
CTabHandle c_ctab;
ColorSpec *c_ctab_table;
int c_ctab_size;
c_ctab = (CTabHandle) HxP (t_aux_c, acCTable);
c_ctab_table = CTAB_TABLE (c_ctab);
c_ctab_size = CTAB_SIZE (c_ctab);
for (i = c_ctab_size; i >= 0; i --)
{
ColorSpec *c_ctab_entry;
c_ctab_entry = &c_ctab_table[i];
if (CW (c_ctab_entry->value) >= n_ctl_colors)
{
/* don't make so much noise; our own default control
color table will set off this warning */
#if 0
warning_unexpected
("control color table with index `%d' > %d or < 0; ignored",
CW (c_ctab_entry->value), n_ctl_colors);
#endif
continue;
}
ctl_ctab_colors[CW (c_ctab_entry->value)] = c_ctab_entry->rgb;
}
}
if (hilited_p)
{
text_mode = srcOr;
if (active_p)
{
/* swapped */
current_control_colors[body_color] = ctl_ctab_colors[cTextColor];
current_control_colors[text_color] = ctl_ctab_colors[cBodyColor];
}
else
{
current_control_colors[text_color] = ctl_ctab_colors[cTextColor];
current_control_colors[body_color] = ctl_ctab_colors[cBodyColor];
}
current_control_colors[frame_color] = ctl_ctab_colors[frame_color];
PATASSIGN (frame_pattern, black);
}
else
{
if (! CGrafPort_p (thePort)
|| ! AVERAGE_COLOR (&ctl_ctab_colors[cFrameColor],
&ctl_ctab_colors[cBodyColor], 0x8000,
&current_control_colors[frame_color]))
{
current_control_colors[frame_color] = ctl_ctab_colors[frame_color];
PATASSIGN (frame_pattern, gray);
}
else
{
PATASSIGN (frame_pattern, black);
}
text_mode = grayishTextOr;
current_control_colors[body_color] = ctl_ctab_colors[cBodyColor];
current_control_colors[text_color] = ctl_ctab_colors[cTextColor];
}
}
static int countchar (StringPtr str, char c)
{
register int retval;
char *p, *ep;
for (retval = 0, p = (char *) str+1, ep = p + str[0]; p != ep; )
if (*p++ == c)
retval++;
return retval;
}
typedef enum { justleft, justmiddle } justenum;
#define SEPCHAR '\r'
static void
drawlabel (StringPtr str, Rect *rp, justenum just)
{
struct tempstr
{
INTEGER firstb;
INTEGER bytec;
INTEGER left;
} *infop, *temp;
register int i, ei, nlines;
FontInfo fi;
INTEGER mid, top, incr, text_mode_save;
ALLOCABEGIN
RGBForeColor (&current_control_colors[text_color]);
text_mode_save = PORT_TX_MODE_X (thePort);
TextMode (text_mode);
GetFontInfo(&fi);
nlines = countchar(str, SEPCHAR) + 1;
temp = infop = (struct tempstr *) ALLOCA(sizeof(*infop) * nlines);
temp->firstb = 1;
for (i = 1, ei = str[0]+1; i < ei; i++)
{
if (str[i] == SEPCHAR)
{
temp->bytec = i - temp->firstb;
temp++;
temp->firstb = i+1;
}
}
temp->bytec = i - temp->firstb;
if (just == justmiddle)
{
mid = (CW(rp->left) + CW(rp->right)) / 2;
for (i = 0; i < nlines; i++)
infop[i].left
= mid - TextWidth ((Ptr) str, infop[i].firstb, infop[i].bytec) / 2;
}
else
{
for (i = 0; i < nlines; i++)
infop[i].left = CW(rp->left);
}
incr = CW(fi.ascent) + CW(fi.descent) + CW(fi.leading);
top = (CW(rp->top) + CW(rp->bottom)) / 2 -
(nlines * incr - CW(fi.leading) + 1) / 2 + CW(fi.ascent);
for (i = 0; i < nlines; i++, top += incr)
{
MoveTo(infop[i].left, top);
DrawText((Ptr) str, infop[i].firstb, infop[i].bytec);
}
TextMode (text_mode_save);
ALLOCAEND
}
/*
* NOTE: mapvar used to return 0 if v couldn't be matched to pushButProc,
* checkBoxProc or radioButProc. However, the behaviour of Quicken 3.0
* suggests that the test really should be anything other than
* pushButProc returns inCheckBox. Blech!
*/
static int
mapvar (int v)
{
#if 0
switch (v) {
case pushButProc & 0xF:
return inButton;
case checkBoxProc & 0xF:
case radioButProc & 0xF:
return inCheckBox;
}
return 0;
#else
return ((v & 7) == pushButProc) ? inButton : inCheckBox;
#endif
}
static void
draw_push (ControlHandle c, int16 part)
{
RgnHandle save;
int16 h, v;
Rect r;
r = CTL_RECT (c);
h = CW (r.right) - CW(r.left);
v = (CW (r.bottom) - CW (r.top)) / 2;
if (h > v)
h = v;
save = PORT_CLIP_REGION_X (CTL_OWNER (c));
PORT_CLIP_REGION_X (CTL_OWNER (c)) = RM (NewRgn ());
OpenRgn();
FrameRoundRect (&r, h, v);
CloseRgn (PORT_CLIP_REGION (CTL_OWNER (c)));
/* erase in the body color */
RGBForeColor (&current_control_colors[body_color]);
PaintRoundRect (&r, h, v);
/* frame in the frame color */
RGBForeColor (&current_control_colors[frame_color]);
PenPat (frame_pattern);
FrameRoundRect (&r, h, v);
/* inset the rect by a pixel so that drawing cannot overlap the oval */
InsetRgn (PORT_CLIP_REGION (CTL_OWNER (c)), 1, 1);
/* draw the label in the body color, since it is internal to the
button. by default, `drawlabel ()' draws the text background in
the current background color (as used by radio and check buttons) */
RGBBackColor (&current_control_colors[body_color]);
drawlabel (CTL_TITLE (c), &r, justmiddle);
DisposeRgn (PORT_CLIP_REGION (CTL_OWNER (c)));
PORT_CLIP_REGION_X (CTL_OWNER (c)) = save;
}
static void
add_title (ControlHandle c)
{
WindowPtr control_owner;
RgnHandle save;
Rect r;
control_owner = CTL_OWNER (c);
save = PORT_CLIP_REGION_X (control_owner);
PORT_CLIP_REGION_X (control_owner) = RM (NewRgn ());
r = CTL_RECT (c);
RectRgn (PORT_CLIP_REGION (control_owner), &r);
r.left = CW (CW (r.left) + 16);
drawlabel (CTL_TITLE (c), &r, justleft);
DisposeRgn (PORT_CLIP_REGION (control_owner));
PORT_CLIP_REGION_X (control_owner) = save;
}
static void
draw_check (ControlHandle c, int16 part)
{
Rect r;
if (!part)
{
r = CTL_RECT (c);
r.right = CW (CW (r.right) - 2);
EraseRect (&r);
add_title (c);
}
r.left = CW (CW (CTL_RECT (c).left) + 2);
r.top = CW ((CW (CTL_RECT (c).top) + CW (CTL_RECT (c).bottom)) / 2 - 6);
r.bottom = CW (CW (r.top) + 12);
r.right = CW (CW (r.left) + 12);
EraseRect (&r);
RGBForeColor (&current_control_colors[frame_color]);
PenPat (frame_pattern);
if (CTL_HILITE (c) == inCheckBox)
PenSize (2, 2);
FrameRect (&r);
if (CTL_VALUE (c))
{
PenSize (1, 1);
MoveTo (CW (r.left) + 1, CW (r.top) + 1);
LineTo (CW (r.right) - 2, CW (r.bottom) - 2);
MoveTo (CW (r.right) - 2, CW (r.top) + 1);
LineTo (CW (r.left) + 1, CW (r.bottom) - 2);
}
}
static void
draw_radio (ControlHandle c, int16 part)
{
Rect r;
if (!part)
{
r = CTL_RECT (c);
r.right = CW (CW (r.right) - 2);
EraseRect (&r);
add_title (c);
}
r.left = CW (CW (CTL_RECT (c).left) + 2);
r.top = CW ((CW (CTL_RECT (c).top) + CW (CTL_RECT (c).bottom)) / 2 - 6);
r.bottom = CW (CW (r.top) + 12);
r.right = CW (CW (r.left) + 12);
EraseRect (&r);
if (CTL_HILITE (c) == inCheckBox)
PenSize (2, 2);
RGBForeColor (&current_control_colors[frame_color]);
PenPat (frame_pattern);
FrameOval (&r);
if (CTL_VALUE (c))
{
InsetRect (&r, 3, 3);
PaintOval (&r);
}
}
P4 (PUBLIC, pascal LONGINT, cdef0, INTEGER, var, ControlHandle, c,
INTEGER, mess, LONGINT, param) /* IMI-328 */
{
Point p;
Rect r;
draw_state_t draw_state;
int draw_p;
switch (mess)
{
case calcCRgns:
case calcCntlRgn:
case calcThumbRgn:
case thumbCntl:
param = (LONGINT) SYN68K_TO_US (param);
break;
default:
break;
}
/* if drawing can occur, validate the color state */
draw_p = (mess == drawCntl);
if (draw_p)
{
validate_colors_for_control (c);
draw_state_save (&draw_state);
}
switch (mess)
{
case drawCntl:
if (Hx(c, contrlVis) &&
SectRect (&HxX (PORT_VIS_REGION (thePort), rgnBBox),
&HxX(c, contrlRect), &r))
{
PenNormal ();
if (! (var & useWFont))
{
TextFont (0);
TextSize (0);
TextFace (0);
TextMode (srcCopy);
}
switch (var & ~useWFont)
{
case pushButProc & 0xF:
draw_push (c, (int16) param);
break;
case checkBoxProc & 0xF:
draw_check(c, (int16) param);
break;
case radioButProc & 0xF:
draw_radio(c, (int16) param);
break;
}
}
break;
case testCntl:
p.v = HiWord(param);
p.h = LoWord(param);
if (CTL_HILITE (c) != 255 && PtInRect (p, &CTL_RECT (c)))
return mapvar(var);
else
return 0;
case calcCRgns:
case calcCntlRgn:
{
RgnHandle rgn = (RgnHandle) param;
SignedByte state;
state = HGetState ((Handle) rgn);
if (state & LOCKBIT)
HSetState ((Handle) rgn, state & ~LOCKBIT);
RectRgn (rgn, &CTL_RECT (c));
HSetState ((Handle) rgn, state);
break;
}
case initCntl:
case dispCntl:
case posCntl:
case thumbCntl:
case dragCntl:
case autoTrack:
break;
default:
gui_assert (0); /* die */
return 0; /* make gcc -Wall happy */
}
if (draw_p)
draw_state_restore (&draw_state);
return 0;
}