Metatarget for copying of testfile fixed.
[AROS.git] / workbench / libs / gadtools / menus.c
blob469d868e23739e71ea732ae1f8c357fe5b073129
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: GadTools menu creation functions
6 Lang: English
7 */
9 /**************************************************************************************************/
11 #include <stdio.h>
12 #include <string.h>
14 #include <proto/exec.h>
15 #include <exec/types.h>
16 #include <exec/libraries.h>
17 #include <exec/memory.h>
18 #include <proto/intuition.h>
19 #include <proto/utility.h>
20 #include <intuition/intuition.h>
21 #include <intuition/classusr.h>
22 #include <intuition/imageclass.h>
23 #include <intuition/screens.h>
24 #include <intuition/icclass.h>
25 #include <proto/utility.h>
26 #include <utility/tagitem.h>
27 #include <libraries/gadtools.h>
29 #define SDEBUG 1
30 #define DEBUG 1
31 #include <aros/debug.h>
33 #include "gadtools_intern.h"
35 /**************************************************************************************************/
37 #define CHECKMARK_TEXT_SPACING 2
38 #define MENU_COLUMN_SPACING 8 /* when items must be arranged in 2 or more columns to fit on screen */
39 #define AMIGAKEY_KEY_SPACING 4 /* we guess that Intuition uses the same value */
40 #define TEXT_AMIGAKEY_SPACING 20
42 #define ITEXT_EXTRA_LEFT 2
43 #define ITEXT_EXTRA_RIGHT 2
44 #define ITEXT_EXTRA_TOP 1
45 #define ITEXT_EXTRA_BOTTOM 1
47 #define IMAGE_EXTRA_LEFT 1
48 #define IMAGE_EXTRA_RIGHT 1
49 #define IMAGE_EXTRA_TOP 1
50 #define IMAGE_EXTRA_BOTTOM 1
52 /**************************************************************************************************/
54 BOOL is_menubarlabelclass_image(struct Image *im, struct GadToolsBase_intern *GadToolsBase)
56 BOOL is_barlabel = FALSE;
58 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: im %p\n", im));
60 if (im)
62 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: depth %ld\n", im->Depth));
63 if (im->Depth == CUSTOMIMAGEDEPTH)
65 Class *cl;
67 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: boopsi\n"));
69 cl = OCLASS(im);
71 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: cl %p\n",cl));
73 if (cl)
75 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: ID %p\n",cl->cl_ID));
76 if (cl->cl_ID)
78 if (strcmp(cl->cl_ID, MENUBARLABELCLASS) == 0)
80 DEBUG_FREEMENUS(bug("is_menubarlabelclass_image: barlabel\n"));
81 is_barlabel = TRUE;
88 return is_barlabel;
91 /**************************************************************************************************/
93 void appendmenu(struct Menu * firstmenu,
94 struct Menu * lastmenu)
96 while (NULL != firstmenu->NextMenu)
97 firstmenu = firstmenu->NextMenu;
99 firstmenu->NextMenu = lastmenu;
102 /**************************************************************************************************/
104 void appenditem(struct Menu * curmenu,
105 struct MenuItem * item)
107 struct MenuItem * mi = curmenu->FirstItem;
109 if (NULL == mi)
110 curmenu->FirstItem = item;
111 else
113 while (NULL != mi->NextItem)
114 mi = mi->NextItem;
116 mi->NextItem = item;
120 /**************************************************************************************************/
122 void appendsubitem(struct MenuItem * curitem,
123 struct MenuItem * cursubitem)
125 struct MenuItem *mi = curitem->SubItem;
127 if (NULL == mi)
128 curitem->SubItem = cursubitem;
129 else
131 while (NULL != mi->NextItem)
132 mi = mi->NextItem;
134 mi->NextItem = cursubitem;
138 /**************************************************************************************************/
140 #if NEWMENUCODE
141 struct Menu * makemenutitle(struct NewMenu * newmenu,
142 UBYTE **MyMenuMemPtr,
143 struct TagItem * taglist)
145 struct Menu * menu = NULL;
146 ULONG * p;
148 p =(ULONG*) *MyMenuMemPtr;
149 memset(p,0,sizeof(ULONG)+sizeof(struct Menu)+sizeof(APTR));
150 *MyMenuMemPtr += sizeof(ULONG)+sizeof(struct Menu)+sizeof(APTR);
152 *p = 0;
153 menu = (struct Menu *)(p + 1);
154 menu->Flags = (newmenu->nm_Flags & NM_MENUDISABLED) ^ MENUENABLED;
155 menu->MenuName = (STRPTR)newmenu->nm_Label;
156 GTMENU_USERDATA(menu) = newmenu->nm_UserData;
158 return menu;
161 ULONG getmenutitlesize(struct NewMenu * newmenu,
162 struct TagItem * taglist)
164 return(sizeof(ULONG)+sizeof(struct Menu)+sizeof(APTR));
167 #else
168 struct Menu * makemenutitle(struct NewMenu * newmenu,
169 struct TagItem * taglist)
171 struct Menu * menu = NULL;
172 ULONG * p;
174 p = (ULONG *)AllocMem(sizeof(ULONG)+sizeof(struct Menu)+sizeof(APTR), MEMF_CLEAR);
176 if (NULL != p)
178 *p = 0;
179 menu = (struct Menu *)(p + 1);
180 menu->Flags = (newmenu->nm_Flags & NM_MENUDISABLED) ^ MENUENABLED;
181 menu->MenuName = newmenu->nm_Label;
182 GTMENU_USERDATA(menu) = newmenu->nm_UserData;
185 return menu;
187 #endif
189 /**************************************************************************************************/
190 #if NEWMENUCODE
191 struct MenuItem * makemenuitem(struct NewMenu * newmenu,
192 UBYTE **MyMenuMemPtr,
193 struct Image ***MyBarTablePtr,
194 BOOL is_image,
195 struct TagItem * taglist,
196 struct GadToolsBase_intern * GadToolsBase)
198 struct MenuItem * menuitem = NULL;
199 UWORD allocsize;
200 ULONG * p;
202 /* Note: 2 IntuiTexts must be alloced, because CreateMenusA can depend on it
203 if a subitem mark (">>") must be added */
205 if (newmenu->nm_Label == NM_BARLABEL) is_image = TRUE;
207 allocsize = sizeof(ULONG) + sizeof(struct MenuItem) + sizeof(APTR);
208 if (!is_image) allocsize += sizeof(struct IntuiText) * 2; /* for text + (commandstring OR ">>") */
210 p =(ULONG*) *MyMenuMemPtr;
211 memset(p,0,allocsize);
212 *MyMenuMemPtr += allocsize;
214 *p = allocsize;
215 menuitem = (struct MenuItem *)(p + 1);
217 DEBUG_ALLOCMENUS(bug("makemenuitem: MenuItem %p\n",menuitem));
218 menuitem->Flags = (newmenu->nm_Flags & (NM_ITEMDISABLED | CHECKIT | MENUTOGGLE | CHECKED)) ^
219 ITEMENABLED;
221 menuitem->Flags |= HIGHCOMP;
223 if (newmenu->nm_CommKey)
225 if (!(newmenu->nm_Flags & NM_COMMANDSTRING))
227 menuitem->Flags |= COMMSEQ;
228 menuitem->Command = newmenu->nm_CommKey[0];
232 menuitem->MutualExclude = newmenu->nm_MutualExclude;
233 GTMENUITEM_USERDATA(menuitem) = newmenu->nm_UserData;
235 if (FALSE == is_image)
238 ** Text
240 struct IntuiText * it = (struct IntuiText *)(((UBYTE *)menuitem) +
241 sizeof(struct MenuItem) +
242 sizeof(APTR));
244 DEBUG_ALLOCMENUS(bug("makemenuitem: Text MenuItem\n"));
245 menuitem->ItemFill = (APTR)it;
247 it->FrontPen = GetTagData(GTMN_FrontPen, 0, taglist);
248 it->DrawMode = JAM1;
250 it->IText = (STRPTR)newmenu->nm_Label;
251 DEBUG_ALLOCMENUS(bug("makemenuitem: FillName <%s>\n",it->IText));
253 menuitem->Flags |= ITEMTEXT;
255 if (newmenu->nm_CommKey && (newmenu->nm_Flags & NM_COMMANDSTRING))
257 struct IntuiText *it2 = it + 1;
259 *it2 = *it;
260 it2->IText = (STRPTR)newmenu->nm_CommKey;
261 it->NextText = it2;
264 } /* if (FALSE == is_image) */
265 else
267 DEBUG_ALLOCMENUS(bug("makemenuitem: Image MenuItem\n"));
268 menuitem->Flags &= ~ITEMTEXT;
270 if (newmenu->nm_Label != NM_BARLABEL)
273 ** An image.
275 menuitem->ItemFill = (APTR)newmenu->nm_Label;
276 DEBUG_ALLOCMENUS(bug("makemenuitem: FillImage 0x%lx\n",menuitem->ItemFill));
278 else
281 ** A barlabel image.
284 struct TagItem barlabel_tags[] =
286 {IA_Left , ITEXT_EXTRA_LEFT },
287 {IA_Top , 3 },
288 {IA_Width , 20 },
289 {IA_Height , 2 },
290 {TAG_DONE }
293 menuitem->Flags &= ~ITEMENABLED;
295 menuitem->ItemFill = NewObjectA(NULL, MENUBARLABELCLASS, barlabel_tags);
297 DEBUG_ALLOCMENUS(bug("makemenuitem: BarImage 0x%lx\n",menuitem->ItemFill));
299 if (!menuitem->ItemFill)
301 DEBUG_ALLOCMENUS(bug("makemenuitem: barimage failed\n"));
302 menuitem = NULL;
304 DEBUG_ALLOCMENUS(bug("makemenuitem: BarTablePtr 0x%lx\n",*MyBarTablePtr));
306 * Here we put the new Image to the array the BarTablePtr points to
307 * and then inc the BarTablePtr to the next empty Array slot
309 **MyBarTablePtr = menuitem->ItemFill;
311 * Attention..the () is *required*
313 (*MyBarTablePtr)++;
316 } /* is_image */
318 return menuitem;
321 ULONG getmenuitemsize(struct NewMenu * newmenu,
322 BOOL is_image,
323 struct TagItem * taglist,
324 struct GadToolsBase_intern * GadToolsBase)
326 ULONG allocsize;
328 if (newmenu->nm_Label == NM_BARLABEL) is_image = TRUE;
330 allocsize = sizeof(ULONG) + sizeof(struct MenuItem) + sizeof(APTR);
331 if (!is_image) allocsize += sizeof(struct IntuiText) * 2; /* for text + (commandstring OR ">>") */
333 DEBUG_ALLOCMENUS(bug("getmenuitemsize: allocsize %ld\n",allocsize));
334 return(allocsize);
337 #else
338 struct MenuItem * makemenuitem(struct NewMenu * newmenu,
339 BOOL is_image,
340 struct TagItem * taglist,
341 struct GadToolsBase_intern * GadToolsBase)
343 struct MenuItem * menuitem = NULL;
344 ULONG allocsize;
345 ULONG * p;
347 /* Note: 2 IntuiTexts must be alloced, because CreateMenusA can depend on it
348 if a subitem mark (">>") must be added */
350 if (newmenu->nm_Label == NM_BARLABEL) is_image = TRUE;
352 allocsize = sizeof(ULONG) + sizeof(struct MenuItem) + sizeof(APTR);
353 if (!is_image) allocsize += sizeof(struct IntuiText) * 2; /* for text + (commandstring OR ">>") */
355 p = (ULONG *)AllocMem(allocsize, MEMF_CLEAR);
357 if (NULL != p)
359 *p = allocsize;
360 menuitem = (struct MenuItem *)(p + 1);
362 DEBUG_ALLOCMENUS(bug("makemenuitem: MenuItem %p\n",menuitem));
363 menuitem->Flags = (newmenu->nm_Flags & (NM_ITEMDISABLED | CHECKIT | MENUTOGGLE | CHECKED)) ^
364 ITEMENABLED;
366 menuitem->Flags |= HIGHCOMP;
368 if (newmenu->nm_CommKey)
370 if (!(newmenu->nm_Flags & NM_COMMANDSTRING))
372 menuitem->Flags |= COMMSEQ;
373 menuitem->Command = newmenu->nm_CommKey[0];
377 menuitem->MutualExclude = newmenu->nm_MutualExclude;
378 GTMENUITEM_USERDATA(menuitem) = newmenu->nm_UserData;
380 if (FALSE == is_image)
383 ** Text
385 struct IntuiText * it = (struct IntuiText *)(((UBYTE *)menuitem) +
386 sizeof(struct MenuItem) +
387 sizeof(APTR));
389 DEBUG_ALLOCMENUS(bug("makemenuitem: Text MenuItem\n"));
390 menuitem->ItemFill = (APTR)it;
392 it->FrontPen = GetTagData(GTMN_FrontPen, 0, taglist);
393 it->DrawMode = JAM1;
395 it->IText = newmenu->nm_Label;
396 DEBUG_ALLOCMENUS(bug("makemenuitem: FillName <%s>\n",it->IText));
398 menuitem->Flags |= ITEMTEXT;
400 if (newmenu->nm_CommKey && (newmenu->nm_Flags & NM_COMMANDSTRING))
402 struct IntuiText *it2 = it + 1;
404 *it2 = *it;
405 it2->IText = newmenu->nm_CommKey;
406 it->NextText = it2;
409 } /* if (FALSE == is_image) */
410 else
412 DEBUG_ALLOCMENUS(bug("makemenuitem: Image MenuItem\n"));
413 menuitem->Flags &= ~ITEMTEXT;
415 if (newmenu->nm_Label != NM_BARLABEL)
418 ** An image.
420 menuitem->ItemFill = (APTR)newmenu->nm_Label;
421 DEBUG_ALLOCMENUS(bug("makemenuitem: FillImage 0x%lx\n",menuitem->ItemFill));
423 else
426 ** A barlabel image.
429 struct TagItem barlabel_tags[] =
431 {IA_Left , ITEXT_EXTRA_LEFT },
432 {IA_Top , 3 },
433 {IA_Width , 20 },
434 {IA_Height , 2 },
435 {TAG_DONE }
438 menuitem->Flags &= ~ITEMENABLED;
440 menuitem->ItemFill = NewObjectA(NULL, MENUBARLABELCLASS, barlabel_tags);
442 DEBUG_ALLOCMENUS(bug("makemenuitem: BarImage 0x%lx\n",menuitem->ItemFill));
444 if (!menuitem->ItemFill)
446 DEBUG_ALLOCMENUS(bug("makemenuitem: barimage failed\n"));
447 FreeVec(menuitem);
448 menuitem = NULL;
452 } /* is_image */
454 } /* if (NULL != menuitem) */
456 return menuitem;
458 #endif
460 /**************************************************************************************************/
462 #if !NEWMENUCODE
463 static void freeitem(struct MenuItem *item, struct GadToolsBase_intern * GadToolsBase)
465 ULONG * p = (ULONG *)item - 1;
467 DEBUG_FREEMENUS(bug("FreeItem: item %p\n", item));
469 DEBUG_FREEMENUS(bug("FreeItem: NextItem %p\n", item->NextItem));
470 DEBUG_FREEMENUS(bug("FreeItem: Left %ld Top %ld Width %ld Height %ld\n", item->LeftEdge,item->TopEdge,item->Width,item->Height));
471 DEBUG_FREEMENUS(bug("FreeItem: Flags 0x%lx ItemFill 0x%lx SelectFill 0x%lx\n", item->Flags,item->ItemFill,item->SelectFill));
472 DEBUG_FREEMENUS(bug("FreeItem: Command %lc SubItem 0x%lx NextSelect 0x%lx\n", item->Command,item->SubItem,item->NextSelect));
474 if (!(item->Flags & ITEMTEXT))
476 struct Image *im = (struct Image *)item->ItemFill;
478 DEBUG_FREEMENUS(bug("FreeItem: free image\n"));
479 if (is_menubarlabelclass_image(im, GadToolsBase))
481 DEBUG_FREEMENUS(bug("FreeItem: menubarimage %p\n",im));
482 DisposeObject(im);
485 else
487 struct IntuiText *MyText=(struct IntuiText*) item->ItemFill;
488 struct IntuiText *MyText2=(struct IntuiText*) item->SelectFill;
489 if (MyText)
491 DEBUG_FREEMENUS(bug("FreeItem: FillName <%s>\n",MyText->IText));
493 if (MyText2)
495 DEBUG_FREEMENUS(bug("FreeItem: SelectName <%s>\n",MyText2->IText));
499 DEBUG_FREEMENUS(bug("FreeItem: freeitem %p size %ld\n", p,*p));
501 FreeMem(p, *p);
502 DEBUG_FREEMENUS(bug("FreeItem: done\n"));
505 /**************************************************************************************************/
507 void freeitems(struct MenuItem * mi, struct GadToolsBase_intern * GadToolsBase)
509 DEBUG_FREEMENUS(bug("FreeItems: MenuItem %p\n",mi));
510 while (mi)
512 struct MenuItem * _mi = mi->NextItem, *si = mi->SubItem;
514 DEBUG_FREEMENUS(bug("FreeItems: CurrentItem %p NextItem %p\n",mi,_mi));
516 DEBUG_FREEMENUS(bug("FreeItems: free SubItems\n"));
517 while(si)
519 struct MenuItem * _si = si->NextItem;
521 DEBUG_FREEMENUS(bug("FreeItems: Current SubItem %p Next SubItem %p\n",si,_si));
523 freeitem(si, GadToolsBase);
524 si = _si;
527 DEBUG_FREEMENUS(bug("FreeItems: free MenuItem %p\n",mi));
529 freeitem(mi, GadToolsBase);
531 mi = _mi;
533 DEBUG_FREEMENUS(bug("FreeItems: done\n"));
535 #endif
536 /**************************************************************************************************/
538 static WORD MyIntuiTextLength(struct VisualInfo *vi, struct IntuiText *it,
539 struct GadToolsBase_intern * GadToolsBase)
541 WORD width;
543 if (it->ITextFont)
545 struct IntuiText *it_next = it->NextText;
547 it->NextText = NULL;
548 width = IntuiTextLength(it);
549 it->NextText = it_next;
552 else
554 width = TextLength(&vi->vi_screen->RastPort, it->IText, strlen(it->IText));
557 return width;
560 /**************************************************************************************************/
562 static ULONG EqualizeItems(struct MenuItem *firstitem, struct MenuItem *lastitem,
563 struct Image *amikeyimage, struct VisualInfo *vi,
564 struct GadToolsBase_intern * GadToolsBase)
566 struct MenuItem *item;
567 struct TextExtent te;
568 WORD minx = 0, maxwidth = 0, maxrightstuffwidth = 0;
570 if (!firstitem) return 0;
572 /* Calc. the max. width of item text/image (+ checkmark image)
573 Calc. the min. item->LeftEdge */
575 for(item = firstitem; item && (item != lastitem); item = item->NextItem)
577 if (item->LeftEdge < minx) minx = item->LeftEdge;
578 if (item->Width > maxwidth) maxwidth = item->Width;
581 /* Calc. the max. width of AmigaKey/CommandString/">>" */
583 FontExtent(vi->vi_dri->dri_Font, &te);
585 for(item = firstitem; item && (item != lastitem); item = item->NextItem)
587 WORD width = 0;
589 if (item->Flags & COMMSEQ)
591 width = te.te_Width;
593 if (item->Flags & ITEMTEXT)
595 struct TextFont *font;
596 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
598 if (it->ITextFont)
600 if ((font = OpenFont(it->ITextFont)))
602 struct TextExtent e;
604 FontExtent(font, &e);
606 width = e.te_Width;
607 CloseFont(font);
612 width += amikeyimage->Width +
613 AMIGAKEY_KEY_SPACING;
616 else if (item->Flags & ITEMTEXT)
618 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
619 struct IntuiText *it2;
621 if ((it2 = it->NextText))
623 it2->FrontPen = it->FrontPen;
624 it2->BackPen = it->BackPen;
625 it2->DrawMode = it->DrawMode;
626 it2->TopEdge = it->TopEdge;
628 /* save width also in it->LeftEdge. Will be used below to
629 calc. x position */
631 width = it2->LeftEdge = MyIntuiTextLength(vi, it2, GadToolsBase);
635 if (width > maxrightstuffwidth) maxrightstuffwidth = width;
637 } /* for(item = firstitem; item; item = item->NextItem) */
639 /* Calc. x coordinate of command strings and ">>"'s and submenu pos. */
641 if (maxrightstuffwidth)
643 maxwidth += maxrightstuffwidth + TEXT_AMIGAKEY_SPACING;
645 for(item = firstitem; item && (item != lastitem); item = item->NextItem)
647 struct MenuItem *subitem;
649 if (item->Flags & ITEMTEXT)
651 struct IntuiText *it = (struct IntuiText *)item->ItemFill;
653 if ((it = it->NextText))
655 /* it->LeftEdge contains the pixel width. see above */
657 it->LeftEdge = minx + maxwidth - it->LeftEdge - ITEXT_EXTRA_RIGHT;
661 for(subitem = item->SubItem; subitem; subitem = subitem->NextItem)
663 subitem->LeftEdge += (maxwidth - maxrightstuffwidth);
667 } /* if (maxrightstuffwidth) */
669 /* Make all items have the same width and set also the width and the
670 drawinfo of barlabel images */
672 for(item = firstitem; item && (item != lastitem); item = item->NextItem)
674 item->Width = maxwidth;
676 if(!(item->Flags & ITEMTEXT))
678 struct Image *im = (struct Image *)item->ItemFill;
680 if (is_menubarlabelclass_image(im, GadToolsBase))
682 struct TagItem image_tags [] =
684 {IA_Width , maxwidth - ITEXT_EXTRA_LEFT - ITEXT_EXTRA_RIGHT },
685 {SYSIA_DrawInfo , (IPTR)vi->vi_dri },
686 {TAG_DONE }
689 SetAttrsA(im, image_tags);
695 return (ULONG)maxwidth;
698 /**************************************************************************************************/
700 BOOL layoutmenuitems(struct MenuItem * firstitem,
701 struct VisualInfo * vi,
702 struct TagItem * taglist,
703 struct GadToolsBase_intern * GadToolsBase)
705 struct Menu * menu;
706 struct MenuItem * menuitem = firstitem;
707 struct MenuItem * equalizeitem = firstitem;
708 struct Image * amikeyimage, * chkimage;
709 struct TextExtent te;
710 ULONG curX = 0;
711 ULONG curY = 0;
712 WORD numcolumns = 1;
714 amikeyimage = (struct Image *)GetTagData(GTMN_AmigaKey, 0, taglist);
715 if (!amikeyimage) amikeyimage = vi->vi_dri->dri_AmigaKey;
717 chkimage = (struct Image *)GetTagData(GTMN_Checkmark, 0, taglist);
718 if (!chkimage) chkimage = vi->vi_dri->dri_CheckMark;
720 FontExtent(vi->vi_dri->dri_Font, &te);
722 while (NULL != menuitem)
724 ULONG addwidth = 0;
725 ULONG addleft = 0;
727 menuitem->LeftEdge = curX;
728 menuitem->TopEdge = curY;
730 if (0 != (menuitem->Flags & CHECKIT))
733 ** A checkmark will appear on the left.
736 addleft += chkimage->Width + CHECKMARK_TEXT_SPACING;
737 addwidth += chkimage->Width + CHECKMARK_TEXT_SPACING;
740 if (0 != (menuitem->Flags & ITEMTEXT))
743 ** Text
745 struct IntuiText * it = (struct IntuiText *)menuitem->ItemFill;
746 struct TagItem * ti;
748 if (NULL == it)
749 return FALSE;
751 if (NULL != (ti = FindTagItem(GTMN_FrontPen, taglist)))
753 it->FrontPen = ti->ti_Data;
755 else
757 it->FrontPen = vi->vi_dri->dri_Pens[BARDETAILPEN];
760 it->ITextFont = (struct TextAttr *)GetTagData(GTMN_TextAttr,
762 taglist);
764 it->LeftEdge = ITEXT_EXTRA_LEFT + addleft;
765 it->TopEdge = ITEXT_EXTRA_TOP;
767 menuitem->Width = MyIntuiTextLength(vi, it, GadToolsBase) +
768 addwidth + ITEXT_EXTRA_LEFT + ITEXT_EXTRA_RIGHT;
771 ** Calculate the height menu item.
773 if (NULL == it->ITextFont)
776 ** No font is provided, so I will work with the screen font.
778 menuitem->Height = vi->vi_dri->dri_Font->tf_YSize + ITEXT_EXTRA_TOP + ITEXT_EXTRA_BOTTOM;
780 else
782 struct TextFont * font;
784 if (NULL != (font = OpenFont(it->ITextFont)))
786 menuitem->Height = font->tf_YSize + ITEXT_EXTRA_TOP + ITEXT_EXTRA_BOTTOM;
787 CloseFont(font);
789 else
790 return FALSE;
793 } /* if (0 != (menuitem->Flags & ITEMTEXT)) */
794 else
797 ** Image
799 struct Image * im = (struct Image *)menuitem->ItemFill;
801 if (NULL == im) return FALSE;
803 if (is_menubarlabelclass_image(im, GadToolsBase))
805 menuitem->Width = 10;
806 menuitem->Height = 7;
809 else
812 menuitem->Width = im->Width + addwidth + IMAGE_EXTRA_LEFT + IMAGE_EXTRA_RIGHT;
813 menuitem->Height = im->Height + IMAGE_EXTRA_TOP + IMAGE_EXTRA_BOTTOM;
814 im->LeftEdge = IMAGE_EXTRA_LEFT + addleft;
815 im->TopEdge = IMAGE_EXTRA_TOP;
818 } /* if (0 != (menuitem->Flags & ITEMTEXT)) else ... */
820 curY += menuitem->Height;
823 ** In case this menu becomes too high it will have more columns.
826 if (curY > vi->vi_screen->Height)
828 ULONG width;
830 width = EqualizeItems(equalizeitem, menuitem, amikeyimage, vi, GadToolsBase);
831 equalizeitem = menuitem;
833 curY = 0;
834 curX += width + MENU_COLUMN_SPACING;
835 menuitem->LeftEdge = curX;
836 menuitem->TopEdge = curY;
838 curY += menuitem->Height;
840 numcolumns++;
844 ** Process the next menu item
846 menuitem = menuitem->NextItem;
848 } /* while (NULL != menuitem) */
850 EqualizeItems(equalizeitem, NULL, amikeyimage, vi, GadToolsBase);
852 menu = (struct Menu *)GetTagData(GTMN_Menu, 0, taglist);
853 if (menu && (menu->FirstItem == firstitem))
855 /* Make sure the menu box is at least as large as the menu title,
856 otherwise it looks ugly */
858 WORD menuwidth, minx, maxx, titlewidth, prevy = -1, col = 1;
860 minx = 32767;
861 maxx = -32768;
863 for(menuitem = firstitem; menuitem; menuitem = menuitem->NextItem)
865 if (menuitem->LeftEdge < minx) minx = menuitem->LeftEdge;
866 if (menuitem->LeftEdge + menuitem->Width - 1 > maxx) maxx = menuitem->LeftEdge + menuitem->Width - 1;
869 menuwidth = maxx - minx + 1;
870 titlewidth = TextLength(&vi->vi_screen->RastPort, menu->MenuName, strlen(menu->MenuName));
872 if (titlewidth > menuwidth)
874 WORD extrawidth = (titlewidth - menuwidth + numcolumns / 2) / numcolumns;
876 for(menuitem = firstitem; menuitem; menuitem = menuitem->NextItem)
878 struct MenuItem *subitem;
880 if (menuitem->TopEdge < prevy) col++;
881 prevy = menuitem->TopEdge;
883 menuitem->LeftEdge += (col - 1) * extrawidth;
884 menuitem->Width += extrawidth;
886 if (menuitem->Flags & ITEMTEXT)
888 struct IntuiText *it = (struct IntuiText *)menuitem->ItemFill;
890 if ((it = it->NextText))
892 it->LeftEdge += extrawidth;
895 else
897 struct Image *im = (struct Image *)menuitem->ItemFill;
899 if (is_menubarlabelclass_image(im, GadToolsBase))
901 im->Width += extrawidth;
905 if ((subitem = menuitem->SubItem))
907 while(subitem)
909 subitem->LeftEdge += extrawidth;
910 subitem = subitem->NextItem;
914 } /* for(menuitem = firstitem; menuitem; menuitem = menuitem->NextItem) */
916 } /* if (titlewidth > menuwidth) */
918 } /* if (menu && (menu->FirstItem == firstitem)) */
921 return TRUE;
924 /**************************************************************************************************/
926 BOOL layoutsubitems(struct MenuItem * motheritem,
927 struct VisualInfo * vi,
928 struct TagItem * taglist,
929 struct GadToolsBase_intern * GadToolsBase)
931 struct MenuItem * menuitem = motheritem->SubItem;
933 layoutmenuitems(menuitem, vi, taglist, GadToolsBase);
935 return TRUE;
938 /**************************************************************************************************/