home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / PT20PC.ZIP / MENU.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-04  |  11.4 KB  |  432 lines

  1. #include "pt.h"
  2. #include "memory.h"
  3. #include "malloc.h"
  4. #include "string.h"
  5.  
  6. void pascal
  7. /* XTAG:pulldown */
  8. pulldown(menuNumber)
  9.     int menuNumber;
  10. {
  11.     extern unsigned char msgBuffer[];
  12.     extern int menuLine;
  13.     extern struct menuBlock far *menus[];
  14.     extern int scrRows, scrCols;
  15.     extern unsigned char topColor;
  16.     extern int menuShowing;
  17.     
  18.     register int i;
  19.     int limit, col, row;
  20.     unsigned char far *fp;
  21.     
  22.     if( menuLine == 0 )
  23.         return;
  24.     limit = menus[menuNumber]->nItems;
  25.     col = 0;
  26.     row = (menuLine > 0 ? 0 : (scrRows-1) );
  27.     for(i = 1; i < limit; i++) {
  28.         fp = menus[menuNumber]->cmdName[i];
  29.         while( *fp != '\0' ) {
  30.             displayChar(row, col++, *fp++, topColor);
  31.             if( col >= scrCols )
  32.                 return;
  33.         }
  34.     }
  35.     while( col < scrCols )
  36.         displayChar(row, col++, ' ', topColor);
  37.     /* remember which menu is up for showing descriptions */
  38.     menuShowing = menuNumber;
  39. }
  40.  
  41. int pascal
  42. /* XTAG:menu */
  43. menu(thisMenu, row1, col1)
  44.     struct menuBlock far *thisMenu;
  45.     int row1, col1;
  46. {
  47.     extern unsigned char msgBuffer[];
  48.     extern unsigned char textBuffer[];
  49.     extern unsigned char border2[];
  50.     extern union REGS rin, rout;
  51.     extern struct SREGS segRegs;
  52.     extern unsigned char *screenChars;
  53.     extern int debug;
  54.     extern unsigned char bannerColor, borderColor, elevColor;
  55.     extern unsigned char textColor, selColor;
  56.     extern int scrRows, scrCols;
  57.     extern struct event events[];
  58.     extern struct menuBlock far *menus[];
  59.     extern int mousePresent;
  60.     extern int i43lines;
  61.     extern int descrFileId;
  62.     extern int helpMode;
  63.     extern unsigned char *userMessages[];
  64.     extern int lastCommand;
  65.     extern int menuLine;
  66.     extern int centerMenus;
  67.     extern struct optionItem options[];
  68.     extern struct window *activeWindow;
  69.     extern unsigned char msgColor, promptColor, errorColor, topColor;
  70.     extern int toplineMenu;
  71.  
  72.     int i, j, n, row, col, row2, col2, numItems, maxSize, fn;
  73.     int attr, selRow, curRow, curCol, lastRow, lastCol;
  74.     int oldSelRow, r1, r2;
  75.     int chordExit, startButtons;
  76.     int evhead;
  77.     int menuNumber;
  78.     unsigned char far *sBuffer;
  79.     unsigned int sizeOfBuffer;
  80.     unsigned char key, scan, ch;
  81.     unsigned char far *fname;
  82.     int restart;
  83.  
  84. startOver:
  85.     restart = 0;
  86.     /* get the present mouse button state */
  87.     if( mousePresent ) {
  88.         rin.x.ax = 3;
  89.         int86(51, &rin, &rout);
  90.         startButtons = rout.x.bx;
  91.     } else
  92.         startButtons = 0x0;
  93.     chordExit = 0;    /* set to 1 if any buttons change */
  94.  
  95.     /* it is only necessary to differentiate between menu 0 */
  96.     /* and all other menus so this will suffice */
  97.     if( thisMenu == menus[0] )
  98.         menuNumber = 0;
  99.     else
  100.         menuNumber = 1;
  101.     numItems = thisMenu->nItems;
  102.     if( numItems <= 0 )
  103.         return FDONOTHING;
  104.     maxSize = 0;
  105.     for(n = 0; n < numItems; n++) {
  106.         /* see if this is an option menu item */
  107.         fn = thisMenu->cmdNumber[n];
  108.         if( FFIRSTOPTION <= fn && fn <= FLASTOPTION ) {
  109.                 /* 70 should handle the largest option string */
  110.             thisMenu->cmdName[n] =
  111.                 (unsigned char far *)_fmalloc(70);
  112.             /* create the option string */
  113.             i = 0;
  114.             while( options[i].commandNumber != fn ) {
  115.                 if( options[i].index == OLASTITEM ) {
  116.                     sprintf(msgBuffer,
  117. "Unknown option command [%d]; ignored in menu", fn);
  118.                     goto loopAgain;
  119.                 }
  120.                 ++i;
  121.             }
  122.             switch( options[i].type ) {
  123.             case OBOOLEAN:
  124.             case UBOOLEAN:
  125.                 sprintf(msgBuffer,"%s is %s",options[i].name,
  126.                     (*(options[i].variable)?"On":"Off"));
  127.                 break;
  128.             case OINTEGER:
  129.             case UINTEGER:
  130.                 sprintf(msgBuffer,"%s = %d",options[i].name,
  131.                     *(options[i].variable));
  132.                 break;
  133.             case OSTRING:
  134.             case USTRING:
  135.                 sprintf(msgBuffer,"%s = %s",options[i].name,
  136.                     options[i].variable);
  137.                 break;
  138.             case OOTHERS:
  139.             case UOTHERS:
  140.                 switch(options[i].index) {
  141.                 case OTEXTCOLORS:
  142.                     sprintf(msgBuffer,"%s = %02X%02X",
  143.                         options[i].name,
  144.                         activeWindow->textColor,
  145.                         activeWindow->selColor);
  146.                     break;
  147.                 case OBORDERCOLORS:
  148.                     sprintf(msgBuffer,"%s = %02X%02X%02X",
  149.                         options[i].name,
  150.                         activeWindow->bannerColor,
  151.                         activeWindow->borderColor,
  152.                         activeWindow->elevColor);
  153.                     break;
  154.                 case OMSGCOLORS:
  155.                     sprintf(msgBuffer,
  156.                         "%s = %02X%02X%02X%02X",
  157.                         options[i].name,
  158.                         msgColor, promptColor,
  159.                         errorColor, topColor);
  160.                     break;
  161.                 case OREDEFINE:
  162.                     sprintf(msgBuffer, "%s",
  163.                         options[i].name);
  164.                 }
  165.                 break;
  166.             }
  167.             sBuffer = thisMenu->cmdName[n];
  168.             movedata(segRegs.ds, (unsigned)msgBuffer,
  169.                 FP_SEG(sBuffer), FP_OFF(sBuffer),
  170.                 strlen(msgBuffer)+1);
  171.                 /* +1 to move the '\0' */
  172.         }
  173.         j = farStrlen(thisMenu->cmdName[n]);
  174.         if( n == 0 )
  175.             j += 4;
  176.         if( j > maxSize )
  177.             maxSize = j;
  178.     loopAgain:
  179.         ;
  180.     }
  181.     row2 = row1 + numItems;
  182.     /* double space in 43 line mode (so menus are easier to read) */
  183.     if( i43lines && numItems <= 19 )
  184.         row2 += numItems;
  185.     col2 = col1 + maxSize + 5; /* so centering looks better */
  186.         /* 5 = 4 (2 spaces on each side of names) + 1 (col1->col2) */
  187.     /* if not centering menus, just add one space on each side */
  188.     if( !centerMenus )
  189.         col2 -= 2;
  190.     /* adjust the dimensions so that the menu always fits on the screen */
  191.     if( row2 > (scrRows-1) ) {
  192.         row1 -= (row2 - (scrRows-1));
  193.         row2 = (scrRows-1);
  194.         if( menuLine < 0 ) {
  195.             /* a fix so that the menus do not cover the */
  196.             /* message lien when using bottom line menus */
  197.             if( row1 > 1 ) {
  198.                 row1 -= 2;
  199.                 row2 -= 2;
  200.             } else if( row1 > 0 ) {
  201.                 --row1;
  202.                 --row2;
  203.             }
  204.         }
  205.     }
  206.     if( col2 > (scrCols-1) ) {
  207.         col1 -= (col2 - (scrCols-1));
  208.         col2 = (scrCols-1);
  209.     }
  210.  
  211. /* ELIMINATE THIS WHEN YOU ELIMINATE screenChars */
  212.     /* save the present screen characters */
  213.     /* allocate some memory to hold the screen image */
  214.     sizeOfBuffer = (unsigned)((scrCols<<1)*(row2-row1+1));
  215.     sBuffer = _fmalloc(sizeOfBuffer);
  216.     if( sBuffer == 0L ) {
  217.         msg(userMessages[NOSPACEMSG], 3);
  218.         return FDONOTHING;
  219.     }
  220.     movedata(segRegs.ds, (int)(screenChars+(scrCols<<1)*row1),
  221.         FP_SEG(sBuffer), FP_OFF(sBuffer), sizeOfBuffer);
  222.  
  223.     /* set up the map and draw the menu */
  224.     setMap(row1, col1, row2, col2, 2, textColor);
  225.     
  226.     /* draw the menu name in */
  227.     fname = thisMenu->cmdName[0];
  228.     col = col1 + (col2-col1-farStrlen(fname)-3)/2;
  229.     displayChar(row1, col++, 16, elevColor);
  230.     displayChar(row1, col++, ' ', elevColor);
  231.     for(i = 0; fname[i] != '\0'; i++)
  232.         displayChar(row1, col++, fname[i], elevColor);
  233.     displayChar(row1, col++, ' ', elevColor);
  234.     displayChar(row1, col++, 17, elevColor);
  235.     
  236.     /* draw the border */
  237.     drawBorder(&border2[0], row1, col1, row2, col2, borderColor, 0);
  238.  
  239.     selRow = row1;
  240.     lastRow = curRow = row1;
  241.     lastCol = curCol = col1;
  242.     oldSelRow = -1;
  243.     /* start by prompting with the menus "comment" */
  244. while( 1 ) {
  245.     /* first draw the menu */
  246.     setMap(row1+1, col1+1, row2-1, col2-1, 1, textColor);
  247.     row = row1 + 1;
  248.     if( i43lines && numItems <= 19 )
  249.         ++row;
  250.     fn = 0;
  251.     for(i = 1; i < numItems; i++) {
  252.         fname = thisMenu->cmdName[i];
  253.         col = col1 + 1;
  254.         j = 0;
  255.         if( row == selRow ) {    /* the selected item */
  256.             attr = selColor;
  257.             fn = i;
  258.         } else
  259.             attr = textColor;
  260.         if( centerMenus ) {
  261.             /* center the menu item */
  262.             n = (col2-col1-farStrlen(fname)-1)/2;
  263.         } else
  264.             n = 1;
  265.         while( n-- > 0 )
  266.             displayChar(row, col++, ' ', attr);
  267.         while( 1 ) {
  268.             ch = fname[j++];
  269.             if( ch == '\0' )
  270.                 break;
  271.             displayChar(row, col++, ch, attr);
  272.         }
  273.         while( col < col2 )
  274.             displayChar(row, col++, ' ', attr);
  275.         ++row;
  276.         /* double space menu items in 43 line mode */
  277.         if( i43lines && numItems <= 19 )
  278.             ++row;
  279.     }
  280.     if( oldSelRow == -1 ) {
  281.         /* first time -- write the whole menu */
  282.         r1 = row1;
  283.         r2 = row2;
  284.     } else {
  285.         if( oldSelRow == row1 )
  286.             /* no old selection to erase */
  287.             oldSelRow = selRow;
  288.         /* rewrite the old and new selection only */
  289.         r1 = min(oldSelRow, selRow);
  290.         r2 = max(oldSelRow, selRow);
  291.         if( selRow == row1 )
  292.             /* no new selection to rewrite */
  293.             r1 = oldSelRow;
  294.     }
  295.     updateScreen(r1, r2);
  296.     /* remember the last command selected (except the default) */
  297.     if( menuNumber != 0 && fn != 0 ) {
  298.         lastCommand = thisMenu->cmdNumber[fn];
  299.     }
  300.     if( menuNumber != 0 && helpMode > 0 ) {
  301.         /* if in help mode then display one line descriptions */
  302.         readLine(descrFileId, 80L*(long)(thisMenu->cmdNumber[fn]),
  303.             &msgBuffer[0], 0);
  304.         msgBuffer[78] = '\0';
  305.         msg(msgBuffer, 1);
  306.     }
  307.     while( 1 ) {
  308.         if( isKeystroke() != 0 ) {
  309.             key = getKeystroke(&scan);
  310.             switch( key ) {
  311.             case '\r':    /* return/enter */
  312.                 goto done;    /* accept current selection */
  313.             case '\033':    /* ESCape */
  314.                 selRow = row1;    /* no selection */
  315.                 goto done;
  316.             default:    /* ignore it */
  317.                 fn = translateKey(key, scan);
  318.                 cursor(fn, 0);
  319.                 break;
  320.             }
  321.         }
  322.  
  323.         if( isMouseEvent(0) ) {
  324.             evhead = getMouseEvent();
  325.             while( events[evhead].mask == 1 && isMouseEvent(0) )
  326.                 evhead = getMouseEvent();
  327.             n = events[evhead].buttons;
  328.  
  329.             /* see if we are done or need to exit to */
  330.             /* another menu */
  331.             if( n == 0 ) {    /* no buttons are down */
  332.                 if( startButtons != 0 )
  333.                     /* the buttons came up */
  334.                     goto done;
  335.                 /* otherwise we are still choosing */
  336.             } else {    /* some buttons are down */
  337.                 /* is this the down press of a click? */
  338.                 if( startButtons == 0 )
  339.                     startButtons = n;
  340.                 else {
  341.                     /* check if a button is down (bit=1)*/
  342.                     /* in n that was not down in */
  343.                     /* startButtons by zeroing all the */
  344.                     /* bits in n that were =1 in */
  345.                     /* startButtons if any 1 bits are */
  346.                     /* left we have more buttons down */
  347.                     /* now than before so look for */
  348.                     /* another menu */
  349.                     if( ((~startButtons) & n) != 0 ) {
  350.                         chordExit = 1;
  351.                         goto done;
  352.                     }
  353.                 }
  354.             }
  355.             curRow = events[evhead].vertical>>3;
  356.             curCol = events[evhead].horizontal>>3;
  357.             if( (curRow!=lastRow) || (curCol!=lastCol) ) {
  358.                 if( curRow == 0 && toplineMenu != 0 ) {
  359.                     i = CommandToMenuNumber(
  360.                         FindMenuItem(toplineMenu,
  361.                                 curCol));
  362.                     if( i!=0 && menus[i]!=thisMenu ) {
  363.                         thisMenu = menus[i];
  364.                         row1 = 1;
  365.                         col1 = curCol;
  366.                         restart = 1;
  367.                         goto done;
  368.                     }
  369.                 }
  370.                 lastRow = curRow;
  371.                 lastCol = curCol;
  372.                 oldSelRow = selRow;
  373.                 if( curCol < col1 || curCol > col2
  374.                  || curRow <= row1 || curRow >= row2 )
  375.                     selRow = row1;    /* no selection */
  376.                 else
  377.                     selRow = curRow;
  378.                 /* if we are pointing at a spacing line */
  379.                 /* then select the line above it. */
  380.                 /* A spacing line is an odd number of rows */
  381.                 /* from row1. */
  382.                 if( i43lines && numItems <= 19
  383.                  && ((0x1 & (selRow-row1)) == 1) )
  384.                     --selRow;
  385.                 n = selRow - row1;
  386.                 if( i43lines && numItems <= 19 )
  387.                     n /= 2;
  388.                 if( 1 <= n && n < numItems ) {
  389.                     if( -1 == thisMenu->cmdNumber[n] )
  390.                         selRow = row1;
  391.                 }
  392.                 break;
  393.             }
  394.         }
  395.     }
  396. }
  397.  
  398. done:
  399. /**************************************************
  400. this is slower but doesn't require a screenChars buffer
  401. redrawBox(row1, col1, row2, col2);
  402. ****************************************************/
  403. movedata(FP_SEG(sBuffer), FP_OFF(sBuffer), segRegs.ds,
  404.     (int)(screenChars+(scrCols<<1)*row1), sizeOfBuffer);
  405. _ffree(sBuffer);
  406. updateScreen(row1, row2);
  407. msg("", 1);
  408.  
  409. for(n = 0; n < numItems; n++) {
  410.     /* see if this is an option menu item */
  411.     if( thisMenu->cmdNumber[n] >= FFIRSTOPTION &&
  412.         thisMenu->cmdNumber[n] <= FLASTOPTION ) {
  413.         _ffree( thisMenu->cmdName[n] );
  414.     }
  415. }
  416.  
  417. if( restart )
  418.     goto startOver;
  419.  
  420. /* figure out what to return */
  421. n = selRow - row1;
  422. if( i43lines && numItems <= 19 )
  423.     n /= 2;
  424. if( 1 <= n && n < numItems )
  425.     i = thisMenu->cmdNumber[n];
  426. else
  427.     i = thisMenu->cmdNumber[0];
  428. if( chordExit )
  429.     i = FCHANGEMENU;
  430. return i;
  431. }
  432.