[comp.sources.atari.st] v02i021: uw -- Unix Windows windowing terminal software part03/05

koreth@ssyx.ucsc.edu (Steven Grimm) (03/03/89)

Submitted-by: sun.com!laidbak!katzung (Brian Katzung)
Posting-number: Volume 2, Issue 21
Archive-name: uw/part03

#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file WINDEFS.H continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> WINDEFS.H
X} FNT;
X
Xtypedef struct wi_str {
X  int port;			/* the UW port identifier */
X  int fulled,used;		/* flags */
X  int inverse;			/* inverse chars */
X  int insmode;			/* insert mode on */
X  int curstate;			/* state of the cursor */
X  int x, y, w, h;		/* work area on screen */
X  int px, py, pw, ph;		/* previous location of entire window */
X  int x_off, y_off;		/* offset for visible part */
X  int px_off, py_off;		/* previous offset */
X  int m_off;			/* memory offset */
X  int wi_w, wi_h;		/* max w,h */
X  int cur_x, cur_y;		/* current cursor position */
X  int top_y;			/* position of top of circular window buffer */
X  int state;			/* state for the emulation FSM */
X  FNT *font;			/* the font in use */
X  MFDB wi_mf;			/* memory form for this window */
X  char name[80];		/* name of this window */
X  char nuname[80];		/* new name under construction */
X  char dname[80];		/* name actually displayed (w/ flags, etc.) */
X				/* (dname is set in w_rename) */
X  int nuptr;			/* curr. len of new name or parameter assembly*/
X  int ptr_status;		/* status of print loging for window */
X  int x_chrs, y_chrs;		/* size of terminal emulation */
X  int top_age;			/* number of windows topped after this window */
X  int wi_style;			/* style of window (see WI_*SLD) */
X  char wi_fpath[80];		/* log file path */
X  char wi_fname[20];		/* log file name */
X  FILE *wi_lfd;			/* log file descriptor */
X  int kerm_act;			/* is this a kermit window? */
X  int w_local;			/* is this a local window? */
X} WI_STR;
X
X#define LOG_BOTOM	1	/* print incoming characters */
X#define LOG_TOP		2	/* print lines which scroll off screen top */
X#define LOG_NONE	0	/* no printer output for this window */
X
Xtypedef struct gemfont {
X	short	ft_id;
X	short	ft_psize;
X	char	ft_name[32];
X	short	ft_l_ade;
X	short	ft_h_ade;
X	short	ft_topl;
X	short	ft_ascl;
X	short	ft_halfl;
X	short	ft_descl;
X	short	ft_botl;
X	short	ft_chwidth;
X	short	ft_clwidth;
X	short	ft_lf_off;
X	short	ft_rt_off;
X	short	ft_thick;
X	short	ft_ul;
X	short	ft_light;
X	short	ft_skew;
X	short	ft_flags;
X	short	*ft_h_off;
X	short	*ft_c_off;
X	short	*ft_data;
X	short	ft_fwidth;
X	short	ft_fheight;
X	struct gemfont *ft_next;
X} GEMFONT;
X
Xtypedef char FUNCSTRING[MAXFUNCLEN];
X
SHAR_EOF
chmod 0600 WINDEFS.H || echo "restore of WINDEFS.H fails"
sed 's/^X//' << 'SHAR_EOF' > WINHASH.C &&
X/*
X * This file contains routines which can be used to determine the character
X * present at a given location in a window.  These functions are used to
X * determine the character under the mouse cursor, and for the log-top printer
X * function.
X */
X
X#include <stdio.h>
X#include <osbind.h>
X#include "windefs.h"
X
Xextern struct wi_str w[];
X
Xint	highlighted_wdes = -1;	/* make this global now for use in winmain.c*/
X
X/*
X * char_at returns the ascii code of the character in wdes window at
X * (x_loc, y_loc) cursor position.  Zero is returned if the character can
X * not be identified.
X */
Xint char_at(wdes, x_loc, y_loc)
Xint wdes, x_loc, y_loc;
X
X{
X
X  register struct wi_str *wp = &w[wdes];
X  int ch, width, boffset, count, cur_y, cur_x;
X  register unsigned long mask;
X  register unsigned long *dptr;
X  register int shift;
X  register FNT *fnt = wp->font;
X  static char pa[32]; 		/* pixel array containing character image */
X  
X  cur_x = x_loc * fnt->inc_x + X0;
X  cur_y = y_loc * fnt->inc_y + wp->top_y;
X  
X  width = 2 * wp->wi_mf.wwords;
X  boffset = wp->m_off+cur_x+fnt->inc_x-1;
X  dptr = ((char *)(wp->wi_mf.ptr)) + cur_y * width
X    + ((boffset >> 4) << 1) - 2;
X  shift = 15 - (boffset & 15);
X  mask = (-1L<<(shift+fnt->inc_x)|(1<<shift)-1);
X  for (count = 0; count < fnt->inc_y; count ++)
X  {
X    pa[count] = (*dptr & (~ mask)) >> shift;
X    ((char *) dptr) += width;
X  }
X  
X  ch = which_char(fnt, &fnt->f_hash, pa);
X  if (ch == 0)		/* Not found, check for inverse vidio case */
X  {
X    for (count = 0; count < fnt->inc_y; count ++)
X      pa[count] = ~pa[count] & (1<< fnt->inc_x) - 1;
X    ch = which_char(fnt, &fnt->f_hash, pa);
X  }
X  return (ch);
X}
X
X/*
X * which_char returns the ascii code of the character bitmap in pa from font
X * font using hash table htbl.
X */
Xint which_char(font, htbl, pa)
XFNT *font;
XHTBL *htbl;
Xchar *pa;
X
X{
X  register int i, h, n;
X  
X  h = hash_char (pa, font->inc_y);
X  if ((htbl->h_t[h] & 128) == 0) /* collision bit set? */
X  {
X    for (i=0; i<font->inc_y; i++)
X      if (font->f_data[(htbl->h_t)[h] * 16 + i] != pa[i])
X        break;
X    if (i < font->inc_y){
X      return 0;
X    }
X    else
X      return (htbl->h_t[h]);
X  }
X  else				/* collision, search colision list for char */
X  {
X    n = htbl->h_t[h] & 127;
X    while (n != 0)
X    {
X      for (i=0; i<font->inc_y; i++)
X        if (font->f_data[(htbl->h_colision)[n].h_try * 16 + i] != pa[i])
X	  break;
X      if (i < font->inc_y)
X        n = htbl->h_colision[n].h_next;
X      else
X        return (htbl->h_colision[n].h_try);
X    }
X    return 0;
X  }
X}
X
X/*
X * gen_hash initalizes htbl with the hash table for font font.
X */
Xvoid gen_hash(font, htbl)
XFNT *font;
XHTBL *htbl;
X
X{
X  register int overflowcnt = 1;
X  register int np, tp, i, j;
X  int h;
X  
X  for (i=0; i<128; i++)		/* initalize */
X    htbl->h_colision[i].h_next = '\0';
X  for (i=0; i<(1<<HASHBITS); i++)
X    htbl->h_t[i] = '\0';
X  
X  for (i=32; i<128; i++)
X  {			/* for each character */
X    h = hash_char(&font->f_data[i*16], font->inc_y);
X    if (htbl->h_t[h] == 0)
X      htbl->h_t[h] = i;
X    else
X    {
X      if ((htbl->h_t[h] & 128) == 0) /* already overflowed? */
X      { /* No, move first element to overflow list */
X	htbl->h_colision[overflowcnt].h_try = htbl->h_t[h];
X        htbl->h_t[h] = 128 | overflowcnt;
X	overflowcnt++;
X      }
X	
X      tp = htbl->h_t[h] & 127;
X      j=0;	/* dbug */
X      while ((np = htbl->h_colision[tp].h_next) != 0){
X	tp = np;
X	j++; /* dbug */
X      }
X#ifdef DEBUG
X      printf("overflow=%d depth=%d hash %d = %d\n",overflowcnt, j, i, h);
X#endif
X      htbl->h_colision[tp].h_next = overflowcnt;
X      htbl->h_colision[overflowcnt].h_try = i;
X      ++ overflowcnt;
X    }
X  }
X
X#ifdef DEBUG 	/* verify sanity of hash table */
X  for (i=32; i<128; i++) /* dbug */
X    if ((j = which_char(font, htbl, &font->f_data[i*16])) != i)
X  {
X    printf("%d != %d\n", i, j);
X  }
X#endif
X}
X
X/*
X * hash_char returns the hash code for the character pixel image in pa of
X * height height.
X */
Xint hash_char(pa, height)
Xchar *pa;
Xint height;
X
X{
X  register int h, i, j;
X  
X  h=0;
X  for (i=0; i<height; i++)
X  {
X    h += pa[i] << i*3 % HASHBITS;
X  }
X  j = (1<<HASHBITS) - 1;
X  h = (h + (h >> HASHBITS + 1)) & j;
X
X  return h;
X}
X
X/*
X * dump_line send the y_coord'th line in the window wdes to the printer.
X * zero is returned if the line was printed ok.
X */
Xdump_line(wdes, y_coord)
X{
X  int i;
X  char ch;
X  
X  for (i = 0; i < w[wdes].x_chrs; i++){
X    ch = char_at(wdes, i, y_coord);
X    if (Cprnout(ch) == 0) {
X      w[wdes].ptr_status = LOG_NONE;
X      return -1;
X    }
X  }
X  if (Cprnout('\n') == 0 | Cprnout('\r') == 0) {
X    w[wdes].ptr_status = LOG_NONE;
X    return -1;
X  }
X  return 0;
X}
X
X/*
X * dump_window send the contents of wdes to the printer.
X */
Xdump_window(wdes)
X{
X  int i;
X  
X  for (i = 0; i < w[wdes].y_chrs; i++){
X    dump_line(wdes, i);
X  }
X}
X/* copy_word fills buffer with the word at (x1, y1) from wdes
X * No checks are made for buffer overflow.
X */
Xcopy_word(wdes, x1, y1, buffer)
Xint wdes, x1, y1;
Xchar * buffer;
X{
X  register int fx, lx, yo, xo;
X  
X  yo = w[wdes].y_off / w[wdes].font->inc_y; /* adjust for scroll bar action */  
X  xo = w[wdes].x_off / w[wdes].font->inc_x;
X  fx = x1 - 1;
X  lx = x1 + 1;
X  
X  while (fx + xo >= 0 && char_at(wdes, fx + xo, y1 + yo) != ' ')
X    --fx;
X  while (lx + xo < w[wdes].x_chrs && char_at(wdes, lx + xo, y1 + yo) != ' ')
X    ++lx;
X  copy_text(wdes, ++fx, y1, --lx, y1, buffer);
X}
X
X/* copy_text fills buffer with the text between (x1, y1) and (x2, y2) from wdes
X * where point 1 is before point 2.  No checks are made for buffer overflow.
X */
Xcopy_text(wdes, x1, y1, x2, y2, buffer)
Xint wdes, x1, y1, x2, y2;
Xchar * buffer;
X{
X  static int old_hh;
X  static int old_y1;
X  register int cx, cy, i, lastnbi, lastnbx;
X  int inc_y, inc_x, top_y;
X
X  /* undo any old selected text which might be inverted on screen */
X  if (highlighted_wdes > 0 && w[highlighted_wdes].font != NULL)
X  {
X    w_update(highlighted_wdes, FM_COPY, 0, old_y1,
X      w[highlighted_wdes].x_chrs * w[highlighted_wdes].font->inc_x + X0 + 1,
X      old_hh);
X  }
X  if (y1 > y2) return;	/* nothing to do */
X
X  inc_y = w[wdes].font->inc_y;
X  inc_x = w[wdes].font->inc_x;
X  top_y = w[wdes].top_y;
X    
X  y1 = y1 + w[wdes].y_off / inc_y;	/* adjust for scroll bar action */  
X  y2 = y2 + w[wdes].y_off / inc_y;	/* assumes _off is multiple of inc_ */
X  x1 = x1 + w[wdes].x_off / inc_x;
X  x2 = x2 + w[wdes].x_off / inc_x;
X  i = 0;
X  lastnbi = 0;
X  lastnbx = x1;
X
X  if (y1 > y2)
X  {
X    highlighted_wdes = -1;	/* no undo required on next call */
X    return;
X  }
X  
X  old_y1 = y1 * inc_y + top_y;
X  old_hh = (y2 - y1 + 2) * inc_y + Y0;
X  highlighted_wdes = wdes;
X  
X  cx = x1;
X  cy = y1;
X
X  while (cy < y2 || (cy == y2 && cx <= x2))
X  {
X    buffer[i] = char_at(wdes, cx, cy);
X    if (buffer[i] != ' ')
X    {
X      lastnbi = i;
X      lastnbx = cx;
X    }
X    cx ++;
X    if (cx >= w[wdes].x_chrs)
X    {
X      if (cy == y1)	/* first line */
X        w_update(wdes, FM_INVERT, x1 * inc_x, cy * inc_y + top_y,
X	  (++lastnbx - x1) * inc_x + X0, inc_y);
X      else
X        w_update(wdes, FM_INVERT, 0, cy * inc_y + top_y,
X	  ++lastnbx * inc_x + X0, inc_y);
X      cx = 0;
X      cy ++;
X      i = ++lastnbi;
X      lastnbx = -1;
X      buffer[i] = '\r';
X    }
X    i++;
X  }
X  if (cy == y1)	/* one line */
X    w_update(wdes, FM_INVERT, x1 * inc_x, cy * inc_y + top_y,
X      (++lastnbx - x1) * inc_x + X0, inc_y);
X  else
X    w_update(wdes, FM_INVERT, 0, cy * inc_y + top_y,
X      ++lastnbx * inc_x + X0, inc_y);
X  buffer[++lastnbi] = '\0';
X}
X
SHAR_EOF
chmod 0600 WINHASH.C || echo "restore of WINHASH.C fails"
sed 's/^X//' << 'SHAR_EOF' > WINIO.C &&
X/*
X * This file contains file io routines
X */
X#include <obdefs.h>
X#include <gemdefs.h>
X#include <stdio.h>
X#include <osbind.h>
X#include <xbios.h>
X#include "wind.h"
X#include "uw.h"
X#include "windefs.h"
X
Xextern struct wi_str w[];
X
X/*
X * Character stuff (fonts, keymaps).
X */
Xextern FNT *fnttbl[10];			/* List of pointers to fonts avail */
Xextern int fontsavail;			/* Number of fonts available */
Xextern FNT *curfont;			/* font in use */
Xextern int fontmenuobj[];		/* array of font menu object numbers */
X/*
X * Options (somewhat loosely defined).
X */
Xextern int fast;			/* flag for fast open/close */
Xextern int overstrike;			/* flag for character output */
Xextern int sliders;			/* flag for sliders on new windows */
Xextern int titles;			/* flag for title bars on new windows */
Xextern int audibell;			/* Audible bell. */
Xextern int visibell;			/* Visible bell. */
Xextern int toponbel;			/* Top window on bell. */
X
Xextern FUNCSTRING fstrings[];		/* storage for function key bodys */
X
Xextern char cmdpath[];			/* default command executions strings */
Xextern char cmdname[];
Xextern char cmdargs[];
X
Xextern OBJECT *menubar;
X
Xvoid rsbufset();
Xlong	bufsizs[] = {		/* rs-232 buffer sizes setable from uw */
X	256l,	2048l,	16384l
X};
Xint	bufsiz = 0;		/* index into table above of current size */
X
X#ifdef	LOCATE
Xextern	char	*locate();
X#else
X#define	locate(n)	n
X#endif
X
X/* read a font from a file */
XFNT * loadfont (name)
Xchar	*name;
X{
X  FNT * curfont;
X  char *tmpfnt;
X  char menustr[20];
X  char namestr[20];
X  register int shift;
X  register unsigned int mask;
X  register int	i;
X  char *getmem();
X
X  if ((curfont = (FNT *) getmem((long)sizeof(FNT))) == NULL)
X    return(NULL);
X  i = Fopen(locate(name), 0);
X  if (i<0)
X    return (NULL);
X  Fread(i, 2048L, curfont->f_data);
X  Fclose(i);
X  curfont->inc_x = MINMAX(curfont->f_data[16], 1, 8);
X  curfont->inc_y = MINMAX(curfont->f_data[32], 1, 16);
X  shift = 8-curfont->inc_x;
X  mask = (1<<curfont->inc_x)-1;
X  tmpfnt = curfont->f_data;
X  for (i=0; i<2048; i++)
X  {
X    *tmpfnt = (*tmpfnt>>shift)&mask;
X    tmpfnt++;
X  }
X  sscanf(name, "wind%3s", namestr);
X  sprintf(menustr, "%1.2d x %1.2d %s font", curfont->inc_x, curfont->inc_y,
X    namestr);
X  set_menu_string(menustr, fontmenuobj[fontsavail]);
X  gen_hash(curfont, &curfont->f_hash);
X
X  fnttbl[fontsavail] = curfont;
X  fontsavail++;
X  return (curfont);
X}
X
X/* This function reads the config file from name in directory path and sets
X * the apropriate variables.
X */
Xread_config(path, name)
Xchar *path;
Xchar *name;
X{
X  char file[100];
X  char *ptr;
X  char *status;
X  FILE *fd;
X  int i, j;
X  char *index(), *rindex();
X  
X  strcpy(file, path);
X  ptr = rindex(file, '\\');
X  if (ptr != NULL)
X    *(ptr+1) = '\0';
X  strcat(file, name);
X  
X  fd = fopen(file, "r");
X  if (fd == NULL)
X  {
X    if (*path != '\0')	/* don't print error if in startup */
X      form_alert(1, "[2][Can't open config input file][ok]");
X    return;
X  }
X  status = fgets(file, 100,fd);
X  while (status != NULL)
X  {
X    char * endline;
X    if ((endline = rindex(file, '\n')) != NULL)
X      *endline = '\0';
X    if (!strncmp("audibell=", file, 9))
X      audibell = atoi(file + 9);
X    else if (!strncmp("visibell=", file, 9))
X      visibell = atoi(file + 9);
X    else if (!strncmp("topbell=", file, 8))
X      toponbel = atoi(file + 8);
X    else if (!strncmp("fast", file, 4))
X      ++fast;
X    else if (!strncmp("slow", file, 4))
X    	fast = 0;
X    else if (!strncmp("overstrike", file, 4))
X      ++overstrike;
X    else if (!strncmp("nooverstrike", file, 4))
X      overstrike = 0;
X    else if (!strncmp("sliders", file, 7))
X      ++sliders;
X    else if (!strncmp("nosliders", file, 9))
X    	sliders = 0;
X    else if (!strncmp("titles", file, 6))
X      ++titles;
X    else if (!strncmp("notitless", file, 8))
X    	titles = 0;
X    else if (!strncmp("font=", file, 5))
X    {
X      i = atoi(file+5);
X      if (fontsavail > i)
X      {
X        for (j = 0; j < fontsavail; j++)
X          objc_change(menubar, fontmenuobj[j], 0, 0, 0, 0, 0, NONE, 0);
X        objc_change(menubar, fontmenuobj[i], 0, 0, 0, 0, 0, CHECKED, 0);
X        curfont = fnttbl[i];
X      }
X    }
X    else if (!strncmp("bufsiz=", file, 7))
X    {
X      i = atoi(file+7);
X      for (j=0; j < sizeof(bufsizs)/sizeof(bufsizs[0]); j++)
X      	if (bufsizs[j] >= i)
X	  break;
X      bufsiz = j;
X      rsbufset(j);
X    }
X    else if (file[0] == 'f' && file[1] >= '0' && file[1] <= '9'
X      && (file[2] == '=' || file[3] == '='))
X      {
X	i = atoi(file+1);
X	if (i < 1) i = 1;
X	if (i > NFSTRINGS - 2) i = NFSTRINGS - 2;
X	status = index(file, '=');
X	ptr = index(status, '\n');
X	if (ptr != NULL)
X	  *ptr = '\0';
X	strcpy(fstrings[i-1], status+1);
X      }
X    else if (!strncmp("cmdpath=", file, 8))
X	strcpy(cmdpath, file+8);
X    else if (!strncmp("cmdname=", file, 8))
X	strcpy(cmdname, file+8);
X    else if (!strncmp("cmdargs=", file, 8))
X	strcpy(cmdargs, file+8);
X    status = fgets(file, 100, fd);
X  }
X  objc_change(menubar, VISIBELL, 0, 0, 0, 0, 0,
X    visibell? CHECKED: 0, 0);
X  objc_change(menubar, AUDIBELL, 0, 0, 0, 0, 0,
X    audibell? CHECKED: 0, 0);
X  objc_change(menubar, TOPONBEL, 0, 0, 0, 0, 0,
X    toponbel? CHECKED: 0, 0);
X  menu_icheck(menubar, MFAST, !fast);
X  menu_icheck(menubar, OVERSTRI, overstrike);
X  menu_icheck(menubar, WINSTYLE, sliders);
X  menu_icheck(menubar, WINTITLE, titles);
X}
X
X/* This function writes the config file name in directory path.
X */
Xwrite_config (path, name)
Xchar	*path;
Xchar	*name;
X{
X	char	file[100];
X	char	*ptr;
X	FILE	*fd;
X	int	i;
X	char	*rindex();
X  
X	strcpy(file, path);
X	ptr = rindex(file, '\\');
X	if (ptr != NULL)
X		*(ptr + 1) = '\0';
X	strcat(file, name);
X  
X	fd = fopen(file, "w");
X	if (fd == NULL)
X	{
X		form_alert(1, "[2][Can't open config output file][ok]");
X		return;
X	}
X
X	fprintf(fd, "audibell=%d\n", audibell);
X	fprintf(fd, "visibell=%d\n", visibell);
X	fprintf(fd, "topbell=%d\n", toponbel);
X	fprintf(fd, "%s\n", fast? "fast": "slow");
X	fprintf(fd, "%s\n", overstrike? "overstrike": "nooverstrike");
X	fprintf(fd, "%s\n", sliders? "sliders": "nosliders");
X	fprintf(fd, "%s\n", titles? "titles": "notitles");
X	fprintf(fd, "bufsiz=%ld\n", bufsizs[bufsiz]);
X	fprintf(fd, "cmdpath=%s\n", cmdpath);
X	fprintf(fd, "cmdname=%s\n", cmdname);
X	fprintf(fd, "cmdargs=%s\n", cmdargs);
X	for (i = 0; i < fontsavail; i++)
X		if (curfont == fnttbl[i])
X			fprintf(fd, "font=%d\n", i);
X
X	for (i = 0; i < NFSTRINGS - 2; ++i)
X		fprintf(fd, "f%d=%s\n", i + 1, fstrings[i]);
X	fclose(fd);
X}
X
Xsetcapture (wp)
XWI_STR	*wp;
X{
X	char	full[80];
X	register char	*cp1, *cp2;
X
X	if (wp->wi_lfd)
X	{
X		fclose(wp->wi_lfd);
X		wp->wi_lfd = NULL;
X	}
X	if (*wp->wi_fname)
X	{
X		cp1 = full;
X		for (cp2 = wp->wi_fpath; *cp2; *cp1++ = *cp2++);
X		while (--cp1 >= full && *cp1 != '\\');
X		strcpy(++cp1, wp->wi_fname);
X		if ((wp->wi_lfd = fopen(full, "a")) == NULL)
X		{
X			form_alert(1, "[2][Unable to open capture file.][ok]");
X			*wp->wi_fname = '\0';
X		}
X	}
X	w_rename(wp - w, NULL);
X}
X
X#define	DEFUCR	0x88		/* Async, 1 stop bit */
X
Xint	speedobjs[] = {
X	BB1920,	BB960,	BB480,	BB360,	BB240,	BB200,	BB180,	BB120,
X	BB60,	BB30,	BB20,	BB15,	BB13,	BB11,	BB7,	BB5
X};
Xint	flowobjs[] = {
X	FCBNONE,	FCBXON,		FCBRTS
X};
Xint	parobjs[] = {
X	PBNONE,		PBODD,		PBEVEN
X};
Xint	stopobjs[] = {
X	SBB1,		SBB15,		SBB2
X};
Xint	bcbobjs[] = {
X	BCB8,		BCB7,		BCB6,		BCB5
X};
Xint	bufobjs[] = {
X	BUFSIZ1,	BUFSIZ2,	BUFSIZ32
X};
X#ifdef	GETSPEED
X/* Baud rates 75 and 50 are not currently decoded. */
Xint	timevals[] = {
X	1,	2,	4,	5,	8,	10,	11,
X	16,	32,	64,	96,	128,	143,	175
X};
X#endif
X
Xint	speed = -1;		/* Don't know */
Xint	flow = -1;
Xint	ucr = -1;
Xstruct iorec old_iorec;
X
X/* load rs232 configuration into RSCONF dialog */
Xgetrsconf ()
X{
X	OBJECT	*obj;
X	register int	i;
X#ifdef	GETSPEED
X#define	MFP	0xFFFFFA01L
X#define	TDDR	36
X#define	hz_200	((unsigned long *) 0x4BAL)
X	int	tv;			/* Timer value */
X	int	maxtv;			/* Maximum timer value */
X	unsigned long	endhz;		/* End of polling period */
X	long	savessp;		/* Old stack pointer */
X#endif
X#ifdef	GETFLOW
X	struct	rsiorec	{
X		char	fill0[32];
X		char	rsmode;
X		char	fill1[1];
X	};
X#endif
X
X#ifdef	GETSPEED
X	savessp = Super(0L);
X	maxtv = 0;
X	endhz = *hz_200 + 8;
X	while (*hz_200 < endhz)
X	{
X		tv = *((unsigned char *) (0xFFFFFA01L + 36));
X		if (tv > maxtv)
X			maxtv = tv;
X	}
X	(void) Super(savessp);
X	for (i = sizeof(timevals) / sizeof(timevals[0]);
X	  --i >= 0 && timevals[i] != maxtv; );
X	if (i >= 0)
X		speed = i;
X#endif
X#ifdef	GETFLOW
X	flow = ((struct rsiorec *) Iorec(0))->rsmode;
X	if (flow == 3)			/* UW doesn't support both */
X		flow = 1;
X#endif
X#ifdef	GETUCR
X	/* Dev. Kit code suggests that Rsconf() returns old register vals */
X	ucr = (xbios(15, -1, -1, -1, -1, -1, -1) >> 24) & 0xFF;
X#endif
X	rsrc_gaddr(R_TREE, RSCONF, &obj);
X	for (i = sizeof(speedobjs) / sizeof(int); --i >= 0; )
X		obj[speedobjs[i]].ob_state = NORMAL;
X	for (i = sizeof(flowobjs) / sizeof(int); --i >= 0; )
X		obj[flowobjs[i]].ob_state = NORMAL;
X	for (i = sizeof(parobjs) / sizeof(int); --i >= 0; )
X		obj[parobjs[i]].ob_state = NORMAL;
X	for (i = sizeof(stopobjs) / sizeof(int); --i >= 0; )
X		obj[stopobjs[i]].ob_state = NORMAL;
X	for (i = sizeof(bcbobjs) / sizeof(int); --i >= 0; )
X		obj[bcbobjs[i]].ob_state = NORMAL;
X	for (i = sizeof(bufobjs) / sizeof(int); --i >= 0; )
X		obj[bufobjs[i]].ob_state = NORMAL;
X
X	if (speed >= 0)
X		obj[speedobjs[speed]].ob_state = SELECTED;
X
X	if (flow >= 0)
X		obj[flowobjs[flow]].ob_state = SELECTED;
X
X	if (ucr >= 0)
X	{
X		switch (ucr & 0x6)	/* Parity */
X		{
X		default:
X			obj[PBNONE].ob_state = SELECTED;
X			break;
X		case 0x4:
X			obj[PBODD].ob_state = SELECTED;
X			break;
X		case 0x6:
X			obj[PBEVEN].ob_state = SELECTED;
X			break;
X		}
X	
X		switch (ucr & 0x18)
X		{
X		default:
X			obj[SBB1].ob_state = SELECTED;
X			break;
X		case 0x10:
X			obj[SBB15].ob_state = SELECTED;
X			break;
X		case 0x18:
X			obj[SBB2].ob_state = SELECTED;
X			break;
X		}
X	
X		obj[bcbobjs[(ucr >> 5) & 3]].ob_state = SELECTED;
X	}
X	obj[bufobjs[bufsiz]].ob_state = SELECTED;
X}
X	
X/* set rs232 configuration from the RSCONF dialog */
Xsetrsconf ()
X{
X	register int	i;
X	OBJECT	*obj;
X	short	parity = 0;
X	short	stop = 0;
X	short	bcb = -1;
X
X	rsrc_gaddr(R_TREE, RSCONF, &obj);
X
X	for (i = sizeof(speedobjs) / sizeof(int); --i >= 0; )
X		if (obj[speedobjs[i]].ob_state & SELECTED)
X		{
X			speed = i;
X			break;
X		}
X
X	for (i = sizeof(flowobjs) / sizeof(int); --i >= 0; )
X		if (obj[flowobjs[i]].ob_state & SELECTED)
X		{
X			flow = i;
X			break;
X		}
X
X	for (i = sizeof(parobjs) / sizeof(int); --i >= 0; )
X		if (obj[parobjs[i]].ob_state & SELECTED)
X		{
X			parity = i + 1;
X			break;
X		}
X
X	for (i = sizeof(stopobjs) / sizeof(int); --i >= 0; )
X		if (obj[stopobjs[i]].ob_state & SELECTED)
X		{
X			stop = i + 1;
X			break;
X		}
X
X	for (i = sizeof(bcbobjs) / sizeof(int); --i >= 0; )
X		if (obj[bcbobjs[i]].ob_state & SELECTED)
X		{
X			bcb = i;
X			break;
X		}
X
X	for (i = sizeof(bufobjs) / sizeof(int); --i >= 0; )
X		if (obj[bufobjs[i]].ob_state & SELECTED)
X		{
X			bufsiz = i;
X			break;
X		}
X
X	if ((parity || stop || bcb >= 0) && ucr < 0)
X		ucr = DEFUCR;
X	if (parity)
X		ucr = (ucr & ~0x6) | (parity << 1);
X	if (stop)
X		ucr = (ucr & ~0x18) | (stop << 3);
X	if (bcb >= 0)
X		ucr = (ucr & ~0x60) | (bcb << 5);
X
X	Rsconf(speed, flow, ucr, -1, -1, -1);
X	rsbufset(bufsiz);
X}
X
Xvoid rsbufset(bufsiz)
Xint bufsiz;
X{
X	struct iorec *ioptr;
X	static char    *memalloced = NULL;
X	static int	oldbufsiz = 0;
X
X	ioptr = Iorec(0);
X	if (old_iorec.io_bufsiz == 0)
X		old_iorec = *ioptr;	/* save gem buffer */
X	if (oldbufsiz != bufsiz) {
X		char *mem;
X		oldbufsiz = bufsiz;
X		mem = (char *) Malloc(bufsizs[bufsiz]);
X		if (mem != NULL) {
X			if (memalloced != NULL)
X				Mfree(memalloced);
X			memalloced = mem;
X			ioptr->io_buff = mem;
X			ioptr->io_bufsiz = bufsizs[bufsiz];
X			ioptr->io_head = 0;
X			ioptr->io_tail = 0;
X			ioptr->io_low = bufsizs[bufsiz] / 4;
X			ioptr->io_high = ioptr->io_bufsiz - ioptr->io_low;
X		}
X	}
X}
SHAR_EOF
chmod 0600 WINIO.C || echo "restore of WINIO.C fails"
sed 's/^X//' << 'SHAR_EOF' > WINMAIN.C &&
X/* multi-window terminal emulation Version 0.2, May 29th 1986
X *
X * (C) Copyright 1986 Hans-Martin Mosner, University of Dortmund, Germany
X * You may freely use and distribute this program as source
X * and/or binary provided you make no profit with it.
X */
X
X#include <obdefs.h>
X#include <gemdefs.h>
X#include <osbind.h>
X#include <stdio.h>
X#include <bios.h>
X#include <xbios.h>
X#include "wind.h"
X#include "uw.h"
X#include "windefs.h"
X
X#define FIRSTOBJ DABOUT
X#define LASTOBJ PRTSTOP
X
X
X/* global constants
X */
X
Xextern	int		gl_apid;
Xextern	struct	wi_str	w[];
X
Xint	contrl[12];
Xint	intin[128];
Xint	ptsin[128];
Xint	intout[128];
Xint	ptsout[128];
Xint	work_in[11];
Xint	work_out[57];
Xint	pxyarray[20];
Xint	msgbuff[8];
X
Xint	phys_handle, handle;
X
X/*
X * Variables used by various routines (miscellaneous).
X */
X
Xlong	dummy;				/* dummy return variable */
Xint	scr_x, scr_y, scr_w, scr_h;	/* size of screen */
Xint	key;				/* the key pressed */
Xint	tmp;				/* temporary for anything... */
Xchar	alert[300];			/* used for alerts */
Xint	xsiz, ysiz;			/* temporarys for size of window */
X
X/*
X * Character stuff (fonts, keymaps).
X */
XFNT	*fnttbl[10];			/* List of pointers to fonts avail */
Xint	fontsavail;			/* Number of fonts available */
XFNT	*tempfont;			/* font pointer */
Xchar	*oldshifted;			/* Pointer to old shifted key map. */
Xchar	*oldnormal;			/* Pointer to old normal key map. */
Xchar	*oldcapslock;			/* Pointer to old caps lock key map. */
Xint	menu_key_map[0x80];		/* menu objects indexed by key map
X					   (alt key) read from object file */
Xint fontmenuobj[] =			/* array of font menu object numbers */
X  { FNTBIG,
X    FNTSYS,
X    FNTOWN,
X    FNTALT,
X    FNTTINY,
X    FNTUNKNW,
X    /* Add new font menu items here! */
X    0
X  };
Xextern	FNT	*loadfont();
X
X/*
X * State (loosely defined).
X */
Xint	tick;				/* used for flashing cursor */
Xint	outport;			/* ports used with uw */
Xint	inwind, outwind;		/* windows for input/output */
Xint	uw_runs;			/* is uw running ? */
XFNT	*curfont;			/* font in use */
Xint	mouse;				/* is mouse visible ? */
Xint	menonoff;			/* Menu toggle. */
Xint	m1inout;			/* mouse event  enter = 0  exit = 1 */
Xint	sel_inp_mode;			/* input select with right button */
Xextern int highlighted_wdes;		/* window with text highligted */
X#define LOCKLEN 30			/* Max length of lock password */
Xchar	lockword[LOCKLEN];		/* lock password */
Xchar	lockbld[LOCKLEN];		/* lock password build area*/
Xextern int kermwdes;			/* port number for kermit window */
X
X/*
X * Options (somewhat loosely defined).
X */
Xint	fast;				/* flag for fast open/close */
Xint	overstrike;			/* flag for character drawing */
Xint	sliders;			/* flag for sliders on new windows */
Xint	titles;				/* flag for titles on new windows */
Xint	audibell;			/* Audible bell. */
Xint	visibell;			/* Visible bell. */
Xint	toponbel;			/* Top window on bell. */
X
XFUNCSTRING fstrings[NFSTRINGS];		/* storage for function key bodys */
X
Xchar	pastebuff[4096] = "";		/* 50 full lines of text */
X
Xchar	confpath[80] = ".\\*.*";	/* initial config file path */
Xchar	confname[40] = "win.cnf";	/* initial config file name */
Xint	confbutt;			/* button from fsel_input */
X
X/*
X * Screen forms, objects, and other similar goodies...
X */
XMFDB	screen_mf;
X
XOBJECT	*obj_tmp, *menubar;
XTEDINFO	*ted_tmp;
XTEDINFO	*ted_fnum;
X
Xextern struct iorec old_iorec;	/* copy of old rs_232 io record from winio.c */
X
XMFORM	rmbmform[1];
XMFORM	lckmform[1];
X
X#define	CHECKWIN	if (!outwind) break
X
X/*
X * The program code...
X */
X
Xextern	char	*getmem();
X#ifdef	MWC
X#include <linea.h>
X#endif
X
X/*
X * If LOCATE is defined, it is assumed to be the path to check after
X * "." for standard files (fonts, config files, etc.).
X */
X#ifndef	LOCATE
X#define	locate(n)	n
X#else
Xchar	locpath[64] = LOCATE;
X
Xchar	*
Xlocate (name)
Xchar	*name;
X{
X	int	fd;
X	static	char	new[80];
X
X	close(fd = open(name, 0));
X	if (fd >= 0)
X		return (name);
X
X	sprintf(new, "%s\\%s", locpath, name);
X	close(fd = open(new, 0));
X	return (fd >= 0? new: name);
X}
X#endif
X
Xstartup()
X{
Xint i,j;
Xchar *tmpfnt;
Xstatic char my_shft_map[128];
Xstatic char my_norm_map[128];
X
X#ifndef	MWC
Xregister GEMFONT **a5;		/* this is really register A5 */
X#endif
X
X  /* start up everything: appl_init, menu, and the like
X   */
X  appl_init();
X  rsrc_load(locate("wind.rsc"));
X  rsrc_gaddr(R_TREE, MENUBAR, &menubar);
X
X  /*
X   * Fill menu_key_map by scaning object strings for ALTINDICATOR.
X   */
X  for (i = FIRSTOBJ; i <= LASTOBJ; i++)
X    if (menubar[i].ob_type == G_STRING)
X    {
X      char * found;
X      char * index();
X
X      found = index((char *)menubar[i].ob_spec, ALTINDICATOR);
X      if (found != NULL)
X      {
X        menu_key_map[*(++found) & 0x7f] = i;
X#ifdef DEBUG
X        printf("menu_key_map[%c] = %d\n", *found, i);
X#endif
X      }
X    }
X
X/*  objc_change(menubar, VISIBELL, 0, 0, 0, 0, 0, CHECKED, 0); *already done*/
X  menu_bar(menubar, menonoff = 1);
X  m1inout = 1;
X  audibell = 1;
X  visibell = 1;
X  sliders = 1;
X  titles = 1;
X
X  /* set mouse symbol to arrow
X   */
X  graf_mouse(ARROW, NULL);
X  mouse = 1;
X
X  /* get screen handle and sizes;
X   * open virtual workstation
X   */
X  phys_handle = graf_handle(&dummy, &dummy, &dummy, &dummy);
X  wind_get(0, WF_WORKXYWH, &scr_x, &scr_y, &scr_w, &scr_h);
X  for (i=0; i<10; work_in[i++]=1);
X  work_in[10] = 2;
X  handle = phys_handle;
X  v_opnvwk(work_in, &handle, work_out);
X
X  /* set up screen mfdb
X   */
X
X  screen_mf.ptr = NULL;
X  screen_mf.wpix = 640;
X  screen_mf.hpix = 400;
X  screen_mf.wwords = 40;
X  screen_mf.format = 0;
X  screen_mf.planes = 1;
X
X  /*
X   * now set up the system fonts
X   */
X  fontsavail = 0;
X  if ((curfont = getmem((long)sizeof(FNT))) != NULL)
X  {
X#ifdef	MWC
X    linea0();
X    tmpfnt = la_init.li_a1[2]->font_data;	/* 8 x 16 system font */
X#else
X    asm("dc.w $a000");		/* get font addresses from line A */
X    asm("move.l a1,a5");		/* put it into A5 */
X    tmpfnt = a5[2]->ft_data;
X#endif
X    for (i=0; i<128; i++)
X      for (j=0; j<16; j++)
X        curfont->f_data[i*16+j] = tmpfnt[i+j*256];
X    curfont->inc_x = 8;
X    curfont->inc_y = 16;
X
X    set_menu_string("8 x 16 sys font", fontmenuobj[fontsavail]);
X
X    curfont->def_win_x = 80;	/* Set default window size */
X    curfont->def_win_y = 24;
X
X    gen_hash(curfont, &curfont->f_hash);
X
X    fnttbl[fontsavail] = curfont;
X    fontsavail++;
X  }
X  /* set up 6 x 6 system font */
X  if ((curfont = getmem((long)sizeof(FNT))) != NULL)
X  {
X#ifdef	MWC
X    linea0();
X    tmpfnt = la_init.li_a1[0]->font_data;
X#else
X    asm("dc.w $a000");		/* get font addresses from line A */
X    asm("move.l a1,a5");		/* put it into A5 */
X    tmpfnt = a5[0]->ft_data;
X#endif
X    for (i=0; i<128; i++){ /* for each character (first 128) */
X      int bitpos, index, offset;
X
X      bitpos = i*6;
X      index = bitpos >> 3;
X      offset = bitpos & ~(~0<<3);
X      for (j=0; j<6; j++) /* for each pixel row in character */
X        curfont->f_data[i*16+j+1] = ((tmpfnt[index+j*192] << offset) +
X	  (tmpfnt[index+j*192+1] >> (8-offset) & ~(~0<<offset)))>>2 & 63;
X      curfont->f_data[i*16+0] = 0; /* extra empty row */
X    }
X    curfont->inc_x = 6;
X    curfont->inc_y = 7;
X
X    /*
X     * The 6x6 system font can be made better.  (dot the i etc.)
X     * This is a bad hack, but it makes it easier to read.
X     */
X    curfont->f_data[105*16+1] = 8;
X    curfont->f_data[105*16+2] = 0;
X    curfont->f_data[105*16+5] = 8;
X    curfont->f_data[106*16+5] = 20;
X    curfont->f_data[106*16+6] = 8;
X    curfont->f_data[106*16+2] = 0;
X
X    curfont->def_win_x = 80;	/* Set default window size */
X    curfont->def_win_y = 40;
X
X    set_menu_string("6 x 7 sys font", fontmenuobj[fontsavail]);
X    gen_hash(curfont, &curfont->f_hash);
X
X    fnttbl[fontsavail] = curfont;
X    fontsavail++;
X  }
X
X  /*
X   * Load font file(s) if any.
X   */
X
X  if (curfont = loadfont("windstd.fnt")) /* yes, I want the assignment (=). */
X  {
X    objc_change(menubar, fontmenuobj[fontsavail-1], 0, 0, 0, 0, 0, CHECKED, 0);
X    curfont->def_win_x = 80;	/* Set default window size */
X    curfont->def_win_y = 24;
X  }
X  else {
X    objc_change(menubar, FNTSYS, 0, 0, 0, 0, 0, CHECKED, 0);
X    curfont = fnttbl[fontsavail - 1];
X  }
X
X  if (tempfont = loadfont("windalt.fnt"))
X  {
X    tempfont->def_win_x = 80;	/* Set default window size */
X    tempfont->def_win_y = 32;
X  }
X
X  if (tempfont = loadfont("windtny.fnt"))
X  {
X    tempfont->def_win_x = 80;	/* Set default window size */
X    tempfont->def_win_y = 48;
X  }
X  if (tempfont = loadfont("windoth.fnt"))
X  {
X    tempfont->def_win_x = 80;	/* Set default window size */
X    tempfont->def_win_y = 24;
X  }
X  
X  /*
X   * Disable unused font entrys.
X   */
X  for (i = fontsavail; fontmenuobj[i] != 0; i++)
X  {
X    set_menu_string("unavailable font", fontmenuobj[i]);
X    objc_change(menubar, fontmenuobj[i], 0, 0, 0, 0, 0, DISABLED, 0);
X  }
X    
X
X  /* set up the serial line (XON/XOFF flow control)
X   */
X
X  Rsconf(-1, 1, -1, -1, -1, -1);
X
X  /* Initalize function keys to default values.
X   */
X  for (i=0; i<NFSTRINGS; i++)
X  {
X    sprintf(fstrings[i], "^A%d^M", i);
X  }
X  fstrings[NFSTRINGS-1][0] = '\0'; /* last function zero length for coding */
X
X  /* Set up the key tables to use the help key for break.
X   */
X  oldshifted = ((struct keytbl *) Keytbl(-1L, -1L, -1L))->kt_shifted;
X  oldnormal = ((struct keytbl *) Keytbl(-1L, -1L, -1L))->kt_normal;
X  oldcapslock = ((struct keytbl *) Keytbl(-1L, -1L, -1L))->kt_capslock;
X
X  for (i=0; i<128; i++) { /* copy bios tables */
X    my_shft_map[i] = oldshifted[i];
X    my_norm_map[i] = oldnormal[i];
X  }
X
X  my_shft_map[KC_HELP] = 0x6f; /* except help key */
X  for (i=KC_F1; i<=KC_F10; i++) { /* and function keys */
X    my_norm_map[i] = 0x6f;
X  }
X#ifdef COMMENT
X  /*
X   * These keys must be decoded manualy so that the field editing
X   * of gem will not be impacted.
X   */
X  my_norm_map[KC_CDOWN] = 0x0a; /* and cursor motion keys (for adm31) */
X  my_norm_map[KC_CLEFT] = 0x08;
X  my_norm_map[KC_CRIGHT] = 0x0c;
X  my_norm_map[KC_CUP] = 0x0b;
X#endif
X/* (void) Keytbl(my_norm_map, my_shft_map, my_norm_map); */
X  (void) Keytbl(my_norm_map, my_shft_map, -1L);
X  
X  form_dial(FMD_START, 0, 0, 0, 0, scr_x, scr_y, scr_w, scr_h);
X  form_dial(FMD_FINISH, 0, 0, 0, 0, scr_x, scr_y, scr_w, scr_h);
X  
X  /*
X   * Read initial configuration file if any
X   */
X  read_config("", locate(confname));
X}
X
Xfinish()
X{
Xint i;
Xstruct iorec *ioptr;
X
X  /* close all windows and clean up
X   */
X
X  if (uw_runs) xmitcmd(CB_FN_MAINT|CB_MF_EXIT);
X  for (i=0; i<MAX_WIND; i++)
X    w_close(i);
X  (void) Keytbl(oldnormal, oldshifted, oldcapslock); /* restore key maps */
X
X  if (old_iorec.io_bufsiz != 0) {
X    ioptr = Iorec(0);	/* restore rs_232 io record */
X    *ioptr = old_iorec;
X  }
X
X  menu_bar(menubar, 0);
X  v_clsvwk(handle);
X  appl_exit();
X  exit();
X}
X
Xmemory()
X{
Xlong m = Malloc(-1L);
X
X  sprintf(alert, "[0][Free memory: %ld bytes][Ok]", m);
X  form_alert(1, alert);
X}
X
Xmain()
X{
X  long _stksiz = 4096l;		/* Tell Mark Williams C we need 4k stack */
X  int	event;
X  int	menuitem = 0;		/* Alt sequence mapped to menu item */
X  int	cx, cy, cw, ch;
X  int	mx, my, mb, mk;		/* mouse coordinates from event_multi */
X  int	ww, wh;			/* window width & height for move */
X  int	buttonstate = 2;	/* button state to wait for next. */
X  int	clicks;			/* number of clicks seen by evnt_multi. */
X  register int	cnt;
X  int	funcindex = 0;
X  int	regionflag = 0;		/* indicates region selection in progress */
X  int	locked = 0;		/* keyboard and mouse locked with password ?*/
X  startup();
X
X  xsiz = curfont->def_win_x;
X  ysiz = curfont->def_win_y;
X
Xinit:
X  w_open(1, "Terminal", xsiz, ysiz);
X  outport = 1;
X  inwind = outwind = find_wind(1);
X  printer_mark(outwind);
X
X  for (;;)
X  {
X    if (!mouse)
X    {
X      graf_mouse(M_ON, NULL);
X      ++mouse;
X    }
X    if (menuitem)
X    {
X      event = MU_MESAG;
X      msgbuff[0] = MN_SELECTED;
X      msgbuff[4] = menuitem;
X      menuitem = 0;
X    }
X    else
X    {
X      event = evnt_multi(MU_MESAG | MU_KEYBD | MU_TIMER | MU_BUTTON | MU_M1,
X	2, 2, buttonstate,
X	m1inout, scr_x, scr_y, scr_w, scr_h,
X	0, 0, 0, 0, 0,
X	msgbuff, 15, 0,
X	&mx, &my, &mb, &mk,
X	&key, &clicks);
X    }
X
X    if (event & MU_KEYBD)
X    if (locked) {
X      static char lockkey[LOCKLEN];
X      static int lockindex;
X      int keyval = key & 0xff;
X      
X      if (keyval == '\r') {
X        lockkey[lockindex] = '\0';
X        if (strcmp (lockkey, lockword) == 0) {
X          graf_mouse(ARROW, &dummy);
X          menu_bar(menubar, menonoff);
X	  locked = 0;
X	}
X	lockindex = 0;
X      }
X      else 
X        if (lockindex < LOCKLEN - 1)
X          lockkey[lockindex++] = keyval;
X    }
X    else
X    {
X      int i, j;
X      int outcount;
X      int keyindex = key >> 8;
X      int keyval = key & 0xff;
X      int funcindex = NFSTRINGS;
X      char outputstring[MAXFUNCLEN];
X
X#ifdef DEBUG
X      printf("keyindex = %x, keyval = %x\n", keyindex, keyval);
X#endif
X
X      /*
X       * Decode key for function keys or other special keys
X       * This section could be made faster at the expense of less clear
X       * code.  It seems to be fast enough for now. (How fast can you type?)
X       * It should probrably be table driven.
X       */
X      if (keyindex >= KC_F1 || (keyval == 0 
X        && keyindex != 0x39 /* ctl-space */ && keyindex != 3 /* ctl-@ */))
X      {	/* decode these keys manualy */
X        if (keyindex >= KC_F1 && keyindex <= KC_F10) /* Unshifted F keys */
X        {
X	  if (keyval == 0x6f)	/* plain function key */
X	    funcindex = keyindex - KC_F1;
X
X	  else if (keyval == 0x0f)/* control function key */
X	    funcindex = keyindex - KC_F1 + 10;
X
X	  else if (keyval == 0)	/* alt function key */
X	    funcindex = keyindex - KC_F1 + 30;
X        }
X
X        else if (keyindex >= KC_F1+25 && keyindex <= KC_F10+25) /* shift F */
X          funcindex = keyindex - KC_F1 - 25 + 20;
X
X	else if (key == (KC_CDOWN << 8))
X	  keyval = 0x0a;
X
X	else if (key == (KC_CLEFT << 8))
X	  keyval = 0x08;
X
X	else if (key == (KC_CRIGHT << 8))
X	  keyval = 0x0c;
X
X	else if (key == (KC_CUP << 8))
X	  keyval = 0x0b;
X
X        else if (key == 0x626f) /* break key (shift help) */
X        {
X          long	clk_time;
X	
X	  clk_time = clock();
X	  Rsconf(-1, -1, -1, -1, 9, -1); /* set break condition */
X	  while (clock() - clk_time < BREAK_TICKS); /* delay while break is sent */
X	  Rsconf(-1, -1, -1, -1, 1, -1); /* clear break condition */
X	  funcindex = NFSTRINGS - 1; /* last function key is zero length */
X	}
X	else if (keyval == 0)
X	{	/* check if alt key used to select menu entry */
X	  if (keyindex >= 0x78 && keyindex <= 0x7e)
X	  {	/* alt number used to select window number */
X	    int newwind = keyindex - 0x77;
X
X	    if (find_port(newwind) > 0)
X	      w_top(newwind);
X	  }
X	  else
X	  {	/* alt key short-hand--fake menu message next time around */
X	    menuitem = menu_key_map[oldnormal[keyindex] & 0x7f];
X#ifdef DEBUG
X	    printf("menu keyindex = %x, char = %c, menuitem = %d\n",
X	      keyindex, oldnormal[keyindex], menuitem);
X#endif
X	  }
X	  funcindex = NFSTRINGS - 1; /* last function key is zero length */
X	}
X      }
X      if (funcindex < NFSTRINGS) /* if function key */
X      {		/* copy function string to outputstring decoding ^ */
X	j=0;
X	outcount = 0;
X        for (i=0; fstrings[funcindex][i] != '\0'; i++)
X	{
X	  outputstring[j] = fstrings[funcindex][i];
X	  if (outputstring[j] == '^')
X	  {
X	    i++;
X	    if (fstrings[funcindex][i] == '?')
X	      outputstring[j] = '\177';
X	    else if (fstrings[funcindex][i] != '^')
X	      outputstring[j] = fstrings[funcindex][i] & 0x1f;
X	  }
X	  j++;
X	}
X	outcount = j;
X      }
X      else	/* normal key press */
X      {
X        outputstring[0] = keyval & 0x7f;
X	outcount = 1;
X      }
X      /*
X       * Now output outcount characters which are stored in outputstring.
X       */
X      proto_out(outport, outputstring, outcount);
X    }
X
X    if (event & MU_TIMER)
X    {
X      if (tick++ > 20)
X      {
X	w_flash(outwind, 2);
X	tick = 0;
X	if (kermwdes) kermtimchk();
X      }
X      /* act on any input from serial port */
X      if (proto_in () < 0) goto init	/* uw mode ended? */;
X    }
X
X    if (event & MU_MESAG)
X    {
X      switch (msgbuff[0])
X      {
X      case MN_SELECTED:
X	switch (msgbuff[4])
X	{
X	case REMSHELL:
X	case SHELLOTH:
X	case SHELL32:
X	case SHELL24:
X	case SHELL12:
X	case SHELL8:
X	  if (msgbuff[4] == REMSHELL)
X	  {	/* default window size */
X            xsiz = curfont->def_win_x;
X	    ysiz = curfont->def_win_y;
X	  }
X	  else if (msgbuff[4] == SHELLOTH)
X	  {
X	    if (!size_dial()) break;
X	  }
X	  else
X	  {	/* size specified in menu string */
X	    char *ent_str;
X
X	    ent_str = (char *) menubar[msgbuff[4]].ob_spec;
X	    sscanf(ent_str, "%*s%d%*s%d", &ysiz, &xsiz);
X	  }
X	  if (uw_runs)
X	  {
X	    tmp = w_open(0, "Terminal", xsiz, ysiz);
X	    if (tmp)
X	    {
X	      outport = tmp;
X	      outwind = find_wind(tmp);
X	      xmitcmd(CB_FN_NEWW|tmp);
X	    }
X	  } else
X	  {
X	    form_alert(1, "[1][UW is not running][Ok]");
X	  }
X	  break;
X
X	case LOCCOPY:
X	  for (cnt=1; cnt<MAX_WIND; cnt++)
X	  {
X	    if (!find_wind(cnt))
X	    {
X	      break;		/* a free port */
X	    }
X	  }
X	  if (cnt < MAX_WIND)
X	  {
X	    static int c[8];
X	    struct wi_str *wp1 = &w[outwind];
X	    struct wi_str *wp2;
X	    outport = w_open(cnt, "Local Copy", wp1->x_chrs, wp1->y_chrs);
X	    outwind = find_wind(outport);
X	    wp2 = &w[outwind];
X	    c[0] = wp1->m_off;
X	    c[1] = wp1->top_y;
X	    c[2] = c[0] + wp1->wi_mf.wpix;
X	    c[3] = c[1] + wp1->wi_mf.hpix;
X	    c[4] = wp2->m_off;
X	    c[5] = wp2->top_y;
X	    c[6] = c[4] + wp2->wi_mf.wpix;
X	    c[7] = c[5] + wp2->wi_mf.hpix;
X	    vro_cpyfm(handle, FM_COPY, c, &wp1->wi_mf, &wp2->wi_mf);
X	    wp2->w_local = TRUE;
X	  }
X	  break;
X
X	case WINRESIZ:
X	  if (!size_dial()) break;
X	  w_resize(outwind, xsiz, ysiz);
X	  break;
X
X	case FQUIT:
X	  finish();
X
X	case FQUITUW:
X	  if (uw_runs)
X	  {
X	  int i;
X	    xmitcmd(CB_FN_MAINT|CB_MF_EXIT);
X	    uw_runs = 0;
X	    for (i=1; i<8; i++)
X	    {
X	      w_close(find_wind(i));
X	    }
X	    menu_tnormal(menubar, msgbuff[3], 1);
X	    goto init;
X	  }
X	  break;
X
X	case LOADCONF:
X	  fsel_input(confpath, confname, &confbutt);
X	  if (confbutt) 
X	    read_config(confpath, confname);
X	  break;
X
X	case SAVECONF:
X	  fsel_input(confpath, confname, &confbutt);
X	  if (confbutt) 
X	    write_config(confpath, confname);
X	  break;
X
X	case CAPTURE:
X	  if (outwind)
X	  {
X	    WI_STR *wp = &w[outwind];
X
X	    fsel_input(wp->wi_fpath, wp->wi_fname, &confbutt);
X	    if (confbutt)
X	      setcapture(wp);
X	  }
X	  break;
X
X	case COMMAND:
X	  do_exec();
X	  break;
X
X	case SETPATH:
X	  do_path();
X	  break;
X
X	case KERMIT:
X	  kerminit(outwind);
X	  break;
X
X	case FLOCKKEY:
X	  s_dial(LOCKINFO, 1);
X	  cnt = 0;
X	  while ((key = evnt_keybd() & 0xff) != '\r') {
X	    if (key == '\033') {	/* ESC means use old password */
X	      locked = 1;
X	      strcpy(lockbld, lockword);
X	      break;
X	    }
X	    if (cnt < LOCKLEN - 1)
X	      lockbld[cnt++] = key;
X	  }
X	  while (! locked) {
X	    lockbld[cnt] = '\0';
X	    locked = 1;
X	    cnt = 0;
X	    while ((key = (evnt_keybd() & 0xff)) != '\r')
X	      if (cnt < LOCKLEN - 1)
X	        if (key != lockbld[cnt++]) {
X		  locked = 0;
X		  lockbld[cnt - 1] = key;
X		}
X	    if (lockbld[cnt] != '\0')
X	      locked = 0;
X	  }
X	  if (lockbld[0] == '\0')
X	    locked = 0;
X	  if (locked) {
X	    strcpy(lockword, lockbld);
X	    menu_bar(menubar, 0);
X	    graf_mouse(USER_DEF, lckmform);
X	  }
X	  s_dial(LOCKINFO, 2);
X	  break;
X
X	case DABOUT:
X	  if (s_dial(ABOUT, 3) == MOREINF1)
X	  {
X	    if (s_dial(INFO1, 3) == CONT1)
X	    {	/* give short help screens */
X	      if (s_dial(INFO2, 3) == CONT2)
X	      {
X	        if (s_dial(INFO3, 3) == CONT3)
X	        {
X	          if (s_dial(INFO4, 3) == CONT4)
X	          {
X		    s_dial(INFO5, 3);
X	          }
X	        }
X	      }
X	    }
X	  }
X	  break;
X
X	case WRENAME:
X	  CHECKWIN;
X	  rsrc_gaddr(R_TREE, NEWNAME, &obj_tmp);
X	  ted_tmp = (TEDINFO *) obj_tmp[FLD1].ob_spec;
X	  strcpy(ted_tmp->te_ptext, w[outwind].name);
X	  form_center(obj_tmp, &cx, &cy, &cw, &ch);
X	  form_dial(FMD_START, 0, 0, 20, 10, cx, cy, cw, ch);
X	  if (!fast) form_dial(FMD_GROW, 0, 0, 20, 10, cx, cy, cw, ch);
X	  objc_draw(obj_tmp, 0, 5, cx, cy, cw, ch);
X	  tmp = form_do(obj_tmp, FLD1);
X	  if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch);
X	  form_dial(FMD_FINISH, 0, 0, 20, 10, cx, cy, cw, ch);
X	  objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0);
X	  if (tmp == OKRENAME) w_rename(outwind, (char *) ted_tmp->te_ptext);
X	  break;
X
X	case FUNCTKEY:
X	  rsrc_gaddr(R_TREE, FUNCTEDT, &obj_tmp);
X	  ted_fnum = (TEDINFO *) obj_tmp[FUNCNAME].ob_spec;
X	  sprintf(ted_fnum->te_ptext, "%2d", funcindex+1);
X	  ted_tmp = (TEDINFO *) obj_tmp[FUNCBODY].ob_spec;
X	  strcpy((char *) ted_tmp->te_ptext, fstrings[funcindex]);
SHAR_EOF
echo "End of part 3, continue with part 4"
echo "4" > s2_seq_.tmp
exit 0