earlybrowserreborn - Blame information for rev 4

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 roytam 1 /*
2  * Copyright 1990-93 Pei-Yuan Wei.      All rights reserved.
3  *
4  * Permission to use, copy, and/or distribute for any purpose and
5  * without fee is hereby granted, provided that both the above copyright
6  * notice and this permission notice appear in all copies and derived works.
7  * Fees for distribution or use of this software or derived works may only
8  * be charged with express written permission of the copyright holder.
9  * This software is provided ``as is'' without express or implied warranty.
10  */
11 /*
12  * event_x.c
13  *
14  * Scott Silvey 6/21/93: broken up eventLoop() into smaller pieces.
15  */
16 #include "utils.h"
17 #include "X11/Xlib.h"
18 #include "X11/cursorfont.h"
19 #include "X11/keysym.h"
20 #include "X11/keysymdef.h"
21 #include <sys/param.h>
22 #include <sys/types.h>
23 #include <signal.h>
24 #include <sys/time.h>
25 #include <pwd.h>
26 #include <ctype.h>
27 #include "mystrings.h"
28 #include "error.h"
29 #include "hash.h"
30 #include "ident.h"
31 #include "obj.h"
32 #include "vlist.h"
33 #include "packet.h"
34 #include "membership.h"
35 #include "class.h"
36 #include "slotaccess.h"
37 #include "classlist.h"
38 #include "glib.h"
39 #include "event.h"
40 #include "misc.h"
41  
42 #include <netdb.h>
43 #include <sys/socket.h>
44 #include <arpa/inet.h>
45 #include <netinet/in.h>
46 #ifdef _AIX
47 #include <sys/select.h>
48 #endif
49  
4 roytam 50 #ifndef SIGEMT
51 #define NO_SIGEMT
52 #define SIGEMT SIGUNUSED
53 #endif
54 #ifndef SIGSYS
55 #define NO_SIGSYS
56 #define SIGSYS SIGUNUSED
57 #endif
58  
1 roytam 59 static int signal_fatal[] = {
60         SIGBUS, SIGFPE, SIGEMT, SIGILL, SIGSEGV, SIGSYS, 0
61 };
62 static int signal_nonfatal[] = {
63         SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2, 0
64 };
65  
66 typedef struct TimeInfo {
67         struct timeval time;
68         struct TimeInfo *next;
69         int (*func)();
70         VObj *obj;
71         int argc;
72         Packet *argv;
73 } TimeInfo;
74  
75 #define EVENT_MASK_ABSOLUTE \
76         Button1MotionMask | StructureNotifyMask | ExposureMask
77  
78 #define EVENT_MASK_DEFAULT \
79         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
80         PointerMotionMask | PointerMotionHintMask | EnterWindowMask | \
81         LeaveWindowMask | Button1MotionMask | StructureNotifyMask | \
82         ExposureMask
83  
84 int finish = 0;
85 int obj_track = 0;
86 int mouse_track = 0;
87 int objectPeekFlag = 0;
88 int flag_window_tracking = 0;
89 int mouseButtonPressedState = 0;
90 FILE *user_action_tracking = NULL;
91  
92 IntPair mouse;
93  
94 XEvent e;
95  
96 #define KEYBUFSIZE 1
97 char keybuf[KEYBUFSIZE];
98  
99 char keyStat_key;
100 int keyStat_control;
101 int keyStat_shift;
102  
103 int max_socks = NOFILE;
104 fd_set read_mask;
105 VObj *objFDList[NOFILE]; /* list of association between fd and object */
106 TimeInfo *firstTimeInfo = NULL;
107  
108 int async_event = 0;
109  
110 /* forward decl */
111 char *eventChar();
112 void processPeekKeys();
113 int checkParam();
114 void process_event();
115 void signalHandler();
116  
117 VObj *reparented_obj = NULL;
118 VObj *floatingObject = NULL;
119  
120 VObj *xselectionObj = NULL; /* object that has data for x clip buffer */
121 char *sharedSelectionBuffer = NULL;
122  
123 int modalState = 0;
124 Packet *modalResult;
125  
126 char *eventStr[] = {
127         "unknown event 0",
128         "unknown event 1",
129         "KeyPress",
130         "KeyRelease",
131         "ButtonPress",
132         "ButtonRelease",
133         "MotionNotify",
134         "EnterNotify",
135         "LeaveNotify",
136         "FocusIn",
137         "FocusOut",
138         "KeymapNotify",
139         "Expose",
140         "GraphicsExpose",
141         "NoExpose",
142         "VisibilityNotify",
143         "CreateNotify",
144         "DestroyNotify",
145         "UnmapNotify",
146         "MapNotify",
147         "MapRequest",
148         "ReparentNotify",
149         "ConfigureNotify",
150         "ConfigureRequest",
151         "GravityNotify",
152         "ResizeRequest",
153         "CirculateNotify",
154         "CirculateRequest",
155         "PropertyNotify",
156         "SelectionClear",
157         "SelectionRequest",
158         "SelectionNotify",
159         "ColormapNotify",
160         "ClientMessage",
161         "MappingNotify",
162         "LASTEvent"
163 };
164  
165 /*
166  * to be initialized by init_event
167  */
168 Packet *result;         /* scrap packets */
169 Packet *result2;
170  
171 int intBuff[4];         /* temporary buffers */
172  
173 int init_event()
174 {
175         int i;
176  
177         /* initialize object-fileDescriptor list */
178         for (i = 0; i < max_socks; i++) objFDList[i] = NULL;
179  
180         for (i = 0; signal_nonfatal[i]; i++)
181                 signal(signal_nonfatal[i], signalHandler);
182         for (i = 0; signal_fatal[i]; i++)
183                 signal(signal_fatal[i], signalHandler);
184  
185         result = makePacket();
186         result2 = makePacket();
187         modalResult = makePacket();
188  
189         return 1;
190 }
191  
192 void signalHandler(sig)
193         int sig;
194 {
195         static int exiting = 0;
196  
197         if (exiting == 1) exit(0); /* alright already */
198  
199         switch (sig) {
200         /* fatal signals */
201         case SIGBUS:
202         case SIGFPE:
4 roytam 203 #ifndef NO_SIGEMT
1 roytam 204         case SIGEMT:
4 roytam 205 #endif
1 roytam 206         case SIGILL:
207         case SIGSEGV:
4 roytam 208 #ifndef NO_SIGSYS
1 roytam 209         case SIGSYS:
4 roytam 210 #endif
1 roytam 211                 fprintf(stderr,
212                         "signalHandler: caught fatal signal %d. Exiting.\n",
213                         sig);
214                 fflush(stderr);
215                 exit(0);
216         break;
217         case SIGHUP:
218         case SIGINT:
219         case SIGPIPE:
220         case SIGQUIT:
221         case SIGTERM:
222         case SIGUSR1:
223         case SIGUSR2:
224         default:
225                 exiting = 1;
226  
227                 fprintf(stderr,
228                         "signalHandler: caught nonfatal signal %d.\n",
229                         sig);
230                 fprintf(stderr, "signalHandler: freeing fonts.\n");
231                 fflush(stderr);
232  
233                 free_fonts();
234  
235                 fprintf(stderr, "signalHandler: freeing X resources.\n");
236                 fflush(stderr);
237  
238                 freeAllObjects();
239  
240                 fprintf(stderr, "signalHandler: exiting.\n");
241                 fflush(stderr);
242  
243                 exit(0);
244         break;
245         }
246 }
247  
248 /*
249  * HANDLE_EVENT() ...
250  *
251  * For Viola in library mode where calling program has its own event loop.
252  * This routine processes the event passed by the calling program.
253  */
254 void violaProcessEvent(e)
255     XEvent *e;
256 {
257     VObj *topObj, *obj;
258     HashEntry *hentry;
259     Window w;
260  
261     w = e->xany.window;
262     mouse.x = mouseX(e);
263     mouse.y = mouseY(e);
264  
265     if (mouse_track)
266         fprintf(stderr, "mouse.x=%d, mouse.y%d\n", mouse.x, mouse.y);
267  
268     hentry = window2Obj->get(window2Obj, (long)w);
269     if (hentry) {
270         obj = (VObj*)hentry->val;
271         if (obj && validObjectP(obj)/*XXX probably unnecessary now */) {
272             VCurrentObj = obj;
273             if (flag_window_tracking &&
274                 VCurrentObj != VPrevObj) {
275                 fprintf(stderr, "CurrentObj=\"%s\"\n", GET_name(VCurrentObj));
276             }
277             if (GET_lock(VCurrentObj) && GET_window(VCurrentObj))
278                 process_event(e, ACTION_TOOL);
279             else
280                 process_event(e, currentTool);
281         } else {
282           if (verbose) fprintf(stderr, "can't find object!\n");
283         }
284     } else {
285         if (verbose)
286             fprintf(stderr, "Can't find object associated with window.\n");
287     }
288 }
289  
290  
291 static struct timeval noblocktimeval = {0,0};
292 /*
293  * VIOLA_IDLE_EVENT() ... Called by the main program each time through its
294  * event loop when there isn't an event waiting on the queue.
295  *
296  * This routine selects on all open sockets.  When one has read info, an
297  * "input" message is send to the object that owns the socket.
298  *
299  * Derived from eventLoop().
300  *
301  */
302 void violaIdleEvent()
303 {
304         int i, bits;
305         fd_set cur_read_mask;
306         TimeInfo *tip;
307         struct timeval timeout, timenow, *timeval=NULL;
308         struct timeval time;
309         VObj *topObj, *obj;
310  
311         FD_SET(ConnectionNumber(display), &read_mask);
312  
313         if (firstTimeInfo) {
314                 tip = firstTimeInfo;
315                 gettimeofday(&timenow, (struct timezone*)NULL);
316  
317                 timeout.tv_sec = firstTimeInfo->time.tv_sec -
318                         timenow.tv_sec;
319                 timeout.tv_usec = firstTimeInfo->time.tv_usec -
320                         timenow.tv_usec;
321  
322                 if (timeout.tv_usec > 1000000) {
323                         timeout.tv_usec -= 1000000;
324                         timeout.tv_sec += 1;
325                 }
326                 if (timeout.tv_sec < 0) timeout.tv_sec = 0;
327                 if (timeout.tv_usec < 0) timeout.tv_usec = 0;
328                 timeval = &timeout;
329         }
330  
331         bcopy(&read_mask, &cur_read_mask, sizeof(cur_read_mask));
332  
333 /*      fprintf(stderr, "]\n");
334 */
335         bits = select(max_socks, &cur_read_mask,
336                       (fd_set*)NULL, (fd_set*)NULL, timeval);
337  
338         if (bits < 0) {
339                 perror("violaIdleEvent(): select() error: ");
340                 return;
341         }
342  
343         if (timeval && !bits) {
344                 tip = firstTimeInfo;
345                 firstTimeInfo = firstTimeInfo->next;
346                 (tip->func)(tip->obj, tip->argv, tip->argc);
347                 if (tip->argv) free(tip->argv);
348                 free(tip);
349         }
350  
351         if (!FD_ISSET(ConnectionNumber(display), &cur_read_mask)) {
352                 for (i = 0; bits && i < max_socks; i++) {
353                         if (!FD_ISSET(i, &cur_read_mask)) continue;
354                         /* tell object to handle socket data */
355                         if (obj = objFDList[i]) {
356                                 if (verbose) {
357                                         sprintf(buff,
358                 "data in socket number = %d, obj = %s\n", i, GET_name(obj));
359                                         fprintf(stderr, buff);
360                                         messageToUser(NULL,
361                                                 MESSAGE_DEBUG, buff);
362                                 }
363                                 sendMessage1(obj, "input");
364                         } else {
365                                 sprintf(buff,
366                 "data in fd = %d, but no associated object. closing it.\n", i);
367                                 fprintf(stderr, buff);
368                                 close(i);
369                         }
370                         bits--;
371                 }
372         }
373 }
374  
375 /*
376  *
377  */
378 int eventLoop()
379 {
380         VObj *topObj, *obj;
381         HashEntry *hentry;
382         TimeInfo *tip;
383         int lock = 0;
384         int i;
385         Window w;
386         fd_set cur_read_mask;
387         struct timeval timeout, timenow, *timeval = NULL;
388         int bits;
389  
390         FD_SET(ConnectionNumber(display), &read_mask);
391  
392         while (!finish) {
393  
394                 if (async_event) {
395                         /* Handle async_event */
396                         async_event = 0;
397                 }
398                 /* changeToNormalMouseCursor();*/
399  
400                 if (XPending(display)) {
401                         FD_SET(ConnectionNumber(display), &cur_read_mask);
402                 } else {
403                         struct timeval time;
404  
405                         if (firstTimeInfo) {
406                                 tip = firstTimeInfo;
407                                 gettimeofday(&timenow, (struct timezone*)NULL);
408  
409                                 timeout.tv_sec = firstTimeInfo->time.tv_sec -
410                                                         timenow.tv_sec;
411                                 timeout.tv_usec = firstTimeInfo->time.tv_usec -
412                                                         timenow.tv_usec;
413  
414                                 if (timeout.tv_usec > 1000000) {
415                                         timeout.tv_usec -= 1000000;
416                                         timeout.tv_sec += 1;
417                                 }
418                                 if (timeout.tv_sec < 0) timeout.tv_sec = 0;
419                                 if (timeout.tv_usec < 0) timeout.tv_usec = 0;
420                                 timeval = &timeout;
421 /*
422                                 gettimeofday(&time, (struct timezone*)NULL);
423                                 printf("before select: %d,%d now\n",
424                                         time.tv_sec, time.tv_usec);
425                                 printf("timeout : %d,%d \n",
426                                         timeout.tv_sec, timeout.tv_usec);
427 */
428                         }
429                         bcopy(&read_mask, &cur_read_mask,sizeof cur_read_mask);
430  
431                         bits = select(max_socks, &cur_read_mask,
432                                         (fd_set*)NULL,
433                                         (fd_set*)NULL,
434                                         (struct timeval*)timeval);
435  
436                         if (timeval && !bits) {
437                                 tip = firstTimeInfo;
438                                 firstTimeInfo = firstTimeInfo->next;
439                                 (tip->func)(tip->obj, tip->argv, tip->argc);
440                                 if (tip->argv) {
441                                         int i = tip->argc;
442                                         while (--i >= 0) {
443                                                 clearPacket(&(tip->argv[i]));
444                                         }
445                                         free(tip->argv);
446                                 }
447                                 free(tip);
448                         }
449                         timeval = NULL;
450                 }
451  
452                 if (!FD_ISSET(ConnectionNumber(display), &cur_read_mask)) {
453                         for (i = 0; bits && i < max_socks; i++) {
454                                 if (!FD_ISSET(i, &cur_read_mask)) continue;
455                                 /* tell object to handle socket data */
456                                 if (obj = objFDList[i]) {
457  
458                                         if (verbose) {
459                                                 sprintf(buff,
460                                                         "data in socket number = %d, obj = %s\n",
461                                                         i, GET_name(obj));
462                                                 fprintf(stderr, buff);
463  
464                                                 messageToUser(NULL, MESSAGE_DEBUG, buff);
465                                         }
466                                         sendMessage1(obj, "input");
467  
468                                 } else {
469                                         sprintf(buff,
470                                                 "data in fd = %d, but no associated object. closing it.\n",
471                                                 i);
472 /*
473                                         messageToUser(NULL, MESSAGE_DEBUG, buff);
474 */
475                                         fprintf(stderr, buff);
476                                         close(i);
477                                 }
478                                 bits--;
479                         }
480                 } else {
481                         XNextEvent(display, &e);
482  
483                         /* super hack */
484 /*
485                         if (e.type == MapNotify) {
486                           if (verbose) {
487                                 w = eventWindow(e);
488                                 printf("ignoring event %s. w=ox%x\n",
489                                         eventStr[e.type], w);
490                           }
491                           continue;
492                         }
493 */
494                         w = eventWindow(e);
495                         mouse.x = mouseX(e);
496                         mouse.y = mouseY(e);
497  
498                         if (mouse_track) {
499                                 fprintf(stderr, "mouse.x=%d, mouse.y%d\n",
500                                          mouse.x, mouse.y);
501                         }
502                         obj = findWindowObject(w);
503                         if (obj) {
504                                 VCurrentObj = obj;
505                                 if (flag_window_tracking &&
506                                     VCurrentObj != VPrevObj) {
507                                         fprintf(stderr,
508                                                 "CurrentObj=\"%s\"\n",
509                                                 GET_name(VCurrentObj));
510                                 }
511                                 if (GET_lock(VCurrentObj)
512                                     && GET_window(VCurrentObj)) {
513                                         process_event(&e, ACTION_TOOL);
514                                 } else {
515                                         process_event(&e, currentTool);
516                                 }
517                         } else {
518 /*                              fprintf(stderr, "can't find object!\n");*/
519                         }
520 /*
521                         hentry = window2Obj->get(window2Obj, (long)w);
522                         if (hentry) {
523                                 obj = (VObj*)hentry->val;
524                                 if (obj) {
525                                         VCurrentObj = obj;
526                                         if (flag_window_tracking &&
527                                             VCurrentObj != VPrevObj) {
528                                                 fprintf(stderr,
529                                                         "CurrentObj=\"%s\"\n",
530                                                         GET_name(VCurrentObj));
531                                         }
532                                         if (GET_lock(VCurrentObj)
533                                             && GET_window(VCurrentObj)) {
534                                                 process_event(&e, ACTION_TOOL);
535                                         } else {
536                                                 process_event(&e, currentTool);
537                                         }
538                                 } else {
539                                   fprintf(stderr,
540                                           "can't find object!\n");
541                                 }
542                         } else {
543                           if (verbose)
544                             fprintf(stderr,
545                                 "Can't find object associated with window.\n");
546                         }
547 */
548                 }
549         }
550 }
551  
552 void process_event(ep, tool)
553         XEvent *ep;
554         int tool;
555 {
556         static VObj *dragObj = NULL;
557         static int resize_corner, mouseDown = 0, from_x, from_y;
558 /*      Window w = GET_window(VCurrentObj);
559 */
560         Window w;
561  
562 /*      if (verbose) {
563                 XExposeEvent *eep = (XExposeEvent*)ep;
564                 VObj *obj;
565                 w = eep->window;
566                 obj = findWindowObject(w);
567  
568                 fprintf(stderr,
569                         "Event=%d %18s objw=0x%x obj=0x%x %s\n",
570                         eventType(*ep), eventStr[eventType(*ep)],
571                         w, obj, GET_name(obj));
572         }
573 */
574         if (dragObj) {
575                 if (GET_window(dragObj) == 0) {
576 /*                      if (verbose)
577                                 fprintf(stderr,
578                                         "** w=0 in dragObj =%s\n",
579                                         GET_name(dragObj));
580 */
581                         dragObj = NULL;
582                         return;
583                 }
584         }
585         switch (eventType(*ep)) {
586         case KeyPress:
587                 handle_KeyPress(ep);
588         break;
589  
590         case KeyRelease:
591                 handle_KeyRelease(ep);
592         break;
593  
594         case EnterNotify:
595                 handle_EnterNotify(ep, &dragObj, tool, &mouseDown);
596         break;
597  
598         case LeaveNotify:
599                 handle_LeaveNotify(ep, &dragObj, tool, &mouseDown);
600  
601                 keyStat_control = 0;
602                 keyStat_shift = 0;
603  
604                 /*processPeekKeys();*/
605         break;
606  
607         case ButtonPress:
608                 handle_ButtonPress(ep, &dragObj, tool, &resize_corner,
609                                    &mouseDown, &from_x, &from_y);
610         break;
611  
612         case ButtonRelease:
613                 handle_ButtonRelease(ep, &dragObj, tool, &resize_corner,
614                                      &mouseDown);
615                 break;
616  
617         case MotionNotify:
618                 handle_MotionNotify(ep, &dragObj, tool, &resize_corner,
619                                     &mouseDown, &from_x, &from_y);
620                 break;
621  
622         case MapNotify: {
623                 VObj *obj;
624                 XMapEvent *eep = (XMapEvent*)ep;
625  
626 /*if (verbose) printf("MapNotify! w = 0x%x\n", (XMapEvent*)eep->window);*/
627  
628                 obj = findWindowObject((XMapEvent*)eep->window);
629  
630                 if (obj) {
631 /*
632                         if (GET_visible(obj)) {
633 if (verbose) printf("MapNotify! w = ox%x obj=%s\n",
634                                 (XMapEvent*)eep->window, GET_name(obj));
635                                 SET_window(obj, (XMapEvent*)eep->window);
636                         } else {
637 if (verbose) printf("MapNotify! w = ox%x obj=%s not IGNORED\n",
638                                 (XMapEvent*)eep->window, GET_name(obj));
639                                 SET_window(obj, (XMapEvent*)eep->window);
640                         }
641 */
642                         SET_visible(obj, 1);
643                 }
644                 if (reparented_obj) {
645                         GLDrawRubberFrame(reparented_obj,
646                                         GET_x(reparented_obj) + 1,
647                                         GET_y(reparented_obj) + 1,
648                                         GET_x(reparented_obj)
649                                           + GET_width(reparented_obj) - 1,
650                                         GET_y(reparented_obj)
651                                           + GET_height(reparented_obj) - 1);
652                         reparented_obj = NULL;
653                 }
654                 break;
655         }
656         case Expose: {
657                 XExposeEvent *eep = (XExposeEvent*)ep;
658                 VObj *obj;
659                 HashEntry *entry;
660  
661 /*safer & slower:
662                 obj = findWindowObject((XMapEvent*)eep->window);
663 */
664                 if (entry = window2Obj->get(window2Obj,
665                                          (XMapEvent*)eep->window)) {
666                         obj = (VObj*)entry->val;
667                 } else {
668                         obj = NULL;
669                 }
670  
671                 if (obj) {
672 /*
673                         if (GET_visible(obj)) {
674 if (verbose) printf("Expose! w = ox%x obj=%s\n",
675                     (XExposeEvent*)eep->window, GET_name(obj));
676                                 SET_window(obj, (XExposeEvent*)eep->window);
677                         } else {
678 if (verbose) printf("Expose! w = ox%x obj=%s NOT IGNORED\n",
679                         (XExposeEvent*)eep->window, GET_name(obj));
680                                 SET_window(obj, (XExposeEvent*)eep->window);
681  
682                         }
683 */
684                         SET_visible(obj, 1);
685  
686                         /* supress drawing, if tool-draging is going on */
687                         if (!mouseDown) {
688                                 intBuff[0] = eep->x;
689                                 intBuff[1] = eep->y;
690                                 intBuff[2] = eep->width;
691                                 intBuff[3] = eep->height;
692                                 sendTokenMessageAndInts(obj, STR_expose,
693                                                         intBuff, 4);
694                                 SET_visible(obj, 1);
695                         }
696                 }
697                 break;
698         }
699         case ResizeRequest:
700                 if (!mouseDown) handle_ResizeRequest(ep);
701                 break;
702  
703         case ConfigureNotify:
704                 if (!mouseDown) handle_ConfigureNotify(ep);
705                 break;
706  
707         case UnmapNotify: {
708                 XUnmapEvent *eep = (XUnmapEvent*)ep;
709                 VObj *obj = findWindowObject((XUnmapEvent*)eep->window);
710  
711 /*if (verbose) fprintf(stderr, "unmapNotify! w=ox%x obj=%s\n",
712                  eep->window, GET_name(obj));
713 */
714                 if (obj) {
715                         SET_window(obj, 0);
716                         SET_visible(obj, 0);
717                 }
718                 break;
719         }
720         case DestroyNotify: {
721                 XDestroyWindowEvent *eep = ep;
722                 VObj *obj = findWindowObject((XDestroyWindowEvent*)eep->window);
723  
724 /*
725 if (verbose) fprintf(stderr, "destroyNotify! w=ox%x obj=%s\n",
726                  eep->window, GET_name(obj));
727 */
728                 if (obj) {
729                         SET_window(obj, 0);
730                         SET_visible(obj, 0);
731                 }
732                 break;
733         }
734         case SelectionClear:
735                 if (xselectionObj) {
736 /*                      sendMessage1(xselectionObj, "clearSelection");
737 */
738                         GLClearSelection();
739                 }
740                 break;
741  
742         case SelectionRequest:
743                 if (xselectionObj) {
744                         char *cp;
745  
746                         callMeth(xselectionObj, result, 0, NULL,
747                                         STR_getSelection);
748  
749                         cp = PkInfo2Str(result);
750                         if (cp) {
751                                 Packet *result = borrowPacket();
752                                 XSelectionEvent reply;
753                                 XSelectionRequestEvent *sep;
754                                 int length;
755  
756                                 length = strlen(cp);
757  
758                                 XChangeProperty(ep->xselectionrequest.display,
759                                         ep->xselectionrequest.requestor,
760                                         ep->xselectionrequest.property,
761                                         XA_STRING, 8,
762                                         PropModeReplace,
763                                         cp, length);
764  
765                                 sep = (XSelectionRequestEvent*)ep;
766  
767                                 reply.type = SelectionNotify;
768                                 reply.serial = 0;
769                                 reply.send_event = True;
770                                 reply.display = sep->display;
771                                 reply.requestor = sep->requestor;
772                                 reply.selection = sep->selection;
773                                 reply.target = sep->target;
774                                 reply.time = sep->time;
775  
776                                 if (sep->property == None)
777                                         reply.property = sep->target;
778                                 else
779                                         reply.property = sep->property;
780  
781  
782                                 XSendEvent(reply.display, reply.requestor,
783                                                 False, 0, (XEvent *)&reply);
784                                 returnPacket();
785                         }
786                 }
787                 break;
788         }
789 }
790  
791 handle_KeyPress(ep)
792         XKeyEvent *ep;
793 {
794         VObj *obj = findWindowObject(ep->window);
795         char *keyInfo;
796  
797         keyInfo = eventChar(ep);
798  
799         if (obj) {
800                 if ((unsigned int)keyInfo <= (char*)1) {
801                         sendMessage1(obj, "keyPress");
802                 } else {
803                         sendMessage1(obj, keyInfo);
804                 }
805         }
806         /* printf("control=%d shift=%d\n", keyStat_control, keyStat_shift);*/
807 }
808  
809 handle_KeyRelease(ep)
810         XKeyEvent *ep;
811 {
812         VObj *obj = findWindowObject(ep->window);
813         if (((int)eventChar(ep) <= 1) && obj) {
814                 sendMessage1(obj, "keyRelease");
815         }
816 }
817  
818 handle_EnterNotify(ep, dragObjp, tool, mouseDown)
819         XEnterWindowEvent *ep;
820         VObj **dragObjp;
821         int tool;
822         int *mouseDown;
823 {
824         if (VCurrentObj == NULL) return;
825         if (ep->detail == NotifyVirtual ||
826             ep->detail == NotifyNonlinearVirtual) return;
827  
828         if (validObjectP(VCurrentObj) == 0) {
829                 VCurrentObj = NULL;
830                 return;
831         }
832  
833         if ((tool != ACTION_TOOL) && (*mouseDown == 0)) {
834                 GLDrawRubberFrame(VCurrentObj,
835                                 GET_x(VCurrentObj) + 1,
836                                 GET_y(VCurrentObj) + 1,
837                                 GET_x(VCurrentObj)
838                                   + GET_width(VCurrentObj) - 1,
839                                 GET_y(VCurrentObj)
840                                   + GET_height(VCurrentObj) - 1);
841         } else {
842                 sendMessage1(VCurrentObj, "enter");
843         }
844 }
845  
846 handle_LeaveNotify(ep, dragObjp, tool, mouseDown)
847         XLeaveWindowEvent *ep;
848         VObj **dragObjp;
849         int tool;
850         int *mouseDown;
851 {
852         if (VCurrentObj == NULL) return;
853         if (ep->detail == NotifyVirtual ||
854             ep->detail == NotifyNonlinearVirtual) return;
855  
856         if (validObjectP(VCurrentObj) == 0) {
857                 VCurrentObj = NULL;
858                 return;
859         }
860  
861         /*
862          * the cursor has moved off the top window... onto root.
863          */
864         if ((tool != ACTION_TOOL) && (*mouseDown == 0)) {
865                 GLDrawRubberFrame(VCurrentObj,
866                                 GET_x(VCurrentObj) + 1,
867                                 GET_y(VCurrentObj) + 1,
868                                 GET_x(VCurrentObj)
869                                   + GET_width(VCurrentObj) - 1,
870                                 GET_y(VCurrentObj)
871                                   + GET_height(VCurrentObj) - 1);
872         } else {
873                 sendMessage1(VCurrentObj, "leave");
874         }
875 }
876  
877 handle_ButtonPress(ep, dragObjp, tool, resize_corner, mouseDown, from_x,from_y)
878         XButtonEvent *ep;
879         VObj **dragObjp;
880         int tool;
881         int *resize_corner;
882         int *mouseDown;
883         int *from_x, *from_y;
884 {
885         int root_x, root_y;
886  
887         if (validObjectP(VCurrentObj) == 0) {
888                 VCurrentObj = NULL;
889                 return;
890         }
891  
892         mouseButtonPressedState |= 1<<(ep->button);
893 /*printf("press button#=%d\n", ep->button);*/
894  
895         /* only the combination of control-key & middle mouse button
896          * will get you the CLI
897          */
898         if (keyStat_control) {
899                 execScript(VCurrentObj, result, "shell(\"visible\", 1);");
900                 execScript(VCurrentObj, result, "shell(\"raise\");");
901                 return;
902         }
903  
904         switch (tool) {
905         case ACTION_TOOL: { /* press */
906  
907                 if (cmd_history) {
908                         sprintf(buff, "%s;mouseDown\n",
909                                 GET_name(VCurrentObj));
910                         messageToUser(NULL, MESSAGE_HISTORY, buff);
911                 }
912                 *dragObjp = VCurrentObj;
913                 sendMessage1(VCurrentObj, "buttonPress");
914         }
915         break;
916  
917         case TARGET_TOOL: /* press */
918                 VTargetObj = VCurrentObj;
919                 sendMessage1(VResourceObj, "targetSet");
920         break;
921  
922         case REPARENT_TOOL: {/* press */
923  
924                 VObj *stack;
925                 Window w = GET_window(VCurrentObj);
926                 int child_x, child_y;
927  
928                 *dragObjp = VCurrentObj;
929                 if (!*dragObjp) {
930                         IERROR("reparent tool: can't find the object! abort.\n");
931                 }
932                 if (!w) {
933                         MERROR(*dragObjp, "reparent to root window failed.\n");
934                         *dragObjp = NULL;
935                         return;
936                 }
937                 if (GET__classInfo(VCurrentObj) != &class_glass) {
938                         XSetWindowAttributes attrs;
939                         attrs.save_under = True;
940                         XChangeWindowAttributes(display, w, CWSaveUnder,
941                                                 &attrs);
942                 }
943  
944 #ifdef dsdsgs
945                 if (stack = ObjStack(*dragObjp)) {
946                         Window stackw = GET_window(stack);
947                         int stack_x, stack_y;
948  
949                         w = GET_window(*dragObjp);
950                         GLRootPosition(w, &child_x, &child_y);
951                         GLRootPosition(stackw, &stack_x, &stack_y);
952  
953                         /*
954                          * dragObject's param is relative to the stack object.
955                          * from_{x,y} is relative to the root window.
956                          */
957                         GLDrawRubberFrame(*dragObjp,
958                                         GET_x(*dragObjp) + 1,
959                                         GET_y(*dragObjp) + 1,
960                                         GET_x(*dragObjp)
961                                           + GET_width(*dragObjp) - 1,
962                                         GET_y(*dragObjp)
963                                           + GET_height(*dragObjp) - 1);
964  
965                         SET_x(*dragObjp, child_x - stack_x);
966                         SET_y(*dragObjp, child_y - stack_y);
967  
968                         callMethod(stack, "self", result2);
969                         callMethod(*dragObjp, "set", result, "parent",
970                                         result2, NULL);
971  
972                         callMethod(VResourceObj, "self", result2);
973                         callMethod(*dragObjp, "set", result, "parent",
974                                         result2, NULL);
975  
976                         if (GET__classInfo(VCurrentObj) != &class_glass) {
977                                 XSetWindowAttributes attrs;
978                                 attrs.save_under = True;
979                                 XChangeWindowAttributes(display, w,
980                                                         CWSaveUnder, &attrs);
981                                 XSelectInput(display, w,
982                                         KeyPressMask |
983                                         ButtonPressMask |
984                                         ButtonReleaseMask |
985                                         Button1MotionMask|
986                                         PointerMotionMask |
987                                         PointerMotionHintMask |
988                                         EnterWindowMask |
989                                         LeaveWindowMask |
990                                         SubstructureRedirectMask);
991                         }
992                         *mouseDown = 1;
993                         GLQueryMouse(rootWindow, &root_x, &root_y, &(mouse.x),
994                                         &(mouse.y));
995  
996                         *from_x = root_x - GET_x(*dragObjp);
997                         *from_y = root_y - GET_y(*dragObjp);
998                 } else {
999                         *dragObjp = NULL;
1000                         IERROR("stack attribute is not set for object `%s'\n", GET_name(stack));
1001                 }
1002 #endif
1003  
1004 printf("*       from %d,%d\n", *from_x, *from_y);
1005 printf("         x,y %d,%d\n", GET_x(*dragObjp), GET_y(*dragObjp));
1006  
1007         }
1008         break;
1009  
1010         case MOVE_TOOL: { /* press */
1011  
1012                 Window w = GET_window(VCurrentObj);
1013  
1014                 if (!w) return;
1015  
1016                 /* restrict user from moving non-field (stack, card...) */
1017                 *dragObjp = VCurrentObj;
1018                 if (*dragObjp == NULL) {
1019                         IERROR("move tool: can't find the object! abort.\n");
1020                 }
1021                 GLDrawRubberFrame(*dragObjp,
1022                                 GET_x(*dragObjp) + 1,
1023                                 GET_y(*dragObjp) + 1,
1024                                 GET_x(*dragObjp)
1025                                   + GET_width(*dragObjp) - 1,
1026                                 GET_y(*dragObjp)
1027                                   + GET_height(*dragObjp) - 1);
1028  
1029                 if (GET__classInfo(VCurrentObj) != &class_glass) {
1030  
1031                         XSetWindowAttributes attrs;
1032                         attrs.save_under = True;
1033                         XChangeWindowAttributes(display, w, CWSaveUnder,
1034                                                 &attrs);
1035                         XSelectInput(display, w,
1036                                         KeyPressMask |
1037                                         ButtonPressMask |
1038                                         ButtonReleaseMask |
1039                                         Button1MotionMask |
1040                                         PointerMotionMask |
1041                                         PointerMotionHintMask |
1042                                         EnterWindowMask |
1043                                         LeaveWindowMask |
1044                                         SubstructureRedirectMask);
1045                 }
1046                 *mouseDown = 1;
1047                 GLQueryMouse(rootWindow, &root_x, &root_y,
1048                                 &(mouse.x), &(mouse.y));
1049                 *from_x = root_x;
1050                 *from_y = root_y;
1051         }
1052         break;
1053  
1054         case RESIZE_TOOL: { /* press */
1055  
1056                 Window w = GET_window(VCurrentObj);
1057  
1058                 if (!w) return;
1059  
1060                 *dragObjp = VCurrentObj;
1061  
1062                 if (GET__classInfo(VCurrentObj) != &class_glass) {
1063  
1064                         XSetWindowAttributes attrs;
1065  
1066                         attrs.save_under = True;
1067                         XChangeWindowAttributes(display, w, CWSaveUnder,
1068                                                 &attrs);
1069                         XSelectInput(display, w,
1070                                         KeyPressMask |
1071                                         ButtonPressMask |
1072                                         ButtonReleaseMask |
1073                                         Button1MotionMask |
1074                                         PointerMotionMask |
1075                                         PointerMotionHintMask |
1076                                         EnterWindowMask |
1077                                         LeaveWindowMask |
1078                                         SubstructureRedirectMask);
1079                 }
1080                 *mouseDown = 1;
1081                 GLQueryMouse(w, &root_x, &root_y, &(mouse.x), &(mouse.y));
1082                 *from_x = root_x;
1083                 *from_y = root_y;
1084  
1085                 if (mouse.x < (int)(GET_width(*dragObjp) / 2)) {
1086                         if (mouse.y < (int)(GET_height(*dragObjp) / 2))
1087                                 *resize_corner = RC_UPPER_LEFT;
1088                         else
1089                                 *resize_corner = RC_LOWER_LEFT;
1090                 } else {
1091                         if (mouse.y < (int)(GET_height(*dragObjp) / 2))
1092                                 *resize_corner = RC_UPPER_RIGHT;
1093                         else
1094                                 *resize_corner = RC_LOWER_RIGHT;
1095                 }
1096         }
1097         break;
1098         }
1099 }
1100  
1101 handle_ButtonRelease(ep, dragObjp, tool, resize_corner, mouseDown)
1102         XButtonEvent *ep;
1103         VObj **dragObjp;
1104         int tool;
1105         int *resize_corner;
1106         int *mouseDown;
1107 {
1108         Window w;
1109  
1110         if (validObjectP(VCurrentObj) == 0) {
1111                 VCurrentObj = NULL;
1112                 return;
1113         }
1114         w = GET_window(VCurrentObj);
1115  
1116         mouseButtonPressedState &= ~(1<<(ep->button));
1117  
1118         switch (tool) {
1119         case ACTION_TOOL: /* release */
1120                 if (VCurrentObj == *dragObjp) {
1121                         if (cmd_history) {
1122                                 sprintf(buff,
1123                                         "%s;mouseDown\n", GET_name(*dragObjp));
1124                                 messageToUser(NULL, MESSAGE_HISTORY, buff);
1125                         }
1126                         sendMessage1(*dragObjp, "buttonRelease");
1127                 }
1128                 *dragObjp = NULL;
1129                 *mouseDown = 0;
1130         break;
1131  
1132         case MOVE_TOOL: { /* release */
1133                 if (*dragObjp) {
1134                         if (GET__classInfo(VCurrentObj) != &class_glass) {
1135                                 XSetWindowAttributes attrs;
1136  
1137                                 attrs.save_under = False;
1138                                 XChangeWindowAttributes(display, w,
1139                                                         CWSaveUnder, &attrs);
1140                                 XSelectInput(display, w,
1141                                                 KeyPressMask |
1142                                                 KeyReleaseMask |
1143                                                 ButtonPressMask |
1144                                                 ButtonReleaseMask |
1145                                                 PointerMotionMask |
1146                                                 PointerMotionHintMask |
1147                                                 EnterWindowMask |
1148                                                 LeaveWindowMask |
1149                                                 Button1MotionMask |
1150                                                 StructureNotifyMask |
1151                                                 ExposureMask);
1152                                 callMeth(*dragObjp, result, 0, result2,
1153                                         STR_render);
1154                         }
1155                         GLDrawRubberFrame(*dragObjp,
1156                                         GET_x(*dragObjp) + 1,
1157                                         GET_y(*dragObjp) + 1,
1158                                         GET_x(*dragObjp)
1159                                           + GET_width(*dragObjp) - 1,
1160                                         GET_y(*dragObjp)
1161                                           + GET_height(*dragObjp) - 1);
1162                 }
1163                 *dragObjp = NULL;
1164                 *mouseDown = 0;
1165                 break;
1166         }
1167         case REPARENT_TOOL: /* release */
1168                 if (*dragObjp) {
1169                         VObj parent;
1170                         Window pw, w = GET_window(*dragObjp);
1171                         int parent_rx, parent_ry, child_rx, child_ry;
1172  
1173                         if (GET__classInfo(VCurrentObj) != &class_glass) {
1174  
1175                                 XSetWindowAttributes attrs;
1176                                 attrs.save_under = False;
1177                                 XChangeWindowAttributes(display, w,
1178                                                         CWSaveUnder, &attrs);
1179  
1180                                 XSelectInput(display, w,
1181                                                 KeyPressMask |
1182                                                 KeyReleaseMask |
1183                                                 ButtonPressMask |
1184                                                 ButtonReleaseMask |
1185                                                 PointerMotionMask |
1186                                                 PointerMotionHintMask |
1187                                                 EnterWindowMask |
1188                                                 LeaveWindowMask |
1189                                                 Button1MotionMask |
1190                                                 StructureNotifyMask |
1191                                                 ExposureMask);
1192                         }
1193                         GLRootPosition(w, &child_rx, &child_ry);
1194                         unMapObject(*dragObjp);
1195  
1196                         if (pw = GLQueryWindow()) {
1197                                 GLRootPosition(pw, &parent_rx, &parent_ry);
1198                         } else {
1199                                 MERROR(*dragObjp,
1200                                         "reparent tool can't find the new parent window.\n");
1201                         }
1202 /*
1203                         if (parent = findWindowObject(pw)) {
1204                                 if (ScanAttr(parent, "G") &&
1205                                     !ScanAttr(*dragObjp, "G")) {
1206                                         MERROR(*dragObjp,
1207 "Sorry, X11R4 does not allow visible inferiors to InputOnly windows.\n");
1208                                         } else {
1209                                                 SET_x(*dragObjp,
1210                                                         child_rx - parent_rx);
1211                                                 SET_y(*dragObjp,
1212                                                         child_ry - parent_ry);
1213  
1214                                                 callMethod(parent, "self", result2);
1215                                                 callMethod(*dragObjp, "set", result, "parent", result2, NULL);
1216  
1217                                                 callMethod(*dragObjp, "set", result, "visible", packetConst_1, NULL);
1218                                         }
1219                                 reparented_obj = *dragObjp;
1220                         } else {
1221                                 MERROR(*dragObjp,
1222                                         "reparent tool can't figure out the new parent\n");
1223                         }
1224 */
1225                 }
1226                 *dragObjp = NULL;
1227                 *mouseDown = 0;
1228                 floatingObject = NULL;
1229         break;
1230  
1231         case RESIZE_TOOL: /* release */
1232  
1233                 if (*dragObjp) {
1234                         if (GET__classInfo(VCurrentObj) != &class_glass) {
1235                                 XSetWindowAttributes attrs;
1236  
1237                                 attrs.save_under = 0;
1238                                 XChangeWindowAttributes(display, w,
1239                                                         CWSaveUnder, &attrs);
1240                                 XSelectInput(display, w,
1241                                                 KeyPressMask |
1242                                                 KeyReleaseMask |
1243                                                 ButtonPressMask |
1244                                                 ButtonReleaseMask |
1245                                                 PointerMotionMask |
1246                                                 PointerMotionHintMask |
1247                                                 EnterWindowMask |
1248                                                 LeaveWindowMask |
1249                                                 Button1MotionMask |
1250                                                 StructureNotifyMask |
1251                                                 ExposureMask);
1252                         }
1253                         intBuff[0] = GET_x(*dragObjp);
1254                         intBuff[1] = GET_y(*dragObjp);
1255                         intBuff[2] = GET_width(*dragObjp);
1256                         intBuff[3] = GET_height(*dragObjp);
1257                         sendTokenMessageAndInts(*dragObjp, STR_config,
1258                                                 intBuff, 4);
1259  
1260                         callMeth(*dragObjp, result, 0, 0, STR_render);
1261                         GLDrawRubberFrame(*dragObjp,
1262                                 GET_x(*dragObjp) + 1,
1263                                 GET_y(*dragObjp) + 1,
1264                                 GET_x(*dragObjp)
1265                                   + GET_width(*dragObjp) - 1,
1266                                 GET_y(*dragObjp)
1267                                   + GET_height(*dragObjp) - 1);
1268                 }
1269                 *dragObjp = NULL;
1270                 *mouseDown = 0;
1271                 break;
1272         }
1273 }
1274  
1275 handle_MotionNotify(ep, dragObjp, tool, resize_corner,mouseDown, from_x,from_y)
1276         XEvent *ep;
1277         VObj **dragObjp;
1278         int tool;
1279         int *resize_corner;
1280         int *mouseDown;
1281         int *from_x, *from_y;
1282 {
1283         if (((XMotionEvent*)ep)->is_hint != NotifyHint) return;
1284  
1285         if (validObjectP(VCurrentObj) == 0) {
1286                 VCurrentObj = NULL;
1287                 return;
1288         }
1289  
1290         switch (tool) {
1291         case ACTION_TOOL: {
1292                 int root_x, root_y, dx, dy;
1293                 Window w = GET_window(VCurrentObj);
1294  
1295                 if (VCurrentObj && w) {
1296                         GLQueryMouse(w, &root_x, &root_y,
1297                                         &(mouse.x), &(mouse.y));
1298                         intBuff[0] = mouse.x;
1299                         intBuff[1] = mouse.y;
1300                         sendMessageAndInts(VCurrentObj,
1301                                         "mouseMove", intBuff, 2);
1302                 }
1303         } break;
1304  
1305         case MOVE_TOOL:
1306  
1307                 if (*mouseDown && *dragObjp) {
1308                         Window w = GET_window(*dragObjp);
1309                         int root_x, root_y, dx, dy;
1310  
1311 /*                      if (*dragObjp != findWindowObject(w)) return;
1312 */
1313                         GLQueryMouse(rootWindow, &root_x, &root_y,
1314                                      &(mouse.x), &(mouse.y));
1315  
1316                         printf("** from %d,%d root %d,%d\n",
1317                                         *from_x, *from_y, root_x, root_y);
1318                         dx = root_x - *from_x;
1319                         dy = root_y - *from_y;
1320                         *from_x = root_x;
1321                         *from_y = root_y;
1322  
1323                         SET_x(*dragObjp, GET_x(*dragObjp) + dx);
1324                         SET_y(*dragObjp, GET_y(*dragObjp) + dy);
1325                         XMoveWindow(display, w,
1326                                         GET_x(*dragObjp), GET_y(*dragObjp));
1327                 }
1328         break;
1329  
1330         case REPARENT_TOOL:
1331  
1332                 if (*mouseDown && *dragObjp) {
1333                         Window w;
1334                         int root_x, root_y, dx, dy;
1335                         XSetWindowAttributes attrs;
1336  
1337                         w = GET_window(*dragObjp);
1338                         GLQueryMouse(rootWindow, &root_x, &root_y,
1339                                    &(mouse.x), &(mouse.y));
1340  
1341                         SET_x(*dragObjp, root_x - *from_x);
1342                         SET_y(*dragObjp, root_y - *from_y);
1343  
1344                         printf("*from %d,%d\n", *from_x, *from_y);
1345                         printf(" param %d,%d\n", GET_x(*dragObjp), GET_y(*dragObjp));
1346  
1347                         attrs.override_redirect = True;
1348                         XChangeWindowAttributes(display, w, CWOverrideRedirect,
1349                                                 &attrs);
1350                         if (GET__parent(*dragObjp))
1351                                 GLUpdatePosition(0, w,
1352                                         GET_x(*dragObjp), GET_y(*dragObjp));
1353                         else
1354                                 GLUpdatePosition(1, w,
1355                                         GET_x(*dragObjp), GET_y(*dragObjp));
1356  
1357                         attrs.override_redirect = 0;
1358                         XChangeWindowAttributes(display, w, CWOverrideRedirect,
1359                                                 &attrs);
1360                 }
1361                 break;
1362  
1363         case RESIZE_TOOL: /* motion */
1364  
1365                 if (*mouseDown && *dragObjp) {
1366                         Window pw, w = eventWindow(*((XEvent*)ep));
1367                         int root_x, root_y, dx, dy;
1368  
1369                         if (*dragObjp != findWindowObject(w)) return;
1370  
1371                         GLDrawRubberFrame(*dragObjp,
1372                                         GET_x(*dragObjp) + 1,
1373                                         GET_y(*dragObjp) + 1,
1374                                         GET_x(*dragObjp)
1375                                           + GET_width(*dragObjp) - 1,
1376                                         GET_y(*dragObjp)
1377                                           + GET_height(*dragObjp) - 1);
1378  
1379                         GLQueryMouse(rootWindow, &root_x, &root_y,
1380                                    &(mouse.x), &(mouse.y));
1381  
1382                         dx = root_x - *from_x;
1383                         dy = root_y - *from_y;
1384                         *from_x = root_x;
1385                         *from_y = root_y;
1386  
1387                         switch (*resize_corner) {
1388                         case RC_UPPER:
1389                                 SET_y(*dragObjp, GET_y(*dragObjp) + dy);
1390                                 SET_height(*dragObjp,
1391                                                 GET_height(*dragObjp) - dy);
1392                                 *resize_corner =
1393                                         checkParam(*dragObjp, *resize_corner);
1394                                 XMoveResizeWindow(display, w,
1395                                                 GET_x(*dragObjp),
1396                                                 GET_y(*dragObjp),
1397                                                 GET_width(*dragObjp),
1398                                                 GET_height(*dragObjp));
1399                         break;
1400  
1401                         case RC_LOWER:
1402                                 SET_height(*dragObjp,
1403                                                 GET_height(*dragObjp) + dy);
1404                                 *resize_corner =
1405                                         checkParam(*dragObjp, *resize_corner);
1406                                 XMoveResizeWindow(display, w,
1407                                                 GET_x(*dragObjp),
1408                                                 GET_y(*dragObjp),
1409                                                 GET_width(*dragObjp),
1410                                                 GET_height(*dragObjp));
1411                         break;
1412  
1413                         case RC_LEFT:
1414                                 SET_x(*dragObjp, GET_x(*dragObjp) + dx);
1415                                 SET_width(*dragObjp,
1416                                         GET_width(*dragObjp) - dx);
1417                                 *resize_corner =
1418                                         checkParam(*dragObjp, *resize_corner);
1419                                 XMoveResizeWindow(display, w,
1420                                                 GET_x(*dragObjp),
1421                                                 GET_y(*dragObjp),
1422                                                 GET_width(*dragObjp),
1423                                                 GET_height(*dragObjp));
1424                         break;
1425  
1426                         case RC_RIGHT:
1427                                 SET_width(*dragObjp,
1428                                         GET_width(*dragObjp) + dx);
1429                                 *resize_corner =
1430                                         checkParam(*dragObjp, *resize_corner);
1431                                 XResizeWindow(display, w,
1432                                                 GET_width(*dragObjp),
1433                                                 GET_height(*dragObjp));
1434                         break;
1435  
1436                         case RC_UPPER_LEFT:
1437                                 SET_x(*dragObjp, GET_x(*dragObjp) + dx);
1438                                 SET_y(*dragObjp, GET_y(*dragObjp) + dy);
1439                                 SET_width(*dragObjp,
1440                                                 GET_width(*dragObjp) - dx);
1441                                 SET_height(*dragObjp,
1442                                                 GET_height(*dragObjp) - dy);
1443                                 *resize_corner =
1444                                         checkParam(*dragObjp, *resize_corner);
1445                                 XMoveResizeWindow(display, w,
1446                                                 GET_x(*dragObjp),
1447                                                 GET_y(*dragObjp),
1448                                                 GET_width(*dragObjp),
1449                                                 GET_height(*dragObjp));
1450                         break;
1451  
1452                         case RC_LOWER_LEFT:
1453                                 SET_x(*dragObjp, GET_x(*dragObjp) + dx);
1454                                 SET_y(*dragObjp, GET_y(*dragObjp));
1455                                 SET_width(*dragObjp,
1456                                                 GET_width(*dragObjp) - dx);
1457                                 SET_height(*dragObjp,
1458                                                 GET_height(*dragObjp) + dy);
1459                                 *resize_corner =
1460                                         checkParam(*dragObjp, *resize_corner);
1461                                 XMoveResizeWindow(display, w,
1462                                                 GET_x(*dragObjp),
1463                                                 GET_y(*dragObjp),
1464                                                 GET_width(*dragObjp),
1465                                                 GET_height(*dragObjp));
1466                         break;
1467  
1468                         case RC_UPPER_RIGHT:
1469                                 SET_x(*dragObjp, GET_x(*dragObjp));
1470                                 SET_y(*dragObjp, GET_y(*dragObjp) + dy);
1471                                 SET_width(*dragObjp,
1472                                                 GET_width(*dragObjp) + dx);
1473                                 SET_height(*dragObjp,
1474                                                 GET_height(*dragObjp) - dy);
1475                                 *resize_corner =
1476                                         checkParam(*dragObjp, *resize_corner);
1477                                 XMoveWindow(display, w, GET_x(*dragObjp),
1478                                                 GET_y(*dragObjp));
1479                                 XResizeWindow(display, w,
1480                                                 GET_width(*dragObjp),
1481                                                 GET_height(*dragObjp));
1482                         break;
1483  
1484                         case RC_LOWER_RIGHT:
1485                                 SET_width(*dragObjp,
1486                                                 GET_width(*dragObjp) + dx);
1487                                 SET_height(*dragObjp,
1488                                                 GET_height(*dragObjp) + dy);
1489                                 *resize_corner =
1490                                         checkParam(*dragObjp, *resize_corner);
1491                                 XResizeWindow(display, w,
1492                                                 GET_width(*dragObjp),
1493                                                 GET_height(*dragObjp));
1494                         break;
1495                         }
1496                         GLDrawRubberFrame(*dragObjp,
1497                                         GET_x(*dragObjp) + 1,
1498                                         GET_y(*dragObjp) + 1,
1499                                         GET_x(*dragObjp)
1500                                           + GET_width(*dragObjp) - 1,
1501                                         GET_y(*dragObjp)
1502                                           + GET_height(*dragObjp) - 1);
1503                 }
1504                 break;
1505         }
1506 }
1507  
1508 #ifdef INLINED_handle_ExposeNotify
1509 handle_ExposeNotify(ep)
1510         XExposeEvent *ep;
1511 {
1512         VObj *obj = findWindowObject(ep->window);
1513  
1514 /*      while(XCheckTypedWindowEvent(display, ep->window, Expose, ep));*/
1515 /*
1516         if (GET__classInfo(obj) != &class_txtDisp &&
1517             GET__classInfo(obj) != &class_HTML) {
1518                 while(XCheckTypedWindowEvent(display, ep->window, Expose, ep));
1519         }
1520 */
1521         if (obj) {
1522                 intBuff[0] = ep->x;
1523                 intBuff[1] = ep->y;
1524                 intBuff[2] = ep->width;
1525                 intBuff[3] = ep->height;
1526                 sendTokenMessageAndInts(obj, STR_expose, intBuff, 4);
1527         }
1528         SET_visible(obj, 1);
1529 }
1530 #endif
1531  
1532 handle_ResizeRequest(ep)
1533         XResizeRequestEvent *ep;
1534 {
1535         VObj *obj = findWindowObject(ep->window);
1536  
1537         if (obj) {
1538                 intBuff[0] = GET_x(obj);
1539                 intBuff[1] = GET_y(obj);
1540                 intBuff[2] = ep->width;
1541                 intBuff[3] = ep->height;
1542                 sendTokenMessageAndInts(obj, STR_config, intBuff, 4);
1543         }
1544 }
1545  
1546 handle_ConfigureNotify(ep)
1547         XConfigureEvent *ep;
1548 {
1549         VObj *obj = findWindowObject(ep->window);
1550  
1551         if (obj) {
1552                 if (ep->above != 0) {
1553                         intBuff[0] = ep->x;
1554                         intBuff[1] = ep->y;
1555                 } else {
1556                         intBuff[0] = GET_x(obj);
1557                         intBuff[1] = GET_y(obj);
1558                 }
1559                 intBuff[2] = ep->width;
1560                 intBuff[3] = ep->height;
1561                 sendTokenMessageAndInts(obj, STR_config, intBuff, 4);
1562         }
1563 }
1564  
1565 char *eventChar(e)
1566         XKeyEvent *e;
1567 {
1568         KeySym ks;
1569  
1570         keybuf[0] = '\0';
1571         XLookupString (e, keybuf, KEYBUFSIZE, &ks, NULL);
1572  
1573         if (ks != NoSymbol) {
1574                 /* printf("e=%ld, key[0]='%c'\n", (long)e, keybuf[0]);*/
1575  
1576                 switch (ks) {
1577                 case XK_Shift_L:
1578                 case XK_Shift_R:
1579                         if (keyStat_shift) keyStat_shift = 0;
1580                         else keyStat_shift = 1;
1581                         keyStat_key = '\0';
1582                         return 0;
1583                 case XK_Control_L:
1584                         if (keyStat_control) keyStat_control = 0;
1585                         else keyStat_control = 1;
1586                         keyStat_key = '\0';
1587                         return 0;
1588                 case XK_Home:                           /* major ickyness */
1589                         return "key_home";
1590                 case XK_Up:
1591                         return "key_up";
1592                 case XK_Down:
1593                         return "key_down";
1594                 case XK_Left:
1595                         return "key_left";
1596                 case XK_Right:
1597                         return "key_right";
1598                 case XK_Begin:
1599                         return "key_begin";
1600                 case XK_End:
1601                         return "key_end";
1602                 case XK_Prior:
1603                         return "key_prior";
1604                 case XK_Next:
1605                         return "key_next";
1606                 default:
1607                         keyStat_key = keybuf[0];
1608                 }
1609                 if (keyStat_key != '\0')
1610                         return (char)1; /*XXX 1 has special meaning. ick. */
1611         }
1612         return NULL;
1613 }
1614  
1615 void processPeekKeys()
1616 {
1617         if (keyStat_control && keyStat_shift) {
1618 /*
1619                 method_generic_renderObjectParam(CurrentObj);
1620 */
1621                 objectPeekFlag = 1;
1622         } else {
1623                 if (objectPeekFlag) {
1624                         objectPeekFlag = 0;
1625 /*
1626                         method_generic_renderObjectParam(CurrentObj);
1627 */
1628                 }
1629         }
1630 }
1631  
1632 int checkParam(self, resize_corner)
1633         VObj *self;
1634         int resize_corner;
1635 {
1636         if (GET_width(self) < 1) {
1637                 SET_width(self, 1);
1638                 if ((resize_corner == RC_LEFT) ||
1639                     (resize_corner == RC_UPPER_LEFT) ||
1640                     (resize_corner == RC_LOWER_LEFT))
1641                         resize_corner = RC_RIGHT;
1642                 else
1643                         resize_corner = RC_LEFT;
1644  
1645         } else if (GET_height(self) < 1) {
1646                 SET_height(self, 1);
1647                 if ((resize_corner == RC_UPPER) ||
1648                     (resize_corner == RC_UPPER_RIGHT) ||
1649                     (resize_corner == RC_UPPER_LEFT))
1650                         resize_corner = RC_LOWER;
1651                 else
1652                         resize_corner = RC_UPPER;
1653         }
1654         return resize_corner;
1655 }
1656  
1657 long scheduleEvent(delay, func, obj, argc, argv)
1658         int delay;      /* milliseconds */
1659         int (*func)();
1660         VObj *obj;
1661         int argc;
1662         Packet *argv;
1663 {
1664         TimeInfo *ltip = NULL, *tip, *new;
1665  
1666         /* later, do recycling by making a circular linked list...
1667          */
1668         if (!(new = (TimeInfo*)malloc(sizeof(struct TimeInfo)))) return 0;
1669         gettimeofday(&new->time, (struct timezone*)NULL);
1670         new->time.tv_sec += delay / 1000;
1671         new->time.tv_usec += (delay % 1000) * 1000;
1672         if (new->time.tv_usec > 1000000) {
1673                 new->time.tv_usec -= 1000000;
1674                 new->time.tv_sec += 1;
1675         }
1676         new->func = func;
1677         new->obj = obj;
1678         new->argc = argc;
1679         new->argv = argv;
1680  
1681         if (!firstTimeInfo) {
1682                 firstTimeInfo = new;
1683                 new->next = NULL;
1684                 return (long)new;
1685         }
1686         for (tip = firstTimeInfo; tip; tip = tip->next) {
1687                 if (new->time.tv_sec < tip->time.tv_sec) {
1688                         if (ltip) ltip->next = new;
1689                         else firstTimeInfo = new;
1690                         new->next = tip;
1691                         return (long)new;
1692                 } else if (new->time.tv_sec == tip->time.tv_sec) {
1693                         if (new->time.tv_usec <= tip->time.tv_usec) {
1694                                 if (ltip) ltip->next = new;
1695                                 else firstTimeInfo = new;
1696                                 new->next = tip;
1697                                 return (long)new;
1698                         }
1699                 }
1700                 ltip = tip;
1701         }
1702         ltip->next = new;
1703         new->next = NULL;
1704  
1705         return (long)new;
1706 }
1707  
1708 int cancelEvent(timeInfoID)
1709         long timeInfoID;
1710 {
1711         TimeInfo *ltip = NULL, *tip;
1712  
1713         for (tip = firstTimeInfo; tip; tip = tip->next) {
1714                 if ((long)tip == timeInfoID) {
1715                         if (ltip) ltip->next = tip->next;
1716                         else firstTimeInfo = tip->next;
1717                         if (tip->argv) free(tip->argv);
1718                         free(tip);
1719                         return 1;
1720                 }
1721                 ltip = tip;
1722         }
1723         return 0;
1724 }
1725  
1726 int cancelEventByObject(obj)
1727         VObj *obj;
1728 {
1729         TimeInfo *ltip = NULL, *tip, *ntip;
1730  
1731         for (tip = firstTimeInfo; tip; tip = ntip) {
1732                 if (tip->obj == obj) {
1733                         if (ltip) ltip->next = tip->next;
1734                         else firstTimeInfo = tip->next;
1735                         if (tip->argv) free(tip->argv);
1736                         ntip = tip->next;
1737                         free(tip);
1738                         /* don't exit yet, there may be more than one events
1739                          * for this object
1740                          */
1741                 } else {
1742                         ltip = tip;
1743                         ntip = tip->next;
1744                 }
1745         }
1746         return 0;
1747 }
1748  
1749 void dumpSchedule()
1750 {
1751         TimeInfo *tip;
1752         struct timeval time;
1753         int i;
1754  
1755         gettimeofday(&time, (struct timezone*)NULL);
1756         printf("%d,%d now\n", time.tv_sec, time.tv_usec);
1757  
1758         for (tip = firstTimeInfo; tip; tip = tip->next) {
1759                 printf("%d,%d: obj=%s \t",
1760                         tip->time.tv_sec,
1761                         tip->time.tv_usec,
1762                         GET_name(tip->obj));
1763                 for (i = 0; i < tip->argc; i++) {
1764                         dumpPacket(&(tip->argv[i]));
1765                 }
1766                 printf("\n");
1767         }
1768 }
1769  
1770  
1771 void modalLoop()
1772 {
1773         modalState = 1;
1774  
1775         /* loop in this state, to implement modal ness */
1776         while (modalState) {
1777                 XEvent e;
1778                 VObj *obj;
1779  
1780                 XNextEvent(display, &e);
1781                 obj = findWindowObject(eventWindow(e));
1782                 if (obj) {
1783                         process_event(&e, ACTION_TOOL);
1784                 }
1785         }
1786 }
1787