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


/* Change these for testing */



#include "global.h"


#define WOL_OPTIONS_G
#include "wol_options.h"


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

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


#define wndsize         20   /* lines in disp window */
#define wndtop          4   /* top of disp window */
#define infinity        30000


Static short norm_high;   /* highlight for normal text - set at startup */
Static short spec_high;   /* highlight for special text - this one changes */
Static short tab_default;
Static boolean emax_ret;
Static Char last_char;


/* input the next character, save it in last_char */
Static Char next_char(void)
{
  last_char = wait_pen_or_kbd();   /*getkey*/
  return last_char;
}


Static void spaz(Char *s)
{
  puts(s);
}


Static void crt_write_str(short x, short y, Char *s, short field)
{
  /*$if false$
   crtp:=addr(screen^[x+y*screenwidth],-2);

   len := abs(field)-strlen(s);
   if len>0 then
      if field>0
         then s := strrpt(' ',len) + s
         else s := s + strrpt(' ',len);

   for p:=1 to strlen(s) do crtp^[p].wholeword:=ord(s[p])+spec_high;
$end$*/
  nk_screenhigh = spec_high;
  nk_crtwritestr(x, y, s, field);
}


Static void crt_writeln(Char *s)
{
  crt_write_str(XPOS, YPOS, s, XPOS - nk_screenwidth);
  XPOS = 0;
  if (YPOS < 23)   /* from newCrt */
    YPOS++;
  else
    nc_scrollUp();
}


Static void crt_center_str(Char *s, short y)
{
  crt_write_str((nk_screenwidth - strlen(s)) / 2, y, s, 0);
}


Static void crt_write_int(short x, short y, long i, short field)
{
  Char s[11];
  long dummy;

  sprintf(s, "%ld", i);
  dummy = strlen(s) + 1;
  crt_write_str(x, y, s, field);
}


Static void Disp1(dispRec *head, boolean highlightit, short offset)
{
  short f;

  if (head->line < offset || head->line >= offset + wndsize)
    return;
  spec_high = norm_high;
  if (highlightit) {
    f = 0;
    crt_write_str(30, head->line - offset + wndtop, "", 30 - nk_screenwidth);
    nk_gotoxy(30, head->line - offset + wndtop);
    spec_high = nc_yellow;
  } else {
    /* show the name */
    crt_write_str(4, head->line - offset + wndtop, head->name, -26);
    f = 30 - nk_screenwidth;
  }
  switch ((dispKinds)head->kind) {

  case d_str:
    crt_write_str(30, head->line - offset + wndtop, head->UU.U0.strcur, f);
    break;

  case d_short:
    if (*head->UU.U1.shcur < head->UU.U1.shmin)
      *head->UU.U1.shcur = head->UU.U1.shmin;
    else if (*head->UU.U1.shcur > head->UU.U1.shmax)
      *head->UU.U1.shcur = head->UU.U1.shmax;
    crt_write_int(30, head->line - offset + wndtop, *head->UU.U1.shcur, f);
    break;

  case d_int:
    if (*head->UU.U3.intcur < head->UU.U3.intmin)
      *head->UU.U3.intcur = head->UU.U3.intmin;
    else if (*head->UU.U3.intcur > head->UU.U3.intmax)
      *head->UU.U3.intcur = head->UU.U3.intmax;
    crt_write_int(30, head->line - offset + wndtop, *head->UU.U3.intcur, f);
    break;

  case d_enum:
    if (*head->UU.U2.ecur < head->UU.U2.emin)
      *head->UU.U2.ecur = head->UU.U2.emin;
    else if (*head->UU.U2.ecur > head->UU.U2.emax)
      *head->UU.U2.ecur = head->UU.U2.emax;
    crt_write_str(30, head->line - offset + wndtop,
		  head->UU.U2.enames[*head->UU.U2.ecur], f);
    break;
  }
}


Static void chgdisp(short val, short line, short offset, boolean high)
{
  dispRec *d;
  short t;

  d = dispHead;
  while (d != NULL && d->line != line)
    d = d->next;
  if (d == NULL)
    spaz("chgdisp: Could not find proper line.");

  switch ((dispKinds)d->kind) {

  case d_str:
    if (val > 0)
      strcpy(d->UU.U0.strcur, d->UU.U0.strleft);
    else if (val < 0)
      strcpy(d->UU.U0.strcur, d->UU.U0.strright);
    break;

  case d_short:
    *d->UU.U1.shcur += val;
    break;

  case d_int:
    *d->UU.U3.intcur += val;
    break;

  case d_enum:
    t = *d->UU.U2.ecur + val;
    if (t < d->UU.U2.emin)
      *d->UU.U2.ecur = d->UU.U2.emin;
    else if (t > d->UU.U2.emax)
      *d->UU.U2.ecur = d->UU.U2.emax;
    else
      *d->UU.U2.ecur = t;
    break;
  }
  Disp1(d, high, offset);
  switch ((dispSpecials)d->special) {

  case sp_tab:
    break;
    /* tabs_init(d^.shcur^);    */
    /* update_tabs;               */

  case sp_none:
    /* blank case */
    break;

  case sp_tech:
    /* blank case */
    break;

  case sp_redraw:
    /* blank case */
    break;

  case sp_back_color:
    /* blank case */
    break;

  case sp_lambda:
    /* blank case */
    break;

  default:
    spaz("chgdisp: bad display special");
    break;
  }
}


Static void addDisp(dispRec *d)
{
  dispRec *p;

  p = Malloc(sizeof(dispRec));
  d->special = (unsigned)sp_none;
  d->line = dispLine;
  dispLine++;
  d->next = dispHead;
  *p = *d;
  dispHead = p;
}


void dispStr(Char *name, Char *c, Char *l, Char *r)
{
  dispRec d;

  strcpy(d.name, name);
  d.kind = (unsigned)d_str;
  d.UU.U0.strcur = c;
  d.UU.U0.strleft = l;
  d.UU.U0.strright = r;
  d.UU.U0.strmax = 255;
/* p2c: wol_options.text, line 278:
 * Note: STRMAX of "c" wants VarStrings=1 [151] */
  addDisp(&d);
}


void dispShort(Char *name, short *s, short max, short min)
{
  dispRec d;

  strcpy(d.name, name);
  d.kind = (unsigned)d_short;
  d.UU.U1.shcur = s;
  d.UU.U1.shmax = max;
  d.UU.U1.shmin = min;
  addDisp(&d);
}


void dispInt(Char *name, long *s, long max, long min)
{
  dispRec d;

  strcpy(d.name, name);
  d.kind = (unsigned)d_int;
  d.UU.U3.intcur = s;
  d.UU.U3.intmax = max;
  d.UU.U3.intmin = min;
  addDisp(&d);
}


void dispEnum(Char *name, Char *e, short max, short min, Char (*p)[15])
{
  dispRec d;

  strcpy(d.name, name);
  d.kind = (unsigned)d_enum;
  d.UU.U2.ecur = e;
  d.UU.U2.emax = max;
  d.UU.U2.emin = min;
  d.UU.U2.enames = p;
  addDisp(&d);
}


void dispLEnum(Char *name, Char *e, short max, short min, Char (*p)[15])
{
  Char *c;

  c = e + 1;
  dispEnum(name, c, max, min, p);
}


/* Local variables for newenter_str: */
struct LOC_newenter_str {
  Char ans_str[81];
} ;

Local long assign(long max, long min, long cur, struct LOC_newenter_str *LINK)
{
  long Result, val, pos;
  Char *STR1;

  TRY(try1);
    val = strtol(LINK->ans_str, &STR1, 10);
    pos = STR1 - LINK->ans_str + 1;
    if (val < min)
      Result = min;
    else if (val > max)
      Result = max;
    else
      Result = val;
  RECOVER(try1);
    return cur;
  ENDTRY(try1);
  return Result;
}


Static void newenter_str(short mode)
{
  struct LOC_newenter_str V;
  dispRec *d;
  Char *TEMP;

  d = dispHead;
  while (d != NULL && d->line != mode)
    d = d->next;
  if (d == NULL)
    spaz("newenter_str: Could not find proper line.");

  if (((1L << d->kind) & ((1L << ((long)d_str)) | (1L << ((long)d_short)) |
			  (1L << ((long)d_int)))) == 0)
    return;
  nk_ungetkey(last_char);
  nk_gotoxy(0, 22);
  putchar('\t');
  nk_gotoxy(30, wndtop + mode);
  putchar('\t');
  spec_high = nc_yellow;
  if ((dispKinds)d->kind != d_str)
    crt_center_str("Enter string, [RETURN] to terminate", 22);
  else
    crt_center_str("Enter integer, [RETURN] to terminate", 22);
  fgets(V.ans_str, 81, stdin);
  TEMP = strchr(V.ans_str, '\n');
  if (TEMP != NULL)
    *TEMP = 0;
  nk_gotoxy(0, 22);
  putchar('\t');
  nk_gotoxy(30, wndtop + mode);
  switch ((dispKinds)d->kind) {

  case d_short:
    *d->UU.U1.shcur = assign(d->UU.U1.shmax, d->UU.U1.shmin, *d->UU.U1.shcur,
			     &V);
    break;

  case d_int:
    *d->UU.U3.intcur = assign(d->UU.U3.intmax, d->UU.U3.intmin,
			      *d->UU.U3.intcur, &V);
    break;

  case d_str:
    if (strlen(V.ans_str) > d->UU.U0.strmax) {
      V.ans_str[d->UU.U0.strmax] = '\0';
/* p2c: wol_options.text, line 363:
 * Note: Modification of string length may translate incorrectly [146] */
    }
    strcpy(d->UU.U0.strcur, V.ans_str);
    break;
  }
  chgdisp(0, mode, 0, true);
}


void cmd_options(void)
{
  short tmp, mode, omode;
  boolean done_opt;
  dispRec *head;
  Char TEMP;

  norm_high = nc_green;
  /* spec_high := 4*4096;  */
  spec_high = norm_high;

  /* show everything */
  head = dispHead;
  while (head != NULL) {
    Disp1(head, false, 0);
    head = head->next;
  }

  crt_center_str("Press pen or <EXECUTE> to return, <STOP> to abort", 23);

  mode = old_mode;
  done_opt = false;
  spec_high = nc_yellow;
  chgdisp(0, mode, 0, true);
  do {
    TEMP = next_char();
    if (!((uchar)TEMP < 32 && ((1L << TEMP) & 0x90000509L) != 0))
      newenter_str(mode);
    else {
      spec_high = nc_green;
      tmp = 0;
      omode = mode;
      switch (last_char) {

      case '\n':
	mode = (mode + 1) % numOpt;
/* p2c: wol_options.text, line 402:
 * Note: Using % for possibly-negative arguments [317] */
	break;

      case '\037':
	mode = (mode - 1) % numOpt;
/* p2c: wol_options.text, line 403:
 * Note: Using % for possibly-negative arguments [317] */
	break;

      case '\b':
	tmp = -1;
	break;

      case '\034':
	tmp = 1;
	break;

      case '\003':
      case '\0':   /* EXIT command */
	done_opt = true;
	break;
      }
      if (omode != mode)
	chgdisp(0, omode, 0, false);
      chgdisp(tmp, mode, 0, true);
    }
  } while (!done_opt);
  old_mode = mode;
  /*  setreflevel(rflgful);    */
}




/* End. */
