
/* "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 "wolmain.text" */


/* Change these for testing */

/*$debug on$*/


#include "global.h"


/*IMPORT asm, sysglobals, fs, misc, sysdevs, hpib_2, hpib_1, general_1,
       general_2, filepack, newkbd, citinfomod, newci, mylib, newasm,  */

#ifndef NEWASM_H
#include <p2c/newasm.h>
#endif

#ifndef SYSGLOBALS_H
#include <p2c/sysglobals.h>
#endif

/*homeless orphans*/

#ifndef FILEPACK_H
#include <p2c/filepack.h>
#endif

#ifndef NEWKBD_H
#include <p2c/newkbd.h>
#endif

#ifndef NEWCI_H
#include <p2c/newci.h>
#endif

#ifndef MYLIB_H
#include <p2c/mylib.h>
#endif

#ifndef WOL_GRAPHICS_H
#include "wol_graphics.h"
#endif

#ifndef WOL_ASM_H
#include "wol_asm.h"
#endif

#ifndef HPGL_PLOTTER_H
#include "hpgl_plotter.h"
#endif

#ifndef TIMING_H
#include "timing.h"
#endif

#ifndef LAYER_STUFF_H
#include "layer_stuff.h"
#endif

/* Lots of the tablet stuff. */

#ifndef TABLET_STUFF_H
#include "tablet_stuff.h"
#endif

#ifndef MESSAGE_STUFF_H
#include "message_stuff.h"
#endif

/* define the major cell stuff in use */

#ifndef CELL_STUFF_H
#include "cell_stuff.h"
#endif

#ifndef NAME_STUFF_H
#include "name_stuff.h"
#endif

#ifndef WOL_HEADER_H
#include "wol_header.h"
#endif

#ifndef WOL_GRAPHICS_2_H
#include "wol_graphics_2.h"
#endif

#ifndef WOL_ROUTE_H
#include "wol_route.h"
#endif

#ifndef WOL_MENU_H
#include "wol_menu.h"
#endif

#ifndef WOL_INITIALIZE_H
#include "wol_initialize.h"
#endif

#ifndef WOL_OPTIONS_H
#include "wol_options.h"
#endif

#ifndef WOL_CIF_H
#include "wol_cif.h"
#endif

#ifndef WOL_CMD_H
#include "wol_cmd.h"
#endif

#ifndef EXT_DEFS_H
#include "ext_defs.h"
#endif

#ifndef WOL_XTRACT_H
#include "wol_xtract.h"
#endif

#ifndef WOL_DRC_H
#include "wol_drc.h"
#endif

/*$if COM68020$
       $search '/BIN/NEWCRT300'$ newcrt;
$end$*/

#ifndef NEWCRT_H
#include <p2c/newcrt.h>
#endif


/*******************************************************************************/
Static boolean location;   /* Show location always? */


Static void setup_screen(void)
{
  nc_windowRec *WITH;

  if (!location) {
    nc_setWindow_(nc_defaultWindow);
    return;
  }
  WITH = nc_defaultWindow;
  nc_makeWindow(nc_tempWindow, WITH->top, WITH->height - 1, 0, WITH->width);
  nc_setWindow_(nc_tempWindow);
}


Static void shutdown_screen(void)
{
  nc_setWindow_(nc_defaultWindow);
}


Static void do_exit(void);


Static void full_graphics_redraw(void)
{
  big_graphics();
  clear_screen();
  do_refresh();
  menu_show();
  small_graphics();
}


Local void show_help_screen(void)
{
  Char STR2[52];

  sprintf(STR2, "                       WOL %s Keyboard  Commands", Version);
  show_message(STR2, true);
/* p2c: wolmain.text, line 230: Note: Characters >= 128 encountered [281] */
/* p2c: wolmain.text, line 230:
 * Note: WRITE statement contains color/attribute characters [203] */
  printf(
    "\n(A) Toggle AUTO-REFRESH mode        \214(^W) make suggestions for NEXTWOL\210\n");
  printf(
    "(F)   \"    FILL BOX mode            (P)   \"    Prompting cell/filenames\n");
  printf("(Q)   quick exit (same as X)        (D)   \"    DISPLAY PORTS mode\n");
  printf(
    "(M)   \"    Manhattan routing mode   (W)   \"    Fleshed-out routing mode\n");
  printf("(R) Force a screen refresh (SPACE does this also)\n");
  printf("(C) CLEAR Alpha screen              (G) REDRAW Graphics screen\n");
  printf("(Z) Zoom to window                  (5) Zoom back to top level\n");
  printf("()) PUSH a viewing transform        (^) POP a viewing transform\n");
  printf("(.) Push window only                (() Exchange top two transforms\n");
  printf("(Y) Draw ruler (yardstick)          (^G) Enter GRIPE system\n");
  printf("(#) execute a program               (!) SHELL escape  \n");
  printf("(=) display cursor coordinates      (@) center viewing window \n");
  printf("(L) LOAD CIF file                   (S) SAVE CIF file\n");
  printf("(+) Double zoom factor              (-) Halve zoom factor\n");
  printf("(TAB) Increment display style       (BACKTAB) Decrement display style  \n");
/* p2c: wolmain.text, line 247: Note: Characters >= 128 encountered [281] */
/* p2c: wolmain.text, line 247:
 * Note: WRITE statement contains color/attribute characters [203] */
  printf(
    "(E) Toggle Select algorithm sensitive to edges only\214   (V) point-to-point MOVE\210\n");
  printf("              <EXECUTE>  --  Manually select objects\n");
  printf("\n              arrow keys:  scroll by 1/20 screen. (Wheel also)\n");
  printf("              8, 2, 6, 4:  scroll by 1 page (N, S, E, W respectively)\n");
}


Static void do_check_pen(tablet_info *check_pen)
{
  unsigned char c;   /* character from typeahead, if any */
  double newzoom;
  tablet_info t_i;
  Char ans[81], ans2[81];
  cell *geommbb;
  comp_list *compmbb;
  double zoom1, zoom2;
  m_colorarray r, g, b;
  long junk, x, y;
  Char STR2[256];
  Char *TEMP, TEMP1;
  unsigned char lookahead;

  TRY(try1);
    gsave();
    xor_off();
    t_i = get_pen();
    *check_pen = t_i;   /* return tablet info, as required */
    if (!t_i.near_) {
      if (select_in_progress_g) {
	if (!strcmp(current_buffer_name, "GEOM"))
	  unhighlight_g(last_selected_object_g);
	recl_nodes(&select_list_head_g);
      }
      select_in_progress_g = false;
      last_selected_object_g = NULL;
      if (select_in_progress_c) {
	if (!strcmp(current_buffer_name, "COMP"))
	  unhighlight_c(last_selected_object_c);
	printf("WARNING: memory being wasted -- recl_c_c_cell\n");
	recl_c_c_cell(&select_list_head_c);
      }
      select_in_progress_c = false;
      last_selected_object_c = NULL;
    }
    /* check type-ahead here, and take evasive action */
    if (nk_keybufsize() != 0) {   /* there is something in the type-ahead */
      c = nk_getkey();
/*      if (memavail() < min_mem_recurse * 5)
	show_message("Not enough memory to do keyboard commands in CHECK_PEN",
		     false);
      else {*/
	switch (c) {

	/* following commands are undocumented */
	case '*':
	  update_comp_mbb();
	  break;

	case '&':
	  disable_heirarchy = !disable_heirarchy;
	  if (disable_heirarchy)
	    show_message("Disable Heirarchy ON", true);
	  else
	    show_message("Disable Heirarchy OFF", true);
	  break;

	/* following commands are documented */
	case ')':
	  push_window();
	  break;

	case '^':
	  pop_window();
	  break;

	case 'Z':
	case 'z':
	case '.':
	  show_message("Draw window for ZOOM", true);
	  if (c == '.')
	    window_zoom(false);
	  else
	    window_zoom(true);
	  m_alpha_off();
	  break;

	case '(':
	  exchange_window();
	  break;

	case '=':
	  location = !location;
	  nk_screenhigh = 0;
	  alpha_screen(CLR);   /* clear screen */
	  nk_crtwritestr(0, 23, "", nk_screenwidth);
	  /* setup_screen(); */
	  break;

	case '@':
	  push_window();
	  m_graphics_off();
	  m_alpha_on();
	  printf("\n\nEnter (x,y) to center:  ");
	  fgets(ans, 81, stdin);
	  TEMP = strchr(ans, '\n');
	  if (TEMP != NULL)
	    *TEMP = 0;
	  TRY(try2);
	    sscanf(ans, "%ld%ld%ln", &x, &y, &junk);
	    junk++;

	    off_x = (x / 2 - (long)(RIGHT_OF_SCREEN / zoom)) / 2;
	    off_y = (y / 2 - (long)(TOP_OF_SCREEN / zoom)) / 2;
	    do_refresh();
	    menu_show();
	    m_alpha_off();
	  RECOVER(try2);
	    printf("Bad input format;  Try:  x y\n");
	    pop_window();
	  ENDTRY(try2);
	  m_graphics_on();
	  break;

	case '!':
	  /* m_seecolors(r, g, b);
	  m_graphics_off();
	  shutdown_screen();
	  TRY(try3);
	    newci_fullshellescape("", "I");
	  RECOVER(try3);
	    show_error("SHELL escape failed: ", false);
	  ENDTRY(try3);
	  setup_screen();
	  re_init_graphics();
	  m_setcolors(r, g, b);
	  full_graphics_redraw(); */
	  break;

	case '#':
       /* m_seecolors(r, g, b);
	  m_graphics_off();
	  m_alpha_on();
	  printf("\n\nEnter file to execute:  ");
	  fgets(ans, 81, stdin);
	  TEMP = strchr(ans, '\n');
	  if (TEMP != NULL)
	    *TEMP = 0;
	  shutdown_screen();
	  TRY(try4);
	    newci_fullshellescape(ans, "I");
	  RECOVER(try4);
	    show_error("SHELL escape failed: ", false);
	  ENDTRY(try4);
	  setup_screen();
	  re_init_graphics();
	  m_setcolors(r, g, b);
	  full_graphics_redraw(); */
	  break;

	case 'a':
	case 'A':
	  auto_refresh = !auto_refresh;
	  if (auto_refresh)
	    show_message("Auto refresh ON", true);
	  else
	    show_message("Auto refresh OFF", true);
	  break;

	case 'm':
	case 'M':
	  manhattan_routing = !manhattan_routing;
	  if (manhattan_routing)
	    show_message("Manhattan routing ON", true);
	  else
	    show_message("Manhattan routing OFF", true);
	  break;

	case 'w':
	case 'W':
	  fleshed_out_routing = !fleshed_out_routing;
	  if (!strcmp(current_buffer_name, "COMP"))
	    do_refresh();
	  else {
	    if (fleshed_out_routing)
	      show_message("Fleshed-out routing ON", true);
	    else
	      show_message("Fleshed-out routing OFF", true);
	  }
	  break;

	case 'r':
	case 'R':
	case ' ':  /* screen refresh only */
	  if (!strcmp(m_machine, "X"))
	    full_graphics_redraw();
	  else
	    do_refresh();
	  while ((TEMP1 = nk_testkey(0), TEMP1 == ' ' || TEMP1 == 'R' ||
					 TEMP1 == 'r'))
	    c = nk_getkey();
	  break;

	/*'b','B' :  begin    (B) Toggle DISPLAY MBB mode
	             bbox_nobbox := not bbox_nobbox;
	             disp_bb_nobb;
	             if auto_refresh then do_refresh;
	           end;      */
	case 'c':
	case 'C':
	  shutdown_screen();
	  alpha_screen(CLR);
	  setup_screen();
	  break;

	case '\007':
	  bitch_bitch_bitch("GRIPES.WOL");
	  break;

	case '\027':
	  bitch_bitch_bitch("IDEAS.WOL");
	  break;

	case 251:  /* screen resize , so reinit and refresh */
	  re_init_graphics();
	  full_graphics_redraw();
	  while ((lookahead = nk_testkey(0), lookahead == 250))
	    c = nk_getkey();
	  break;

	case 'g':
	case 'G':
	case 250:  /* erase and refresh graphics screen */
	  full_graphics_redraw();
	  break;

	case 'f':
	case 'F':
	  set_disp_style((disp_style + 1) & 1);
	  /* fill_boxes := not fill_boxes;   */
	  do_refresh();
	  menu_show();
	  break;

	case '\013':
	case '\t':
	  if (c == '\t') {
/* p2c: wolmain.text, line 416:
 * Note: Using % for possibly-negative arguments [317] */
	    set_disp_style((disp_style + 1) % numstyles);
	  } else {
/* p2c: wolmain.text, line 417:
 * Note: Using % for possibly-negative arguments [317] */
	    set_disp_style((disp_style - 1) % numstyles);
	  }
	  sprintf(STR2, "Current display style is %d", disp_style);
	  show_message(STR2, true);
	  do_refresh();
	  menu_show();
	  break;

	case '\b':
	case '\034':
	case '\n':
	case '\037':
	case '4':
	case '6':
	case '2':
	case '8':
	  /* scroll around */
	  waitfor(10000);   /* centiseconds, in order to accumulate events */
	  scroll_window(true, c);
	  break;

	case '5':
	  if (!strcmp(current_buffer_name, "GEOM")) {
	    TRY(try5);
	      geommbb = get_g_cell();
	      geommbb->data = main_;
	      set_bb(geommbb);
	      if ((geommbb->ur.x - geommbb->ll.x != 0) &&
		  (geommbb->ur.y - geommbb->ll.y != 0)) {
	      zoom1 = 0.95 * RIGHT_OF_SCREEN / (geommbb->ur.x - geommbb->ll.x);
	      zoom2 = 0.95 * TOP_OF_SCREEN / (geommbb->ur.y - geommbb->ll.y);
	      if (zoom1 >= zoom2)
		zoom = zoom2;
	      else
		zoom = zoom1;
	      if (zoom > 32.0)   /* clip */
		zoom = 32.0;
	      if (zoom > 1.0)
		zoom = (long)zoom;
	      izoom = (long)zoom;
	      intzoom = (zoom == izoom);

	      off_x = (geommbb->ll.x +
		       geommbb->ur.x - (long)(RIGHT_OF_SCREEN / zoom)) / 2;
	      off_y = (geommbb->ll.y +
		       geommbb->ur.y - (long)(TOP_OF_SCREEN / zoom)) / 2;}
	    RECOVER(try5);
	      ;
	    ENDTRY(try5);
	    geommbb->data = NULL;
	    recl_g_cell(&geommbb);
	    refresh_geom();
	  } else {  /* buffer = COMP */
	    TRY(try6);
	      compmbb = get_c_cell();
	      compmbb->data = comp_cells->data;
	      set_c_bb(compmbb);
	      if ((compmbb->ur.x - compmbb->ll.x != 0) &&
		  (compmbb->ur.y - compmbb->ll.y != 0)) {
	      zoom1 = 0.95 * RIGHT_OF_SCREEN / (compmbb->ur.x - compmbb->ll.x);
	      zoom2 = 0.95 * TOP_OF_SCREEN / (compmbb->ur.y - compmbb->ll.y);
	      if (zoom1 >= zoom2)
		zoom = zoom2;
	      else
		zoom = zoom1;
	      if (zoom > 32.0)   /* clip */
		zoom = 32.0;
	      if (zoom > 1.0)
		zoom = (long)zoom;
	      izoom = (long)zoom;
	      intzoom = (zoom == izoom);

	      off_x = (compmbb->ll.x +
		       compmbb->ur.x - (long)(RIGHT_OF_SCREEN / zoom)) / 2;
	      off_y = (compmbb->ll.y +
		       compmbb->ur.y - (long)(TOP_OF_SCREEN / zoom)) / 2; }
	    RECOVER(try6);
	      ;
	    ENDTRY(try6);
	    compmbb->data = NULL;
	    recl_c_cell(&compmbb);
	    do_refresh();
	  }
	  /* writeln ('zoom = ',zoom:0:2, '  off_x = ',off_x:0, '  off_y = ',off_y:0);  */
	  break;

	case '+':
	case '-':
	case '<':
	case '>':
	  newzoom = zoom;
	  waitfor(10);
	  do {
	    if (c == '>' || c == '+')
	      newzoom = 2 * newzoom;
	    else
	      newzoom /= 2;
	    if (nk_keybufsize() == 0)
	      waitfor(20);
	    TEMP1 = nk_testkey(0);
	    if (TEMP1 == '>' || TEMP1 == '<' || TEMP1 == '-' || TEMP1 == '+')
	      c = nk_getkey();
	    else
	      c = '\0';
	  } while (c == '>' || c == '<' || c == '-' || c == '+');

	  zoom_it(newzoom);
	  break;

	case 'P':
	case 'p':
	  prompt_cellname = !prompt_cellname;
	  prompt_filename = prompt_cellname;
	  if (prompt_cellname)
	    show_message("Cell/Filename prompting ON", true);
	  else
	    show_message("Cell/Filename prompting OFF", true);
	  break;

	case 'd':
	case 'D':
	  display_ports = !display_ports;
	  if (display_ports)
	    show_message("Port Display ON", true);
	  else
	    show_message("Port Display OFF", true);
	  do_refresh();
	  break;

	case 'E':
	case 'e':
	  edges_only = !edges_only;
	  if (edges_only)
	    show_message("Select sensitive to edges ONLY", true);
	  else
	    show_message("Select sensitive to whole object", true);
	  break;

	case 'V':
	case 'v':
	  point_to_point_move = !point_to_point_move;
	  if (point_to_point_move)
	    show_message("Point-to-point MOVE is ON", true);
	  else
	    show_message("Point-to-point MOVE is OFF", true);
	  break;

	case 'L':
	case 'l':
	  show_message("LOAD CIF file --", true);
	  printf("   Enter file name: ");
	  fgets(ans, 81, stdin);
	  TEMP = strchr(ans, '\n');
	  if (TEMP != NULL)
	    *TEMP = 0;
	  read_cif_file(ans);
	  break;

	case 'S':
	case 's':
	  show_message("SAVE CIF file --", true);
	  printf("   Enter cell to save: ");
	  fgets(ans, 81, stdin);
	  TEMP = strchr(ans, '\n');
	  if (TEMP != NULL)
	    *TEMP = 0;
	  printf("   Enter file name:    ");
	  fgets(ans2, 81, stdin);
	  TEMP = strchr(ans2, '\n');
	  if (TEMP != NULL)
	    *TEMP = 0;
	  write_cif_file(ans2, ans);
	  break;

	case '\003':  /* EXECUTE pressed -- manual select mode */
	  if (ok_to_select) {
	    if (!strcmp(current_buffer_name, "GEOM")) {
	      if (!select_in_progress_g) {
		if (last_moved != NULL)
		  reinstate();
		select_in_progress_g = true;
		t_i = scale(t_i, 3);
		select_pen_position_g = change_to_point(t_i.x, t_i.y);
		select_pen_position_g = scale_down(select_pen_position_g);
		/* writeln ('Selecting objects at : ',
		          select_pen_position_g.x:0,', ',
		          select_pen_position_g.y:0);  */
		find_all_possible_objects(select_pen_position_g);
	      }
	      select_object(select_pen_position_g);
	    } else if (!strcmp(current_buffer_name, "COMP")) {
	      if (!select_in_progress_c) {
		select_in_progress_c = true;
		t_i = scale(t_i, 3);
		select_pen_position_c = change_to_point(t_i.x, t_i.y);
		select_pen_position_c = scale_down(select_pen_position_c);
		/* writeln ('Selecting objects at : ',
		          select_pen_position_c.x:0,', ',
		          select_pen_position_c.y:0);   */
		find_all_possible_objects(select_pen_position_c);
	      }
	      select_object(select_pen_position_c);
	    }
	  }
	  break;

	case 'Y':
	case 'y':  /* yardstick function */
	  show_message("Press pen twice in grid area for ruler:", true);
	  t_i = track();
	  do_ruler(change_to_point(t_i.x, t_i.y));
	  break;

	case 'q':
	case 'Q':
	case 'x':
	case 'X':
	  quit = true;
	  do_exit();
	  if (quit) {
	    P_escapecode = -1;
	    goto _Ltry1;
	  }
	  show_message("Press pen or STOP to exit", true);
	  break;

	case '?':
	case '/':
	case 'h':
	case 'H':
	  show_help_screen();
	  break;

	default:   /* must be garbage, so be safe */
	  nk_keybufclear();
	  show_help_screen();
	  break;
        }
 /*     }*/
    }
  RECOVER2(try1,_Ltry1);
    if (P_escapecode == 10)
      _Escape(10);
    else {
      show_error("ERROR in Check_pen:", false);
      _Escape(P_escapecode);
    }
  ENDTRY(try1);
  grestore();
}


Static void do_nothing(void)
{
  printf("Nothing here \n");
}


Static void do_debug_geom(void)
{
  show_message("Dump of geom data structure:", true);
  dump_geom_data(main_, NULL, 0);
}


Static void do_debug_gcell(void)
{
  show_message("Dump of defined geom cells list:", true);
  dump_geom_cells_list(geom_cells);
}


Static void do_debug_ccell(void)
{
  show_message("Dump of comp buffer:", true);
  dump_comp_data(comp_cells);
}


Static void do_debug_comp(void)
{
  show_message("Dump of defined comp cells list:", true);
  dump_comp_cells_contents(comp_cells);
}


Static void do_debug_make(void)
{
  Char ch;

  show_message("Making buffer into cell:", true);
  printf("     Make Geometry buffer or Composition buffer? (G/C) ");
/*  ch = getchar();*/
  ch = nk_getkey();
  if (ch == '\n')
    ch = ' ';
  switch (ch) {

  case 'g':
  case 'G':
    make_cell();
    break;

  case 'c':
  case 'C':
    make_comp();
    break;
  }
}


Static void do_debug_wcomp(void)
{
  if (yes_no_quest("\n\015Individually DUMP only modified cells  "))
    dump_cells_independently(false, false);
  else
    dump_cells_independently(
      yes_no_quest("\n\015Individually DUMP ALL geometry cells   "),
      yes_no_quest("\n\015Individually DUMP ALL composition cells"));
}


Static void do_debug_flush(void)
{
  printf("flush is not supported anymore.\n");
  if (false) {
    restart_wol();
    do_refresh();
  }
}


Static void debug_init(void)
{
  ok_to_select = false;
}


Static void debug_exit(void)
{
  ok_to_select = true;
  m_graphics_on();
}


Static void do_exit(void)
{
  alpha_screen(CLR);
  m_alpha_on();
  show_modified();
  if (!cells_modified)
    quit = true;
  else {
    printf("\n\n\n\n\n");
    quit = yes_no_quest("      Are you \213SURE\210 you want to exit");
/* p2c: wolmain.text, line 667: Note: Characters >= 128 encountered [281] */
  }
}


Static void add_blank(void)
{
  _PROCEDURE TEMP;

  TEMP.proc = do_nothing;
  TEMP.link = NULL;
  add_action("", 0, TEMP);
}


Static void mp_ignore(point start)
{
  /*writeln('Ignored pen press at ',x:1,',',y:1);*/
}


Static void mp_exitdisp(point start)
{
  menu_change(menu_prev->name);
  menu_show();
}


Static void mp_exitdrc(point start)
{
  menu_change(menu_prev->name);
  menu_show();
}


Static void mp_noinit(void)
{
  /*writeln('Initializing "',menu_curr^.name,'"');*/
}


Static void mp_initcomp(void)
{
  /*writeln('Comp-Initializing "',menu_curr^.name,'"');*/
  strcpy(comp_menu, menu_curr->name);
  if (strcmp(current_buffer_name, "COMP")) {
    set_buffer("COMP");
    do_refresh();
  }
}


Static void mp_noexit(void)
{
  /*writeln('Exiting "',menu_curr^.name,'"');*/
}


/*******************************************************************************/

Static void mp_initgeom(void)
{
  /*writeln('Geom-Initializing "',menu_curr^.name,'"');*/
  if (strcmp(current_buffer_name, "GEOM")) {
    set_buffer("GEOM");
    refresh_geom();
  }
}


Static void geom_pop(void)
{
  immediate_make_cell();
  menu_change("Poke");
}


Static void geom_add(point start)
{
  modify(GEOM);
  set_layer(curr_layer);   /* force correct stuff */
  make_wire(start, curr_layer);
}


Static void geom_move(point start, short modenum, Char *modename)
{
  move_obj(start, modenum, modename);
  /* Until the menu system is fixed... */
  if (last_moved != NULL)
    reinstate();
}


/* Something needs to be done for copy and poked open cells */
Static void comp_copy(point start)
{
  /* if any_cells_open then <close_poked_cells; do_refresh> */
  if (close_poked_cells() && !auto_refresh)
    do_refresh();
  copy_comp(start);
}


Static void comp_scroll(void)
{
  m_nocursor();
  show_message("Type any keyboard character to exit SCROLL mode.", true);
  scroll_window(false, '\0');
}


Static void comp_clear(void)
{
  clear_comp();
}


Static void elec_strch(point start)
{
  ok_to_select = false;
  printf("A silly procedure that does not work has been called.\n");
  ok_to_select = true;
}


Static void do_data(void)
{
  show_message("Dump of data structure:", true);
  dump_geom_data(main_, NULL, 0);
}


Static void opt_init(void)
{
  debug_init();
}


Static void opt_exit(void)
{
  debug_exit();
}


Static void layer_init(void)
{
  menu_rec *p, *WITH;

  p = menu_curr->menu;
  while (p != NULL) {
    WITH = p;
    strcpy(WITH->name, layers[WITH->pos - min_layer + 1].menu_name);
    if (layers[WITH->pos - min_layer + 1].styles[0].fstyle != -1)
      WITH->color = layers[WITH->pos - min_layer + 1].styles[0].fcolor;
    else
      WITH->color = layers[WITH->pos - min_layer + 1].styles[0].color;
    p = p->next;
  }
  ok_to_select = false;
}


Static void layer_exit(void)
{
  ok_to_select = true;
}


Static void Drc_menu_exit(void)
{
  drc_cleanup();
  printf("Exiting DRC menu\n");
}


Static void Drc_menu_init(void)
{
  drc_cleanup();
  drc_init();
  printf("Ready for DRC\n");
}


Static void Xtract_menu_exit(void)
{
  Char obuffer[6];

  if (!in_extract)
    return;
  xtr_free_mem();
  strcpy(obuffer, current_buffer_name);
  set_buffer("COMP");
  display_buffers[current_buffer].refresh.proc = show_comp;
  display_buffers[current_buffer].refresh.link = NULL;
  set_buffer(obuffer);
  in_extract = false;
}


Static void Xtract_refresh(void)
{
  if (strcmp(menu_curr->name, "Xtract")) {
    Xtract_menu_exit();   /* Remove this display routine */
    show_comp();
    return;
  }
  if (in_extract && xtr_display_nodes)
    draw_boxes();
  else
    show_comp();
}


Static void Xtract_menu_init(void)
{
  mp_initcomp();
  /* Force a bounding box update, so coordinates will be right! */
  set_c_bb(comp_cells);
  display_buffers[current_buffer].refresh.proc = Xtract_refresh;
  display_buffers[current_buffer].refresh.link = NULL;
}


Static void disp_init(void)
{
  menu_rec *p, *WITH;

  layer_init();
  p = menu_curr->menu;
  while (p != NULL) {
    WITH = p;
    layers_on[WITH->pos - min_layer + 1] = WITH->selected;
    p = p->next;
  }
  do_refresh();
}


Static void disp_exit(void)
{
  short i;

  layer_exit();
  for (i = min_layer; i <= max_layer; i++)
    layers_on[i - min_layer] = true;
  do_refresh();
}


Static void opt_tech(void)
{
  Char name[fidleng + 1];
  Char *TEMP;

  alpha_screen(CLR);
  m_alpha_on();
  printf("\n\n\nCurrent technology is %s\n", technology);
  printf("New technology? ");
  fgets(name, fidleng + 1, stdin);
  TEMP = strchr(name, '\n');
  if (TEMP != NULL)
    *TEMP = 0;
  if (*name != '\0')
    read_tech_file(name);
  layer_dump();
}


Static void comp_bot(void)
{
  open_all_comp_cells(showing_geometry);
  showing_geometry = !showing_geometry;
  do_refresh();
}


Static void comp_top(void)
{
  if (close_poked_cells())
    do_refresh();
  showing_geometry = false;
}


Static void comp_edit(void)
{
  point start;
  c_cell *d_obj;
  tablet_info tp_d;

  show_message("Press pen on cell to edit", true);
  tp_d = track();
  if (tp_d.menu != 0)
    return;
  start = scale_down(change_to_point(tp_d.x, tp_d.y));
  d_obj = which_open_comp(comp_cells, start, zero_point);
  if (d_obj == NULL)
    return;
  switch (d_obj->tag) {

  case COMP:
    show_message("Cannot edit COMP cell", true);
    break;

  case GEOM:
    set_buffer("GEOM");
    immediate_new_main_cell(d_obj->UU.g_d->name);
    set_buffer("COMP");
    menu_change("BuildC");
    break;
  }
}


Static void draw_width(void)
{
  Char s[21];
  long junk, r;
  Char *STR1;
  Char *TEMP;

  alpha_screen(CLR);
  m_graphics_on();
  m_alpha_on();
  printf("\n\nEnter width of routing wires [%ld lambda]: ", wire_width);
  fgets(s, 21, stdin);
  TEMP = strchr(s, '\n');
  if (TEMP != NULL)
    *TEMP = 0;
  if (*s != '\0') {
    TRY(try7);
      r = strtol(s, &STR1, 10);
      junk = STR1 - s + 1;
      wire_width = r;
    RECOVER(try7);
      if (P_escapecode != -10)
	_Escape(P_escapecode);
      printf("No change performed\n");
    ENDTRY(try7);
  }
  m_graphics_on();
  m_alpha_off();
}


Static void draw_edit(point start)
{
  edit_routing_wire(start);
}


/* Special boolean procedure for Xtract menu */
Static void p_xtr_nodes(menu_rec *mp)
{
  *mp->UU.boolp = !*mp->UU.boolp;
  mp->selected = *mp->UU.boolp;
  if (in_extract)   /* Let users know I changed something */
    do_refresh();
}


typedef Char btype[3][8];
typedef Char xfctype[8][8];
typedef Char xfetype[4][8];


const btype bconst = {
  "ALL", "ONE", "SEL"
};

/*  xfcconst= xfctype['0','R90','R180','R270','M0','M90','M180','M270']; */

const xfctype xfcconst = {
  "0", "R90", "R180", "R270", "MX", "M-XY", "MY", "MXY"
};

/*  xfeconst= xfetype['M270','R180','M0','M180'];  */

const xfetype xfeconst = {
  "R90", "R180", "MX", "MY"
};


Static void menu_setup(void)
{
  menu_rec *p;
  short lay, m_box;
  _PROCEDURE TEMP;
  _PROCEDURE TEMP1;
  _PROCEDURE TEMP2;

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_noinit;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Main", TEMP, TEMP1, TEMP2);
  add_menuchange("LAYER", "Layers");
  add_menuchange("BUILD", "Build");
  add_menuchange("ELEC", "Elec");
  add_menuchange("CELL", "Cell");
  add_menuchangeVar("COMP", comp_menu);
  strcpy(comp_menu, "Comp1");
  add_menuchange("OPTS", "Opts");
  add_blank();
  add_blank();
  add_menuchange("debug", "Debug");
  TEMP.proc = do_exit;
  TEMP.link = NULL;
  add_action("EXIT", 1, TEMP);
  menu_prev = menu_curr;

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initgeom;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Build", TEMP, TEMP1, TEMP2);
  TEMP.proc = geom_add;
  TEMP.link = NULL;
  add_radio("ADD", 7, TEMP);
  TEMP.proc = geom_move;
  TEMP.link = NULL;
  add_radio2("MOVE", 7, TEMP, 3, bconst);
  TEMP.proc = delete_obj;
  TEMP.link = NULL;
  add_radio2("DEL", 7, TEMP, 3, bconst);
  TEMP.proc = copy_obj;
  TEMP.link = NULL;
  add_radio2("COPY", 7, TEMP, 3, bconst);
  TEMP.proc = edit_obj;
  TEMP.link = NULL;
  add_radio("EDIT", 7, TEMP);
  TEMP.proc = undel_obj;
  TEMP.link = NULL;
  add_action("UNDEL", 7, TEMP);
  TEMP.proc = zoom_in_out;
  TEMP.link = NULL;
  add_action("ZOOM", 7, TEMP);
  TEMP.proc = make_cell;
  TEMP.link = NULL;
  add_action("MAKE", 7, TEMP);
  add_menuchange("LAYER", "Layers");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "ADD"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initgeom;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("BuildC", TEMP, TEMP1, TEMP2);
  TEMP.proc = geom_add;
  TEMP.link = NULL;
  add_radio("ADD", 7, TEMP);
  TEMP.proc = geom_move;
  TEMP.link = NULL;
  add_radio2("MOVE", 7, TEMP, 3, bconst);
  TEMP.proc = delete_obj;
  TEMP.link = NULL;
  add_radio2("DEL", 7, TEMP, 3, bconst);
  TEMP.proc = copy_obj;
  TEMP.link = NULL;
  add_radio2("COPY", 7, TEMP, 3, bconst);
  TEMP.proc = edit_obj;
  TEMP.link = NULL;
  add_radio("EDIT", 7, TEMP);
  TEMP.proc = undel_obj;
  TEMP.link = NULL;
  add_action("UNDEL", 7, TEMP);
  TEMP.proc = zoom_in_out;
  TEMP.link = NULL;
  add_action("ZOOM", 7, TEMP);
  TEMP.proc = geom_pop;
  TEMP.link = NULL;
  add_action("pop", 1, TEMP);
  add_menuchange("LAYER", "Layers");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "ADD"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = layer_init;
  TEMP1.link = NULL;
  TEMP2.proc = layer_exit;
  TEMP2.link = NULL;
  new_menu("Layers", TEMP, TEMP1, TEMP2);
  m_box = 1;
  for (lay = min_layer; lay <= max_layer; lay++) {
    if (layers[lay - min_layer].styles[0].menu != 0) {
      add_mlayer(layers[lay - min_layer].menu_name, lay, m_box);
      m_box++;
    }
  }
  /* Warning, the next line must be executed after the build menu is defined */
  menu_press(menu_find_item(menu_curr, "POLY"));


  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initgeom;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Cell", TEMP, TEMP1, TEMP2);
  TEMP.proc = make_cell;
  TEMP.link = NULL;
  add_action("MAKE", 7, TEMP);
  TEMP.proc = list_cells;
  TEMP.link = NULL;
  add_action("LIST", 7, TEMP);
  TEMP.proc = append_cell;
  TEMP.link = NULL;
  add_action("APPEND", 7, TEMP);
  TEMP.proc = new_main_cell;
  TEMP.link = NULL;
  add_action("NEW", 7, TEMP);
  TEMP.proc = delete_cell;
  TEMP.link = NULL;
  add_action("ERASE", 7, TEMP);
  TEMP.proc = clear_main;
  TEMP.link = NULL;
  add_action("CLEAR", 7, TEMP);
  TEMP.proc = plot;
  TEMP.link = NULL;
  add_action("PLOT", 7, TEMP);
  /*add_action('ZOOM',7,zoom_in_out);*/
  add_menuchange("drc", "Drc");
  add_menuchange("BUILD", "Build");
  add_menuchange("MAIN", "Main");

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initgeom;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Elec", TEMP, TEMP1, TEMP2);
  TEMP.proc = get_elecnode;
  TEMP.link = NULL;
  add_radio("ELEC", 7, TEMP);
  TEMP.proc = xform_geom;
  TEMP.link = NULL;
  add_radio2("XFORM", 7, TEMP, 4, xfeconst);
  TEMP.proc = do_ruler;
  TEMP.link = NULL;
  add_radio("RULER", 7, TEMP);
  TEMP.proc = elec_strch;
  TEMP.link = NULL;
  add_radio("stretch", 7, TEMP);
  TEMP.proc = define_port;
  TEMP.link = NULL;
  add_radio("port", 7, TEMP);
  TEMP.proc = do_data;
  TEMP.link = NULL;
  add_action("data", 7, TEMP);
  add_blank();
  add_menuchange("drc", "Drc");
  add_menuchange("Build", "Build");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "RULER"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = Drc_menu_init;
  TEMP1.link = NULL;
  TEMP2.proc = Drc_menu_exit;
  TEMP2.link = NULL;
  new_menu("Drc", TEMP, TEMP1, TEMP2);
  TEMP.proc = get_elecnode;
  TEMP.link = NULL;
  add_radio("ELEC", 7, TEMP);
  TEMP.proc = do_geom_drc;
  TEMP.link = NULL;
  add_action("run drc", 7, TEMP);
  TEMP.proc = drc_test;
  TEMP.link = NULL;
  add_action("drctest", 7, TEMP);
  TEMP.proc = drc_init;
  TEMP.link = NULL;
  add_action("drcinit", 7, TEMP);
  TEMP.proc = drc_clean_cell;
  TEMP.link = NULL;
  add_action("cleanup", 7, TEMP);
  add_blank();
  add_blank();
  add_blank();
  add_menuchange("Build", "Build");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "ELEC"));


  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initcomp;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Comp1", TEMP, TEMP1, TEMP2);
  TEMP.proc = add_comp_cell;
  TEMP.link = NULL;
  add_action("ADD", 7, TEMP);
  TEMP.proc = move_comp;
  TEMP.link = NULL;
  add_radio("MOVE", 7, TEMP);
  TEMP.proc = del_comp;
  TEMP.link = NULL;
  add_radio("DEL", 7, TEMP);
  TEMP.proc = undelete_comp;
  TEMP.link = NULL;
  add_action("UNDEL", 7, TEMP);
  TEMP.proc = comp_copy;
  TEMP.link = NULL;
  add_radio("COPY", 7, TEMP);
  TEMP.proc = new_comp_cell;
  TEMP.link = NULL;
  add_action("NEW", 7, TEMP);
  TEMP.proc = make_comp;
  TEMP.link = NULL;
  add_action("MAKE", 7, TEMP);
  add_menuchange("POKE", "Poke");
  add_menuchange("DRAW", "Draw");
  add_menuchange("OTHER", "Comp2");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "MOVE"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initcomp;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Comp2", TEMP, TEMP1, TEMP2);
  TEMP.proc = xform_comp;
  TEMP.link = NULL;
  add_radio2("XFORM", 7, TEMP, 8, xfcconst);
  TEMP.proc = erase_comp;
  TEMP.link = NULL;
  add_action("ERASE", 7, TEMP);
  TEMP.proc = comp_clear;
  TEMP.link = NULL;
  add_action("CLEAR", 7, TEMP);
  TEMP.proc = zoom_in_out;
  TEMP.link = NULL;
  add_action("ZOOM", 7, TEMP);
  TEMP.proc = array_comp;
  TEMP.link = NULL;
  /*  add_action('SCROLL',7,comp_scroll); */
  add_action("ARRAY", 7, TEMP);
  TEMP.proc = get_comp_name;
  TEMP.link = NULL;
  add_radio("NAMES", 7, TEMP);
  TEMP.proc = list_comp_cells;
  TEMP.link = NULL;
  add_action("LIST", 7, TEMP);
  TEMP.proc = plot_comp;
  TEMP.link = NULL;
  add_action("PLOT", 7, TEMP);
  add_menuchange("OTHER", "Comp1");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "XFORM"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initcomp;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Poke", TEMP, TEMP1, TEMP2);
  TEMP.proc = poke_c_cells;
  TEMP.link = NULL;
  add_radio("POKE", 7, TEMP);
  TEMP.proc = comp_top;
  TEMP.link = NULL;
  add_action("TOP", 7, TEMP);
  TEMP.proc = comp_bot;
  TEMP.link = NULL;
  add_action("BOTT", 7, TEMP);
  TEMP.proc = do_ruler;
  TEMP.link = NULL;
  add_radio("RULER", 7, TEMP);
  TEMP.proc = plot_comp;
  TEMP.link = NULL;
  add_action("PLOT", 7, TEMP);
  TEMP.proc = comp_edit;
  TEMP.link = NULL;
  add_action("EDIT", 1, TEMP);
  add_menuchange("XTRACT", "Xtract");
  add_menuchange("LAYER", "Display");
  add_menuchange("COMP", "Comp1");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "POKE"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = Drc_menu_init;
  TEMP1.link = NULL;
  TEMP2.proc = Drc_menu_exit;
  TEMP2.link = NULL;
  new_menu("Drc2", TEMP, TEMP1, TEMP2);
  TEMP.proc = flash_comp_drc;
  TEMP.link = NULL;
  add_action("flash", 7, TEMP);
  TEMP.proc = show_comp_drc;
  TEMP.link = NULL;
  add_action("show", 7, TEMP);
  TEMP.proc = do_comp_drc;
  TEMP.link = NULL;
  add_action("run drc", 7, TEMP);
  TEMP.proc = do_comp_drc_window;
  TEMP.link = NULL;
  add_action("drc box", 7, TEMP);
  TEMP.proc = clean_comp_drc;
  TEMP.link = NULL;
  add_action("clean", 7, TEMP);
  add_bool("?wells?", 7, &drc_extensive);
  /*    add_blank;
      add_blank;
      add_blank;
      add_blank;       */
  add_menuchange("XTRACT", "Xtract");
  add_menuchange("MAIN", "Main");


  TEMP.proc = mp_Xtract;
  TEMP.link = NULL;
  TEMP1.proc = Xtract_menu_init;
  TEMP1.link = NULL;
  TEMP2.proc = Xtract_menu_exit;
  TEMP2.link = NULL;
  new_menu("Xtract", TEMP, TEMP1, TEMP2);
  TEMP.proc = xtractor;
  TEMP.link = NULL;
  add_action("XTRACT", 7, TEMP);
  TEMP.proc = flatten;
  TEMP.link = NULL;
  add_action("FLATTEN", 3, TEMP);
  TEMP.proc = p_xtr_nodes;
  TEMP.link = NULL;
  /*add_action('xtr_g',3,xtract_geom);*/
  /* Add a special boolean/action thing type */
  p = menu_add("NODES", mn_bool, 7, TEMP);
  p->UU.boolp = &xtr_display_nodes;
  p->selected = false;   /* xtr_display_nodes is OFF by default. */
  TEMP.proc = xtr_flash;
  TEMP.link = NULL;
  add_action("flash", 7, TEMP);
  xtr_debug = false;
  add_bool("debug", 7, &xtr_debug);
  add_bool("AREA", 7, &show_node_info);
  add_bool("SHORT", 7, &short_diodes);
  add_menuchange("drc", "Drc2");
  add_menuchange("COMP", "Comp1");
  add_menuchange("MAIN", "Main");

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = mp_initcomp;
  TEMP1.link = NULL;
  TEMP2.proc = mp_noexit;
  TEMP2.link = NULL;
  new_menu("Draw", TEMP, TEMP1, TEMP2);
  TEMP.proc = draw_routing_wire;
  TEMP.link = NULL;
  add_radio("DRAW", 7, TEMP);
  TEMP.proc = delete_routing_wire;
  TEMP.link = NULL;
  add_radio("DEL", 7, TEMP);
  TEMP.proc = draw_edit;
  TEMP.link = NULL;
  add_radio("EDIT", 7, TEMP);
  add_menuchange("LAYER", "Layers");
  TEMP.proc = draw_width;
  TEMP.link = NULL;
  add_action("WIDTH", 7, TEMP);
  TEMP.proc = do_ruler;
  TEMP.link = NULL;
  add_radio("RULER", 7, TEMP);
  add_blank();
  add_blank();
  add_menuchange("COMP", "Comp1");
  add_menuchange("MAIN", "Main");
  menu_press(menu_find_item(menu_curr, "DRAW"));

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = debug_init;
  TEMP1.link = NULL;
  TEMP2.proc = debug_exit;
  TEMP2.link = NULL;
  new_menu("Debug", TEMP, TEMP1, TEMP2);
  TEMP.proc = do_debug_geom;
  TEMP.link = NULL;
  add_action("geom", 7, TEMP);
  TEMP.proc = do_debug_gcell;
  TEMP.link = NULL;
  add_action("gcell", 7, TEMP);
  TEMP.proc = do_debug_ccell;
  TEMP.link = NULL;
  add_action("ccell", 7, TEMP);
  TEMP.proc = do_debug_comp;
  TEMP.link = NULL;
  add_action("comp", 7, TEMP);
  TEMP.proc = emerg_buffer_action;
  TEMP.link = NULL;
  add_action("emerg", 7, TEMP);
  TEMP.proc = user_options;
  TEMP.link = NULL;
  add_action("OPTS", 7, TEMP);
  TEMP.proc = do_debug_make;
  TEMP.link = NULL;
  add_action("make", 7, TEMP);
  TEMP.proc = do_debug_wcomp;
  TEMP.link = NULL;
  add_action("wcomp", 3, TEMP);
  TEMP.proc = do_debug_flush;
  TEMP.link = NULL;
  add_action("flush", 7, TEMP);
  add_menuchange("MAIN", "Main");

  TEMP.proc = mp_ignore;
  TEMP.link = NULL;
  TEMP1.proc = opt_init;
  TEMP1.link = NULL;
  TEMP2.proc = opt_exit;
  TEMP2.link = NULL;
  new_menu("Opts", TEMP, TEMP1, TEMP2);
  TEMP.proc = read_cif;
  TEMP.link = NULL;
  add_action("LOAD", 3, TEMP);
  TEMP.proc = write_cif;
  TEMP.link = NULL;
  add_action("SAVE", 3, TEMP);
  TEMP.proc = write_comp_ports;
  TEMP.link = NULL;
  add_action("PORTS", 3, TEMP);
  TEMP.proc = disp_memory;
  TEMP.link = NULL;
  add_action("MEM", 7, TEMP);
  TEMP.proc = list_cif_files;
  TEMP.link = NULL;
  add_action("DIR", 3, TEMP);
  TEMP.proc = user_options;
  TEMP.link = NULL;
  add_action("OPTS", 7, TEMP);
  TEMP.proc = save_config;
  TEMP.link = NULL;
  add_action("CNFG", 3, TEMP);
  TEMP.proc = opt_tech;
  TEMP.link = NULL;
  add_action("TECH", 3, TEMP);
  TEMP.proc = dump_all;
  TEMP.link = NULL;
  add_action("DUMP", 3, TEMP);
  add_menuchange("MAIN", "Main");

  TEMP.proc = mp_exitdisp;
  TEMP.link = NULL;
  TEMP1.proc = disp_init;
  TEMP1.link = NULL;
  TEMP2.proc = disp_exit;
  TEMP2.link = NULL;
  new_menu("Display", TEMP, TEMP1, TEMP2);
  m_box = 1;
  for (lay = min_layer; lay <= max_layer; lay++) {
    if (layers[lay - min_layer].styles[0].menu != 0) {
      add_display(layers[lay - min_layer].menu_name, lay);
      m_box++;
    }
  }
  /*      add_display('Poly',1);
        add_display('Wanna',2);
        add_display('Cracker',4);
        add_display('Diff',3);
        add_display('Cut',7);
        add_display('Metal2',15);
        add_display('Via',7);
        add_display('Boolean',6);
        add_display('Whoopee',14);
        add_display('Nol',10);
        add_display('Nolay',11);
        add_display('Nola',12);      */
}



Static tablet_info Ztr_pen(void)
{
  tablet_info t_i;
  point l, bp;
  Char s[81];
  long p;

  big_graphics();   /* Force this */
  do {

    XEvent foo;

    /* fake up blocking read, accounting for error in mylib
       that does not correctly eat EnterNotify and LeaveNotify events */
    XNextEvent(m_display, &foo);
    if ((foo.type != EnterNotify) && (foo.type != LeaveNotify))
      XPutBackEvent(m_display, &foo);


    t_i = check_pen();
    if (t_i.y > TOP_OF_SCREEN && t_i.x > END_OF_MENU)
      t_i.y = TOP_OF_SCREEN;
    if (t_i.y <= TOP_OF_SCREEN)
      t_i = scale(t_i, 3);
    if (cursor_on)
      m_cursor(t_i.x, t_i.y);
    if (location) {
      TRY(try8);
	bp.x = t_i.x;
	bp.y = t_i.y;
	l = scale_down(bp);
	sprintf(s, "Position: %ld,%ld lambda.", l.x, l.y);
	p = strlen(s) + 1;
	nk_screenhigh = 0;
	nk_crtwritestr(0, 23, s, nk_screenwidth);
	m_alpha_on();
      RECOVER(try8);
	show_error("ERROR in show_location:", false);
      ENDTRY(try8);
    }
  } while (!t_i.depressed);
  t_i.menu = 0;
  return t_i;
}


Static tablet_info Ztrack(void)
{
  tablet_info n_ti;

  debounce();   /* Make sure pen is up  */
  n_ti = Ztr_pen();   /* Track the pen */
  debounce();   /* Get the pen up again */
  if (n_ti.y <= TOP_OF_SCREEN + 3)
    n_ti.menu = 0;
  else
    n_ti.menu = 11;
  m_nocursor();
      /* GEG if the calling routine wants it, it will put it back */
  return n_ti;   /* Set the value of the  */
}


Static void trackit(void)
{
  point bogus_point;
  menu_head *WITH;

  quit = false;
  do {
    /*repeat
    {   m_trackpen(t);
    {until t.dn;*/

    debounce();
    pen_data = Ztrack();

    bogus_point.x = pen_data.x;
    bogus_point.y = pen_data.y;

    ok_to_select = false;
    if (!menu_check(pen_data.x, pen_data.y)) {
      WITH = menu_curr;
      if (WITH->modenum < 0) {
	if (menu_curr->tproc.link != NULL)
	  ((void(*)(point start, void *_link))menu_curr->tproc.proc)(
	    bogus_point, menu_curr->tproc.link);
	else
	  ((void(*)(point start))menu_curr->tproc.proc)(bogus_point);
      } else {
	if (menu_curr->t2proc.link != NULL)
	  ((void(*)(point start, short modenum, Char *modename, void *_link))
	   menu_curr->t2proc.proc)(bogus_point, WITH->modenum, WITH->modestr,
				   menu_curr->t2proc.link);
	else
	  ((void(*)(point start, short modenum, Char *modename))
	   menu_curr->t2proc.proc)(bogus_point, WITH->modenum, WITH->modestr);
      }
    }
    ok_to_select = true;
  } while (!quit);
}


Static void wol_main(void)
{
  Char first_menu[8];
  long infile_number, FORLIM;

  init();
  printf("running on machine: %s\n", m_machine);
  xtract_init();   /* Call me only once!! */
  setupDisp();
  setup_screen();

  all_menus = NULL;
  menu_curr = NULL;
  menu_setup();

  check_pen_proc.proc = do_check_pen;
  check_pen_proc.link = NULL;

  if (P_argc > 1) {
    FORLIM = P_argc;
    for (infile_number = 1; infile_number < FORLIM; infile_number++)
      read_cif_file(P_argv[infile_number]);
    strcpy(first_menu, "Main");
  } else
    strcpy(first_menu, "Opts");

  do {
    TRY(try9);
      quit = false;
      m_graphics_on();
      debounce();

      menu_curr = menu_find(first_menu);
      strcpy(first_menu, "Main");
      menu_erase = true;   /* force erase of menu */
      menu_show();
      trackit();
    RECOVER(try9);
      TRY(try10);
	if (P_escapecode != -1) {
	  show_error("\007Main level", false);
	  tablet_reset();
	  waitfor(50);   /* wait for tablet */
	  clear_screen();
	  m_graphics_on();
	  big_graphics();
	  if (in_extract) {
	    TRY(try11);
	      xtr_free_mem();
	    RECOVER(try11);
	      show_error("xtr_free_mem", false);
	    ENDTRY(try11);
	  }
	  in_extract = false;
	}
      RECOVER(try10);
	;
      ENDTRY(try10);
    ENDTRY(try9);
    ok_to_select = true;
  } while (!quit);
  shut_down();
  shutdown_screen();

  m_graphics_off();
  alpha_screen(CLR);
  m_alpha_on();
}


main(int argc, Char *argv[])
{
  nc_text_in_window = 1;
  PASCAL_MAIN(argc, argv);
  wol_main();
  exit(0);
}



/* End. */
