|
|
1.1 root 1: /* $Header: RubberBand.c,v 1.20 87/09/02 15:28:22 swick Exp $ */
2: /* derived from XCreateTerm.c */
3:
4: #include <X11/copyright.h>
5:
6: /*
7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
8: *
9: * All Rights Reserved
10: *
11: * Permission to use, copy, modify, and distribute this software and its
12: * documentation for any purpose and without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and that
14: * both that copyright notice and this permission notice appear in
15: * supporting documentation, and that the name of Digital Equipment
16: * Corporation not be used in advertising or publicity pertaining to
17: * distribution of the software without specific, written prior permission.
18: *
19: *
20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26: * SOFTWARE.
27: */
28:
29: /*
30: * MODIFICATION HISTORY
31: *
32: * 000 -- Loretta Guarino Reid, DEC Ultrix Engineering Group
33: * 001 -- Ralph R. Swick, DEC/MIT Project Athena
34: * tailor to uwm; use global resources created by uwm
35: */
36:
37: #include <stdio.h>
38: #include <strings.h>
39: #include <X11/Xlib.h>
40: #include <X11/Xutil.h>
41: #include <X11/cursorfont.h>
42:
43: #include "uwm.h"
44:
45: #define max(a,b) ( (a) > (b) ? (a) : (b) )
46: #define min(a,b) ( (a) > (b) ? (b) : (a) )
47: #define abs(a) ( (a) > 0 ? (a) : -(a))
48: #define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
49:
50: #define DCOUNT 2
51: #define PCOUNT 1 + (4 * 2 * DCOUNT)
52:
53: #define BW PBorderWidth /* pop-up window border width */
54: #define IBW PPadding /* internal border width for pop-up */
55:
56: AskUser(dpy, scr, window, x, y, width, height, hints)
57: Display *dpy;
58: int scr;
59: Window window;
60: int *x, *y, *width, *height;
61: XSizeHints *hints;
62: {
63: /* XFontStruct *pfont; */
64: #define pfont PFontInfo /* text font for pop-up */
65: Cursor ur, ul, ll, lr; /* cursors for rubber banding */
66: int change_cursor = FALSE;
67: int current_cursor;
68: char *text; /* text for prompt string */
69: int nz; /* count where zeros are */
70: int popw, poph; /* width and height of prompt window*/
71: /* int pfore, pback; */ /* prompt foreground and background */
72: #define pback PTextBackground
73: /* GC popGC, invertGC; */
74: /* XGCValues xgc; */
75: #define popGC PopGC
76: #define invertGC DrawGC
77: int x1, y1; /* location of mouse */
78: int x2, y2; /* other corner of box */
79: int rootx, rooty, mask; /* for XQueryPointer */
80: Window root, subw; /* for XQueryPointer */
81: int xa = -1, ya = -1, xb = -1, yb = -1;
82: int xinc, yinc;
83: int minwidth, minheight;
84: int maxwidth, maxheight;
85: int defwidth, defheight;
86: int chosen = -1;
87: int stop = FALSE;
88: int changed = TRUE;
89: int doit = FALSE;
90: int dx, dy;
91: int delta;
92: XPoint box[PCOUNT];
93: int hsize, vsize;
94: int zero = '0'; /* zero offset for char conversion */
95: XEvent e; /* someplace to put the event */
96: int events; /* what events we want. */
97: Window pop; /* pop up prompt window */
98: int i;
99: char *name;
100: int width_offset, height_offset; /* to subtract if resize increments */
101:
102: if ((hints->flags & USPosition) && (hints->flags & USSize)) {
103: *x = hints->x;
104: *y = hints->y;
105: *width = hints->width;
106: *height = hints->height;
107: return;
108: }
109: if (!XFetchName(dpy, window, &name))
110: name = "Unnamed Window";
111:
112: ur = XCreateFontCursor(dpy, XC_ur_angle);
113: ul = XCreateFontCursor(dpy, XC_ul_angle);
114: ll = XCreateFontCursor(dpy, XC_ll_angle);
115: lr = XCreateFontCursor(dpy, XC_lr_angle);
116: current_cursor = ul;
117:
118: events = ButtonPressMask | ButtonReleaseMask;
119: /* pfont = XLoadQueryFont(dpy, "fixed"); */
120:
121: /*
122: * go get the mouse as soon as you can
123: */
124:
125: while (1) {
126: int res;
127: if ((res = XGrabPointer (dpy, RootWindow(dpy, scr), FALSE, events,
128: GrabModeAsync, GrabModeAsync, None, ul, CurrentTime )) ==
129: GrabSuccess)
130: break;
131: sleep (1);
132: }
133: nz = strlen(name); /* compute number of characters */
134: text = (char *)malloc( nz + 11 );
135: (void) strcpy(text, name);
136: (void) strcat(text, ": 000x000");
137: nz += 9;
138: popw = XTextWidth (pfont, text, nz) + 2 * IBW;
139: poph = pfont->ascent+pfont->descent + 2 * IBW;
140:
141: /* pfore = WhitePixel(dpy, scr);
142: * pback = BlackPixel(dpy, scr);
143: * xgc.foreground = pfore;
144: * xgc.background = pback;
145: * xgc.font = pfont->fid;
146: * popGC = XCreateGC(dpy, RootWindow(dpy, scr),
147: * GCForeground+GCBackground+GCFont, &xgc);
148: * xgc.function = GXinvert;
149: * xgc.subwindow_mode = IncludeInferiors;
150: * invertGC = XCreateGC(dpy, RootWindow(dpy, scr),
151: * GCForeground+GCBackground+GCFont+GCFunction+GCSubwindowMode, &xgc);
152: */
153:
154: pop = XCreateSimpleWindow(dpy, RootWindow(dpy, scr),
155: 0, 0, popw, poph, BW, pback, pback);
156: XMapWindow (dpy, pop);
157:
158: if (hints->flags&PMinSize) {
159: minwidth = hints->min_width;
160: minheight = hints->min_height;
161: } else {
162: minwidth = 0;
163: minheight = 0;
164: }
165: if (hints->flags&PMaxSize) {
166: maxwidth = max(hints->max_width, minwidth);
167: maxheight = max(hints->max_height, minheight);
168: } else {
169: maxwidth = DisplayWidth(dpy, scr);
170: maxheight = DisplayHeight(dpy, scr);
171: }
172: if (hints->flags&PResizeInc) {
173: xinc = hints->width_inc;
174: yinc = hints->height_inc;
175: } else {
176: xinc = 1;
177: yinc = 1;
178: }
179: if (hints->flags&PSize || hints->flags&USSize) {
180: defwidth = hints->width;
181: defheight = hints->height;
182: } else if (hints->flags&PMinSize) {
183: defwidth = hints->min_width;
184: defheight = hints->min_height;
185: } else if (hints->flags&PMaxSize) {
186: defwidth = hints->max_width;
187: defheight = hints->max_height;
188: } else {
189: long dummy;
190: XGetGeometry(dpy, window, &dummy, &dummy, &dummy,
191: &defwidth, &defheight, &dummy, &dummy);
192: }
193:
194: /* until there are better WM_HINTS, we'll assume that the client's
195: * minimum width and height are the appropriate offsets to subtract
196: * when resizing with an explicit resize increment.
197: */
198: if (hints->flags&PMinSize && hints->flags&PResizeInc) {
199: width_offset = hints->min_width;
200: height_offset = hints->min_height;
201: } else
202: width_offset = height_offset = 0;
203:
204:
205: XQueryPointer (dpy, RootWindow(dpy, scr), &root, &subw,
206: &rootx, &rooty, &x1, &y1, &mask);
207: hsize = minwidth;
208: vsize = minheight;
209: x2 = x1+hsize;
210: y2 = y1+vsize;
211:
212: while (stop == FALSE) {
213: if ( (xb != max (x1, x2)) || (yb != max (y1, y2))
214: ||(xa != min (x1, x2)) || (ya != min (y1, y2)) ) {
215: xa = min (x1, x2);
216: ya = min (y1, y2);
217: xb = max (x1, x2);
218: yb = max (y1, y2);
219: for ( i = 0; i < PCOUNT; i += 4) {
220: box[i].x = xa; box[i].y = ya;
221: if (i+1 == PCOUNT) break;
222: box[i+1].x = xb; box[i+1].y = ya;
223: box[i+2].x = xb; box[i+2].y = yb;
224: box[i+3].x = xa; box[i+3].y = yb;
225: }
226: doit = TRUE;
227: }
228: if (changed) {
229: int Hsize = (hsize - width_offset) / xinc;
230: int Vsize = (vsize - height_offset) / yinc;
231: int pos = 3;
232:
233: changed = FALSE;
234: text[nz - 7] = (Hsize>99) ? (Hsize / 100 + zero) : ' ';
235: text[nz - 6] = (Hsize>9) ? ((Hsize / 10) % 10 + zero) : ' ';
236: text[nz - 5] = Hsize % 10 + zero;
237: if (Vsize>99) text[nz - pos--] = Vsize / 100 + zero;
238: if (Vsize>9) text[nz - pos--] = (Vsize / 10) % 10 + zero;
239: text[nz - pos--] = Vsize % 10 + zero;
240: while (pos>0) text[nz - pos--] = ' ';
241: XDrawImageString(dpy, pop, popGC, IBW, IBW+pfont->ascent,
242: text, nz);
243: }
244: if (doit) {
245: XDrawLines(dpy, RootWindow(dpy, scr), invertGC, box, PCOUNT,
246: CoordModeOrigin);
247: }
248: if (XPending(dpy) &&
249: XCheckMaskEvent(dpy, ButtonPressMask|ButtonReleaseMask, &e)) {
250: if ((chosen < 0) && (e.type == ButtonPress)) {
251: x1 = x2 = ((XButtonEvent *)&e)->x;
252: y1 = y2 = ((XButtonEvent *)&e)->y;
253: chosen = ((XButtonEvent *)&e)->button;
254: if (chosen == Button2)
255: change_cursor = TRUE;
256: }
257: else if ((e.type == ButtonRelease) &&
258: ((((XButtonEvent *)&e)->button) == chosen)) {
259: x2 = ((XButtonEvent *)&e)->x;
260: y2 = ((XButtonEvent *)&e)->y;
261: stop = TRUE;
262: }
263: else
264: XQueryPointer (dpy, RootWindow(dpy, scr), &root,
265: &subw, &rootx, &rooty, &x2, &y2, &mask);
266: }
267: else XQueryPointer (dpy, RootWindow(dpy, scr), &root,
268: &subw, &rootx, &rooty, &x2, &y2, &mask);
269: if (change_cursor) {
270: if ((x2 >= x1) && (y2 >= y1) &&
271: current_cursor != lr) {
272: XChangeActivePointerGrab (dpy, events, lr, CurrentTime );
273: current_cursor = lr;
274: }
275: else if ((x2 >= x1) && (y2 < y1) &&
276: current_cursor != ur) {
277: XChangeActivePointerGrab (dpy, events, ur, CurrentTime );
278: current_cursor = ur;
279: }
280: else if ((x2 < x1) && (y2 >= y1) &&
281: current_cursor != ll) {
282: XChangeActivePointerGrab (dpy, events, ll, CurrentTime );
283: current_cursor = ll;
284: }
285: else if ((x2 < x1) && (y2 < y1) &&
286: (current_cursor != ul)) {
287: XChangeActivePointerGrab (dpy, events, ul, CurrentTime );
288: current_cursor = ul;
289: }
290: }
291: if (chosen != Button2) {
292: x1 = x2;
293: y1 = y2;
294: if (chosen >= 0) {
295: x2 = defwidth;
296: if (chosen == Button1)
297: y2 = defheight;
298: else
299: y2 = (DisplayHeight(dpy, scr) - y1);
300: x2 = x1 + x2;
301: y2 = y1 + y2;
302: }
303: }
304:
305: dx = max(min(abs (x2 - x1), maxwidth), minwidth);
306: dx = makemult(dx-minwidth, xinc)+minwidth;
307: dy = max(min(abs(y2 - y1), maxheight), minheight);
308: dy = makemult(dy-minheight, yinc)+minheight;
309:
310: if (hints->flags & PAspect) {
311: if ((dx * hints->max_aspect.y > dy * hints->max_aspect.x)) {
312: delta = makemult(
313: (dx*hints->max_aspect.y/hints->max_aspect.x) - dy,
314: yinc);
315: if ((dy+delta) <= maxheight) dy += delta;
316: else {
317: delta = makemult(
318: dx - hints->max_aspect.x * dy/hints->max_aspect.y,
319: xinc);
320: if ((dx-delta) >= minwidth) dx -= delta;
321: }
322: }
323: if (dx * hints->min_aspect.y < dy * hints->min_aspect.x) {
324: delta = makemult(
325: (hints->min_aspect.x * dy/hints->min_aspect.y) - dx,
326: xinc);
327: if (dx+delta <= maxwidth) dx += delta;
328: else {
329: delta = makemult(
330: dy - (dx*hints->min_aspect.y / hints->min_aspect.x),
331: yinc);
332: if ((dy-delta) >= minheight) dy -= delta;
333: }
334: }
335:
336: }
337:
338: if (dx != hsize) {
339: hsize = dx;
340: changed = TRUE;
341: }
342: if (dy != vsize) {
343: vsize = dy;
344: changed = TRUE;
345: }
346: if (x2 < x1)
347: x2 = x1 - dx;
348: else
349: x2 = x1 + dx;
350:
351: if (y2 < y1)
352: y2 = y1 - dy;
353: else
354: y2 = y1 + dy;
355: }
356: XUngrabPointer(dpy, CurrentTime);
357:
358: XDestroyWindow (dpy, pop);
359: /* XFreeFont(dpy, pfont); */
360: XFreeCursor (dpy, ur);
361: XFreeCursor (dpy, ul);
362: XFreeCursor (dpy, lr);
363: XFreeCursor (dpy, ll);
364: free(name);
365: free(text);
366: *x = min(x1, x2);
367: *y = min(y1, y2);
368: *width = hsize;
369: *height = vsize;
370: XSync(dpy, False);
371: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.