home *** CD-ROM | disk | FTP | other *** search
- /*
- menu.c
-
- menu manager routines and variables
- */
-
- #include "usrif.h"
- #undef NULL
- #include "stdio.h"
-
- /* global variables */
- extern rect_t screen;
- extern vport_t *the_port;
- extern point_t cursor;
-
- /* menu border in pixels */
- #define BDR 3
-
- /* menu text height in pixels */
- #define TH 12
-
- int pop_up_menu( num_items, items)
- int num_items;
- char *items[];
- {
- char *look, *animate_seg();
- text_t *t[MAX_MENUS];
- rect_t area, bmap;
- rect_t *bbox, *text_bbox();
- int i, h, w, mw = 0, x, y;
- seg_t *menu;
- key_t *key;
- void save_bitmap(), restore_bitmap();
-
- /* determine maximum item width */
- for(i = 0; i < num_items; i++)
- {
- bbox = text_bbox(items[i], LEFT, BOTTOM);
- w = bbox->right - bbox->left;
- free(bbox);
-
- if(w > mw)
- mw = w;
- }
-
- /* determine size of menu */
- h = (TH + 2 * BDR) * num_items + 2;
- w = mw + 2 * BDR;
-
- /* determine location of menu */
- x = cursor.x; y = cursor.y;
-
- /* greater than left edge of screen? */
- if(x > (w / 2 + BDR))
- x -= w / 2;
- else
- x = w / 2 + BDR;
-
- /* less than right edge of screen? */
- if( (x + w) > screen.right)
- x -= w + BDR;
- else
- x = screen.right - w - BDR;
-
- /* greater than bottom edge of screen? */
- if(y > (h / 2 + BDR))
- y -= h / 2;
- else
- y = h / 2 + BDR;
-
- /* less than top edge of screen? */
- if( (y + h) > screen.top)
- y -= h + BDR;
- else
- y = screen.top - h - BDR;
-
-
- set_rect(&area, x, y, x + w, y + h);
- set_rect(&bmap, x - 1, y - 1, x + w + 1, y + h + 1);
-
- cr_seg("menu");
- add_attr(RESET);
- add_attr(FILL);
- add_rect(copy_rect(&area));
-
- add_attr(NOFILL);
- add_attr(BLACK);
- add_rect(copy_rect(&area));
-
- for(i = 0; i < num_items; i++)
- {
- t[i] = inst_text(items[i],
- x + 2 + w / 2, y + 2 * BDR + i * (TH + 2 * BDR),
- MIDDLE, BOTTOM);
-
- /*
- If you want menu items left-justified,
- use this text command:
-
- t[i] = inst_text(items[i],
- x + 2 * BDR, y + 2 * BDR + i * (TH + 2 * BDR),
- LEFT, BOTTOM);
- */
-
- add_text(t[i]);
- }
-
- menu = cl_seg();
-
- /* save bit-map region where menu goes */
- save_bitmap(&bmap);
-
- /* draw menu in bit map */
- hide_cursor();
- draw_seg(menu, the_port);
-
- /* re-adjust text bboxs to world space */
- for(i = 0; i < num_items; i++)
- {
- set_rect(t[i]->bbox,
- x + 1, y + i * (TH + 2 * BDR) + 1,
- x - 3 + w, y + (i + 1) * (TH + 2 * BDR)) - 2;
- }
-
- /* animate menu item selection */
- show_cursor();
- look = animate_seg(menu);
- del_seg(menu);
-
- /* replace bit-map region */
- restore_bitmap(&bmap);
-
- /* return selected item */
- for(i = 0;i<num_items;i++)
- if(strcmp(look, items[i]) == 0)
- return(i);
-
- return(-1);
- }
-
- text_t *active = NULL;
-
- char *animate_seg(seg)
- seg_t *seg;
- {
- char *item;
- event_t *myevent;
- key_t *test;
- text_t *t;
-
- for(;;)
- {
- myevent = get_next_event();
-
- if(myevent->what == UP_BUTTON_EVENT)
- {
- if(active == NULL)
- return(NULL);
- else
- {
- item = active->text;
- active = NULL;
- return(item);
- }
- }
- else if( pt_in_rect( seg->bbox, &(myevent->where) ))
- {
- test = seg->data;
- while(test != NULL)
- {
- /* is text primitive */
- if(test->type == TEXT)
- {
- t = test->key.text;
- if(pt_in_rect(t->bbox, &(myevent->where)))
- {
- if(active == NULL)
- {
- /* make t the active text */
- xor_rect(t->bbox, FILL);
- active = t;
- }
- else if(active != t)
- {
- /* dim old text, make t active */
- xor_rect(active->bbox, FILL);
- xor_rect(t->bbox, FILL);
- active = t;
- }
- /* else do nothing */
- }
- }
- test = test->next;
- }
- }
- /* must be outside menu area */
- else if(active != NULL)
- {
- xor_rect(active->bbox, FILL);
- active = NULL;
- }
- }
- }
-
- void save_bitmap( rect )
- rect_t *rect;
- {
- hide_cursor();
-
- /*
- save rectangular area of bit map
- */
-
- show_cursor();
- }
-
- void restore_bitmap( rect )
- rect_t *rect;
- {
- hide_cursor();
-
- /*
- restore rectangular area of bit map
- */
-
- show_cursor();
- }
-
- /*
- Instead of using the segmentation system's
- XOR feature, which clips and maps primitives,
- use this function to provide the fastest
- possible animation speed.
- */
-
- xor_rect( rect, how)
- rect_t *rect;
- int how;
- {
-
- switch( how )
- {
- case FILL :
- /*
- Xor FILLed rectangle
- */
- break;
-
- case FRAME :
- /*
- Xor FRAMEd rectangle
- */
- break;
- }
- }