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
));
448 form
= malloc(sizeof(*form
));
456 co
->takesFocus
= 0; /* we may have 0 components */
459 co
->destroyCallback
= NULL
;
463 form
->numCompsAlloced
= 5;
466 form
->vertOffset
= 0;
467 form
->fixedHeight
= 0;
472 form
->elements
= malloc(sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
474 form
->background
= COLORSET_WINDOW
;
475 form
->hotKeys
= malloc(sizeof(int));
476 form
->numHotKeys
= 0;
478 form
->lastTimeout
.tv_sec
= form
->lastTimeout
.tv_usec
= 0;
479 if (!(form
->flags
& NEWT_FLAG_NOF12
)) {
480 newtFormAddHotKey(co
, NEWT_KEY_F12
);
484 form
->vertBar
= vertBar
;
486 form
->vertBar
= NULL
;
488 form
->helpTag
= help
;
489 form
->helpCb
= helpCallback
;
494 newtComponent
newtFormGetCurrent(newtComponent co
) {
495 struct form
* form
= co
->data
;
497 if (form
->currComp
== -1) return 0;
498 return form
->elements
[form
->currComp
].co
;
501 static void formScroll(newtComponent co
, int delta
) {
502 struct form
* form
= co
->data
;
504 int i
, newVertOffset
= form
->vertOffset
+ delta
;
506 if (newVertOffset
< 0)
508 if (newVertOffset
> form
->numRows
- co
->height
)
509 newVertOffset
= form
->numRows
- co
->height
;
511 delta
= newVertOffset
- form
->vertOffset
;
512 form
->vertOffset
= newVertOffset
;
514 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
515 if (el
->co
== form
->vertBar
)
517 el
->co
->ops
->place(el
->co
, el
->co
->left
, el
->co
->top
- delta
);
521 int newtFormGetScrollPosition(newtComponent co
) {
522 struct form
* form
= co
->data
;
524 return form
->vertOffset
;
527 void newtFormSetScrollPosition(newtComponent co
, int position
) {
528 struct form
* form
= co
->data
;
530 if (form
->numRows
== 0)
532 formScroll(co
, position
- form
->vertOffset
);
535 void newtFormSetCurrent(newtComponent co
, newtComponent subco
) {
536 struct form
* form
= co
->data
;
539 for (i
= 0; i
< form
->numComps
; i
++) {
540 if (form
->elements
[i
].co
== subco
) break;
543 if (form
->elements
[i
].co
!= subco
) return;
546 if (co
->isMapped
&& !componentFits(co
, new)) {
547 gotoComponent(co
, -1);
548 formScroll(co
, form
->elements
[new].co
->top
- co
->top
- 1);
551 gotoComponent(co
, new);
554 void newtFormSetTimer(newtComponent co
, int millisecs
) {
555 struct form
* form
= co
->data
;
557 form
->timer
= millisecs
;
558 form
->lastTimeout
.tv_usec
= 0;
559 form
->lastTimeout
.tv_sec
= 0;
562 void newtFormSetHeight(newtComponent co
, int height
) {
563 struct form
* form
= co
->data
;
565 form
->fixedHeight
= 1;
569 void newtFormSetWidth(newtComponent co
, int width
) {
573 void newtFormAddComponent(newtComponent co
, newtComponent newco
) {
574 struct form
* form
= co
->data
;
578 if (form
->numCompsAlloced
== form
->numComps
) {
579 form
->numCompsAlloced
+= 5;
580 form
->elements
= realloc(form
->elements
,
581 sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
584 form
->elements
[form
->numComps
].co
= newco
;
586 if (newco
->takesFocus
&& form
->currComp
== -1)
587 form
->currComp
= form
->numComps
;
592 void newtFormAddComponents(newtComponent co
, ...) {
598 while ((subco
= va_arg(ap
, newtComponent
)))
599 newtFormAddComponent(co
, subco
);
604 static void formPlace(newtComponent co
, int left
, int top
) {
605 struct form
* form
= co
->data
;
606 int vertDelta
, horizDelta
;
610 vertDelta
= top
- co
->top
;
611 horizDelta
= left
- co
->left
;
615 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
616 el
->co
->ops
->place(el
->co
, el
->co
->left
+ horizDelta
,
617 el
->co
->top
+ vertDelta
);
621 void newtDrawForm(newtComponent co
) {
622 struct form
* form
= co
->data
;
628 SLsmg_set_color(form
->background
);
629 newtClearBox(co
->left
, co
->top
, co
->width
, co
->height
);
631 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
632 /* only draw it if it'll fit on the screen vertically
633 (the scrollbar *always* fits somewhere) */
634 if (el
->co
== form
->vertBar
|| componentFits(co
, i
)) {
635 el
->co
->ops
->mapped(el
->co
, 1);
636 el
->co
->ops
->draw(el
->co
);
638 el
->co
->ops
->mapped(el
->co
, 0);
643 newtScrollbarSet(form
->vertBar
, form
->vertOffset
,
644 form
->numRows
- co
->height
);
647 static struct eventResult
formEvent(newtComponent co
, struct event ev
) {
648 struct form
* form
= co
->data
;
649 newtComponent subco
= form
->elements
[form
->currComp
].co
;
651 struct eventResult er
;
652 int dir
= 0, page
= 0;
656 er
.result
= ER_IGNORED
;
657 if (!form
->numComps
) return er
;
659 if (form
->currComp
== -1) return er
;
663 if (ev
.event
== EV_KEYPRESS
) {
664 if (ev
.u
.key
== NEWT_KEY_TAB
) {
665 er
.result
= ER_SWALLOWED
;
668 } else if (ev
.u
.key
== NEWT_KEY_UNTAB
) {
669 er
.result
= ER_SWALLOWED
;
675 if (form
->numComps
) {
678 while (er
.result
== ER_IGNORED
&& num
!= form
->numComps
) {
679 er
= form
->elements
[i
].co
->ops
->event(form
->elements
[i
].co
, ev
);
683 if (i
== form
->numComps
) i
= 0;
690 if (ev
.event
== EV_MOUSE
) {
692 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
693 if ((el
->co
->top
<= ev
.u
.mouse
.y
) &&
694 (el
->co
->top
+ el
->co
->height
> ev
.u
.mouse
.y
) &&
695 (el
->co
->left
<= ev
.u
.mouse
.x
) &&
696 (el
->co
->left
+ el
->co
->width
> ev
.u
.mouse
.x
)) {
698 if (el
->co
->takesFocus
) {
699 gotoComponent(co
, i
);
700 subco
= form
->elements
[form
->currComp
].co
;
703 /* If we did not find a co to send this event to, we
704 should just swallow the event here. */
707 er
.result
= ER_SWALLOWED
;
712 er
= subco
->ops
->event(subco
, ev
);
715 er
.result
= ER_SWALLOWED
;
720 form
->exitComp
= subco
;
729 er
= subco
->ops
->event(subco
, ev
);
731 if (er
.result
== ER_IGNORED
) {
736 er
.result
= ER_SWALLOWED
;
742 er
.result
= ER_SWALLOWED
;
747 er
.result
= ER_SWALLOWED
;
753 er
.result
= ER_SWALLOWED
;
762 new = form
->currComp
;
765 new += dir
* co
->height
;
768 else if (new >= form
->numComps
)
769 new = (form
->numComps
- 1);
771 while (!form
->elements
[new].co
->takesFocus
&&
772 new - dir
>= 0 && new - dir
< form
->numComps
)
780 new = form
->numComps
- 1;
781 else if (new >= form
->numComps
)
783 if (new == form
->currComp
)
784 /* back where we started */
786 } else if (new < 0 || new >= form
->numComps
)
788 } while (!form
->elements
[new].co
->takesFocus
);
791 /* make sure this component is visible */
792 if (!componentFits(co
, new)) {
795 gotoComponent(co
, -1);
798 /* make the new component the first one */
799 vertDelta
= form
->elements
[new].co
->top
- co
->top
;
801 /* make the new component the last one */
802 vertDelta
= (form
->elements
[new].co
->top
+
803 form
->elements
[new].co
->height
) -
804 (co
->top
+ co
->height
);
807 formScroll(co
, vertDelta
);
811 gotoComponent(co
, new);
812 er
.result
= ER_SWALLOWED
;
818 /* Destroy a component. Components which have been added to a form
819 * are destroyed when the form is destroyed; this is just for the
820 * (rare) case of components which for whatever reason weren't added
823 void newtComponentDestroy(newtComponent co
) {
824 /* If the user registered a destroy callback for this component,
825 * now is a good time to call it.
827 if (co
->destroyCallback
)
828 co
->destroyCallback(co
, co
->destroyCallbackData
);
830 if (co
->ops
->destroy
) {
831 co
->ops
->destroy(co
);
833 if (co
->data
) free(co
->data
);
838 /* this also destroys all of the components on the form */
839 void newtFormDestroy(newtComponent co
) {
841 struct form
* form
= co
->data
;
844 /* first, destroy all of the components */
845 for (i
= 0; i
< form
->numComps
; i
++) {
846 subco
= form
->elements
[i
].co
;
847 newtComponentDestroy(subco
);
850 if (form
->hotKeys
) free(form
->hotKeys
);
852 free(form
->elements
);
857 newtComponent
newtRunForm(newtComponent co
) {
858 struct newtExitStruct es
;
860 newtFormRun(co
, &es
);
861 if (es
.reason
== NEWT_EXIT_HOTKEY
) {
862 if (es
.u
.key
== NEWT_KEY_F12
) {
863 es
.reason
= NEWT_EXIT_COMPONENT
;
868 } else if (es
.reason
== NEWT_EXIT_ERROR
)
874 void newtFormAddHotKey(newtComponent co
, int key
) {
875 struct form
* form
= co
->data
;
878 form
->hotKeys
= realloc(form
->hotKeys
, sizeof(int) * form
->numHotKeys
);
879 form
->hotKeys
[form
->numHotKeys
- 1] = key
;
882 void newtFormSetSize(newtComponent co
) {
883 struct form
* form
= co
->data
;
890 if (!form
->fixedHeight
) co
->height
= 0;
896 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
897 if (el
->co
->ops
== &formOps
)
898 newtFormSetSize(el
->co
);
899 else if (el
->co
== form
->vertBar
)
903 co
->top
= el
->co
->top
;
904 co
->left
= el
->co
->left
;
908 if (co
->left
> el
->co
->left
) {
909 delta
= co
->left
- el
->co
->left
;
914 if (co
->top
> el
->co
->top
) {
915 delta
= co
->top
- el
->co
->top
;
917 form
->numRows
+= delta
;
918 if (!form
->fixedHeight
)
922 if ((co
->left
+ co
->width
) < (el
->co
->left
+ el
->co
->width
))
923 co
->width
= (el
->co
->left
+ el
->co
->width
) - co
->left
;
925 if (!form
->fixedHeight
) {
926 if ((co
->top
+ co
->height
) < (el
->co
->top
+ el
->co
->height
))
927 co
->height
= (el
->co
->top
+ el
->co
->height
) - co
->top
;
930 if ((el
->co
->top
+ el
->co
->height
- co
->top
) > form
->numRows
) {
931 form
->numRows
= el
->co
->top
+ el
->co
->height
- co
->top
;
935 co
->top
+= form
->vertOffset
;
938 void newtFormRun(newtComponent co
, struct newtExitStruct
* es
) {
939 struct form
* form
= co
->data
;
941 struct eventResult er
;
944 fd_set readSet
, writeSet
, exceptSet
;
945 struct timeval nextTimeout
, now
, timeout
;
951 /* Set up GPM interface */
952 conn
.eventMask
= ~GPM_MOVE
;
953 conn
.defaultMask
= GPM_MOVE
;
960 /* draw all of the components */
963 if (form
->currComp
== -1) {
965 gotoComponent(co
, 0);
967 gotoComponent(co
, form
->currComp
);
978 FD_SET(gpm_fd
, &readSet
);
980 max
= form
->maxFd
> gpm_fd
? form
->maxFd
: gpm_fd
;
985 for (i
= 0; i
< form
->numFds
; i
++) {
986 if (form
->fds
[i
].flags
& NEWT_FD_READ
)
987 FD_SET(form
->fds
[i
].fd
, &readSet
);
988 if (form
->fds
[i
].flags
& NEWT_FD_WRITE
)
989 FD_SET(form
->fds
[i
].fd
, &writeSet
);
990 if (form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
991 FD_SET(form
->fds
[i
].fd
, &exceptSet
);
995 /* Calculate when we next need to return with a timeout. Do
996 this inside the loop in case a callback resets the timer. */
997 gettimeofday(&now
, 0);
999 if ((!form
->lastTimeout
.tv_sec
&& !form
->lastTimeout
.tv_usec
) ||
1000 now
.tv_sec
< form
->lastTimeout
.tv_sec
||
1001 (now
.tv_sec
== form
->lastTimeout
.tv_sec
&&
1002 now
.tv_usec
< form
->lastTimeout
.tv_usec
))
1003 form
->lastTimeout
= now
;
1005 nextTimeout
.tv_sec
= form
->lastTimeout
.tv_sec
+
1006 (form
->timer
/ 1000);
1007 nextTimeout
.tv_usec
= form
->lastTimeout
.tv_usec
+
1008 (form
->timer
% 1000) * 1000;
1010 if (now
.tv_sec
> nextTimeout
.tv_sec
) {
1011 timeout
.tv_sec
= timeout
.tv_usec
= 0;
1012 } else if (now
.tv_sec
== nextTimeout
.tv_sec
) {
1014 if (now
.tv_usec
> nextTimeout
.tv_usec
)
1015 timeout
.tv_usec
= 0;
1017 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
1018 } else if (now
.tv_sec
< nextTimeout
.tv_sec
) {
1019 timeout
.tv_sec
= nextTimeout
.tv_sec
- now
.tv_sec
;
1020 if (now
.tv_usec
> nextTimeout
.tv_usec
)
1022 timeout
.tv_usec
= nextTimeout
.tv_usec
+ 1000000 -
1025 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
1028 timeout
.tv_sec
= timeout
.tv_usec
= 0;
1033 newtResizeScreen(1);
1035 /* The application may want to handle the resize */
1036 for (i
= 0; i
< form
->numHotKeys
; i
++) {
1037 if (form
->hotKeys
[i
] == NEWT_KEY_RESIZE
) {
1038 es
->reason
= NEWT_EXIT_HOTKEY
;
1039 es
->u
.key
= NEWT_KEY_RESIZE
;
1048 i
= select(max
+ 1, &readSet
, &writeSet
, &exceptSet
,
1049 form
->timer
? &timeout
: NULL
);
1050 if (i
< 0) continue; /* ?? What should we do here? */
1054 es
->reason
= NEWT_EXIT_TIMER
;
1055 gettimeofday(&form
->lastTimeout
, NULL
);
1058 if (gpm_fd
> 0 && FD_ISSET(gpm_fd
, &readSet
)) {
1059 Gpm_GetEvent(&event
);
1061 if (event
.type
& GPM_DOWN
) {
1062 /* Transform coordinates to current window */
1063 newtGetWindowPos(&x
, &y
);
1065 ev
.event
= EV_MOUSE
;
1066 ev
.u
.mouse
.type
= MOUSE_BUTTON_DOWN
;
1067 ev
.u
.mouse
.x
= event
.x
- x
- 1;
1068 ev
.u
.mouse
.y
= event
.y
- y
- 1;
1070 /* Send the form the event */
1071 er
= sendEvent(co
, ev
);
1073 if (er
.result
== ER_EXITFORM
) {
1075 es
->reason
= NEWT_EXIT_COMPONENT
;
1076 es
->u
.co
= form
->exitComp
;
1083 if (FD_ISSET(0, &readSet
)) {
1087 for (i
= 0; i
< form
->numHotKeys
; i
++) {
1088 if (form
->hotKeys
[i
] == key
) {
1089 es
->reason
= NEWT_EXIT_HOTKEY
;
1096 if (key
== NEWT_KEY_F1
&& form
->helpTag
&& form
->helpCb
) {
1097 if (form
->currComp
!= -1) {
1098 ev
.event
= EV_UNFOCUS
;
1099 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1101 form
->helpCb(co
, form
->helpTag
);
1102 if (form
->currComp
!= -1) {
1103 ev
.event
= EV_FOCUS
;
1104 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1108 if (key
== NEWT_KEY_ERROR
) {
1110 es
->reason
= NEWT_EXIT_ERROR
;
1115 ev
.event
= EV_KEYPRESS
;
1118 er
= sendEvent(co
, ev
);
1120 if (er
.result
== ER_EXITFORM
) {
1122 es
->reason
= NEWT_EXIT_COMPONENT
;
1123 es
->u
.co
= form
->exitComp
;
1127 for (i
= 0; i
< form
->numFds
; i
++) {
1128 if (((form
->fds
[i
].flags
& NEWT_FD_READ
)
1129 && FD_ISSET(form
->fds
[i
].fd
, &readSet
))
1130 || ((form
->fds
[i
].flags
& NEWT_FD_WRITE
)
1131 && FD_ISSET(form
->fds
[i
].fd
, &writeSet
))
1132 || ((form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
1133 && FD_ISSET(form
->fds
[i
].fd
, &exceptSet
))) break;
1135 if(i
< form
->numFds
)
1136 es
->u
.watch
= form
->fds
[i
].fd
;
1140 es
->reason
= NEWT_EXIT_FDREADY
;
1151 static struct eventResult
sendEvent(newtComponent co
, struct event ev
) {
1152 struct eventResult er
;
1155 er
= co
->ops
->event(co
, ev
);
1157 if (er
.result
== ER_IGNORED
) {
1158 ev
.when
= EV_NORMAL
;
1159 er
= co
->ops
->event(co
, ev
);
1162 if (er
.result
== ER_IGNORED
) {
1164 er
= co
->ops
->event(co
, ev
);
1170 static void gotoComponent(newtComponent co
, int newComp
) {
1171 struct form
* form
= co
->data
;
1174 if (form
->currComp
!= -1) {
1175 ev
.event
= EV_UNFOCUS
;
1176 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1179 form
->currComp
= newComp
;
1181 if (form
->currComp
!= -1) {
1182 ev
.event
= EV_FOCUS
;
1183 ev
.when
= EV_NORMAL
;
1184 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1188 co
->callback(co
, co
->callbackData
);
1191 void newtComponentAddCallback(newtComponent co
, newtCallback f
, void * data
) {
1193 co
->callbackData
= data
;
1196 /* Add a callback which is called when the component is destroyed. */
1197 void newtComponentAddDestroyCallback(newtComponent co
,
1198 newtCallback f
, void * data
) {
1199 co
->destroyCallback
= f
;
1200 co
->destroyCallbackData
= data
;
1203 void newtComponentTakesFocus(newtComponent co
, int val
) {
1204 co
->takesFocus
= val
;
1207 void newtFormSetBackground(newtComponent co
, int color
) {
1208 struct form
* form
= co
->data
;
1210 form
->background
= color
;
1213 void newtFormWatchFd(newtComponent co
, int fd
, int fdFlags
) {
1214 struct form
* form
= co
->data
;
1217 for (i
= 0; i
< form
->numFds
; i
++)
1218 if (form
->fds
[i
].fd
== fd
)
1221 if(i
>= form
->numFds
)
1222 form
->fds
= realloc(form
->fds
, (++form
->numFds
) * sizeof(*form
->fds
));
1224 form
->fds
[i
].fd
= fd
;
1225 form
->fds
[i
].flags
= fdFlags
;
1226 if (form
->maxFd
< fd
) form
->maxFd
= fd
;
1229 void newtSetHelpCallback(newtCallback cb
) {