6 #include <sys/select.h>
11 #include <sys/time.h> /* timeval */
12 #include <sys/types.h> /* socket() */
13 #include <sys/socket.h> /* socket() */
14 #include <sys/un.h> /* struct sockaddr_un */
15 #include <sys/fcntl.h> /* O_RDONLY */
16 #include <sys/stat.h> /* stat() */
17 #include <termios.h> /* winsize */
19 #include <sys/kd.h> /* KDGETMODE */
28 /*....................................... The connection data structure */
30 typedef struct Gpm_Connect
{
31 unsigned short eventMask
, defaultMask
;
32 unsigned short minMod
, maxMod
;
37 /*....................................... Stack struct */
38 typedef struct Gpm_Stst
{
40 struct Gpm_Stst
*next
;
45 GPM_DRAG
=2, /* exactly one of the bare ones is active at a time */
49 #define GPM_BARE_EVENTS(type) ((type)&(0x0f|GPM_ENTER|GPM_LEAVE))
51 GPM_SINGLE
=16, /* at most one in three is set */
53 GPM_TRIPLE
=64, /* WARNING: I depend on the values */
55 GPM_MFLAG
=128, /* motion during click? */
56 GPM_HARD
=256, /* if set in the defaultMask, force an already
57 used event to pass over to another handler */
59 GPM_ENTER
=512, /* enter event, user in Roi's */
60 GPM_LEAVE
=1024 /* leave event, used in Roi's */
63 /*....................................... The reported event */
65 enum Gpm_Margin
{GPM_TOP
=1, GPM_BOT
=2, GPM_LFT
=4, GPM_RGT
=8};
67 typedef struct Gpm_Event
{
68 unsigned char buttons
, modifiers
; /* try to be a multiple of 4 */
73 enum Gpm_Margin margin
;
76 static int Gpm_Open(Gpm_Connect
*conn
, int flag
);
77 static int Gpm_Close(void);
80 static int gpm_flag
=0;
81 static int gpm_tried
=0;
82 Gpm_Stst
*gpm_stack
=NULL
;
83 static struct sigaction gpm_saved_suspend_hook
;
84 static struct sigaction gpm_saved_winch_hook
;
88 #define GPM_NODE_DEV "/dev/gpmctl"
89 #define GPM_NODE_CTL GPM_NODE_DEV
91 static inline int putdata(int where
, Gpm_Connect
*what
)
93 if (write(where
,what
,sizeof(Gpm_Connect
))!=sizeof(Gpm_Connect
))
100 static void gpm_winch_hook (int signum
)
102 if (SIG_IGN
!= gpm_saved_winch_hook
.sa_handler
&&
103 SIG_DFL
!= gpm_saved_winch_hook
.sa_handler
) {
104 gpm_saved_winch_hook
.sa_handler(signum
);
108 static void gpm_suspend_hook (int signum
)
110 Gpm_Connect gpm_connect
;
116 sigemptyset (&new_sigset
);
117 sigaddset (&new_sigset
, SIGTSTP
);
118 sigprocmask (SIG_BLOCK
, &new_sigset
, &old_sigset
);
120 /* Open a completely transparent gpm connection */
121 gpm_connect
.eventMask
= 0;
122 gpm_connect
.defaultMask
= ~0;
123 gpm_connect
.minMod
= ~0;
124 gpm_connect
.maxMod
= 0;
125 /* cannot do this under xterm, tough */
126 success
= (Gpm_Open (&gpm_connect
, 0) >= 0);
128 /* take the default action, whatever it is (probably a stop :) */
129 sigprocmask (SIG_SETMASK
, &old_sigset
, 0);
130 sigaction (SIGTSTP
, &gpm_saved_suspend_hook
, 0);
131 kill (getpid (), SIGTSTP
);
135 /* Reincarnation. Prepare for another death early. */
136 sigemptyset(&sa
.sa_mask
);
137 sa
.sa_handler
= gpm_suspend_hook
;
138 sa
.sa_flags
= SA_NOMASK
;
139 sigaction (SIGTSTP
, &sa
, 0);
141 /* Pop the gpm stack by closing the useless connection */
142 /* but do it only when we know we opened one.. */
148 static int Gpm_Open(Gpm_Connect
*conn
, int flag
)
153 struct sockaddr_un addr
;
157 /*....................................... First of all, check xterm */
159 if ((term
=(char *)getenv("TERM")) && !strncmp(term
,"xterm",5))
161 if (gpm_tried
) return gpm_fd
; /* no stack */
167 /*....................................... No xterm, go on */
171 * So I chose to use the current tty, instead of /dev/console, which
172 * has permission problems. (I am fool, and my console is
173 * readable/writeable by everybody.
175 * However, making this piece of code work has been a real hassle.
178 if (!gpm_flag
&& gpm_tried
) return -1;
179 gpm_tried
=1; /* do or die */
181 new=malloc(sizeof(Gpm_Stst
));
187 conn
->pid
=getpid(); /* fill obvious values */
190 conn
->vc
=new->next
->info
.vc
; /* inherit */
193 conn
->vc
=0; /* default handler */
195 { /* forced vc number */
197 sprintf(tty
,"/dev/tty%i",flag
);
199 else if (flag
==0) /* use your current vc */
201 char *t
= ttyname(0); /* stdin */
202 if (!t
) t
= ttyname(1); /* stdout */
205 if (strncmp(tty
,"/dev/tty",8) || !isdigit(tty
[8]))
207 conn
->vc
=atoi(tty
+8);
209 else /* a default handler -- use console */
210 sprintf(tty
,"/dev/tty0");
216 /*....................................... Connect to the control socket */
221 if ( (gpm_fd
=socket(AF_UNIX
,SOCK_STREAM
,0))<0 )
226 bzero((char *)&addr
,sizeof(addr
));
227 addr
.sun_family
=AF_UNIX
;
228 if (!(sock_name
= tempnam (0, "gpm"))) {
231 strncpy (addr
.sun_path
, sock_name
, sizeof (addr
.sun_path
));
232 if (bind (gpm_fd
, (struct sockaddr
*)&addr
,
233 sizeof (addr
.sun_family
) + strlen (addr
.sun_path
))==-1) {
237 bzero((char *)&addr
,sizeof(addr
));
238 addr
.sun_family
=AF_UNIX
;
239 strcpy(addr
.sun_path
, GPM_NODE_CTL
);
240 i
=sizeof(addr
.sun_family
)+strlen(GPM_NODE_CTL
);
242 if ( connect(gpm_fd
,(struct sockaddr
*)(&addr
),i
)<0 )
247 * Well, try to open a chr device called /dev/gpmctl. This should
248 * be forward-compatible with a kernel server
250 close(gpm_fd
); /* the socket */
251 if ((gpm_fd
=open(GPM_NODE_DEV
,O_RDWR
))==-1) {
254 if (fstat(gpm_fd
,&stbuf
)==-1 || (stbuf
.st_mode
&S_IFMT
)!=S_IFCHR
)
258 /*....................................... Put your data */
260 if (putdata(gpm_fd
,conn
)!=-1)
262 /* itz Wed Dec 16 23:22:16 PST 1998 use sigaction, the old
263 code caused a signal loop under XEmacs */
265 sigemptyset(&sa
.sa_mask
);
267 #if (defined(SIGWINCH))
268 /* And the winch hook .. */
269 sa
.sa_handler
= gpm_winch_hook
;
271 sigaction(SIGWINCH
, &sa
, &gpm_saved_winch_hook
);
274 #if (defined(SIGTSTP))
276 /* Install suspend hook */
277 sa
.sa_handler
= SIG_IGN
;
278 sigaction(SIGTSTP
, &sa
, &gpm_saved_suspend_hook
);
280 /* if signal was originally ignored, job control is not supported */
281 if (gpm_saved_suspend_hook
.sa_handler
!= SIG_IGN
) {
282 sa
.sa_flags
= SA_NOMASK
;
283 sa
.sa_handler
= gpm_suspend_hook
;
284 sigaction(SIGTSTP
, &sa
, 0);
292 /*....................................... Error: free all memory */
301 if (gpm_fd
>=0) close(gpm_fd
);
311 /*-------------------------------------------------------------------*/
312 static int Gpm_Close(void)
316 gpm_tried
=0; /* reset the error flag for next time */
317 if (gpm_fd
==-2) /* xterm */
321 if (!gpm_flag
) return 0;
322 next
=gpm_stack
->next
;
326 putdata(gpm_fd
,&(next
->info
));
328 if (--gpm_flag
) return -1;
331 if (gpm_fd
>=0) close(gpm_fd
);
334 sigaction(SIGTSTP
, &gpm_saved_suspend_hook
, 0);
337 sigaction(SIGWINCH
, &gpm_saved_winch_hook
, 0);
342 /*-------------------------------------------------------------------*/
343 static int Gpm_GetEvent(Gpm_Event
*event
)
347 if (!gpm_flag
) return 0;
349 if ((count
=read(gpm_fd
,event
,sizeof(Gpm_Event
)))!=sizeof(Gpm_Event
))
362 /****************************************************************************
363 These forms handle vertical scrolling of components with a height of 1
365 Horizontal scrolling won't work, and scrolling large widgets will fail
366 miserably. It shouldn't be too hard to fix either of those if anyone
367 cares to. I only use scrolling for listboxes and text boxes though so
369 *****************************************************************************/
372 int top
, left
; /* Actual, not virtual. These are translated */
373 newtComponent co
; /* into actual through vertOffset */
383 struct element
* elements
;
389 newtComponent vertBar
, exitComp
;
399 int timer
; /* in milliseconds */
400 struct timeval lastTimeout
;
405 static void gotoComponent(struct form
* form
, int newComp
);
406 static struct eventResult
formEvent(newtComponent co
, struct event ev
);
407 static struct eventResult
sendEvent(newtComponent comp
, struct event ev
);
408 static void formPlace(newtComponent co
, int left
, int top
);
411 static newtCallback helpCallback
;
413 /* this isn't static as grid.c tests against it to find forms */
414 struct componentOps formOps
= {
419 newtDefaultMappedHandler
,
422 static inline int componentFits(newtComponent co
, int compNum
) {
423 struct form
* form
= co
->data
;
424 struct element
* el
= form
->elements
+ compNum
;
426 if ((co
->top
+ form
->vertOffset
) > el
->top
) return 0;
427 if ((co
->top
+ form
->vertOffset
+ co
->height
) <
428 (el
->top
+ el
->co
->height
)) return 0;
433 newtComponent
newtForm(newtComponent vertBar
, void * help
, int flags
) {
437 co
= malloc(sizeof(*co
));
438 form
= malloc(sizeof(*form
));
446 co
->takesFocus
= 0; /* we may have 0 components */
451 form
->numCompsAlloced
= 5;
454 form
->vertOffset
= 0;
455 form
->fixedHeight
= 0;
461 form
->elements
= malloc(sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
463 form
->background
= COLORSET_WINDOW
;
464 form
->hotKeys
= malloc(sizeof(int));
465 form
->numHotKeys
= 0;
467 form
->lastTimeout
.tv_sec
= form
->lastTimeout
.tv_usec
= 0;
468 if (!(form
->flags
& NEWT_FLAG_NOF12
)) {
469 newtFormAddHotKey(co
, NEWT_KEY_F12
);
473 form
->vertBar
= vertBar
;
475 form
->vertBar
= NULL
;
477 form
->helpTag
= help
;
478 form
->helpCb
= helpCallback
;
483 newtComponent
newtFormGetCurrent(newtComponent co
) {
484 struct form
* form
= co
->data
;
486 return form
->elements
[form
->currComp
].co
;
489 void newtFormSetCurrent(newtComponent co
, newtComponent subco
) {
490 struct form
* form
= co
->data
;
493 for (i
= 0; i
< form
->numComps
; i
++) {
494 if (form
->elements
[i
].co
== subco
) break;
497 if (form
->elements
[i
].co
!= subco
) return;
500 if (co
->isMapped
&& !componentFits(co
, new)) {
501 gotoComponent(form
, -1);
502 form
->vertOffset
= form
->elements
[new].top
- co
->top
- 1;
503 if (form
->vertOffset
> (form
->numRows
- co
->height
))
504 form
->vertOffset
= form
->numRows
- co
->height
;
507 gotoComponent(form
, new);
510 void newtFormSetTimer(newtComponent co
, int millisecs
) {
511 struct form
* form
= co
->data
;
513 form
->timer
= millisecs
;
514 form
->lastTimeout
.tv_usec
= 0;
515 form
->lastTimeout
.tv_sec
= 0;
518 void newtFormSetHeight(newtComponent co
, int height
) {
519 struct form
* form
= co
->data
;
521 form
->fixedHeight
= 1;
525 void newtFormSetWidth(newtComponent co
, int width
) {
529 void newtFormAddComponent(newtComponent co
, newtComponent newco
) {
530 struct form
* form
= co
->data
;
534 if (form
->numCompsAlloced
== form
->numComps
) {
535 form
->numCompsAlloced
+= 5;
536 form
->elements
= realloc(form
->elements
,
537 sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
540 /* we grab real values for these a bit later */
541 form
->elements
[form
->numComps
].left
= -2;
542 form
->elements
[form
->numComps
].top
= -2;
543 form
->elements
[form
->numComps
].co
= newco
;
545 if (newco
->takesFocus
&& form
->currComp
== -1)
546 form
->currComp
= form
->numComps
;
551 void newtFormAddComponents(newtComponent co
, ...) {
557 while ((subco
= va_arg(ap
, newtComponent
)))
558 newtFormAddComponent(co
, subco
);
563 static void formPlace(newtComponent co
, int left
, int top
) {
564 struct form
* form
= co
->data
;
565 int vertDelta
, horizDelta
;
571 vertDelta
= top
- co
->top
;
572 horizDelta
= left
- co
->left
;
576 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
577 el
->co
->top
+= vertDelta
;
578 el
->top
+= vertDelta
;
579 el
->co
->left
+= horizDelta
;
580 el
->left
+= horizDelta
;
584 void newtDrawForm(newtComponent co
) {
585 struct form
* form
= co
->data
;
591 SLsmg_set_color(form
->background
);
592 newtClearBox(co
->left
, co
->top
, co
->width
, co
->height
);
594 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
595 /* the scrollbar *always* fits somewhere */
596 if (el
->co
== form
->vertBar
) {
597 el
->co
->ops
->mapped(el
->co
, 1);
598 el
->co
->ops
->draw(el
->co
);
600 /* only draw it if it'll fit on the screen vertically */
601 if (componentFits(co
, i
)) {
602 el
->co
->top
= el
->top
- form
->vertOffset
;
603 el
->co
->ops
->mapped(el
->co
, 1);
604 el
->co
->ops
->draw(el
->co
);
606 el
->co
->ops
->mapped(el
->co
, 0);
612 newtScrollbarSet(form
->vertBar
, form
->vertOffset
,
613 form
->numRows
- co
->height
);
616 static struct eventResult
formEvent(newtComponent co
, struct event ev
) {
617 struct form
* form
= co
->data
;
618 newtComponent subco
= form
->elements
[form
->currComp
].co
;
620 struct eventResult er
;
621 int dir
= 0, page
= 0;
625 er
.result
= ER_IGNORED
;
626 if (!form
->numComps
) return er
;
628 subco
= form
->elements
[form
->currComp
].co
;
632 if (ev
.event
== EV_KEYPRESS
) {
633 if (ev
.u
.key
== NEWT_KEY_TAB
) {
634 er
.result
= ER_SWALLOWED
;
637 } else if (ev
.u
.key
== NEWT_KEY_UNTAB
) {
638 er
.result
= ER_SWALLOWED
;
644 if (form
->numComps
) {
647 while (er
.result
== ER_IGNORED
&& num
!= form
->numComps
) {
648 er
= form
->elements
[i
].co
->ops
->event(form
->elements
[i
].co
, ev
);
652 if (i
== form
->numComps
) i
= 0;
659 if (ev
.event
== EV_MOUSE
) {
661 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
662 if ((el
->co
->top
<= ev
.u
.mouse
.y
) &&
663 (el
->co
->top
+ el
->co
->height
> ev
.u
.mouse
.y
) &&
664 (el
->co
->left
<= ev
.u
.mouse
.x
) &&
665 (el
->co
->left
+ el
->co
->width
> ev
.u
.mouse
.x
)) {
667 if (el
->co
->takesFocus
) {
668 gotoComponent(form
, i
);
669 subco
= form
->elements
[form
->currComp
].co
;
672 /* If we did not find a co to send this event to, we
673 should just swallow the event here. */
676 er
.result
= ER_SWALLOWED
;
681 er
= subco
->ops
->event(subco
, ev
);
684 er
.result
= ER_SWALLOWED
;
689 form
->exitComp
= subco
;
698 er
= subco
->ops
->event(subco
, ev
);
700 if (er
.result
== ER_IGNORED
) {
705 er
.result
= ER_SWALLOWED
;
711 er
.result
= ER_SWALLOWED
;
716 er
.result
= ER_SWALLOWED
;
722 er
.result
= ER_SWALLOWED
;
731 new = form
->currComp
;
734 new += dir
* co
->height
;
737 else if (new >= form
->numComps
)
738 new = (form
->numComps
- 1);
740 while (!form
->elements
[new].co
->takesFocus
)
748 new = form
->numComps
- 1;
749 else if (new >= form
->numComps
)
751 } else if (new < 0 || new >= form
->numComps
)
753 } while (!form
->elements
[new].co
->takesFocus
);
756 /* make sure this component is visible */
757 if (!componentFits(co
, new)) {
758 gotoComponent(form
, -1);
761 /* make the new component the first one */
762 form
->vertOffset
= form
->elements
[new].top
- co
->top
;
764 /* make the new component the last one */
765 form
->vertOffset
= (form
->elements
[new].top
+
766 form
->elements
[new].co
->height
) -
767 (co
->top
+ co
->height
);
770 if (form
->vertOffset
< 0) form
->vertOffset
= 0;
771 if (form
->vertOffset
> (form
->numRows
- co
->height
))
772 form
->vertOffset
= form
->numRows
- co
->height
;
777 gotoComponent(form
, new);
778 er
.result
= ER_SWALLOWED
;
784 /* this also destroys all of the components on the form */
785 void newtFormDestroy(newtComponent co
) {
787 struct form
* form
= co
->data
;
790 /* first, destroy all of the components */
791 for (i
= 0; i
< form
->numComps
; i
++) {
792 subco
= form
->elements
[i
].co
;
793 if (subco
->ops
->destroy
) {
794 subco
->ops
->destroy(subco
);
796 if (subco
->data
) free(subco
->data
);
801 if (form
->hotKeys
) free(form
->hotKeys
);
803 free(form
->elements
);
808 newtComponent
newtRunForm(newtComponent co
) {
809 struct newtExitStruct es
;
811 newtFormRun(co
, &es
);
812 if (es
.reason
== NEWT_EXIT_HOTKEY
) {
813 if (es
.u
.key
== NEWT_KEY_F12
) {
814 es
.reason
= NEWT_EXIT_COMPONENT
;
824 void newtFormAddHotKey(newtComponent co
, int key
) {
825 struct form
* form
= co
->data
;
828 form
->hotKeys
= realloc(form
->hotKeys
, sizeof(int) * form
->numHotKeys
);
829 form
->hotKeys
[form
->numHotKeys
- 1] = key
;
832 void newtFormSetSize(newtComponent co
) {
833 struct form
* form
= co
->data
;
837 if (form
->beenSet
) return;
841 if (!form
->numComps
) return;
844 if (!form
->fixedHeight
) co
->height
= 0;
846 co
->top
= form
->elements
[0].co
->top
;
847 co
->left
= form
->elements
[0].co
->left
;
848 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
849 if (el
->co
->ops
== &formOps
)
850 newtFormSetSize(el
->co
);
852 el
->left
= el
->co
->left
;
853 el
->top
= el
->co
->top
;
855 if (co
->left
> el
->co
->left
) {
856 delta
= co
->left
- el
->co
->left
;
861 if (co
->top
> el
->co
->top
) {
862 delta
= co
->top
- el
->co
->top
;
864 if (!form
->fixedHeight
)
868 if ((co
->left
+ co
->width
) < (el
->co
->left
+ el
->co
->width
))
869 co
->width
= (el
->co
->left
+ el
->co
->width
) - co
->left
;
871 if (!form
->fixedHeight
) {
872 if ((co
->top
+ co
->height
) < (el
->co
->top
+ el
->co
->height
))
873 co
->height
= (el
->co
->top
+ el
->co
->height
) - co
->top
;
876 if ((el
->co
->top
+ el
->co
->height
- co
->top
) > form
->numRows
) {
877 form
->numRows
= el
->co
->top
+ el
->co
->height
- co
->top
;
882 void newtFormRun(newtComponent co
, struct newtExitStruct
* es
) {
883 struct form
* form
= co
->data
;
885 struct eventResult er
;
888 fd_set readSet
, writeSet
, exceptSet
;
889 struct timeval nextTimeout
, now
, timeout
;
895 /* Set up GPM interface */
896 conn
.eventMask
= ~GPM_MOVE
;
897 conn
.defaultMask
= GPM_MOVE
;
905 /* draw all of the components */
908 if (form
->currComp
== -1) {
909 gotoComponent(form
, 0);
911 gotoComponent(form
, form
->currComp
);
922 FD_SET(gpm_fd
, &readSet
);
924 max
= form
->maxFd
> gpm_fd
? form
->maxFd
: gpm_fd
;
929 for (i
= 0; i
< form
->numFds
; i
++) {
930 if (form
->fds
[i
].flags
& NEWT_FD_READ
)
931 FD_SET(form
->fds
[i
].fd
, &readSet
);
932 if (form
->fds
[i
].flags
& NEWT_FD_WRITE
)
933 FD_SET(form
->fds
[i
].fd
, &writeSet
);
934 if (form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
935 FD_SET(form
->fds
[i
].fd
, &exceptSet
);
939 /* Calculate when we next need to return with a timeout. Do
940 this inside the loop in case a callback resets the timer. */
941 if (!form
->lastTimeout
.tv_sec
&& !form
->lastTimeout
.tv_usec
)
942 gettimeofday(&form
->lastTimeout
, NULL
);
944 nextTimeout
.tv_sec
= form
->lastTimeout
.tv_sec
+
945 (form
->timer
/ 1000);
946 nextTimeout
.tv_usec
= form
->lastTimeout
.tv_usec
+
947 (form
->timer
% 1000) * 1000;
949 gettimeofday(&now
, 0);
951 if (now
.tv_sec
> nextTimeout
.tv_sec
) {
952 timeout
.tv_sec
= timeout
.tv_usec
= 0;
953 } else if (now
.tv_sec
== nextTimeout
.tv_sec
) {
955 if (now
.tv_usec
> nextTimeout
.tv_usec
)
958 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
959 } else if (now
.tv_sec
< nextTimeout
.tv_sec
) {
960 timeout
.tv_sec
= nextTimeout
.tv_sec
- now
.tv_sec
;
961 if (now
.tv_usec
> nextTimeout
.tv_usec
)
963 timeout
.tv_usec
= nextTimeout
.tv_usec
+ 1000000 -
966 timeout
.tv_usec
= nextTimeout
.tv_usec
- now
.tv_usec
;
969 timeout
.tv_sec
= timeout
.tv_usec
= 0;
972 i
= select(max
+ 1, &readSet
, &writeSet
, &exceptSet
,
973 form
->timer
? &timeout
: NULL
);
974 if (i
< 0) continue; /* ?? What should we do here? */
978 es
->reason
= NEWT_EXIT_TIMER
;
979 gettimeofday(&form
->lastTimeout
, NULL
);
982 if (gpm_fd
> 0 && FD_ISSET(gpm_fd
, &readSet
)) {
983 Gpm_GetEvent(&event
);
985 if (event
.type
& GPM_DOWN
) {
986 /* Transform coordinates to current window */
987 newtGetWindowPos(&x
, &y
);
990 ev
.u
.mouse
.type
= MOUSE_BUTTON_DOWN
;
991 ev
.u
.mouse
.x
= event
.x
- x
- 1;
992 ev
.u
.mouse
.y
= event
.y
- y
- 1;
994 /* Send the form the event */
995 er
= sendEvent(co
, ev
);
997 if (er
.result
== ER_EXITFORM
) {
999 es
->reason
= NEWT_EXIT_COMPONENT
;
1000 es
->u
.co
= form
->exitComp
;
1007 if (FD_ISSET(0, &readSet
)) {
1011 if (key
== NEWT_KEY_RESIZE
) {
1012 /* newtResizeScreen(1); */
1016 for (i
= 0; i
< form
->numHotKeys
; i
++) {
1017 if (form
->hotKeys
[i
] == key
) {
1018 es
->reason
= NEWT_EXIT_HOTKEY
;
1025 if (key
== NEWT_KEY_F1
&& form
->helpTag
&& form
->helpCb
)
1026 form
->helpCb(co
, form
->helpTag
);
1029 ev
.event
= EV_KEYPRESS
;
1032 er
= sendEvent(co
, ev
);
1034 if (er
.result
== ER_EXITFORM
) {
1036 es
->reason
= NEWT_EXIT_COMPONENT
;
1037 es
->u
.co
= form
->exitComp
;
1041 for (i
= 0; i
< form
->numFds
; i
++) {
1042 if (((form
->fds
[i
].flags
& NEWT_FD_READ
)
1043 && FD_ISSET(form
->fds
[i
].fd
, &readSet
))
1044 || ((form
->fds
[i
].flags
& NEWT_FD_WRITE
)
1045 && FD_ISSET(form
->fds
[i
].fd
, &writeSet
))
1046 || ((form
->fds
[i
].flags
& NEWT_FD_EXCEPT
)
1047 && FD_ISSET(form
->fds
[i
].fd
, &exceptSet
))) break;
1049 if(i
< form
->numFds
)
1050 es
->u
.watch
= form
->fds
[i
].fd
;
1054 es
->reason
= NEWT_EXIT_FDREADY
;
1065 static struct eventResult
sendEvent(newtComponent co
, struct event ev
) {
1066 struct eventResult er
;
1069 er
= co
->ops
->event(co
, ev
);
1071 if (er
.result
== ER_IGNORED
) {
1072 ev
.when
= EV_NORMAL
;
1073 er
= co
->ops
->event(co
, ev
);
1076 if (er
.result
== ER_IGNORED
) {
1078 er
= co
->ops
->event(co
, ev
);
1084 static void gotoComponent(struct form
* form
, int newComp
) {
1087 if (form
->currComp
!= -1) {
1088 ev
.event
= EV_UNFOCUS
;
1089 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1092 form
->currComp
= newComp
;
1094 if (form
->currComp
!= -1) {
1095 ev
.event
= EV_FOCUS
;
1096 ev
.when
= EV_NORMAL
;
1097 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
1101 void newtComponentAddCallback(newtComponent co
, newtCallback f
, void * data
) {
1103 co
->callbackData
= data
;
1106 void newtComponentTakesFocus(newtComponent co
, int val
) {
1107 co
->takesFocus
= val
;
1110 void newtFormSetBackground(newtComponent co
, int color
) {
1111 struct form
* form
= co
->data
;
1113 form
->background
= color
;
1116 void newtFormWatchFd(newtComponent co
, int fd
, int fdFlags
) {
1117 struct form
* form
= co
->data
;
1120 for (i
= 0; i
< form
->numFds
; i
++)
1121 if (form
->fds
[i
].fd
== fd
)
1124 if(i
>= form
->numFds
)
1125 form
->fds
= realloc(form
->fds
, (++form
->numFds
) * sizeof(*form
->fds
));
1127 form
->fds
[i
].fd
= fd
;
1128 form
->fds
[i
].flags
= fdFlags
;
1129 if (form
->maxFd
< fd
) form
->maxFd
= fd
;
1132 void newtSetHelpCallback(newtCallback cb
) {