many bug fixes, finished some delegate code, updated menu file bug from EXEC
[wmaker-crm.git] / WINGs / wpopupbutton.c
blobd955523e23fa5a817138a9eee25a0e949cd7c296
5 #include "WINGsP.h"
7 typedef struct ItemList {
8 char *text;
9 struct ItemList *nextPtr;
10 unsigned int disabled:1;
11 } ItemList;
14 typedef struct W_PopUpButton {
15 W_Class widgetClass;
16 WMView *view;
18 void *clientData;
19 WMAction *action;
21 char *caption;
23 ItemList *items;
24 short itemCount;
26 short selectedItemIndex;
28 short highlightedItem;
30 ItemList *selectedItem; /* selected item if it is a menu btn */
32 WMView *menuView; /* override redirect popup menu */
34 WMHandlerID timer; /* for autoscroll */
36 /**/
37 int scrollStartY; /* for autoscroll */
39 struct {
40 unsigned int pullsDown:1;
42 unsigned int configured:1;
44 unsigned int insideMenu:1;
46 unsigned int enabled:1;
48 } flags;
49 } PopUpButton;
52 #define MENU_BLINK_DELAY 60000
53 #define MENU_BLINK_COUNT 2
55 #define SCROLL_DELAY 10
58 #define DEFAULT_WIDTH 60
59 #define DEFAULT_HEIGHT 20
60 #define DEFAULT_CAPTION ""
63 static void destroyPopUpButton(PopUpButton *bPtr);
64 static void paintPopUpButton(PopUpButton *bPtr);
66 static void handleEvents(XEvent *event, void *data);
67 static void handleActionEvents(XEvent *event, void *data);
69 static void resizeMenu(PopUpButton *bPtr);
72 WMPopUpButton*
73 WMCreatePopUpButton(WMWidget *parent)
75 PopUpButton *bPtr;
76 W_Screen *scr = W_VIEW(parent)->screen;
79 bPtr = wmalloc(sizeof(PopUpButton));
80 memset(bPtr, 0, sizeof(PopUpButton));
82 bPtr->widgetClass = WC_PopUpButton;
84 bPtr->view = W_CreateView(W_VIEW(parent));
85 if (!bPtr->view) {
86 free(bPtr);
87 return NULL;
89 bPtr->view->self = bPtr;
91 WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
92 |ClientMessageMask, handleEvents, bPtr);
95 W_ResizeView(bPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
96 bPtr->caption = wstrdup(DEFAULT_CAPTION);
98 WMCreateEventHandler(bPtr->view, ButtonPressMask|ButtonReleaseMask,
99 handleActionEvents, bPtr);
101 bPtr->flags.enabled = 1;
103 bPtr->menuView = W_CreateTopView(scr);
104 bPtr->menuView->attribs.override_redirect = True;
105 bPtr->menuView->attribFlags |= CWOverrideRedirect;
107 W_ResizeView(bPtr->menuView, bPtr->view->size.width, 1);
109 WMCreateEventHandler(bPtr->menuView, ButtonPressMask|ButtonReleaseMask
110 |EnterWindowMask|LeaveWindowMask|ButtonMotionMask
111 |ExposureMask, handleActionEvents, bPtr);
113 return bPtr;
117 void
118 WMSetPopUpButtonAction(WMPopUpButton *bPtr, WMAction *action, void *clientData)
120 CHECK_CLASS(bPtr, WC_PopUpButton);
122 bPtr->action = action;
124 bPtr->clientData = clientData;
128 void
129 WMAddPopUpButtonItem(WMPopUpButton *bPtr, char *title)
131 ItemList *itemPtr, *tmp;
133 CHECK_CLASS(bPtr, WC_PopUpButton);
135 itemPtr = wmalloc(sizeof(ItemList));
136 memset(itemPtr, 0, sizeof(ItemList));
137 itemPtr->text = wstrdup(title);
139 /* append item to list */
140 tmp = bPtr->items;
141 if (!tmp)
142 bPtr->items = itemPtr;
143 else {
144 while (tmp->nextPtr!=NULL)
145 tmp = tmp->nextPtr;
146 tmp->nextPtr = itemPtr;
149 bPtr->itemCount++;
151 if (bPtr->menuView && bPtr->menuView->flags.realized)
152 resizeMenu(bPtr);
156 void
157 WMInsertPopUpButtonItem(WMPopUpButton *bPtr, int index, char *title)
159 ItemList *itemPtr;
161 CHECK_CLASS(bPtr, WC_PopUpButton);
163 if (index < 0)
164 index = 0;
165 if (index >= bPtr->itemCount) {
166 WMAddPopUpButtonItem(bPtr, title);
167 return;
170 itemPtr = wmalloc(sizeof(ItemList));
171 memset(itemPtr, 0, sizeof(ItemList));
172 itemPtr->text = wstrdup(title);
174 if (index == 0) {
175 itemPtr->nextPtr = bPtr->items;
176 bPtr->items = itemPtr;
177 } else {
178 ItemList *tmp;
179 int i = index;
181 tmp = bPtr->items;
182 /* insert item in list */
183 while (--i > 0) {
184 tmp = tmp->nextPtr;
186 itemPtr->nextPtr = tmp->nextPtr;
187 tmp->nextPtr = itemPtr;
190 bPtr->itemCount++;
192 /* if there is an selected item, update it's index to match the new
193 * position */
194 if (index < bPtr->selectedItemIndex)
195 bPtr->selectedItemIndex++;
197 if (bPtr->menuView && bPtr->menuView->flags.realized)
198 resizeMenu(bPtr);
202 void
203 WMRemovePopUpButtonItem(WMPopUpButton *bPtr, int index)
205 ItemList *tmp;
207 CHECK_CLASS(bPtr, WC_PopUpButton);
209 if (index < 0 || index >= bPtr->itemCount)
210 return;
213 if (index == 0) {
214 free(bPtr->items->text);
215 tmp = bPtr->items->nextPtr;
216 free(bPtr->items);
217 bPtr->items = tmp;
218 } else {
219 ItemList *next;
220 int i = index;
222 tmp = bPtr->items;
223 while (--i > 0)
224 tmp = tmp->nextPtr;
225 next = tmp->nextPtr->nextPtr;
227 free(tmp->nextPtr->text);
228 free(tmp->nextPtr);
230 tmp->nextPtr = next;
233 bPtr->itemCount--;
235 if (bPtr->selectedItem!=NULL && !bPtr->flags.pullsDown) {
236 if (index < bPtr->selectedItemIndex)
237 bPtr->selectedItemIndex--;
238 else if (index == bPtr->selectedItemIndex) {
239 /* reselect first item if the removed item is the
240 * selected one */
241 bPtr->selectedItem = bPtr->items;
242 bPtr->selectedItemIndex = 0;
243 if (bPtr->view->flags.mapped)
244 paintPopUpButton(bPtr);
248 if (bPtr->menuView && bPtr->menuView->flags.realized)
249 resizeMenu(bPtr);
253 void
254 WMSetPopUpButtonEnabled(WMPopUpButton *bPtr, Bool flag)
256 bPtr->flags.enabled = flag;
257 if (bPtr->view->flags.mapped)
258 paintPopUpButton(bPtr);
262 Bool
263 WMGetPopUpButtonEnabled(WMPopUpButton *bPtr)
265 return bPtr->flags.enabled;
269 void
270 WMSetPopUpButtonSelectedItem(WMPopUpButton *bPtr, int index)
272 ItemList *itemPtr = bPtr->items;
273 int i = index;
275 if (index < 0) {
276 bPtr->selectedItem = NULL;
277 if (bPtr->view->flags.mapped)
278 paintPopUpButton(bPtr);
279 return;
282 while (i-- > 0) {
283 itemPtr = itemPtr->nextPtr;
285 bPtr->selectedItem = itemPtr;
286 bPtr->selectedItemIndex = index;
288 if (bPtr->view->flags.mapped)
289 paintPopUpButton(bPtr);
293 WMGetPopUpButtonSelectedItem(WMPopUpButton *bPtr)
295 if (!bPtr->flags.pullsDown && bPtr->selectedItem==NULL)
296 return -1;
297 else
298 return bPtr->selectedItemIndex;
302 void
303 WMSetPopUpButtonText(WMPopUpButton *bPtr, char *text)
305 if (bPtr->caption)
306 free(bPtr->caption);
307 if (text)
308 bPtr->caption = wstrdup(text);
309 else
310 bPtr->caption = NULL;
311 if (bPtr->view->flags.realized) {
312 if (bPtr->flags.pullsDown || bPtr->selectedItemIndex < 0) {
313 paintPopUpButton(bPtr);
320 void
321 WMSetPopUpButtonItemEnabled(WMPopUpButton *bPtr, int index, Bool flag)
323 int i;
324 ItemList *item = bPtr->items;
326 if (index < 0 || index >= bPtr->itemCount)
327 return;
329 for (i = 0; i<index; i++)
330 item=item->nextPtr;
332 item->disabled = !flag;
336 Bool
337 WMGetPopUpButtonItemEnabled(WMPopUpButton *bPtr, int index)
339 int i;
340 ItemList *item = bPtr->items;
342 if (index < 0 || index >= bPtr->itemCount)
343 return False;
345 for (i = 0; i<index; i++)
346 item=item->nextPtr;
348 return !item->disabled;
352 void
353 WMSetPopUpButtonPullsDown(WMPopUpButton *bPtr, Bool flag)
355 bPtr->flags.pullsDown = flag;
356 if (!flag) {
357 /* This code causes bugs. It should not select any item,
358 * since it was not asked to. -Dan
359 bPtr->selectedItem = bPtr->items;
360 if (bPtr->selectedItem)
361 bPtr->selectedItemIndex = 0;
362 else
363 bPtr->selectedItemIndex = -1;
365 bPtr->selectedItem = NULL;
366 /* the drawing routine, still draws things wrong if we put
367 * the index to -1 (i.e. not selected).
368 * Find out why. -Dan */
369 bPtr->selectedItemIndex = 0;
370 } else
371 bPtr->selectedItemIndex = -1;
373 if (bPtr->view->flags.mapped)
374 paintPopUpButton(bPtr);
379 WMGetPopUpButtonNumberOfItems(WMPopUpButton *bPtr)
381 return bPtr->itemCount;
385 char*
386 WMGetPopUpButtonItem(WMPopUpButton *bPtr, int index)
388 ItemList *itemPtr = bPtr->items;
390 if ((index < 0) || (index >= bPtr->itemCount))
391 return NULL;
393 while (index-->0)
394 itemPtr = itemPtr->nextPtr;
396 return itemPtr->text;
400 static void
401 paintPopUpButton(PopUpButton *bPtr)
403 W_Screen *scr = bPtr->view->screen;
404 char *caption;
405 Pixmap pixmap;
408 if (bPtr->flags.pullsDown) {
409 caption = bPtr->caption;
410 } else {
411 if (bPtr->selectedItem == NULL) {
412 /* if no item selected, show the caption */
413 caption = bPtr->caption;
414 } else {
415 caption = bPtr->selectedItem->text;
419 pixmap = XCreatePixmap(scr->display, bPtr->view->window,
420 bPtr->view->size.width, bPtr->view->size.height,
421 scr->depth);
422 XFillRectangle(scr->display, pixmap, WMColorGC(scr->gray), 0, 0,
423 bPtr->view->size.width, bPtr->view->size.height);
425 W_DrawRelief(scr, pixmap, 0, 0, bPtr->view->size.width,
426 bPtr->view->size.height, WRRaised);
428 if (caption) {
429 W_PaintText(bPtr->view, pixmap, scr->normalFont, 6,
430 (bPtr->view->size.height-WMFontHeight(scr->normalFont))/2,
431 bPtr->view->size.width, WALeft,
432 bPtr->flags.enabled ? WMColorGC(scr->black) : WMColorGC(scr->darkGray),
433 False, caption, strlen(caption));
436 if (bPtr->flags.pullsDown) {
437 XCopyArea(scr->display, scr->pullDownIndicator->pixmap,
438 pixmap, scr->copyGC, 0, 0, scr->pullDownIndicator->width,
439 scr->pullDownIndicator->height,
440 bPtr->view->size.width-scr->pullDownIndicator->width-4,
441 (bPtr->view->size.height-scr->pullDownIndicator->height)/2);
442 } else {
443 int x, y;
445 x = bPtr->view->size.width - scr->popUpIndicator->width - 4;
446 y = (bPtr->view->size.height-scr->popUpIndicator->height)/2;
448 XSetClipOrigin(scr->display, scr->clipGC, x, y);
449 XSetClipMask(scr->display, scr->clipGC, scr->popUpIndicator->mask);
450 XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
451 scr->clipGC, 0, 0, scr->popUpIndicator->width,
452 scr->popUpIndicator->height, x, y);
455 XCopyArea(scr->display, pixmap, bPtr->view->window, scr->copyGC, 0, 0,
456 bPtr->view->size.width, bPtr->view->size.height, 0, 0);
458 XFreePixmap(scr->display, pixmap);
463 static void
464 handleEvents(XEvent *event, void *data)
466 PopUpButton *bPtr = (PopUpButton*)data;
468 CHECK_CLASS(data, WC_PopUpButton);
471 switch (event->type) {
472 case Expose:
473 if (event->xexpose.count!=0)
474 break;
475 paintPopUpButton(bPtr);
476 break;
478 case DestroyNotify:
479 destroyPopUpButton(bPtr);
480 break;
486 static void
487 paintMenuEntry(PopUpButton *bPtr, int index, int highlight)
489 W_Screen *scr = bPtr->view->screen;
490 int i;
491 int yo;
492 ItemList *itemPtr;
493 int width, height, itemHeight;
495 itemHeight = bPtr->view->size.height;
496 width = bPtr->view->size.width;
497 height = itemHeight * bPtr->itemCount;
498 yo = (itemHeight - WMFontHeight(scr->normalFont))/2;
500 if (!highlight) {
501 XClearArea(scr->display, bPtr->menuView->window, 0, index*itemHeight,
502 width, itemHeight, False);
503 return;
504 } else if (index < 0 && bPtr->flags.pullsDown) {
505 return;
508 XFillRectangle(scr->display, bPtr->menuView->window, WMColorGC(scr->white),
509 1, index*itemHeight+1, width-3, itemHeight-3);
511 itemPtr = bPtr->items;
512 for (i = 0; i < index; i++)
513 itemPtr = itemPtr->nextPtr;
515 W_DrawRelief(scr, bPtr->menuView->window, 0, index*itemHeight,
516 width, itemHeight, WRRaised);
518 W_PaintText(bPtr->menuView, bPtr->menuView->window, scr->normalFont, 6,
519 index*itemHeight + yo, width, WALeft, WMColorGC(scr->black), False,
520 itemPtr->text, strlen(itemPtr->text));
522 if (!bPtr->flags.pullsDown && index == bPtr->selectedItemIndex) {
523 XCopyArea(scr->display, scr->popUpIndicator->pixmap,
524 bPtr->menuView->window, scr->copyGC, 0, 0,
525 scr->popUpIndicator->width, scr->popUpIndicator->height,
526 width-scr->popUpIndicator->width-4,
527 i*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
532 Pixmap
533 makeMenuPixmap(PopUpButton *bPtr)
535 Pixmap pixmap;
536 W_Screen *scr = bPtr->view->screen;
537 int i;
538 int yo;
539 ItemList *itemPtr;
540 int width, height, itemHeight;
542 itemHeight = bPtr->view->size.height;
543 width = bPtr->view->size.width;
544 height = itemHeight * bPtr->itemCount;
545 yo = (itemHeight - WMFontHeight(scr->normalFont))/2;
547 pixmap = XCreatePixmap(scr->display, bPtr->view->window, width, height,
548 scr->depth);
550 XFillRectangle(scr->display, pixmap, WMColorGC(scr->gray), 0, 0, width, height);
552 itemPtr = bPtr->items;
553 for (i = 0; i < bPtr->itemCount; i++) {
554 GC gc;
556 W_DrawRelief(scr, pixmap, 0, i*itemHeight, width, itemHeight,
557 WRRaised);
559 if (itemPtr->disabled)
560 gc = WMColorGC(scr->darkGray);
561 else
562 gc = WMColorGC(scr->black);
564 W_PaintText(bPtr->menuView, pixmap, scr->normalFont, 6,
565 i*itemHeight + yo, width, WALeft, gc, False,
566 itemPtr->text, strlen(itemPtr->text));
568 if (!bPtr->flags.pullsDown && i == bPtr->selectedItemIndex) {
569 XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
570 scr->copyGC, 0, 0, scr->popUpIndicator->width,
571 scr->popUpIndicator->height,
572 width-scr->popUpIndicator->width-4,
573 i*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
575 itemPtr = itemPtr->nextPtr;
578 return pixmap;
582 static void
583 resizeMenu(PopUpButton *bPtr)
585 int height;
587 height = bPtr->itemCount * bPtr->view->size.height;
588 if (height > 0)
589 W_ResizeView(bPtr->menuView, bPtr->view->size.width, height);
593 static void
594 popUpMenu(PopUpButton *bPtr)
596 W_Screen *scr = bPtr->view->screen;
597 Window dummyW;
598 int x, y;
600 if (!bPtr->menuView->flags.realized) {
601 W_RealizeView(bPtr->menuView);
602 resizeMenu(bPtr);
605 if (bPtr->itemCount < 1)
606 return;
608 XTranslateCoordinates(scr->display, bPtr->view->window, scr->rootWin,
609 0, 0, &x, &y, &dummyW);
611 if (bPtr->flags.pullsDown) {
612 y += bPtr->view->size.height;
613 } else {
614 y -= bPtr->view->size.height*bPtr->selectedItemIndex;
616 W_MoveView(bPtr->menuView, x, y);
618 XSetWindowBackgroundPixmap(scr->display, bPtr->menuView->window,
619 makeMenuPixmap(bPtr));
620 XClearWindow(scr->display, bPtr->menuView->window);
622 W_MapView(bPtr->menuView);
624 bPtr->highlightedItem = 0;
625 if (!bPtr->flags.pullsDown && bPtr->selectedItem != NULL)
626 paintMenuEntry(bPtr, bPtr->selectedItemIndex, True);
630 static void
631 popDownMenu(PopUpButton *bPtr)
633 W_UnmapView(bPtr->menuView);
635 /* free the background pixmap used to draw the menu contents */
636 XSetWindowBackgroundPixmap(bPtr->view->screen->display,
637 bPtr->menuView->window, None);
641 static int
642 itemIsEnabled(PopUpButton *bPtr, int index)
644 ItemList *item = bPtr->items;
646 while (index-- > 0 && item)
647 item = item->nextPtr;
649 return item ? !item->disabled : False;
653 static void
654 autoScroll(void *data)
656 PopUpButton *bPtr = (PopUpButton*)data;
657 int scrHeight = WMWidgetScreen(bPtr)->rootView->size.height;
658 int repeat = 0;
659 int dy = 0;
662 if (bPtr->scrollStartY >= scrHeight-1
663 && bPtr->menuView->pos.y+bPtr->menuView->size.height >= scrHeight-1) {
664 repeat = 1;
666 if (bPtr->menuView->pos.y+bPtr->menuView->size.height-5
667 <= scrHeight - 1) {
668 dy = scrHeight - 1
669 - (bPtr->menuView->pos.y+bPtr->menuView->size.height);
670 } else
671 dy = -5;
673 } else if (bPtr->scrollStartY <= 1 && bPtr->menuView->pos.y < 1) {
674 repeat = 1;
676 if (bPtr->menuView->pos.y+5 > 1)
677 dy = 1 - bPtr->menuView->pos.y;
678 else
679 dy = 5;
682 if (repeat) {
683 int oldItem;
685 W_MoveView(bPtr->menuView, bPtr->menuView->pos.x,
686 bPtr->menuView->pos.y + dy);
688 oldItem = bPtr->highlightedItem;
689 bPtr->highlightedItem = (bPtr->scrollStartY - bPtr->menuView->pos.y)
690 / bPtr->view->size.height;
692 if (oldItem!=bPtr->highlightedItem) {
693 paintMenuEntry(bPtr, oldItem, False);
694 paintMenuEntry(bPtr, bPtr->highlightedItem,
695 itemIsEnabled(bPtr, bPtr->highlightedItem));
698 bPtr->timer = WMAddTimerHandler(SCROLL_DELAY, autoScroll, bPtr);
699 } else {
700 bPtr->timer = NULL;
705 static void
706 handleActionEvents(XEvent *event, void *data)
708 PopUpButton *bPtr = (PopUpButton*)data;
709 int oldItem;
710 int scrHeight = WMWidgetScreen(bPtr)->rootView->size.height;
712 CHECK_CLASS(data, WC_PopUpButton);
714 if (bPtr->itemCount < 1)
715 return;
717 switch (event->type) {
718 /* called for menuView */
719 case Expose:
720 paintMenuEntry(bPtr, bPtr->highlightedItem,
721 itemIsEnabled(bPtr, bPtr->highlightedItem));
722 break;
724 case LeaveNotify:
725 bPtr->flags.insideMenu = 0;
726 if (bPtr->menuView->flags.mapped)
727 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
728 bPtr->highlightedItem = -1;
729 break;
731 case EnterNotify:
732 bPtr->flags.insideMenu = 1;
733 break;
735 case MotionNotify:
736 if (bPtr->flags.insideMenu) {
737 oldItem = bPtr->highlightedItem;
738 bPtr->highlightedItem = event->xmotion.y / bPtr->view->size.height;
739 if (oldItem!=bPtr->highlightedItem) {
740 paintMenuEntry(bPtr, oldItem, False);
741 paintMenuEntry(bPtr, bPtr->highlightedItem,
742 itemIsEnabled(bPtr, bPtr->highlightedItem));
745 if (event->xmotion.y_root >= scrHeight-1
746 || event->xmotion.y_root <= 1) {
747 bPtr->scrollStartY = event->xmotion.y_root;
748 if (!bPtr->timer)
749 autoScroll(bPtr);
750 } else if (bPtr->timer) {
751 WMDeleteTimerHandler(bPtr->timer);
752 bPtr->timer = NULL;
755 break;
757 /* called for bPtr->view */
758 case ButtonPress:
759 if (!bPtr->flags.enabled)
760 break;
762 popUpMenu(bPtr);
763 if (!bPtr->flags.pullsDown) {
764 bPtr->highlightedItem = bPtr->selectedItemIndex;
765 bPtr->flags.insideMenu = 1;
766 } else {
767 bPtr->highlightedItem = -1;
768 bPtr->flags.insideMenu = 0;
770 XGrabPointer(bPtr->view->screen->display, bPtr->menuView->window,
771 False, ButtonReleaseMask|ButtonMotionMask|EnterWindowMask
772 |LeaveWindowMask, GrabModeAsync, GrabModeAsync,
773 None, None, CurrentTime);
774 break;
776 case ButtonRelease:
777 XUngrabPointer(bPtr->view->screen->display, event->xbutton.time);
778 if (!bPtr->flags.pullsDown)
779 popDownMenu(bPtr);
781 if (bPtr->timer) {
782 WMDeleteTimerHandler(bPtr->timer);
783 bPtr->timer = NULL;
786 if (bPtr->flags.insideMenu && bPtr->highlightedItem>=0) {
787 if (itemIsEnabled(bPtr, bPtr->highlightedItem)) {
788 int i;
789 WMSetPopUpButtonSelectedItem(bPtr, bPtr->highlightedItem);
791 if (bPtr->flags.pullsDown) {
792 for (i=0; i<MENU_BLINK_COUNT; i++) {
793 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
794 XSync(bPtr->view->screen->display, 0);
795 wusleep(MENU_BLINK_DELAY);
796 paintMenuEntry(bPtr, bPtr->highlightedItem, True);
797 XSync(bPtr->view->screen->display, 0);
798 wusleep(MENU_BLINK_DELAY);
801 paintMenuEntry(bPtr, bPtr->highlightedItem, False);
802 popDownMenu(bPtr);
803 if (bPtr->action)
804 (*bPtr->action)(bPtr, bPtr->clientData);
807 if (bPtr->menuView->flags.mapped)
808 popDownMenu(bPtr);
809 break;
815 static void
816 destroyPopUpButton(PopUpButton *bPtr)
818 ItemList *itemPtr, *tmp;
820 if (bPtr->timer) {
821 WMDeleteTimerHandler(bPtr->timer);
824 itemPtr = bPtr->items;
825 while (itemPtr!=NULL) {
826 free(itemPtr->text);
827 tmp = itemPtr->nextPtr;
828 free(itemPtr);
829 itemPtr = tmp;
832 if (bPtr->caption)
833 free(bPtr->caption);
835 /* have to destroy explicitly because the popup is a toplevel */
836 W_DestroyView(bPtr->menuView);
838 free(bPtr);