1 
2 #include <stdio.h>
3 
4 #include <X11/StringDefs.h>
5 #include <X11/Intrinsic.h>
6 #include <X11/Core.h>
7 #include <X11/Object.h>
8 #include <X11/Shell.h>
9 
10 #include <X11/Xaw/Form.h>
11 
12 #include <Mowitz/Mowitz.h>
13 
14 	/* X11 stuff */
15 
16 static	Display	*dpy ;
17 static	Atom	wm_protocols ;
18 static	Atom	wm_delete_window ;
19 
20 static	GC	canvasGc ;
21 static	Bool	canvas_init = False ;
22 static	Pixel	black, yellow ;
23 
24 	/* Xt stuff */
25 
26 static	XtAppContext	app_ctx ;
27 
28 static	Widget	topLevel ;
29 static	Widget	mainPanel ;
30 static	Widget	leftRuler, topRuler ;
31 static	Widget	leftFrame, topFrame ;
32 static	Widget	canvas ;
33 
34 static	void	CanvasCB(Widget, XtPointer, XEvent *, Boolean *) ;
35 
36 static String fallback[] = {
37 	"*background:		gray",
38 	"*borderWidth:		0",
39 	"*Frame.shadowWidth:	1",
40 	"*Frame.shadowType:	raised",
41 	"*MwRuler.font:	-*-lucida-medium-r-normal-sans-12-*-*-*-*-*-iso8859-*",
42 	"*MwRuler.fracFont: -*-lucida-medium-r-normal-sans-8-*-*-*-*-*-iso8859-*",
43 	"*mainPanel.defaultDistance:	0",
44 	"*canvas.width:		300",
45 	"*canvas.height:	300",
46 	"*topRuler.width:	300",
47 	"*leftRuler.height:	300",
48 	"*topRuler.scale:	100",
49 	"*leftRuler.scale:	-100",
50 	"Rulerdemo.baseTranslations: #augment <Message>WM_PROTOCOLS: WMProtocols()",
51 	NULL
52 };
53 
54 static	void	RulerCB(Widget, XtPointer, XtPointer) ;
55 
56 static	void	WMProtocols(Widget, XEvent *, String *, Cardinal *) ;
57 
58 
59 	/* define global actions table for the application.  This is done
60 	 * to catch messages.  This could also be done through the main
61 	 * event loop if we wrote one.  It would be nice if Xt had a way
62 	 * of regestering a callback proc for specific kinds of events.
63 	 */
64 
65 XtActionsRec	rulerdemo_actions[] = {
66     {"WMProtocols", WMProtocols},
67 } ;
68 
69 
70 int
main(int argc,char ** argv)71 main(int argc, char **argv)
72 {
73 	Dimension len, bwid ;
74 
75 	topLevel = XtAppInitialize(&app_ctx, "Rulerdemo", NULL,0,
76 	  &argc, argv, fallback, NULL,0) ;
77 	dpy = XtDisplay(topLevel) ;
78 
79 	XtAppAddActions(app_ctx,
80 		rulerdemo_actions, XtNumber(rulerdemo_actions));
81 
82 	mainPanel = XtVaCreateManagedWidget("mainPanel",
83 		formWidgetClass, topLevel,
84 		0) ;
85 
86 	topFrame = XtVaCreateManagedWidget("topFrame",
87 		mwFrameWidgetClass, mainPanel,
88 		XtNleft, XtChainLeft,
89 		XtNright, XtChainRight,
90 		XtNtop, XtChainTop,
91 		XtNbottom, XtChainTop,
92 		0) ;
93 
94 	topRuler = XtVaCreateManagedWidget("topRuler",
95 		mwRulerWidgetClass, topFrame,
96 		XtNorientation, NorthGravity,
97 		0) ;
98 	XtAddCallback(topRuler, XtNcallback, RulerCB, NULL) ;
99 
100 	leftFrame = XtVaCreateManagedWidget("leftFrame",
101 		mwFrameWidgetClass, mainPanel,
102 		XtNleft, XtChainLeft,
103 		XtNright, XtChainLeft,
104 		XtNtop, XtChainTop,
105 		XtNbottom, XtChainBottom,
106 		XtNfromVert, topFrame,
107 		0) ;
108 
109 	leftRuler = XtVaCreateManagedWidget("leftRuler",
110 		mwRulerWidgetClass, leftFrame,
111 		XtNorientation, WestGravity,
112 		0) ;
113 	XtAddCallback(leftRuler, XtNcallback, RulerCB, NULL) ;
114 
115 
116 	/* yuk.  Athena Form widget really sucks; I shouldn't have
117 	 * to go through these gyrations.
118 	 */
119 
120 	XtVaGetValues(leftRuler, XtNwidth, &len, 0) ;
121 	XtVaGetValues(leftFrame, XtNshadowWidth, &bwid, 0) ;
122 	XtVaSetValues(topFrame, XtNhorizDistance, len+bwid*2, 0) ;
123 
124 	canvas = XtVaCreateManagedWidget("canvas",
125 		coreWidgetClass, mainPanel,
126 		XtNleft, XtChainLeft,
127 		XtNright, XtChainRight,
128 		XtNtop, XtChainTop,
129 		XtNbottom, XtChainBottom,
130 		XtNfromHoriz, leftFrame,
131 		XtNfromVert, topFrame,
132 		0) ;
133 	XtAddEventHandler(canvas,
134 	  ExposureMask | ButtonPressMask | PointerMotionMask |
135 	  EnterWindowMask | LeaveWindowMask,
136 	  True, CanvasCB, NULL) ;
137 
138 	XtRealizeWidget(topLevel) ;
139 
140 	/* tell window system we're willing to handle window-delete messages */
141 	wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
142 	wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
143 	(void) XSetWMProtocols(dpy, XtWindow(topLevel), &wm_delete_window,1);
144 
145 	MwRulerSetMinPosition(topRuler, 0., 0) ;
146 	XtVaGetValues(leftRuler, XtNheight, &len, 0) ;
147 	MwRulerSetMinPosition(leftRuler, 0., len-1) ;
148 
149 	XtAppMainLoop(app_ctx) ;
150 
151 	exit(0) ;
152 }
153 
154 
155 
156 
157 
158 
159 
160 
161 
162 static	void
RulerCB(Widget r,XtPointer client,XtPointer call_data)163 RulerCB(Widget r, XtPointer client, XtPointer call_data)
164 {
165 	MwRulerReport	*rep = (MwRulerReport *)call_data ;
166 	Display		*dpy = XtDisplay(canvas) ;
167 	Window		win = XtWindow(canvas) ;
168 	Position	sx,sy ;
169 	Dimension	wid,hgt ;
170 
171 	switch( rep->what ) {
172 	  case SCROLL:
173 	  case STOP:
174 	    XtVaGetValues(canvas, XtNwidth, &wid, XtNheight, &hgt, 0) ;
175 	    sx = -rep->dx ;
176 	    sy = -rep->dy ;
177 	    XCopyArea(dpy, win,win, canvasGc,
178 	      (int)sx, (int)sy, (u_int)wid, (u_int)hgt, 0, 0 ) ;
179 	    break ;
180 	  default:
181 	    break ;
182 	}
183 }
184 
185 
186 static	void
CanvasCB(Widget canvas,XtPointer client,XEvent * ev,Boolean * cont)187 CanvasCB(Widget canvas, XtPointer client, XEvent *ev, Boolean *cont)
188 {
189 	Display	*dpy = XtDisplay(canvas) ;
190 	Window	win = XtWindow(canvas) ;
191 	int	x0,y0 ;
192 
193 	if( !canvas_init )
194 	{
195 	  Colormap cmap ;
196 	  XColor	y,b, dummy ;
197 	  XtVaGetValues(canvas, XtNcolormap, &cmap, 0) ;
198 	  canvasGc = XCreateGC(dpy,win, 0,NULL) ;
199 	  XSetLineAttributes(dpy, canvasGc, 8, LineSolid, CapButt, JoinRound);
200 	  XSetGraphicsExposures(dpy, canvasGc, True) ;
201 	  XAllocNamedColor(dpy, cmap, "yellow", &y, &dummy) ; yellow = y.pixel ;
202 	  XAllocNamedColor(dpy, cmap, "black", &b, &dummy) ; black = b.pixel ;
203 	  canvas_init = True ;
204 	}
205 
206 	switch( ev->type ) {
207 	  case GraphicsExpose:
208 	  case Expose:
209 	    x0 = MwRulerValue2Position(topRuler, 1.) ;
210 	    y0 = MwRulerValue2Position(leftRuler, 1.) - 100 ;
211 	    XSetForeground(dpy,canvasGc, yellow) ;
212 	    XFillArc(dpy,win,canvasGc, x0,y0, 100,100, 0,360*64) ;
213 	    XSetForeground(dpy,canvasGc, black) ;
214 	    XDrawArc(dpy,win,canvasGc, x0,y0, 100,100, 0,360*64) ;
215 	    XFillArc(dpy,win,canvasGc, x0+30,y0+30, 10,10, 0,360*64) ;
216 	    XFillArc(dpy,win,canvasGc, x0+60,y0+30, 10,10, 0,360*64) ;
217 	    XDrawArc(dpy,win,canvasGc, x0+20,y0+20, 60,60, 225*64,90*64) ;
218 	    break ;
219 	  case EnterNotify:
220 	    MwRulerShowPointer(leftRuler, True) ;
221 	    MwRulerShowPointer(topRuler, True) ;
222 	    break ;
223 	  case LeaveNotify:
224 	    MwRulerShowPointer(leftRuler, False) ;
225 	    MwRulerShowPointer(topRuler, False) ;
226 	    break ;
227 	  case MotionNotify:
228 	    MwRulerSetIValue(leftRuler, ev->xmotion.y) ;
229 	    MwRulerSetIValue(topRuler, ev->xmotion.x) ;
230 	    break ;
231 	}
232 
233 }
234 
235 
236 static	void
WMProtocols(w,ev,params,nparams)237 WMProtocols(w, ev, params, nparams)
238 	Widget	w ;
239 	XEvent	*ev ;
240 	String	*params ;
241 	Cardinal *nparams ;
242 {
243 	if( ev->type == ClientMessage  &&
244 	    ev->xclient.message_type == wm_protocols  &&
245 	    ev->xclient.data.l[0] == wm_delete_window )
246 	{
247 	  if( w == topLevel )
248 	    exit(0) ;
249 	}
250 }
251