1 /*
2 * wmslib/src/but/i_general.c, part of wmslib (Library functions)
3 * Copyright (C) 1994,1997 William Shubert.
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <configure.h>
8
9 #ifdef X11_DISP
10
11 #ifdef STDC_HEADERS
12 #include <stdlib.h>
13 #include <unistd.h>
14 #endif /* STDC_HEADERS */
15 #include <stdio.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xatom.h>
20 #include <X11/keysym.h>
21 #include <sys/time.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #include <wms.h>
26 #include <but/but.h>
27 #include <but/net.h>
28 #include <but/timer.h>
29 #include <but/canvas.h>
30
31
32 /**********************************************************************
33 * Forward Declarations
34 **********************************************************************/
35 static void mousein(ButWin *win, int x, int y, ButSet *butset);
36
37
38 /**********************************************************************
39 * Globals
40 **********************************************************************/
41 bool but_inEvent = FALSE;
42
43
44 /**********************************************************************
45 * Functions
46 **********************************************************************/
but_init(But * but)47 void but_init(But *but) {
48 ButWin *win = but->win;
49 ButEnv *env = win->env;
50 int nfl;
51
52 assert(MAGIC(win));
53 MAGIC_SET(but);
54 if (!(but->flags & BUT_DRAWABLE))
55 return;
56 if (win->maxLayer < win->minLayer)
57 win->maxLayer = win->minLayer = but->layer;
58 else {
59 if (but->layer < win->minLayer)
60 win->minLayer = but->layer;
61 if (but->layer > win->maxLayer)
62 win->maxLayer = but->layer;
63 }
64 butSet_addBut(&win->butsNoDraw, but);
65 if (but->w > 0)
66 but_addToTable(but);
67 if (but->flags & BUT_KEYED) {
68 if (win->keyBut != NULL) {
69 nfl = win->keyBut->flags & ~BUT_KEYED;
70 if (env->last_mwin == win)
71 nfl &= ~BUT_KEYACTIVE;
72 but_newFlags(win->keyBut, nfl);
73 }
74 win->keyBut = but;
75 if (env->last_mwin == win)
76 but->flags |= BUT_KEYACTIVE;
77 }
78 nfl = but->flags;
79 but->flags = BUT_DRAWABLE; /* Force a new flags type redraw. */
80 but_newFlags(but, nfl);
81 butWin_mMove(env->last_mwin, env->last_mx, env->last_my);
82 }
83
84
but_resize(But * but,int x,int y,int w,int h)85 void but_resize(But *but, int x, int y, int w, int h) {
86 int oldx = but->x, oldy = but->y, oldw = but->w, oldh = but->h;
87
88 assert(MAGIC(but));
89 if ((oldx == x) && (oldy == y) && (oldw == w) && (oldh == h))
90 return;
91 if ((w <= 0) || (h <= 0))
92 w = h = 0;
93 if ((oldw > 0) && (but->flags & BUT_DRAWABLE))
94 but_delFromTable(but);
95 but->x = x;
96 but->y = y;
97 but->w = w;
98 but->h = h;
99 if ((w > 0) && (but->flags & BUT_DRAWABLE))
100 but_addToTable(but);
101 if (but->action->resize) {
102 if (but->action->resize(but, oldx, oldy, oldw, oldh) &&
103 (but->flags & BUT_DRAWABLE)) {
104 butWin_redraw(but->win, oldx,oldy, oldw,oldh);
105 butWin_redraw(but->win, x,y, w,h);
106 }
107 } else if (but->flags & BUT_DRAWABLE) {
108 if ((oldw > 0) && (oldh > 0))
109 butWin_redraw(but->win, oldx,oldy, oldw,oldh);
110 butWin_redraw(but->win, x,y, w,h);
111 }
112 if (but->flags & BUT_DRAWABLE)
113 butWin_mMove(but->win->env->last_mwin,
114 but->win->env->last_mx, but->win->env->last_my);
115 }
116
117
but_destroy(But * but)118 void but_destroy(But *but) {
119 ButTimer *timer;
120
121 if (but != NULL) {
122 assert(MAGIC(but));
123 but_newFlags(but, 0);
124 for (timer = but_timerList; timer != NULL; timer = timer->next) {
125 if (timer->but == but) {
126 butTimer_destroy(timer);
127 break;
128 }
129 }
130 }
131 if (but_inEvent)
132 but_dList(but);
133 else
134 but_delete(but);
135 }
136
137
but_create(ButWin * win,void * iPacket,const ButAction * action)138 But *but_create(ButWin *win, void *iPacket, const ButAction *action) {
139 But *but;
140
141 but = (But *)wms_malloc(sizeof(But));
142 MAGIC_SET(but);
143 assert(win->parent || (win->win != None));
144 but->uPacket = NULL;
145 but->iPacket = iPacket;
146 but->win = win;
147 but->layer = 0;
148 but->x = 0;
149 but->y = 0;
150 but->w = 0;
151 but->h = 0;
152 but->id = -2;
153 but->flags = 0;
154 but->keys = NULL;
155 but->action = action;
156 but->destroyCallback = NULL;
157 return(but);
158 }
159
160
but_delete(But * but)161 ButOut but_delete(But *but) {
162 ButOut result = 0;
163 ButWin *win = but->win;
164 int x = but->x, y = but->y, w = but->w, h = but->h;
165
166 assert(but != NULL);
167 assert(MAGIC(win));
168 assert(MAGIC(but));
169 if (but->flags)
170 but_newFlags(but, 0);
171 if (but->destroyCallback)
172 but->destroyCallback(but);
173 if (but->action->destroy != NULL)
174 result = but->action->destroy(but);
175 MAGIC_UNSET(but);
176 wms_free(but);
177 butWin_redraw(win, x,y,w,h);
178 return(result);
179 }
180
181
but_setFlags(But * but,uint fch)182 void but_setFlags(But *but, uint fch) {
183 uint fl;
184
185 assert(MAGIC(but));
186 fl = but->flags | fch;
187 fl &= ~(fch >> BUT_MAXBITS);
188 but_newFlags(but, fl);
189 }
190
191
but_setKeys(But * but,const ButKey * keys)192 void but_setKeys(But *but, const ButKey *keys) {
193 assert(MAGIC(but));
194 assert((but->action->kPress) || (but->action->kRelease));
195 but->keys = keys;
196 }
197
198
but_newFlags(But * but,uint nfl)199 void but_newFlags(But *but, uint nfl) {
200 static bool inNewFlags = FALSE;
201 ButWin *win = but->win, *tmpWin, *ancestor;
202 ButEnv *env = win->env;
203 uint oldflags = but->flags;
204
205 assert(MAGIC(win));
206 assert(MAGIC(but));
207 for (ancestor = win; ancestor->parent; ancestor = ancestor->parent)
208 assert(MAGIC(ancestor));
209 if (!(nfl & BUT_PRESSABLE)) {
210 nfl &= ~(BUT_PRESSED|BUT_TWITCHED|BUT_LOCKED);
211 if (env->curhold == but)
212 butEnv_setCursor(env, but, butCur_idle);
213 }
214 if (!(oldflags & BUT_DRAWABLE) && (nfl & BUT_DRAWABLE)) {
215 but->flags = nfl;
216 but_init(but);
217 return;
218 }
219 if (!(nfl & BUT_DRAWABLE) && (env->butIn == but)) {
220 env->butIn = NULL;
221 for (tmpWin = win; tmpWin; tmpWin = tmpWin->parent) {
222 assert(MAGIC(tmpWin));
223 tmpWin->butIn = NULL;
224 }
225 }
226 if ((oldflags & BUT_KEYED) && !(nfl & BUT_KEYED)) {
227 nfl &= ~BUT_KEYACTIVE;
228 ancestor->keyBut = NULL;
229 }
230 if (!(oldflags & BUT_KEYED) && (nfl & BUT_KEYED)) {
231 if (ancestor->keyBut != NULL) {
232 but_newFlags(ancestor->keyBut, ancestor->keyBut->flags & ~BUT_KEYED);
233 }
234 ancestor->keyBut = but;
235 if (env->last_mwin == but->win) {
236 nfl |= BUT_KEYACTIVE;
237 }
238 }
239 if ((but->id != -2) && !inNewFlags &&
240 ((nfl & BUT_NETMASK) != (but->flags & BUT_NETMASK))) {
241 inNewFlags = TRUE;
242 butRnet_newFlags(env, but->id, nfl);
243 inNewFlags = FALSE;
244 }
245 if (!(oldflags & BUT_LOCKED) && (nfl & BUT_LOCKED)) {
246 if (env->lockBut != NULL)
247 but_newFlags(env->lockBut, env->lockBut->flags & ~BUT_LOCKED);
248 env->lockBut = but;
249 win->lock = but;
250 for (tmpWin = env->lockBut->win; tmpWin->parent;
251 tmpWin = tmpWin->parent) {
252 assert(MAGIC(tmpWin));
253 tmpWin->parent->lock = tmpWin->parentBut;
254 }
255 } else if ((oldflags & BUT_LOCKED) && !(nfl & BUT_LOCKED)) {
256 for (tmpWin = but->win; tmpWin; tmpWin = tmpWin->parent) {
257 assert(MAGIC(tmpWin));
258 tmpWin->lock = NULL;
259 }
260 env->lockBut = NULL;
261 }
262 if (nfl != oldflags) {
263 assert(but->action->newFlags);
264 but->action->newFlags(but, nfl);
265 }
266 if ((oldflags & BUT_DRAWABLE) && !(nfl & BUT_DRAWABLE)) {
267 if (but->w > 0) {
268 but_delFromTable(but);
269 }
270 }
271 butWin_mMove(env->last_mwin, env->last_mx, env->last_my);
272 }
273
274
but_draw(But * but)275 void but_draw(But *but) {
276 assert(MAGIC(but));
277 if ((but->flags & (BUT_DRAWABLE|BUT_DEAD)) == BUT_DRAWABLE)
278 butWin_redraw(but->win, but->x,but->y, but->w,but->h);
279 }
280
281
butWin_mMove(ButWin * win,int x,int y)282 ButOut butWin_mMove(ButWin *win, int x, int y) {
283 ButEnv *env;
284 ButOut result = 0;
285 int i;
286 But *but, *oldbut;
287 ButSet butset;
288 ButWin *tmpWin;
289
290 assert(MAGICNULL(win));
291 if (win == NULL)
292 return(0);
293 env = win->env;
294 if ((env->last_mwin != win) &&
295 (!env->last_mwin || (env->last_mwin->physWin != win->physWin))) {
296 env->curwin = win->physWin;
297 env->curlast = butCur_bogus;
298 }
299 if (win->parent == NULL) {
300 /* Only do this if you're on a real window, that is, not in a canvas. */
301 env->last_mwin = win;
302 env->last_mx = x;
303 env->last_my = y;
304 }
305 mousein(win, x, y, &butset);
306 for (i = butset.numButs - 1; i >= 0; --i) {
307 but = butset.buts[i];
308 assert(MAGIC(but));
309 if ((but->flags & BUT_DRAWABLE) && !(but->flags & BUT_PRESSTHRU)) {
310 if (but->action->mMove == NULL)
311 result |= BUTOUT_CAUGHT;
312 else
313 result |= but->action->mMove(but, x,y);
314 if (result & BUTOUT_CAUGHT) {
315 if (result & BUTOUT_IGNORE)
316 return(result);
317 if (env->butIn != but) {
318 if (env->butIn != NULL) {
319 for (tmpWin = env->butIn->win; tmpWin;
320 tmpWin = tmpWin->parent) {
321 tmpWin->butIn = NULL;
322 }
323 if ((env->butIn->flags & BUT_PRESSABLE) &&
324 (env->butIn->action->mLeave != NULL))
325 result |= env->butIn->action->mLeave(env->butIn);
326 }
327 env->butIn = but;
328 but->win->butIn = but;
329 for (tmpWin = but->win; tmpWin->parent; tmpWin = tmpWin->parent) {
330 tmpWin->parent->butIn = tmpWin->parentBut;
331 }
332 }
333 return(result);
334 }
335 }
336 }
337 if (env->butIn != NULL) {
338 oldbut = env->butIn;
339 for (tmpWin = env->butIn->win; tmpWin; tmpWin = tmpWin->parent) {
340 tmpWin->butIn = NULL;
341 }
342 env->butIn = NULL;
343 if ((oldbut->flags & BUT_PRESSABLE) && (oldbut->action->mLeave != NULL))
344 result |= oldbut->action->mLeave(oldbut);
345 }
346 return(result);
347 }
348
349
butWin_mPress(ButWin * win,int x,int y,int butnum)350 ButOut butWin_mPress(ButWin *win, int x, int y, int butnum) {
351 ButOut result;
352 But *but;
353
354 assert(MAGIC(win));
355 result = butWin_mMove(win, x, y);
356 but = win->butIn;
357 if (but != NULL) {
358 assert(MAGIC(but));
359 if ((but->flags & BUT_PRESSABLE) && (but->action->mPress != NULL)) {
360 return(result | but->action->mPress(but, butnum, x, y));
361 }
362 }
363 return(result | BUTOUT_ERR);
364 }
365
366
butWin_mRelease(ButWin * win,int x,int y,int butnum)367 ButOut butWin_mRelease(ButWin *win, int x, int y, int butnum) {
368 ButOut result;
369 But *but;
370
371 assert(MAGIC(win));
372 result = butWin_mMove(win, x, y);
373 but = win->butIn;
374 if (but != NULL) {
375 assert(MAGIC(but));
376 if ((but->flags & BUT_PRESSABLE) && (but->action->mRelease != NULL))
377 return(result | but->action->mRelease(but, butnum, x, y));
378 }
379 return(result);
380 }
381
382
keycheck(But * but,void * packet)383 static int keycheck(But *but, void *packet) {
384 int keycount;
385 KeySym sym = *(KeySym *)packet;
386
387 assert(MAGIC(but));
388 if (but->keys != NULL) {
389 for (keycount = 0; but->keys[keycount].key != 0; ++keycount) {
390 if ((but->keys[keycount].key == sym) &&
391 ((but->win->env->keyModifiers & but->keys[keycount].modMask) ==
392 but->keys[keycount].modifiers))
393 return(1);
394 }
395 }
396 return(0);
397 }
398
399
butWin_kPress(ButWin * win,const char * keystr,KeySym sym)400 ButOut butWin_kPress(ButWin *win, const char *keystr, KeySym sym) {
401 ButOut retVal = 0;
402 But *but;
403
404 assert(MAGIC(win));
405 /*
406 * The keybut _always_ get a shot at the key when it is pressed.
407 */
408 if (win->keyBut) {
409 assert(win->keyBut->flags & BUT_PRESSABLE);
410 retVal |= win->keyBut->action->kPress(win->keyBut, keystr, sym);
411 }
412 if (!(retVal & BUTOUT_CAUGHT)) {
413 but = butWin_findButsInRegion(win, 0,0, win->w,win->h, keycheck, &sym);
414 if ((but != NULL) && (but->flags & BUT_PRESSABLE) &&
415 (but->action->kPress != NULL)) {
416 assert(MAGIC(but));
417 retVal |= but->action->kPress(but, keystr, sym);
418 } else {
419 /*
420 * A key was pressed that nobody wanted.
421 * But only signal an error if it was a "real" key...don't beep when
422 * some poor guy presses shift!
423 */
424 if (!IsModifierKey(sym))
425 retVal |= BUTOUT_ERR;
426 }
427 }
428 return(retVal);
429 }
430
431
butWin_kRelease(ButWin * win,const char * keystr,KeySym sym)432 ButOut butWin_kRelease(ButWin *win, const char *keystr, KeySym sym) {
433 ButOut retval = 0;
434 But *but;
435
436 assert(MAGIC(win));
437 but = butWin_findButsInRegion(win, 0,0, win->w,win->h, keycheck, &sym);
438 if (but != NULL) {
439 assert(MAGIC(but));
440 if ((but->flags & BUT_PRESSABLE) && (but->action->kRelease != NULL))
441 retval |= but->action->kRelease(but, keystr, sym);
442 }
443 return(retval);
444 }
445
446
447 /* mousein(win, x, y, reason) will return the button number that the mouse is
448 * presently inside of. If the mouse is not in any button NULL will
449 * be returned.
450 * The checkfunc will be called only if the mouse is already inside the
451 * (x,y,w,h) boundaries of the button. "reason" is one of BUT_RE_PRESS,
452 * BUT_RE_RELEASE, or BUT_RE_MOVE, depending on the reason for the button
453 * to be checked.
454 * Non-pressable buttons will never be returned.
455 *
456 * NOTE: This does a linear search through the buttons. YUCK! SLOW! I'd
457 * like to recode this to do a three-dimensional binary search (the
458 * dimensions being window, x, and y) but that would take some seriously
459 * heavy-duty coding and I have a million other things to do first.
460 *
461 * NOTE to note: I finally did the 3d binary search. Works great!
462 */
mousein(ButWin * win,int x,int y,ButSet * butset)463 static void mousein(ButWin *win, int x, int y, ButSet *butset) {
464 static But *but;
465
466 assert(MAGIC(win));
467 if (win->lock) {
468 butset->dynamic = FALSE;
469 butset->numButs = 1;
470 butset->buts = &but;
471 but = win->lock;
472 } else
473 butWin_findButSet(win, x, y, butset);
474 }
475
476
but_compare(const void * a,const void * b)477 static int but_compare(const void *a, const void *b) {
478 But **but_a = (But **)a, **but_b = (But **)b;
479
480 assert(MAGIC(*but_a));
481 assert(MAGIC(*but_b));
482 return((*but_a)->layer - (*but_b)->layer);
483 }
484
485
butWin_redraw(ButWin * win,int x,int y,int w,int h)486 void butWin_redraw(ButWin *win, int x, int y, int w, int h) {
487 ButWinArea *newAreas;
488 int newMaxRedraws, i;
489 bool change;
490
491 assert((x > -1000) && (y > -1000));
492 if (!w || !h)
493 return;
494 assert(w > 0);
495 assert(h > 0);
496 if (win->numRedraws + 1 >= win->maxRedraws) {
497 newMaxRedraws = (win->maxRedraws + 1) * 2;
498 newAreas = wms_malloc(newMaxRedraws * sizeof(ButWinArea));
499 for (i = 0; i < win->numRedraws; ++i) {
500 newAreas[i] = win->redraws[i];
501 }
502 if (win->redraws)
503 wms_free(win->redraws);
504 win->redraws = newAreas;
505 win->maxRedraws = newMaxRedraws;
506 }
507 assert(win->numRedraws < win->maxRedraws);
508 do {
509 assert(w > 0);
510 assert(h > 0);
511 change = FALSE;
512 for (i = 0; i < win->numRedraws; ++i) {
513 if ((x <= win->redraws[i].x + win->redraws[i].w) &&
514 (y <= win->redraws[i].y + win->redraws[i].h) &&
515 (x + w >= win->redraws[i].x) &&
516 (y + h >= win->redraws[i].y)) {
517 change = TRUE;
518 if (win->redraws[i].x < x) {
519 w += x - win->redraws[i].x;
520 x = win->redraws[i].x;
521 }
522 if (win->redraws[i].y < y) {
523 h += y - win->redraws[i].y;
524 y = win->redraws[i].y;
525 }
526 if (x + w < win->redraws[i].x + win->redraws[i].w)
527 w = win->redraws[i].x + win->redraws[i].w - x;
528 if (y + h < win->redraws[i].y + win->redraws[i].h)
529 h = win->redraws[i].y + win->redraws[i].h - y;
530 win->redraws[i] = win->redraws[--win->numRedraws];
531 }
532 }
533 } while (change);
534 win->redraws[win->numRedraws].x = x;
535 win->redraws[win->numRedraws].y = y;
536 win->redraws[win->numRedraws].w = w;
537 win->redraws[win->numRedraws].h = h;
538 assert(w > 0);
539 assert(h > 0);
540 ++win->numRedraws;
541 assert(win->numRedraws < win->maxRedraws);
542 }
543
544
butWin_performDraws(ButWin * win)545 void butWin_performDraws(ButWin *win) {
546 int drawNum;
547 int i, drx,dry, drw,drh, x, y, w, h;
548 ButEnv *env = win->env;
549 XRectangle cliprect;
550 ButSet butset;
551 But *but;
552
553 assert(MAGIC(win));
554 if (!win->mapped) {
555 win->numRedraws = 0;
556 return;
557 }
558 for (drawNum = 0; drawNum < win->numRedraws; ++drawNum) {
559 x = win->redraws[drawNum].x;
560 y = win->redraws[drawNum].y;
561 w = win->redraws[drawNum].w;
562 h = win->redraws[drawNum].h;
563 assert(w > 0);
564 assert(h > 0);
565 if (x < win->xOff) {
566 w -= win->xOff - x;
567 x = win->xOff;
568 }
569 if (x + w > win->xOff + win->w)
570 w = win->xOff + win->w - x;
571 if (y < win->yOff) {
572 h -= win->yOff - y;
573 y = win->yOff;
574 }
575 if (y + h > win->yOff + win->h)
576 h = win->yOff + win->h - y;
577 if ((w <= 0) || (h <= 0))
578 continue;
579 if (win->id != -2)
580 butRcur_redraw(env, win->id, x,y,w,h);
581 butWin_findButSetInRegion(win, x,y, w,h, &butset);
582 if (butset.numButs > 0) {
583 cliprect.x = x - win->xOff;
584 cliprect.y = y - win->yOff;
585 cliprect.width = w;
586 cliprect.height = h;
587 XSetClipRectangles(env->dpy, env->gc, 0,0, &cliprect, 1, YXSorted);
588 qsort(butset.buts, butset.numButs, sizeof(But *), but_compare);
589 assert(MAGIC(win));
590 for (i = butset.numButs - 1; i > 0; --i) {
591 but = butset.buts[i];
592 assert(MAGIC(but));
593 if ((but->flags & BUT_OPAQUE) && (but->x <= x) && (but->y <= y) &&
594 (but->x + but->w >= x + w) && (but->y + but->h >= y + h))
595 break;
596 }
597 for (; i < butset.numButs; ++i) {
598 but = butset.buts[i];
599 assert(MAGIC(but));
600 if (!(but->flags & BUT_DEAD)) {
601 if (but->x < x)
602 drx = x;
603 else
604 drx = but->x;
605 if (but->y < y)
606 dry = y;
607 else
608 dry = but->y;
609 if (but->x + but->w < x+w)
610 drw = but->x + but->w - drx;
611 else
612 drw = x + w - drx;
613 if (but->y + but->h < y+h)
614 drh = but->y + but->h - dry;
615 else
616 drh = y+h - dry;
617 but->action->draw(but, x,y, w,h);
618 }
619 }
620 XSetClipMask(env->dpy, env->gc, None);
621 butSet_destroy(&butset);
622 if (win->parent) {
623 /*
624 * It's a canvas. Fire off a redraw request so that the changes to
625 * the canvas pixmap will be seen on the screen.
626 */
627 butCan_redrawn(win, x, y, w, h);
628 }
629 }
630 }
631 win->numRedraws = 0;
632 }
633
634
butSet_destroy(ButSet * butset)635 void butSet_destroy(ButSet *butset) {
636 if (butset->dynamic && (butset->buts != NULL))
637 wms_free(butset->buts);
638 }
639
640
641 /* If win is NULL it will execute all destroy commands built up. */
butWin_dList(ButWin * win)642 ButOut butWin_dList(ButWin *win) {
643 static ButWin **dlist = NULL;
644 static int dlist_len = 0, max_dlist_len = 0;
645 ButWin **new_dlist;
646 int i;
647 ButOut result = 0;
648
649 assert(MAGICNULL(win));
650 if (win == NULL) {
651 /*
652 * It is really important that we start at the end here. Since our
653 * child windows are added to the _end_ of the dlist, and they _must_
654 * be destroyed first, we have to go backwards.
655 */
656 while (dlist_len) {
657 i = dlist_len - 1;
658 if (dlist[i] != NULL) {
659 assert(MAGIC(dlist[i]));
660 result |= butWin_delete(dlist[i]) | BUTOUT_CAUGHT;
661 if (result & BUTOUT_STILLBUTS) {
662 /* Window still has buttons...can't kill it yet! */
663 return(result & ~BUTOUT_STILLBUTS);
664 }
665 dlist[i] = NULL;
666 }
667 --dlist_len;
668 }
669 } else {
670 if (win->iconWin != NULL) {
671 butWin_dList(win->iconWin);
672 win->iconWin = NULL;
673 }
674 if (dlist_len+1 > max_dlist_len) {
675 new_dlist = wms_malloc(sizeof(ButWin *) * (dlist_len * 2 + 2));
676 for (i = 0; i < dlist_len; ++i)
677 new_dlist[i] = dlist[i];
678 if (dlist != NULL)
679 wms_free(dlist);
680 dlist = new_dlist;
681 max_dlist_len = (dlist_len * 2 + 2);
682 }
683 for (i = 0; i < dlist_len; ++i)
684 if (dlist[i] == win)
685 return(result);
686 dlist[dlist_len++] = win;
687 }
688 return(result);
689 }
690
691
692 /* If but is NULL it will execute all destroy commands built up. */
but_dList(But * but)693 ButOut but_dList(But *but) {
694 static But **dlist = NULL;
695 static int dlist_len = 0, max_dlist_len = 0;
696 But **new_dlist;
697 int i;
698 ButOut result = 0;
699
700 if (but == NULL) {
701 if (dlist_len == 0)
702 return(0);
703 for (i = 0; i < dlist_len; ++i) {
704 result |= but_delete(dlist[i]) | BUTOUT_CAUGHT;
705 }
706 dlist_len = 0;
707 } else {
708 if (dlist_len+1 > max_dlist_len) {
709 new_dlist = wms_malloc(sizeof(But *) * (dlist_len * 2 + 2));
710 for (i = 0; i < dlist_len; ++i)
711 new_dlist[i] = dlist[i];
712 if (dlist != NULL)
713 wms_free(dlist);
714 dlist = new_dlist;
715 max_dlist_len = (dlist_len * 2 + 2);
716 }
717 for (i = 0; i < dlist_len; ++i)
718 if (dlist[i] == but)
719 return(result);
720 but_newFlags(but, 0);
721 dlist[dlist_len++] = but;
722 but->flags |= BUT_DEAD;
723 }
724 return(result);
725 }
726
727
but_flags(But * but,uint flags)728 void but_flags(But *but, uint flags) {
729 but->flags = flags;
730 but_draw(but);
731 }
732
733
734 #endif /* X11_DISP */
735