
/* "WOL", an integrated circuit layout tool,
   Copyright (C) 1983, 1990 California Institute of Technology.
   Author: Massimo Sivilotti
   Thanks to: Glenn Gribble, Marty Sirkin, Sylvie Rychebusch
	      Maryann Mayer, Carver Mead, Rick Koshi, Torre Lande
   Maintainer: John Lazzaro
   Maintainers's address: lazzaro@hobiecat.cs.caltech.edu;
                          CB 425/ CU Boulder/Boulder CO 91125. 
			  Send questions, bug fixes, to this address.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation (Version 1, 1989).

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* Output from p2c, the Pascal-to-C translator */
/* p2c: wolopt.text, line 9: Note: Range checking is OFF [216] */
/* p2c: wolopt.text, line 10: Note: Stack checking is OFF [217] */
/* p2c: wolopt.text, line 16: Note: Range checking is ON [216] */
/* From input file "wol_menu.text" */


/* Change these for testing */



#include "global.h"


#define WOL_MENU_G
#include "wol_menu.h"


void new_menu(Char *name, _PROCEDURE tproc, _PROCEDURE init, _PROCEDURE exit)
{
  menu_curr = Malloc(sizeof(menu_head));
  strcpy(menu_curr->name, name);
  strcpy(menu_curr->modestr, name);
  menu_curr->modenum = -1;
  menu_curr->menu = NULL;
  menu_curr->tproc = tproc;
  menu_curr->init = init;
  menu_curr->exit = exit;
  menu_curr->next = all_menus;
  all_menus = menu_curr;

  menu_pos = 0;
}


/* Allocate a new menu at the start of menu_curr */
menu_rec *menu_add(Char *name, menu_kinds tag, short color, _PROCEDURE proc)
{
  menu_rec *Result, *p;

  p = Malloc(sizeof(menu_rec));
  strcpy(p->name, name);
  strcpy(p->lookup, name);
  p->color = color;
  p->selected = false;
  p->proc = proc;
  p->pos = menu_pos;
  p->tag = tag;
  p->UU.U0.null1 = 0;
  p->UU.U0.null2 = 0;
  p->head = menu_curr;
  p->next = menu_curr->menu;
  menu_curr->menu = p;
  Result = p;

  menu_pos++;
  menu_curr->squares = menu_pos;
  return Result;
}


void menu_show(void)
{
  menu_rec *p;
  long r;   /* right hand edge */
  short MENU_SQUARE_SIZE, MENU_LABEL_OFFSET;
  menu_rec *WITH;

  MENU_SQUARE_SIZE = END_OF_MENU / menu_curr->squares;
  MENU_LABEL_OFFSET = MENU_SQUARE_SIZE / 2;
  menu_erase = true;

  gsave();
  m_linestyle(0);
  m_choosefont(1);
  m_colormode(m_normal);
  p = menu_curr->menu;
  /*writeln('Menu: ',menu_curr^.name);*/
  while (p != NULL) {
    WITH = p;
    r = WITH->pos * MENU_SQUARE_SIZE;
    if (menu_erase) {
      m_color(BLACK);   /*m_color(0); */
      /*TOP_OF_SCREEN+5*/
      m_fillrect(r + 1, TOP_OF_SCREEN + 4, r + MENU_SQUARE_SIZE - 2,
		 MAX_TOP_OF_SCREEN - 1);
    }
    m_color(WITH->color);
    m_centerstr(r + MENU_LABEL_OFFSET, MAX_TOP_OF_SCREEN + MENU_LABEL_HEIGHT,
		NULL, WITH->name);
    if (WITH->selected)
      m_color(select_color);
    else
      m_color(border_color);
    m_drawrect(r, TOP_OF_SCREEN + 4, r + MENU_SQUARE_SIZE - 1,
	       MAX_TOP_OF_SCREEN);

    /*writeln(pos:5,'=',name,' @ ',color:1,' s=',selected:1,' p1=',p1:1);*/
    p = WITH->next;
  }

  /* Clear all of the color/mode display */
  m_color(BLACK);   /*m_color(0);*/
  m_fillrect(menu_curr->squares * MENU_SQUARE_SIZE, TOP_OF_SCREEN + 4,
	     RIGHT_OF_SCREEN, MAX_TOP_OF_SCREEN);

  set_layer(curr_layer);   /* Reset to normal layer */
  draw_wire_box(RIGHT_OF_SCREEN - 48, TOP_OF_SCREEN + 10,
		RIGHT_OF_SCREEN - 38, TOP_OF_SCREEN + 19);
      /* Display layer box */
  m_color(BR_WHITE);   /*m_color(7);*/
  m_rightstr(RIGHT_OF_SCREEN, MAX_TOP_OF_SCREEN + MENU_LABEL_HEIGHT, NULL,
	     menu_curr->modestr);

  menu_erase = false;
  grestore();
}


void menu_press(menu_rec *item)
{
  if (item == NULL) {
    printf("menu_press: item=NIL\n");
    return;
  }
  if (item->proc.link != NULL)
    ((void(*)(menu_rec *mp, void *_link))item->proc.proc)(item, item->proc.link);
  else
    ((void(*)(menu_rec *mp))item->proc.proc)(item);
}


/* Return true if pen was within menu area */
boolean menu_check(long x, long y)
{
  boolean Result;
  menu_rec *mp;
  long sq;
  short MENU_SQUARE_SIZE;

  MENU_SQUARE_SIZE = END_OF_MENU / menu_curr->squares;

  Result = false;
  if (y < TOP_OF_SCREEN + 4)
    return Result;
  Result = true;

  sq = x / MENU_SQUARE_SIZE;
  if ((unsigned long)sq >= menu_curr->squares)
    return Result;
  mp = menu_curr->menu;
  while (mp != NULL) {
    if (mp->pos != sq) {
      mp = mp->next;
      continue;
    }
    if (mp->proc.link != NULL)
      ((void(*)(menu_rec *mp, void *_link))mp->proc.proc)(mp, mp->proc.link);
    else
      ((void(*)(menu_rec *mp))mp->proc.proc)(mp);
    mp = NULL;
    menu_show();
  }
  return Result;
}


/* Radio button procedure */
Static void p_radio(menu_rec *mp)
{
  menu_rec *p, *WITH;

  p = mp->head->menu;
  while (p != NULL) {   /* Turn off all radio buttons */
    WITH = p;
    if (mp->tag == mn_radio || mp->tag == mn_radio2)
      WITH->selected = false;
    p = WITH->next;
  }
  mp->selected = true;
  mp->head->tproc = mp->UU.tproc;
  mp->head->modenum = -1;
  *mp->head->modestr = '\0';
}


/* Double-Radio button procedure */
Static void p_radio2(menu_rec *mp)
{
  menu_submoderec *WITH;

  if (mp->selected) {
    WITH = mp->UU.more;
    WITH->mode = (WITH->mode + 1) % WITH->nummodes;
/* p2c: wol_menu.text, line 328:
 * Note: Using % for possibly-negative arguments [317] */
    if (disable_heirarchy && !strcmp(WITH->modes[WITH->mode], "ALL"))
    {   /* MAS */
      WITH->mode = (WITH->mode + 1) % WITH->nummodes;
/* p2c: wol_menu.text, line 330:
 * Note: Using % for possibly-negative arguments [317] */
    }
  }
  p_radio(mp);
  mp->head->modenum = mp->UU.more->mode;
  strcpy(mp->head->modestr, mp->UU.more->modes[mp->head->modenum]);
  mp->head->t2proc = mp->UU.more->t2proc;
}


/* Boolean toggle procedure */
Static void p_bool(menu_rec *mp)
{
  *mp->UU.boolp = !*mp->UU.boolp;
  mp->selected = *mp->UU.boolp;
}


menu_head *menu_find(Char *name)
{
  menu_head *Result, *p;

  Result = NULL;
  p = all_menus;
  while (p != NULL) {
    if (strcmp(p->name, name))
      p = p->next;
    else {
      Result = p;
      p = NULL;
    }
  }
  return Result;
}


menu_rec *menu_find_item(menu_head *menu, Char *name)
{
  menu_rec *p, *f;

  f = NULL;
  if (menu == NULL) {
    printf("menu_find_item: menu=NIL (name=%s)\n", name);
    return f;
  }
  p = menu->menu;
  while (p != NULL && f == NULL) {
    if (!strcmp(p->lookup, name))
      f = p;
    p = p->next;
  }
  if (f == NULL)
    printf("menu_find_item: could not find \"%s\" in %s\n", name, menu->name);
  return f;
}


void menu_change(Char *newmenu_)
{
  Char newmenu[8];
  menu_head *p;

  strcpy(newmenu, newmenu_);
  p = menu_find(newmenu);
  if (p == NULL) {
    printf("Could not find menu \"%s\"\n", newmenu);
    return;
  }
  menu_prev = menu_curr;
  if (menu_curr->exit.link != NULL)
    ((void(*)(void *_link))menu_curr->exit.proc)(menu_curr->exit.link);
  else
    ((void(*)(void))menu_curr->exit.proc)();
  menu_curr = p;
  if (menu_curr->init.link != NULL)
    ((void(*)(void *_link))menu_curr->init.proc)(menu_curr->init.link);
  else
    ((void(*)(void))menu_curr->init.proc)();
  menu_erase = true;
}


/* Menu change procedure */
Static void p_menu(menu_rec *mp)
{
  menu_change(mp->UU.strp);
}


void add_radio(Char *name, short color, _PROCEDURE tproc)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_radio;
  TEMP.link = NULL;
  p = menu_add(name, mn_radio, color, TEMP);
  p->UU.tproc = tproc;
}


void add_radio2(Char *name, short color, _PROCEDURE t2proc, short nummodes,
		Char (*modes)[8])
{
  /* Tablet/submode proc */
  /* How many alternate modes */
  /* Array of names */
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_radio2;
  TEMP.link = NULL;
  p = menu_add(name, mn_radio2, color, TEMP);
  p->UU.more = Malloc(sizeof(menu_submoderec));
  p->UU.more->t2proc = t2proc;
  p->UU.more->mode = 0;
  if (disable_heirarchy && !strcmp(modes[p->UU.more->mode], "ALL")) {
	/* MAS */
	  p->UU.more->mode = (p->UU.more->mode + 1) % nummodes;
/* p2c: wol_menu.text, line 421:
 * Note: Using % for possibly-negative arguments [317] */
  }
  p->UU.more->nummodes = nummodes;
  p->UU.more->modes = modes;
}


void add_bool(Char *name, short color, boolean *boolvar)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_bool;
  TEMP.link = NULL;
  p = menu_add(name, mn_bool, color, TEMP);
  p->UU.boolp = boolvar;
}


/* Layers drc toggle procedure */
Static void p_drc(menu_rec *mp)
{
  short bloat_size;

  alpha_screen(CLR);
  m_alpha_on();
  *mp->UU.boolp = !*mp->UU.boolp;
  mp->selected = *mp->UU.boolp;
  if (*mp->UU.boolp) {
    printf("Bloat amount in 1/2 lambda? [%d] ",
	   layers[mp->color - min_layer].bloat);
    TRY(try1);
      scanf("%hd%*[^\n]", &bloat_size);
/*      getchar();*/
      nk_getkey();
      printf("Bloating layer %12d by %12d half lambda.\n",
	     mp->color, bloat_size);
      layers[mp->color - min_layer].bloat = bloat_size;
    RECOVER(try1);
      printf("Bad bloat size\n");
    ENDTRY(try1);
  }
  m_alpha_off();
}


void add_drc(Char *name, short color)
{
  /* needs to be mn_bool in order to modify bloats_on */
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_drc;
  TEMP.link = NULL;
  p = menu_add(name, mn_bool, color, TEMP);
  p->UU.boolp = &bloats_on[color - min_layer];
}




/* Layers display toggle procedure */
Static void p_display(menu_rec *mp)
{
  *mp->UU.boolp = !*mp->UU.boolp;
  mp->selected = *mp->UU.boolp;
  show_comp();
}


void add_display(Char *name, short color)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_display;
  TEMP.link = NULL;
  p = menu_add(name, mn_bool, color, TEMP);
  p->UU.boolp = &layers_on[menu_pos - min_layer];
}


Static void p_layer(menu_rec *mp)
{
  menu_rec *p, *WITH;

  p = mp->head->menu;
  while (p != NULL) {
    WITH = p;
    if (WITH->tag == mn_layer)
      WITH->selected = false;
    p = WITH->next;
  }
  mp->selected = true;
  curr_layer = mp->UU.layer;
  if (!strcmp(menu_prev->name, "Main") || !strcmp(menu_prev->name, "Build")) {
    menu_press(menu_find_item(menu_find("Build"), "ADD"));
    menu_change("Build");
    return;
  }
  if (!strcmp(menu_prev->name, "BuildC")) {
    menu_press(menu_find_item(menu_find("BuildC"), "ADD"));
    menu_change("BuildC");
  } else
    menu_change(menu_prev->name);
}


void add_mlayer(Char *name, short color, short layer)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_layer;
  TEMP.link = NULL;
  p = menu_add(name, mn_layer, color, TEMP);
  p->UU.layer = layer;
}


Static void p_action(menu_rec *mp)
{
  if (mp->UU.aproc.link != NULL)
    ((void(*)(void *_link))mp->UU.aproc.proc)(mp->UU.aproc.link);
  else
    ((void(*)(void))mp->UU.aproc.proc)();
}


void add_action(Char *name, short color, _PROCEDURE proc)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_action;
  TEMP.link = NULL;
  p = menu_add(name, mn_action, color, TEMP);
  p->UU.aproc = proc;
}


void add_menuchange(Char *name, Char *newmenu)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_menu;
  TEMP.link = NULL;
  p = menu_add(name, mn_change, 1, TEMP);
  p->UU.strp = Malloc(8);
  strcpy(p->UU.strp, newmenu);
}


void add_menuchangeVar(Char *name, Char *newmenu)
{
  menu_rec *p;
  _PROCEDURE TEMP;

  TEMP.proc = p_menu;
  TEMP.link = NULL;
  p = menu_add(name, mn_change, 1, TEMP);
  p->UU.strp = newmenu;
}


/* module wol_menu */



/* End. */
