~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/xmag/xmag.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: xmag.c,v 1.4 2001/02/09 02:05:55 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1991, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall
 
24
not be used in advertising or otherwise to promote the sale, use or
 
25
other dealings in this Software without prior written authorization
 
26
from The Open Group.
 
27
 
 
28
*/
 
29
/* $XFree86: xc/programs/xmag/xmag.c,v 1.11 2003/01/19 04:44:45 paulo Exp $ */
 
30
 
 
31
 
 
32
#include <stdlib.h>             /* for exit() and abs() */
 
33
#include <stdio.h>
 
34
 
 
35
#include <X11/Intrinsic.h>
 
36
#include <X11/StringDefs.h>
 
37
#include <X11/Xaw/Paned.h>
 
38
#include <X11/Xaw/Command.h>
 
39
#include <X11/Xaw/Label.h>
 
40
#include <X11/Shell.h>
 
41
#include <X11/cursorfont.h>
 
42
#include <X11/Xmu/Error.h>
 
43
#include "RootWin.h"
 
44
#include "Scale.h"
 
45
#include "CutPaste.h"
 
46
 
 
47
#define SRCWIDTH  64
 
48
#define SRCHEIGHT 64
 
49
 
 
50
#ifndef min
 
51
#define min(a, b) ((a) < (b) ? (a) : (b))
 
52
#endif
 
53
 
 
54
 
 
55
 
 
56
/* highlight interval */
 
57
#define HLINTERVAL  10          
 
58
 
 
59
/* highlight mode */
 
60
typedef enum { drag, resize, done } hlMode; 
 
61
 
 
62
/* highlight data structure */
 
63
typedef struct { 
 
64
  Boolean   newScale;
 
65
  hlMode    selectMode;
 
66
  GC        gc;
 
67
  XWindowAttributes win_info;   
 
68
  XImage     *image;
 
69
  Position  homeX, homeY, x, y;
 
70
  Dimension width, height;
 
71
  Widget    scaleShell, scaleInstance, pixShell, pixLabel, cmapWinList [2];
 
72
  } hlStruct, *hlPtr;
 
73
 
 
74
static XtIntervalId hlId;
 
75
 
 
76
 
 
77
 
 
78
/* global variables */
 
79
static XtAppContext app;
 
80
static Cursor ulAngle, urAngle, lrAngle, llAngle;
 
81
static Display *dpy;
 
82
static int scr;
 
83
static GC selectGC; 
 
84
static XGCValues selectGCV;
 
85
static Widget toplevel, root;
 
86
static Atom wm_delete_window;
 
87
static int numXmags = 0;
 
88
static int srcStat, srcX, srcY;
 
89
static unsigned int srcWidth, srcHeight;
 
90
 
 
91
/* forward declarations */
 
92
 
 
93
#if NeedFunctionPrototypes
 
94
/* xmag.c */
 
95
static int Error(Display *, XErrorEvent *);
 
96
static void CloseAP(Widget, XEvent *, String *, Cardinal *);
 
97
static void SetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
 
98
static void UnsetCmapPropsAP(Widget, XEvent *, String *, Cardinal *);
 
99
static void NewAP(Widget, XEvent *, String *, Cardinal *);
 
100
static void ReplaceAP(Widget, XEvent *, String *, Cardinal *);
 
101
static void PopupPixelAP(Widget, XEvent *, String *, Cardinal *);
 
102
static void UpdatePixelAP(Widget, XEvent *, String *, Cardinal *);
 
103
static void PopdownPixelAP(Widget, XEvent *, String *, Cardinal *);
 
104
static void SelectRegionAP(Widget, XEvent *, String *, Cardinal *);
 
105
static void CheckPoints(Position *, Position *, Position *, Position *);
 
106
static void HighlightTO(XtPointer, XtIntervalId *);
 
107
static void CloseCB(Widget, XtPointer, XtPointer);
 
108
static void ReplaceCB(Widget, XtPointer, XtPointer);
 
109
static void NewCB(Widget, XtPointer, XtPointer);
 
110
static void SelectCB(Widget, XtPointer, XtPointer);
 
111
static void PasteCB(Widget, XtPointer, XtPointer);
 
112
static void SetupGC(void);
 
113
static Window FindWindow(int, int);
 
114
static void ResizeEH(Widget, XtPointer, XEvent *, Boolean *);
 
115
static void DragEH(Widget, XtPointer, XEvent *, Boolean *);
 
116
static void StartRootPtrGrab(int, hlPtr);
 
117
static void CreateRoot(void);
 
118
static void GetImageAndAttributes(Window, int, int, int, int, hlPtr);
 
119
static int Get_XColors(XWindowAttributes *, XColor **);
 
120
static Pixel GetMaxIntensity(hlPtr);
 
121
static Pixel GetMinIntensity(hlPtr);
 
122
static void PopupNewScale(hlPtr);
 
123
static void RedoOldScale(hlPtr);
 
124
static void InitCursors(void);
 
125
static void ParseSourceGeom(void);
 
126
#else
 
127
static void 
 
128
  CloseAP(), 
 
129
  SetCmapPropsAP(),
 
130
  UnsetCmapPropsAP(),
 
131
  NewAP(), 
 
132
  ReplaceAP(),
 
133
  PopupPixelAP(), 
 
134
  UpdatePixelAP(), 
 
135
  PopdownPixelAP(), 
 
136
  SelectRegionAP(), 
 
137
  CheckPoints(), 
 
138
  HighlightTO(),
 
139
  CloseCB(), 
 
140
  ReplaceCB(),
 
141
  NewCB(), 
 
142
  SelectCB(),
 
143
  SetupGC(), 
 
144
  ResizeEH(), 
 
145
  DragEH(), 
 
146
  StartRootPtrGrab(), 
 
147
  CreateRoot(), 
 
148
  GetImageAndAttributes(),
 
149
  PopupNewScale(), 
 
150
  RedoOldScale(),
 
151
  InitCursors(), 
 
152
  ParseSourceGeom();
 
153
 
 
154
static Window
 
155
  FindWindow();
 
156
 
 
157
static int
 
158
  Error(),
 
159
  Get_XColors();
 
160
 
 
161
static Pixel
 
162
  GetMaxIntensity(),
 
163
  GetMinIntensity();
 
164
#endif
 
165
 
 
166
 
 
167
 
 
168
/* application resources */
 
169
 
 
170
typedef struct { String geometry, source, mag, title; } OptionsRec;
 
171
static OptionsRec options;
 
172
 
 
173
#define Offset(field) XtOffsetOf(OptionsRec, field)
 
174
static XtResource resources[] = {
 
175
  {"geometry", "Geometry", XtRString, sizeof(String),
 
176
     Offset(geometry), XtRString, (XtPointer)NULL},
 
177
  {"mag", "Mag", XtRString, sizeof(String),
 
178
     Offset(mag), XtRString, (XtPointer)"5.0"},
 
179
  {"source", "Source", XtRString, sizeof(String),
 
180
     Offset(source), XtRString, (XtPointer)"SRCWIDTHxSRCHEIGHT"},
 
181
  {"title", XtCString, XtRString, sizeof(char *),
 
182
     Offset(title), XtRString, "xmag"},
 
183
};
 
184
#undef Offset
 
185
 
 
186
static XrmOptionDescRec optionDesc[] = {
 
187
  {"-bd",         "*borderColor", XrmoptionSepArg, (XtPointer)NULL},
 
188
  {"-bg",         "*background",   XrmoptionSepArg, (XtPointer)NULL},
 
189
  {"-bw",         "*borderWidth", XrmoptionSepArg, (XtPointer)NULL},
 
190
  
 
191
  {"-geometry", "*geometry", XrmoptionSepArg, (XtPointer)NULL},
 
192
  {"-mag",      "*mag",                XrmoptionSepArg, (XtPointer)NULL},
 
193
  {"-source",   "*source",             XrmoptionSepArg, (XtPointer)NULL},
 
194
  {"-title",    "*title",              XrmoptionSepArg, (XtPointer)NULL},
 
195
};
 
196
 
 
197
 
 
198
 
 
199
/* action table */
 
200
 
 
201
static XtActionsRec actions_table[] = {
 
202
  {"close", CloseAP},
 
203
  {"set-colors", SetCmapPropsAP},
 
204
  {"unset-colors", UnsetCmapPropsAP},
 
205
  {"new", NewAP},
 
206
  {"replace", ReplaceAP},
 
207
  {"popup-pixel", PopupPixelAP},
 
208
  {"update-pixel", UpdatePixelAP},
 
209
  {"popdown-pixel", PopdownPixelAP},
 
210
  {"select-region", SelectRegionAP}
 
211
};
 
212
 
 
213
 
 
214
 
 
215
/*
 
216
 * Error() -- Error handler:  Catch a bad match in magnifing an
 
217
 *            area that contains bits of different depths.
 
218
 */
 
219
static int 
 
220
Error(Display *dpy, XErrorEvent *err)
 
221
{
 
222
  (void) XmuPrintDefaultErrorMessage (dpy, err, stderr);
 
223
  return 0;
 
224
}
 
225
 
 
226
 
 
227
/*
 
228
 * CloseAP() -- Close this dialog.  If its the last one exit the program.
 
229
 *          
 
230
 */
 
231
static void                     /* ARGSUSED */
 
232
CloseAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
233
{
 
234
  Arg wargs[2]; int n; hlPtr data;
 
235
  if (!--numXmags) exit(0);
 
236
  if (event->type != ClientMessage) {
 
237
    n = 0;                      /* get user data */
 
238
    XtSetArg(wargs[0], XtNuserData, &data); n++;
 
239
    XtGetValues(w, wargs, n); 
 
240
    w = data->scaleShell;
 
241
  }
 
242
  XtPopdown(w);
 
243
  XtDestroyWidget(w);
 
244
}
 
245
 
 
246
 
 
247
 
 
248
/*
 
249
 * SetCmapPropsAP() -- Put the scale widget first in WM_COLORMAP_WINDOWS
 
250
 *                     
 
251
 */
 
252
static void                     /* ARGSUSED */
 
253
SetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
254
{
 
255
  Arg wargs[2]; int n; hlPtr data;
 
256
  n = 0;                        /* get user data */
 
257
  XtSetArg(wargs[0], XtNuserData, &data); n++;
 
258
  XtGetValues(w, wargs, n);
 
259
  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
 
260
    data->cmapWinList[0] = data->scaleInstance;
 
261
    data->cmapWinList[1] = data->scaleShell;
 
262
    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
 
263
  }
 
264
}
 
265
 
 
266
 
 
267
 
 
268
/*
 
269
 * UnsetCmapPropsAP() -- Put the shell first in WM_COLORMAP_WINDOWS
 
270
 *                     
 
271
 */
 
272
static void                     /* ARGSUSED */
 
273
UnsetCmapPropsAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
274
{
 
275
  Arg wargs[2]; int n; hlPtr data;
 
276
  n = 0;                        /* get user data */
 
277
  XtSetArg(wargs[0], XtNuserData, &data); n++;
 
278
  XtGetValues(w, wargs, n);
 
279
  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
 
280
    data->cmapWinList[0] = data->scaleShell;
 
281
    data->cmapWinList[1] = data->scaleInstance;
 
282
    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
 
283
  }
 
284
}
 
285
 
 
286
 
 
287
 
 
288
/*
 
289
 * NewAP() -- Create an additional xmag dialog. THIS IS A COPY OF NewEH
 
290
 *                                              FIND A BETTER WAY....
 
291
 */
 
292
static void                     /* ARGSUSED */
 
293
NewAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
294
{
 
295
  StartRootPtrGrab(True, NULL);
 
296
}
 
297
 
 
298
 
 
299
 
 
300
/*
 
301
 * ReplaceAP() -- Replace this particular xmag dialog.
 
302
 */
 
303
static void                     /* ARGSUSED */
 
304
ReplaceAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
305
{
 
306
  Arg wargs[2]; int n; hlPtr data;
 
307
  n = 0;                        /* get user data */
 
308
  XtSetArg(wargs[0], XtNuserData, &data); n++;
 
309
  XtGetValues(w, wargs, n); 
 
310
  StartRootPtrGrab(False, data);
 
311
}
 
312
 
 
313
 
 
314
 
 
315
/*
 
316
 * PopupPixelAP() -- Show pixel information.
 
317
 */
 
318
static void                     /* ARGSUSED */
 
319
PopupPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
320
{
 
321
    Position scale_x, scale_y;
 
322
    Dimension scale_height;
 
323
    Position label_x, label_y;
 
324
    Dimension label_height;
 
325
    int n;
 
326
    Arg wargs[3];
 
327
    hlPtr data;
 
328
 
 
329
    n = 0;                      /* get user data */
 
330
    XtSetArg(wargs[0], XtNuserData, &data); n++;
 
331
    XtGetValues(w, wargs, n);
 
332
 
 
333
    n = 0;
 
334
    XtSetArg(wargs[n], XtNheight, &scale_height); n++;
 
335
    XtGetValues(w, wargs, n);
 
336
    XtTranslateCoords(w, -1, -1, &scale_x, &scale_y);
 
337
    
 
338
    XtRealizeWidget(data->pixShell); /* to get the right height  */
 
339
 
 
340
    n = 0;
 
341
    XtSetArg(wargs[n], XtNheight, &label_height); n++;
 
342
    XtGetValues(data->pixShell, wargs, n);
 
343
    
 
344
    if ((double) event->xbutton.y / (double) scale_height > 0.5) {
 
345
        label_x = scale_x;
 
346
        label_y = scale_y;
 
347
    }
 
348
    else {
 
349
        label_x = scale_x;
 
350
        label_y = scale_y + scale_height - label_height;
 
351
    }
 
352
 
 
353
    n = 0;
 
354
    XtSetArg(wargs[n], XtNx, label_x); n++;
 
355
    XtSetArg(wargs[n], XtNy, label_y); n++;
 
356
    XtSetValues(data->pixShell, wargs, n);
 
357
    
 
358
    UpdatePixelAP(w, event, 0, 0);
 
359
}
 
360
 
 
361
 
 
362
 
 
363
/*
 
364
 * UpdatePixelAP() -- Update pixel information.
 
365
 */
 
366
static void                     /* ARGSUSED */
 
367
UpdatePixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
368
{
 
369
    Position x, y;
 
370
    Pixel pixel;
 
371
    XColor color;
 
372
    int n;
 
373
    Arg wargs[3];
 
374
    char string[80];
 
375
    hlPtr data;
 
376
 
 
377
    n = 0;
 
378
    XtSetArg(wargs[0], XtNuserData, &data); n++;
 
379
    XtGetValues(w, wargs, n);
 
380
 
 
381
    if (SWGetImagePixel(w, event->xbutton.x, event->xbutton.y, &x, &y, &pixel))
 
382
        XtPopdown(data->pixShell);
 
383
    else {
 
384
        color.pixel = pixel;
 
385
        XQueryColor(dpy, data->win_info.colormap, &color);
 
386
        sprintf(string, "Pixel %ld at (%d,%d) colored (%x,%x,%x).", 
 
387
                pixel, x + data->x, y + data->y,
 
388
                color.red, color.green, color.blue);
 
389
        n = 0;
 
390
        XtSetArg(wargs[n], XtNlabel, string); n++;    
 
391
        XtSetValues(data->pixLabel, wargs, n);
 
392
        XtPopup(data->pixShell, XtGrabNone);
 
393
    }
 
394
}
 
395
 
 
396
 
 
397
 
 
398
/*
 
399
 * PopdownPixelAP() -- Remove pixel info.
 
400
 */
 
401
static void                     /* ARGSUSED */
 
402
PopdownPixelAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
403
{
 
404
  int n;
 
405
  Arg wargs[3];
 
406
  hlPtr data = NULL;
 
407
  
 
408
  n = 0;
 
409
  XtSetArg(wargs[0], XtNuserData, &data); n++;
 
410
  XtGetValues(w, wargs, n);
 
411
 
 
412
  if (data)
 
413
    XtPopdown(data->pixShell);
 
414
}
 
415
 
 
416
 
 
417
 
 
418
static void                     /* ARGSUSED */
 
419
SelectRegionAP(Widget w, XEvent *event, String *params, Cardinal *num_params)
 
420
{    
 
421
/***** NOT SURE WHAT TO DO WITH THIS 
 
422
    if (app_resources.unmap)
 
423
        XtUnmapWidget(toplevel);
 
424
    Redisplay(XtDisplay(w), RootWindow(XtDisplay(w),
 
425
                                       DefaultScreen(XtDisplay(w))),
 
426
              source.width, source.height, 
 
427
              app_resources.freq, app_resources.puls, 
 
428
              ul_angle, lr_angle,
 
429
              app_resources.grab);
 
430
 
 
431
    if (app_resources.unmap)
 
432
        XtMapWidget(toplevel);
 
433
******/
 
434
}
 
435
 
 
436
 
 
437
 
 
438
/* 
 
439
 * CheckPoints() -- Change the cursor for the correct quadrant.
 
440
 *                  Make sure the first point is less than the second 
 
441
 *                  for drawing the selection rectangle.
 
442
 *
 
443
 */
 
444
static void 
 
445
CheckPoints(Position *x1, Position *x2, Position *y1, Position *y2)
 
446
{
 
447
  Position tmp; 
 
448
  Boolean above, left;
 
449
  Cursor newC;
 
450
  above = (*y2 < *y1); left = (*x2 < *x1); 
 
451
  if (above&&left) newC = ulAngle;
 
452
  else if (above&&!left) newC = urAngle;
 
453
  else if (!above&&!left) newC = lrAngle;
 
454
  else newC = llAngle;
 
455
  XChangeActivePointerGrab
 
456
    (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
 
457
     newC, CurrentTime);
 
458
  if (*x2 < *x1) { tmp = *x1; *x1 = *x2; *x2 = tmp; }
 
459
  if (*y2 < *y1) { tmp = *y1; *y1 = *y2; *y2 = tmp; }
 
460
}
 
461
 
 
462
 
 
463
 
 
464
/*
 
465
 * HighlightTO() -- Timer to highlight the selection box
 
466
 */
 
467
static void
 
468
HighlightTO(XtPointer closure, XtIntervalId *id)        /* ARGSUSED */
 
469
{
 
470
  hlPtr data = (hlPtr)closure;
 
471
  XGrabServer(dpy);
 
472
  if (data->selectMode == drag) {
 
473
    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 
 
474
                   data->x, data->y, data->width, data->height);
 
475
    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 
 
476
                   data->x, data->y, data->width, data->height);
 
477
  }
 
478
  else if (data->selectMode == resize) {        
 
479
    Position x1 = data->homeX,
 
480
             x2 = data->x,
 
481
             y1 = data->homeY,
 
482
             y2 = data->y;
 
483
    CheckPoints(&x1, &x2, &y1, &y2);
 
484
    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 
 
485
                   x1, y1, x2 - x1, y2 - y1);
 
486
    XDrawRectangle(dpy, DefaultRootWindow(dpy), data->gc, 
 
487
                   x1, y1, x2 - x1, y2 - y1);
 
488
  }
 
489
  XUngrabServer(dpy);
 
490
  if (data->selectMode != done)
 
491
    XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)data);
 
492
}
 
493
 
 
494
 
 
495
 
 
496
/*
 
497
 * CloseCB() -- Delete this xmag dialog.  If its the only one on the screen
 
498
 *             then exit.
 
499
 */
 
500
static void                     /* ARGSUSED */
 
501
CloseCB(Widget w, XtPointer clientData, XtPointer callData)
 
502
{
 
503
  Widget shell = (Widget)clientData;
 
504
  if (!--numXmags) exit(0);
 
505
  XtPopdown(shell);
 
506
  XtDestroyWidget(shell);
 
507
}
 
508
 
 
509
 
 
510
 
 
511
/*
 
512
 * ReplaceCB() -- Replace this particular xmag dialog.
 
513
 */
 
514
static void                     /* ARGSUSED */
 
515
ReplaceCB(Widget w, XtPointer clientData, XtPointer callData)
 
516
{
 
517
  hlPtr data = (hlPtr)clientData;
 
518
  StartRootPtrGrab(False, data);
 
519
}
 
520
 
 
521
 
 
522
 
 
523
/*
 
524
 * NewCB() -- Create an additional xmag dialog.
 
525
 */
 
526
static void                     /* ARGSUSED */
 
527
NewCB(Widget w, XtPointer clientData, XtPointer callData)
 
528
{
 
529
  StartRootPtrGrab(True, NULL);
 
530
}
 
531
 
 
532
 
 
533
 
 
534
/*
 
535
 * SelectCB() -- Own the primary selection.
 
536
 */
 
537
static void                     /* ARGSUSED */
 
538
SelectCB(Widget w, XtPointer clientData, XtPointer callData)
 
539
{
 
540
  hlPtr data = (hlPtr)clientData;
 
541
  SWGrabSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
 
542
}
 
543
 
 
544
 
 
545
 
 
546
/*
 
547
 * PasteCB() -- Paste from the primary selectin into xmag.
 
548
 */
 
549
static void                     /* ARGSUSED */
 
550
PasteCB(Widget w, XtPointer clientData, XtPointer callData)
 
551
{
 
552
  hlPtr data = (hlPtr)clientData;
 
553
  SWRequestSelection(data->scaleInstance, XtLastTimestampProcessed(dpy));
 
554
}
 
555
 
 
556
 
 
557
 
 
558
/*
 
559
 * SetupGC() -- Graphics context for magnification selection.
 
560
 */
 
561
static void 
 
562
SetupGC(void)
 
563
{
 
564
    selectGCV.function = GXxor;
 
565
    selectGCV.foreground = 1L;
 
566
    selectGCV.subwindow_mode = IncludeInferiors;
 
567
    selectGC = XtGetGC(toplevel, GCFunction|GCForeground|GCSubwindowMode,
 
568
                       &selectGCV);
 
569
}  
 
570
 
 
571
 
 
572
 
 
573
/*
 
574
 * FindWindow() -- Determin window the pointer is over.
 
575
 *
 
576
 */
 
577
static Window 
 
578
FindWindow(int x, int y)        /* Locatation of cursor */
 
579
{
 
580
  XWindowAttributes wa;
 
581
  Window findW = DefaultRootWindow(dpy), stopW, childW;
 
582
  XTranslateCoordinates(dpy, findW, findW,
 
583
                        x, y, &x, &y, &stopW);
 
584
  while (stopW) {
 
585
    XTranslateCoordinates(dpy, findW, stopW, 
 
586
                          x, y, &x, &y, &childW);
 
587
    findW = stopW;
 
588
    if (childW &&
 
589
        XGetWindowAttributes(dpy, childW, &wa) &&
 
590
        wa.class != InputOutput)
 
591
        break;
 
592
    stopW = childW;
 
593
  }
 
594
  return findW;
 
595
}
 
596
 
 
597
 
 
598
 
 
599
/*
 
600
 * ResizeEH() -- Event Handler for resize of selection box.
 
601
 */
 
602
static void 
 
603
ResizeEH(Widget w, XtPointer closure, XEvent *event, 
 
604
         Boolean *continue_to_dispatch) /* ARGSUSED */
 
605
{
 
606
  hlPtr data = (hlPtr)closure;
 
607
  switch (event->type) {
 
608
  case MotionNotify:
 
609
    data->x = event->xmotion.x_root;
 
610
    data->y = event->xmotion.y_root; 
 
611
    break;
 
612
  case ButtonRelease:
 
613
    GetImageAndAttributes(FindWindow(event->xmotion.x_root,
 
614
                        event->xmotion.y_root),
 
615
             min(data->homeX,event->xbutton.x_root),
 
616
             min(data->homeY,event->xbutton.y_root),
 
617
             abs(data->homeX - event->xbutton.x_root),
 
618
             abs(data->homeY - event->xbutton.y_root),
 
619
             data);
 
620
    if (data->newScale)
 
621
      PopupNewScale(data);
 
622
    else 
 
623
      SWSetImage(data->scaleInstance, data->image);
 
624
    XtUngrabPointer(w, CurrentTime);
 
625
/*****
 
626
    XtRemoveRawEventHandler(w, PointerMotionMask|ButtonReleaseMask,
 
627
                         True, ResizeEH, (XtPointer)data);
 
628
*****/
 
629
    XtRemoveEventHandler(w, PointerMotionMask|ButtonReleaseMask,
 
630
                         True, ResizeEH, (XtPointer)data);
 
631
    data->selectMode = done;
 
632
    break;
 
633
  }
 
634
}
 
635
 
 
636
 
 
637
 
 
638
/*
 
639
 * DragEH() -- Event Handler for draging selection box.
 
640
 */
 
641
static void 
 
642
DragEH(Widget w, XtPointer closure, XEvent *event, 
 
643
       Boolean *continue_to_dispatch) /* ARGSUSED */
 
644
{
 
645
  hlPtr data = (hlPtr)closure;
 
646
  switch (event->type) {
 
647
  case MotionNotify:            /* drag mode */
 
648
    data->x = event->xmotion.x_root;
 
649
    data->y = event->xmotion.y_root;
 
650
    break;
 
651
  case ButtonRelease:           /* end drag mode */
 
652
    if (event->xbutton.button == Button1) { /* get image */
 
653
      /* Problem: You can't get bits with XGetImage outside of its window.
 
654
       *          xmag will only do a GetImage on the actual window in the case
 
655
       *          where the depth of the window does not match the depth of
 
656
       *          the root window.
 
657
       */
 
658
      GetImageAndAttributes(FindWindow(event->xmotion.x_root, 
 
659
                          event->xmotion.y_root),
 
660
               event->xbutton.x_root, 
 
661
               event->xbutton.y_root,
 
662
               srcWidth, srcHeight, data);
 
663
      if (data->newScale)
 
664
        PopupNewScale(data);
 
665
      else
 
666
        RedoOldScale(data);
 
667
      XtUngrabPointer(w, CurrentTime);
 
668
      XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
 
669
                              ButtonReleaseMask, True, DragEH,
 
670
                              (XtPointer)data);
 
671
      data->selectMode = done;
 
672
    }
 
673
 
 
674
    break;
 
675
  case ButtonPress:     
 
676
    if (event->xbutton.button == Button2) {     /* turn on resize mode */
 
677
      data->homeX = event->xbutton.x_root; 
 
678
      data->homeY = event->xbutton.y_root;
 
679
      data->x = event->xbutton.x_root + srcWidth;
 
680
      data->y = event->xbutton.y_root + srcHeight;      
 
681
      data->selectMode = resize;
 
682
      XtRemoveRawEventHandler(w, PointerMotionMask|ButtonPressMask|
 
683
                           ButtonReleaseMask, True, DragEH, (XtPointer)data);
 
684
      XChangeActivePointerGrab
 
685
        (dpy, PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
 
686
         lrAngle, CurrentTime);
 
687
      XWarpPointer(dpy, None, None, 0, 0, 0, 0, 
 
688
                   srcWidth, srcHeight);
 
689
      XtAddEventHandler(w, PointerMotionMask|ButtonReleaseMask, 
 
690
                        True, ResizeEH, (XtPointer)data);
 
691
    }
 
692
    break;
 
693
  }
 
694
}
 
695
 
 
696
 
 
697
 
 
698
 
 
699
/*
 
700
 * StartRootPtrGrab() -- Bring up the selection box.
 
701
 *              
 
702
 */
 
703
static void
 
704
StartRootPtrGrab(int new,       /* do we cretate a new scale instance? */
 
705
                 hlPtr data)    /* highligh data */
 
706
{
 
707
  Window    rootR, childR;
 
708
  int       rootX, rootY, winX, winY;
 
709
  unsigned  int mask;
 
710
  hlPtr hlData;
 
711
  XtGrabPointer
 
712
    (root, False,
 
713
     PointerMotionMask|ButtonPressMask|ButtonReleaseMask,
 
714
     GrabModeAsync, GrabModeAsync, None, ulAngle, CurrentTime);
 
715
  XQueryPointer(dpy, DefaultRootWindow(dpy), &rootR, &childR, 
 
716
                &rootX, &rootY, &winX, &winY, &mask);
 
717
  if (new) {
 
718
    numXmags++;
 
719
    hlData = (hlPtr)XtMalloc(sizeof(hlStruct));
 
720
  }
 
721
  else hlData = data;
 
722
  hlData->newScale   = new;
 
723
  hlData->selectMode = drag;
 
724
  hlData->x          = rootX;
 
725
  hlData->y          = rootY;
 
726
  hlData->gc         = selectGC;
 
727
  hlData->width      = srcWidth;
 
728
  hlData->height     = srcHeight;
 
729
  XtAddRawEventHandler
 
730
    (root, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, 
 
731
     True, DragEH, (XtPointer)hlData);
 
732
  hlId = XtAppAddTimeOut(app, HLINTERVAL, HighlightTO, (XtPointer)hlData);
 
733
}
 
734
 
 
735
 
 
736
 
 
737
/*
 
738
 * CreateRoot() -- Create a root window widget. If the user specified x and y
 
739
 *                 in his source geometry then use this to directly get the
 
740
 *                 image.
 
741
 */
 
742
static void
 
743
CreateRoot(void)
 
744
{
 
745
  hlPtr data;
 
746
  root = XtCreateWidget("root", rootWindowWidgetClass, toplevel, NULL, 0);
 
747
  XtRealizeWidget(root);
 
748
  if (XValue & srcStat && YValue &srcStat) { 
 
749
    numXmags = 1;
 
750
    data = (hlPtr)XtMalloc(sizeof(hlStruct));
 
751
    data = data;
 
752
    data->newScale   = True;
 
753
    data->selectMode = drag;
 
754
    data->x          = srcX;
 
755
    data->y          = srcY;
 
756
    data->gc         = selectGC;
 
757
    data->width      = srcWidth;
 
758
    data->height     = srcHeight;
 
759
    GetImageAndAttributes(RootWindow(dpy, scr), srcX, srcY, srcWidth, 
 
760
                          srcHeight, data);
 
761
    PopupNewScale(data);
 
762
    return;
 
763
  }
 
764
}
 
765
 
 
766
 
 
767
/* 
 
768
 * GetImageAndAttributes() -- Get the image bits from the screen.
 
769
 *               We will also determin here the colormap, depth, and
 
770
 *               visual to be used for the magnification image.  
 
771
 */
 
772
static void 
 
773
GetImageAndAttributes(Window w, int x, int y, int width, int height, 
 
774
                      hlPtr data)
 
775
{
 
776
  /* get parameters of window being magnified */
 
777
  XGetWindowAttributes(dpy, w, &data->win_info);
 
778
 
 
779
  if (data->win_info.depth == DefaultDepth(dpy, scr)) {
 
780
    /* avoid off screen pixels */
 
781
    if (x < 0) x = 0; if (y < 0) y = 0;
 
782
    if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
 
783
    if (y + height > DisplayHeight(dpy,scr)) 
 
784
      y = DisplayHeight(dpy,scr) - height;
 
785
    data->x = x; data->y = y;
 
786
    /* get image pixels */
 
787
    data->image = XGetImage (dpy,
 
788
                             RootWindow(dpy, scr),
 
789
                             x, y,
 
790
                             width, height,
 
791
                             AllPlanes, ZPixmap);
 
792
  }
 
793
  else {
 
794
    int xInWin, yInWin; Window childWin;
 
795
    XTranslateCoordinates(dpy, DefaultRootWindow(dpy), w, x, y, 
 
796
                          &xInWin, &yInWin, &childWin);
 
797
    /* avoid off screen pixels */
 
798
    if (x + data->win_info.x < 0) x = abs(data->win_info.x);
 
799
    if (y + data->win_info.y < 0) y = abs(data->win_info.y);
 
800
    if (x + width > DisplayWidth(dpy,scr)) x = DisplayWidth(dpy,scr) - width;
 
801
    if (y + height > DisplayHeight(dpy,scr))
 
802
      y = DisplayHeight(dpy,scr) - height;
 
803
    data->x = x; data->y = y;
 
804
    data->image = XGetImage (dpy,
 
805
                             w,
 
806
                             xInWin, yInWin,
 
807
                             width, height,
 
808
                             AllPlanes, ZPixmap);
 
809
    
 
810
  }
 
811
}
 
812
 
 
813
 
 
814
 
 
815
/*
 
816
 * Get_XColors() Get the XColors of all pixels in image - returns # of colors
 
817
 *               This function was taken from xwd (thanks Bob...)
 
818
 */
 
819
#define lowbit(x) ((x) & (~(x) + 1))
 
820
static int 
 
821
Get_XColors(XWindowAttributes *win_info, XColor **colors)
 
822
{
 
823
    int i, ncolors;
 
824
 
 
825
    if (!win_info->colormap)
 
826
        return(0);
 
827
 
 
828
    ncolors = win_info->visual->map_entries;
 
829
    if (!(*colors = (XColor *) XtMalloc (sizeof(XColor) * ncolors)))
 
830
      XtError("Out of memory!");
 
831
 
 
832
    if (win_info->visual->class == DirectColor ||
 
833
        win_info->visual->class == TrueColor) {
 
834
        Pixel red, green, blue, red1, green1, blue1;
 
835
 
 
836
        red = green = blue = 0;
 
837
        red1 = lowbit(win_info->visual->red_mask);
 
838
        green1 = lowbit(win_info->visual->green_mask);
 
839
        blue1 = lowbit(win_info->visual->blue_mask);
 
840
        for (i=0; i<ncolors; i++) {
 
841
          (*colors)[i].pixel = red|green|blue;
 
842
          (*colors)[i].pad = 0;
 
843
          red += red1;
 
844
          if (red > win_info->visual->red_mask)
 
845
            red = 0;
 
846
          green += green1;
 
847
          if (green > win_info->visual->green_mask)
 
848
            green = 0;
 
849
          blue += blue1;
 
850
          if (blue > win_info->visual->blue_mask)
 
851
            blue = 0;
 
852
        }
 
853
    } else {
 
854
        for (i=0; i<ncolors; i++) {
 
855
          (*colors)[i].pixel = i;
 
856
          (*colors)[i].pad = 0;
 
857
        }
 
858
    }
 
859
 
 
860
    XQueryColors(dpy, win_info->colormap, *colors, ncolors);
 
861
 
 
862
    return(ncolors);
 
863
}
 
864
 
 
865
 
 
866
 
 
867
#define Intensity(cptr) (3.0*cptr->red+0.59*cptr->green+0.11*cptr->blue)
 
868
 
 
869
/*
 
870
 * GetMaxIntensity() -- Find the maximum intensity pixel value for a colormap.
 
871
 */
 
872
static Pixel
 
873
GetMaxIntensity(hlPtr data)
 
874
{
 
875
  XColor *colors = NULL, *mptr, *tptr;
 
876
  int i, ncolors;
 
877
 
 
878
  if (data->win_info.colormap == DefaultColormap(dpy, scr)) 
 
879
    return WhitePixel(dpy, scr);
 
880
  ncolors = Get_XColors(&data->win_info, &colors); 
 
881
  mptr = tptr = colors; tptr++;
 
882
  for (i=1; i<ncolors; i++) {
 
883
    if ((int)Intensity(mptr) < (int)Intensity(tptr)) 
 
884
      mptr = tptr;
 
885
    tptr++;
 
886
  }
 
887
  return mptr->pixel;
 
888
}
 
889
 
 
890
/*
 
891
 * GetMinIntensity() -- Find the minimum intensity pixel value for a colormap.
 
892
 */
 
893
static Pixel
 
894
GetMinIntensity(hlPtr data)
 
895
{
 
896
  XColor *colors = NULL, *mptr, *tptr;
 
897
  int i, ncolors;
 
898
 
 
899
  if (data->win_info.colormap == DefaultColormap(dpy, scr)) 
 
900
    return BlackPixel(dpy, scr);
 
901
  ncolors = Get_XColors(&data->win_info, &colors); 
 
902
  mptr = tptr = colors; tptr++;
 
903
  for (i=1; i<ncolors; i++)  {
 
904
    if ((int)Intensity(mptr) > (int)Intensity(tptr))
 
905
      mptr = tptr; 
 
906
    tptr++;
 
907
  }
 
908
  return mptr->pixel;
 
909
}
 
910
 
 
911
 
 
912
 
 
913
 
 
914
static Widget pane1, pane2, pane3, cclose, replace, new, select_w, paste, label;
 
915
 
 
916
/*
 
917
 * PopupNewScale() -- Create and popup a new scale composite.
 
918
 */
 
919
static void             
 
920
PopupNewScale(hlPtr data)
 
921
{
 
922
  Arg warg;
 
923
 
 
924
  data->scaleShell = 
 
925
    XtVaCreatePopupShell("xmag", topLevelShellWidgetClass, toplevel, 
 
926
                         XtNgeometry, (XtArgVal)options.geometry,
 
927
                         XtNtitle, (XtArgVal)options.title,
 
928
                         NULL);
 
929
  pane1 = XtCreateManagedWidget("pane1", panedWidgetClass, data->scaleShell,
 
930
                                (Arg *) NULL, 0);
 
931
  pane2 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
 
932
                                (Arg *) NULL, 0);
 
933
  cclose = XtCreateManagedWidget("close", commandWidgetClass, pane2,
 
934
                                 (Arg *) NULL, 0);
 
935
  XtAddCallback(cclose, XtNcallback, CloseCB, (XtPointer)data->scaleShell);
 
936
  replace = XtCreateManagedWidget("replace", commandWidgetClass, pane2,
 
937
                                  (Arg *) NULL, 0);
 
938
  XtAddCallback(replace, XtNcallback, ReplaceCB, (XtPointer)data);
 
939
  new = XtCreateManagedWidget("new", commandWidgetClass, pane2,
 
940
                              (Arg *) NULL, 0);
 
941
  XtAddCallback(new, XtNcallback, NewCB, (XtPointer)NULL);
 
942
  select_w = XtCreateManagedWidget("select", commandWidgetClass, pane2,
 
943
                              (Arg *) NULL, 0);
 
944
  XtAddCallback(select_w, XtNcallback, SelectCB, (XtPointer)data);
 
945
  paste = XtCreateManagedWidget("paste", commandWidgetClass, pane2,
 
946
                              (Arg *) NULL, 0);
 
947
  XtAddCallback(paste, XtNcallback, PasteCB, (XtPointer)data);
 
948
  label = XtCreateManagedWidget("helpLabel", labelWidgetClass, pane2,
 
949
                                (Arg *) NULL, 0);
 
950
  pane3 = XtCreateManagedWidget("pane2", panedWidgetClass, pane1,
 
951
                                (Arg *) NULL, 0);
 
952
  data->scaleInstance = 
 
953
    XtVaCreateManagedWidget("scale", scaleWidgetClass, 
 
954
                            pane3,
 
955
                            XtNvisual, (XtArgVal)data->win_info.visual,
 
956
                            XtNcolormap, (XtArgVal)data->win_info.colormap,
 
957
                            XtNdepth, (XtArgVal)data->win_info.depth,
 
958
                            XtNscaleX, (XtArgVal)options.mag,
 
959
                            XtNscaleY, (XtArgVal)options.mag,
 
960
                            NULL);
 
961
  SWSetImage(data->scaleInstance, data->image);
 
962
  XtOverrideTranslations
 
963
    (data->scaleShell,
 
964
     XtParseTranslationTable ("<Message>WM_PROTOCOLS: close()"));
 
965
  XtSetArg(warg, XtNuserData, data);
 
966
  XtSetValues(data->scaleInstance, &warg, 1);
 
967
  data->pixShell = 
 
968
    XtVaCreatePopupShell("pixShell", overrideShellWidgetClass, 
 
969
                         toplevel,
 
970
                         XtNvisual, (XtArgVal)data->win_info.visual,
 
971
                         XtNcolormap, (XtArgVal)data->win_info.colormap,
 
972
                         XtNdepth, (XtArgVal)data->win_info.depth,
 
973
                         XtNborderWidth, (XtPointer)0,
 
974
                         NULL);
 
975
  data->pixLabel = 
 
976
    XtVaCreateManagedWidget("pixLabel", labelWidgetClass, 
 
977
                            data->pixShell, 
 
978
                            XtNforeground, (XtPointer)GetMaxIntensity(data),
 
979
                            XtNbackground, (XtPointer)GetMinIntensity(data),
 
980
                            XtNborderWidth, (XtPointer)0,
 
981
                            NULL);
 
982
  XtInstallAllAccelerators(pane1, pane1);       /* install accelerators */
 
983
  if (data->newScale) {
 
984
    XtPopup(data->scaleShell, XtGrabNone);
 
985
    (void) XSetWMProtocols      /* ICCCM delete window */
 
986
      (dpy, XtWindow(data->scaleShell), &wm_delete_window, 1);
 
987
  }
 
988
  if (data->win_info.colormap != DefaultColormap(dpy, scr)) {
 
989
    data->cmapWinList[0] = data->scaleShell; 
 
990
    data->cmapWinList[1] = data->scaleInstance;
 
991
    XtSetWMColormapWindows(data->scaleShell, data->cmapWinList, 2);
 
992
  }
 
993
}
 
994
 
 
995
 
 
996
 
 
997
/*
 
998
 * RedoOldScale() -- If the visual, depth, or colormap has changed, unrealize
 
999
 *                   the scale widget and change its colormap/depth/visual.
 
1000
 *                   Then re-realize it.  Also do this for the pixel display
 
1001
 *                   widget.
 
1002
 */
 
1003
static void
 
1004
RedoOldScale(hlPtr data)
 
1005
{
 
1006
  Arg wargs[3];
 
1007
  int n;
 
1008
  Visual *oldVis;
 
1009
  int oldDepth;
 
1010
  Colormap oldCmap;
 
1011
 
 
1012
  n=0;
 
1013
  XtSetArg(wargs[n], XtNvisual, &oldVis); n++;
 
1014
  XtSetArg(wargs[n], XtNdepth, &oldDepth); n++;
 
1015
  XtSetArg(wargs[n], XtNcolormap, &oldCmap); n++;
 
1016
  XtGetValues(data->scaleInstance, wargs, n);  
 
1017
  if (oldVis == data->win_info.visual && oldDepth == data->win_info.depth
 
1018
      && oldCmap == data->win_info.colormap) {
 
1019
    SWSetImage(data->scaleInstance, data->image);    
 
1020
    return;
 
1021
  }
 
1022
  /* get width and height, save and reuse them */
 
1023
  XtUnmanageChild(data->scaleInstance);
 
1024
  XtUnrealizeWidget(data->scaleInstance);
 
1025
  n=0;
 
1026
  XtSetArg(wargs[n], XtNcolormap, data->win_info.colormap); n++;
 
1027
  XtSetArg(wargs[n], XtNdepth, data->win_info.depth); n++;
 
1028
  XtSetArg(wargs[n], XtNvisual, data->win_info.visual); n++;
 
1029
  XtSetValues(data->scaleInstance, wargs, n);
 
1030
  n=0;
 
1031
  XtSetArg(wargs[n], XtNforeground, GetMaxIntensity(data)); n++;
 
1032
  XtSetArg(wargs[n], XtNbackground, GetMinIntensity(data)); n++;
 
1033
  XtSetValues(data->pixLabel, wargs, n);
 
1034
  SWSetImage(data->scaleInstance, data->image); 
 
1035
  XtRealizeWidget(data->scaleInstance);
 
1036
  XtManageChild(data->scaleInstance);
 
1037
}
 
1038
 
 
1039
 
 
1040
 
 
1041
/*
 
1042
 * InitCursors() -- Create our cursors for area selection.
 
1043
 */
 
1044
static void
 
1045
InitCursors(void)
 
1046
{
 
1047
  ulAngle = XCreateFontCursor(dpy, XC_ul_angle);
 
1048
  urAngle = XCreateFontCursor(dpy, XC_ur_angle);
 
1049
  lrAngle = XCreateFontCursor(dpy, XC_lr_angle);
 
1050
  llAngle = XCreateFontCursor(dpy, XC_ll_angle);
 
1051
}
 
1052
 
 
1053
 
 
1054
 
 
1055
/*
 
1056
 * ParseSourceGeom() -- Determin dimensions of area to magnify from resources.
 
1057
 */
 
1058
static void 
 
1059
ParseSourceGeom(void)
 
1060
{
 
1061
                                /* source */
 
1062
  srcStat = 
 
1063
    XParseGeometry(options.source, &srcX, &srcY, &srcWidth, &srcHeight);
 
1064
  if (!srcWidth) srcWidth = SRCWIDTH;
 
1065
  if (!srcHeight) srcHeight = SRCHEIGHT;
 
1066
  if (XNegative & srcStat) srcX = DisplayWidth(dpy, scr) + srcX - srcWidth;
 
1067
  if (YNegative & srcStat) srcY = DisplayHeight(dpy, scr) + srcY - srcHeight;
 
1068
                                /* mag */
 
1069
}
 
1070
 
 
1071
 
 
1072
 
 
1073
/*
 
1074
 * Main program.
 
1075
 */
 
1076
int 
 
1077
main(int argc, char *argv[])
 
1078
{
 
1079
  XSetErrorHandler(Error);
 
1080
    
 
1081
                                /* SUPPRESS 594 */
 
1082
  toplevel = XtAppInitialize(&app, "Xmag", optionDesc, XtNumber(optionDesc),
 
1083
                             &argc, argv, NULL,
 
1084
                             NULL, 0);
 
1085
 
 
1086
  dpy = XtDisplay(toplevel);
 
1087
  scr = DefaultScreen(dpy);
 
1088
  XtGetApplicationResources(toplevel, (XtPointer) &options, resources,
 
1089
                            XtNumber(resources), NULL, 0);
 
1090
  if (argc != 1) {
 
1091
    fprintf (stderr,
 
1092
            "usage:  xmag [-source geom] [-mag magfactor] [-toolkitoption]\n");
 
1093
    exit(1);
 
1094
  }
 
1095
  
 
1096
 
 
1097
  ParseSourceGeom();
 
1098
  XtAppAddActions(app, actions_table, XtNumber(actions_table));
 
1099
  InitCursors();
 
1100
  SetupGC();
 
1101
  CreateRoot();
 
1102
  if (!(XValue & srcStat && YValue & srcStat))
 
1103
    StartRootPtrGrab(True, (hlPtr)NULL);
 
1104
  wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
 
1105
  XtAppMainLoop(app);
 
1106
  exit(0);
 
1107
}