home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
- #include "memory.h"
- #include "malloc.h"
- #include "string.h"
-
- void pascal
- /* XTAG:pulldown */
- pulldown(menuNumber)
- int menuNumber;
- {
- extern unsigned char msgBuffer[];
- extern int menuLine;
- extern struct menuBlock far *menus[];
- extern int scrRows, scrCols;
- extern unsigned char topColor;
- extern int menuShowing;
-
- register int i;
- int limit, col, row;
- unsigned char far *fp;
-
- if( menuLine == 0 )
- return;
- limit = menus[menuNumber]->nItems;
- col = 0;
- row = (menuLine > 0 ? 0 : (scrRows-1) );
- for(i = 1; i < limit; i++) {
- fp = menus[menuNumber]->cmdName[i];
- while( *fp != '\0' ) {
- displayChar(row, col++, *fp++, topColor);
- if( col >= scrCols )
- return;
- }
- }
- while( col < scrCols )
- displayChar(row, col++, ' ', topColor);
- /* remember which menu is up for showing descriptions */
- menuShowing = menuNumber;
- }
-
- int pascal
- /* XTAG:menu */
- menu(thisMenu, row1, col1)
- struct menuBlock far *thisMenu;
- int row1, col1;
- {
- extern unsigned char msgBuffer[];
- extern unsigned char textBuffer[];
- extern unsigned char border2[];
- extern union REGS rin, rout;
- extern struct SREGS segRegs;
- extern unsigned char *screenChars;
- extern int debug;
- extern unsigned char bannerColor, borderColor, elevColor;
- extern unsigned char textColor, selColor;
- extern int scrRows, scrCols;
- extern struct event events[];
- extern struct menuBlock far *menus[];
- extern int mousePresent;
- extern int i43lines;
- extern int descrFileId;
- extern int helpMode;
- extern unsigned char *userMessages[];
- extern int lastCommand;
- extern int menuLine;
- extern int centerMenus;
- extern struct optionItem options[];
- extern struct window *activeWindow;
- extern unsigned char msgColor, promptColor, errorColor, topColor;
- extern int toplineMenu;
-
- int i, j, n, row, col, row2, col2, numItems, maxSize, fn;
- int attr, selRow, curRow, curCol, lastRow, lastCol;
- int oldSelRow, r1, r2;
- int chordExit, startButtons;
- int evhead;
- int menuNumber;
- unsigned char far *sBuffer;
- unsigned int sizeOfBuffer;
- unsigned char key, scan, ch;
- unsigned char far *fname;
- int restart;
-
- startOver:
- restart = 0;
- /* get the present mouse button state */
- if( mousePresent ) {
- rin.x.ax = 3;
- int86(51, &rin, &rout);
- startButtons = rout.x.bx;
- } else
- startButtons = 0x0;
- chordExit = 0; /* set to 1 if any buttons change */
-
- /* it is only necessary to differentiate between menu 0 */
- /* and all other menus so this will suffice */
- if( thisMenu == menus[0] )
- menuNumber = 0;
- else
- menuNumber = 1;
- numItems = thisMenu->nItems;
- if( numItems <= 0 )
- return FDONOTHING;
- maxSize = 0;
- for(n = 0; n < numItems; n++) {
- /* see if this is an option menu item */
- fn = thisMenu->cmdNumber[n];
- if( FFIRSTOPTION <= fn && fn <= FLASTOPTION ) {
- /* 70 should handle the largest option string */
- thisMenu->cmdName[n] =
- (unsigned char far *)_fmalloc(70);
- /* create the option string */
- i = 0;
- while( options[i].commandNumber != fn ) {
- if( options[i].index == OLASTITEM ) {
- sprintf(msgBuffer,
- "Unknown option command [%d]; ignored in menu", fn);
- goto loopAgain;
- }
- ++i;
- }
- switch( options[i].type ) {
- case OBOOLEAN:
- case UBOOLEAN:
- sprintf(msgBuffer,"%s is %s",options[i].name,
- (*(options[i].variable)?"On":"Off"));
- break;
- case OINTEGER:
- case UINTEGER:
- sprintf(msgBuffer,"%s = %d",options[i].name,
- *(options[i].variable));
- break;
- case OSTRING:
- case USTRING:
- sprintf(msgBuffer,"%s = %s",options[i].name,
- options[i].variable);
- break;
- case OOTHERS:
- case UOTHERS:
- switch(options[i].index) {
- case OTEXTCOLORS:
- sprintf(msgBuffer,"%s = %02X%02X",
- options[i].name,
- activeWindow->textColor,
- activeWindow->selColor);
- break;
- case OBORDERCOLORS:
- sprintf(msgBuffer,"%s = %02X%02X%02X",
- options[i].name,
- activeWindow->bannerColor,
- activeWindow->borderColor,
- activeWindow->elevColor);
- break;
- case OMSGCOLORS:
- sprintf(msgBuffer,
- "%s = %02X%02X%02X%02X",
- options[i].name,
- msgColor, promptColor,
- errorColor, topColor);
- break;
- case OREDEFINE:
- sprintf(msgBuffer, "%s",
- options[i].name);
- }
- break;
- }
- sBuffer = thisMenu->cmdName[n];
- movedata(segRegs.ds, (unsigned)msgBuffer,
- FP_SEG(sBuffer), FP_OFF(sBuffer),
- strlen(msgBuffer)+1);
- /* +1 to move the '\0' */
- }
- j = farStrlen(thisMenu->cmdName[n]);
- if( n == 0 )
- j += 4;
- if( j > maxSize )
- maxSize = j;
- loopAgain:
- ;
- }
- row2 = row1 + numItems;
- /* double space in 43 line mode (so menus are easier to read) */
- if( i43lines && numItems <= 19 )
- row2 += numItems;
- col2 = col1 + maxSize + 5; /* so centering looks better */
- /* 5 = 4 (2 spaces on each side of names) + 1 (col1->col2) */
- /* if not centering menus, just add one space on each side */
- if( !centerMenus )
- col2 -= 2;
- /* adjust the dimensions so that the menu always fits on the screen */
- if( row2 > (scrRows-1) ) {
- row1 -= (row2 - (scrRows-1));
- row2 = (scrRows-1);
- if( menuLine < 0 ) {
- /* a fix so that the menus do not cover the */
- /* message lien when using bottom line menus */
- if( row1 > 1 ) {
- row1 -= 2;
- row2 -= 2;
- } else if( row1 > 0 ) {
- --row1;
- --row2;
- }
- }
- }
- if( col2 > (scrCols-1) ) {
- col1 -= (col2 - (scrCols-1));
- col2 = (scrCols-1);
- }
-
- /* ELIMINATE THIS WHEN YOU ELIMINATE screenChars */
- /* save the present screen characters */
- /* allocate some memory to hold the screen image */
- sizeOfBuffer = (unsigned)((scrCols<<1)*(row2-row1+1));
- sBuffer = _fmalloc(sizeOfBuffer);
- if( sBuffer == 0L ) {
- msg(userMessages[NOSPACEMSG], 3);
- return FDONOTHING;
- }
- movedata(segRegs.ds, (int)(screenChars+(scrCols<<1)*row1),
- FP_SEG(sBuffer), FP_OFF(sBuffer), sizeOfBuffer);
-
- /* set up the map and draw the menu */
- setMap(row1, col1, row2, col2, 2, textColor);
-
- /* draw the menu name in */
- fname = thisMenu->cmdName[0];
- col = col1 + (col2-col1-farStrlen(fname)-3)/2;
- displayChar(row1, col++, 16, elevColor);
- displayChar(row1, col++, ' ', elevColor);
- for(i = 0; fname[i] != '\0'; i++)
- displayChar(row1, col++, fname[i], elevColor);
- displayChar(row1, col++, ' ', elevColor);
- displayChar(row1, col++, 17, elevColor);
-
- /* draw the border */
- drawBorder(&border2[0], row1, col1, row2, col2, borderColor, 0);
-
- selRow = row1;
- lastRow = curRow = row1;
- lastCol = curCol = col1;
- oldSelRow = -1;
- /* start by prompting with the menus "comment" */
- while( 1 ) {
- /* first draw the menu */
- setMap(row1+1, col1+1, row2-1, col2-1, 1, textColor);
- row = row1 + 1;
- if( i43lines && numItems <= 19 )
- ++row;
- fn = 0;
- for(i = 1; i < numItems; i++) {
- fname = thisMenu->cmdName[i];
- col = col1 + 1;
- j = 0;
- if( row == selRow ) { /* the selected item */
- attr = selColor;
- fn = i;
- } else
- attr = textColor;
- if( centerMenus ) {
- /* center the menu item */
- n = (col2-col1-farStrlen(fname)-1)/2;
- } else
- n = 1;
- while( n-- > 0 )
- displayChar(row, col++, ' ', attr);
- while( 1 ) {
- ch = fname[j++];
- if( ch == '\0' )
- break;
- displayChar(row, col++, ch, attr);
- }
- while( col < col2 )
- displayChar(row, col++, ' ', attr);
- ++row;
- /* double space menu items in 43 line mode */
- if( i43lines && numItems <= 19 )
- ++row;
- }
- if( oldSelRow == -1 ) {
- /* first time -- write the whole menu */
- r1 = row1;
- r2 = row2;
- } else {
- if( oldSelRow == row1 )
- /* no old selection to erase */
- oldSelRow = selRow;
- /* rewrite the old and new selection only */
- r1 = min(oldSelRow, selRow);
- r2 = max(oldSelRow, selRow);
- if( selRow == row1 )
- /* no new selection to rewrite */
- r1 = oldSelRow;
- }
- updateScreen(r1, r2);
- /* remember the last command selected (except the default) */
- if( menuNumber != 0 && fn != 0 ) {
- lastCommand = thisMenu->cmdNumber[fn];
- }
- if( menuNumber != 0 && helpMode > 0 ) {
- /* if in help mode then display one line descriptions */
- readLine(descrFileId, 80L*(long)(thisMenu->cmdNumber[fn]),
- &msgBuffer[0], 0);
- msgBuffer[78] = '\0';
- msg(msgBuffer, 1);
- }
- while( 1 ) {
- if( isKeystroke() != 0 ) {
- key = getKeystroke(&scan);
- switch( key ) {
- case '\r': /* return/enter */
- goto done; /* accept current selection */
- case '\033': /* ESCape */
- selRow = row1; /* no selection */
- goto done;
- default: /* ignore it */
- fn = translateKey(key, scan);
- cursor(fn, 0);
- break;
- }
- }
-
- if( isMouseEvent(0) ) {
- evhead = getMouseEvent();
- while( events[evhead].mask == 1 && isMouseEvent(0) )
- evhead = getMouseEvent();
- n = events[evhead].buttons;
-
- /* see if we are done or need to exit to */
- /* another menu */
- if( n == 0 ) { /* no buttons are down */
- if( startButtons != 0 )
- /* the buttons came up */
- goto done;
- /* otherwise we are still choosing */
- } else { /* some buttons are down */
- /* is this the down press of a click? */
- if( startButtons == 0 )
- startButtons = n;
- else {
- /* check if a button is down (bit=1)*/
- /* in n that was not down in */
- /* startButtons by zeroing all the */
- /* bits in n that were =1 in */
- /* startButtons if any 1 bits are */
- /* left we have more buttons down */
- /* now than before so look for */
- /* another menu */
- if( ((~startButtons) & n) != 0 ) {
- chordExit = 1;
- goto done;
- }
- }
- }
- curRow = events[evhead].vertical>>3;
- curCol = events[evhead].horizontal>>3;
- if( (curRow!=lastRow) || (curCol!=lastCol) ) {
- if( curRow == 0 && toplineMenu != 0 ) {
- i = CommandToMenuNumber(
- FindMenuItem(toplineMenu,
- curCol));
- if( i!=0 && menus[i]!=thisMenu ) {
- thisMenu = menus[i];
- row1 = 1;
- col1 = curCol;
- restart = 1;
- goto done;
- }
- }
- lastRow = curRow;
- lastCol = curCol;
- oldSelRow = selRow;
- if( curCol < col1 || curCol > col2
- || curRow <= row1 || curRow >= row2 )
- selRow = row1; /* no selection */
- else
- selRow = curRow;
- /* if we are pointing at a spacing line */
- /* then select the line above it. */
- /* A spacing line is an odd number of rows */
- /* from row1. */
- if( i43lines && numItems <= 19
- && ((0x1 & (selRow-row1)) == 1) )
- --selRow;
- n = selRow - row1;
- if( i43lines && numItems <= 19 )
- n /= 2;
- if( 1 <= n && n < numItems ) {
- if( -1 == thisMenu->cmdNumber[n] )
- selRow = row1;
- }
- break;
- }
- }
- }
- }
-
- done:
- /**************************************************
- this is slower but doesn't require a screenChars buffer
- redrawBox(row1, col1, row2, col2);
- ****************************************************/
- movedata(FP_SEG(sBuffer), FP_OFF(sBuffer), segRegs.ds,
- (int)(screenChars+(scrCols<<1)*row1), sizeOfBuffer);
- _ffree(sBuffer);
- updateScreen(row1, row2);
- msg("", 1);
-
- for(n = 0; n < numItems; n++) {
- /* see if this is an option menu item */
- if( thisMenu->cmdNumber[n] >= FFIRSTOPTION &&
- thisMenu->cmdNumber[n] <= FLASTOPTION ) {
- _ffree( thisMenu->cmdName[n] );
- }
- }
-
- if( restart )
- goto startOver;
-
- /* figure out what to return */
- n = selRow - row1;
- if( i43lines && numItems <= 19 )
- n /= 2;
- if( 1 <= n && n < numItems )
- i = thisMenu->cmdNumber[n];
- else
- i = thisMenu->cmdNumber[0];
- if( chordExit )
- i = FCHANGEMENU;
- return i;
- }
-