home *** CD-ROM | disk | FTP | other *** search
- /*************************************
- * *
- * Menus v2.0 *
- * by Torsten Jürgeleit in 08/91 *
- * *
- * Routines *
- * *
- *************************************/
-
- /* Includes */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <functions.h>
- #include <string.h>
- #include "/render/render.h"
- #include "menus.h"
-
- /* Static prototypes */
-
- ULONG get_buffer_size(struct MenuList *ml);
- VOID get_item_text_pens(struct MenuList *ml);
- BOOL init_menu(struct MenuList *ml);
- VOID equal_select_box_width(struct MenuItem *item);
-
- /* Static pragmas */
-
- #pragma regcall(get_buffer_size(a0))
- #pragma regcall(get_item_text_pens(a0))
- #pragma regcall(init_menu(a0))
- #pragma regcall(equal_select_box_width(a0))
-
- /* Create menu list */
-
- struct MenuList *
- create_menu(struct RenderInfo *ri, struct Window *win,
- struct MenuData *md, struct TextAttr *ta)
- {
- struct MenuList *ml;
-
- if (ri && md) {
- if (ml = AllocMem((LONG)sizeof(struct MenuList), (LONG)MEMF_PUBLIC |
- MEMF_CLEAR)) {
- /* init menu list struct */
- ml->ml_RenderInfo = ri;
- ml->ml_Window = win; /* needed for colors !!! */
- ml->ml_Data = md;
- ml->ml_TextAttr = ta;
- ml->ml_Flags = 0;
- if (ta) {
- ml->ml_TextFont = OpenFont(ta);
- } else {
- ml->ml_TextFont = ri->ri_TextFont;
- }
- if (ml->ml_TextFont) {
- if (ml->ml_BufferSize = get_buffer_size(ml)) {
- if (ml->ml_Buffer = AllocMem(ml->ml_BufferSize, (LONG)
- MEMF_PUBLIC | MEMF_CLEAR)) {
- get_item_text_pens(ml);
- if (init_menu(ml) == TRUE) {
- return(ml);
- }
- FreeMem(ml->ml_Buffer, ml->ml_BufferSize);
- }
- }
- if (ta) {
- CloseFont(ml->ml_TextFont);
- }
- }
- FreeMem(ml, (LONG)sizeof(struct MenuList));
- }
- }
- return(NULL);
- }
- /* Attach menu list to given window */
-
- VOID
- attach_menu(struct Window *win, struct MenuList *ml)
- {
- if (win && ml) {
- /* remove menu strip from old window if any and attach it to new one */
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- ClearMenuStrip(ml->ml_Window);
- }
- SetMenuStrip(win, (struct Menu *)ml->ml_Buffer);
- ml->ml_Window = win;
- ml->ml_Flags |= MENU_LIST_FLAG_ATTACHED;
- }
- }
- /* Return menu item address */
-
- struct MenuItem *
- menu_item_address(struct MenuList *ml, USHORT menu_num)
- {
- return(ItemAddress((struct Menu *)ml->ml_Buffer, (LONG)menu_num));
- }
- /* Remove menu list from window currently attached to */
-
- VOID
- remove_menu(struct MenuList *ml)
- {
- if (ml) {
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- ClearMenuStrip(ml->ml_Window);
- ml->ml_Flags &= ~MENU_LIST_FLAG_ATTACHED;
- }
- }
- }
- /* Free menu */
-
- VOID
- free_menu(struct MenuList *ml)
- {
- if (ml) {
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- ClearMenuStrip(ml->ml_Window);
- }
- if (ml->ml_TextAttr) {
- CloseFont(ml->ml_TextFont);
- }
- FreeMem(ml->ml_Buffer, ml->ml_BufferSize);
- FreeMem(ml, (LONG)sizeof(struct MenuList));
- }
- }
- /* Get buffer size for menus, items and intui texts */
-
- STATIC ULONG
- get_buffer_size(struct MenuList *ml)
- {
- struct MenuData *md = ml->ml_Data;
- USHORT menus = 0, items = 0;
- ULONG buffer_size = 0;
-
- if (md->md_Type == MENU_DATA_TYPE_TITLE) {
- do {
- switch (md++->md_Type) {
- case MENU_DATA_TYPE_TITLE :
- menus++;
- break;
- case MENU_DATA_TYPE_ITEM :
- case MENU_DATA_TYPE_SUBITEM :
- items++;
- break;
- }
- } while (md->md_Type != INTUISUP_DATA_END &&
- md->md_Type <= MAX_MENU_DATA_TYPE);
- if (menus && items) {
- buffer_size = menus * sizeof(struct Menu) + items *
- (sizeof(struct MenuItem) + sizeof(struct IntuiText));
- }
- }
- return(buffer_size);
- }
- /* Get two different text pens for items */
-
- STATIC VOID
- get_item_text_pens(struct MenuList *ml)
- {
- struct RenderInfo *ri = ml->ml_RenderInfo;
- struct ColorMap *cmap;
- SHORT i, j, temp, num_colors, back_color, colors[MAX_RENDER_COLORS],
- pens[MAX_RENDER_COLORS];
-
- if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
- num_colors = MAX_RENDER_COLORS;
- }
- if (num_colors < 3) {
- /* set render pens for monochrome screen */
- if (ml->ml_Window->BlockPen) {
- ml->ml_TextPen1 = 0;
- ml->ml_TextPen2 = 0;
- } else {
- ml->ml_TextPen1 = 1;
- ml->ml_TextPen2 = 1;
- }
- } else {
- /* get current screen colors */
- Forbid();
- cmap = ml->ml_Window->WScreen->ViewPort.ColorMap;
- for (i = 0; i < num_colors; i++) {
- colors[i] = GetRGB4(cmap, (LONG)i);
- pens[i] = i;
- }
- Permit();
- /* save normal background color */
- back_color = colors[ml->ml_Window->BlockPen];
- /* set pen 1 */
- for (i = 0, j = 0; i < num_colors; i++) {
- if ((temp = calc_color_difference(colors[i], back_color)) > j) {
- j = temp;
- ml->ml_TextPen1 = pens[i];
- }
- }
- /* set text pen 2 */
- for (i = 0, j = 0; i < num_colors; i++) {
- if ((temp = calc_color_difference(colors[i], back_color)) > j &&
- pens[i] != ri->ri_TextPen1) {
- j = temp;
- ml->ml_TextPen2 = pens[i];
- }
- }
- }
- }
- /* Initialize menu from menu list */
-
- STATIC BOOL
- init_menu(struct MenuList *ml)
- {
- struct RenderInfo *ri = ml->ml_RenderInfo;
- struct MenuData *md;
- struct TextFont *menu_tf = ri->ri_TextFont, *item_tf = ml->ml_TextFont;
- struct Menu *last_menu, *menu = NULL;
- struct MenuItem *last_item, *last_subitem, *item = NULL;
- struct IntuiText *itext, *last_itext;
- SHORT item_ypos, subitem_xpos, subitem_ypos;
- BYTE *buffer = ml->ml_Buffer;
- USHORT type, flags;
- BOOL success = FALSE, error = FALSE, subitem_flag = FALSE;
-
- /* init menus and items */
- for (md = ml->ml_Data; md->md_Type != INTUISUP_DATA_END &&
- md->md_Type <= MAX_MENU_DATA_TYPE; md++) {
- type = md->md_Type;
- flags = md->md_Flags;
- switch (type) {
- case MENU_DATA_TYPE_TITLE :
- /* prepare last menu and subitem list */
- if (menu) {
- equal_select_box_width(menu->FirstItem);
- }
- if (subitem_flag == TRUE) {
- equal_select_box_width(last_item->SubItem);
- }
- /* init data for new menu */
- item = NULL;
- last_item = NULL;
- last_subitem = NULL;
- item_ypos = 0;
- subitem_flag = FALSE;
- last_menu = menu;
- menu = (struct Menu *)buffer;
- buffer += sizeof(struct Menu);
- /* init new menu */
- if (last_menu) {
- last_menu->NextMenu = menu;
- menu->LeftEdge = last_menu->LeftEdge + last_menu->Width
- + menu_tf->tf_XSize;
- } else {
- menu->LeftEdge = 5;
- }
- menu->Width = (strlen(md->md_Name) + 1) * menu_tf->tf_XSize;
- menu->Height = menu_tf->tf_YSize;
- menu->Flags = MIDRAWN | (flags & MENU_DATA_FLAG_DISABLED ?
- 0 : MENUENABLED);
- menu->MenuName = md->md_Name;
- menu->FirstItem = (struct MenuItem *)buffer;
- break;
- case MENU_DATA_TYPE_ITEM :
- case MENU_DATA_TYPE_SUBITEM :
- /* init item data */
- if (subitem_flag == TRUE) {
- last_subitem = item;
- } else {
- last_item = item;
- }
- item = (struct MenuItem *)buffer;
- itext = (struct IntuiText *)(item + 1);
- buffer += sizeof(struct MenuItem) + sizeof(struct IntuiText);
- /* init intui text */
- itext->LeftEdge = (flags & MENU_DATA_FLAG_ATTRIBUTE ?
- CHECKWIDTH : 0);
- itext->TopEdge = 1;
- itext->FrontPen = ml->ml_TextPen1;
- itext->DrawMode = JAM1;
- itext->ITextFont = ml->ml_TextAttr;
- itext->IText = (UBYTE *)md->md_Name;
- /* init menu item */
- item->Width = (strlen(md->md_Name) +
- (md->md_CommandKey ? 2 : 0)) * item_tf->tf_XSize +
- (md->md_CommandKey ? COMMWIDTH : 0) +
- (flags & MENU_DATA_FLAG_ATTRIBUTE ? CHECKWIDTH : 0);
- item->Height = item_tf->tf_YSize + 1;
- item->Flags = ITEMTEXT |
- (md->md_CommandKey ? COMMSEQ : 0) |
- (flags & MENU_DATA_FLAG_DISABLED ? 0 : ITEMENABLED) |
- (flags & MENU_DATA_FLAG_HIGH_NONE ? HIGHNONE :
- (flags & MENU_DATA_FLAG_HIGH_BOX ? HIGHBOX : HIGHCOMP)) |
- (flags & MENU_DATA_FLAG_ATTRIBUTE ? CHECKIT : 0) |
- (flags & MENU_DATA_FLAG_SELECTED ? CHECKED : 0);
- item->MutualExclude = md->md_MutualExclude;
- item->ItemFill = (APTR)itext;
- item->SelectFill = (APTR)itext;
- item->Command = *md->md_CommandKey;
- /* insert empty line before item ? */
- if (flags & MENU_DATA_FLAG_EMPTY_LINE) {
- if (type == MENU_DATA_TYPE_SUBITEM) {
- subitem_ypos += item->Height;
- } else {
- item_ypos += item->Height;
- }
- }
- if (type == MENU_DATA_TYPE_SUBITEM) {
- if (subitem_flag == TRUE) {
- last_subitem->NextItem = item;
- } else {
- if (!last_item) {
- error = TRUE; /* no menu item to attach subitem */
- break;
- } else {
- last_itext = (struct IntuiText *)
- last_item->ItemFill;
- last_itext->FrontPen = ml->ml_TextPen2;
- last_item->SubItem = item;
- subitem_xpos = strlen((BYTE *)last_itext->IText)
- * item_tf->tf_XSize + (last_item->Flags & CHECKIT ?
- CHECKWIDTH : 0);
- subitem_ypos = 0;
- subitem_flag = TRUE;
- }
- }
- item->LeftEdge = subitem_xpos;
- item->TopEdge = subitem_ypos;
- subitem_ypos += item->Height;
- } else {
- if (last_item) {
- last_item->NextItem = item;
- }
- item->TopEdge = item_ypos;
- item_ypos += item->Height;
- if (subitem_flag == TRUE) {
- /* prepare last subitem list */
- equal_select_box_width(last_item->SubItem);
- subitem_flag = FALSE;
- }
- }
- break;
- }
- if (error == FALSE && item) {
- /* prepare current menu and subitem list */
- equal_select_box_width(menu->FirstItem);
- if (subitem_flag == TRUE) {
- equal_select_box_width(last_item->SubItem);
- }
- success = TRUE;
- }
- }
- return(success);
- }
- /* Set equal select box width for given menu item list */
-
- STATIC VOID
- equal_select_box_width(struct MenuItem *item)
- {
- struct MenuItem *save_item = item;
- ULONG max_width = 0;
-
- /* search max width */
- do {
- if (item->Width > max_width) {
- max_width = item->Width;
- }
- } while (item = item->NextItem);
- /* set max width */
- item = save_item;
- do {
- item->Width = max_width;
- } while (item = item->NextItem);
- }
-