home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Class Implementation for Popup menu system
- *
- * (C) 1990 Vision Software
- *
- * $Id: popup.c 1.2001 91/04/25 15:07:51 pcalvin release $
- *
- * Comments:
- *
- * Superclass POPUP menus. This class provides popup menuing capabilities.
- * In addition, we have the base class for all scroll/menus etc..
- *
- * Bugs:
- *
- * None documented
- *
- */
- #include <stdlib.h>
- #include <conio.h>
- #include <string.h>
- #include <ctype.h>
- #include <dos.h>
-
- #include <stdhdr.h>
- #include <adl.h>
- #include <menu.h>
-
- #include "lowlevel.h"
-
- /*
- * Public constructors, used by the general public for
- * Straight forward popup menus..
- */
- POPUP::POPUP(ROW row,COL col,CENT centMenu,PENT pentMenu,SZ sz) : help(szNil)
- {
- cchMenuMax = cchNil;
- rowTop = row;
- colLeft = col;
- centMax = centMenu;
- pentBase = pentMenu;
- szTitle = sz;
- }
-
- /*
- * Protected constructors. These are used by the Pulldown system
- * and others to build popups as needed.
- */
- POPUP::POPUP(SZ sz) : help(szNil)
- {
- cchMenuMax = cchNil;
- pentBase = pentNil;
- szTitle = sz;
- }
-
- /*
- * Get routine called by derived classes to adjust menu dynamically
- */
- CENT POPUP::CentGet(ROW row,COL col,CENT cent,PENT pentMenu)
- {
- colLeft = col;
- rowTop = row;
- centMax = cent;
- pentBase = pentMenu;
- return (CentGet());
- }
-
- /*
- * Answers with the key that exited the previous POPUP
- */
- CD POPUP::CdExitKey(VOID)
- {
- return (cdLastKey);
- }
-
- /*
- * Get routine available to the general public, popup must be set
- * at declaration time..
- */
- CENT POPUP::CentGet()
- {
- CURSOR crs(fFalse);
-
- /*
- * Place popup on the screen if needed.
- * Set flag to remove at end..
- */
- Show();
-
- if (pentBase != pentNil)
- help.Replace(pentBase[centAnswer].szQuickHelp);
-
- /*
- * Loop until menu is terminated.
- */
- while (FHandleCd(centAnswer,cdLastKey = CdInput(),pentBase,wnd))
- Display(centAnswer,pentBase,wnd,fTrue);
-
- /*
- * An indication of the selected entry. This flash is NOT done if
- * the selected entry is the root of a sub-menu. Otherwise, we
- * would have flashes all over the screen as sub-menus are unwound.
- */
- if (centAnswer != centError && pentBase[centAnswer].pentNext == pentNil)
- Flash(centAnswer,pentBase,wnd);
-
- /*
- * If this Get is not Re-entrant, remove it from the screen..
- */
- Hide();
-
- /*
- * If a selection was made, attempt to call that function
- */
- if ((centAnswer != centError) && (pentBase != pentNil))
- {
- if (pentBase[centAnswer].pfnFunction != Nil)
- pentBase[centAnswer].pfnFunction();
- }
-
- return (centAnswer);
- }
-
- /*
- * Puts popup onto the screen
- */
- VOID POPUP::Show(VOID)
- {
- /*
- * Compute size of window and open it..
- */
- rowTop = RowTopFromCentPent(centMax,pentBase);
- colLeft = ColLeftFromCentPent(centMax,pentBase);
- rowBottom = CrowFromCentPent(centMax,pentBase) + rowTop+1;
- colRight = CcolFromCentPent(centMax,pentBase) + colLeft+1;
-
- /*
- * Now, simply create the window..
- */
- wnd = WINDOW(rowTop+2,colLeft,rowBottom,colRight,coBlack,coCyan,szTitle);
- wnd.Open();
-
- /*
- * Fill in related information
- */
- Redraw();
-
- /*
- * First member is selected
- */
- Display(centNil,pentBase,wnd,fTrue);
- centAnswer = centNil;
- }
-
- /*
- * Removes the popup from the screen..
- */
- VOID POPUP::Hide(VOID)
- {
- wnd.Close();
- }
-
- /*
- * Redraws the selections
- */
- VOID POPUP::Redraw(VOID)
- {
- for (CENT cent = centNil; cent < centMax; cent++)
- Display(cent,pentBase,wnd,fFalse);
- }
-
- /*
- * Called by Redraw() to display individual entries..
- */
- VOID POPUP::Display(CENT cent,PENT pent,WINDOW &rwnd,BOOL fSelected)
- {
- PointerAssert(pent);
- PointerAssert(pent[cent].sz);
-
- CO coBack = fSelected ? coGreen : coCyan;
- SZ sz = SzFromCentPent(cent,pent);
- CCH cch = pent[cent].cchHotKey+1;
-
- rwnd.SayHot(cent,0,sz,cch,coBlack,coBack);
- }
-
- /*
- * This is the base level handling for Keyboard input. This virtual
- * function answers if the input should continue.
- * Additionally, the first formal parameter (CENT &rcent) answers with
- * the new selected entry
- */
- BOOL POPUP::FHandleCd(CENT &rcent,CD cd,PENT pent,WINDOW &rwnd)
- {
- BOOL fContinue = fTrue;
- /*
- * Defaults to no exit, must prove otherwise.
- */
- switch (cd)
- {
- case cdEscape:
- /*
- * The escape key, Unless trapped by a derived class
- * Quits the popup..
- */
- rcent = centError;
- fContinue = fFalse;
- break;
- case cdReturn:
- /*
- * If a derived class is not using the standard MENU entries,
- * It had BETTER trap the return key.
- * If they are not, the program will ASSERT right here.
- */
- Assert(pent != pentNil);
- Assert(pent->sz != szNil);
- /*
- * If there is a sub-menu, display it..
- */
- if (pent[rcent].pentNext != pentNil)
- {
- fContinue = FSubMenuFromCentPent(rcent,pent);
- }
- else
- {
- cdLastKey = pent[rcent].sz[pent[rcent].cchHotKey];
- fContinue = fFalse;
- }
- break;
- case cdCursorUp:
- if (rcent > 0)
- {
- Display(rcent,pent,rwnd,fFalse);
- rcent -= 1;
- help.Replace(pent[rcent].szQuickHelp);
- }
- break;
- case cdCursorDown:
- if (rcent+1 < centMax)
- {
- Display(rcent,pent,rwnd,fFalse);
- rcent += 1;
- help.Replace(pent[rcent].szQuickHelp);
- }
- break;
- default:
- if (pentBase != pentNil && isascii(cd))
- {
- CHAR ch = toupper(cd);
-
- for (CENT centKey = centNil; fContinue && centKey < centMax; centKey++)
- {
- /*
- * Search array for matching key.
- */
- if (toupper(pent[centKey].sz[pent[centKey].cchHotKey]) == ch)
- {
- Display(rcent,pent,rwnd,fFalse);
- cdLastKey = (CD)pent[centKey].sz[pent[centKey].cchHotKey];
- rcent = centKey;
-
- /*
- * If this menu has a sub-menu, move the highlight over the
- * selected member and activate the sub-menu
- */
- if (pent[centKey].pentNext != pentNil)
- {
- Display(rcent,pent,rwnd,fTrue);
- fContinue = FSubMenuFromCentPent(centKey,pent);
- }
- else
- {
- fContinue = fFalse;
- }
- }
- }
- }
- }
-
- return (fContinue);
- }
-
- /*
- * Builds a temporary string for output. This string is padded with
- * a space on the left and right
- */
- VOLATILE SZ POPUP::SzFromCentPent(CENT cent,PENT pent)
- {
- PointerAssert(pent);
- PointerAssert(pent[cent].sz);
-
- STATIC SZTEMP szAnswer = { " " };
- CHAR chRight = (pent[cent].pentNext == pentNil) ? ' ' : 175;
- CCH cch = strlen(pent[cent].sz);
-
- /*
- * Build the temporary string.
- * After copy, pad the string with spaces.
- */
- strncpy(&szAnswer[1],pent[cent].sz,cch);
-
- while (cch < cchMenuMax)
- szAnswer[1+cch++] = chSpace;
-
- /*
- * Finally, fill in the ending character..
- */
- szAnswer[cch+1] = chRight;
- szAnswer[cch+2] = chNil;
-
- return (szAnswer);
- }
-
- /*
- * Flash the selected entry
- */
- VOID POPUP::Flash(CENT cent,PENT pent,WINDOW &rwnd)
- {
- for (INT count=0; count < 5; count++)
- {
- Display(cent,pent,rwnd,fFalse);
- delay(40);
- Display(cent,pent,rwnd,fTrue);
- delay(40);
- }
- }
-
- /*
- * Windows dimensions..
- */
- ROW POPUP::RowTopFromCentPent(CENT cent,PENT pent)
- {
- return (rowTop);
- }
-
- COL POPUP::ColLeftFromCentPent(CENT cent,PENT pent)
- {
- return (colLeft);
- }
-
- ROW POPUP::CrowFromCentPent(CENT centMac,PENT pent)
- {
- return (centMac);
- }
-
- COL POPUP::CcolFromCentPent(CENT centMac,PENT pent)
- {
- cchMenuMax = cchNil;
-
- Assert(pent != pentNil);
-
- for (CENT cent = centNil; cent < centMac; cent++)
- {
- Assert(pent[cent].sz != szNil);
- cchMenuMax = Max(cchMenuMax,strlen(pent[cent].sz));
- }
-
- return (cchMenuMax);
- }
-
- /*
- * Creates and activates a sub-menu for this object.
- */
- BOOL POPUP::FSubMenuFromCentPent(CENT cent,PENT pent)
- {
- PENT pentSub = pent[cent].pentNext;
- CENT centSub = pent[cent].centNext;
- POPUP pop(rowTop+cent,colRight,centSub,pentSub,szNil);
- BOOL fContinue = fTrue;
-
- /*
- * If the user "selects" the sub-menu, as opposed to ESCaping, then
- * we take that as this menu was selected also.
- */
- if (pop.CentGet() != centError)
- fContinue = fFalse;
-
- return (fContinue);
- }
-