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 struct sigaction gpm_saved_suspend_hook;
87
static struct sigaction gpm_saved_winch_hook;
91
#define GPM_NODE_DEV "/dev/gpmctl"
92
#define GPM_NODE_CTL GPM_NODE_DEV
94
static inline int putdata(int where, Gpm_Connect *what)
96
if (write(where,what,sizeof(Gpm_Connect))!=sizeof(Gpm_Connect))
103
static void gpm_winch_hook (int signum)
105
if (SIG_IGN != gpm_saved_winch_hook.sa_handler &&
106
SIG_DFL != gpm_saved_winch_hook.sa_handler) {
107
gpm_saved_winch_hook.sa_handler(signum);
111
static void gpm_suspend_hook (int signum)
113
Gpm_Connect gpm_connect;
119
sigemptyset (&new_sigset);
120
sigaddset (&new_sigset, SIGTSTP);
121
sigprocmask (SIG_BLOCK, &new_sigset, &old_sigset);
123
/* Open a completely transparent gpm connection */
124
gpm_connect.eventMask = 0;
125
gpm_connect.defaultMask = ~0;
126
gpm_connect.minMod = ~0;
127
gpm_connect.maxMod = 0;
128
/* cannot do this under xterm, tough */
129
success = (Gpm_Open (&gpm_connect, 0) >= 0);
131
/* take the default action, whatever it is (probably a stop :) */
132
sigprocmask (SIG_SETMASK, &old_sigset, 0);
133
sigaction (SIGTSTP, &gpm_saved_suspend_hook, 0);
134
kill (getpid (), SIGTSTP);
138
/* Reincarnation. Prepare for another death early. */
139
sigemptyset(&sa.sa_mask);
140
sa.sa_handler = gpm_suspend_hook;
141
sa.sa_flags = SA_NOMASK;
142
sigaction (SIGTSTP, &sa, 0);
144
/* Pop the gpm stack by closing the useless connection */
145
/* but do it only when we know we opened one.. */
151
static int Gpm_Open(Gpm_Connect *conn, int flag)
156
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 (!(sock_name = tempnam (0, "gpm"))) {
234
strncpy (addr.sun_path, 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);
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
sigaction(SIGTSTP, &gpm_saved_suspend_hook, 0);
341
sigaction(SIGWINCH, &gpm_saved_winch_hook, 0);
346
/*-------------------------------------------------------------------*/
347
static int Gpm_GetEvent(Gpm_Event *event)
351
if (!gpm_flag) return 0;
353
if ((count=read(gpm_fd,event,sizeof(Gpm_Event)))!=sizeof(Gpm_Event))
366
/****************************************************************************
367
These forms handle vertical scrolling of components with a height of 1
369
Horizontal scrolling won't work, and scrolling large widgets will fail
370
miserably. It shouldn't be too hard to fix either of those if anyone
371
cares to. I only use scrolling for listboxes and text boxes though so
373
*****************************************************************************/
386
struct element * elements;
392
newtComponent vertBar, exitComp;
401
int timer; /* in milliseconds */
402
struct timeval lastTimeout;
407
static void gotoComponent(struct form * form, int newComp);
408
static struct eventResult formEvent(newtComponent co, struct event ev);
409
static struct eventResult sendEvent(newtComponent comp, struct event ev);
410
static void formPlace(newtComponent co, int left, int top);
413
static newtCallback helpCallback;
415
/* this isn't static as grid.c tests against it to find forms */
416
struct componentOps formOps = {
421
newtDefaultMappedHandler,
426
static inline int componentFits(newtComponent co, int compNum) {
427
struct form * form = co->data;
428
struct element * el = form->elements + compNum;
430
if (co->top > el->co->top)
432
if (co->top + co->height < el->co->top + el->co->height)
438
newtComponent newtForm(newtComponent vertBar, void * help, int flags) {
442
co = malloc(sizeof(*co));
443
form = malloc(sizeof(*form));
451
co->takesFocus = 0; /* we may have 0 components */
453
co->destroyCallback = NULL;
457
form->numCompsAlloced = 5;
460
form->vertOffset = 0;
461
form->fixedHeight = 0;
466
form->elements = malloc(sizeof(*(form->elements)) * form->numCompsAlloced);
468
form->background = COLORSET_WINDOW;
469
form->hotKeys = malloc(sizeof(int));
470
form->numHotKeys = 0;
472
form->lastTimeout.tv_sec = form->lastTimeout.tv_usec = 0;
473
if (!(form->flags & NEWT_FLAG_NOF12)) {
474
newtFormAddHotKey(co, NEWT_KEY_F12);
476
newtFormAddHotKey (co, NEWT_KEY_ESCAPE);
479
form->vertBar = vertBar;
481
form->vertBar = NULL;
483
form->helpTag = help;
484
form->helpCb = helpCallback;
489
newtComponent newtFormGetCurrent(newtComponent co) {
490
struct form * form = co->data;
492
if (form->currComp == -1) return 0;
493
return form->elements[form->currComp].co;
496
static void formScroll(newtComponent co, int delta) {
497
struct form * form = co->data;
499
int i, newVertOffset = form->vertOffset + delta;
501
if (newVertOffset < 0)
503
if (newVertOffset > form->numRows - co->height)
504
newVertOffset = form->numRows - co->height;
506
delta = newVertOffset - form->vertOffset;
507
form->vertOffset = newVertOffset;
509
for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
510
if (el->co == form->vertBar)
512
el->co->ops->place(el->co, el->co->left, el->co->top - delta);
516
void newtFormSetCurrent(newtComponent co, newtComponent subco) {
517
struct form * form = co->data;
520
for (i = 0; i < form->numComps; i++) {
521
if (form->elements[i].co == subco) break;
524
if (form->elements[i].co != subco) return;
527
if (co->isMapped && !componentFits(co, new)) {
528
gotoComponent(form, -1);
529
formScroll(co, form->elements[new].co->top - co->top - 1);
532
gotoComponent(form, new);
535
void newtFormSetTimer(newtComponent co, int millisecs) {
536
struct form * form = co->data;
538
form->timer = millisecs;
539
form->lastTimeout.tv_usec = 0;
540
form->lastTimeout.tv_sec = 0;
543
void newtFormSetHeight(newtComponent co, int height) {
544
struct form * form = co->data;
546
form->fixedHeight = 1;
550
void newtFormSetWidth(newtComponent co, int width) {
554
void newtFormAddComponent(newtComponent co, newtComponent newco) {
555
struct form * form = co->data;
559
if (form->numCompsAlloced == form->numComps) {
560
form->numCompsAlloced += 5;
561
form->elements = realloc(form->elements,
562
sizeof(*(form->elements)) * form->numCompsAlloced);
565
form->elements[form->numComps].co = newco;
567
if (newco->takesFocus && form->currComp == -1)
568
form->currComp = form->numComps;
573
void newtFormAddComponents(newtComponent co, ...) {
579
while ((subco = va_arg(ap, newtComponent)))
580
newtFormAddComponent(co, subco);
585
static void formPlace(newtComponent co, int left, int top) {
586
struct form * form = co->data;
587
int vertDelta, horizDelta;
591
vertDelta = top - co->top;
592
horizDelta = left - co->left;
596
for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
597
el->co->ops->place(el->co, el->co->left + horizDelta,
598
el->co->top + vertDelta);
602
void newtDrawForm(newtComponent co) {
603
struct form * form = co->data;
609
SLsmg_set_color(form->background);
610
newtClearBox(co->left, co->top, co->width, co->height);
612
for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
613
/* only draw it if it'll fit on the screen vertically
614
(the scrollbar *always* fits somewhere) */
615
if (el->co == form->vertBar || componentFits(co, i)) {
616
el->co->ops->mapped(el->co, 1);
617
el->co->ops->draw(el->co);
619
el->co->ops->mapped(el->co, 0);
624
newtScrollbarSet(form->vertBar, form->vertOffset,
625
form->numRows - co->height);
628
static struct eventResult formEvent(newtComponent co, struct event ev) {
629
struct form * form = co->data;
630
newtComponent subco = form->elements[form->currComp].co;
632
struct eventResult er;
633
int dir = 0, page = 0;
637
er.result = ER_IGNORED;
638
if (!form->numComps) return er;
640
if (form->currComp == -1) return er;
644
if (ev.event == EV_KEYPRESS) {
645
if (ev.u.key == NEWT_KEY_TAB) {
646
er.result = ER_SWALLOWED;
649
} else if (ev.u.key == NEWT_KEY_UNTAB) {
650
er.result = ER_SWALLOWED;
656
if (form->numComps) {
659
while (er.result == ER_IGNORED && num != form->numComps ) {
660
er = form->elements[i].co->ops->event(form->elements[i].co, ev);
664
if (i == form->numComps) i = 0;
671
if (ev.event == EV_MOUSE) {
673
for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
674
if ((el->co->top <= ev.u.mouse.y) &&
675
(el->co->top + el->co->height > ev.u.mouse.y) &&
676
(el->co->left <= ev.u.mouse.x) &&
677
(el->co->left + el->co->width > ev.u.mouse.x)) {
679
if (el->co->takesFocus) {
680
gotoComponent(form, i);
681
subco = form->elements[form->currComp].co;
684
/* If we did not find a co to send this event to, we
685
should just swallow the event here. */
688
er.result = ER_SWALLOWED;
693
er = subco->ops->event(subco, ev);
696
er.result = ER_SWALLOWED;
701
form->exitComp = subco;
710
er = subco->ops->event(subco, ev);
712
if (er.result == ER_IGNORED) {
717
er.result = ER_SWALLOWED;
723
er.result = ER_SWALLOWED;
728
er.result = ER_SWALLOWED;
734
er.result = ER_SWALLOWED;
743
new = form->currComp;
746
new += dir * co->height;
749
else if (new >= form->numComps)
750
new = (form->numComps - 1);
752
while (!form->elements[new].co->takesFocus &&
753
new - dir >= 0 && new - dir < form->numComps)
761
new = form->numComps - 1;
762
else if (new >= form->numComps)
764
if (new == form->currComp)
765
/* back where we started */
767
} else if (new < 0 || new >= form->numComps)
769
} while (!form->elements[new].co->takesFocus);
772
/* make sure this component is visible */
773
if (!componentFits(co, new)) {
776
gotoComponent(form, -1);
779
/* make the new component the first one */
780
vertDelta = form->elements[new].co->top - co->top;
782
/* make the new component the last one */
783
vertDelta = (form->elements[new].co->top +
784
form->elements[new].co->height) -
785
(co->top + co->height);
788
formScroll(co, vertDelta);
792
gotoComponent(form, new);
793
er.result = ER_SWALLOWED;
799
/* Destroy a component. Components which have been added to a form
800
* are destroyed when the form is destroyed; this is just for the
801
* (rare) case of components which for whatever reason weren't added
804
void newtComponentDestroy(newtComponent co) {
805
/* If the user registered a destroy callback for this component,
806
* now is a good time to call it.
808
if (co->destroyCallback)
809
co->destroyCallback(co, co->destroyCallbackData);
811
if (co->ops->destroy) {
812
co->ops->destroy(co);
814
if (co->data) free(co->data);
819
/* this also destroys all of the components on the form */
820
void newtFormDestroy(newtComponent co) {
822
struct form * form = co->data;
825
/* first, destroy all of the components */
826
for (i = 0; i < form->numComps; i++) {
827
subco = form->elements[i].co;
828
newtComponentDestroy(subco);
831
if (form->hotKeys) free(form->hotKeys);
833
free(form->elements);
838
newtComponent newtRunForm(newtComponent co) {
839
struct newtExitStruct es;
841
newtFormRun(co, &es);
842
if (es.reason == NEWT_EXIT_HOTKEY) {
843
if (es.u.key == NEWT_KEY_F12) {
844
es.reason = NEWT_EXIT_COMPONENT;
849
} else if (es.reason == NEWT_EXIT_ERROR)
855
void newtFormAddHotKey(newtComponent co, int key) {
856
struct form * form = co->data;
859
form->hotKeys = realloc(form->hotKeys, sizeof(int) * form->numHotKeys);
860
form->hotKeys[form->numHotKeys - 1] = key;
863
void newtFormSetSize(newtComponent co) {
864
struct form * form = co->data;
871
if (!form->fixedHeight) co->height = 0;
877
for (i = 0, el = form->elements; i < form->numComps; i++, el++) {
878
if (el->co->ops == &formOps)
879
newtFormSetSize(el->co);
880
else if (el->co == form->vertBar)
884
co->top = el->co->top;
885
co->left = el->co->left;
889
if (co->left > el->co->left) {
890
delta = co->left - el->co->left;
895
if (co->top > el->co->top) {
896
delta = co->top - el->co->top;
898
form->numRows += delta;
899
if (!form->fixedHeight)
903
if ((co->left + co->width) < (el->co->left + el->co->width))
904
co->width = (el->co->left + el->co->width) - co->left;
906
if (!form->fixedHeight) {
907
if ((co->top + co->height) < (el->co->top + el->co->height))
908
co->height = (el->co->top + el->co->height) - co->top;
911
if ((el->co->top + el->co->height - co->top) > form->numRows) {
912
form->numRows = el->co->top + el->co->height - co->top;
916
co->top += form->vertOffset;
919
void newtFormRun(newtComponent co, struct newtExitStruct * es) {
920
struct form * form = co->data;
922
struct eventResult er;
925
fd_set readSet, writeSet, exceptSet;
926
struct timeval nextTimeout, now, timeout;
932
/* Set up GPM interface */
933
conn.eventMask = ~GPM_MOVE;
934
conn.defaultMask = GPM_MOVE;
941
/* draw all of the components */
944
if (form->currComp == -1) {
946
gotoComponent(form, 0);
948
gotoComponent(form, form->currComp);
959
FD_SET(gpm_fd, &readSet);
961
max = form->maxFd > gpm_fd ? form->maxFd : gpm_fd;
966
for (i = 0; i < form->numFds; i++) {
967
if (form->fds[i].flags & NEWT_FD_READ)
968
FD_SET(form->fds[i].fd, &readSet);
969
if (form->fds[i].flags & NEWT_FD_WRITE)
970
FD_SET(form->fds[i].fd, &writeSet);
971
if (form->fds[i].flags & NEWT_FD_EXCEPT)
972
FD_SET(form->fds[i].fd, &exceptSet);
976
/* Calculate when we next need to return with a timeout. Do
977
this inside the loop in case a callback resets the timer. */
978
gettimeofday(&now, 0);
980
if ((!form->lastTimeout.tv_sec && !form->lastTimeout.tv_usec) ||
981
now.tv_sec < form->lastTimeout.tv_sec ||
982
(now.tv_sec == form->lastTimeout.tv_sec &&
983
now.tv_usec < form->lastTimeout.tv_usec))
984
form->lastTimeout = now;
986
nextTimeout.tv_sec = form->lastTimeout.tv_sec +
987
(form->timer / 1000);
988
nextTimeout.tv_usec = form->lastTimeout.tv_usec +
989
(form->timer % 1000) * 1000;
991
if (now.tv_sec > nextTimeout.tv_sec) {
992
timeout.tv_sec = timeout.tv_usec = 0;
993
} else if (now.tv_sec == nextTimeout.tv_sec) {
995
if (now.tv_usec > nextTimeout.tv_usec)
998
timeout.tv_usec = nextTimeout.tv_usec - now.tv_usec;
999
} else if (now.tv_sec < nextTimeout.tv_sec) {
1000
timeout.tv_sec = nextTimeout.tv_sec - now.tv_sec;
1001
if (now.tv_usec > nextTimeout.tv_usec)
1003
timeout.tv_usec = nextTimeout.tv_usec + 1000000 -
1006
timeout.tv_usec = nextTimeout.tv_usec - now.tv_usec;
1009
timeout.tv_sec = timeout.tv_usec = 0;
1014
newtResizeScreen(1);
1017
i = select(max + 1, &readSet, &writeSet, &exceptSet,
1018
form->timer ? &timeout : NULL);
1019
if (i < 0) continue; /* ?? What should we do here? */
1023
es->reason = NEWT_EXIT_TIMER;
1024
gettimeofday(&form->lastTimeout, NULL);
1027
if (gpm_fd > 0 && FD_ISSET(gpm_fd, &readSet)) {
1028
Gpm_GetEvent(&event);
1030
if (event.type & GPM_DOWN) {
1031
/* Transform coordinates to current window */
1032
newtGetWindowPos(&x, &y);
1034
ev.event = EV_MOUSE;
1035
ev.u.mouse.type = MOUSE_BUTTON_DOWN;
1036
ev.u.mouse.x = event.x - x - 1;
1037
ev.u.mouse.y = event.y - y - 1;
1039
/* Send the form the event */
1040
er = sendEvent(co, ev);
1042
if (er.result == ER_EXITFORM) {
1044
es->reason = NEWT_EXIT_COMPONENT;
1045
es->u.co = form->exitComp;
1052
if (FD_ISSET(0, &readSet)) {
1056
for (i = 0; i < form->numHotKeys; i++) {
1057
if (form->hotKeys[i] == key) {
1058
es->reason = NEWT_EXIT_HOTKEY;
1065
if (key == NEWT_KEY_F1 && form->helpTag && form->helpCb) {
1066
if (form->currComp != -1) {
1067
ev.event = EV_UNFOCUS;
1068
sendEvent(form->elements[form->currComp].co, ev);
1070
form->helpCb(co, form->helpTag);
1071
if (form->currComp != -1) {
1072
ev.event = EV_FOCUS;
1073
sendEvent(form->elements[form->currComp].co, ev);
1077
if (key == NEWT_KEY_ERROR) {
1079
es->reason = NEWT_EXIT_ERROR;
1084
ev.event = EV_KEYPRESS;
1087
er = sendEvent(co, ev);
1089
if (er.result == ER_EXITFORM) {
1091
es->reason = NEWT_EXIT_COMPONENT;
1092
es->u.co = form->exitComp;
1096
for (i = 0; i < form->numFds; i++) {
1097
if (((form->fds[i].flags & NEWT_FD_READ)
1098
&& FD_ISSET(form->fds[i].fd, &readSet))
1099
|| ((form->fds[i].flags & NEWT_FD_WRITE)
1100
&& FD_ISSET(form->fds[i].fd, &writeSet))
1101
|| ((form->fds[i].flags & NEWT_FD_EXCEPT)
1102
&& FD_ISSET(form->fds[i].fd, &exceptSet))) break;
1104
if(i < form->numFds)
1105
es->u.watch = form->fds[i].fd;
1109
es->reason = NEWT_EXIT_FDREADY;
1120
static struct eventResult sendEvent(newtComponent co, struct event ev) {
1121
struct eventResult er;
1124
er = co->ops->event(co, ev);
1126
if (er.result == ER_IGNORED) {
1127
ev.when = EV_NORMAL;
1128
er = co->ops->event(co, ev);
1131
if (er.result == ER_IGNORED) {
1133
er = co->ops->event(co, ev);
1139
static void gotoComponent(struct form * form, int newComp) {
1142
if (form->currComp != -1) {
1143
ev.event = EV_UNFOCUS;
1144
sendEvent(form->elements[form->currComp].co, ev);
1147
form->currComp = newComp;
1149
if (form->currComp != -1) {
1150
ev.event = EV_FOCUS;
1151
ev.when = EV_NORMAL;
1152
sendEvent(form->elements[form->currComp].co, ev);
1156
void newtComponentAddCallback(newtComponent co, newtCallback f, void * data) {
1158
co->callbackData = data;
1161
/* Add a callback which is called when the component is destroyed. */
1162
void newtComponentAddDestroyCallback(newtComponent co,
1163
newtCallback f, void * data) {
1164
co->destroyCallback = f;
1165
co->destroyCallbackData = data;
1168
void newtComponentTakesFocus(newtComponent co, int val) {
1169
co->takesFocus = val;
1172
void newtFormSetBackground(newtComponent co, int color) {
1173
struct form * form = co->data;
1175
form->background = color;
1178
void newtFormWatchFd(newtComponent co, int fd, int fdFlags) {
1179
struct form * form = co->data;
1182
for (i = 0; i < form->numFds; i++)
1183
if (form->fds[i].fd == fd)
1186
if(i >= form->numFds)
1187
form->fds = realloc(form->fds, (++form->numFds) * sizeof(*form->fds));
1189
form->fds[i].fd = fd;
1190
form->fds[i].flags = fdFlags;
1191
if (form->maxFd < fd) form->maxFd = fd;
1194
void newtSetHelpCallback(newtCallback cb) {