8 #ifdef HAVE_SYS_SELECT_H
9 #include <sys/select.h>
15 #include <sys/time.h> /* timeval */
16 #include <sys/socket.h> /* socket() */
17 #include <sys/un.h> /* struct sockaddr_un */
18 #include <sys/fcntl.h> /* O_RDONLY */
19 #include <sys/stat.h> /* stat() */
20 #include <termios.h> /* winsize */
22 #include <sys/kd.h> /* KDGETMODE */
31 /*....................................... The connection data structure */
33 typedef struct Gpm_Connect
{
34 unsigned short eventMask
, defaultMask
;
35 unsigned short minMod
, maxMod
;
40 /*....................................... Stack struct */
41 typedef struct Gpm_Stst
{
43 struct Gpm_Stst
*next
;
48 GPM_DRAG
=2, /* exactly one of the bare ones is active at a time */
52 #define GPM_BARE_EVENTS(type) ((type)&(0x0f|GPM_ENTER|GPM_LEAVE))
54 GPM_SINGLE
=16, /* at most one in three is set */
56 GPM_TRIPLE
=64, /* WARNING: I depend on the values */
58 GPM_MFLAG
=128, /* motion during click? */
59 GPM_HARD
=256, /* if set in the defaultMask, force an already
60 used event to pass over to another handler */
62 GPM_ENTER
=512, /* enter event, user in Roi's */
63 GPM_LEAVE
=1024 /* leave event, used in Roi's */
66 /*....................................... The reported event */
68 enum Gpm_Margin
{GPM_TOP
=1, GPM_BOT
=2, GPM_LFT
=4, GPM_RGT
=8};
70 typedef struct Gpm_Event
{
71 unsigned char buttons
, modifiers
; /* try to be a multiple of 4 */
76 enum Gpm_Margin margin
;
79 static int Gpm_Open(Gpm_Connect
*conn
, int flag
);
80 static int Gpm_Close(void);
83 static int gpm_flag
=0;
84 static int gpm_tried
=0;
85 Gpm_Stst
*gpm_stack
=NULL
;
86 static char *gpm_sock_name
=NULL
;
87 static struct sigaction gpm_saved_suspend_hook
;
88 static struct sigaction gpm_saved_winch_hook
;
92 #define GPM_NODE_DEV "/dev/gpmctl"
93 #define GPM_NODE_CTL GPM_NODE_DEV
95 static inline int putdata(int where
, Gpm_Connect
*what
)
97 if (write(where
,what
,sizeof(Gpm_Connect
))!=sizeof(Gpm_Connect
))
104 static void gpm_winch_hook (int signum
)
106 if (SIG_IGN
!= gpm_saved_winch_hook
.sa_handler
&&
107 SIG_DFL
!= gpm_saved_winch_hook
.sa_handler
) {
108 gpm_saved_winch_hook
.sa_handler(signum
);
112 static void gpm_suspend_hook (int signum
)
114 Gpm_Connect gpm_connect
;
120 sigemptyset (&new_sigset
);
121 sigaddset (&new_sigset
, SIGTSTP
);
122 sigprocmask (SIG_BLOCK
, &new_sigset
, &old_sigset
);
124 /* Open a completely transparent gpm connection */
125 gpm_connect
.eventMask
= 0;
126 gpm_connect
.defaultMask
= ~0;
127 gpm_connect
.minMod
= ~0;
128 gpm_connect
.maxMod
= 0;
129 /* cannot do this under xterm, tough */
130 success
= (Gpm_Open (&gpm_connect
, 0) >= 0);
132 /* take the default action, whatever it is (probably a stop :) */
133 sigprocmask (SIG_SETMASK
, &old_sigset
, 0);
134 sigaction (SIGTSTP
, &gpm_saved_suspend_hook
, 0);
135 kill (getpid (), SIGTSTP
);
139 /* Reincarnation. Prepare for another death early. */
140 sigemptyset(&sa
.sa_mask
);
141 sa
.sa_handler
= gpm_suspend_hook
;
142 sa
.sa_flags
= SA_NOMASK
;
143 sigaction (SIGTSTP
, &sa
, 0);
145 /* Pop the gpm stack by closing the useless connection */
146 /* but do it only when we know we opened one.. */
152 static int Gpm_Open(Gpm_Connect
*conn
, int flag
)
157 struct sockaddr_un addr
;
160 /*....................................... First of all, check xterm */
162 if ((term
=(char *)getenv("TERM")) && !strncmp(term
,"xterm",5))
164 if (gpm_tried
) return gpm_fd
; /* no stack */
170 /*....................................... No xterm, go on */
174 * So I chose to use the current tty, instead of /dev/console, which
175 * has permission problems. (I am fool, and my console is
176 * readable/writeable by everybody.
178 * However, making this piece of code work has been a real hassle.
181 if (!gpm_flag
&& gpm_tried
) return -1;
182 gpm_tried
=1; /* do or die */
184 new=malloc(sizeof(Gpm_Stst
));
190 conn
->pid
=getpid(); /* fill obvious values */
193 conn
->vc
=new->next
->info
.vc
; /* inherit */
196 conn
->vc
=0; /* default handler */
198 { /* forced vc number */
200 sprintf(tty
,"/dev/tty%i",flag
);
202 else if (flag
==0) /* use your current vc */
204 char *t
= ttyname(0); /* stdin */
205 if (!t
) t
= ttyname(1); /* stdout */
208 if (strncmp(tty
,"/dev/tty",8) || !isdigit(tty
[8]))
210 conn
->vc
=atoi(tty
+8);
212 else /* a default handler -- use console */
213 sprintf(tty
,"/dev/tty0");
219 /*....................................... Connect to the control socket */
224 if ( (gpm_fd
=socket(AF_UNIX
,SOCK_STREAM
,0))<0 )
229 bzero((char *)&addr
,sizeof(addr
));
230 addr
.sun_family
=AF_UNIX
;
231 if (!(gpm_sock_name
= tempnam (0, "gpm"))) {
234 strncpy (addr
.sun_path
, gpm_sock_name
, sizeof (addr
.sun_path
));
235 if (bind (gpm_fd
, (struct sockaddr
*)&addr
,
236 sizeof (addr
.sun_family
) + strlen (addr
.sun_path
))==-1) {
240 bzero((char *)&addr
,sizeof(addr
));
241 addr
.sun_family
=AF_UNIX
;
242 strcpy(addr
.sun_path
, GPM_NODE_CTL
);
243 i
=sizeof(addr
.sun_family
)+strlen(GPM_NODE_CTL
);
245 if ( connect(gpm_fd
,(struct sockaddr
*)(&addr
),i
)<0 )
250 * Well, try to open a chr device called /dev/gpmctl. This should
251 * be forward-compatible with a kernel server
253 close(gpm_fd
); /* the socket */
254 if ((gpm_fd
=open(GPM_NODE_DEV
,O_RDWR
))==-1) {
257 if (fstat(gpm_fd
,&stbuf
)==-1 || (stbuf
.st_mode
&S_IFMT
)!=S_IFCHR
)
261 /*....................................... Put your data */
263 if (putdata(gpm_fd
,conn
)!=-1)
265 /* itz Wed Dec 16 23:22:16 PST 1998 use sigaction, the old
266 code caused a signal loop under XEmacs */
268 sigemptyset(&sa
.sa_mask
);
270 #if (defined(SIGWINCH))
271 /* And the winch hook .. */
272 sa
.sa_handler
= gpm_winch_hook
;
274 sigaction(SIGWINCH
, &sa
, &gpm_saved_winch_hook
);
277 #if (defined(SIGTSTP))
279 /* Install suspend hook */
280 sa
.sa_handler
= SIG_IGN
;
281 sigaction(SIGTSTP
, &sa
, &gpm_saved_suspend_hook
);
283 /* if signal was originally ignored, job control is not supported */
284 if (gpm_saved_suspend_hook
.sa_handler
!= SIG_IGN
) {
285 sa
.sa_flags
= SA_NOMASK
;
286 sa
.sa_handler
= gpm_suspend_hook
;
287 sigaction(SIGTSTP
, &sa
, 0);
295 /*....................................... Error: free all memory */
304 if (gpm_fd
>=0) close(gpm_fd
);
306 unlink(gpm_sock_name
);
308 gpm_sock_name
= NULL
;
315 /*-------------------------------------------------------------------*/
316 static int Gpm_Close(void)
320 gpm_tried
=0; /* reset the error flag for next time */
321 if (gpm_fd
==-2) /* xterm */
325 if (!gpm_flag
) return 0;
326 next
=gpm_stack
->next
;
330 putdata(gpm_fd
,&(next
->info
));
332 if (--gpm_flag
) return -1;
335 if (gpm_fd
>=0) close(gpm_fd
);
338 unlink(gpm_sock_name
);
340 gpm_sock_name
= NULL
;
343 sigaction(SIGTSTP
, &gpm_saved_suspend_hook
, 0);
346 sigaction(SIGWINCH
, &gpm_saved_winch_hook
, 0);
351 /*-------------------------------------------------------------------*/
352 static int Gpm_GetEvent(Gpm_Event
*event
)
356 if (!gpm_flag
) return 0;
358 if ((count
=read(gpm_fd
,event
,sizeof(Gpm_Event
)))!=sizeof(Gpm_Event
))
371 /****************************************************************************
372 These forms handle vertical scrolling of components with a height of 1
374 Horizontal scrolling won't work, and scrolling large widgets will fail
375 miserably. It shouldn't be too hard to fix either of those if anyone
376 cares to. I only use scrolling for listboxes and text boxes though so
378 *****************************************************************************/
391 struct element
* elements
;
397 newtComponent vertBar
, exitComp
;
406 int timer
; /* in milliseconds */
407 struct timeval lastTimeout
;
412 static void gotoComponent(newtComponent co
, int newComp
);
413 static struct eventResult
formEvent(newtComponent co
, struct event ev
);
414 static struct eventResult
sendEvent(newtComponent comp
, struct event ev
);
415 static void formPlace(newtComponent co
, int left
, int top
);
418 static newtCallback helpCallback
;
420 /* this isn't static as grid.c tests against it to find forms */
421 struct componentOps formOps
= {
426 newtDefaultMappedHandler
,
431 static inline int componentFits(newtComponent co
, int compNum
) {
432 struct form
* form
= co
->data
;
433 struct element
* el
= form
->elements
+ compNum
;
435 if (co
->top
> el
->co
->top
)
437 if (co
->top
+ co
->height
< el
->co
->top
+ el
->co
->height
)
443 newtComponent
newtForm(newtComponent vertBar
, void * help
, int flags
) {
447 co
= malloc(sizeof(*co
));
451 form
= malloc(sizeof(*form
));
464 co
->takesFocus
= 0; /* we may have 0 components */
467 co
->destroyCallback
= NULL
;
469 form
->elements
= NULL
;
470 form
->hotKeys
= NULL
;
474 form
->numCompsAlloced
= 5;
477 form
->vertOffset
= 0;
478 form
->fixedHeight
= 0;
483 form
->elements
= malloc(sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
484 if (form
->elements
== NULL
) goto error
;
486 form
->background
= COLORSET_WINDOW
;
487 form
->hotKeys
= malloc(sizeof(int));
488 if (form
->hotKeys
== NULL
) goto error
;
490 form
->numHotKeys
= 0;
492 form
->lastTimeout
.tv_sec
= form
->lastTimeout
.tv_usec
= 0;
493 if (!(form
->flags
& NEWT_FLAG_NOF12
)) {
494 newtFormAddHotKey(co
, NEWT_KEY_F12
);
498 form
->vertBar
= vertBar
;
500 form
->vertBar
= NULL
;
502 form
->helpTag
= help
;
503 form
->helpCb
= helpCallback
;
509 free(form
->elements
);
516 newtComponent
newtFormGetCurrent(newtComponent co
) {
517 struct form
* form
= co
->data
;
519 if (form
->currComp
== -1) return 0;
520 return form
->elements
[form
->currComp
].co
;
523 static void formScroll(newtComponent co
, int delta
) {
524 struct form
* form
= co
->data
;
526 int i
, newVertOffset
= form
->vertOffset
+ delta
;
528 if (newVertOffset
< 0)
530 if (newVertOffset
> form
->numRows
- co
->height
)
531 newVertOffset
= form
->numRows
- co
->height
;
533 delta
= newVertOffset
- form
->vertOffset
;
534 form
->vertOffset
= newVertOffset
;
536 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
537 if (el
->co
== form
->vertBar
)
539 el
->co
->ops
->place(el
->co
, el
->co
->left
, el
->co
->top
- delta
);
543 int newtFormGetScrollPosition(newtComponent co
) {
544 struct form
* form
= co
->data
;
546 return form
->vertOffset
;
549 void newtFormSetScrollPosition(newtComponent co
, int position
) {
550 struct form
* form
= co
->data
;
552 if (form
->numRows
== 0)
554 formScroll(co
, position
- form
->vertOffset
);
557 void newtFormSetCurrent(newtComponent co
, newtComponent subco
) {
558 struct form
* form
= co
->data
;
561 for (i
= 0; i
< form
->numComps
; i
++) {
562 if (form
->elements
[i
].co
== subco
) break;
565 if (form
->elements
[i
].co
!= subco
) return;
568 if (co
->isMapped
&& !componentFits(co
, new)) {
569 gotoComponent(co
, -1);
570 formScroll(co
, form
->elements
[new].co
->top
- co
->top
- 1);
573 gotoComponent(co
, new);
576 void newtFormSetTimer(newtComponent co
, int millisecs
) {
577 struct form
* form
= co
->data
;
579 form
->timer
= millisecs
;
580 form
->lastTimeout
.tv_usec
= 0;
581 form
->lastTimeout
.tv_sec
= 0;
584 void newtFormSetHeight(newtComponent co
, int height
) {
585 struct form
* form
= co
->data
;
587 form
->fixedHeight
= 1;
591 void newtFormSetWidth(newtComponent co
, int width
) {
595 void newtFormAddComponent(newtComponent co
, newtComponent newco
) {
596 struct form
* form
= co
->data
;
600 if (form
->numCompsAlloced
== form
->numComps
) {
601 form
->numCompsAlloced
+= 5;
602 form
->elements
= realloc(form
->elements
,
603 sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
606 form
->elements
[form
->numComps
].co
= newco
;
608 if (newco
->takesFocus
&& form
->currComp
== -1)
609 form
->currComp
= form
->numComps
;
614 void newtFormAddComponents(newtComponent co
, ...) {
620 while ((subco
= va_arg(ap
, newtComponent
)))
621 newtFormAddComponent(co
, subco
);
626 static void formPlace(newtComponent co
, int left
, int top
) {
627 struct form
* form
= co
->data
;
628 int vertDelta
, horizDelta
;
632 vertDelta
= top
- co
->top
;
633 horizDelta
= left
- co
->left
;
637 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
638 el
->co
->ops
->place(el
->co
, el
->co
->left
+ horizDelta
,
639 el
->co
->top
+ vertDelta
);
643 void newtDrawForm(newtComponent co
) {
644 struct form
* form
= co
->data
;
650 SLsmg_set_color(form
->background
);
651 newtClearBox(co
->left
, co
->top
, co
->width
, co
->height
);
653 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
654 /* only draw it if it'll fit on the screen vertically
655 (the scrollbar *always* fits somewhere) */
656 if (el
->co
== form
->vertBar
|| componentFits(co
, i
)) {
657 el
->co
->ops
->mapped(el
->co
, 1);
658 el
->co
->ops
->draw(el
->co
);
660 el
->co
->ops
->mapped(el
->co
, 0);
665 newtScrollbarSet(form
->vertBar
, form
->vertOffset
,
666 form
->numRows
- co
->height
);
669 static struct eventResult
formEvent(newtComponent co
, struct event ev
) {
670 struct form
* form
= co
->data
;
671 newtComponent subco
= form
->elements
[form
->currComp
].co
;
673 struct eventResult er
;
674 int dir
= 0, page
= 0;
678 er
.result
= ER_IGNORED
;
679 if (!form
->numComps
) return er
;
681 if (form
->currComp
== -1) return er
;
685 if (ev
.event
== EV_KEYPRESS
) {
686 if (ev
.u
.key
== NEWT_KEY_TAB
) {
687 er
.result
= ER_SWALLOWED
;
690 } else if (ev
.u
.key
== NEWT_KEY_UNTAB
) {
691 er
.result
= ER_SWALLOWED
;
697 if (form
->numComps
) {
700 while (er
.result
== ER_IGNORED
&& num
!= form
->numComps
) {
701 er
= form
->elements
[i
].co
->ops
->event(form
->elements
[i
].co
, ev
);
705 if (i
== form
->numComps
) i
= 0;
712 if (ev
.event
== EV_MOUSE
) {
714 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
715 if ((el
->co
->top
<= ev
.u
.mouse
.y
) &&
716 (el
->co
->top
+ el
->co
->height
> ev
.u
.mouse
.y
) &&
717 (el
->co
->left
<= ev
.u
.mouse
.x
) &&
718 (el
->co
->left
+ el
->co
->width
> ev
.u
.mouse
.x
)) {
720 if (el
->co
->takesFocus
) {
721 gotoComponent(co
, i
);
722 subco
= form
->elements
[form
->currComp
].co
;
725 /* If we did not find a co to send this event to, we
726 should just swallow the event here. */
729 er
.result
= ER_SWALLOWED
;
734 er
= subco
->ops
->event(subco
, ev
);
737 er
.result
= ER_SWALLOWED
;
742 form
->exitComp
= subco
;
751 er
= subco
->ops
->event(subco
, ev
);
753 if (er
.result
== ER_IGNORED
) {
758 er
.result
= ER_SWALLOWED
;
764 er
.result
= ER_SWALLOWED
;
769 er
.result
= ER_SWALLOWED
;
775 er
.result
= ER_SWALLOWED
;
784 new = form
->currComp
;
787 new += dir
* co
->height
;
790 else if (new >= form
->numComps
)
791 new = (form
->numComps
- 1);
793 while (!form
->elements
[new].co
->takesFocus
&&
794 new - dir
>= 0 && new - dir
< form
->numComps
)
802 new = form
->numComps
- 1;
803 else if (new >= form
->numComps
)
805 if (new == form
->currComp
)
806 /* back where we started */
808 } else if (new < 0 || new >= form
->numComps
)
810 } while (!form
->elements
[new].co
->takesFocus
);
813 /* make sure this component is visible */
814 if (!componentFits(co
, new)) {
817 gotoComponent(co
, -1);
820 /* make the new component the first one */
821 vertDelta
= form
->elements
[new].co
->top
- co
->top
;
823 /* make the new component the last one */
824 vertDelta
= (form
->elements
[new].co
->top
+
825 form
->elements
[new].co
->height
) -
826 (co
->top
+ co
->height
);
829 formScroll(co
, vertDelta
);
833 gotoComponent(co
, new);
834 er
.result
= ER_SWALLOWED
;
840 /* Destroy a component. Components which have been added to a form
841 * are destroyed when the form is destroyed; this is just for the
842 * (rare) case of components which for whatever reason weren't added
845 void newtComponentDestroy(newtComponent co
) {
846 /* If the user registered a destroy callback for this component,
847 * now is a good time to call it.
849 if (co
->destroyCallback
)
850 co
->destroyCallback(co
, co
->destroyCallbackData
);
852 if (co
->ops
->destroy
) {
853 co
->ops
->destroy(co
);
855 if (co
->data
) free(co
->data
);
860 /* this also destroys all of the components on the form */
861 void newtFormDestroy(newtComponent co
) {
863 struct form
* form
= co
->data
;
866 /* first, destroy all of the components */
867 for (i
= 0; i
< form
->numComps
; i
++) {
868 subco
= form
->elements
[i
].co
;
869 newtComponentDestroy(subco
);
872 if (form
->hotKeys
) free(form
->hotKeys
);
874 free(form
->elements
);
879 newtComponent
newtRunForm(newtComponent co
) {
880 struct newtExitStruct es
;
882 newtFormRun(co
, &es
);
883 if (es
.reason
== NEWT_EXIT_HOTKEY
) {
884 if (es
.u
.key
== NEWT_KEY_F12
) {
885 es
.reason
= NEWT_EXIT_COMPONENT
;
890 } else if (es
.reason
== NEWT_EXIT_ERROR
)
896 void newtFormAddHotKey(newtComponent co
, int key
) {
897 struct form
* form
= co
->data
;
900 form
->hotKeys
= realloc(form
->hotKeys
, sizeof(int) * form
->numHotKeys
);
901 form
->hotKeys
[form
->numHotKeys
- 1] = key
;
904 void newtFormSetSize(newtComponent co
) {
905 struct form
* form
= co
->data
;
912 if (!form
->fixedHeight
) co
->height
= 0;
918 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
919 if (el
->co
->ops
== &formOps
)
920 newtFormSetSize(el
->co
);
921 else if (el
->co
== form
->vertBar
)
925 co
->top
= el
->co
->top
;
926 co
->left
= el
->co
->left
;
930 if (co
->left
> el
->co
->left
) {
931 delta
= co
->left
- el
->co
->left
;
936 if (co
->top
> el
->co
->top
) {
937 delta
= co
->top
- el
->co
->top
;
939 form
->numRows
+= delta
;
940 if (!form
->fixedHeight
)
944 if ((co
->left
+ co
->width
) < (el
->co
->left
+ el
->co
->width
))
945 co
->width
= (el
->co
->left
+ el
->co
->width
) - co
->left
;
947 if (!form
->fixedHeight
) {
948 if ((co
->top
+ co
->height
) < (el
->co
->top
+ el
->co
->height
))
949 co
->height
= (el
->co
->top
+ el
->co
->height
) - co
->top
;
952 if ((el
->co
->top
+ el
->co
->height
- co
->top
) > form
->numRows
) {
953 form
->numRows
= el
->co
->top
+ el
->co
->height
- co
->top
;
957 co
->top
+= form
->vertOffset
;
960 void newtFormRun(newtComponent co
, struct newtExitStruct
* es
) {
961 struct form
* form
= co
->data
;
963 struct eventResult er
;
966 fd_set readSet
, writeSet
, exceptSet
;
967 struct timeval nextTimeout
, now
, timeout
;
973 /* Set up GPM interface */
974 conn
.eventMask
= ~GPM_MOVE
;
975 conn
.defaultMask
= GPM_MOVE
;
982 /* draw all of the components */
985 if (form
->currComp
== -1) {
987 gotoComponent(co
, 0);
989 gotoComponent(co
, form
->currComp
);
1000 FD_SET(gpm_fd
, &readSet
);
1002 max
= form
->maxFd
> gpm_fd
? form
->maxFd
: gpm_fd
;
1007 for (i
= 0; i
< form
->numFds
; i
++) {
1008 if (form
->fds
[i
].flags
& NEWT_FD_READ
)
1009 FD_SET(form
->fds
[i
].fd
, &readSet
);
1010 if (form
->fds
[i
].flags
& NEWT_FD_WRITE
)
1011 FD_SET(form
->fds
[i
].fd
, &writeSet
);
1012 if (form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
1013 FD_SET(form
->fds
[i
].fd
, &exceptSet
);
1017 /* Calculate when we next need to return with a timeout. Do
1018 this inside the loop in case a callback resets the timer. */
1019 gettimeofday(&now
, 0);
1021 if ((!form
->lastTimeout
.tv_sec
&& !form
->lastTimeout
.tv_usec
) ||
1022 now
.tv_sec
< form
->lastTimeout
.tv_sec
||
1023 (now
.tv_sec
== form
->lastTimeout
.tv_sec
&&
1024 now
.tv_usec
< form
->lastTimeout
.tv_usec
))
1025 form
->lastTimeout
= now
;
1027 nextTimeout
.tv_sec
= form
->lastTimeout
.tv_sec
+
1028 (form
->timer
/ 1000);
1029 nextTimeout
.tv_usec
= form
->lastTimeout
.tv_usec
+
1030 (form
->timer
% 1000) * 1000;
1032 if (now
.tv_sec
> nextTimeout
.tv_sec
) {
1033 timeout
.tv_sec
= timeout
.tv_usec
= 0;
1034 } else if (now
.tv_sec
== nextTimeout
.tv_sec
) {
1036 if (now
.tv_usec
> nextTimeout
.tv_usec
)
1037 timeout
.tv_usec
= 0;
1039 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
1040 } else if (now
.tv_sec
< nextTimeout
.tv_sec
) {
1041 timeout
.tv_sec
= nextTimeout
.tv_sec
- now
.tv_sec
;
1042 if (now
.tv_usec
> nextTimeout
.tv_usec
)
1044 timeout
.tv_usec
= nextTimeout
.tv_usec
+ 1000000 -
1047 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
1050 timeout
.tv_sec
= timeout
.tv_usec
= 0;
1055 newtResizeScreen(1);
1057 /* The application may want to handle the resize */
1058 for (i
= 0; i
< form
->numHotKeys
; i
++) {
1059 if (form
->hotKeys
[i
] == NEWT_KEY_RESIZE
) {
1060 es
->reason
= NEWT_EXIT_HOTKEY
;
1061 es
->u
.key
= NEWT_KEY_RESIZE
;
1070 i
= select(max
+ 1, &readSet
, &writeSet
, &exceptSet
,
1071 form
->timer
? &timeout
: NULL
);
1072 if (i
< 0) continue; /* ?? What should we do here? */
1076 es
->reason
= NEWT_EXIT_TIMER
;
1077 gettimeofday(&form
->lastTimeout
, NULL
);
1080 if (gpm_fd
> 0 && FD_ISSET(gpm_fd
, &readSet
)) {
1081 Gpm_GetEvent(&event
);
1083 if (event
.type
& GPM_DOWN
) {
1084 /* Transform coordinates to current window */
1085 newtGetWindowPos(&x
, &y
);
1087 ev
.event
= EV_MOUSE
;
1088 ev
.u
.mouse
.type
= MOUSE_BUTTON_DOWN
;
1089 ev
.u
.mouse
.x
= event
.x
- x
- 1;
1090 ev
.u
.mouse
.y
= event
.y
- y
- 1;
1092 /* Send the form the event */
1093 er
= sendEvent(co
, ev
);
1095 if (er
.result
== ER_EXITFORM
) {
1097 es
->reason
= NEWT_EXIT_COMPONENT
;
1098 es
->u
.co
= form
->exitComp
;
1105 if (FD_ISSET(0, &readSet
)) {
1109 for (i
= 0; i
< form
->numHotKeys
; i
++) {
1110 if (form
->hotKeys
[i
] == key
) {
1111 es
->reason
= NEWT_EXIT_HOTKEY
;
1118 if (key
== NEWT_KEY_F1
&& form
->helpTag
&& form
->helpCb
) {
1119 if (form
->currComp
!= -1) {
1120 ev
.event
= EV_UNFOCUS
;
1121 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1123 form
->helpCb(co
, form
->helpTag
);
1124 if (form
->currComp
!= -1) {
1125 ev
.event
= EV_FOCUS
;
1126 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1130 if (key
== NEWT_KEY_ERROR
) {
1132 es
->reason
= NEWT_EXIT_ERROR
;
1137 ev
.event
= EV_KEYPRESS
;
1140 er
= sendEvent(co
, ev
);
1142 if (er
.result
== ER_EXITFORM
) {
1144 es
->reason
= NEWT_EXIT_COMPONENT
;
1145 es
->u
.co
= form
->exitComp
;
1149 for (i
= 0; i
< form
->numFds
; i
++) {
1150 if (((form
->fds
[i
].flags
& NEWT_FD_READ
)
1151 && FD_ISSET(form
->fds
[i
].fd
, &readSet
))
1152 || ((form
->fds
[i
].flags
& NEWT_FD_WRITE
)
1153 && FD_ISSET(form
->fds
[i
].fd
, &writeSet
))
1154 || ((form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
1155 && FD_ISSET(form
->fds
[i
].fd
, &exceptSet
))) break;
1157 if(i
< form
->numFds
)
1158 es
->u
.watch
= form
->fds
[i
].fd
;
1162 es
->reason
= NEWT_EXIT_FDREADY
;
1173 static struct eventResult
sendEvent(newtComponent co
, struct event ev
) {
1174 struct eventResult er
;
1177 er
= co
->ops
->event(co
, ev
);
1179 if (er
.result
== ER_IGNORED
) {
1180 ev
.when
= EV_NORMAL
;
1181 er
= co
->ops
->event(co
, ev
);
1184 if (er
.result
== ER_IGNORED
) {
1186 er
= co
->ops
->event(co
, ev
);
1192 static void gotoComponent(newtComponent co
, int newComp
) {
1193 struct form
* form
= co
->data
;
1196 if (form
->currComp
!= -1) {
1197 ev
.event
= EV_UNFOCUS
;
1198 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1201 form
->currComp
= newComp
;
1203 if (form
->currComp
!= -1) {
1204 ev
.event
= EV_FOCUS
;
1205 ev
.when
= EV_NORMAL
;
1206 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1210 co
->callback(co
, co
->callbackData
);
1213 void newtComponentAddCallback(newtComponent co
, newtCallback f
, void * data
) {
1215 co
->callbackData
= data
;
1218 /* Add a callback which is called when the component is destroyed. */
1219 void newtComponentAddDestroyCallback(newtComponent co
,
1220 newtCallback f
, void * data
) {
1221 co
->destroyCallback
= f
;
1222 co
->destroyCallbackData
= data
;
1225 void newtComponentTakesFocus(newtComponent co
, int val
) {
1226 co
->takesFocus
= val
;
1229 void newtFormSetBackground(newtComponent co
, int color
) {
1230 struct form
* form
= co
->data
;
1232 form
->background
= color
;
1235 void newtFormWatchFd(newtComponent co
, int fd
, int fdFlags
) {
1236 struct form
* form
= co
->data
;
1239 for (i
= 0; i
< form
->numFds
; i
++)
1240 if (form
->fds
[i
].fd
== fd
)
1243 if(i
>= form
->numFds
)
1244 form
->fds
= realloc(form
->fds
, (++form
->numFds
) * sizeof(*form
->fds
));
1246 form
->fds
[i
].fd
= fd
;
1247 form
->fds
[i
].flags
= fdFlags
;
1248 if (form
->maxFd
< fd
) form
->maxFd
= fd
;
1251 void newtSetHelpCallback(newtCallback cb
) {