This is HitMain.c in view mode; [Download] [Up]
/*
* $RCSfile: HitMain.c,v $
*
* Copyright (C) 1992 by Adobe Systems Incorporated.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notices appear in all copies and that
* both those copyright notices and this permission notice appear in
* supporting documentation and that the name of Adobe Systems
* Incorporated not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. If any portion of this software is changed, it cannot be
* marketed under Adobe's trademarks and/or copyrights unless Adobe, in
* its sole discretion, approves by a prior writing the quality of the
* resulting implementation.
*
* ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
* ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
* TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
* PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
*
* PostScript, Display PostScript, and Adobe are trademarks of Adobe Systems
* Incorporated registered in the U.S.A. and other countries.
*
* Author: Adobe Systems Incorporated
*/
/***************************************************************
**
** INCLUDES
**
***************************************************************/
#include "Hit.h"
#include "zoom.xbm"
#include "zoom_mask.xbm"
/***************************************************************
**
** DATA DECLARATIONS
**
***************************************************************/
/*
** Global pointers to the application data block
*/
AppDataType AppData;
/*
** Global resource management data
*/
MrmHierarchy SMrmHierarchy; /* MRM database hierarchy ID */
static MrmType *DummyClass; /* and class variable. */
static char *DbFilenameVec [] = /* Mrm.heirarchy file list. */
{
"Hit.uid"
};
static void resizeWindow(), refreshWindow(), createProc(), quitApp(),
traceProc(), showBufferProc(), bufferExposeProc(), refreshMouse(),
gridSel(), copyAllSel(), mouseSel(), magnificationSel(),
initApplication(), mouseDown();
/* Names and addresses for Mrm to bind */
static MrmRegisterArg RegList [] =
{
{"resizeWindow" , (XtPointer) resizeWindow },
{"refreshWindow" , (XtPointer) refreshWindow },
{"graphicExpose" , (XtPointer) graphicExpose },
{"createProc" , (XtPointer) createProc },
{"quitApp" , (XtPointer) quitApp },
{"scrollProc" , (XtPointer) scrollProc },
{"traceProc" , (XtPointer) traceProc },
{"showBufferProc" , (XtPointer) showBufferProc },
{"bufferExposeProc", (XtPointer) bufferExposeProc},
{"refreshMouse" , (XtPointer) refreshMouse },
{"gridSel" , (XtPointer) gridSel },
{"copyAllSel" , (XtPointer) copyAllSel },
{"mouseSel" , (XtPointer) mouseSel },
{"magnificationSel", (XtPointer) magnificationSel}
};
static XrmOptionDescRec CommandLineOptions[] = {
{ "-draw", ".drawTrace", XrmoptionNoArg, (caddr_t)"True",},
{ "-hit", ".hitTrace", XrmoptionNoArg, (caddr_t) "True",},
{ "-zoom", ".zoomTrace", XrmoptionNoArg, (caddr_t) "True",},
};
static XtResource Resources[] = {
{
"drawTrace",
"DrawTrace",
XtRBoolean,
sizeof (Boolean),
XtOffset (AppDataTypePtr, drawTrace),
XtRImmediate,
(caddr_t) False
},
{
"hitTrace",
"hitTrace",
XtRBoolean,
sizeof (Boolean),
XtOffset (AppDataTypePtr, hitTrace),
XtRImmediate,
(caddr_t) False
},
{
"zoomTrace",
"zoomTrace",
XtRBoolean,
sizeof (Boolean),
XtOffset (AppDataTypePtr, zoomTrace),
XtRImmediate,
(caddr_t) False
},
};
static Cursor zoomCursor; /* cursor for zooming window */
/***************************************************************
**
** FUNCTION: main
**
** DESCRIPTION: Main procedure for the Hit Detection Application.
** This procedure sets up the X Window environment
** and then enters event dispatching loop.
**
** PARAMETERS: argc argument count of command line call
** argv array of command line arguments
**
** RETURN: N/A
**
***************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext appContext;
Widget toplevel;
Widget mainWindow;
Widget optionBox;
/*
** Initialize MRM before initializing the X Toolkit.
*/
MrmInitialize();
/*
** Initialize the X Toolkit. We get back a top level shell widget.
*/
toplevel = XtAppInitialize (
&appContext, "Hit", CommandLineOptions,
XtNumber(CommandLineOptions), &argc, argv,
(String) NULL, (ArgList) NULL, 0);
XtGetApplicationResources (
toplevel, (XtPointer) &AppData, (XtResourceList) Resources,
XtNumber(Resources), (ArgList) NULL, 0
);
if (!XDPSExtensionPresent(XtDisplay(toplevel))) {
fprintf (stderr, "%s: DPS extension not in server\n", argv [0]);
exit (1);
}
/*
** Open the UID files (the output of the UIL compiler)
*/
if (MrmOpenHierarchy (XtNumber(DbFilenameVec), DbFilenameVec, NULL,
&SMrmHierarchy) != MrmSUCCESS) {
fprintf (stderr, "Can't open heirarchy\n");
exit (1);
}
/*
** Register the items MRM needs to bind for us.
*/
MrmRegisterNames (RegList, XtNumber(RegList));
/*
** Get the main window for the application.
*/
if (MrmFetchWidget (SMrmHierarchy, "MainWindow", toplevel,
&mainWindow, &DummyClass) != MrmSUCCESS)
{
fprintf (stderr, "Can't fetch main window\n");
exit (0);
}
/*
** Get the option box widget
*/
if (MrmFetchWidget(SMrmHierarchy, "OptionBox", mainWindow,
&optionBox, &DummyClass) != MrmSUCCESS)
{
fprintf(stderr, "Can't fetch option window\n");
exit(0);
}
/*
** Get the show buffer box widget
*/
if (MrmFetchWidget(SMrmHierarchy, "BufferBox", mainWindow,
&AppData.bufferBox, &DummyClass) != MrmSUCCESS)
{
fprintf(stderr, "Can't fetch show buffer window\n");
exit(0);
}
/*
** Manage the main window and option box and realize everything.
** The interface comes up on the display now.
*/
XtManageChild(mainWindow);
XtManageChild(optionBox);
XtVaSetValues(
XtParent(optionBox),
XmNmwmFunctions,
MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE,
XmNmwmDecorations,
MWM_DECOR_ALL | MWM_DECOR_MAXIMIZE | MWM_DECOR_RESIZEH,
NULL
);
XtRealizeWidget(toplevel);
/* Perform onetime initialization of application data structures */
initApplication();
/*
** Do all the post-realization DPS/X processing here
*/
initDPSContext();
/*
** Sit around forever waiting to process X-events.
** From here on, we only execute our callback routines.
*/
while (1) {
XEvent event;
XtAppNextEvent(appContext, &event);
if (!XDPSDispatchEvent(&event)) (void) XtDispatchEvent(&event);
}
}
/***************************************************************
**
** FUNCTION: initApplication
**
** DESCRIPTION: One-time initialization of application data
** structures.
**
** PARAMETERS: None.
**
** RETURN: None.
**
***************************************************************/
static void initApplication()
{
XGCValues values;
Pixmap cursor, mask;
Display *dpy = XtDisplay(AppData.drawingArea);
Window win = XtWindow(AppData.drawingArea);
XColor fore, back;
/*
** Initialize the booleans
*/
AppData.showBuffer = False;
AppData.gridOn = False;
AppData.copyAll = False;
AppData.selected = False;
AppData.zooming = False;
AppData.scrolling = False;
/*
** Initialize the initial radio button selection
*/
AppData.magnify = 100;
AppData.hitSize = 4;
AppData.scale = 1.0;
/*
** Create a GC for copying
*/
AppData.gc = XCreateGC(dpy, win, 0, &values);
/*
** Create a zoom pixmap
*/
cursor = XCreateBitmapFromData(dpy, win, zoom_bits,
zoom_width, zoom_height);
mask = XCreateBitmapFromData(dpy, win, zoom_mask_bits,
zoom_mask_width, zoom_mask_height);
if (cursor != None && mask != None) {
fore.red = fore.green = fore.blue = 0;
back.red = back.green = back.blue = 65535;
fore.flags = back.flags = DoRed | DoGreen | DoBlue;
zoomCursor = XCreatePixmapCursor(dpy, cursor, mask, &fore, &back,
zoom_x_hot, zoom_y_hot);
XFreePixmap(dpy, cursor);
XFreePixmap(dpy, mask);
} else zoomCursor = None;
} /* end initApplication() */
/***************************************************************
**
** FUNCTION: resizeWindow
**
** DESCRIPTION: Callback routine to handle resize events.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void resizeWindow(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int depth;
Display *dpy = XtDisplay(w);
XPoint xpoint;
Point point;
if (!XtIsRealized(w)) return;
/*
** Convert lower left corner into PS units so we can keep it fixed
*/
xpoint.x = 0;
xpoint.y = (int) AppData.drawingHeight;
convertToDPS(&xpoint, &point);
/*
** Get new size of drawing area
*/
XtVaGetValues(AppData.drawingArea, XtNheight, &AppData.drawingHeight,
XtNwidth, &AppData.drawingWidth,
XtNdepth, &depth, NULL);
/*
** Resizing automatically moved the y offset
*/
AppData.yOffset = AppData.drawingHeight;
/*
** Change the sizes of the buffer windows
*/
XtVaSetValues(AppData.bufOrig, XtNheight, AppData.drawingHeight,
XtNwidth, AppData.drawingWidth, NULL);
XtVaSetValues(AppData.bufComp, XtNheight, AppData.drawingHeight,
XtNwidth, AppData.drawingWidth, NULL);
/*
** Create new pixmaps to match the drawable
*/
XFreePixmap(dpy, AppData.original);
XFreePixmap(dpy, AppData.composite);
AppData.original = XCreatePixmap(dpy, XtWindow(w), AppData.drawingWidth,
AppData.drawingHeight, depth);
AppData.composite = XCreatePixmap(dpy, XtWindow(w), AppData.drawingWidth,
AppData.drawingHeight, depth);
/*
** Clear pixmaps
*/
XFillRectangle(dpy, AppData.original, AppData.gc, 0, 0,
AppData.drawingWidth, AppData.drawingHeight);
XFillRectangle(dpy, AppData.composite, AppData.gc, 0, 0,
AppData.drawingWidth, AppData.drawingHeight);
/*
** Update the gstates for the two buffers to reflect the new pixmaps
*/
XDPSSetContextGState(AppData.dpsCtxt, AppData.compGState);
XDPSSetContextDrawable(AppData.dpsCtxt, AppData.composite,
AppData.drawingHeight);
XDPSUpdateContextGState(AppData.dpsCtxt, AppData.compGState);
XDPSSetContextGState(AppData.dpsCtxt, AppData.origGState);
XDPSSetContextDrawable(AppData.dpsCtxt, AppData.original,
AppData.drawingHeight);
XDPSUpdateContextGState(AppData.dpsCtxt, AppData.origGState);
/*
** Move the drawing area so the bottom left corner
** of the image remains located at the bottom left corner
*/
positionDrawingArea(point.x, point.y, 0, AppData.drawingHeight);
drawSelfAndUpdate();
} /* end resizeWindow() */
/***************************************************************
**
** FUNCTION: refreshWindow
**
** DESCRIPTION: Callback routine to handle regular expose events
** to the main window. Updates the window by copying
** from the original pixmap
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void refreshWindow(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XmDrawingAreaCallbackStruct *callback =
(XmDrawingAreaCallbackStruct *) callData;
XExposeEvent *e = &callback->event->xexpose;
/*
** Only update exposed areas
*/
XCopyArea(XtDisplay(w), AppData.original, XtWindow(w), AppData.gc,
e->x, e->y, e->width, e->height, e->x, e->y);
} /* end refreshWindow() */
/***************************************************************
**
** FUNCTION: refreshMouse
**
** DESCRIPTION: Callback routine to handle expose events on the
** mouse hit drawing area. Refreshes the window by
** redrawing the circle
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void refreshMouse(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
register Display *dpy = XtDisplay(w);
register Window window = XtWindow(w);
XEvent event;
/*
** Pseudo Exposure event compression for the Drawing Area Widget
*/
if (XPending(dpy) > 0) {
XPeekEvent(dpy, &event);
if (event.type == Expose && event.xany.window == window) return;
}
/*
** Redraw mouse sensitivity area
*/
drawSensitivityCircle();
} /* end refreshMouse() */
/***************************************************************
**
** FUNCTION: createProc
**
** DESCRIPTION: Callback routine for widget creation.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void createProc(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int widgetNum = *(int *) clientData;
/*
** Save widget ID
*/
switch (widgetNum) {
case cMainDrawArea:
AppData.drawingArea= w;
/*
** Add event handlers for main window
*/
XtAddRawEventHandler(w, 0, True, graphicExpose, NULL);
XtAddEventHandler(w, ButtonPressMask, False, mouseDown, NULL);
break;
case cBufferDrawArea0: AppData.bufOrig = w; break;
case cBufferDrawArea1: AppData.bufComp = w; break;
case cMainHorzSBar: AppData.hScroll = w; break;
case cMainVertSBar: AppData.vScroll = w; break;
case cMouseDrawArea: AppData.mouseArea = w; break;
case cDrawingToggle:
/* If trace turned on by command line, set button */
if (AppData.drawTrace) XtVaSetValues(w, XmNset, True, NULL);
break;
case cHitDetToggle:
if (AppData.hitTrace) XtVaSetValues(w, XmNset, True, NULL);
break;
case cZoomingToggle:
if (AppData.zoomTrace) XtVaSetValues(w, XmNset, True, NULL);
break;
} /* end switch */
} /* end createProc() */
/***************************************************************
**
** FUNCTION: quitApp
**
** DESCRIPTION: Callback routine for "quit" command menu
** selection. Exits from the application.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: Returns to OS.
**
***************************************************************/
static void quitApp(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
exit(0);
} /* end quitApp() */
/***************************************************************
**
** FUNCTION: traceProc
**
** DESCRIPTION: Callback routine for the trace toggle buttons.
** Sets or resets the appropriate tracing flags.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void traceProc(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int num = *(int *) clientData;
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
switch (num) {
case 0: /* Trace - Drawing */
AppData.drawTrace = toggle->set;
break;
case 1: /* Trace - Hit Detection */
AppData.hitTrace = toggle->set;
break;
case 2: /* Trace - Zooming */
AppData.zoomTrace = toggle->set;
break;
}
} /* end traceProc() */
/***************************************************************
**
** FUNCTION: showBufferProc
**
** DESCRIPTION: Callback routine for show buffer toggle button
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void showBufferProc(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
AppData.showBuffer = toggle->set;
if (AppData.showBuffer) {
/*
** Resize buffers to match current window size and pop up
*/
XtVaSetValues(AppData.bufOrig, XtNheight, AppData.drawingHeight,
XtNwidth, AppData.drawingWidth, NULL);
XtVaSetValues(AppData.bufComp, XtNheight, AppData.drawingHeight,
XtNwidth, AppData.drawingWidth, NULL);
XtManageChild(AppData.bufferBox);
} else XtUnmanageChild(AppData.bufferBox);
} /* end showBufferProc() */
/***************************************************************
**
** FUNCTION: bufferExposeProc
**
** DESCRIPTION: Callback routine for buffer exposure
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void bufferExposeProc(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XmDrawingAreaCallbackStruct *callback =
(XmDrawingAreaCallbackStruct *) callData;
XExposeEvent *e = &callback->event->xexpose;
/*
** Only update exposed areas
*/
if (w == AppData.bufOrig) {
XCopyArea(XtDisplay(w), AppData.original, XtWindow(w), AppData.gc,
e->x, e->y, e->width, e->height, e->x, e->y);
} else {
XCopyArea(XtDisplay(w), AppData.composite, XtWindow(w), AppData.gc,
e->x, e->y, e->width, e->height, e->x, e->y);
}
} /* end bufferExposeProc() */
/***************************************************************
**
** FUNCTION: gridSel
**
** DESCRIPTION: Callback routine for grid togglebutton selection.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void gridSel(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
/*
** Change the state of the flag
*/
AppData.gridOn = toggle->set;
drawSelfAndUpdate();
} /* end gridSel() */
/***************************************************************
**
** FUNCTION: copyAllSel
**
** DESCRIPTION: Callback routine for copyAll togglebutton selection.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void copyAllSel(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
/*
** Change the state of the flag
*/
AppData.copyAll = toggle->set;
} /* end copyAllSel() */
/***************************************************************
**
** FUNCTION: mouseSel
**
** DESCRIPTION: Callback routine for mouse sensitivity selection.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void mouseSel(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int num = *(int *) clientData;
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
/*
** If setting, change stored hit size and redraw sensitivity
*/
if (toggle->set) {
AppData.hitSize = num;
drawSensitivityCircle();
}
} /* end mouseSel() */
/***************************************************************
**
** FUNCTION: magnificationSel
**
** DESCRIPTION: Callback routine for magnification selection.
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
static void magnificationSel(w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int num = *(int *) clientData;
XmToggleButtonCallbackStruct *toggle =
(XmToggleButtonCallbackStruct *) callData;
/*
** If set, start zooming by setting zoom cursor
*/
if (toggle->set && AppData.magnify != num) {
AppData.zooming = True;
AppData.magnify = num;
if (zoomCursor != None) {
XDefineCursor(XtDisplay(AppData.drawingArea),
XtWindow(AppData.drawingArea), zoomCursor);
}
}
} /* end magnificationSel() */
/***************************************************************
**
** FUNCTION: mouseDown
**
** DESCRIPTION: This function acts as the event handler for the
** ButtonDown event. If the magnification is being
** changed (zooming), then scale and position the
** drawing view. Else check for hit detection on the
** Bezier or the control points.
**
** PARAMETERS: w window widget
** clientData clientdata
** event event information
** goOn continue to dispatch
**
** RETURN: None
**
***************************************************************/
static void mouseDown(w, clientData, event, goOn)
Widget w;
XtPointer clientData;
XEvent *event;
Boolean *goOn;
{
XPoint xpoint;
Point point;
int ptNum;
XButtonPressedEvent *bp = (XButtonPressedEvent *) event;
if (event->xany.window != XtWindow(AppData.drawingArea)) return;
xpoint.x = bp->x;
xpoint.y = bp->y;
/*
** If zooming, rescale so clicked-on point remains fixed
*/
if (AppData.zooming) {
XDPSChainTextContext(AppData.dpsCtxt, AppData.zoomTrace);
/*
** Convert point to PS units and scale
*/
convertToDPS(&xpoint, &point);
scaleDrawingArea();
positionDrawingArea(point.x, point.y, xpoint.x, xpoint.y);
drawSelfAndUpdate();
AppData.zooming = False;
if (zoomCursor != None) {
XUndefineCursor(XtDisplay(w), XtWindow(w));
}
if (AppData.zoomTrace) XDPSChainTextContext(AppData.dpsCtxt, False);
} else {
/*
** Not zooming; do hit detection. If not already selected, see if
** the user hit it; redraw showing control points
*/
if (!AppData.selected) {
if (hitObject(&xpoint)) {
AppData.selected = True;
drawSelfAndUpdate();
}
} else {
/*
** Already selected; see if the user hit a control point
** or the curve itself. If so, reshape or move; if not,
** redraw without control points
*/
if (hitControl(&xpoint, &ptNum)) reshapeObject(&xpoint, ptNum);
else if (hitObject(&xpoint)) moveObject(&xpoint);
else {
AppData.selected = False;
drawSelfAndUpdate();
}
}
}
} /* end mouseDown() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.