home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
500-599
/
ff562.lza
/
Intuisup
/
Menus
/
source.lzh
/
menus.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-23
|
11KB
|
370 lines
/*************************************
* *
* 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);
}