#include <aes.h>
#include <vdi.h>
#include <gemdefs.h>
#include <osbind.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <vaproto.h>
#include <scancode.h>

typedef struct view
{
  int	handle, flag,
	lbc,			/* left-border-count fr Fenster.	*/
	tlc,			/* top-line-count fr Fenster.		*/
	bc,			/* border-count fr Fenster.		*/
	lc,			/* line-count fr Fenster.		*/
	xfac, yfac,		/* Scroll- und Rastereinheiten.		*/
	x, y, w, h,		/* Arbeitsbereich des Fensters.		*/
	hslide, vslide,		/* Puffer fr Sliderpositionen.		*/
	(*key)( struct view *tv, int code, int ks );
  void	(*draw)( struct view *tv, int *clip ),
	(*free)( struct view *tv ),
	(*sclick)( struct view *tv, int mx, int my, int flag );
  char	path[128];		/* Datei-Pfad (Fenstertitel).		*/
  struct view *next;		/* Zeiger auf nchste Fensterstruktur.	*/
  struct view *prev;		/* Zeiger auf vorige Fensterstruktur.	*/
  BASPAG *actpd;		/* Zeiger auf Prozess-Descriptor.	*/

  char	*text;
  int   font, point, line, effect, dist;
  char  dummy, null;
  char  buf[];			/* Textpuffer.				*/
}
VIEW;

#include "1stview.h"
#include "util.h"

#define TABU	9
#define Esc	27

#define TXT_THICKENED	1
#define TXT_LIGHT	2
#define TXT_SKEWED	4
#define TXT_UNDERLINED	8
#define TXT_SUPERSCRIPT 0x10
#define TXT_SUBSCRIPT	0x20

static int wchar, hchar, dist, oeffect = 0, effects = 0;
static struct { char space[104], text[408], end[]; } read_buf;
static char fontstring[] = "  XXXXXXXX-Font ^E",
	    zeilstring[] = "---XXXXX Zeilen ---",
	    savestring[] = "  >> OUT-Datei  ^X";

#pragma warn -rpt
static OBJECT popup[] =
{
   0,  1,  8, G_BOX,	NONE,	SHADOWED, 0xFF1100L,		0, 0, 19,0,
   2, -1, -1, G_STRING, NONE,	DISABLED, "--- System-Font ---",0, 0, 19,1,
   3, -1, -1, G_STRING, NONE,	NORMAL,   "  Norm  (10 Pt) ^N", 0, 0, 19,0,
   4, -1, -1, G_STRING, NONE,	NORMAL,   "  Mittel (9 Pt) ^M", 0, 0, 19,0,
   5, -1, -1, G_STRING, NONE,	NORMAL,   "  Klein  (8 Pt) ^K", 0, 0, 19,0,
   6, -1, -1, G_STRING, NONE,	DISABLED, "-------------------",0, 0, 19,1,
   7, -1, -1, G_STRING, NONE,	NORMAL,   fontstring,		0, 0, 19,1,
   8, -1, -1, G_STRING, NONE,	DISABLED, zeilstring,		0, 0, 19,1,
   0, -1, -1, G_STRING, LASTOB, NORMAL,   savestring,		0, 0, 19,1
};
#pragma warn +rpt

#if defined(__TOS__) && defined(__TURBOC__)
typedef void (*DIV_FUNC)( int numer, int denom, div_t *qr );
#define mydiv(a,b,c) (*(DIV_FUNC)((char *)div + 4))(a,b,c)
#else
#define mydiv(a,b,c) *c = div(a,b)
#endif

static int text_just( int x, int y, char *string )
{
  int ret, extent[8];
  char *p;

  vqt_extent( handle, ++string, extent );
  p = string; ret = 0; while (*p++) ret += wchar;
  dist += ret;
  if (extent[2] <= ret)
    { v_gtext( handle, x, y, string ); return extent[2]; }
  if ((effects & TXT_SKEWED) == 0)
    { v_justified( handle, x, y, string, ret, 1, 1 ); return ret; }
  if (extent[2] <= ret + wchar)
    { v_gtext( handle, x, y, string ); return ret; }
  v_justified( handle, x, y, string, ret + wchar, 1, 1 ); return ret;
}

static void set_fontpoint( int font, int point )
{
  int extent[8];

  par.font  = vst_font( handle, font );
  par.point = vst_point( handle, point, extent, extent, &dist, &hchar );
  if (effects) vst_effects( handle, effects = 0 );
  vqt_extent( handle, "W", extent ); wchar = extent[2];
  vqt_extent( handle, "l", extent ); dist += abs( wchar - extent[2] );
}

static void new_fontpoint( VIEW *tv, int font, int point )
{
  if (tv->font == font && tv->point == point) return;
  set_fontpoint( font, point );	*(long *)&tv->font = *(long *)&par.font;
  if (tv->flag < 0) tv->dist = dist;
  else { tv->dist /= tv->xfac; tv->dist *= wchar; }
  tv->bc += tv->w / tv->xfac; tv->xfac = wchar;
  tv->lc += tv->h / tv->yfac; tv->yfac = hchar;
  new_size( 0 );
}

static int draw_popup( OBJECT *tree, int i, int depth,
		       int xc, int yc, int wc, int hc )
{
  int dummy[1], hcell[1];

  tree[4].ob_flags = tree[3].ob_flags = tree[2].ob_flags = HIDETREE;
  objc_draw( tree, i, depth, xc, yc, wc, hc );
  if (effects) vst_effects( handle, effects = 0 );
  if (par.font != 1) vst_font( handle, 1 ); i = 2;
  do
  { vst_point( handle, 12 - i, dummy, dummy, dummy, hcell );
    tree[i].ob_flags = NONE;
    v_gtext( handle, tree->ob_x,
	     tree->ob_y + tree[i].ob_y + tree[i].ob_height - *hcell,
	     tree[i].ob_spec.free_string );
  }
  while (++i < 5);
  if (par.font != 1) vst_font( handle, par.font );
  vst_point( handle, par.point, dummy, dummy, dummy, dummy );
  return 0;
}

static void write_out( VIEW *tv, char *ext, int effect )
{
  int  i, fh, lines, new;
  char *p;
  FBUF f;

  if ((p = strrchr( strrchr( Path, PATHSEP ), '.' )) != 0) *p = 0;
  graf_mouse( HOURGLASS, 0 );
  if ((fh = Fcreate( strcat( Path, ext ), 0 )) < 0)
  {
    graf_mouse( ARROW, 0 ); form_error( -fh - 31 ); return;
  }
  f.handle = fh; Fbufcreate( &f );
  p = tv->buf; lines = tv->lc + tv->h / tv->yfac;
  for (;;)
    switch (i = (unsigned char)*p++)
    {
      case   0: Fputc( 13, &f ); Fputc( 10, &f );
		if (--lines == 0)
		{
		  Fbufflush( &f ); Fbufclose( &f );
		  graf_mouse( ARROW, 0 ); return;
		}
		break;
      case Esc: new = *p++ & 0x3F; if (effect < 0) break; effect ^= new;
	if (new & TXT_THICKENED)
	{
	  Fputc( 18, &f ); Fputc( effect & TXT_THICKENED ? '0' : '1', &f );
	}
	if (new & TXT_LIGHT)
	{
	  Fputc( 18, &f ); Fputc( effect & TXT_LIGHT ? 'E' : 'F', &f );
	}
	if (new & TXT_SKEWED)
	{
	  Fputc( 18, &f ); Fputc( effect & TXT_SKEWED ? '2' : '3', &f );
	}
	if (new & TXT_UNDERLINED)
	{
	  Fputc( 18,&f ); Fputc( effect & TXT_UNDERLINED ? '4' : '5', &f );
	}
	if (new & TXT_SUPERSCRIPT)
	{
	  Fputc( 18,&f ); Fputc( effect & TXT_SUPERSCRIPT ? '6' : '7',&f );
	}
	if (new & TXT_SUBSCRIPT)
	{
	  Fputc( 18, &f ); Fputc( effect & TXT_SUBSCRIPT ? '8' : '9', &f );
	}
	break;
      default:  Fputc( i, &f );
}   }

static void write_dump( VIEW *tv )
{
  int  fh, b, c;
  long count, val;
  char *p, *end, buf[8];
  FBUF f;

  if ((p = strrchr( strrchr( Path, PATHSEP ), '.' )) != 0) *p = 0;
  graf_mouse( HOURGLASS, 0 ); strupr( Path );
  if ((fh = Fcreate( strcat( Path, ".DMP" ), 0 )) < 0)
  {
    graf_mouse( ARROW, 0 ); form_error( -fh - 31 ); return;
  }
  f.handle = fh; Fbufcreate( &f ); p = tv->buf; end = tv->text; count = 0;
  do
  { b = 7; val = count;
    do
    { c = (int)val & 15; c += '0'; if (c > '9') c += 'A' - '9' - 1;
      buf[b] = c; val >>= 4;
    }
    while (--b >= 0);
    do Fputc( buf[++b], &f ); while (b < 7);
    Fputc( ':', &f ); Fputc( ' ', &f ); count += val = 16;
    for (;;)
    {
      Fputc( ' ', &f ); if (--val < 0) break;
      if (p < end)
      {
	b = (unsigned char)*p++;
	c = b >> 4; c += '0'; if (c > '9') c += 'A' - '9' - 1;
	b &= 15; b += '0'; if (b > '9') b += 'A' - '9' - 1;
      }
      else { ++p; c = b = ' '; }
      Fputc( c, &f ); Fputc( b, &f );
    }
    Fputc( ' ', &f ); p -= val = 16;
    do { c = (unsigned char)*p++; Fputc( c < ' ' ? '.' : c, &f ); }
    while (p < end && --val);
    Fputc( 13, &f ); Fputc( 10, &f );
  }
  while (p < end);
  Fbufflush( &f ); Fbufclose( &f ); graf_mouse( ARROW, 0 );
}

static void draw_text( VIEW *tv, int *clip )
{
  int  x, y, fx;
  char *text, *next;

  if (*(long *)&tv->font != *(long *)&par.font)
    set_fontpoint( tv->font, tv->point );
  vr_recfl( handle, clip ); y = clip[1];
  if (tv->lc < 0)
  {
    x = tv->y + tv->h - 1 + tv->lc * tv->yfac;
    if (clip[3] > x) if ((clip[3] = x) < y) return;
  }
  vs_clip( handle, 1, clip ); mydiv( y - tv->y, tv->yfac, (div_t *)clip );
  tv->line += x = tv->tlc - tv->line + ((div_t *)clip)->quot;
  y -= ((div_t *)clip)->rem; text = tv->text;
  if (tv->flag == 0)
  {
    char c, e = Esc;

    if (x < 0)
      do
	for (;;)
	{
	  if ((c = *--text) == 0) break;
	  if (c == e)
	  {
	    fx = 15 & Esc;
	    if (*--text != c) { fx = 15; (char)fx &= (++text)[1]; }
	    tv->effect ^= fx;
	} }
      while (++x < 0);
    if (x > 0)
      do
	for (;;)
	{
	  if ((c = *++text) == 0) break;
	  if (c == e) { fx = 15; (char)fx &= *++text; tv->effect ^= fx; }
	}
      while (--x > 0);
  }
  else
  {
    if (x < 0) do { while (*--text); } while (++x < 0);
    if (x > 0) do { while (*++text); } while (--x > 0);
  }
  if (tv->effect != effects) vst_effects( handle, effects = tv->effect );
  tv->text = next = text; x = fx = tv->x - tv->lbc * tv->xfac; dist = 0;
  for (;;)
    switch (*++next)
    {
      case 0:	 if (effects) text_just( x, y, text );
		 else v_gtext( handle, x, y, text + 1 );
		 if ((y += tv->yfac) <= clip[3])
		 {
		   x = fx; dist = 0; text = next; break;
		 }
		 vs_clip( handle, 0, clip ); return;
      case TABU: *next = 0; text_just( x, y, text ); *next = TABU;
		 x = dist; x += tv->dist; x -= x % tv->dist;
		 dist = x; x += fx; text = next; break;
      case Esc:  *next = 0; x += text_just( x, y, text ); *next++ = Esc;
		 vst_effects( handle, effects ^= *next & 15 );
		 text = next;
}   }

static void draw_dump( VIEW *tv, int *clip )
{
  int   e, f, cflag, *pintin;
  long  count, val;
  char  *pbyte;
  div_t xqr, yqr;

  if (*(long *)&tv->font != *(long *)&par.font)
    set_fontpoint( tv->font, tv->point );
  e = clip[2]; f = clip[3];
  if (tv->bc < 0)
    { int x = tv->x - 1 + 77 * tv->xfac; if (x < e) e = x; }
  if (tv->lc < 0)
    { int y = tv->y + tv->h - 1 + tv->lc * tv->yfac; if (y < f) f = y; }
  if (e < clip[2] || f < clip[3] || tv->xfac < tv->dist)
  {
    vr_recfl( handle, clip ); clip[2] = e; clip[3] = f;
    if (e < clip[0] || f < clip[1]) return;
  }
  if (effects) vst_effects( handle, effects = 0 );
  cflag = tv->dist + tv->yfac - 2;
  mydiv( clip[2] - tv->x, tv->xfac, &xqr ); e = xqr.quot+1; cflag-=xqr.rem;
  mydiv( clip[0] - tv->x, tv->xfac, &xqr ); e -= xqr.quot; cflag +=xqr.rem;
  mydiv( clip[3] - tv->y, tv->yfac, &yqr ); f = yqr.quot; cflag -= yqr.rem;
  mydiv( clip[1] - tv->y, tv->yfac, &yqr ); f -= yqr.quot;
  if ((cflag += yqr.rem) != 0) vs_clip( handle, 1, clip );
  pbyte = tv->buf; pbyte += (long)(tv->tlc + yqr.quot) << 4;
  ptsin[1] = clip[1] - yqr.rem;
  if (tv->xfac < tv->dist) { ptsin[0] = tv->x - tv->lbc * tv->xfac; e=76; }
  else { ptsin[0] = clip[0] - xqr.rem; vdipb[1] += tv->lbc + xqr.quot; }
  do
  { pintin = intin + 77;
    *--pintin = ' '; val = 15; count = tv->text - pbyte;
    while (val >= count) { *--pintin = ' '; --val; }
    do *--pintin = (unsigned char)pbyte[val]; while (--val >= 0);
    *--pintin = ' '; val = 15;
    while (val >= count)
      { int c = ' '; *--pintin = c; *--pintin = c; *--pintin = c; --val; }
    do
    { int b, c; c = (unsigned char)pbyte[val];
      *--pintin = ' ';
      b = c & 15; b += '0'; if (b > '9') b += 'A' - '9' - 1;
      *--pintin = b;
      c >>= 4; c += '0'; if (c > '9') c += 'A' - '9' - 1;
      *--pintin = c;
    }
    while (--val >= 0);
    *--pintin = ' '; *--pintin = ' ';
    *--pintin = ':'; val = pbyte - tv->buf;
    do
    { int c; c = (int)val & 15; c += '0'; if (c > '9') c += 'A' - '9' - 1;
      *--pintin = c; val >>= 4;
    }
    while (pintin > intin);
    pbyte += 16; VDI( 8, 1, e, handle ); ptsin[1] += tv->yfac;
  }
  while (--f >= 0);
  vdipb[1] = pintin; if (cflag) vs_clip( handle, 0, clip );
}

static void free_text() { load_fonts( 0 ); }

#pragma warn -par
static int key_text( VIEW *tv, int code, int ks )
{
  switch (code)
  {
    case CNTRL_N: new_fontpoint( tv, 1, 10 ); return 0;
    case CNTRL_M: new_fontpoint( tv, 1, 9 ); return 0;
    case CNTRL_K: new_fontpoint( tv, 1, 8 ); return 0;
    case CNTRL_E: AVSendMessage( AV_ASKFILEFONT, 0, 0 ); return 0;
    case CNTRL_X: strcpy( Path, tv->path );
		  if (tv->flag < 0) write_dump( tv );
		  else write_out( tv, ".OUT", 0 );
		  return 0;
    case CNTRL_C: if (set_scrp())
		    if (tv->flag < 0) write_dump( tv );
		    else {
			   write_out( tv, ".TXT", -1 );
			   write_out( tv, ".OUT", 0 );
			 }
		  return 0;
  }
  return 1;
}
#pragma warn +par

static void sclick_text( VIEW *tv, int mx, int my, int flag )
{
  if (flag)
  {
    if (flag == 1) new_fontpoint( tv, mx, my ); else par.hwin = tv->h;
    return;
  }
  popup[6].ob_state = VA_Flags & 2 ? NORMAL : DISABLED;
  strncpy( fontstring + 2, VA_Flags & 2 ? VA_Name : "VA_FILE ", 8 );
  strncpy( savestring + 5, tv->flag < 0 ? "DMP" : "OUT", 3 );
  itostring( tv->lc + tv->h / tv->yfac, zeilstring + 8, 6 );
  flag = 5; if (tv->font == 1 && tv->point <= 10) flag = 12 - tv->point;
  switch (flag = popup_menu( popup, flag, mx, my, draw_popup ))
  {
    case 2:
    case 3:
    case 4: new_fontpoint( tv, 1, 12 - flag ); break;
    case 6: AVSendMessage( AV_ASKFILEFONT, 0, 0 ); break;
    case 8: strcpy( Path, tv->path );
	    if (tv->flag < 0) write_dump( tv );
	    else write_out( tv, ".OUT", 0 );
} }

static void init_popup( void )
{
  int i, count;

  vst_point( handle, 10, &popup->ob_next,&popup->ob_next, &wchar, &hchar );
  popup->ob_next = -1; count = 0; i = 1;
  do
  { popup[i].ob_width *= wchar;
    popup[i].ob_y = count;
    count += popup[i].ob_height = popup[i].ob_height ? gl_hchar : hchar;
  }
  while (++i < 9);
  popup->ob_width *= wchar; popup->ob_height = count;
}

VIEW *load_text( int fh, long len )
{
  int  i, effect;
  char *wp, *rp, *rend;
  VIEW *rv;

  if ((rv = Malloc( (1 + sizeof(VIEW)) + len )) == 0)
    { Fclose( fh ); form_error( EINVMEM ); return 0; }
  wp = rv->text = &rv->null; *wp++ = 0; rp = wp;
  rend = rp + Fread( fh, len, rp ); Fclose( fh );
  if (popup->ob_next == 0) init_popup();
  i = 8;
  if (rend > rp && rend[-1] == TABU)
    if (--rend > rp && rend[-1] == 13)
      if (--rend > rp && rend[-1] == TABU)
	if (--rend > rp && rend[-1] == 13)
	{
	  while (--rend > rp && rend[-1] == TABU) ++i;
	  if ((i -= 8) <= 0) i = 8;
	}
  rv->dist = i; *(long *)&rv->line = 0;
  rv->lc = 0; rv->bc = 1; rv->flag = 1;
  effect = 0; len = 0;
  while (rp < rend)
    switch (i = (unsigned char)*rp++)
    {
      case   0: 
      case  10: while (wp[-1] == ' ' && wp[-2] != Esc) { --wp; --len; }
		if (len > rv->bc)
		{
		  if (len <= 512) rv->bc = (int)len;
		  else { while (*--wp); ++wp; *wp++ = 14; *wp++ = 15; }
		}
		*wp++ = 0; ++rv->lc; len = 0; break;
      case TABU: len += rv->dist; len -= len % rv->dist; *wp++ = i; break;
      case  28:				/* 1st Word Soft Space		*/
      case  29:				/* 1st Word			*/
      case  30: i = ' '; ++len; *wp++ = i; break; /* WP Wide Space	*/
      case  31: while (rp < rend && *rp++ != 10); break;
      case  11: ++rp;			/* 1st Word Soft Formfeed	*/
      case  13: break;
      case  18:	i = effect;
		switch (*rp++)
		{
		  case '0': effect |= TXT_THICKENED;	break;
		  case '1': effect &= ~TXT_THICKENED;	break;
		  case '2': effect |= TXT_SKEWED;	break;
		  case '3': effect &= ~TXT_SKEWED;	break;
		  case '4': effect |= TXT_UNDERLINED;	break;
		  case '5': effect &= ~TXT_UNDERLINED;	break;
		  case '6': effect |= TXT_SUPERSCRIPT;	break;
		  case '7': effect &= ~TXT_SUPERSCRIPT;	break;
		  case '8': effect |= TXT_SUBSCRIPT;	break;
		  case '9': effect &= ~TXT_SUBSCRIPT;	break;
		  case 'E': effect |= TXT_LIGHT;	break;
		  case 'F': effect &= ~TXT_LIGHT;
		}
		if ((i ^= effect) != 0)
		{
		  rv->flag = 0; *wp++ = Esc; *wp++ = i;
		}
		break;
      case Esc: if ((i = *rp++) != Esc)
		{
		  i &= 0x3F; i ^= effect; effect ^= i;
		  if (i)
		  {
		    rv->flag = 0; *wp++ = Esc; *wp++ = i;
		} }
		break;
      case  25: i = '-';		/* 1st Word Soft Slash		*/
      default:  ++len; *wp++ = i;
    }
  if (len > rv->bc)
  {
    if (len <= 512) rv->bc = (int)len;
    else { while (*--wp); ++wp; *wp++ = 14; *wp++ = 15; }
  }
  *wp = 0; while (--rv->lc >= 0 && *--wp == 0);
  if ((rv->lc += 2) <= 0) { Mfree( rv ); form_error( ENOENT ); return 0; }
  load_fonts( 1 ); set_fontpoint( par.font, par.point );
  if (par.textdef) AVSendMessage( AV_ASKFILEFONT, 0, 0 );
  *(long *)&rv->font = *(long *)&par.font;
  rv->dist *= rv->xfac = wchar; rv->yfac = hchar;
  rv->w = (rv->bc + 1) * wchar; rv->h = par.hwin;
  rv->draw = draw_text; rv->free = free_text;
  rv->key = key_text; rv->sclick = sclick_text;
  return rv;
}

VIEW *load_dump( int fh, long len )
{
  VIEW *rv;

  if (len > 16L * 32767) len = 16L * 32767;
  if ((rv = Malloc( sizeof(VIEW) + len )) == 0)
    if ((len = Mavail()-sizeof(VIEW)) > 0) rv = Malloc(sizeof(VIEW)+len);
    else { Fclose( fh ); form_error( EINVMEM ); return 0; }
  len = Fread( fh, len, rv->buf ); Fclose( fh );
  if (len <= 0)
  {
    Mfree(rv); form_alert( 1,"[1][|Nichts zu dumpen.][  OK  ]" ); return 0;
  }
  if (popup->ob_next == 0) init_popup();
  rv->text = rv->buf; rv->text += len; rv->flag = -1;
  rv->bc = 76; rv->lc = (int)((len + 15) >> 4);
  load_fonts( 1 ); set_fontpoint( par.font, par.point );
  if (par.textdef) AVSendMessage( AV_ASKFILEFONT, 0, 0 );
  *(long *)&rv->font = *(long *)&par.font;
  rv->yfac = hchar; rv->xfac = wchar; rv->dist = dist;
  rv->h = par.hwin; rv->w = 77 * wchar;
  rv->draw = draw_dump; rv->free = free_text;
  rv->key = key_text; rv->sclick = sclick_text;
  return rv;
}

static void outchar( int c )
{
  static int  flag = 0;
  static char *read_ptr = read_buf.text;

  if ((*read_ptr = c) == 0)
  {
    read_ptr = read_buf.text; c = par.margin;
    v_alpha_text( ohandle, read_buf.text - c );
    if (flag)
    {
      read_buf.text[-2] = ' '; read_buf.text[-1] = ' ';
      read_buf.text[-c] = ' '; read_buf.text[1-c] = ' ';
      par.margin = c -= 4; flag = 0;
    }
    if (c && oeffect & TXT_UNDERLINED)
    {
      par.margin = c += 4; flag = 1;
      read_buf.text[-2] = 18; read_buf.text[-1] = '4';
      read_buf.text[-c] = 18; read_buf.text[1-c] = '5';
  } }
  else if (read_ptr < read_buf.end - 1) ++read_ptr;
}

static void out_effect( int new )
{
  oeffect ^= new;

  if (oeffect & TXT_THICKENED)
  {
    outchar( 18 ); outchar( new & TXT_THICKENED ? '0' : '1' );
  }
  if (oeffect & TXT_LIGHT)
  {
    outchar( 18 ); outchar( new & TXT_LIGHT ? 'E' : 'F' );
  }
  if (oeffect & TXT_SKEWED)
  {
    outchar( 18 ); outchar( new & TXT_SKEWED ? '2' : '3' );
  }
  if (oeffect & TXT_UNDERLINED)
  {
    outchar( 18 ); outchar( new & TXT_UNDERLINED ? '4' : '5' );
  }
  if (oeffect & TXT_SUPERSCRIPT)
  {
    outchar( 18 ); outchar( new & TXT_SUPERSCRIPT ? '6' : '7' );
  }
  if (oeffect & TXT_SUBSCRIPT)
  {
    outchar( 18 ); outchar( new & TXT_SUBSCRIPT ? '8' : '9' );
  }
  oeffect = new;
}

static int out_line( int fh )
{
  unsigned char c[2];

  while (Fread( fh, 1, c ) > 0)
    switch (*c)
    {
      case  10: outchar( 10 ); outchar( 0 ); return 0;
      case  11: Fread( fh, 1, c ); break; /* 1st Word Soft Formfeed	*/
      case Esc: Fread( fh, 1, c );
		if (*c == Esc) { outchar( Esc ); outchar( Esc ); }
		else out_effect( *c & 0x3F ); break;
      case  28:				  /* 1st Word Soft Space	*/
      case  29:				  /* 1st Word			*/
      case  30: outchar( ' ' ); break;	  /* 1st Word Wide Space	*/
      case  31: while (Fread( fh, 1, c ) > 0 && *c != 10); break;
      case  25: *c = '-';		  /* 1st Word Soft Slash	*/
      default:  outchar( *c );
    }
  outchar( 12 + par.no_ff ); outchar( 0 ); return 1;
}

int (*out_text( void ))( int fh )
{
  memset( read_buf.space, ' ', sizeof(read_buf.space) );
  if (par.quality) { outchar( 18 ); outchar( 'C' - par.quality ); }
  out_effect( 0 ); return out_line;
}