//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  GCUI: Golded+ Character-oriented User Interface.
//  Menu class.
//  ------------------------------------------------------------------

#include <cstdlib>
#include <cstring>
#include <gmnubase.h>


//  ------------------------------------------------------------------

void GMnu::Init() {

  bordertype = 0;
  bordercolor = BLACK_|_BLACK;

  textcolor = BLACK_|_BLACK;
  quickcolor = BLACK_|_BLACK;
  noselcolor = BLACK_|_BLACK;
  barcolor = BLACK_|_BLACK;
  shadowcolor = DEFATTR;

  title = NULL;
  titlepos = TCENTER;
  titlecolor = BLACK_|_BLACK;

  deschdl = -1;
  descrow = 0;
  desccolumn = 0;
  desccolor = BLACK_|_BLACK;

  helpnumber = -1;

  beginrow = 0;
  begincolumn = 0;

  menuopen = NULL;
  itemmask = 0;

  escape = YES;
  finaltag = -1;
  status = W_NOERROR;

  depth = -1;
  memset(stack, 0, sizeof(stack));
}


//  ------------------------------------------------------------------

void GMnu::SetBorder(int type, vattr color) {

  bordertype = type;
  bordercolor = color;
}


//  ------------------------------------------------------------------

void GMnu::SetColor(vattr text, vattr quick, vattr nosel, vattr bar, vattr shadow) {

  textcolor = text;
  quickcolor = quick;
  noselcolor = nosel;
  barcolor = bar;
  shadowcolor = shadow;
}


//  ------------------------------------------------------------------

void GMnu::SetTitle(const char* text, vattr color, int pos) {

  title = text;
  titlepos = pos;
  titlecolor = color;
}


//  ------------------------------------------------------------------

void GMnu::SetTitle(const char* text) {

  title = text;
}


//  ------------------------------------------------------------------

void GMnu::SetDesc(int hdl, int row, int col, vattr color) {

  deschdl = hdl;
  descrow = row;
  desccolumn = col;
  desccolor = color;
}


//  ------------------------------------------------------------------

void GMnu::SetPos(int row, int col, int width, int height) {

  beginrow = row;
  begincolumn = col;
  beginwidth = width;
  beginheight = height;
}


//  ------------------------------------------------------------------

void GMnu::SetEsc(int option) {

  escape = option;
}


//  ------------------------------------------------------------------

void GMnu::SetHelp(int help) {

  helpnumber = help;
}


//  ------------------------------------------------------------------

void GMnu::SetMask(int mask) {

  itemmask = mask;
}


//  ------------------------------------------------------------------

void GMnu::SetTag(int tag) {

  stack[depth].tag = tag;
}


//  ------------------------------------------------------------------

void GMnu::Begin(int type) {

  bool was_horz = make_bool(stack[depth].type & M_HORZ);
  depth++;
  stack[depth].tag = -1;
  stack[depth].type = type | M_SAVE;
  stack[depth].winrow = (beginrow != -1) ? beginrow : (was_horz ? stack[depth-1].winrow+1 : stack[depth-1].winrow+stack[depth-1].itemrow);
  stack[depth].wincolumn = (begincolumn != -1) ? begincolumn : (stack[depth-1].wincolumn+(was_horz?0:1));
  stack[depth].itemrow = stack[depth].itemcolumn = 0;
  status = wmenubeg_(
    stack[depth].winrow,
    stack[depth].wincolumn,
    beginheight,
    beginwidth,
    bordertype,
    bordercolor,
    textcolor,
    menuopen,
    stack[depth].type
  );
  wmenutitshad(title, titlepos, titlecolor, shadowcolor);
  beginwidth = beginheight = 0;
  beginrow = begincolumn = -1;
}


//  ------------------------------------------------------------------

void GMnu::End() {

  status = wmenuend(stack[depth].tag, stack[depth].type, (stack[depth].type&M_VERT)?255:0, 0, textcolor, quickcolor, noselcolor, barcolor);
  depth--;
  if((depth >= 0) and (stack[depth].type & M_HORZ))
    stack[depth].wincolumn += stack[depth].winwidth;
  title = NULL;
}


//  ------------------------------------------------------------------

extern int _overtagid;
extern int _finaltagid;

void GMnu::Start() {

  int _prev_escape = wsetesc(escape);
  wmenuget();
  finaltag = _finaltagid;
  overtag = _overtagid;
  wsetesc(_prev_escape);
}


//  ------------------------------------------------------------------

void GMnu::Item(int tag, const char* text) {

  Item(tag, text, itemmask, NULL, 0);
}


//  ------------------------------------------------------------------

void GMnu::Item(int tag, const char* text, int fmask) {

  Item(tag, text, fmask, NULL, 0);
}


//  ------------------------------------------------------------------

void GMnu::Item(int tag, const char* text, VfvCP select, int fmask) {

  Item(tag, text, fmask, select, 0);
}


//  ------------------------------------------------------------------

void GMnu::Item(int tag, const char* text, int fmask, VfvCP select, gkey hotkey) {

  if(stack[depth].tag == -1)
    stack[depth].tag = tag;

  char shortcut = *text;

  for(_item_t* p = gwin.cmenu->item; p; p = p->prev) {
    if(p->schar == shortcut)
      shortcut = NUL;
  }

  status = wmenuitem(stack[depth].itemrow, stack[depth].itemcolumn, text+1, shortcut, tag, fmask, select, hotkey, helpnumber);
  stack[depth].winwidth = strlen(text+1);
  if(stack[depth].type & M_HORZ)
    stack[depth].itemcolumn += stack[depth].winwidth;
  else
    stack[depth].itemrow++;
}


//  ------------------------------------------------------------------

void GMnu::ItemDesc(const char* text) {

  status = wmenuitxt(deschdl, descrow, desccolumn, desccolor, text);
}


//  ------------------------------------------------------------------

void GMnu::ItemSep()
{
  Item(-1, " ", M_SEPAR, NULL, 0);
}


//  ------------------------------------------------------------------

void GMnu::ItemFuncs(VfvCP before, VfvCP after) {

  status = wmenuiba(before, after);
}


//  ------------------------------------------------------------------

void GMnu::SetNextItem(int tag) {

  status = wmenuinext(tag);
}


//  ------------------------------------------------------------------

void GMnu::DisableItem(int tag) {

  status = wmenuidsab(tag);
}


//  ------------------------------------------------------------------

void GMnu::EnableItem(int tag) {

  status = wmenuienab(tag);
}


//  ------------------------------------------------------------------

GMnuItm* GMnu::FindItem(int tag) {

  return wmenuifind(tag);
}


//  ------------------------------------------------------------------
