#include "xlisp.h"
#include "xlstat.h"
#include "wxlisp.h"
#include "ledit.h"
#include "winutils.h"
/* external variables */
extern HWND hWndFrame, hWndClient;
extern HANDLE hInst, hAccel;
extern LVAL s_menu, sk_allocate, sk_close, sk_install, sk_remove;
extern LVAL s_hardware_objects;
extern int Exiting;
extern int xldebug;
extern int xlisp_mono;
/* global variables */
static char szIVWinClass[] = "MdiIVWinChild";
static char graphicsSection[] = "Graphics";
extern char *iniFile;
static HCURSOR hSaveCursor;
static HCURSOR hGCCursor, hArrowCursor, hWaitCursor, hCrossCursor,
hHandCursor, hBrushCursor, hFingerCursor;
static BOOL MouseCaptured = FALSE, MouseMotionOnly;
static HWND MouseWnd = 0;
static void (*MouseAction)(HWND, int, int);
static TEXTMETRIC tm;
static HFONT hGraphFont, hGraphFontUp;
/* buffer variables */
static HBITMAP monoBuffBits = 0, colorBuffBits = 0;
static HDC currentDC = 0, bufferDC = 0;
static int buffering = FALSE;
static int bufflevel = 0;
void StGWCopyToClip(StGWWinInfo *);
long CALLBACK IVWinProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam);
static HCURSOR get_cursor(unsigned int index);
static void init_msw_cursors(void);
static void init_msw_colors(void);
static unsigned long get_color(unsigned int index);
void init_msw_buffer(void);
static void init_msw_text(void);
static void cleanup_msw_text(void);
static void init_msw_symbols(void);
static void cleanup_msw_symbols(void);
static void StGWPrint(StGWWinInfo *gwinfo);
/**************************************************************************/
/** **/
/** Internal Data Functions **/
/** **/
/**************************************************************************/
int StGWWinInfoSize(void) { return(sizeof(StGWWinInfo)); }
void StGWInitWinInfo(LVAL object)
{
StGWWinInfo *gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
gwinfo->Object = object;
gwinfo->initialized = FALSE;
gwinfo->mouse_x = 0;
gwinfo->mouse_y = 0;
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 = NULL;
gwinfo->idleOn = FALSE;
gwinfo->use_color = FALSE;
gwinfo->cursor = 0;
gwinfo->RefCon = 0L;
gwinfo->drawPen.lopnStyle = PS_SOLID;
gwinfo->drawPen.lopnWidth.x = 1;
gwinfo->drawPen.lopnColor = 0;
gwinfo->rect_offset = 0;
}
void StGWSetRefCon(StGWWinInfo *gwinfo, long x)
{
if (gwinfo) gwinfo->RefCon = x;
}
long StGWGetRefCon(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->RefCon : 0);
}
void StGWSetObject(StGWWinInfo *gwinfo, LVAL x)
{
if (gwinfo) gwinfo->Object = x;
}
LVAL IViewWindowGetObject(HWND w)
{
StGWWinInfo *gwinfo = GETGWINFO(w);
return(gwinfo ? gwinfo->Object : NIL);
}
LVAL StGWGetObject(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->Object : NIL);
}
static void SetHardwareState(StGWWinInfo *gwinfo)
{
HDC hDC;
HWND w;
if (gwinfo && (w = gwinfo->window) != 0) {
hDC = GetDC((HWND) w);
SetBkMode(hDC, TRANSPARENT);
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
SelectObject(hDC, hGraphFont);
SetROP2(hDC, gwinfo->drawMode ? R2_NOT : R2_COPYPEN);
SetPolyFillMode(hDC, WINDING);
ReleaseDC((HWND) w, hDC);
}
}
/**************************************************************************/
/** **/
/** Initialization Functions **/
/** **/
/**************************************************************************/
BOOL InitApplGraphics(HANDLE hInstance)
{
WNDCLASS wc;
/* class structure for the IVIEW window */
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = IVWinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(LVAL) + sizeof(char *);
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, "GraphIcon");
wc.hCursor = (HCURSOR) NULL;
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc. lpszClassName = szIVWinClass;
if (! RegisterClass(&wc)) return(FALSE);
if (! InitApplResizeBrush(hInstance)) return(FALSE);
return(TRUE);
}
BOOL InitInstGraphics(HANDLE hInstance)
{
hGCCursor = LoadCursor(hInstance, "GCCursor");
hHandCursor = LoadCursor(hInstance, "HandCursor");
hFingerCursor = LoadCursor(hInstance, "FingerCursor");
hBrushCursor = LoadCursor(hInstance, "BrushCursor");
hArrowCursor = LoadCursor((HWND) NULL, IDC_ARROW);
hWaitCursor = LoadCursor((HWND) NULL, IDC_WAIT);
hCrossCursor = LoadCursor((HWND) NULL, IDC_CROSS);
return(TRUE);
}
void StInitGraphics(void)
{
init_msw_buffer();
init_msw_symbols();
init_msw_colors();
init_msw_cursors();
init_msw_text();
}
void MSWGraphCleanup(void)
{
if (bufferDC) {
DeleteDC(bufferDC);
bufferDC = 0;
}
if (colorBuffBits) {
DeleteObject(colorBuffBits);
colorBuffBits = 0;
}
if (monoBuffBits) {
DeleteObject(monoBuffBits);
monoBuffBits = 0;
}
cleanup_msw_symbols();
cleanup_msw_text();
}
/**************************************************************************/
/** **/
/** Window Creation, Destruction and Callback Functions **/
/** **/
/**************************************************************************/
HWND IViewWindowNew(LVAL object, int is_GW)
{
char *title;
int left, top, width, height, goAway;
StGWWinInfo *gwinfo;
HWND wind;
MDICREATESTRUCT mdicreate;
StGWGetAllocInfo(object, &title, &left, &top, &width, &height, &goAway);
if (title == NULL || strlen(title) <= 0) title = "Graph Window";
width += 2 * GetSystemMetrics(SM_CXFRAME);
height += 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
mdicreate.szClass = szIVWinClass;
mdicreate.szTitle = title;
mdicreate.hOwner = hInst;
mdicreate.x = left;
mdicreate.y = top;
mdicreate.cx = width;
mdicreate.cy = height;
mdicreate.style = WS_MINIMIZE | WS_HSCROLL | WS_VSCROLL;
mdicreate.lParam = (LONG) object;
wind = MDICreateWindow(hWndClient, &mdicreate);
if (! wind) xlfail("allocation Failed");
gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
gwinfo->window = wind;
SetScrollRange(wind, SB_VERT, 0, 0, TRUE);
SetScrollRange(wind, SB_HORZ, 0, 0, TRUE);
if (! gwinfo->hasHscroll) gwinfo->canvasWidth = width;
if (! gwinfo->hasVscroll) gwinfo->canvasHeight = height;
gwinfo->initialized = FALSE;
SETGWINFO(wind, gwinfo);
SETWINOBJECT(wind, object);
SetHardwareState(gwinfo);
StGWSetClipRect(gwinfo, FALSE, 0, 0, 0, 0);
if (is_GW) set_iview_window_address(wind, object);
else set_iview_address(wind, object);
return(wind);
}
void StGWRemove(StGWWinInfo *gwinfo)
{
HWND w;
if (gwinfo == NULL || (w = gwinfo->window) == NULL) return;
else MDIDestroyWindow(hWndClient, w);
}
void ReleaseMouse(void)
{
if (MouseCaptured) {
ReleaseCapture();
MouseCaptured = FALSE;
MouseAction = NULL;
}
MouseWnd = 0; // indicates mouse is up
}
void CaptureMouse(HWND hWnd)
{
ReleaseMouse();
SetCapture(hWnd);
MouseCaptured = TRUE;
MouseWnd = hWnd;
}
long CALLBACK IVWinProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam)
{
StGWWinInfo *gwinfo;
static int activating = FALSE;
switch (message) {
case WM_CREATE:
ReleaseMouse();
return(0);
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
case IDC_SHOWWINDOW:
if (IsIconic(hWnd))
MDIRestoreWindow(hWndClient, hWnd);
MDIActivateWindow(hWndClient, hWnd);
return(0);
case IDC_HIDEWINDOW:
if (! IsIconic(hWnd))
ShowWindow(hWnd, SW_MINIMIZE);
return(0);
case IDM_COPY:
gwinfo = GETGWINFO(hWnd);
StGWCopyToClip(gwinfo);
return(0);
case IDM_PRINT:
gwinfo = GETGWINFO(hWnd);
StGWPrint(gwinfo);
break;
break;
}
break;
case WM_SIZE:
if (! IsIconic(hWnd)) {
gwinfo = GETGWINFO(hWnd);
if (gwinfo->hasHscroll) {
SetScrollRange(hWnd, SB_HORZ, 0, gwinfo->canvasWidth - LOWORD(lParam), TRUE);
}
else gwinfo->canvasWidth = LOWORD(lParam);
if (gwinfo->hasVscroll) {
SetScrollRange(hWnd, SB_VERT, 0, gwinfo->canvasHeight - HIWORD(lParam), TRUE);
}
else gwinfo->canvasHeight = HIWORD(lParam);
if (gwinfo->hasVscroll || gwinfo->hasHscroll)
StGWSetScroll(gwinfo, gwinfo->view_h, gwinfo->view_v, TRUE);
StGWObResize(GETWINOBJECT(hWnd));
}
// ### fix slot value
break;
case WM_MOVE:
// ### fix slot value
break;
case WM_VSCROLL:
case WM_HSCROLL:
{
int val, hval, vval, *incs;
gwinfo = GETGWINFO(hWnd);
val = (message == WM_HSCROLL) ? gwinfo->view_h : gwinfo->view_v;
incs = (message == WM_HSCROLL) ? gwinfo->h_scroll_inc : gwinfo->v_scroll_inc;
switch (GET_WM_VSCROLL_CODE(wParam,lParam)) {
case SB_LINEUP: val -= incs[0]; break;
case SB_LINEDOWN: val += incs[0]; break;
case SB_PAGEUP: val -= incs[1]; break;
case SB_PAGEDOWN: val += incs[1]; break;
case SB_TOP:
{
int nMin,nMax;
int scroll = (message == WM_HSCROLL) ? SB_HORZ : SB_VERT;
GetScrollRange(hWnd, scroll, &nMin, &nMax);
val = nMin;
break;
}
case SB_BOTTOM:
{
int nMin,nMax;
int scroll = (message == WM_HSCROLL) ? SB_HORZ : SB_VERT;
GetScrollRange(hWnd, scroll, &nMin, &nMax);
val = nMax;
break;
}
case SB_THUMBPOSITION: val = GET_WM_VSCROLL_POS(wParam,lParam); break;
}
hval = (message == WM_HSCROLL) ? val: gwinfo->view_h;
vval = (message == WM_HSCROLL) ? gwinfo->view_v : val;
StGWSetScroll(gwinfo, hval, vval, TRUE);
}
return(0);
case WM_CHAR:
StGWObDoKey(GETWINOBJECT(hWnd),
(unsigned char) wParam,
GetKeyState(VK_SHIFT),
GetKeyState(VK_CONTROL));
return(0);
#ifdef DODO
/**** These don't make any sense. Something like sending a symbol
or a logical key code to the application is needed */
case WM_KEYDOWN:
switch (wParam) {
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
case VK_END:
case VK_HOME:
case VK_PRIOR:
case VK_NEXT:
StGWObDoKey(GETWINOBJECT(hWnd),
(unsigned char) wParam,
GetKeyState(VK_SHIFT),
GetKeyState(VK_CONTROL));
break;
}
return(0);
#endif
case WM_MOUSEMOVE:
gwinfo = GETGWINFO(hWnd);
SetCursor(get_cursor(gwinfo->cursor));
if (! MouseCaptured) {
gwinfo->mouse_x = LOWORD(lParam);
gwinfo->mouse_y = HIWORD(lParam);
StGWObDoMouse(GETWINOBJECT(hWnd),
gwinfo->mouse_x + gwinfo->view_h,
gwinfo->mouse_y + gwinfo->view_v,
MouseMove,
(MouseClickModifier) 0);
}
else if (MouseWnd == hWnd && xldebug <= 0) { // ### move to WhileButtonDown?
if (gwinfo->mouse_x != LOWORD(lParam)
|| gwinfo->mouse_y != HIWORD(lParam)
|| ! MouseMotionOnly) {
gwinfo->mouse_x = LOWORD(lParam);
gwinfo->mouse_y = HIWORD(lParam);
if (MouseAction != NULL)
(*MouseAction)(hWnd,
gwinfo->mouse_x + gwinfo->view_h,
gwinfo->mouse_y + gwinfo->view_v);
}
}
return(0);
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
{
int mods = 2 * ((MK_CONTROL & wParam) ? 1 : 0) + ((MK_SHIFT & wParam) ? 1 : 0);
gwinfo = GETGWINFO(hWnd);
gwinfo->mouse_x = LOWORD(lParam);
gwinfo->mouse_y = HIWORD(lParam);
ReleaseMouse();
MouseWnd = hWnd; // to indicate button is down
StGWObDoMouse(GETWINOBJECT(hWnd),
gwinfo->mouse_x + gwinfo->view_h,
gwinfo->mouse_y + gwinfo->view_v,
MouseClick,
(MouseClickModifier) mods);
}
return(0);
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
ReleaseMouse();
return(0);
case WM_PAINT:
{
PAINTSTRUCT ps;
int left, top, width, height;
gwinfo = GETGWINFO(hWnd);
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
if (! gwinfo->initialized) {
gwinfo->initialized = TRUE;
SetHardwareState(gwinfo);
}
StGWGetViewRect(gwinfo, &left, &top, &width, &height);
StGWStartBuffering(gwinfo);
StGWObRedraw(GETWINOBJECT(hWnd));
StGWBufferToScreen(gwinfo, left, top, width, height);
return(0);
}
case WM_MDIACTIVATE:
{
LVAL menu = slot_value(GETWINOBJECT(hWnd), s_menu);
activating = GET_WM_MDIACTIVATE_FACTIVATE(hWnd, wParam, lParam);
if (menu != NIL) {
if (activating) send_callback_message(menu, sk_install);
else send_callback_message(menu, sk_remove);
}
}
return(0);
case WM_NCACTIVATE:
ReleaseMouse();
return(DefMDIChildProc(hWnd, message, wParam, lParam));
case WM_MOUSEACTIVATE:
if (activating && HTCLIENT == LOWORD(lParam))
return MA_ACTIVATEANDEAT;
else
return MA_ACTIVATE;
case WM_SETCURSOR:
activating = FALSE;
break;
case WM_CLOSE:
send_callback_message(GETWINOBJECT(hWnd), sk_close);
return(0);
case WM_DESTROY:
if (! Exiting) {
gwinfo = GETGWINFO(hWnd);
if (gwinfo) {
if (IViewInternalIsLinked(hWnd))
IViewUnlinkWindow(hWnd);
StGWObDoClobber(gwinfo->Object);
if (gwinfo->FreeMem)
(*gwinfo->FreeMem)(hWnd);
gwinfo->window = NULL;
}
}
return(0);
}
return(DefMDIChildProc(hWnd, message, wParam, lParam));
}
void StGWWhileButtonDown(StGWWinInfo *gwinfo, void (*action)(), int motionOnly)
{
MSG msg;
if (! gwinfo || ! gwinfo->window) return;
if (! MouseWnd) return; // checks if mouse is down
MouseAction = action;
MouseMotionOnly = motionOnly;
CaptureMouse((HWND) gwinfo->window);
while (MouseCaptured) {
if (PeekMessage(&msg, (HWND) gwinfo->window, 0, 0, PM_REMOVE)) {
if(! TranslateMDISysAccel(hWndClient, &msg)
&& ! TranslateAccelerator(hWndFrame, hAccel, &msg)) {
TTYFlushOutput();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if (! MouseMotionOnly && MouseAction && MouseCaptured) {
(*MouseAction)(gwinfo->window,
gwinfo->mouse_x + gwinfo->view_h,
gwinfo->mouse_y + gwinfo->view_v);
TTYFlushOutput();
}
}
ReleaseMouse(); // should have heppened already
}
void MSWResetGraphics(void)
{
ReleaseMouse();
StGWResetBuffer();
}
/**************************************************************************/
/** **/
/** Idle Action Functions **/
/** **/
/**************************************************************************/
int MSWAnyIdleActions(void)
{
LVAL next, object;
StGWWinInfo *gwinfo;
for (next = getvalue(s_hardware_objects); consp(next); next = cdr(next)) {
if (valid_iview_window_address(car(next))) {
object = car(cdr(cdr(car(next))));
gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
if (gwinfo && gwinfo->window
&& gwinfo->idleOn && ! IsIconic((HWND) gwinfo->window)) {
return TRUE;
}
}
}
return FALSE;
}
void MSWDoIdleActions(void)
{
LVAL next, object;
StGWWinInfo *gwinfo;
for (next = getvalue(s_hardware_objects); consp(next); next = cdr(next)) {
if (valid_iview_window_address(car(next))) {
object = car(cdr(cdr(car(next))));
gwinfo = (StGWWinInfo *) StGWObWinInfo(object);
if (gwinfo && gwinfo->window
&& gwinfo->idleOn && ! IsIconic((HWND) gwinfo->window)) {
StGWObDoIdle(object);
}
}
}
}
int StGWIdleOn(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->idleOn : FALSE);
}
void StGWSetIdleOn(StGWWinInfo *gwinfo, int on)
{
if (gwinfo) gwinfo->idleOn = on;
}
/**************************************************************************/
/** **/
/** Scrolling and Canvas Functions **/
/** **/
/**************************************************************************/
//**** not sure this is needed -- it probably duplicates stuff
static void ResetDCClipRect(HDC hDC, StGWWinInfo *gwinfo)
{
if (gwinfo->clipped) {
HRGN rgn;
rgn = CreateRectRgn(gwinfo->clip_rect.left - gwinfo->view_h,
gwinfo->clip_rect.top - gwinfo->view_v,
gwinfo->clip_rect.right - gwinfo->view_h,
gwinfo->clip_rect.bottom) - gwinfo->view_v;
SelectClipRgn(hDC, rgn);
DeleteObject(rgn);
}
}
int StGWCanvasWidth(StGWWinInfo *gwinfo) { return (gwinfo ? gwinfo->canvasWidth : 0); }
int StGWCanvasHeight(StGWWinInfo *gwinfo) { return (gwinfo ? gwinfo->canvasHeight : 0); }
int StGWHasVscroll(StGWWinInfo *gwinfo) { return (gwinfo ? gwinfo->hasVscroll : FALSE); }
int StGWHasHscroll(StGWWinInfo *gwinfo) { return (gwinfo ? gwinfo->hasHscroll : FALSE); }
void StGWSetHasVscroll(StGWWinInfo *gwinfo, int has, int size)
{
RECT r;
HWND w;
int height;
if (gwinfo && (w = gwinfo->window) != 0) {
GetClientRect((HWND) w, &r);
height = r.bottom - r.top;
gwinfo->hasVscroll = has;
gwinfo->canvasHeight = has ? size : height;
SetScrollRange((HWND) w, SB_VERT, 0, gwinfo->canvasHeight - height, TRUE);
StGWSetScroll(gwinfo, gwinfo->view_h, gwinfo->view_v, TRUE);
}
}
void StGWSetHasHscroll(StGWWinInfo *gwinfo, int has, int size)
{
RECT r;
HWND w;
int width;
if (gwinfo && (w = gwinfo->window) != 0) {
GetClientRect((HWND) w, &r);
width = r.right - r.left;
gwinfo->hasHscroll = has;
gwinfo->canvasWidth = has ? size : width;
SetScrollRange((HWND) w, SB_HORZ, 0, gwinfo->canvasWidth - width, TRUE);
StGWSetScroll(gwinfo, gwinfo->view_h, gwinfo->view_v, TRUE);
}
}
void StGWSetScroll(StGWWinInfo *gwinfo, int h, int v, int move)
#pragma argsused gwinfo h v
{
RECT r;
HWND w;
int width, height, hmax, vmax;
HDC hDC;
if (gwinfo && (w = gwinfo->window) != 0) {
GetClientRect((HWND) w, &r);
width = r.right - r.left;
height = r.bottom - r.top;
hmax = gwinfo->canvasWidth - width;
vmax = gwinfo->canvasHeight - height;
if (hmax < 0) hmax = 0;
if (vmax < 0) vmax = 0;
if (h < 0) h = 0; if (h > hmax) h = hmax;
if (v < 0) v = 0; if (v > vmax) v = vmax;
gwinfo->view_h = (gwinfo->hasHscroll) ? h : 0;
gwinfo->view_v = (gwinfo->hasVscroll) ? v : 0;
if (gwinfo->view_h != GetScrollPos((HWND) w, SB_HORZ))
SetScrollPos((HWND) w, SB_HORZ, gwinfo->view_h, TRUE);
if (gwinfo->view_v != GetScrollPos((HWND) w, SB_VERT))
SetScrollPos((HWND) w, SB_VERT, gwinfo->view_v, TRUE);
hDC = GET_DC(w);
SetViewportOrgEx(hDC, -gwinfo->view_h, -gwinfo->view_v, NULL);
ResetDCClipRect(hDC, gwinfo);
RELEASE_DC(w, hDC);
if (currentDC) {
SetViewportOrgEx(currentDC, -gwinfo->view_h, -gwinfo->view_v, NULL);
ResetDCClipRect(currentDC, gwinfo);
}
InvalidateRect((HWND) w, &r, FALSE);
}
}
void StGWGetScroll(StGWWinInfo *gwinfo, int *h, int *v)
{
if (gwinfo) {
if (h) *h = gwinfo->view_h;
if (v) *v = gwinfo->view_v;
}
}
void StGWSetHscrollIncs(StGWWinInfo *gwinfo, int inc, int pageInc)
{
if (gwinfo) {
gwinfo->h_scroll_inc[0] = inc;
gwinfo->h_scroll_inc[1] = pageInc;
}
}
void StGWGetHscrollIncs(StGWWinInfo *gwinfo, int *inc, int *pageInc)
{
if (gwinfo) {
if (inc) *inc = gwinfo->h_scroll_inc[0];
if (pageInc) *pageInc = gwinfo->h_scroll_inc[1];
}
}
void StGWSetVscrollIncs(StGWWinInfo *gwinfo, int inc, int pageInc)
{
if (gwinfo) {
gwinfo->v_scroll_inc[0] = inc;
gwinfo->v_scroll_inc[1] = pageInc;
}
}
void StGWGetVscrollIncs(StGWWinInfo *gwinfo, int *inc, int *pageInc)
{
if (gwinfo) {
if (inc) *inc = gwinfo->v_scroll_inc[0];
if (pageInc) *pageInc = gwinfo->v_scroll_inc[1];
}
}
void StGWGetViewRect(StGWWinInfo *gwinfo, int *left, int *top, int *width, int *height)
{
HWND w;
RECT r;
if (gwinfo && (w = gwinfo->window) != 0) {
GetClientRect((HWND) w, &r);
if (left) *left = r.left + gwinfo->view_h;
if (top) *top = r.top + gwinfo->view_v;
if (width) *width = r.right - r.left;
if (height) *height = r.bottom - r.top;
}
else {
if (left) *left = 0;
if (top) *top = 0;
if (width) *width = 1;
if (height) *height = 1;
}
}
/**************************************************************************/
/** **/
/** Cursor Functions **/
/** **/
/**************************************************************************/
#define NumBasicCursors 9
static int NumCursors;
typedef struct {
HCURSOR curs;
int created;
long refcon;
} cursor_entry;
static cursor_entry *curstab;
static HCURSOR get_cursor(unsigned int index)
{
if (index < NumCursors) return(curstab[index].curs);
else return(hArrowCursor);
}
void set_gc_cursor(int set)
{
if (set) hSaveCursor = SetCursor(hGCCursor);
else SetCursor(hSaveCursor);
}
static void init_msw_cursors(void)
{
NumCursors = NumBasicCursors;
curstab = (cursor_entry *) StCalloc(NumCursors, sizeof(cursor_entry));
curstab[ARROW_CURSOR].curs = hArrowCursor;
curstab[WATCH_CURSOR].curs = hWaitCursor;
curstab[CROSS_CURSOR].curs = hCrossCursor;
curstab[BRUSH_CURSOR].curs = hBrushCursor;
curstab[HAND_CURSOR].curs = hHandCursor;
curstab[FINGER_CURSOR].curs = hFingerCursor;
curstab[HOUR_GLASS_CURSOR].curs = hWaitCursor;
curstab[TRASH_BAG_CURSOR].curs = hGCCursor;
curstab[TRASH_CAN_CURSOR].curs = hGCCursor;
}
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(0L);
}
void StGWSetCursor(StGWWinInfo *gwinfo, int cursor)
{
if (gwinfo) gwinfo->cursor = cursor;
}
int StGWCursor(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->cursor : 0);
}
static int get_free_cursor_index(void)
{
char *temp;
int index;
for (index = 0;
index < NumCursors && curstab[index].curs != NULL;
index++);
if (index >= NumCursors) {
temp = realloc((char *) curstab, (NumCursors + 1) * sizeof(cursor_entry));
if (temp == NULL) return(-1);
curstab = (cursor_entry *) temp;
NumCursors++;
curstab[index].curs = NULL;
curstab[index].created = FALSE;
curstab[index].refcon = 0L;
}
return(index);
}
static char *make_bitmap_bits(char *image,
int width, int height,
int cwidth, int cheight,
int mask)
{
HBITMAP hbm = 0, oldbm;
BITMAP bm;
HDC bmDC, hDC;
char *bits = NULL;
int i, j, size;
hDC = GetDC(hWndFrame);
bmDC = CreateCompatibleDC(hDC);
ReleaseDC(hWndFrame, hDC);
if (bmDC) {
hbm = CreateBitmap(cwidth, cheight, 1, 1, NULL);
if (hbm) {
oldbm = SelectObject(bmDC, hbm);
PatBlt(bmDC, 0, 0, cwidth, cheight, WHITENESS);
if (image) {
PatBlt(bmDC, 0, 0, cwidth, cheight, mask ? WHITENESS : BLACKNESS);
PatBlt(bmDC, 0, 0, width, height, WHITENESS);
for (i = 0; i < height && i < cheight; i++)
for (j = 0; j < width && j < cwidth; j++)
if (image[i * width + j])
SetPixel(bmDC, j, i, 0);
}
else PatBlt(bmDC, 0, 0, width, height, BLACKNESS);
GetObject(hbm, sizeof(BITMAP), (LPSTR) &bm);
size = (int) bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
bits = StCalloc(size, 1);
if (bits) GetBitmapBits(hbm, size, bits);
SelectObject(bmDC, oldbm);
DeleteObject(hbm);
}
DeleteDC(bmDC);
}
return(bits);
}
static void free_bitmap_bits(char *bits)
{
if (bits) StFree(bits);
}
int StGWMakeCursor(int n, char *image, char *mask, int h, int v, long refcon)
{
int index, cwidth, cheight, i;
char *imageBits, *maskBits;
HCURSOR hc = 0;
index = get_free_cursor_index();
if (index < 0) return(-1);
cwidth = GetSystemMetrics(SM_CXCURSOR);
cheight = GetSystemMetrics(SM_CYCURSOR);
if (mask && image)
for (i = 0; i < n * n; i++)
if (! mask[i]) image[i] = 1;
imageBits = make_bitmap_bits(image, n, n, cwidth, cheight, FALSE);
maskBits = make_bitmap_bits(mask, n, n, cwidth, cheight, TRUE);
if (imageBits && maskBits)
hc = CreateCursor(hInst, h, v, cwidth, cheight, maskBits, imageBits);
free_bitmap_bits(imageBits);
free_bitmap_bits(maskBits);
if (! hc) return(-1);
curstab[index].curs = hc;
curstab[index].created = TRUE;
curstab[index].refcon = refcon;
return(index);
}
int StGWMakeResCursor(char *name, int num, long refcon)
{
int index;
char *cname = NULL;
long resnum = 0;
LVAL arg;
if (name) return(-1);
else if (! num) return(-1);
else {
arg = xlgetarg();
if (stringp(arg)) cname = (char *) getstring(arg);
else if (fixp(arg)) resnum = getfixnum(arg);
else return(-1);
index = get_free_cursor_index();
if (index < 0) return(-1);
curstab[index].curs = LoadCursor((HINSTANCE) num, cname ? cname : MAKEINTRESOURCE(resnum));
if (curstab[index].curs) curstab[index].refcon = refcon;
else return(-1);
}
return(index);
}
void StGWFreeCursor(unsigned int index)
{
if (index < NumCursors && index >= NumBasicCursors) {
if (curstab[index].curs != NULL && curstab[index].created)
DestroyCursor(curstab[index].curs);
curstab[index].curs = 0;
curstab[index].refcon = 0;
curstab[index].created = FALSE;
}
else xlfail("can't free standard cursor");
}
/**************************************************************************/
/** **/
/** Color Functions **/
/** **/
/**************************************************************************/
#define NumBasicColors 8
#define NumRGBColors 256
# define CMULT 255
static int NumColors;
typedef struct {
unsigned long rgb;
long refcon;
} ctab_entry;
static ctab_entry *ctable;
static void init_msw_colors(void)
{
NumColors = NumBasicColors;
if (StScreenHasColor()) NumColors += NumRGBColors;
ctable = (ctab_entry *) StCalloc(NumColors, sizeof(ctab_entry));
ctable[0].rgb = RGB(255, 255, 255); // white
ctable[1].rgb = RGB( 0, 0, 0); // black
ctable[2].rgb = RGB(255, 0, 0); // red
ctable[3].rgb = RGB( 0, 255, 0); // green
ctable[4].rgb = RGB( 0, 0, 255); // blue
ctable[5].rgb = RGB( 0, 255, 255); // cyan
ctable[6].rgb = RGB(255, 0, 255); // magenta
ctable[7].rgb = RGB(255, 255, 0); // yellow
}
void StGWSetColRefCon(unsigned int index, long rc)
{
if (index < NumColors) ctable[index].refcon = rc;
}
long StGWGetColRefCon(unsigned int index)
{
if (index < NumColors) return(ctable[index].refcon);
else return(0L);
}
int StGWMakeColor(double red, double green, double blue, long refcon)
{
int index;
for (index = NumBasicColors;
index < NumColors && StGWGetColRefCon(index) != 0;
index++);
if (index >= NumColors) return(-1);
else {
StGWSetColRefCon(index, refcon);
ctable[index].rgb = RGB(CMULT * red, CMULT * green, CMULT * blue);
return(index);
}
}
void StGWFreeColor(unsigned int index)
{
if (index < NumColors && index >= NumBasicColors)
StGWSetColRefCon(index, 0);
else xlfail("can't free standard color");
}
static unsigned long get_color(unsigned int index)
{
if (index < NumColors) return(ctable[index].rgb);
else return(ctable[1].rgb);
}
int StGWUseColor(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->use_color : FALSE);
}
ColorCode StGWDrawColor(StGWWinInfo *gwinfo)
{
return ((ColorCode) (gwinfo ? gwinfo->drawColor : 1));
}
ColorCode StGWBackColor(StGWWinInfo *gwinfo)
{
return ((ColorCode) (gwinfo ? gwinfo->backColor : 0));
}
void StGWSetUseColor(StGWWinInfo *gwinfo, int use)
{
if (gwinfo) {
gwinfo->use_color = use;
if (! colorBuffBits) gwinfo->use_color = FALSE;
}
}
void StGWSetDrawColor(StGWWinInfo *gwinfo, ColorCode color)
{
HDC hDC;
if (gwinfo) {
if (color < NumColors) gwinfo->drawColor = color;
gwinfo->drawPen.lopnColor = get_color(color);
if (gwinfo->window) {
hDC = GetDC((HWND) gwinfo->window);
SetTextColor(hDC, get_color(color));
ReleaseDC((HWND) gwinfo->window, hDC);
if (currentDC) SetTextColor(currentDC, get_color(color));
}
}
}
void StGWSetBackColor(StGWWinInfo *gwinfo, ColorCode color)
{
HDC hDC;
if (gwinfo) {
if (color < NumColors) gwinfo->backColor = color;
if (gwinfo->window) {
hDC = GetDC((HWND) gwinfo->window);
SetBkColor(hDC, get_color(color));
ReleaseDC((HWND) gwinfo->window, hDC);
if (currentDC) SetBkColor(currentDC, get_color(color));
}
}
}
/**************************************************************************/
/** **/
/** Drawing State Functions **/
/** **/
/**************************************************************************/
int StGWDrawMode(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->drawMode : 0);
}
int StGWLineType(StGWWinInfo *gwinfo)
{
return(gwinfo ? gwinfo->lineType : 0);
}
void StGWGetLineWidth(StGWWinInfo *gwinfo, int *width)
{
if (gwinfo && width) *width = gwinfo->lineWidth;
}
void StGWSetDrawMode(StGWWinInfo *gwinfo, int mode)
{
HDC hDC;
if (gwinfo) {
gwinfo->drawMode = mode;
if (gwinfo->window) {
hDC = GetDC((HWND) gwinfo->window);
SetROP2(hDC, gwinfo->drawMode ? R2_NOT : R2_COPYPEN);
ReleaseDC((HWND) gwinfo->window, hDC);
if (currentDC)
SetROP2(currentDC, gwinfo->drawMode ? R2_NOT : R2_COPYPEN);
}
}
}
void StGWSetLineType(StGWWinInfo *gwinfo, int type)
{
if (gwinfo) {
gwinfo->lineType = type ? 1 : 0;
gwinfo->drawPen.lopnStyle = type ? PS_DOT : PS_SOLID;
}
}
void StGWSetLineWidth(StGWWinInfo *gwinfo, int width)
{
if (gwinfo) {
gwinfo->lineWidth = (width > 0) ? width : 1;
gwinfo->rect_offset = width / 2;
gwinfo->drawPen.lopnWidth.x = (width > 1) ? width : 1;
}
}
int StGWGetClipRect(StGWWinInfo *gwinfo,
int *pleft, int *ptop, int *pwidth, int *pheight)
{
if (gwinfo == NULL) return(FALSE);
if (gwinfo->clipped) {
if (pleft) *pleft = gwinfo->clip_rect.left;
if (ptop) *ptop = gwinfo->clip_rect.top;
if (pwidth) *pwidth = gwinfo->clip_rect.right - gwinfo->clip_rect.left;
if (pheight) *pheight = gwinfo->clip_rect.bottom - gwinfo->clip_rect.top;
}
return(gwinfo->clipped);
}
// ### fix
void StGWSetClipRect(StGWWinInfo *gwinfo, int clipping,
int left, int top, int width, int height)
{
HDC hDC;
HRGN rgn;
int right, bottom;
if (gwinfo) {
if (clipping) {
right = left + width;
bottom = top + height;
}
else {
left = 0;
top = 0;
right = gwinfo->canvasWidth;
right = gwinfo->canvasHeight;
}
gwinfo->clipped = clipping;
gwinfo->clip_rect.left = left;
gwinfo->clip_rect.top = top;
gwinfo->clip_rect.right = right;
gwinfo->clip_rect.bottom = bottom;
left -= gwinfo->view_h;
top -= gwinfo->view_v;
right -= gwinfo->view_h;
bottom -= gwinfo->view_v;
hDC = GetDC((HWND) gwinfo->window);
rgn = CreateRectRgn(left, top, right, bottom); /***** error check */
SelectClipRgn(hDC, rgn);
ReleaseDC((HWND) gwinfo->window, hDC);
if (currentDC) SelectClipRgn(currentDC, rgn);
DeleteObject(rgn);
}
}
/**************************************************************************/
/** **/
/** Buffer Functions **/
/** **/
/**************************************************************************/
void init_msw_buffer(void)
{
HDC hDC;
int width, height;
StGetScreenSize(&width, &height);
hDC = GetDC(hWndFrame);
if (StScreenHasColor() && ! xlisp_mono) {
colorBuffBits = CreateCompatibleBitmap(hDC, width, height);
if (! colorBuffBits) {
WarningBox("Can't allocate color buffer");
}
}
ReleaseDC(hWndFrame, hDC);
monoBuffBits = CreateBitmap(width, height, 1, 1, NULL);
if (! monoBuffBits) {
WarningBox("Can't allocate monochrome buffer");
xexit();
}
}
static void init_dc(StGWWinInfo *gwinfo, HDC bufferDC, int buffer)
{
HBRUSH hbr;
RECT r;
SetBkMode(bufferDC, TRANSPARENT);
SetBkColor(bufferDC, get_color(gwinfo->backColor));
SetTextColor(bufferDC, get_color(gwinfo->drawColor));
SelectObject(bufferDC, hGraphFont);
SetROP2(bufferDC, gwinfo->drawMode ? R2_NOT : R2_COPYPEN);
SetPolyFillMode(bufferDC, WINDING);
if (buffer)
SetViewportOrgEx(bufferDC, -gwinfo->view_h, -gwinfo->view_v, NULL);
ResetDCClipRect(bufferDC, gwinfo);
if (buffer) {
GetClientRect((HWND) gwinfo->window, &r);
r.left += gwinfo->view_h; r.top += gwinfo->view_v;
r.right += gwinfo->view_h; r.bottom += gwinfo->view_v;
}
else {
r.left = r.top = 0;
r.right = gwinfo->canvasWidth;
r.bottom = gwinfo->canvasHeight;
}
hbr = GET_ERASE_BRUSH(gwinfo);
FillRect(bufferDC, &r, hbr);
RELEASE_BRUSH(hbr);
}
void StGWStartBuffering(StGWWinInfo *gwinfo)
{
HDC hDC;
if (gwinfo && gwinfo->window) {
if (! buffering) {
StGWResetBuffer();
buffering = TRUE;
hDC = GetDC((HWND) gwinfo->window);
bufferDC = CreateCompatibleDC(hDC);
ReleaseDC((HWND) gwinfo->window, hDC);
SelectObject(bufferDC, (gwinfo->use_color && colorBuffBits) ? colorBuffBits : monoBuffBits);
init_dc(gwinfo, bufferDC, TRUE);
currentDC = bufferDC;
}
bufflevel++;
}
}
void StGWBufferToScreen(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
HDC hDC;
if (gwinfo && gwinfo->window) {
if (--bufflevel <= 0 && buffering) {
hDC = GetDC((HWND) gwinfo->window);
if (! gwinfo->use_color) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
}
BitBlt(hDC, left, top, width, height, currentDC, left, top, SRCCOPY);
if (! gwinfo->use_color) {
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
ReleaseDC((HWND) gwinfo->window, hDC);
StGWResetBuffer();
}
}
}
void StGWResetBuffer(void)
{
bufflevel = 0;
buffering = FALSE;
currentDC = 0;
if (bufferDC) {
DeleteDC(bufferDC);
bufferDC = 0;
}
}
// ### fix
void StGWDumpImage(StGWWinInfo *gwinfo, FILEP file, double scale)
{
xlfail("not supported yet");
}
#ifdef WIN32
static int GetPrinterDC(HDC *pdc)
{
static PRINTDLG pd = { sizeof (PRINTDLG) } ;
/* Show the Print dialog box and get printer DC */
pd.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION
| PD_USEDEVMODECOPIESANDCOLLATE;
if (!PrintDlg (&pd))
return FALSE;
else {
*pdc = pd.hDC;
return TRUE;
}
}
static int PrintEMF(HDC printerDC, HENHMETAFILE hemf)
{
static DOCINFO di = { sizeof (DOCINFO), TEXT ("EmfView: Printing") } ;
ENHMETAHEADER emh;
int play_success, print_success, width, height, dwidth, dheight;
RECT r;
double hScale, vScale, scale;
/* get the metafile header */
GetEnhMetaFileHeader(hemf, sizeof(emh), &emh);
/* Calculate the scale factor */
dwidth = GetDeviceCaps(printerDC, HORZRES);
width = emh.rclBounds.right - emh.rclBounds.left;
if (width > 0) hScale = (double) dwidth / width;
else hScale = 1.0;
dheight = GetDeviceCaps(printerDC, VERTRES);
height = emh.rclBounds.bottom - emh.rclBounds.top;
if (height > 0) vScale = (double) dheight/ height;
else vScale = 1.0;
scale = hScale > vScale ? vScale : hScale;
if (scale > 1.0) scale = floor(scale);
/* Set the display rectangle */
/***** add margins? */
width = scale * width;
height = scale * height;
r.left = (dwidth - width) / 2;
r.top = (dheight - height) / 2;
r.right = r.left + width;
r.bottom = r.top + height;
/* Play the EMF to the printer */
/**** save current cursor and set up wait cursor */
print_success = FALSE;
if ((StartDoc(printerDC, &di) > 0) && (StartPage(printerDC) > 0)) {
play_success = PlayEnhMetaFile (printerDC, hemf, &r);
if (EndPage(printerDC) > 0) {
print_success = TRUE;
EndDoc(printerDC) ;
}
}
/**** restore original cursor */
return play_success;
}
#endif /* WIN32 */
static void StGWPrint(StGWWinInfo *gwinfo)
{
#ifdef WIN32
/***** need to figure out how to disable for win32s */
if (gwinfo && gwinfo->window) {
HDC printerDC;
HENHMETAFILE hEMF;
int success;
/* Show the Print dialog box and get printer DC */
if (! GetPrinterDC(&printerDC))
return;
if (printerDC == NULL)
xlfail("Can't get printer DC");
/* Draw the graph into an enhanced metafile */
{
CONTEXT cntxt, *target;
int jumping, mask;
LVAL val;
xlbegin(&cntxt,CF_UNWIND,NIL);
if (XL_SETJMP(cntxt.c_jmpbuf)) {
target = xltarget;
mask = xlmask;
val = xlvalue;
jumping = TRUE;
}
else {
target = NULL;
mask = 0;
val = NIL;
jumping = FALSE;
/* protected code */
if (buffering) xlfail("already buffering");
StGWResetBuffer();
bufferDC = CreateEnhMetaFile(NULL, NULL, NULL, NULL);
if (bufferDC == NULL) xlfail("can't create meta file");
init_dc(gwinfo, bufferDC, FALSE);
currentDC = bufferDC;
buffering = TRUE;
bufflevel++;
StGWObRedraw(GETWINOBJECT(gwinfo->window));
}
xlend(&cntxt);
/* cleanup code */
if (bufferDC != NULL) hEMF = CloseEnhMetaFile(bufferDC);
bufferDC = 0;
StGWResetBuffer();
if (jumping) DeleteDC(printerDC);
if (hEMF == NULL) xlfail("failed to close metafile properly");
if (jumping) xljump(target, mask, val);
}
success = PrintEMF(printerDC, hEMF);
DeleteDC (printerDC);
DeleteEnhMetaFile(hEMF);
if (! success) xlfail("printing failed");
}
#endif /* WIN32 */
}
/**************************************************************************/
/** **/
/** Basic Drawing Functions **/
/** **/
/**************************************************************************/
void StGWDrawPoint(StGWWinInfo *gwinfo, int x, int y)
{
HWND w;
HDC hDC;
HPEN oldPen;
int oldWidth;
if (gwinfo && (w = gwinfo->window) != 0) {
oldWidth = gwinfo->drawPen.lopnWidth.x;
gwinfo->drawPen.lopnWidth.x = 1;
hDC = GET_DC(w);
oldPen = SET_PEN(hDC, gwinfo);
MoveToEx(hDC, x, y, NULL);
LineTo(hDC, x + 1, y + 1);
RESTORE_PEN(hDC, oldPen);
RELEASE_DC(w, hDC);
gwinfo->drawPen.lopnWidth.x = oldWidth;
}
}
void StGWDrawLine(StGWWinInfo *gwinfo, int x1, int y1, int x2, int y2)
{
HWND w;
HDC hDC;
HPEN oldPen;
if (gwinfo && (w = gwinfo->window) != 0) {
hDC = GET_DC(w);
oldPen = SET_PEN(hDC, gwinfo);
MoveToEx(hDC, x1, y1, NULL);
LineTo(hDC, x2, y2);
RESTORE_PEN(hDC, oldPen);
RELEASE_DC(w, hDC);
}
}
void StGWFrameRect(StGWWinInfo *gwinfo, int left, int top, int width, int height)
{
HDC hDC;
HPEN oldPen;
HBRUSH oldBrush;
if (gwinfo && gwinfo->window) {
hDC = GET_DC(gwinfo->window);
oldPen = SET_PEN(hDC, gwinfo);
oldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
if (gwinfo->lineWidth != 1) {
left += gwinfo->rect_offset;
top += gwinfo->rect_offset;
width += 1 - gwinfo->lineWidth;
height += 1 - gwinfo->lineWidth;
}
Rectangle(hDC, left, top, left + width, top + height);
SelectObject(hDC, oldBrush);
RESTORE_PEN(hDC, oldPen);
RELEASE_DC(gwinfo->window, hDC);
}
}
static void fill_rect(StGWWinInfo *gwinfo, int which,
int left, int top, int width, int height)
{
HDC hDC;
RECT r;
HBRUSH hbr;
if (gwinfo && gwinfo->window) {
r.left = left; r.top = top;
r.right = left + width; r.bottom = top + height;
hDC = GET_DC(gwinfo->window);
hbr = (which == 'P') ? GET_DRAW_BRUSH(gwinfo) : GET_ERASE_BRUSH(gwinfo);
FillRect(hDC, &r, hbr);
RELEASE_BRUSH(hbr);
RELEASE_DC(gwinfo->window, hDC);
}
}
void StGWPaintRect(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
fill_rect(gwinfo, 'P', left, top, width, height);
}
void StGWEraseRect(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
fill_rect(gwinfo, 'E', left, top, width, height);
}
static void draw_oval(StGWWinInfo *gwinfo, int which,
int left, int top, int width, int height)
{
HDC hDC;
HPEN oldPen;
HBRUSH oldBrush;
if (gwinfo && gwinfo->window) {
hDC = GET_DC(gwinfo->window);
if (which == 'F') {
oldPen = SET_PEN(hDC, gwinfo);
oldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
if (gwinfo->lineWidth != 1) {
left += gwinfo->rect_offset;
top += gwinfo->rect_offset;
width += 1 - gwinfo->lineWidth;
height += 1 - gwinfo->lineWidth;
}
}
else {
oldPen = SelectObject(hDC, GetStockObject(NULL_PEN));
oldBrush = SelectObject(hDC, (which == 'P') ? GET_DRAW_BRUSH(gwinfo) : GET_ERASE_BRUSH(gwinfo));
width++; // make up for some deficiency in filling
height++; // make up for some deficiency in filling
}
Ellipse(hDC, left, top, left + width, top + height);
if (which == 'F') {
SelectObject(hDC, oldBrush);
RESTORE_PEN(hDC, oldPen);
}
else {
RESTORE_BRUSH(hDC, oldBrush);
SelectObject(hDC, oldPen);
}
RELEASE_DC(gwinfo->window, hDC);
}
}
void StGWFrameOval(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
draw_oval(gwinfo, 'F', left, top, width, height);
}
void StGWPaintOval(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
draw_oval(gwinfo, 'P', left, top, width, height);
}
void StGWEraseOval(StGWWinInfo *gwinfo,
int left, int top, int width, int height)
{
draw_oval(gwinfo, 'E', left, top, width, height);
}
static POINT angle_to_point(double angle,
int left, int top, int width, int height)
{
static double deg2rad = 3.14159 / 180.0;
double c = cos(deg2rad * angle), s = sin(deg2rad * angle);
int radius = (width > height) ? width : height;
POINT pt;
pt.x = left + width / 2 + radius * c;
pt.y = top + height / 2 - radius * s;
return(pt);
}
static void draw_arc(StGWWinInfo *gwinfo, int which,
int left, int top, int width, int height,
double angle1, double angle2)
{
HDC hDC;
HPEN oldPen;
HBRUSH oldBrush;
POINT a1, a2;
a1 = angle_to_point(angle1, left, top, width, height);
a2 = angle_to_point(angle1 + angle2, left, top, width, height);
if (gwinfo && gwinfo->window) {
hDC = GET_DC(gwinfo->window);
if (which == 'F') {
oldPen = SET_PEN(hDC, gwinfo);
oldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
if (gwinfo->lineWidth != 1) {
left += gwinfo->rect_offset;
top += gwinfo->rect_offset;
width += 1 - gwinfo->lineWidth;
height += 1 - gwinfo->lineWidth;
}
}
else {
oldPen = SelectObject(hDC, GetStockObject(NULL_PEN));
oldBrush = SelectObject(hDC, (which == 'P') ? GET_DRAW_BRUSH(gwinfo) : GET_ERASE_BRUSH(gwinfo));
width++; // make up for some deficiency in filling
height++; // make up for some deficiency in filling
}
if (which == 'F')
Arc(hDC, left, top, left + width, top + height, a1.x, a1.y, a2.x, a2.y);
else
Pie(hDC, left, top, left + width, top + height, a1.x, a1.y, a2.x, a2.y);
if (which == 'F') {
SelectObject(hDC, oldBrush);
RESTORE_PEN(hDC, oldPen);
}
else {
RESTORE_BRUSH(hDC, oldBrush);
SelectObject(hDC, oldPen);
}
RELEASE_DC(gwinfo->window, hDC);
}
}
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 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);
}
static void draw_poly(StGWWinInfo *gwinfo, int which, int n, short *p,
int from_origin)
{
HDC hDC;
HPEN oldPen;
HBRUSH oldBrush;
int i;
POINT *P;
if (! from_origin) {
for (i = 1; i < n; i++) {
p[2 * i] += p[2 * (i - 1)];
p[2 * i + 1] += p[2 * (i - 1) + 1];
}
}
if (gwinfo && gwinfo->window) {
P = (POINT *) ((n > 0) ? StCalloc(n, sizeof(POINT)) : NULL);
for (i = 0; i < n; i++) {
P[i].x = p[2 * i];
P[i].y = p[2 * i + 1];
}
hDC = GET_DC(gwinfo->window);
if (which == 'F') {
oldPen = SET_PEN(hDC, gwinfo);
oldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH));
}
else {
oldPen = SelectObject(hDC, GetStockObject(NULL_PEN));
oldBrush = SelectObject(hDC, (which == 'P') ? GET_DRAW_BRUSH(gwinfo) : GET_ERASE_BRUSH(gwinfo));
}
if (which == 'F') Polyline(hDC, P, n);
else Polygon(hDC, P, n);
if (which == 'F') {
SelectObject(hDC, oldBrush);
RESTORE_PEN(hDC, oldPen);
}
else {
RESTORE_BRUSH(hDC, oldBrush);
SelectObject(hDC, oldPen);
}
RELEASE_DC(gwinfo->window, hDC);
StFree(P);
}
}
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);
}
void StGWErasePoly(StGWWinInfo *gwinfo, int n, short *p, int from_origin)
{
draw_poly(gwinfo, 'E', n, p, from_origin);
}
/**************************************************************************/
/** **/
/** Text Functions **/
/** **/
/**************************************************************************/
static HDC charDC = 0, upcharDC = 0;
static HBITMAP charBits = 0, upcharBits = 0;
static int charSize = 0;
static void init_msw_text(void)
{
HFONT oldFont;
HDC hDC;
LOGFONT lf;
POINT pt;
memset(&lf, 0, sizeof(LOGFONT));
GetPrivateProfileString(graphicsSection, "Font", "Courier New",
lf.lfFaceName, LF_FACESIZE, iniFile);
pt.y = -GetPrivateProfileInt(graphicsSection, "FontSize", 11, iniFile);
hDC = GetDC(hWndFrame);
/* convert specified point size to pixels */
pt.y = (pt.y * GetDeviceCaps(hDC, LOGPIXELSY)) / 72;
DPtoLP(hDC, &pt, 1);
lf.lfHeight = pt.y;
hGraphFont = CreateFontIndirect(&lf);
oldFont = SelectObject(hDC, hGraphFont);
GetTextMetrics(hDC, &tm);
SelectObject(hDC, oldFont);
if (tm.tmPitchAndFamily & TMPF_TRUETYPE) {
/* rotate 90 degrees for drawing up */
lf.lfEscapement = lf.lfOrientation = 900;
hGraphFontUp = CreateFontIndirect(&lf);
}
else hGraphFontUp = NULL;
charDC = CreateCompatibleDC(hDC);
upcharDC = CreateCompatibleDC(hDC);
ReleaseDC(hWndFrame, hDC);
charSize = (tm.tmHeight > tm.tmAveCharWidth) ? tm.tmHeight : tm.tmAveCharWidth;
charBits = CreateBitmap(charSize, charSize, 1, 1, NULL);
upcharBits = CreateBitmap(charSize, charSize, 1, 1, NULL);
SelectObject(charDC, charBits);
SelectObject(charDC, hGraphFont);
SelectObject(upcharDC, upcharBits);
SelectObject(upcharDC, hGraphFont);
}
static void cleanup_msw_text(void)
{
if (charDC) {
DeleteDC(charDC);
charDC = 0;
}
if (upcharDC) {
DeleteDC(upcharDC);
upcharDC = 0;
}
if (charBits) {
DeleteObject(charBits);
charBits = 0;
}
if (upcharBits) {
DeleteObject(upcharBits);
upcharBits = 0;
}
if (hGraphFont)
DeleteObject(hGraphFont);
if (hGraphFontUp)
DeleteObject(hGraphFontUp);
}
static void draw_char(char ch, int x, int y, HDC hDC, int mode)
{
if (mode) {
PatBlt(charDC, 0, 0, charSize, charSize, WHITENESS);
TextOut(charDC, 0, 0, &ch, 1);
BitBlt(hDC, x, y, charSize, charSize, charDC, 0, 0, 0x990066L);
}
else {
int bkm = SetBkMode(hDC, TRANSPARENT);
TextOut(hDC, x, y, &ch, 1);
SetBkMode(hDC, bkm);
}
}
static void draw_char_up(char ch, int x, int y, HDC hDC, int mode)
{
if (hGraphFontUp) {
HFONT hfontOld;
/* offsets of 1 seem to be needed to mach bitmap results */
x++;
y++;
if (mode) {
hfontOld = SelectObject(charDC, hGraphFontUp);
PatBlt(charDC, 0, 0, charSize, charSize, WHITENESS);
TextOut(charDC, 0, tm.tmAveCharWidth, &ch, 1);
BitBlt(hDC, x, y, charSize, charSize, charDC, 0, 0, 0x990066L);
SelectObject(charDC, hfontOld);
}
else {
hfontOld = SelectObject(hDC, hGraphFontUp);
draw_char(ch, x, y, hDC, mode);
SelectObject(hDC, hfontOld);
}
}
else {
int i, j;
HDC targetDC;
COLORREF dc;
targetDC = mode ? upcharDC : hDC;
dc = mode ? 0 : GetTextColor(hDC);
PatBlt(charDC, 0, 0, charSize, charSize, WHITENESS);
TextOut(charDC, 0, 0, &ch, 1);
if (mode)
PatBlt(upcharDC, 0, 0, charSize, charSize, WHITENESS);
for (i = 0; i < tm.tmAveCharWidth; i++)
for (j = 0; j < tm.tmHeight; j++)
if (GetPixel(charDC, i, j) == 0)
SetPixel(targetDC, x + j, y + tm.tmAveCharWidth - i, dc);
if (mode)
BitBlt(hDC, x, y, charSize, charSize, upcharDC, 0, 0, 0x990066L);
}
}
void StGWDrawString(StGWWinInfo *gwinfo, char *s, int x, int y)
{
HDC hDC;
HWND w;
if (s && gwinfo && (w = gwinfo->window) != 0) {
hDC = GET_DC(w);
y -= tm.tmAscent;
SelectObject(hDC, hGraphFont); // **** why is this needed??
if (gwinfo->drawMode) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
for (; *s != '\0'; s++, x += tm.tmAveCharWidth)
draw_char(*s, x, y, hDC, gwinfo->drawMode);
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
else {
int bkm = SetBkMode(hDC, TRANSPARENT);
TextOut(hDC, x, y, s, strlen(s));
SetBkMode(hDC, bkm);
}
RELEASE_DC(w, hDC);
}
}
void StGWDrawStringUp(StGWWinInfo *gwinfo, char *s, int x, int y)
{
HDC hDC;
HWND w;
if (s && gwinfo && (w = gwinfo->window) != 0) {
hDC = GET_DC(w);
x -= tm.tmAscent;
if (gwinfo->drawMode || hGraphFontUp == NULL)
y -= tm.tmAveCharWidth;
if (gwinfo->drawMode) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
}
for (; *s != '\0'; s++, y -= tm.tmAveCharWidth)
draw_char_up(*s, x, y, hDC, gwinfo->drawMode);
if (gwinfo->drawMode) {
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
RELEASE_DC(w, hDC);
}
}
int StGWTextAscent(StGWWinInfo *gwinfo)
#pragma argsused
{
return(tm.tmAscent);
}
int StGWTextDescent(StGWWinInfo *gwinfo)
#pragma argsused
{
return(tm.tmDescent);
}
int StGWTextWidth(StGWWinInfo *gwinfo, char *text)
#pragma argsused text
{
return(text ? strlen(text) * tm.tmAveCharWidth : 0);
}
void StGWDrawText(StGWWinInfo *gwinfo,
char *text,
int x, int y, int h, int v)
{
int FontAscent, string_width;
if (text && gwinfo) {
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);
}
}
void StGWDrawTextUp(StGWWinInfo *gwinfo,
char *text,
int x, int y, int h, int v)
{
int FontAscent, string_width;
if (text && gwinfo) {
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 {
HBITMAP map;
HDC hDC;
int left, top, width, height;
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(0);
}
static void InitSymbol(int sym, int left, int top, int width, int height)
{
HDC hDC;
hDC = GetDC(hWndFrame);
Symbols[sym].hDC = CreateCompatibleDC(hDC);
ReleaseDC(hWndFrame, hDC);
Symbols[sym].map = CreateBitmap(width, height, 1, 1, NULL);
SelectObject(Symbols[sym].hDC, Symbols[sym].map);
PatBlt(Symbols[sym].hDC, 0, 0, width, height, WHITENESS);
Symbols[sym].left = left;
Symbols[sym].top = top;
Symbols[sym].width = width;
Symbols[sym].height = height;
}
void StGWGetSymbolSize(int sym, int *pwidth, int *pheight)
{
if (pwidth) *pwidth = Symbols[sym].width;
if (pheight) *pheight = Symbols[sym].height;
}
static void SetSymbolData(int sym, int row,
int bit0, int bit1, int bit2, int bit3, int bit4)
{
if (bit0) SetPixel(Symbols[sym].hDC, row, 0, 0);
if (bit1) SetPixel(Symbols[sym].hDC, row, 1, 0);
if (bit2) SetPixel(Symbols[sym].hDC, row, 2, 0);
if (bit3) SetPixel(Symbols[sym].hDC, row, 3, 0);
if (bit4) SetPixel(Symbols[sym].hDC, row, 4, 0);
}
static void init_msw_symbols(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);
}
static void cleanup_msw_symbols(void)
{
int i;
for (i = 0; i < NUMSYMBOLS; i++) {
if (Symbols[i].hDC) {
DeleteDC(Symbols[i].hDC);
Symbols[i].hDC = 0;
}
if (Symbols[i].map) {
DeleteObject(Symbols[i].map);
Symbols[i].map = 0;
}
}
}
void StGWDrawSymbol(StGWWinInfo *gwinfo, int sym, int x, int y)
{
HDC hDC;
if (gwinfo && gwinfo->window && sym >= 0 && sym < NUMSYMBOLS) {
hDC = GET_DC(gwinfo->window);
x -= Symbols[sym].left;
y -= Symbols[sym].top;
if (gwinfo->drawMode) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
BitBlt(hDC, x, y, Symbols[sym].width, Symbols[sym].height,
Symbols[sym].hDC, 0, 0, 0x990066L);
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
else if (! buffering || gwinfo->use_color || gwinfo->backColor == 0)
BitBlt(hDC, x, y, Symbols[sym].width, Symbols[sym].height,
Symbols[sym].hDC, 0, 0, SRCCOPY);
else
BitBlt(hDC, x, y, Symbols[sym].width, Symbols[sym].height,
Symbols[sym].hDC, 0, 0, NOTSRCCOPY);
RELEASE_DC(gwinfo->window, hDC);
}
}
void StGWReplaceSymbol(StGWWinInfo *gwinfo,
unsigned oldsym, unsigned newsym,
int x, int y)
{
int oldwidth, oldheight, newwidth, newheight;
if (oldsym < NUMSYMBOLS && newsym < NUMSYMBOLS) {
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);
}
}
/**************************************************************************/
/** **/
/** Miscellaneous Functions **/
/** **/
/**************************************************************************/
void StGWSetFreeMem(StGWWinInfo *gwinfo, void (*FreeMem)(HWND))
{
if (gwinfo) gwinfo->FreeMem = FreeMem;
}
void StGWShowWindow(StGWWinInfo *gwinfo)
{
HWND w;
if (gwinfo && (w = gwinfo->window) != 0) {
StShowWindow(w);
if (! gwinfo->initialized) StGWInitialDraw(gwinfo);
}
}
void StGWSetSize(StGWWinInfo *gwinfo, int width, int height, int frame)
{
if (gwinfo && gwinfo->window)
StWSetSize(gwinfo->window, width, height, frame);
}
StGWWinInfo *IViewWindowWinInfo(HWND w)
{
return(w ? (StGWWinInfo *) GETGWINFO(w) : NULL);
}
void StGWInitialDraw(StGWWinInfo *gwinfo)
{
int left, top, width, height;
if (gwinfo) {
gwinfo->initialized = TRUE;
SetHardwareState(gwinfo);
StGWObResize(gwinfo->Object);
StGWGetViewRect(gwinfo, &left, &top, &width, &height);
StGWStartBuffering(gwinfo);
StGWObRedraw(gwinfo->Object);
StGWBufferToScreen(gwinfo, left, top, width, height);
}
}
void StGWReverseColors(StGWWinInfo *gwinfo)
{
ColorCode backColor, drawColor;
LVAL object;
object = StGWGetObject(gwinfo);
backColor = StGWBackColor(gwinfo);
drawColor = StGWDrawColor(gwinfo);
if (backColor != drawColor) {
StGWSetBackColor(gwinfo, drawColor);
StGWSetDrawColor(gwinfo, backColor);
StGWObRedraw(object);
}
}
void StGWDrawBitmap(StGWWinInfo *gwinfo,
int left, int top, int width, int height,
char *image)
{
HBITMAP hbm, oldbm;
HDC bmDC, hDC;
int i, j;
if (gwinfo && gwinfo->window) {
hDC = GET_DC(gwinfo->window);
bmDC = CreateCompatibleDC(hDC);
if (bmDC) {
hbm = CreateBitmap(width, height, 1, 1, NULL);
if (hbm) {
oldbm = SelectObject(bmDC, hbm);
PatBlt(bmDC, 0, 0, width, height, WHITENESS);
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
if (image[i * width + j])
SetPixel(bmDC, j, i, 0);
if (gwinfo->drawMode) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
BitBlt(hDC, left, top, width, height, bmDC, 0, 0, 0x990066L);
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
else BitBlt(hDC, left, top, width, height, bmDC, 0, 0, SRCCOPY);
SelectObject(bmDC, oldbm);
DeleteObject(hbm);
}
DeleteDC(bmDC);
}
RELEASE_DC(gwinfo->window, hDC);
}
}
void StGWCopyToClip(StGWWinInfo *gwinfo)
{
HDC hDC, hDCMem;
HBITMAP hBM, hOldBM;
int left, top, width, height;
if (gwinfo && gwinfo->window) {
StGWGetViewRect(gwinfo, &left, &top, &width, &height);
StGWStartBuffering(gwinfo);
StGWObRedraw(GETWINOBJECT(gwinfo->window));
hDC = GetDC((HWND) gwinfo->window);
hDCMem = CreateCompatibleDC(hDC);
hBM = CreateCompatibleBitmap(hDC, width, height);
if (hBM) {
hOldBM = SelectObject(hDCMem, hBM);
if (! gwinfo->use_color) {
SetBkColor(hDC, get_color(0));
SetTextColor(hDC, get_color(1));
}
BitBlt(hDCMem, left, top, width, height, currentDC, left, top, SRCCOPY);
if (! gwinfo->use_color) {
SetBkColor(hDC, get_color(gwinfo->backColor));
SetTextColor(hDC, get_color(gwinfo->drawColor));
}
OpenClipboard(gwinfo->window);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBM);
CloseClipboard();
SelectObject(hDCMem, hOldBM);
}
else SysBeep(10);
DeleteDC(hDCMem);
ReleaseDC((HWND) gwinfo->window, hDC);
StGWResetBuffer();
}
}
syntax highlighted by Code2HTML, v. 0.9.1