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

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

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

#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file WINMAIN.C continued
#
CurArch=4
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' >> WINMAIN.C
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 = 0;
X	  while (tmp != FUNCEXIT)
X	  {
X	    int i;
X	    
X	    tmp = form_do(obj_tmp, FUNCNAME);
X	    switch (tmp)
X	    {
X	    case FUNCSHOW:
X	      funcindex = atoi(ted_fnum->te_ptext) - 1;
X	      if (funcindex < 0)
X	        funcindex = NFSTRINGS - 3;
X	      else if (funcindex > NFSTRINGS - 3)
X	        funcindex = 0;
X	      strcpy((char *) ted_tmp->te_ptext, fstrings[funcindex]);
X	      objc_draw(obj_tmp, FUNCBODY, 5, cx, cy, cw, ch);
X	      sprintf(ted_fnum->te_ptext, "%2d", funcindex+1);
X	      objc_draw(obj_tmp, FUNCNAME, 5, cx, cy, cw, ch);
X	      break;
X	    case FUNCPREV:
X	      funcindex --;
X	      if (funcindex < 0)
X	        funcindex = NFSTRINGS - 3;
X	      sprintf(ted_fnum->te_ptext, "%2d", funcindex+1);
X	      objc_draw(obj_tmp, FUNCNAME, 5, cx, cy, cw, ch);
X	      strcpy((char *) ted_tmp->te_ptext, fstrings[funcindex]);
X	      objc_draw(obj_tmp, FUNCBODY, 5, cx, cy, cw, ch);
X	      break;
X	    case FUNCNEXT:
X	      funcindex ++;
X	      if (funcindex > NFSTRINGS - 3)
X	        funcindex = 0;
X	      sprintf(ted_fnum->te_ptext, "%2d", funcindex+1);
X	      objc_draw(obj_tmp, FUNCNAME, 5, cx, cy, cw, ch);
X	      strcpy((char *) ted_tmp->te_ptext, fstrings[funcindex]);
X	      objc_draw(obj_tmp, FUNCBODY, 5, cx, cy, cw, ch);
X	      break;
X	    case FUNCENT:
X	      funcindex = atoi(ted_fnum->te_ptext) - 1;
X	      strcpy(fstrings[funcindex], ted_tmp->te_ptext);
X	      fstrings[funcindex][i] = ted_tmp->te_ptext[i];
X	      strcpy((char *) ted_tmp->te_ptext, fstrings[funcindex]);
X	      objc_draw(obj_tmp, FUNCBODY, 5, cx, cy, cw, ch);
X	      break;
X	    }
X	    objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 1);
X	  }
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	  break;
X
X	case MFREE:
X	  memory();
X	  break;
X
X	case MFAST:
X	  menu_icheck(menubar, MFAST, fast);
X	  fast = !fast;
X	  break;
X
X	case OVERSTRI:
X	  overstrike = !overstrike;
X	  menu_icheck(menubar, OVERSTRI, overstrike);
X	  break;
X
X	case FNTSYS:
X	case FNTOWN:
X	case FNTALT:
X	case FNTBIG:
X	case FNTTINY:
X	case FNTUNKNW:
X	/* Add new font menu items here! */
X	  for (cnt = 0; fontmenuobj[cnt] != 0; cnt++)
X	  {
X	    if (fontmenuobj[cnt] != msgbuff[4])
X	    {
X	      if (cnt < fontsavail)
X	        objc_change(menubar, fontmenuobj[cnt], 0, 0, 0, 0, 0,
X		  NONE, 0);
X	      else
X	        objc_change(menubar, fontmenuobj[cnt], 0, 0, 0, 0, 0,
X		  DISABLED, 0);
X	    }
X	    else
X	      curfont = fnttbl[cnt];
X	  }
X	  objc_change(menubar, msgbuff[4], 0, 0, 0, 0, 0, CHECKED, 0);
X	  break;
X
X	case PRTBOTOM:
X	  if (outwind)
X	  {
X	    w[outwind].ptr_status = LOG_BOTOM;
X	    printer_mark(outwind);
X	    w_rename(outwind, NULL);
X	  }
X	  break;
X
X	case PRTTOP:
X	  if (outwind)
X	  {
X	    w[outwind].ptr_status = LOG_TOP;
X	    printer_mark(outwind);
X	    w_rename(outwind, NULL);
X	  }
X	  break;
X
X	case PRTWIND:
X	  if (outwind)
X	  {
X	    printer_mark(outwind);
X	    dump_window(outwind);
X	  }
X	  break;
X
X	case PRTSTOP:
X	  if (outwind)
X	  {
X	    w[outwind].ptr_status = LOG_NONE;
X	    printer_mark(outwind);
X	    w_rename(outwind, NULL);
X	  }
X	  break;
X
X	case INPUTWIN:
X	case PASTE:
X	  sel_inp_mode = msgbuff[4];
X	  graf_mouse(USER_DEF, rmbmform);
X	  break;
X
X	case RESETAUX:
X	  if (rs232_reset())
X	    Cauxout(0x11);	/* send XOFF	*/
X	  break;
X
X	case ASSRD:		/* Assert RTS/DTR. */
X		Offgibit(~0x18);
X		break;
X
X	case RESRD:		/* Reset RTS/DTR. */
X		Ongibit(0x18);
X		break;
X
X	case AUDIBELL:
X	  audibell = !audibell;
X	  objc_change(menubar, AUDIBELL, 0, 0, 0, 0, 0,
X	    audibell? CHECKED: 0, 0);
X	  break;
X
X	case VISIBELL:
X	  visibell = !visibell;
X	  objc_change(menubar, VISIBELL, 0, 0, 0, 0, 0,
X	    visibell? CHECKED: 0, 0);
X	  break;
X
X	case TOPONBEL:
X	  toponbel = !toponbel;
X	  objc_change(menubar, TOPONBEL, 0, 0, 0, 0, 0,
X	    toponbel? CHECKED: 0, 0);
X	  break;
X	  
X	case SHRNKWIN:	/* Shrink window to iconic size */
X	  if (outwind)
X	  {
X	    outwind = w_shrink(outwind);
X	    outport = find_port(outwind);
X	  }
X	  break;
X
X	case BOTTOMTO:	/* send bottom window to top */
X	  w_bottom();
X	  break;
X
X	case WINSTYLE:	/* enable/disable sliders and arrows for new windows */
X	  sliders = !sliders;
X	  menu_icheck(menubar, WINSTYLE, sliders);
X	  break;
X
X	case HIDEWIN:	/* send top window to bottom */
X	  if (outwind = w_hide())
X	  {
X	    outport = find_port(outwind);
X	    printer_mark(outwind);
X	  }
X	  break;
X
X	case MOVEWIN:
X	  if (outwind)
X	  {
X	    graf_mouse(POINT_HAND, &dummy);
X	    evnt_button(1, 1, 1, &mx, &my, &dummy, &dummy);
X	    wind_get(outwind, WF_CURRXYWH, &dummy, &dummy, &ww, &wh);
X	    if (graf_dragbox(ww, wh, mx, my,
X	      scr_x, scr_y, scr_w + ww, scr_h + wh, &mx, &my))
X	        w_move(outwind, mx, my, ww, wh);
X	    graf_mouse(sel_inp_mode? USER_DEF: ARROW, rmbmform);
X	  }
X	  break;
X
X	case OSIZEWIN:
X	  if (outwind)
X	  {
X	    outwind = w_full(outwind);
X	    outport = find_port(outwind);
X	  }
X	  break;
X
X	case CLOSEWIN:
X	  if (outwind = proto_close(outwind))
X	  {
X	    printer_mark(outwind);
X	    outport = find_port(outwind);
X	  }
X	  if (!uw_runs && !find_wind(1))
X	  {
X	    menu_tnormal(menubar, msgbuff[3], 1);
X	    goto init;
X	  }
X	  break;
X
X	case WINTITLE:	/* enable/disable window headers */
X	  titles = !titles;
X	  menu_icheck(menubar, WINTITLE, titles);
X	  break;
X
X	case SETCONF:	/* set rs232 port configuration */
X	  getrsconf();
X	  if (s_dial(RSCONF, 3) == RCOK)
X	    setrsconf();
X	  break;
X
X	case WINCLEAR:	/* clear current window */
X	  if (outwind)
X	  {
X	    w[outwind].ptr_status = LOG_NONE;
X	    w_output(outwind, "\032");
X	  }
X	  break;
X	}
X	menu_tnormal(menubar, msgbuff[3], 1);
X	break;
X
X      case WM_NEWTOP:
X      case WM_TOPPED:
X	if (!locked)
X	  w_top(msgbuff[3]);
X	break;
X
X      case WM_SIZED:
X      case WM_MOVED:
X	if (!locked)
X	  w_move(msgbuff[3], msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
X	break;
X
X      case WM_CLOSED:
X        if (locked) break;
X	if (cnt = proto_close(msgbuff[3]))
X	{
X	  if (msgbuff[3] == outwind)	/* was keyboard input window closed? */
X	    outwind = cnt;
X	  printer_mark(outwind);
X	  outport = find_port(outwind);
X	}
X	if (!uw_runs && !find_wind(1))
X	{
X	  goto init;
X	}
X	break;
X
X      case WM_REDRAW:
X        if (highlighted_wdes == msgbuff[3])
X	{	/* this window has highlighted text, redraw all of window*/
X	  register struct wi_str *wp = &w[msgbuff[3]];
X	  w_redraw(msgbuff[3], FM_COPY, wp->x, wp->y, wp->w, wp->h);
X	}
X	else
X	  /* redraw only damaged part */
X	  w_redraw(msgbuff[3], FM_COPY, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
X	break;
X
X      case WM_FULLED:
X	if (locked) break;
X	outwind = w_full(msgbuff[3]);
X	outport = find_port(outwind);
X	break;
X
X      case WM_ARROWED:
X	if (!locked)
X	  w_arrow(msgbuff[3], msgbuff[4]);
X	break;
X
X      case WM_HSLID:
X      case WM_VSLID:
X	if (!locked)
X	  w_slide(msgbuff[3], msgbuff[0] == WM_HSLID, msgbuff[4]);
X	break;
X      }
X    }
X    if ((event & MU_BUTTON) && ! locked)
X    {
X      if (sel_inp_mode && buttonstate) /* select input mode and button down */
X      {
X        int found;
X
X	graf_mouse(ARROW, &dummy);
X	if ((found = wind_find(mx, my)) != 0) {
X	  outwind = found;
X	  outport = find_port(outwind);
X	  if (sel_inp_mode == PASTE)
X	      proto_out(outport, pastebuff, strlen(pastebuff));
X	}
X	evnt_button(1, 2, 0, &dummy, &dummy, &dummy, &dummy);
X	buttonstate = 0;
X	sel_inp_mode = FALSE;
X      }
X      else if (my < scr_y)	/* is mouse on menu bar? */
X      {	/* yes, disable menu bar if button down */
X        if (buttonstate)
X	{
X          objc_change(menubar, DESK, 0, 0, 0, 0, 0,
X            menonoff? DISABLED: NORMAL, menonoff);
X          menu_bar(menubar, menonoff = !menonoff);
X	  if (menonoff)
X	    graf_mouse(ARROW, &dummy);
X	  else
X	    graf_mouse(USER_DEF, rmbmform);
X	  evnt_button(1, 2, 0, &dummy, &dummy, &dummy, &dummy);
X	  buttonstate = 0;
X	}
X      }
X      else	/* button click in work area */
X      {	/* handle text selection or output or mouse packet */
X        int found, found1, x1, y1, x2, y2, w_x, w_y, w_w, w_h;
X
X	if ((found = wind_find(mx, my)) != 0)
X	{
X	  wind_get(found, WF_WORKXYWH, &w_x, &w_y, &w_w, &w_h);
X	  if (mx >= w_x && mx < w_x + w_w && my >= w_y && my <w_y + w_h)
X	  { /* in window, fill paste buffer */
X	    if (clicks > 1 && buttonstate)
X	    {
X	      y1 = (my - w_y - Y0) / w[found].font->inc_y;
X	      copy_text(found, 0, y1, w[found].x_chrs - 1, y1, pastebuff);
X	      evnt_button(3, 2, 0, &dummy, &dummy, &dummy, &dummy);
X	      regionflag = 0;
X	    }
X	    else if (buttonstate)	/* if button down */
X	    {
X	      x1 = (mx - w_x - X0) / w[found].font->inc_x;
X	      y1 = (my - w_y - Y0) / w[found].font->inc_y;
X	      regionflag = 1;
X	      found1 = found;
X	    }
X	    else if (regionflag && found == found1)
X	    {	/* button up */
X	      x2 = (mx - w_x - X0) / w[found].font->inc_x;
X	      y2 = (my - w_y - Y0) / w[found].font->inc_y;
X	      if (y2 == y1 && x2 == x1)
X	      {	 /* simple click on char; select word */
X	        copy_word(found, x1, y1, pastebuff);
X	      }
X	      else if (y2 > y1 || (y2 == y1 && x2 > x1))
X	        copy_text(found, x1, y1, x2-1, y2, pastebuff);
X	      else
X		copy_text(found, x2+1, y2, x1, y1, pastebuff);
X	    }
X	  }
X	  else
X	  { /* in border */
X	    /* send paste buffer and select keyboard window*/
X	    if (buttonstate)	/* if button down */
X	    {
X	      char * pptr = pastebuff;
X	      outwind = found;
X	      outport = find_port(outwind);
X	      if (clicks > 1)
X	          proto_out(outport, pptr, strlen(pptr));
X	    }
X	    regionflag = 0;
X	  }
X	}
X	else
X	{	/* not in window or border */
X		/* clear paste buffer and erase any current marks */
X	  pastebuff[0] = '\0';
X	  regionflag = 0;
X	  copy_text(1, 1, 1, 0, 0, pastebuff);
X	}
X      }
X      buttonstate = buttonstate? 0: 2;	/* toggle buttonstate */
X    }
X    if (event & MU_M1)	/* mouse moved into or out of work area */
X    {
X      if (!sel_inp_mode && !menonoff && !locked)
X	graf_mouse(m1inout? USER_DEF: ARROW, rmbmform);
X      m1inout = ! m1inout;
X    }
X  }
X}
X/*
X * printer_mark(wnd) places check marks in the apropriate places in the
X * printer menu.
X */
Xprinter_mark (wnd)
X{
X    objc_change(menubar, PRTBOTOM, 0, 0, 0, 0, 0,
X      (w[wnd].ptr_status & LOG_BOTOM)? CHECKED: NONE, 0);
X
X    objc_change(menubar, PRTTOP, 0, 0, 0, 0, 0,
X      (w[wnd].ptr_status & LOG_TOP)? CHECKED: NONE, 0);
X}
X
X/*
X * s_dial performs a simple dialog with buttons and text only.
X * The index of the terminating button is returned.
X * If action == 1, the dialog is displayed.  If action == 2, it is
X * removed.  If action == 3, both operations are done and form_do is
X * called.
X */
Xint s_dial(tree, action)
Xint tree, action;
X{
X  int tmp = 0;
X  int cx, cy, cw, ch;
X  OBJECT *obj_tmp;
X
X  rsrc_gaddr(R_TREE, tree, &obj_tmp);
X  form_center(obj_tmp, &cx, &cy, &cw, &ch);
X  if (action & 1) {
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  }
X  if (action == 3) {
X    tmp = form_do(obj_tmp, 0);
X  }
X  if (action & 2) {
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  }
X    return (tmp);
X}
X
X/*
X * set_menu_string sets the menu string for the specified menu object to
X * newstr.
X */
Xset_menu_string(newstr, object)
Xregister char * newstr;
Xint object;
X{
X  register char * oldstr;
X
X  oldstr = (char *) menubar[object].ob_spec + 2;
X  while (*oldstr && *newstr)
X    *oldstr++ = *newstr++;
X  if (*oldstr)
X  	*oldstr = ' ';
X}
X
Xsize_dial()
X{
X  /*
X   * Enter rows and columns dialog
X   */
X  int cx, cy, cw, ch;
X  char *rowstr, *colstr;
X  rsrc_gaddr(R_TREE, WINDSIZE, &obj_tmp);
X  ted_tmp = (TEDINFO *) obj_tmp[WINDROWS].ob_spec;
X  rowstr = ((char *)ted_tmp->te_ptext);
X  if (atoi(rowstr) < 2)
X    strcpy (rowstr, "24");
X  ted_tmp = (TEDINFO *) obj_tmp[WINDCOLS].ob_spec;
X  colstr = ((char *)ted_tmp->te_ptext);
X  if (atoi(colstr) < 2)
X    strcpy (colstr, "80");
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)
X    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, WINDROWS);
X  if (!fast)
X    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 == WINDCANC)
X    return(FALSE);
X  xsiz = atoi(colstr);
X  ysiz = atoi(rowstr);
X  if (xsiz < 2)
X    xsiz = 2;
X  if (xsiz > 300)
X    xsiz = 300;
X  if (ysiz < 2)
X    ysiz = 2;
X  if (ysiz > 300)
X    ysiz = 300;
X  return (TRUE);
X}
SHAR_EOF
chmod 0600 WINMAIN.C || echo "restore of WINMAIN.C fails"
sed 's/^X//' << 'SHAR_EOF' > WINPROC.C &&
X/*
X * This file contains subroutines which deal with other processes
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	char * environ;
X
Xextern struct wi_str w[];
Xextern int fast;
Xextern int	scr_x, scr_y, scr_w, scr_h;	/* size of screen */
Xextern OBJECT	*menubar;
X
Xchar cmdpath[40] = "e:\\bin\\*.*";
X					/* Path for command execution */
Xchar cmdname[40] = "msh.prg";		/* Name of command to run */
Xchar cmdargs[40] = " ";			/* Arguments for command */
X
X/*
X * Exec process from dialog.
X */
Xint do_exec()
X{
X  int status = 0;
X  int confbutt;
X
X  fsel_input(cmdpath, cmdname, &confbutt);
X  if (confbutt) {
X    extern char * rindex();
X    char cmdstr[80];
X    char cmdargv[40];
X    char *argv[20];
X    char * ind;
X    OBJECT *obj_tmp;
X    TEDINFO *ted_tmp;
X    int cx, cy, cw, ch, tmp;
X
X    strcpy(cmdstr, cmdpath);
X      ind = rindex(cmdstr, '\\');
X      if (ind) * ++ind = '\0';
X    strcat(cmdstr, cmdname);
X    form_dial(FMD_START, 0, 0, 0, 0, scr_x, scr_y, scr_w, scr_h);
X    				/* save screen */
X
X    rsrc_gaddr(R_TREE, PARAM, &obj_tmp);
X    ted_tmp = (TEDINFO *) obj_tmp[PARAMSTR].ob_spec;
X    strcpy(ted_tmp->te_ptext, cmdargs);
X    form_center(obj_tmp, &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, PARAMSTR);
X    if (!fast) form_dial(FMD_SHRINK, 0, 0, 20, 10, cx, cy, cw, ch);
X    objc_change(obj_tmp, tmp, 0, cx, cy, cw, ch, NONE, 0);
X    if (tmp != OKEXEC) {
X      form_dial(FMD_FINISH, 0, 0, 0, 0, scr_x, scr_y, scr_w, scr_h);
X      return(0);
X    }
X    strcpy(cmdargs, ted_tmp->te_ptext);
X    strcpy(cmdargv, cmdargs);
X
X    graf_mouse(M_OFF, NULL);	/* turn mouse off */
X    menu_bar(menubar, 0); 	/* menu bar off */
X    Cconws("\033E\033e");	/* clear screen, cursor on */
X    ind = cmdargv;
X    argv[0] = cmdname;
X    tmp = 1;
X    while (*ind != '\0') {
X      while (*ind == ' ' && *ind != '\0'){
X        *ind = '\0';
X        ++ind;
X      }
X      argv[tmp++] = ind;
X      while (*ind != ' ' && *ind != '\0')
X        ++ind;
X    }
X    argv[tmp] = NULL;
X    status = execve(cmdstr, argv, environ);
X    sleep(1);
X    Cconws("\033E\033f");	/* clear screen, cursor off */
X    form_dial(FMD_FINISH, 0, 0, 0, 0, scr_x, scr_y, scr_w, scr_h);
X    menu_bar(menubar, 1); 	/* menu bar on */
X    graf_mouse(M_ON, NULL);	/* turn mouse on */
X  }
X  return(status);
X}
X
X/*
X * Set current path with dialog.
X */
Xint do_path()
X{
X  int status = 0;
X  int confbutt;
X  char curpath[80];
X  char ignore[40] = "";
X  int drv;
X
X  curpath[0] = Dgetdrv() + 'a';
X  curpath[1] = ':';
X  Dgetpath(curpath+2, 0);
X  strcat(curpath, "\\*.*");
X  fsel_input(curpath, ignore, &confbutt);
X  if (confbutt) {
X    extern char * index(), *rindex();
X    char * ind;
X    ind = index(curpath, ':');
X    if (ind) {
X      drv = *(ind - 1);
X      if (drv > '\\')
X        drv -= 'a';
X      else
X	drv -= 'A';
X      if (drv >= 0 && drv <= 15)
X        Dsetdrv(drv);
X    }
X    else
X      ind = curpath;
X    *rindex(ind, '\\') = 0;
X    status = Dsetpath(++ind);
X  }
X  return(status);
X}
SHAR_EOF
chmod 0600 WINPROC.C || echo "restore of WINPROC.C fails"
sed 's/^X//' << 'SHAR_EOF' > WINPROTO.C &&
X/*
X * This file contains the routines which implement the uw protocol.
X * Code has been migrating here from winmain.c, but its not all here yet.
X */
X
X#include <stdio.h>
X#include <osbind.h>
X#include <gemdefs.h>
X#include "wind.h"
X#include "uw.h"
X#include "windefs.h"
X
X#define LIMIT	300
X
Xextern	struct	wi_str	w[];
Xextern int outport;			/* ports used with uw */
Xextern int inwind, outwind;		/* windows for input/output */
Xextern int uw_runs;			/* is uw running ? */
XFNT	*curfont;			/* font in use */
X
X/* proto_out sends length chars from str to the window defined by outport. */
Xproto_out(outport, str, length)
Xint outport, length;
Xchar *str;
X
X{
Xstatic int oldoutport = 1;
Xint key, i;
Xint outwind;
X
Xoutwind = find_wind(outport);
X  if (w[outwind].w_local == TRUE)	/* local window? */
X  {
X    char *found, *index();
X    char strcr[3] = "\r\n";
X
X    str[length] = '\0';
X    while (found = index(str, '\r'))
X    {
X      char line[500];
X      strncpy(line, str, found - str);
X      line[found-str] = '\0';
X      w_output(outwind, line);
X      w_output(outwind, strcr);
X      str = found + 1;
X    }
X    w_output(outwind, str);
X    return;
X  }
X  for (key = *str, i = 0; i < length; key = str[++i])
X  {
X    if (uw_runs)
X    {
X      if (outport != oldoutport)
X      {
X        xmitcmd(CB_FN_ISELW|outport);
X        oldoutport = outport;
X      }
X      if (key & 0x80) {
X        key &= 0x7f;
X	xmitcmd(CB_FN_META);
X      }
X      switch (key)
X      {
X      case XON:
X        xmitcmd(CB_FN_CTLCH|CB_CC_ON);
X        break;
X 
X      case XOFF:
X        xmitcmd(CB_FN_CTLCH|CB_CC_OFF);
X        break;
X
X      case IAC:
X        xmitcmd(CB_FN_CTLCH|CB_CC_IAC);
X        break;
X
X      default:
X        Bconout(1, key);
X        break;
X      }
X    } else
X      Bconout(1, key);	/* need mask with 0x7f? */
X  }
X}
X
X/*
X * proto_close closes the current window and notifies the remote.  The new
X * current window is returned.
X */
Xint proto_close(curwind)
Xint curwind;
X{
X  long dummy;
X
X  if (uw_runs && (find_port(curwind) < MAX_WIND))
X  {
X    xmitcmd(CB_FN_KILLW|find_port(curwind));
X  }
X  w_close(curwind);
X  wind_get(0, WF_TOP, &curwind, &dummy, &dummy, &dummy);
X  return (curwind);
X/*  } else
X  {
X    w_close(curwind);
X    return (0);
X  } */
X}
X
X/* proto_in receives characters from the serial port. */
Xproto_in()
X#define NORMSTATE 0
X#define IACSTATE 1
X/* #define METASTATE 2  replaced with seenmeta flag. */
X#define INITSTATE 3
X{
X  register char	*ptr;
X  char	str[LIMIT+2];
X  register char	chr;
X  register int	cnt;
X  long dummy;
X  static int state;
X  static int seenmeta = 0;
X
X      ptr = str;
X      cnt = 0;
X      while (Bconstat(1) && cnt++<LIMIT)
X      {
X	chr = Bconin(1)&0x7f;
X	switch (state)
X	{
X	case NORMSTATE:
X	  if (!chr || chr=='\177') continue;
X	  if (chr == IAC)
X	  {
X	    if (uw_runs)
X	      state = IACSTATE;
X	    else
X	      state = INITSTATE;
X	    continue;
X	  }
X	  if (seenmeta) {
X	    seenmeta = 0;
X	    *ptr++ = chr|0x80;
X	  }
X	  else *ptr++ = chr;
X	  break;
X	case INITSTATE:
X	  if (chr == CB_FN_MAINT | CB_MF_ENTRY){
X	    xmitcmd(CB_FN_MAINT|CB_MF_ENTRY);
X	    uw_runs = 1;
X	    outport = 0;
X	    outwind = 0;
X	  }
X	  else {
X	    *ptr++ = IAC;
X	    *ptr++ = chr;
X	  }
X	  state = NORMSTATE;
X	  break;
X	case IACSTATE:
X	  state = NORMSTATE;
X	  if (chr&CB_DIR_MTOH) continue;
X	  switch (chr&CB_FN)
X	  {
X	  case CB_FN_NEWW:
X	    outport = w_open(chr&CB_WINDOW, "Terminal", curfont->def_win_x,
X	      curfont->def_win_y);
X	    outwind = find_wind(outport);
X	    xmitcmd(CB_FN_ISELW|outport);
X	    break;
X
X	  case CB_FN_KILLW:
X	    w_close(find_wind(chr&CB_WINDOW));
X	    wind_get(0, WF_TOP, &outwind, &dummy, &dummy, &dummy);
X	    outport = find_port(outwind);
X	    break;
X
X	  case CB_FN_OSELW:
X	    if (inwind != find_wind(chr&CB_WINDOW))
X	    {
X	      *ptr = '\0';
X	      if (ptr != str)
X	      {
X	        if (w[inwind].kerm_act)
X		  rpack(" ", NULL, str);
X		else
X		  w_output(inwind, str);
X	      }
X	      ptr = str;
X	    }
X	    inwind = find_wind(chr&CB_WINDOW);
X	    break;
X
X	  case CB_FN_META:
X	    seenmeta = 1;
X	    break;
X
X	  case CB_FN_CTLCH:
X	    switch (chr&CB_CC)
X	    {
X	    case CB_CC_IAC:
X	      if (seenmeta) {
X	        seenmeta = 0;
X	        *ptr++ = IAC|0x80;
X	      }
X	      else *ptr++ = IAC;
X	      break;
X
X	    case CB_CC_ON:
X	      if (seenmeta) {
X	        seenmeta = 0;
X	        *ptr++ = XON|0x80;
X	      }
X	      else *ptr++ = XON;
X	      break;
X
X	    case CB_CC_OFF:
X	      if (seenmeta) {
X	        seenmeta = 0;
X	        *ptr++ = XOFF|0x80;
X	      }
X	      else *ptr++ = XOFF;
X
X	      break;
X	    }
X	    break;
X
X	  case CB_FN_MAINT:
X	    switch (chr&CB_MF)
X	    {
X	    case CB_MF_ENTRY:
X	      xmitcmd(CB_FN_MAINT|CB_MF_ENTRY);
X	      uw_runs = 1;
X	      outport = 0;
X	      outwind = 0;
X	      break;
X
X	    case CB_MF_EXIT:
X	      uw_runs = 0;
X	      return (-1);
X	    }
X	    break;
X	  }
X	  break;
X	}
X      }
X      *ptr = '\0';
X      if (ptr!=str)
X      {
X        if (w[inwind].kerm_act)
X	  rpack(" ", NULL, str);
X	else
X	  w_output(inwind, str);
X      }
X      return (0);
X}
SHAR_EOF
chmod 0600 WINPROTO.C || echo "restore of WINPROTO.C fails"
sed 's/^X//' << 'SHAR_EOF' > WINSUBR.C &&
X/* subroutines for multi-window terminal emulation
X */
X
X#include <obdefs.h>
X#include <gemdefs.h>
X#include <osbind.h>
X#include <stdio.h>
X#include "wind.h"
X#include "windefs.h"
X
Xextern int handle;
X
X/* variables used by various routines
X */
X
Xlong dummy;				/* dummy return variable */
Xextern	int	outwind, outport;	/* window selection */
Xextern	int	scr_x, scr_y;		/* size of the screen */
Xextern	int	scr_w, scr_h;
Xextern	int	fast;			/* flag for fast open/close */
Xextern	int	overstrike;
Xextern	int	sliders;		/* flag for sliders on new windows */
Xextern	int	titles;			/* flag for title bars on new windows */
Xint	tmp;				/* temporary for anything... */
Xextern	char	alert[300];		/* used for alerts */
Xextern	FNT	*curfont;		/* current font */
Xextern	MFDB	screen_mf;		/* screen descriptor */
Xextern	int	mouse;			/* for mouse on/off */
Xextern	int	audibell;		/* What happens on BEL? */
Xextern	int	visibell;
Xextern	int	toponbel;
X
Xstruct	wi_str	w[MAX_WIND];
X
X/* the program code...
X */
X
Xchar *getmem(size)
Xregister long size;
X{
X  char *got;
X
X  got = (char *) Malloc(size);
X#ifdef DEBUG
X  printf("alloc returned %lx of %ld size\n", got, size);
X#endif
X  if (got == NULL)
X  {
X    sprintf(alert, "[1][Could not get %ld bytes][Ok]", size);
X    form_alert(1, alert);
X  } else
X  {
X    bzero(got, size);
X  }
X  return got;
X}
X
Xbzero(ptr, size)
Xregister char *ptr;
Xregister long size;
X{
X  while (size--)
X    *ptr++ = 0;
X}
X
X/* find_port maps from window handles to UW port identifiers
X */
X
Xfind_port(wnd)
X{
X  return w[wnd].port;
X}
X
X/* find_wind maps from port ids to window handles
X */
X
Xfind_wind(port)
X{
Xint i;
X
X  for (i=1; i<MAX_WIND; i++)
X    if (w[i].port == port) return i;
X  return 0;
X}
X
X/* w_open opens a window with the supplied name and port and returns a port
X * number.  If port was zero, a free port is chosen.
X */
X
Xw_open(port, name, xsiz, ysiz)
Xchar *name;
X{
X  register struct wi_str *wp;
X  int wdes;
X  int i, cnt, wtyp;
X  int tmp_x, tmp_y, tmp_w, tmp_h;
X
X  if (port && find_wind(port)) return port;  /* this window is already open */
X  if (!port)
X  {
X    for (i=1; i<MAX_WIND; i++)
X    {
X      if (!find_wind(i))
X      {
X        port = i;		/* a free port */
X        break;
X      }
X    }
X  }
X
X  wtyp = (sliders ? WI_WITHSLD : 0) | (titles ? WI_NOSLD : 0);
X  wind_calc(0, wtyp, 0, 0, curfont->inc_x*xsiz+2*X0,
X    curfont->inc_y*ysiz+2*Y0, &dummy, &dummy, &tmp_w, &tmp_h);
X  if (tmp_w>scr_w)
X    tmp_w = scr_w;	/* full size <= screen size */
X  tmp_x = 10*(port-1);
X  if (tmp_h>scr_h)
X    tmp_h = scr_h;
X  tmp_y = scr_y+16*(port-1);
X
X  wdes = wind_create(wtyp, tmp_x, tmp_y, tmp_w,
X    tmp_h);
X  if (wdes < 0)
X  {
X    form_alert(1, "[1][Sorry, GEM has|no more windows|for us...][Ok]");
X    return 0;
X  }
X  wp = &w[wdes];
X  wp->wi_w = X0*2 + curfont->inc_x*xsiz;
X  wp->wi_h = Y0*2 + curfont->inc_y*ysiz;
X  wp->port = port;
X  if (!fast)
X    graf_growbox(0, 0, 20, 10, tmp_x, tmp_y, tmp_w, tmp_h);
X  wind_open(wdes, tmp_x, tmp_y, tmp_w, tmp_h);
X  wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
X  wp->fulled = 0;
X  wp->used = 1;
X  wp->x_off = 0;
X  wp->y_off = 0;
X  wp->px_off = 0;
X  wp->py_off = 0;
X  wp->m_off = wp->x & 15;
X  wp->cur_x = X0;
X  wp->cur_y = Y0;
X  wp->top_y = Y0;
X  wp->font = curfont;
X  wp->x_chrs = xsiz;
X  wp->y_chrs = ysiz;
X  wp->wi_mf.wpix = 2*X0 + xsiz*curfont->inc_x;
X  wp->wi_mf.hpix = 2*Y0 + ysiz*curfont->inc_y;
X#ifdef	KOPY
X  wp->wi_mf.wwords = ((wp->wi_mf.wpix>>5) +1) << 1;
X#else
X  wp->wi_mf.wwords = (wp->wi_mf.wpix>>4) +1;
X#endif
X  wp->wi_mf.ptr = getmem(((long)wp->wi_mf.hpix+wp->font->inc_y*MAXSCROLLED)
X				*wp->wi_mf.wwords*2);
X  wp->wi_mf.format = 0;
X  wp->wi_mf.planes = 1;
X  wp->ptr_status = LOG_NONE;
X  wp->wi_style = wtyp;
X  w_rename(wdes, name);
X  strcpy(wp->wi_fpath, ".\\*.*");
X  wp->top_age = 1;
X  for (cnt = 1; cnt < MAX_WIND; cnt++)
X    if (w[cnt].port != 0)
X      w[cnt].top_age++;
X  
X  setvslide(wdes);
X  sethslide(wdes);
X  
X  return wp->port;
X}
X
X/* w_closei removes a window but does not release its storage.
X * This is used if the window contents must be saved for later use.
X */
X
Xw_closei(wdes)
X{
X  int xx, yy, ww, hh;
X  register struct wi_str *wp = &w[wdes];
X
X  if (!wp->used) return;
X  if (wp->wi_lfd)
X    fclose(wp->wi_lfd);
X  wind_get(wdes, WF_CURRXYWH, &xx, &yy, &ww, &hh);
X  wind_close(wdes);
X  if (!fast)
X    graf_shrinkbox(0, 0, 20, 10, xx, yy, ww, hh);
X  wind_delete(wdes);
X}
X
X/* w_close removes a window.  Most work is done by GEM, although w_close
X * does some cleanup functions, too.
X */
X
Xw_close(wdes)
X{
X  register struct wi_str *wp = &w[wdes];
X
X  if (!wp->used) return;
X  w_closei(wdes);
X  Mfree(wp->wi_mf.ptr);
X  bzero(wp, (long)sizeof (struct wi_str));
X}
X
X/* w_resize resizes an existing window.
X */
X
Xw_resize(wdes, xsiz, ysiz)
X{
X  register struct wi_str *wp1 = &w[wdes];
X  struct wi_str *wp2;
X  struct wi_str ws;
X  static int c[8];
X  int port, wind, i;
X
X  if (!wp1->used) return;
X  ws = *wp1;
X  port = find_port(wdes);
X  w_closei(wdes);
X  bzero(wp1, (long)sizeof (struct wi_str));
X  port = w_open(port, "", xsiz, ysiz);
X  wind = find_wind(port);
X  wp2 = &w[wind];
X  c[0] = ws.m_off;
X  c[1] = ws.top_y + max(0, ws.wi_mf.hpix - wp2->wi_mf.hpix);
X  c[2] = c[0] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
X  c[3] = c[1] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
X  c[4] = wp2->m_off;
X  c[5] = wp2->top_y;
X  c[6] = c[4] + min(ws.wi_mf.wpix, wp2->wi_mf.wpix);
X  c[7] = c[5] + min(ws.wi_mf.hpix, wp2->wi_mf.hpix);
X  /* copy screen */
X  vro_cpyfm(handle, FM_COPY, c, &ws.wi_mf, &wp2->wi_mf);
X  /* copy parameters */
X  wp2->inverse = ws.inverse;
X  wp2->insmode = ws.insmode;
X  if (wp2->font != ws.font)
X  {
X    wp2->cur_x = X0;
X    wp2->cur_y = (wp2->y_chrs - 1) * wp2->font->inc_y + Y0;
X  }
X  else
X  {
X    wp2->cur_x = (wp2->x_chrs - 1) * wp2->font->inc_x + X0;
X    if (ws.cur_x < wp2->cur_x)
X      wp2->cur_x = ws.cur_x;
X    wp2->cur_y = max(0, ws.cur_y - c[1]) + Y0;
X  }
X  wp2->state = ws.state;
X  for (i=0; i<80; i++) wp2->nuname[i] = ws.nuname[i];
X  for (i=0; i<80; i++) wp2->wi_fpath[i] = ws.wi_fpath[i];
X  for (i=0; i<20; i++) wp2->wi_fname[i] = ws.wi_fname[i];
X  wp2->nuptr = ws.nuptr;
X  wp2->ptr_status = ws.ptr_status;
X  wp2->wi_lfd = ws.wi_lfd;
X  wp2->kerm_act = ws.kerm_act;
X  w_rename(wind, ws.name);
X  
X  Mfree(ws.wi_mf.ptr);
X  return port;
X}
X
X/* w_rename changes the title bar of a window
X */
X
Xw_rename(wdes, name)
Xchar *name;
X{
X  register struct wi_str *wp = &w[wdes];
X
X  if (name)
X    strcpy(wp->name, name);
X  if (wp->wi_style & NAME)
X  {
X    sprintf(wp->dname, " %s%s %s ", (wp->ptr_status != LOG_NONE)? "\275": "",
X      wp->wi_lfd? "\237": "", wp->name);
X    wind_set(wdes, WF_NAME, wp->dname + (wp->dname[1] == ' '), 0, 0);
X  }
X}
X
X/* w_redraw redraws part of the screen from window contents.
X * The coordinates are screen relative.
X */
X
Xw_redraw(wdes, logic, xx, yy, ww, hh)
X{
X  static int c[8];
X  static GRECT t1, t2;
X  register struct wi_str *wp = &w[wdes];
X
X  if (xx+ww > scr_w)
X    ww = scr_w - xx;
X  if (yy+hh > scr_h+scr_y)
X    hh = scr_h+scr_y - yy;
X  t2.g_x = xx; t2.g_y = yy;
X  t2.g_w = ww; t2.g_h = hh;
X  t1.g_x = wp->x; t1.g_y = wp->y;
X  t1.g_w = wp->w; t1.g_h = wp->h;
X  if (!rc_intersect(&t2, &t1)) return;	/* nothing to do... */
X  wind_update(TRUE);
X  wind_get(wdes, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
X  while (t1.g_w && t1.g_h)
X  {
X    if (rc_intersect(&t2, &t1))
X    {
X      if (mouse)
X      {
X	/* we have to do graphics, so switch the mouse off.
X	 * mouse will be switched on again in main loop.
X	 * this is ugly, but it improves speed a bit...
X	 */
X	mouse = 0;
X	graf_mouse(M_OFF, NULL);
X      }
X#ifdef	KCOPY
X      tfbmr(wp->wi_mf.ptr, t1.g_x - wp->x + wp->x_off + wp->m_off,
X	t1.g_y - wp->y + wp->y_off + wp->top_y - Y0, wp->wi_mf.wwords >> 1,
X	screen_mf.ptr, t1.g_x, t1.g_y, screen_mf.wwords >> 1,
X	t1.g_w, t1.g_h, logic);
X#else
X      c[0] = t1.g_x - wp->x + wp->x_off + wp->m_off;
X      c[1] = t1.g_y - wp->y + wp->y_off + wp->top_y - Y0;
X      c[2] = c[0] + t1.g_w - 1;
X      c[3] = c[1] + t1.g_h - 1;
X      c[4] = t1.g_x;
X      c[5] = t1.g_y;
X      c[6] = c[4] + t1.g_w - 1;
X      c[7] = c[5] + t1.g_h - 1;
X      vro_cpyfm(handle, logic, c, &wp->wi_mf, &screen_mf);
X#endif
X    }
X    wind_get(wdes, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
X  }
X  if (!fast && !mouse)
X  {
X    mouse = 1;
X    graf_mouse(M_ON, NULL);
X  }
X  wind_update(FALSE);
X}
X
X/* w_update copies a portion of the window to the screen.  Coordinates
X * are window-relative
X */
X
Xw_update(wdes, logic, xx, yy, ww, hh)
X{
X  register struct wi_str *wp = &w[wdes];
X
X  w_redraw(wdes, logic, xx + wp->x - wp->x_off, 
X  		yy + wp->y - wp->y_off - wp->top_y + Y0, ww, hh);
X}
X
X/* w_move sets the window's idea of its own position on the screen
X */
X
Xw_move(wdes, xx, yy, ww, hh)
X{
X  register struct wi_str *wp = &w[wdes];
X  int flag = 0;
X  int m_w, m_h;
X  int x1, x2;
X  int tmp;
X
X  wind_calc(1, wp->wi_style, xx, yy, ww, hh, &dummy, &dummy, &m_w, &m_h);
X  if (tmp = (m_w-2*X0)%wp->font->inc_x)
X  {
X    ww -= tmp;
X    m_w -= tmp;
X  }
X  if (tmp = (m_h-2*Y0)%wp->font->inc_y)
X  {
X    hh -= tmp;
X    m_h -= tmp;
X  }
X  if (m_w>wp->wi_w) ww = ww-(m_w-wp->wi_w);
X  if (m_h>wp->wi_h) hh = hh-(m_h-wp->wi_h);
X  wind_set(wdes, WF_CURRXYWH, xx, yy, ww, hh);
X  wind_get(wdes, WF_WORKXYWH, &wp->x, &wp->y, &wp->w, &wp->h);
X  if (wp->x_off+wp->w > wp->wi_w)
X  {
X    register int inc_x = wp->font->inc_x;
X    flag = 1;
X    wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
X  }
X  if (wp->y_off+wp->h > wp->wi_h)
X  {
X    register int inc_y = wp->font->inc_y;
X    flag = 1;
X    wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
X  }
X  x1 = wp->m_off;
X  x2 = (wp->x - wp->x_off) & 15;
X  if (x1 != x2)
X  {
X#ifdef	KOPY
X    int top = wp->top_y;
X    int cnt = wp->wi_mf.wwords >> 1;
X    cpbmr(wp->wi_mf.ptr, x1, top, cnt, wp->wi_mf.ptr, x2, top, cnt,
X      wp->wi_w, wp->wi_h);
X#else
X  int c[8];
X    c[0] = x1;
X    c[1] = wp->top_y;	/* displayed part of memory form starts here */
X    c[2] = x1 + wp->wi_w - 1;
X    c[3] = wp->wi_h - 1 + c[1];
X    c[4] = x2;
X    c[5] = c[1];
X    c[6] = x2 + wp->wi_w - 1;
X    c[7] = c[3];
X    vro_cpyfm(handle, 3, c, &wp->wi_mf, &wp->wi_mf);
X#endif
X    wp->m_off = x2;
X  }
X  if (flag)
X    w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
X  setvslide(wdes);
X  sethslide(wdes);
X}
X 
X/*
X * w_top makes win the top window.
X */
Xw_top(win)
Xint win;
X{
X  int cnt;
X
X  wind_set(win, WF_TOP, 0, 0, 0, 0);
X  outport = find_port(win);
X  outwind = win;
X  w[outwind].top_age = 0;
X  for (cnt = 1; cnt < MAX_WIND; cnt++)
X    if (find_port(cnt))	/* if window is in use */
X      w[cnt].top_age++;
X  printer_mark(outwind);
X}
X
X/*
X * w_bottom finds the bottom window and puts it on top
X */
Xw_bottom()
X{
X  int i;
X  int highwin, highcnt;
X  
X  highcnt = 0;
X  highwin = 1;
X  for (i = 1; i < MAX_WIND; i++)
X    if (w[i].top_age > highcnt)
X    {
X      highcnt = w[i].top_age;
X      highwin = i;
X    }
X  if (w[highwin].used)
X    w_top(highwin);
X}
X
X/*
X * w_hide puts the top window on the bottom.  The new top window is returned.
X */
Xint w_hide()
X{
X  int i, j;
X  int newtop, botwin, highcnt;
X  int oldtop, dum;
X  
X  wind_get(0, WF_TOP, &oldtop, &dum, &dum, &dum);
X  if (!oldtop)
X    return (0);
X  j = -1;
X  botwin = 0;
X  for (j = -1; ; j--)
X  {
X    newtop = botwin;
X    botwin = oldtop;
X    highcnt = 0;
X    for (i = 1; i < MAX_WIND; i++)
X    {
X      if (w[i].top_age > highcnt)
X      {
X        highcnt = w[i].top_age;
X        botwin = i;
X      }
X    }
X    if (botwin == oldtop)
X      break;
X    wind_set(botwin, WF_TOP, 0, 0, 0, 0);
X    w[botwin].top_age = j; /*top_age less than untouched windows (top_age < 0)*/
X  }
X  for (j = 1; j < MAX_WIND; j++)
X    if (find_port(j)) /* if window is in use */
X      w[j].top_age += MAX_WIND + 3; /* correct top_age to reflect new order */
X  return(newtop ? newtop : oldtop);
X}
X
X#define TINYX 80
X#define TINYY 70
X/*
X * w_shrink saves current size and location and shrinks to standard tiny size.
X * The second from the top non-shrunk window is placed on top.
X */
Xw_shrink(wdes)
Xint wdes;
X{
X  register struct wi_str *wp = &w[wdes];
X  int curw, dummy;
X  
X  /*
X   * Don't shrink a window that is currently shrunk
X   */
X  wind_get(wdes, WF_CURRXYWH, &dummy, &dummy, &curw, &dummy);
X  if (curw <= TINYX)
X    return;
X
X  /*
X   * Set up fulled and previous size and location window variables to tiny
X   * size.  Then call w_full
X   */
X  wp->fulled = 1;
X  wp->px = scr_x + scr_w - TINYX + 2;
X  wp->py = scr_y + (wdes - 1) * (TINYY - 2);
X  wp->pw = TINYX;
X  wp->ph = TINYY;
X  if (wp->py + 10 > scr_y + scr_h)
X  {
X    wp->py = wp->py - scr_h + 10;
X    wp->px = scr_x + scr_w - TINYY * 2;
X  }
X  
X  return (w_full(wdes));
X}
X
X/* w_full toggles size and location
X */
Xw_full(wdes)
X{
X  register struct wi_str *wp = &w[wdes];
X  int x1, y1, w1, h1;
X  int x2, y2, w2, h2;
X  int full, topwin;
X
X  full = wp->fulled;
X  if (full) {
X    x1 = wp->px;
X    y1 = wp->py;
X    w1 = wp->pw;
X    h1 = wp->ph;
X  } else
X    wind_get(wdes, WF_FULLXYWH, &x1, &y1, &w1, &h1);
X
X  wind_get(wdes, WF_CURRXYWH, &x2, &y2, &w2, &h2);
X  wp->px = x2;
X  wp->py = y2;
X  wp->pw = w2;
X  wp->ph = h2;
X  if (!fast)
X  {
X    if (w2>=w1 && h2>=h1)
X      graf_growbox(x2, y2, w2, h2, x1, y1, w1, h1);
X    else if (w2<=w1 && h2<=h1)
X      graf_shrinkbox(x1, y1, w1, h1, x2, y2, w2, h2);
X  }
X
X  x2 = wp->x_off;
X  y2 = wp->y_off;
X  wp->x_off = wp->px_off;
X  wp->y_off = wp->py_off;
X  wp->px_off = x2;
X  wp->py_off = y2;
X
X  w_move(wdes, x1, y1, w1, h1);
X  w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
X  wp->fulled = 1;
X  topwin = wdes;
X  if (h1 < TINYY + 10)
X  {
X    int lowcnt, i;
X  
X    lowcnt = 32000;
X    for (i = 1; i< MAX_WIND; i++)
X    {
X      if (find_port(i))
X      {
X        wind_get(i, WF_CURRXYWH, &x2, &y2, &w2, &h2);
X      
X        if (w[i].top_age < lowcnt && h2 > TINYY + 10 )
X        { /* find top non-tiny open window */
X          lowcnt = w[i].top_age;
X          topwin = i;
X	}
X      }
X    }
X    wind_set(topwin, WF_TOP, 0, 0, 0, 0);
X  }
X  return(topwin);
X}
X
Xw_arrow(wdes, arrow)
X{
X  register struct wi_str *wp = &w[wdes];
X  int inc_x = wp->font->inc_x;
X  int inc_y = wp->font->inc_y;
X
X  switch (arrow)
X  {
X  case 0:	/* page up */
X    wp->y_off -= wp->h/inc_y*inc_y;
X    goto y_upd;
X
X  case 1:	/* page down */
X    wp->y_off += wp->h/inc_y*inc_y;
X    goto y_upd;
X
X  case 2:	/* row up */
X    wp->y_off -= inc_y;
X    goto y_upd;
X
X  case 3:	/* row down */
X    wp->y_off += inc_y;
X    goto y_upd;
X
X  case 4:	/* page left */
X    wp->x_off -= wp->w/inc_x*inc_x;
X    goto x_upd;
X
X  case 5:	/* page right */
X    wp->x_off += wp->w/inc_x*inc_x;
X    goto x_upd;
X
X  case 6:	/* column left */
X    wp->x_off -= inc_x;
X    goto x_upd;
X
X  case 7:	/* column right */
X    wp->x_off += inc_x;
X    goto x_upd;
X  }
X
Xx_upd:
X  if (wp->x_off<0) wp->x_off = 0; else
X  if (wp->x_off+wp->w > wp->wi_w) wp->x_off = (wp->wi_w - wp->w)/inc_x*inc_x;
X  sethslide(wdes);
X  goto upd;
X
Xy_upd:
X  if (wp->y_off<0) wp->y_off = 0; else
X  if (wp->y_off+wp->h > wp->wi_h) wp->y_off = (wp->wi_h - wp->h)/inc_y*inc_y;
X  setvslide(wdes);
X  
Xupd:
X  w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
X}
X
Xw_slide(wdes, hor, val)
X{
X  register struct wi_str *wp = &w[wdes];
X
X  if (hor)
X  {
X    tmp = wp->font->inc_x;
X    wp->x_off = ((long)val*(wp->wi_w-wp->w)/1000)/tmp*tmp;
X    sethslide(wdes);
X  } else
X  {
X    tmp = wp->font->inc_y;
X    wp->y_off = ((long)val*(wp->wi_h-wp->h)/1000)/tmp*tmp;
X    setvslide(wdes);
X  }
X  w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
X}
X
Xsethslide(wdes)
X{
X  register struct wi_str *wp = &w[wdes];
X
X  if (wp->wi_style & HSLIDE)
X  {
X    tmp = (long)1000*wp->x_off/(wp->wi_w-wp->w);
X    wind_set(wdes, WF_HSLIDE, tmp, 0, 0, 0);
X    tmp = (long)1000*wp->w/wp->wi_w;
X    wind_set(wdes, WF_HSLSIZE, tmp, 0, 0, 0);
X  }
X}
X
Xsetvslide(wdes)
X{
X  register struct wi_str *wp = &w[wdes];
X
X  if (wp->wi_style & VSLIDE)
X  {
X    tmp = (long)1000*wp->y_off/(wp->wi_h-wp->h);
X    wind_set(wdes, WF_VSLIDE, tmp, 0, 0, 0);
X    tmp = (long)1000*wp->h/wp->wi_h;
X    wind_set(wdes, WF_VSLSIZE, tmp, 0, 0, 0);
X  }
X}
X
Xw_flash(wdes, state)
X{
X  register struct wi_str *wp = &w[wdes];
X  static int wdes_last;
X#ifdef	KOPY
X  int x, y, cnt;
X#else
X  int t[8];
X#endif
X
X  if (wdes != wdes_last) w_flash(wdes_last, 1);
X  wdes_last = wdes;
X  if (!wp->used || wp->curstate == state) return;
X  if (state == 2)
X    wp->curstate = !wp->curstate;
X  else
X    wp->curstate = state;
X#ifdef	KOPY
X  x = wp->cur_x + wp->m_off;
X  y = wp->cur_y;
X  cnt = wp->wi_mf.wwords >> 1;
X  tfbmr(wp->wi_mf.ptr, x, y, cnt, wp->wi_mf.ptr, x, y, cnt,
X    wp->font->inc_x, wp->font->inc_y, 12);
X#else
X  t[0] = t[4] = wp->cur_x + wp->m_off;
X  t[1] = t[5] = wp->cur_y;
X  t[2] = t[6] = t[0]+wp->font->inc_x-1;
X  t[3] = t[7] = t[1]+wp->font->inc_y-1;
X  vro_cpyfm(handle, 12, t, &wp->wi_mf, &wp->wi_mf);
X#endif
X  w_update(wdes, FM_COPY, wp->cur_x, wp->cur_y, wp->font->inc_x, wp->font->inc_y);
X}
X  
X/* w_output prints a string onto the window.  The string may
X * contain control chars and escape sequences.  It ends with \0.
X */
X
Xw_output(wdes, ptr)
Xchar *ptr;
X{
X  register struct wi_str *wp = &w[wdes];
X  static char ch;
X  static int inc_x, cur_x;
X  static int state;
X  static int inc_y, cur_y;
X#ifdef	KOPY
X  int x, w, cnt;
X#else
X  static int t[8];
X#endif
X  static int f_x, f_y, f_mod;
X  static int scrolled;	/* Number of scrolling operations delayed */
X  static int xsiz, ysiz;/* Size in chars of terminal emulation for this window*/
X  register unsigned char *sptr;
X  register unsigned long *dptr;
X  register unsigned long mask;
X  register int shift;
X  register unsigned long val;
X  static int count;
X  static char * fdata;
X  static long width;
X  static char * wimfptr;
X  static int moffincx;
X  static char * savptr;
X  
X
X#ifdef DEBUG
X  printf("entered w_output\n");
X#endif
X  if (!wp->font) return;
X  state = wp->state;
X  inc_x = wp->font->inc_x;
X  inc_y = wp->font->inc_y;
X  xsiz = wp->x_chrs;
X  ysiz = wp->y_chrs;
X  f_x = cur_x = wp->cur_x;
X  f_y = cur_y = wp->cur_y;
X  scrolled = wp->top_y/inc_y;
X  fdata = wp->font->f_data;
X  width = 2 * wp->wi_mf.wwords;
X  wimfptr = ((char *) (wp-> wi_mf.ptr)) - 2;
X  moffincx = wp->m_off + inc_x - 1;
X  f_mod = 0;
X  savptr = ptr;
X  
X  if (wp->curstate) w_flash(wdes, 0);
X
X  while (ch = *ptr++)
X  {
X    switch (state)
X    {
X    case S_NORMAL:
X      if (ch >= ' ')
X      {
X	if (wp->insmode) /* open space for character */
X	{
X#ifdef	KOPY
X	  x = cur_x + wp->m_off;
X	  cnt = wp->wi_mf.wwords >> 1;
X	  cpbmr(wp->wi_mf.ptr, x, cur_y, cnt,
X	    wp->wi_mf.ptr, x + inc_x, cur_y, cnt,
X	    (xsiz - 1) * inc_x + wp->m_off - x, inc_y);
X#else
X	  t[0] = cur_x + wp->m_off;
X	  t[1] = t[5] = cur_y;
X	  t[2] = (xsiz - 1) * inc_x + wp->m_off - 1;
X	  t[3] = t[7] = cur_y + inc_y - 1;
X	  t[4] = t[0] + inc_x;
X	  t[6] = t[2] + inc_x;
X	  vro_cpyfm(handle, 3, t, &wp->wi_mf, &wp->wi_mf);
X#endif
X	}
X	/* paint the character */
X	sptr = fdata+ch*16;
X	dptr = wimfptr + cur_y*width
X		+ (((moffincx + cur_x)>>4)<<1);
X	shift = 15 - ((moffincx + cur_x)&15);
X	if (overstrike)
X	  mask = -1L;
X	else
X	  mask = (-1L<<(shift+inc_x)|(1<<shift)-1);
X	if (wp->inverse)
X	{
X	  for (count = inc_y; count; count--)
X	  {
X	    val = ((long)(*sptr++))<<shift ^ ~mask;
X	    *dptr = (*dptr&mask)|val;
X	    ((char *)dptr) += width;
X	  }
X	} else
X	{
X	  for (count = inc_y; count; count--)
X	  {
X	    val = ((long)(*sptr++))<<shift;
X	    *dptr = (*dptr&mask)|val;
X	    ((char *)dptr) += width;
X	  }
X	}
X        cur_x += inc_x;
X	f_mod = 1;
X	if (cur_x > inc_x * xsiz) /* autowrap */
X	{
X	  cur_y += inc_y;
X	  if (cur_y >= wp->top_y + inc_y * ysiz) {
X	    if (wp->ptr_status & LOG_TOP)
X	      dump_line(wdes, 0);
X	    wp->top_y += inc_y;
X	    ++ scrolled;
X	  }
X	  if (! scrolled)
X	  {
X	    w_update(wdes, FM_COPY, f_x, f_y, cur_x-f_x, inc_y);
X	    f_mod = 0;
X	  }
X	  cur_x = X0;
X
X	  f_x = cur_x;
X	  f_y = cur_y;
X	}
X      } else /* not printable character */
X      {
X	if (f_mod && !scrolled)
X	{
X	  if (!wp->insmode)
X	    w_update(wdes, FM_COPY, f_x, f_y, cur_x - f_x, inc_y);
X	  else
X	    w_update(wdes, FM_COPY, f_x, f_y, xsiz * inc_x-f_x, inc_y);
X	  f_mod = 0;
X	}
X	switch (ch)
X	{
X	case '\007':	/* Bell */
X	  if (audibell)
X	    Bconout(2, '\007');
X	  if (toponbel)
X	    /* put this window on top but don't make it the current window.
X	     * should we set a flag so that the first input from the current
X	     * window puts it back on top?
X	     */
X	    wind_set(wdes, WF_TOP, wdes, 0, 0, 0);
X	  if (visibell)
X	  {
X	    w_redraw(wdes, FM_INVERT, wp->x, wp->y, wp->w, wp->h);
X	    w_redraw(wdes, FM_COPY, wp->x, wp->y, wp->w, wp->h);
X	    /* Should clear flag to prevent need for next update? */
X	  }
X	  break;
X
X	case '\r':	/* Carriage Return */
X	  cur_x = X0;
X	  break;
X
X	case '\b':	/* Backspace */
X	  if (cur_x>X0) cur_x -= inc_x;
X	  break;
X
X	case '\n':	/* Newline */
X	  cur_y += inc_y;
X	  if (cur_y >= inc_y * ysiz + wp->top_y)
X	  {
X	    if (wp->ptr_status & LOG_TOP)
X	      dump_line(wdes, 0);
X	    wp->top_y += inc_y;
SHAR_EOF
echo "End of part 4, continue with part 5"
echo "5" > s2_seq_.tmp
exit 0