/*
** WN_PDOWN - Pulldown Menu/Window Functions
**
** Adapted, with permission, from Keith Funk's code.
**
** Copyright (C) 1992 - Philip A. Mongelluzzo
** All rights reserved.
**
*/

#include "winboss.h"                    /* window header */

#define ITEM scrn[i]                    /* some short hand */

/*
*************
* wn_pdopen *
*************
*/

/*
** wn_pdopen(page,row,col,width,height,watr,batr,hkatr,mx,aflag)
*/

wn_pdopen(page,row,col,width,height,watr,batr,hkatr,mx,aflag)
int page;                               /* video page */
int row, col;                           /* window - upper row/col */
int width, height;                      /* window - height & width */
WNPDPTR mx;                             /* pointer to pulldown menu struct */
int aflag;                              /* active menu items flag */
int watr, batr;                         /* attributes - window & border */
int hkatr;                              /* hot key attribute */
{
int i, ix;                              /* scratch integers */
WINDOWPTR w;                            /* window pointer */

  if(!mx->winopn) {                     /* menu not open, open it now */
    mx->lndx = -1;                      /* set index out of range */
    w = wn_open(page, row, col, width, height, watr, batr);
    if (w == NULL) return(FALSE);       /* out of mem or just fubar */
    wn_sync(w,FALSE);                   /* sync cursor */
    mx->wpsave = w;                     /* save pointer */
    mx->wa = watr;                      /* window atrib */
    mx->ba = batr;                      /* border atrib */
    mx->hka = hkatr;                    /* hot key atrib */
    mx->winopn = TRUE;                  /* say window is open */
  }
  else {
    w = mx->wpsave;                     /* fetch window pointer */
    watr = mx->wa;                      /* fetch window atrib */
    hkatr = mx->hka;                    /* fetch hot key atrib */
  }

/*
** For as long as there is data, display it.
**  Use the first active menu item as the initial index.
**    If the item is active then highlight the hot key and remember it.
**    ONLY IF MENU IS ACTIVE
*/

  i = 0;                                /* init index */
  while(mx->ITEM.r != 99) { 
    wn_putsa(w, mx->ITEM.r, mx->ITEM.c, mx->ITEM.t, watr);
    if(aflag) {
      if(mx->ITEM.status == PDACTIVE) {
        if(mx->lndx == -1) mx->lndx = i;
        ix = wn_cndx(mx->ITEM.t, mx->ITEM.hkc,0);
        wn_putca(w, mx->ITEM.r, mx->ITEM.c+ix, mx->ITEM.hkc, mx->hka);
      }
    }
    i++;
  }
  return(TRUE);
}

/*
**************
* wn_pdclose *
**************
*/

void wn_pdclose(mx)                     /* close pulldown */
WNPDPTR mx;
{
  if(!mx->winopn) return;               /* dont be stupid */
  wn_close(mx->wpsave);
  mx->winopn = FALSE;
}


/*
***************
* wn_pdupdate *
***************
*/

int wn_pdupdate(mx, i, style)           /* update menu item display */
WNPDPTR mx;                             /* pull down menu struct ptr */
int  i;                                 /* menu item to update */
int  style;                             /* PDNORMAL or PDREVERSE */
{
int watr;                               /* window contents attribute */
int hkatr;                              /* attributes for hotkey */
int atr;                                /* atrib that will be used */
int hklite;                             /* hotkey highlight attrib */
WINDOWPTR w;                            /* window pointer */
int ix;                                 /* hot key char index */

  if (!mx->winopn) return(FALSE);       /* window isn't open */

  w = mx->wpsave;                       /* fetch window ptr */
  watr = mx->wa;                        /* and misc atributes */
  hkatr = mx->hka;                      /* .... */

  if (style == PDREVERSE)               /* use reverse video */
  {
    atr = v_setrev(watr);               /* make reverse atrib for line */
    hklite = ((hkatr & 0x0F) | (~watr & 0x70)); /* form new hotkey atrib */
  }
  else                                  /* normal video */
  {
    atr = watr;                         /* right from the structure */
    hklite = hkatr;                     /* as it was opened */
  }

  wn_putsa(w, mx->ITEM.r, mx->ITEM.c, mx->ITEM.t, atr);

  if (mx->ITEM.status == PDACTIVE) {    /* display hot key */
    ix = wn_cndx(mx->ITEM.t, mx->ITEM.hkc,0);
    wn_putca(w, mx->ITEM.r, mx->ITEM.c + ix, mx->ITEM.hkc, hklite);
  }
  return(TRUE);
}

#ifdef COMMENTS
/*
***************
* wn_pdsettog *                         /* set toggle */
***************
*/
#endif

wn_pdsettog(mx, i)                      /* reverse state of togle */
WNPDPTR mx;                             /* menu pointer */
int i;                                  /* menu item of interest */
{
int j, k;                               /* scratch intergers */

  if((mx->ITEM.type != 'T')  && (mx->ITEM.type != 'E'))
    return(PDTOGOK);                    /* no toggles active */
  if (*(mx->ITEM.t) == 'û')             /* toggle is ON, so turn it OFF. */
  {
    *(mx->ITEM.t) = ' ';                /* by loading a blank */
    return(PDTOGOK);                    /* then return */
  }
  
  *(mx->ITEM.t) = 'û';                  /* toggle is off so turn it on */
  if(mx->ITEM.type == 'T')              /* exclusive toggle ?? */
    return(PDTOGOK);                    /* no... simply return */

  k = -2;                               /* set index mark */

  for (j = mx->fm; j <= mx->lm; j++) {  /* turn all other toggles OFF */
    if ((j != i) && (mx->scrn[j].type != 'S')) {
      if (*(mx->scrn[j].t) == 'û') {   /* was ON, so save its index */
        k = j;
        *(mx->scrn[j].t) = ' ';
      }
    }
  }
  if(k == -2)                           /* no other toggles were on */
    return(PDTOGOK);                    /* so say all went well */
  else
    return(k);                          /* ret index of previous ON toggle */
}

/*
***************
* wn_pdgettog *
***************
*/

wn_pdgettog(mx, i)                      /* get toggle */
WNPDPTR mx;                             /* menu pointer */
int i;                                  /* RETURN val of menu item of interest */
{                                       /* -1 sez look for any ON toggle */
int j;                                  /* scratch integer */

  if (i != -1)                          /* get status of specific toggle */
  {
    for (j = mx->fm; j <= mx->lm; j++)  /* find the toggle by its return code */
      if (mx->scrn[j].rv == i) break;
    if (*(mx->scrn[j].t) == 'û')        /* ALT-251, toggle is ON */
      return(TRUE);
    else
      return(FALSE);
  }
  else                                  /* find out if any toggle is ON */
  {
    for (j = mx->fm; j <= mx->lm; j++)
      if (*(mx->scrn[j].t) == 'û')      /* ALT-251, toggle is ON */
        return(mx->scrn[j].rv);         /* return toggles rv code */
  }
  return(PDTOGOK);                      /* no toggles are ON */
}


/*
***************
* wn_pdactive *
***************
*/

void wn_pdactive(mx, i, action)         /* menu activate/deactivate */
WNPDPTR mx;                             /* pointer to menu structure. */
int i;                                  /* menu item's RETURN code */
int action;                             /* TRUE=activate, FALSE=de-activate */
{
int j;                                  /* scratch integer */

  for (j = mx->fm; j <= mx->lm; j++)    /* look up item via RETURN code */
    if (mx->scrn[j].rv == i) break;

  if(action == TRUE)
    mx->scrn[j].status = PDACTIVE;
  else
    mx->scrn[j].status = PDINACTIVE;
}

/*
*************
* wn_pdtype *
*************
*/

int  wn_pdtype(mx, i, newtype, action)
WNPDPTR mx;                             /* pointer to menu structure. */
int i;                                  /* menu item RETURN code */
char newtype;                           /* ignored if Action is FALSE */
int action;                             /* TRUE or FALSE */
{
int j;                                  /* scratch integer */

  for (j = mx->fm; j <= mx->lm; j++)    /* lookup via return code */
    if (mx->scrn[j].rv == i) break;

  if (action == TRUE)                   /* set a new type */
    mx->scrn[j].type = newtype;
  else
    return (mx->scrn[j].type);          /* return current type */
  return(FALSE);
}

/*
************
* wn_pdget *
************
*/

int wn_pdget(mx)
WNPDPTR mx;                             /* pointer to popup menu struct */
{
int i;                                  /* scratch integer */
unsigned int c;                         /* key scan code,,char */
int j;                                  /* 1st char scan index */
char ch;                                /* CHARACTER (!scan code) Entered */
char ch1, ch2;                          /* for caseless searching */
int barmenu;                            /* holds menu type */

  if (!mx->winopn)                      /* avoid foolishness */
    return(-1);                         /* make sure menu is open */

  i = mx->lndx;                         /* and index of last menu item */

/*
** If first and last menu items are on the same row then its a BARMENU
*/

  if (mx->scrn[mx->fm].r == mx->scrn[mx->lm].r)
    barmenu = TRUE;
  else
    barmenu = FALSE;

  while(TRUE)                           /* exit via RET or hotkey */
  {
    if (mx->scrn[i].status == PDACTIVE) /* option is active, so display */
      wn_pdupdate(mx, i, PDREVERSE);    /* in reverse video */

    c = v_getch();                      /* Fetch char and scan code */
    ch = c & 0x7F;                      /* extract character */

    if(c == ESCAPE) break;              /* ESC (user wants out) */
    if((!barmenu) && ((c==LARROW) || (c==RARROW)))
      break;                            /* user wants out of pulldown menu */

    if (mx->scrn[i].status != PDACTIVE) /* no active options in the menu, so */
      continue;                         /* only EXIT type keys are valid */

/*
** CASE 1 - RETURN or DOWN ARROW Pressed (on barmenu)
**          Select & Exit
*/

    if ((c == RETurn) || (barmenu && (c == DARROW)))
    {                                   /* Non toggle type */
      if ((mx->scrn[i].type != 'T') && (mx->scrn[i].type != 'E'))
      {
        mx->lndx = i;                   /* save option index */
        return(mx->scrn[i].rv);         /* exit */
      }
      else                              /* is a toggle, so don't exit */
      {                                 /* reverse the toggle state */
        j = wn_pdsettog(mx, i);         /* if they are Exclusive toggles */
        if (j != PDTOGOK)               /* and another toggle was ON */
          wn_pdupdate(mx, j, PDNORMAL); /* j has its index, update display*/
      }
    }

/*
** CASE 2 - On a Barmenu and Right Arrow Pressed or
**          On a drop menu and Down Arrow Pressed
**          On a Barmenu and Left Arrow Pressed or
**          On a drop menu and Up Arrow Pressed
*/

    if((barmenu && (c == RARROW)) || (!barmenu && (c == DARROW)))
    {
      j = i + 1;                        /* find next active option */
      while (TRUE)
      {
        if (j > mx->lm) j = mx->fm;     /* wrap at end */
        if (mx->scrn[j].status == PDACTIVE) break; /* active option found */
        if (j == i) break;              /* no active menu options */
        j++;
      }
      if (j != i)                       /* found a diff  active option*/
        wn_pdupdate(mx, i, PDNORMAL);   /* unmark old choice. */
      i = j;                            /* bump index */
    }
    else if ((barmenu && (c == LARROW)) || (!barmenu && (c == UARROW)))
    {
      j = i - 1;                        /* find previous active option */
      while (TRUE)
      {
        if (j < mx->fm) j = mx->lm;     /* wrap at end */
        if (mx->scrn[j].status == PDACTIVE) break; /* active option found */
        if (j == i) break;              /* no active options */
        j--;
      }
      if (j != i)                       /* found a diff  active option*/
        wn_pdupdate(mx, i, PDNORMAL);   /* unmark old choice */
      i = j;                            /* bump index */
    }

/*
** CASE 3 - Hot Key Pressed
*/
    for (j = mx->fm; j <= mx->lm; j++)  /* Search for match */
    {
      ch1 = toupper(ch);
      ch2 = toupper(mx->scrn[j].hkc);
      if ((ch1 == ch2) && (mx->scrn[j].status == PDACTIVE))
      {
       wn_pdupdate(mx, i, PDNORMAL);    /* unmark old choice */

                                        /* IF TOGGLE then... */
       if ((mx->scrn[j].type == 'T') || (mx->scrn[j].type == 'E'))
        i = wn_pdsettog(mx, j);         /* switch toggle */
       if (i != PDTOGOK)                /* if other exclusive toggle */
          wn_pdupdate(mx, i, PDNORMAL); /* was ON, redisplay as OFF */
       i = j;                           /* set new choice */

                                        /* IF NOT TOGGLE then... */
       if ((mx->scrn[i].type != 'T') && (mx->scrn[i].type != 'E'))
       {
         wn_pdupdate(mx, i, PDREVERSE); /* hilight new choice */
         mx->lndx = i;                  /* remember last indx */
         return(mx->scrn[i].rv);        /* return with rv */
       }
       else
         break;                         /* don't EXIT on a toggle */
      }
    }                                   /* end hotkey scan loop */
  }                                     /* end while */

  wn_pdclose(mx);                       /* CLOSE the menu */

  if (c==LARROW) return(97);            /* Set return code */
  if (c==RARROW) return(98);
  return(99); 
}

/* End */
