home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * Iteraction library - pop up menus handler. *
- * *
- * Written by Gershon Elber, Oct. 1990 *
- *******************************************************************************
- * History: *
- * 3 Oct 90 - Version 1.0 by Gershon Elber. *
- ******************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <stdio.h>
- #include <dos.h>
- #include "intr_loc.h"
- #include "intr_gr.h"
-
- #define POP_UP_BORDER 10
- #ifdef DJGCC
- #define POP_UP_BASE_LINE 16
- #else
- #define POP_UP_BASE_LINE 12
- #endif /* DJGCC */
-
- static int GRLastColor = 0; /* GR Color set before query. */
- static IntrBType HasHeader = FALSE;
-
- static void MenuProlog(IntrCursorShapeStruct *Cursor,
- int MenuWidth, int MenuHeight, int Top, int Left,
- int FrameWidth,
- IntrColorType FrameColor, IntrColorType BackColor,
- int *Xmin, int *Ymin, int *Xmax, int *Ymax);
- static void MenuEpilog(void);
- static void IntrPopUpMenuDrawItems(IntrPopUpMenuStruct *PUMenu,
- int Top,
- int Left);
- static int MatchPosition(int x, int y, int Top, int Left,
- int Bottom, int Right, int Space, int ItemHeight);
-
- /****************************************************************************
- * Save current graphic state. *
- ****************************************************************************/
- static void MenuProlog(IntrCursorShapeStruct *Cursor,
- int MenuWidth, int MenuHeight, int Top, int Left,
- int FrameWidth,
- IntrColorType FrameColor, IntrColorType BackColor,
- int *Xmin, int *Ymin, int *Xmax, int *Ymax)
- {
- /* Save current graphic state. */
- IntrPushCursorType();
- IntrSetCursorType(Cursor);
-
- GRPushViewPort();
- _GRSetViewPort(0, 0, GRScreenMaxX, GRScreenMaxY);
-
- GRPushTextSetting();
- GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_BOTTOM);
- GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
-
- GRLastColor = GRGetColor();
-
- *Xmin = Left;
- *Ymin = Top;
- *Xmax = Left + MenuWidth;
- *Ymax = Top + MenuHeight;
- _IntrBoundBBox(Xmin, Ymin, Xmax, Ymax, FrameWidth); /* To screen coords. */
-
- _IntrWndwDrawFrame(*Xmin, *Xmax, *Ymin, *Ymax, FrameWidth,
- FrameColor, TRUE, FrameColor, INTR_SCRLBAR_NONE,
- FrameColor, INTR_SCRLBAR_NONE, TRUE);
- IntrAllocColor(BackColor, INTR_INTENSITY_HIGH);
- GRSBar(*Xmin, *Ymin, *Xmax, *Ymax);
-
- }
-
- /****************************************************************************
- * Restore current graphic state. *
- ****************************************************************************/
- static void MenuEpilog(void)
- {
- if (_IntrSaveBelow) {
- _IntrRestoreWindow();
- if (HasHeader) {
- _IntrRestoreWindow();
- HasHeader = FALSE;
- }
- }
-
- GRPopViewPort();
- GRPopTextSetting();
- GRSetColor(GRLastColor);
-
- IntrPopCursorType();
- }
-
- /******************************************************************************
- * Routine to free a pop up menu. *
- ******************************************************************************/
- void IntrPopUpMenuDelete(IntrPopUpMenuStruct *PUMenu)
- {
- _IntrFree(PUMenu);
- }
-
- /******************************************************************************
- * Routine to create a pop up menu. *
- * If SizeOfEntry = 0 then StrEntries is an array of (char *). Otherwise it *
- * holds the size of each entry in StrEntries which is a long string itself. *
- * NumOfEntries defines the length of the menu. *
- * It should be noted that in both cases StrEntries is NOT copied. *
- ******************************************************************************/
- IntrPopUpMenuStruct *IntrPopUpMenuCreate(char *Header,
- char **StrEntries,
- int SizeOfEntry,
- int NumOfEntries,
- IntrColorType FrameColor,
- IntrColorType BackColor,
- IntrColorType ForeColor,
- IntrColorType XorColor,
- int FrameWidth,
- IntrCursorShapeStruct *Cursor)
- {
- int i, MaxLen;
- IntrPopUpMenuStruct *PUMenu;
-
- PUMenu = (IntrPopUpMenuStruct *) _IntrMalloc(sizeof(IntrPopUpMenuStruct));
- PUMenu -> Header = Header;
- PUMenu -> ForeColor = ForeColor;
- PUMenu -> BackColor = BackColor;
- PUMenu -> FrameColor = FrameColor;
- PUMenu -> XorColor = XorColor;
- PUMenu -> FrameWidth = FrameWidth;
- PUMenu -> NumOfEntries = NumOfEntries;
- PUMenu -> SizeOfEntry = SizeOfEntry;
- PUMenu -> StrEntries = StrEntries;
- GEN_COPY(&PUMenu -> Cursor, Cursor, sizeof(IntrCursorShapeStruct));
-
- /* Find width and height of menu using number of items and their */
- /* maximum entry string length. */
- if (SizeOfEntry == 0) { /* Its an array of pointers to strings. */
- for (i = MaxLen = 0; i < NumOfEntries; i++)
- if (MaxLen < strlen(StrEntries[i]))
- MaxLen = strlen(StrEntries[i]);
- }
- else
- MaxLen = SizeOfEntry;
-
- GRPushTextSetting();
- GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
- PUMenu -> _MenuWidth = GRGetTextWidth("M") * MaxLen + (POP_UP_BORDER << 1);
- PUMenu -> _MenuHeight = POP_UP_BASE_LINE * NumOfEntries +
- (POP_UP_BORDER << 1);
- GRPopTextSetting();
-
- return PUMenu;
- }
-
- /****************************************************************************
- * Routine to change pop up menu entry i. Only menus defined using array of *
- * strings can be modified in this way (PUMenu -> SizeOfEntry must be zero). *
- ****************************************************************************/
- void IntrPopUpSetEntry(IntrPopUpMenuStruct *PUMenu, char *Entry, int Index)
- {
- if (PUMenu -> SizeOfEntry == 0)
- PUMenu -> StrEntries[Index] = Entry;
- else
- strncpy((char *) &PUMenu -> StrEntries[Index * PUMenu -> SizeOfEntry],
- Entry,
- PUMenu -> SizeOfEntry - 1);
- }
-
- /****************************************************************************
- * Routine to change pop up menu header. *
- ****************************************************************************/
- void IntrPopUpSetHeader(IntrPopUpMenuStruct *PUMenu, char *Header)
- {
- PUMenu -> Header = Header;
- }
-
- /****************************************************************************
- * Routine to change pop up menu frame width. *
- ****************************************************************************/
- void IntrPopUpSetFrameWidth(IntrPopUpMenuStruct *PUMenu, int FrameWidth)
- {
- PUMenu -> FrameWidth = FrameWidth;
- }
-
- /****************************************************************************
- * Routine to change pop up menu colors. *
- ****************************************************************************/
- void IntrPopUpSetColors(IntrPopUpMenuStruct *PUMenu,
- IntrColorType FrameColor,
- IntrColorType BackColor,
- IntrColorType ForeColor,
- IntrColorType XorColor)
- {
- PUMenu -> ForeColor = ForeColor;
- PUMenu -> BackColor = BackColor;
- PUMenu -> FrameColor = FrameColor;
- PUMenu -> XorColor = XorColor;
- }
-
- /****************************************************************************
- * Routine to draw the given pop up menu items at the given position. *
- ****************************************************************************/
- static void IntrPopUpMenuDrawItems(IntrPopUpMenuStruct *PUMenu,
- int Left,
- int Top)
- {
- int i, Color;
- char *Str = (char *) PUMenu -> StrEntries;
-
- Color = IntrAllocColor(PUMenu -> ForeColor, INTR_INTENSITY_VHIGH);
- GRSetTextJustify(GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_TOP);
- GRSetSTextStyle(GR_FONT_DEFAULT, GR_HORIZ_DIR, GR_TEXT_MAG_1);
-
- Left += POP_UP_BORDER;
- Top += POP_UP_BORDER;
- for (i = 0; i < PUMenu -> NumOfEntries; i++) {
- if (PUMenu -> SizeOfEntry > 0) {
- GRSTextShadow(Left, Top + i * POP_UP_BASE_LINE, Color,
- &Str[i * PUMenu -> SizeOfEntry]);
- }
- else {
- GRSTextShadow(Left, Top + i * POP_UP_BASE_LINE, Color,
- PUMenu -> StrEntries[i]);
- }
- }
- }
-
- /****************************************************************************
- * Routine to attempt to match given location with one of the elements in *
- * items displayed. Item are displayed from Top to Bottom, Left to Right. *
- * Item is placed with Space between them and border, and has ItemHeight *
- * height. *
- * Returns the index that matches, or -1 if No match. *
- ****************************************************************************/
- static int MatchPosition(int x, int y, int Top, int Left,
- int Bottom, int Right, int Space, int ItemHeight)
- {
- int CurrentY, i;
-
- /* Fast clipping if cursor is not in the menu at all. */
- if (x <= Left || x >= Right || y <= Top || y >= Bottom) return -1;
-
- for (i = 0, CurrentY = Top;
- CurrentY < Bottom;
- CurrentY += Space, i++) {
- if (CurrentY <= y && CurrentY + ItemHeight >= y) return i;
- }
- return -1;
- }
-
- /****************************************************************************
- * Routine to pop up a menu. *
- * Return TRUE if was SELECT key, FALSE if ABORT key. *
- * Attempt will be made to pop up the menu in the window specified or in a *
- * screen location INTR_WNDW_PLACE_XXXX. *
- * position may be modified so the entire pop up menu will be visible. *
- * The selected index is saved in PUMenu structure, SelectedIndex entry. *
- ****************************************************************************/
- int IntrPopUpMenu(IntrPopUpMenuStruct *PUMenu, int WindowID)
- {
- IntrBBoxStruct *BBox;
- int MenuCenterX, MenuCenterY;
-
- /* Find center of query prefered position and find BBox for query. */
- if (WindowID > 0) {
- BBox = IntrWndwGetBBox(WindowID);
-
- MenuCenterX = (BBox -> Xmax + BBox -> Xmin) >> 1;
- MenuCenterY = (BBox -> Ymax + BBox -> Ymin) >> 1;
- }
- else
- switch (WindowID) {
- case INTR_WNDW_PLACE_LEFT:
- MenuCenterX = GRScreenMaxX >> 2;
- MenuCenterY = GRScreenMaxY >> 1;
- break;
- case INTR_WNDW_PLACE_RIGHT:
- MenuCenterX = (GRScreenMaxX >> 1) + (GRScreenMaxX >> 2);
- MenuCenterY = GRScreenMaxY >> 1;
- break;
- case INTR_WNDW_PULL_DOWN:
- if (_IntrAsyncLastEvent.AsyncEvent == ASYNC_EVNT_PDMENU) {
- MenuCenterX = _IntrAsyncLastEvent.PDLeft +
- PUMenu -> FrameWidth + (PUMenu -> _MenuWidth >> 1);
- MenuCenterY = _IntrAsyncLastEvent.PDBottom +
- PUMenu -> FrameWidth + (PUMenu -> _MenuHeight >> 1);
- if (PUMenu -> Header != NULL)
- MenuCenterY += IntrWndwGetHeaderHeight(
- PUMenu -> Header, PUMenu -> FrameWidth) + 2;
-
- _IntrAsyncLastEvent.AsyncEvent = ASYNC_EVNT_NONE;
- break;
- }
- case INTR_WNDW_PLACE_CENTER:
- default:
- MenuCenterX = GRScreenMaxX >> 1;
- MenuCenterY = GRScreenMaxY >> 1;
- break;
- }
-
- return _IntrPopUpMenu(PUMenu,
- MenuCenterX - (PUMenu -> _MenuWidth >> 1),
- MenuCenterY - (PUMenu -> _MenuHeight >> 1));
- }
-
- /****************************************************************************
- * Same as IntrPopUpMenu, but exact position is specified via Top/Left. *
- ****************************************************************************/
- int _IntrPopUpMenu(IntrPopUpMenuStruct *PUMenu,
- int Left,
- int Top)
- {
- int x, y, Xmin, Xmax, Ymin, Ymax, Event, MatchIndex, NewIndex,
- RetVal, ListLeft, ListTop, ListRight, ListBottom,
- Exit = FALSE;
-
- MenuProlog(&PUMenu -> Cursor,
- PUMenu -> _MenuWidth, PUMenu -> _MenuHeight, Top, Left,
- PUMenu -> FrameWidth, PUMenu -> FrameColor, PUMenu -> BackColor,
- &Xmin, &Ymin, &Xmax, &Ymax);
-
- ListLeft = Xmin + POP_UP_BORDER; /* Item list boundaries: */
- ListTop = Ymin + POP_UP_BORDER;
- ListRight = Xmax - POP_UP_BORDER;
- ListBottom = Ymax - POP_UP_BORDER;
-
- MatchIndex = -1; /* No match == -1. */
- IntrPopUpMenuDrawItems(PUMenu, Xmin, Ymin);
- if (PUMenu -> Header != NULL) {
- HasHeader = TRUE;
- _IntrWndwPutNameHeader(Xmin - PUMenu -> FrameWidth,
- Xmax + PUMenu -> FrameWidth,
- Ymin - PUMenu -> FrameWidth - 2,
- PUMenu -> FrameWidth, PUMenu -> Header,
- TRUE, PUMenu -> FrameColor,
- PUMenu -> ForeColor, PUMenu -> BackColor,
- TRUE);
- }
-
- Event = INTR_EVNT_MOVE;/* Emulate move event, and test current position. */
- x = GRCurrentCursorX = (ListLeft + ListRight) >> 1;
- y = GRCurrentCursorY = ListTop + (GRGetTextHeight("M") >> 1);
-
- IntrAllocColor(PUMenu -> XorColor, INTR_INTENSITY_VHIGH);
-
- delay(25);
- IntrInputFlush();
-
- while (!Exit) {
- switch (Event) {
- case INTR_EVNT_SELECT:
- /* We are on list item - need to return its index. */
- if (MatchIndex >= 0) {
- RetVal = TRUE;
- PUMenu -> SelectedIndex = MatchIndex;
- Exit = TRUE;
- }
- else {
- GRTone(1500, 100); /* Do some noise... */
- GRTone( 500, 200);
- }
- break;
- case INTR_EVNT_ABORT:
- RetVal = FALSE;
- PUMenu -> SelectedIndex = MatchIndex;
- Exit = TRUE;
- break;
- case INTR_EVNT_MOVE:
- NewIndex = MatchPosition(x, y,
- ListTop, ListLeft, ListBottom, ListRight,
- POP_UP_BASE_LINE, GRGetTextHeight("M"));
- if (NewIndex != MatchIndex) {
- /* Invert this entry back to original state: */
- if (MatchIndex >= 0)
- GRXORRectangle(ListLeft - 1,
- ListTop + MatchIndex * POP_UP_BASE_LINE - 1,
- ListRight + 1,
- ListTop + GRGetTextHeight("M") + 1 +
- MatchIndex * POP_UP_BASE_LINE);
- MatchIndex = NewIndex;
- /* Invert this entry: */
- if (MatchIndex >= 0)
- GRXORRectangle(ListLeft - 1,
- ListTop + MatchIndex * POP_UP_BASE_LINE - 1,
- ListRight + 1,
- ListTop + GRGetTextHeight("M") + 1 +
- MatchIndex * POP_UP_BASE_LINE);
- }
- break;
- }
- if (!Exit) Event = IntrGetEventWait(&x, &y);
- }
-
- MenuEpilog();
-
- return RetVal;
- }
-