]>
git.ipfire.org Git - thirdparty/newt.git/blob - form.c
8 /****************************************************************************
9 These forms handle vertical scrolling of components with a height of 1
11 Horizontal scrolling won't work, and scrolling large widgets will fail
12 miserably. It shouldn't be too hard to fix either of those if anyone
13 cares to. I only use scrolling for listboxes and text boxes though so
15 *****************************************************************************/
18 int top
, left
; /* actual, not virtual */
24 struct element
* elements
;
30 newtComponent vertBar
, exitComp
;
38 static void gotoComponent(struct form
* form
, int newComp
);
39 static struct eventResult
formEvent(newtComponent co
, struct event ev
);
40 static struct eventResult
sendEvent(newtComponent comp
, struct event ev
);
42 static struct componentOps formOps
= {
48 static inline int componentFits(newtComponent co
, int compNum
) {
49 struct form
* form
= co
->data
;
50 struct element
* el
= form
->elements
+ compNum
;
52 if ((co
->top
+ form
->vertOffset
) > el
->top
) return 0;
53 if ((co
->top
+ form
->vertOffset
+ co
->height
) <
54 (el
->top
+ el
->co
->height
)) return 0;
59 newtComponent
newtForm(newtComponent vertBar
, const char * help
, int flags
) {
63 co
= malloc(sizeof(*co
));
64 form
= malloc(sizeof(*form
));
76 form
->numCompsAlloced
= 5;
80 form
->fixedHeight
= 0;
82 form
->elements
= malloc(sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
84 form
->background
= COLORSET_WINDOW
;
85 form
->hotKeys
= malloc(sizeof(int));
87 if (!(form
->flags
& NEWT_FLAG_NOF12
)) {
88 newtFormAddHotKey(co
, NEWT_KEY_F12
);
92 form
->vertBar
= vertBar
;
99 newtComponent
newtFormGetCurrent(newtComponent co
) {
100 struct form
* form
= co
->data
;
102 return form
->elements
[form
->currComp
].co
;
105 void newtFormSetCurrent(newtComponent co
, newtComponent subco
) {
106 struct form
* form
= co
->data
;
109 for (i
= 0; i
< form
->numComps
; i
++) {
110 if (form
->elements
[i
].co
== subco
) break;
113 if (form
->elements
[i
].co
!= subco
) return;
116 if (!componentFits(co
, new)) {
117 gotoComponent(form
, -1);
118 form
->vertOffset
= form
->elements
[new].top
- co
->top
- 1;
119 if (form
->vertOffset
> (form
->numRows
- co
->height
))
120 form
->vertOffset
= form
->numRows
- co
->height
;
123 gotoComponent(form
, new);
126 void newtFormSetHeight(newtComponent co
, int height
) {
127 struct form
* form
= co
->data
;
129 form
->fixedHeight
= 1;
133 void newtFormSetWidth(newtComponent co
, int width
) {
137 void newtFormAddComponent(newtComponent co
, newtComponent newco
) {
138 struct form
* form
= co
->data
;
141 if (form
->numCompsAlloced
== form
->numComps
) {
142 form
->numCompsAlloced
+= 5;
143 form
->elements
= realloc(form
->elements
,
144 sizeof(*(form
->elements
)) * form
->numCompsAlloced
);
147 form
->elements
[form
->numComps
].left
= newco
->left
;
148 form
->elements
[form
->numComps
].top
= newco
->top
;
149 form
->elements
[form
->numComps
].co
= newco
;
151 if (newco
->takesFocus
&& form
->currComp
== -1)
152 form
->currComp
= form
->numComps
;
156 if (co
->left
== -1) {
157 co
->left
= newco
->left
;
158 co
->top
= newco
->top
;
159 co
->width
= newco
->width
;
160 if (!form
->fixedHeight
) {
161 co
->height
= newco
->height
;
164 if (co
->left
> newco
->left
) {
165 delta
= co
->left
- newco
->left
;
170 if (co
->top
> newco
->top
) {
171 delta
= co
->top
- newco
->top
;
173 if (!form
->fixedHeight
)
177 if ((co
->left
+ co
->width
) < (newco
->left
+ newco
->width
))
178 co
->width
= (newco
->left
+ newco
->width
) - co
->left
;
180 if (!form
->fixedHeight
) {
181 if ((co
->top
+ co
->height
) < (newco
->top
+ newco
->height
))
182 co
->height
= (newco
->top
+ newco
->height
) - co
->top
;
186 if ((newco
->top
+ newco
->height
- co
->top
) > form
->numRows
) {
187 form
->numRows
= newco
->top
+ newco
->height
- co
->top
;
192 void newtFormAddComponents(newtComponent co
, ...) {
198 while ((subco
= va_arg(ap
, newtComponent
)))
199 newtFormAddComponent(co
, subco
);
204 void newtDrawForm(newtComponent co
) {
205 struct form
* form
= co
->data
;
209 SLsmg_set_color(form
->background
);
210 newtClearBox(co
->left
, co
->top
, co
->width
, co
->height
);
211 for (i
= 0, el
= form
->elements
; i
< form
->numComps
; i
++, el
++) {
212 /* the scrollbar *always* fits */
213 if (el
->co
== form
->vertBar
)
214 el
->co
->ops
->draw(el
->co
);
216 /* only draw it if it'll fit on the screen vertically */
217 if (componentFits(co
, i
)) {
218 el
->co
->top
= el
->top
- form
->vertOffset
;
219 el
->co
->isMapped
= 1;
220 el
->co
->ops
->draw(el
->co
);
222 el
->co
->top
= -1; /* tell it not to draw itself */
228 newtScrollbarSet(form
->vertBar
, form
->vertOffset
,
229 form
->numRows
- co
->height
);
232 static struct eventResult
formEvent(newtComponent co
, struct event ev
) {
233 struct form
* form
= co
->data
;
234 newtComponent subco
= form
->elements
[form
->currComp
].co
;
236 struct eventResult er
;
237 int dir
= 0, page
= 0;
240 er
.result
= ER_IGNORED
;
244 if (ev
.event
== EV_KEYPRESS
) {
245 if (ev
.u
.key
== NEWT_KEY_TAB
) {
246 er
.result
= ER_SWALLOWED
;
249 } else if (ev
.u
.key
== NEWT_KEY_UNTAB
) {
250 er
.result
= ER_SWALLOWED
;
258 while (er
.result
== ER_IGNORED
&& num
!= form
->numComps
) {
259 er
= form
->elements
[i
].co
->ops
->event(form
->elements
[i
].co
, ev
);
263 if (i
== form
->numComps
) i
= 0;
269 er
= subco
->ops
->event(subco
, ev
);
272 er
.result
= ER_SWALLOWED
;
277 form
->exitComp
= subco
;
286 er
= subco
->ops
->event(subco
, ev
);
288 if (er
.result
== ER_IGNORED
) {
293 er
.result
= ER_SWALLOWED
;
299 er
.result
= ER_SWALLOWED
;
304 er
.result
= ER_SWALLOWED
;
310 er
.result
= ER_SWALLOWED
;
319 new = form
->currComp
;
322 new += dir
* co
->height
;
325 else if (new >= form
->numComps
)
326 new = (form
->numComps
- 1);
328 while (!form
->elements
[new].co
->takesFocus
)
336 new = form
->numComps
- 1;
337 else if (new >= form
->numComps
)
339 } else if (new < 0 || new >= form
->numComps
)
341 } while (!form
->elements
[new].co
->takesFocus
);
344 /* make sure this component is visible */
345 if (!componentFits(co
, new)) {
346 gotoComponent(form
, -1);
349 /* make the new component the first one */
350 form
->vertOffset
= form
->elements
[new].top
- co
->top
;
352 /* make the new component the last one */
353 form
->vertOffset
= (form
->elements
[new].top
+
354 form
->elements
[new].co
->height
) -
355 (co
->top
+ co
->height
);
358 if (form
->vertOffset
< 0) form
->vertOffset
= 0;
359 if (form
->vertOffset
> (form
->numRows
- co
->height
))
360 form
->vertOffset
= form
->numRows
- co
->height
;
365 gotoComponent(form
, new);
366 er
.result
= ER_SWALLOWED
;
372 /* this also destroys all of the components on the form */
373 void newtFormDestroy(newtComponent co
) {
375 struct form
* form
= co
->data
;
378 /* first, destroy all of the components */
379 for (i
= 0; i
< form
->numComps
; i
++) {
380 subco
= form
->elements
[i
].co
;
381 if (subco
->ops
->destroy
) {
382 subco
->ops
->destroy(subco
);
384 if (subco
->data
) free(subco
->data
);
389 free(form
->elements
);
394 newtComponent
newtRunForm(newtComponent co
) {
395 struct newtExitStruct es
;
397 newtFormRun(co
, &es
);
398 if (es
.reason
== NEWT_EXIT_HOTKEY
) {
399 if (es
.u
.key
== NEWT_KEY_F12
) {
400 es
.reason
= NEWT_EXIT_COMPONENT
;
410 void newtFormAddHotKey(newtComponent co
, int key
) {
411 struct form
* form
= co
->data
;
414 form
->hotKeys
= realloc(form
->hotKeys
, sizeof(int) * form
->numHotKeys
);
415 form
->hotKeys
[form
->numHotKeys
- 1] = key
;
418 void newtFormRun(newtComponent co
, struct newtExitStruct
* es
) {
419 struct form
* form
= co
->data
;
421 struct eventResult er
;
425 /* first, draw all of the components */
428 if (form
->currComp
== -1) {
429 gotoComponent(form
, 0);
431 gotoComponent(form
, form
->currComp
);
437 if (key
== NEWT_KEY_RESIZE
) {
438 /* newtResizeScreen(1); */
442 for (i
= 0; i
< form
->numHotKeys
; i
++) {
443 if (form
->hotKeys
[i
] == key
) {
444 es
->reason
= NEWT_EXIT_HOTKEY
;
452 ev
.event
= EV_KEYPRESS
;
455 er
= sendEvent(co
, ev
);
457 if (er
.result
== ER_EXITFORM
) {
459 es
->reason
= NEWT_EXIT_COMPONENT
;
460 es
->u
.co
= form
->exitComp
;
468 static struct eventResult
sendEvent(newtComponent co
, struct event ev
) {
469 struct eventResult er
;
472 er
= co
->ops
->event(co
, ev
);
474 if (er
.result
== ER_IGNORED
) {
476 er
= co
->ops
->event(co
, ev
);
479 if (er
.result
== ER_IGNORED
) {
481 er
= co
->ops
->event(co
, ev
);
487 static void gotoComponent(struct form
* form
, int newComp
) {
490 if (form
->currComp
!= -1) {
491 ev
.event
= EV_UNFOCUS
;
492 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
495 form
->currComp
= newComp
;
497 if (form
->currComp
!= -1) {
500 sendEvent(form
->elements
[form
->currComp
].co
, ev
);
504 void newtComponentAddCallback(newtComponent co
, newtCallback f
, void * data
) {
506 co
->callbackData
= data
;
509 void newtComponentTakesFocus(newtComponent co
, int val
) {
510 co
->takesFocus
= val
;
513 void newtFormSetBackground(newtComponent co
, int color
) {
514 struct form
* form
= co
->data
;
516 form
->background
= color
;