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


/* Change these for testing */



#include "global.h"


#define WOL_INITIALIZE_G
#include "wol_initialize.h"


long get_new_prefixid(Char *cell_name, Char *cell_type)
{
  /*searches first the cells of type "cell_type" to find "cell_name".
    Once it finds the correct cell that is being added, copied, etc,
    it searches in the attached list of prefixid's that are in use,
    until it finds one that is not (it inserts this into the sorted list) */
  return 0;
  /*$if false$
   new (prfxid);
   start := true;
   if cell_type = 'GEOM' then
     begin
       g_ptr := geom_cells;
       while (start or (g_ptr <> geom_cells))
              and (g_ptr^.name <> cell_name) do
         begin
           start := false;
           g_ptr := g_ptr^.next;
         end;
       i := 1;
       found := false;
       prfxid := g_ptr^.prefixid_list;
       old_prfxid := prfxid;
       while not found do
         begin
           if i < prfxid^.id then found := true
             else if i > prfxid^.id then prfxid := prfxid^.next
               else { i = prfxid^.id } begin
                                         i := i + 1;
                                         prfxid := prfxid^.next;
                                       end;
           { check if we have hit the end of the list }
         end;
     end;
$end$*/
}


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


Static void more_layer_junk(void)
{
  short i;
  layer_info *WITH;

  bb = -1;
  sel_box = -1;
  comp_box = -1;
  /* find special layers MBB, SEL, COMP */
  for (i = min_layer; i <= max_layer; i++) {
    WITH = &layers[i - min_layer];
    if (!strcmp(WITH->cif_name, "MBB"))
      bb = i;
    else if (!strcmp(WITH->cif_name, "SEL"))
      sel_box = i;
    else if (!strcmp(WITH->cif_name, "COMP"))
      comp_box = i;   /*multiple comp-box kluges */
    else if (!strcmp(WITH->cif_name, "LCX"))
      comp_box = i;
  }
  if (bb == -1)
    show_message("\007MBB layer not defined!!!", false);
  if (sel_box == -1)
    show_message("\007Select Box layer not defined!!!", false);
  if (comp_box == -1)
    show_message("\007Composition Box layer not defined!!!", false);
}


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

/* Attempt to read a technology file.  If it is not found in the current */
/* directory, look in WOLLIB. */
void read_tech_file(Char *origname)
{
  Char name[fidleng + 1];
  Char STR1[202];
  Char STR3[150];

  strcpy(name, origname);
  if (strpos2(name, ".wol", 1) == 0 && strpos2(name, ".WOL", 1) == 0)
    strcat(name, ".wol");
  TRY(try1);
    read_tech(name);
    strcpy(technology, name);
    more_layer_junk();   /* must reset layer stuff */
  RECOVER(try1);
    if (P_escapecode == 10)
      m_alpha_on();
    else if (P_escapecode != -10)
      _Escape(P_escapecode);
    else {
      TRY(try2);
	if (P_ioresult != (int)inofile)
	{   /* propogate any other kind of error */
	  P_escapecode = -10;
	  goto _Ltry2;
	}
	/* Since the file was not found in the current directory, try this */
	sprintf(name, "%s%s", WolLib, strcpy(STR1, name));
	read_tech(name);
	strcpy(technology, name);
	more_layer_junk();   /* must reset layer stuff */
      RECOVER2(try2,_Ltry2);
	if (P_escapecode != 10) {
	  if (P_escapecode != -10)
	    _Escape(P_escapecode);
	  else {
	    sprintf(STR3, "\007Technology file %s not found.", origname);
	    show_error(STR3, false);
	    _Escape(10);
	  }
	}
	m_alpha_on();
      ENDTRY(try2);
    }
  ENDTRY(try1);
}


Local Char *wb(Char *Result, boolean a)
{
  /* return ON if a is true, OFF otherwise */
  if (a)
    return strcpy(Result, "ON");
  else
    return strcpy(Result, "OFF");
}


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

void save_config(void)
{
  /* saves a configuration file for NEWOL */
  FILE *out_fyle;
  Char out_fyle_name[81];
  Char *TEMP;
  Char STR2[81];

  out_fyle = NULL;
  TRY(try3);
    show_message("Writing configuration file: ", true);
    printf("    Enter file name: [info.wol]  ");
    fgets(out_fyle_name, 81, stdin);
    TEMP = strchr(out_fyle_name, '\n');
    if (TEMP != NULL)
      *TEMP = 0;
    if (*out_fyle_name == '\0')
      strcpy(out_fyle_name, "info.wol");
    if (out_fyle != NULL)
      out_fyle = freopen(out_fyle_name, "w", out_fyle);
    else
      out_fyle = fopen(out_fyle_name, "w");
    if (out_fyle == NULL) {
      P_escapecode = -10;
      P_ioresult = FileNotFound;
      goto _Ltry3;
    }
    fprintf(out_fyle, "TECHNOLOGY:  %s\n", technology);
    fprintf(out_fyle, "LAMBDA:  %0.2f\n", lambda_to_microns / 100.0);
    fprintf(out_fyle, "DISPLAY STYLE:  %d\n", disp_style);
    fprintf(out_fyle, "CELL NAME PROMPTING:  %s\n", wb(STR2, prompt_cellname));
    fprintf(out_fyle, "FILE NAME PROMPTING:  %s\n", wb(STR2, prompt_filename));
    fprintf(out_fyle, "EDGE-PRIORITY SELECTION:  %s\n", wb(STR2, edges_only));
    fprintf(out_fyle, "AUTO-REFRESH:  %s\n", wb(STR2, auto_refresh));
    fprintf(out_fyle, "DISPLAY BOUNDING BOXES:  %s\n", wb(STR2, bbox_nobbox));
    fprintf(out_fyle, "DISPLAY PORTS:  %s\n", wb(STR2, display_ports));
    fprintf(out_fyle, "MANHATTAN ROUTING:  %s\n", wb(STR2, manhattan_routing));
    fprintf(out_fyle, "FLESHED-OUT ROUTING:  %s\n",
	    wb(STR2, fleshed_out_routing));
    fprintf(out_fyle, "BACKGROUND COLOR:  %ld\n", background_color);
    fprintf(out_fyle, "MEMORY THRESHOLD:  %ld\n", mem_thresh);
    fprintf(out_fyle, "DISABLE HEIRARCHY:  %s\n", wb(STR2, disable_heirarchy));
    fprintf(out_fyle, "POINT-TO-POINT MOVE:  %s\n",
	    wb(STR2, point_to_point_move));
    fprintf(out_fyle, "  \n");
    fprintf(out_fyle, "Written by WOL %s  %s\n",
	    Version, get_date_string(STR2));
    fprintf(out_fyle, "User:  %s\n", wol_username);
    if (out_fyle != NULL)
      fclose(out_fyle);
    out_fyle = NULL;
  RECOVER2(try3,_Ltry3);
    show_error("SAVE_CONFIG:  ", false);
  ENDTRY(try3);
  if (out_fyle != NULL)
    fclose(out_fyle);
}


Local void parse(Char *source, Char *target, boolean *ans)
{
  /* looks for the target string in the source line;
     returns true if the string ' ON' also found on the line,
             false if the string ' OFF' is found
             leaves 'ans' unchanged if neither is found, or if target not found
   */
  if (strpos2(source, target, 1) == 0)
    return;
  if (strpos2(source, " ON", 1) != 0)
    *ans = true;
  else if (strpos2(source, " OFF", 1) != 0)
    *ans = false;
}


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

/* Format of an INFO.WOL file: */
/*   technology "file" name */
/* EOF */
Static boolean read_info_file(void)
{
  /* Indicate if a technology file was read. */
  /* try to read INFO.WOL file in (i) current directory
                                 (ii) home directory
                                 (iii) WolLib directory
  */
  boolean Result, fill_boxes;
  Char fil_str[fidleng + 1];
  FILE *inf_fil;
  long col, m, junk;
  double l;
  Char STR1[90];
  Char STR2[26];
  Char STR3[256];
  Char *TEMP;
  Char STR4[256];
  Char STR5[158];
  Char *STR6;


  inf_fil = NULL;
  fill_boxes = false;
  TRY(try4);
    Result = false;
    TRY(try5);
      if (inf_fil != NULL)
	inf_fil = freopen("info.wol", "r", inf_fil);
      else
	inf_fil = fopen("info.wol", "r");
      if (inf_fil == NULL) {
	P_escapecode = -10;
	P_ioresult = FileNotFound;
	goto _Ltry5;
      }
    RECOVER2(try5,_Ltry5);

      TRY(try6);
	if (P_escapecode != -10 && P_escapecode != 10)
	  goto _Ltry6;
	if (inf_fil != NULL) {
	  sprintf(STR2, "/usr/%s/info.wol", wol_username);
	  inf_fil = freopen(STR2, "r", inf_fil);
	} else {
	  sprintf(STR2, "/usr/%s/info.wol", wol_username);
	  inf_fil = fopen(STR2, "r");
	}
	if (inf_fil == NULL) {
	  P_escapecode = -10;
	  P_ioresult = FileNotFound;
	  goto _Ltry6;
	}
      RECOVER2(try6,_Ltry6);
	if (P_escapecode != -10 && P_escapecode != 10)
	  goto _Ltry4;
	if (inf_fil != NULL) {
	  sprintf(STR1, "%sinfo.wol", WolLib);
	  inf_fil = freopen(STR1, "r", inf_fil);
	} else {
	  sprintf(STR1, "%sinfo.wol", WolLib);
	  inf_fil = fopen(STR1, "r");
	}
	if (inf_fil == NULL) {
	  P_escapecode = -10;
	  P_ioresult = FileNotFound;
	  goto _Ltry4;
	}
      ENDTRY(try6);
    ENDTRY(try5);
    do {
      fgets(fil_str, fidleng + 1, inf_fil);
      TEMP = strchr(fil_str, '\n');
      if (TEMP != NULL)
	*TEMP = 0;
      strcpy(fil_str, strrtrim(strcpy(STR3, fil_str)));
      if (strpos2(fil_str, "TECH", 1) != 0) {
	strcpy(fil_str, fil_str + strpos2(fil_str, ": ", 1));
	strcpy(STR3, strltrim(strrtrim(strcpy(STR4, fil_str))));
	strcpy(fil_str, STR3);
	TRY(try7);
	  read_tech_file(fil_str);
	  Result = true;
	RECOVER(try7);
	  sprintf(STR5, "ERROR in read_info_file -- reading: %s", fil_str);
	  show_error(STR5, true);
	ENDTRY(try7);
      } else {
	parse(fil_str, "FILL", &fill_boxes);
	parse(fil_str, "CELL", &prompt_cellname);
	parse(fil_str, "FILE", &prompt_filename);
	parse(fil_str, "EDGE", &edges_only);
	parse(fil_str, "AUTO", &auto_refresh);
	parse(fil_str, "BOX", &bbox_nobbox);
	parse(fil_str, "MAN", &manhattan_routing);
	parse(fil_str, "FLESH", &fleshed_out_routing);
	parse(fil_str, "PORTS", &display_ports);
	parse(fil_str, "HEIRARCHY", &disable_heirarchy);
	parse(fil_str, "POINT", &point_to_point_move);
	if (strpos2(fil_str, "BACK", 1) != 0) {
	  TRY(try8);
	    junk = strpos2(fil_str, ": ", 1) + 1;
	    col = strtol(fil_str + junk - 1, &STR6, 10);
	    junk = STR6 - fil_str + 1;
	  RECOVER(try8);
	    col = 0;
	  ENDTRY(try8);
	  m_setcolor(0, col, col, col);
	  background_color = col;
	}
	if (strpos2(fil_str, "LAMBDA", 1) != 0) {
	  TRY(try9);
	    junk = strpos2(fil_str, ": ", 1) + 1;
	    l = strtod(fil_str + junk - 1, &STR6);
	    junk = STR6 - fil_str + 1;
	    lambda_to_microns = (long)(100 * l);
	  RECOVER(try9);
	    ;
	  ENDTRY(try9);
	}
	if (strpos2(fil_str, "DISPLAY STYLE", 1) != 0) {
	  TRY(try10);
	    junk = strpos2(fil_str, ": ", 1) + 1;
	    m = strtol(fil_str + junk - 1, &STR6, 10);
	    junk = STR6 - fil_str + 1;
	    set_disp_style(m);
	  RECOVER(try10);
	    ;
	  ENDTRY(try10);
	}
	if (strpos2(fil_str, "MEMORY", 1) != 0) {
	  TRY(try11);
	    junk = strpos2(fil_str, ": ", 1) + 1;
	    m = strtol(fil_str + junk - 1, &STR6, 10);
	    junk = STR6 - fil_str + 1;
	    mem_thresh = m;
	  RECOVER(try11);
	    ;
	  ENDTRY(try11);
	}
      }
    } while (!P_eof(inf_fil));
    if (inf_fil != NULL)
      fclose(inf_fil);
    inf_fil = NULL;
    /* enforce consistency between fill_boxes and disp_style*/
    if (fill_boxes)   /* why not */
      set_disp_style(1);

  RECOVER2(try4,_Ltry4);
    if (P_escapecode != -10 && P_escapecode != 10) {
      show_error("ERROR in read_info_file", true);
      /*escape(10);*/
    }
  ENDTRY(try4);
  if (inf_fil != NULL)
    fclose(inf_fil);
  return Result;
}


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

void read_motd_file(Char *name)
{
  FILE *infile;
  Char s[256];
  short motd_line;
  long x, y;
  Char *TEMP;
  Char STR1[132];

  infile = NULL;
  nk_getxy(&x, &y);
  motd_line = y;
  TRY(try12);
    if (infile != NULL)
      infile = freopen(name, "r", infile);
    else
      infile = fopen(name, "r");
    if (infile == NULL) {
      P_escapecode = -10;
      P_ioresult = FileNotFound;
      goto _Ltry12;
    }
    while (fgets(s, 256, infile) != NULL) {
      TEMP = strchr(s, '\n');
      if (TEMP != NULL)
	*TEMP = 0;
      puts(s);
      motd_line++;
      if (motd_line > 18) {
	printf("\201\211Tap pen or press SPACE to continue:\210\200");
	/* just EAT it */
	wait_pen_or_kbd();
	printf("\015\t");
	motd_line = 0;
      }
/* p2c: wol_init.text, line 342:
 * Note: Characters >= 128 encountered [281] */
/* p2c: wol_init.text, line 342:
 * Note: WRITE statement contains color/attribute characters [203] */
    }
    if (infile != NULL)
      fclose(infile);
    infile = NULL;
  RECOVER2(try12,_Ltry12);
    if (P_escapecode != -10 || P_ioresult != (int)inofile) {
      sprintf(STR1, "\007motd: \"%s\"", name);
      show_error(STR1, false);
    }
  ENDTRY(try12);
  if (infile != NULL)
    fclose(infile);
}  /*read_motd_file*/


Static void get_motd(void)
{
  /* Print out the daily message */
  /* Looks in WOLLIB and in current directory for file "MOTD.WOL" */
  Char STR1[90];

  printf("\n\n");
  read_motd_file("motd.wol");
  sprintf(STR1, "%smotd.wol", WolLib);
  read_motd_file(STR1);
}


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

Static void refresh_null(void)
{
  printf("refresh_null called.\n");
}


Static void init_vars(void)
{
  short i, count;
  newci_parserec parsetab[11];
  Char infname[81];
  Char username[L_cuserid];
  _PROCEDURE TEMP;

  /* clear out ALL global varibles upon program invokation */
  /* this seems superfluous in C, and core-dumps on 386's, thus comments */
  /*  memset(&STARTVARS, '\0', (long)(&ENDVARS) - (long)(&STARTVARS)); */

  if (!strcmp(m_machine, "X"))
    strcpy(WolLib, WOLLIBDIR);
  else
    strcpy(WolLib, WOLLIBDIR);

  /* set up command line switches */
  strcpy(parsetab[0].switch_, "qQ");   /* quiet startup */
  parsetab[0].kind = 'S';
  strcpy(parsetab[1].switch_, "uU");   /* user name */
  parsetab[1].kind = 'S';
  strcpy(parsetab[2].switch_, "tT");   /* technology name */
  parsetab[2].kind = 'S';
  newci_parseswitch(parsetab, 3, infname);
  if (*infname != '\0') {
    printf("Usage:  WOL [-q] [-u\"name\"] [filename1] [filename2] ...\n");
    _Escape(-20);
  }
  quiet_startup = (parsetab[0].used != 0);
  if (parsetab[1].used != 0)
    strcpy(wol_username, parsetab[1].UU.s);
  else
    {
      cuserid(username);
      strcpy(wol_username, (char *)username);
    }
/*    strcpy(wol_username, P_citinfo->username);*/


  /* First, print out the message of the day */
  if (!quiet_startup)
    get_motd();

  init_mem = asm_memavail();   /* Start memory before anything else */
  mem_thresh = init_mem * 2 / 5;   /* complain with <40% */

  lambda_to_microns = 150;   /* default lambda = 1.50 microns */

  /* First, convince make_buffer that there are no display buffers */
  for (i = 0; i <= max_buffer; i++)
    strcpy(display_buffers[i].name, "None");
  /* Now force the buffers to be dull. */
  for (i = 0; i <= max_buffer; i++) {
    TEMP.proc = refresh_null;
    TEMP.link = NULL;
    make_buffer("None", TEMP);
  }

  current_buffer = -1;
  strcpy(current_buffer_name, "None");
  TEMP.proc = refresh_geom;
  TEMP.link = NULL;
  make_buffer("GEOM", TEMP);
  TEMP.proc = show_comp;
  TEMP.link = NULL;
  make_buffer("COMP", TEMP);
  set_buffer("GEOM");

  cursor_on = true;
  auto_refresh = true;   /* allow self refresh */
  ref_flg = false;

  /* Layer stuff */
  disp_style = 0;
  gstate.ref_in_black = false;   /* Draw all refresh items in black */
  gstate.dotted = false;   /* Draw wires in dotted style      */
  curr_layer = POLY;
  set_layer(curr_layer);
  for (i = 0; i < max_patterns; i++)
    patterns[i] = NULL;
  for (i = min_layer; i <= max_layer; i++) {
    deferred[i - min_layer] = false;
    layers_on[i - min_layer] = true;
  }

  background_color = 0;

  making_wire = false;   /* Are we now making a wire?       */
  retain_nodes = false;   /* Don't keep nodes                */
  bbox_nobbox = true;   /* show bboxes */

  last_deferred = NULL;
  deferred_stack = NULL;
  /*geom_window_stack := NIL;*/
  /*comp_window_stack := NIL;*/
  garbage_window_stack = NULL;
  cell_init();   /* Initialize memory handler */

  main_ = NULL;
  last_moved = NULL;
  last_added = NULL;
  for (count = 0; count <= 4; count++)
    del_nodes[count] = NULL;

  comp_cells = get_c_cell();
  comp_cells->next = comp_cells;
  comp_cells->data = NULL;
  strcpy(comp_cells->name, "*COMP*");
  comp_cells->ll.x = INFIN;
  comp_cells->ll.y = INFIN;
  comp_cells->ur.x = INFIN;
  comp_cells->ur.y = INFIN;
  comp_cells->modified = false;
  wire_width = 4;
  comp_undelete_list = NULL;

  geom_cells = get_g_cell();
  strcpy(geom_cells->name, "*GEOM*");
  geom_cells->next = geom_cells;
  geom_cells->prev = geom_cells;
  geom_cells->data = main_;
  geom_cells->modified = false;

  *curr_geom_cell = '\0';
  *curr_comp_cell = '\0';

  /* random variables that should be initialized  --  MAS  */
  a_w_layer = 0;
  a_w_count = 0;
  initial_cif_symbol_number = 1;
  a_w_list = NULL;
  d_c_p = NULL;

  pl_ident();

  xform = 0;
  geometry_xform = 0;

  prompt_filename = true;
  prompt_cellname = false;   /* TRUE is to prompt obnoxiously */
  manhattan_routing = true;   /* permit only manhattan routing */
  fleshed_out_routing = false;   /* draw centerlines only */

  debug_clip = true;
  display_ports = false;
  disable_heirarchy = false;
  point_to_point_move = false;

  edges_only = false;
  select_in_progress_g = false;   /* not selecting objects now */
  last_selected_object_g = NULL;   /* no selected object */
  select_list_head_g = NULL;
  select_list_tail_g = NULL;
  select_in_progress_c = false;   /* not selecting objects now */
  last_selected_object_c = NULL;   /* no selected object */
  select_list_head_c = NULL;
  select_list_tail_c = NULL;
  ok_to_select = true;

  make_matrix();

  if (!read_info_file())   /* Try real hard to have a technology */
    read_tech_file("cbul");
  if (parsetab[2].used != 0)
    read_tech_file(parsetab[2].UU.s);
  strcpy(technology2, "cbul");
  strcpy(technology3, "cmos");

  cells_modified = false;


}


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

void init(void)
{
  short typelimit;

  acursoroff();   /* Make sure alpha cursor is off */
  SETRUNLIGHT('W');
  /* need to allow the wheel to input more than one character here */
  typelimit = nk_setrpgbufsize(20);

  init_graphics();   /* Set up graphics          */
  tablet_reset();   /* Kick the tablet          */
  xor_off();   /* No xor                   */
  alpha_screen(CLR);
  m_alpha_on();
  m_graphics_on();
  printf("\n\n\n     Welcome to WOL, Version #%s, Compiled %s\n",
	 Version, Compilation_date);
  printf("              Copyright 1987,  Massimo A. Sivilotti, Caltech\n");
  init_vars();   /* Initialize variables     */
  waitfor(50);   /* wait for tablet */

}


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

void shut_down(void)
{
  /* clean things up before exiting */
  short typelimit;

  /* set number of wheel events allowed in typeahead back to 1 */
  typelimit = nk_setrpgbufsize(1);
}




/* End. */
