/*@z51.c:Plain Text Back End:Plain_BackEnd@***********************************/
/*                                                                           */
/*  THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.42)                       */
/*  COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston                             */
/*                                                                           */
/*  Jeffrey H. Kingston (jeff@it.usyd.edu.au)                                */
/*  School of Information Technologies                                       */
/*  The University of Sydney 2006                                            */
/*  AUSTRALIA                                                                */
/*                                                                           */
/*  This program is free software; you can redistribute it and/or modify     */
/*  it under the terms of the GNU General Public License as published by     */
/*  the Free Software Foundation; either Version 3, or (at your option)      */
/*  any later version.                                                       */
/*                                                                           */
/*  This program is distributed in the hope that it will be useful,          */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
/*  GNU General Public License for more details.                             */
/*                                                                           */
/*  You should have received a copy of the GNU General Public License        */
/*  along with this program; if not, write to the Free Software              */
/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA   */
/*                                                                           */
/*  FILE:         z51.c                                                      */
/*  MODULE:       Plain Text Back End                                        */
/*  EXTERNS:      Plain_BackEnd, PlainCharWidth, PlainCharHeight,            */
/*                PlainFormFeed                                              */
/*                                                                           */
/*****************************************************************************/
#include "externs.h"


/*****************************************************************************/
/*                                                                           */
/*  PlainCharWidth    the width of each character                            */
/*  PlainCharHeight   the height of each character                           */
/*  PlainFormFeed     TRUE if components to be separated by \f.              */
/*                                                                           */
/*****************************************************************************/

FULL_LENGTH PlainCharWidth, PlainCharHeight;
BOOLEAN PlainFormFeed;

/*****************************************************************************/
/*                                                                           */
/*  State variables for this module                                          */
/*                                                                           */
/*****************************************************************************/

static FILE		*out_fp;	/* file to print output on           */
static int		hsize;		/* horizontal size of page in chars  */
static int		vsize;		/* vertical size of page in chars    */
static FULL_CHAR	*page;		/* the page (two-dim array of chars) */
static BOOLEAN		prologue_done;	/* TRUE after prologue is printed    */


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintInitialize(FILE *fp, BOOLEAN enc)                        */
/*                                                                           */
/*  Initialize this module; fp is the output file.                           */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintInitialize(FILE *fp, BOOLEAN enc)
{
  debug0(DPT, DD, "Plain_PrintInitialize(fp)");
  assert(!enc, "Plain_PrintInitialize");
  out_fp = fp;
  prologue_done = FALSE;
  debug0(DPT, DD, "Plain_PrintInitialize returning.");
} /* end Plain_PrintInitialize */


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintLength(FULL_CHAR *buff, int length, int length_dim)      */
/*                                                                           */
/*  Print a length (debugging only)                                          */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintLength(FULL_CHAR *buff, int length, int length_dim)
{
  if( length_dim == COLM )
  {
    sprintf( (char *) buff, "%.2fs", (float) length/PlainCharWidth);
  }
  else
  {
    sprintf( (char *) buff, "%.2ff", (float) length/PlainCharHeight);
  }
}


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintPageSetupForFont(OBJECT face, int font_curr_page,        */
/*    FULL_CHAR *font_name, FULL_CHAR *first_size_str)                       */
/*                                                                           */
/*  Print the page setup commands required to use a font on some page:       */
/*                                                                           */
/*    face            The font face record, defining which font we need      */
/*    font_curr_page  The current page number                                */
/*    font_name       The name of the font                                   */
/*    first_size_str  No idea, have to check                                 */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintPageSetupForFont(OBJECT face, int font_curr_page,
  FULL_CHAR *font_name, FULL_CHAR *first_size_str)
{
  /* nothing to do here */

} /* end Plain_PrintPageSetupForFont */


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintPageResourceForFont(FULL_CHAR *font_name, BOOLEAN first) */
/*    BOOLEAN first)                                                         */
/*                                                                           */
/*  Print page resource info on file fp for font font_name; first is true    */
/*  if this is the first resource on this page.                              */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintPageResourceForFont(FULL_CHAR *font_name, BOOLEAN first)
{
  /* nothing to do here */

} /* end Plain_PrintPageResourceForFont */


/*****************************************************************************/
/*                                                                           */
/*  static void Plain_PrintMapping(MAPPING m)                                */
/*                                                                           */
/*  Print mapping m.                                                         */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintMapping(MAPPING m)
{
  /* nothing to do here */

} /* end Plain_PrintMapping */


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintBeforeFirstPage(h, v, label)                             */
/*                                                                           */
/*  This procedure is called just before starting to print the first         */
/*  component of the output.  Its size is h, v, and label is the page label. */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintBeforeFirstPage(FULL_LENGTH h, FULL_LENGTH v,
  FULL_CHAR *label)
{ int i, j;
  debug2(DPT, DD, "PrintBeforeFirst(%d, %d)", h, v);

  /* get a new page[] and clear it */
  hsize = ceiling(h, PlainCharWidth);
  vsize = ceiling(v, PlainCharHeight);
  debug2(DPT, DD, "  PlainCharWidth: %d;  PlainCharHeight: %d",
    PlainCharWidth, PlainCharHeight);
  ifdebug(DMA, D, DebugRegisterUsage(MEM_PAGES, 1,
    hsize * vsize * sizeof(FULL_CHAR)));
  debug2(DPT, DD, "  PrintBeforeFirst allocating %d by %d", hsize, vsize);
  page = (FULL_CHAR *) malloc(hsize * vsize * sizeof(FULL_CHAR));
  for( i = 0;  i < vsize;  i++ )
    for( j = 0;  j < hsize;  j++ )
      page[i*hsize + j] = ' ';
  prologue_done = TRUE;
} /* end Plain_PrintBeforeFirstPage */


/*****************************************************************************/
/*                                                                           */
/*  void Plain_PrintBetweenPages(h, v, label)                                */
/*                                                                           */
/*  Start a new output component, of size h by v; label is the page label    */
/*  to attach to the %%Page comment.                                         */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintBetweenPages(FULL_LENGTH h, FULL_LENGTH v,
  FULL_CHAR *label)
{ int new_hsize, new_vsize, i, j, jmax;
  debug2(DPT, DD, "PrintBetween(%d, %d)", h, v);

  /* print the page that has just ended */
  ifdebug(DPT, D,
    putc('+', out_fp);
    for( j = 0;  j < hsize;  j++ )  putc('-', out_fp);
    putc('+', out_fp);
    fputs((char *) STR_NEWLINE, out_fp);
  );
  for( i = vsize - 1;  i >= 0;  i-- )
  { ifdebug(DPT, D, putc('|', out_fp));
    for( jmax = hsize-1;  jmax >= 0 && page[i*hsize+jmax] == ' ';  jmax--);
    ifdebug(DPT, D, jmax = hsize - 1);
    for( j = 0;  j <= jmax;  j++ )
      putc(page[i*hsize + j], out_fp);
    ifdebug(DPT, D, putc('|', out_fp));
    fputs((char *) STR_NEWLINE, out_fp);
  }
  ifdebug(DPT, D,
    putc('+', out_fp);
    for( j = 0;  j < hsize;  j++ )  putc('-', out_fp);
    putc('+', out_fp);
    fputs((char *) STR_NEWLINE, out_fp);
  );

  /* separate the page from the next one with a form-feed if required */
  if( PlainFormFeed ) putc('\f', out_fp);

  /* if page size has changed, get a new page[] array */
  new_hsize = ceiling(h, PlainCharWidth);
  new_vsize = ceiling(v, PlainCharHeight);
  if( new_hsize != hsize || new_vsize != vsize )
  {
    ifdebug(DMA, D, DebugRegisterUsage(MEM_PAGES, -1,
      -hsize * vsize * sizeof(FULL_CHAR)));
    free(page);
    hsize = new_hsize;
    vsize = new_vsize;
    debug2(DPT, DD, "  PrintBetween allocating %d by %d", hsize, vsize);
    ifdebug(DPT, D, DebugRegisterUsage(MEM_PAGES, 1,
      hsize * vsize * sizeof(FULL_CHAR)));
    page = (FULL_CHAR *) malloc(hsize * vsize * sizeof(FULL_CHAR));
  }

  /* clear page[] for the new page just beginning */
  for( i = 0;  i < vsize;  i++ )
    for( j = 0;  j < hsize;  j++ )
      page[i*hsize + j] = ' ';
} /* end Plain_PrintBetweenPges */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintWord(x, hpos, vpos)                                           */
/*                                                                           */
/*  Print non-empty word x; its marks cross at the point (hpos, vpos).       */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintWord(OBJECT x, int hpos, int vpos)
{ FULL_CHAR *p;  int i, h, v;

  debug6(DPT, DD, "Plain_PrintWord( %s, %d, %d ) font %d colour %d%s",
    string(x), hpos, vpos, word_font(x), word_colour(x),
    word_outline(x) ? " outline" : "");
  TotalWordCount++;

  h = ((float) hpos / PlainCharWidth) + 0.5;
  v = ((float) vpos / PlainCharHeight);
  debug3(DPT, DD, "PrintWord(%s at h = %d, v = %d)", string(x), h, v);
  if( h >= 0 && h + StringLength(string(x)) < hsize && v >= 0 && v < vsize )
  {
    assert( h >= 0,     "PrintWord:  h < 0!" );
    assert( h <  hsize, "PrintWord:  h >= hsize!" );
    assert( v >= 0,     "PrintWord:  v < 0!" );
    assert( v <  vsize, "PrintWord:  v >= vsize!" );
    p = &page[v*hsize + h];
    for( i = 0;  string(x)[i] != '\0';  i++ )
      *p++ = string(x)[i];
  }
  else
    Error(51, 1, "word %s deleted (internal error, off page at %d,%d)",
      WARN, &fpos(x), string(x), h, v);
  debug0(DPT, DDD, "PrintWord returning");
} /* end Plain_PrintWord */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintPlainGraphic(x, xmk, ymk, z)                                  */
/*                                                                           */
/*  Print plain graphic object x at xmk, ymk with the size of z.             */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintPlainGraphic(OBJECT x, FULL_LENGTH xmk,
  FULL_LENGTH ymk, OBJECT z)
{ int i, len, starth, startv, stoph, stopv, h = 0, v = 0;
  debug2(DPT, D, "Plain_PrintPlainGraphic(x, xmk %s, ymk %s)",
    EchoLength(xmk), EchoLength(ymk));

  if( type(x) != WORD && type(x) != QWORD )
  {
    Error(51, 2, "left parameter of %s must be a simple word",
      WARN, &fpos(x), KW_PLAINGRAPHIC);
    return;
  }
  len = StringLength(string(x));
  if( StringLength(string(x)) == 0 )
  {
    Error(51, 3, "left parameter of %s must be a non-empty word",
      WARN, &fpos(x), KW_PLAINGRAPHIC);
    return;
  }
  starth = (((float) xmk ) / PlainCharWidth) + 0.5;
  startv = (((float) ymk ) / PlainCharHeight);
  stoph = (((float) xmk + size(z, COLM)) / PlainCharWidth) + 0.5;
  stopv = (((float) ymk - size(z, ROWM)) / PlainCharHeight); /* NB - not + */
  SetLengthDim(COLM);
  debug5(DPT, D, "  xmk %s bk %s fwd %s -> %d,%d",
    EchoLength(xmk), EchoLength(back(z, COLM)), EchoLength(fwd(z, COLM)),
    starth, stoph);
  SetLengthDim(ROWM);
  debug5(DPT, D, "  ymk %s bk %s fwd %s -> %d,%d",
    EchoLength(ymk), EchoLength(back(z, ROWM)), EchoLength(fwd(z, ROWM)),
    startv, stopv);
  if( starth >= 0 && stoph < hsize && startv >= 0 && stopv < vsize )
  { i = 0;
    for( v = startv-1;  v >= stopv;  v-- )
    {
      for( h = starth;  h < stoph;  h++ )
      {
        if( i == len )  i = 0;
        page[v*hsize + h] = string(x)[i++];
      }
    }
  }
  else
  {
    Error(51, 4, "fill %s deleted (internal error, off page at %d,%d)",
      WARN, &fpos(x), string(x), h, v);
  }
} /* end Plain_PrintPlainGraphic */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintUnderline(fnum, col, pat, xstart, xstop, ymk)                 */
/*                                                                           */
/*  Draw an underline suitable for font fnum, in colour col, from xstart to  */
/*  xstop at the appropriate distance below mark ymk.                        */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintUnderline(FONT_NUM fnum, COLOUR_NUM col,
  TEXTURE_NUM pat, FULL_LENGTH xstart, FULL_LENGTH xstop, FULL_LENGTH ymk)
{

  debug5(DPT, DD, "Plain_PrintUnderline(fnum %d, col %d, xstart %s, xstop %s, ymk %s )",
    fnum, col, EchoLength(xstart), EchoLength(xstop), EchoLength(ymk));

  /* do nothing */

  debug0(DPT, DD, "PrintUnderline returning.");
} /* end Plain_PrintUnderline */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintAfterLastPage()                                               */
/*                                                                           */
/*  Clean up this module and close output stream.                            */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintAfterLastPage(void)
{ int i, j, jmax;
  if( prologue_done )
  { 
    /* print the page that has just ended (exists since prologue_done) */
    ifdebug(DPT, D,
      putc('+', out_fp);
      for( j = 0;  j < hsize;  j++ )  putc('-', out_fp);
      putc('+', out_fp);
      fputs((char *) STR_NEWLINE, out_fp);
    );
    for( i = vsize - 1;  i >= 0;  i-- )
    { ifdebug(DPT, D, putc('|', out_fp));
      for( jmax = hsize-1;  jmax >= 0 && page[i*hsize+jmax] == ' ';  jmax--);
      ifdebug(DPT, D, jmax = hsize - 1);
      for( j = 0;  j <= jmax;  j++ )
        putc(page[i*hsize + j], out_fp);
      ifdebug(DPT, D, putc('|', out_fp));
      fputs((char *) STR_NEWLINE, out_fp);
    }
    ifdebug(DPT, D,
      putc('+', out_fp);
      for( j = 0;  j < hsize;  j++ )  putc('-', out_fp);
      putc('+', out_fp);
      fputs((char *) STR_NEWLINE, out_fp);
    );
  }
} /* end Plain_PrintAfterLastPage */


/*****************************************************************************/
/*                                                                           */
/*  Plain_CoordTranslate(xdist, ydist)                                       */
/*                                                                           */
/*  Translate coordinate system by the given x and y distances.              */
/*                                                                           */
/*****************************************************************************/

static void Plain_CoordTranslate(FULL_LENGTH xdist, FULL_LENGTH ydist)
{ debug2(DPT, D, "Plain_CoordTranslate(%s, %s)",
    EchoLength(xdist), EchoLength(ydist));
  assert(FALSE, "Plain_CoordTranslate: should never be called!");
  debug0(DPT, D, "Plain_CoordTranslate returning.");
} /* end Plain_CoordTranslate */


/*****************************************************************************/
/*                                                                           */
/*  Plain_CoordRotate(amount)                                                */
/*                                                                           */
/*  Rotate coordinate system by given amount (in internal DG units)          */
/*                                                                           */
/*****************************************************************************/

static void Plain_CoordRotate(FULL_LENGTH amount)
{ debug1(DPT, D, "Plain_CoordRotate(%.1f degrees)", (float) amount / DG);
  assert(FALSE, "Plain_CoordRotate: should never be called!");
  debug0(DPT, D, "Plain_CoordRotate returning.");
} /* end Plain_CoordRotate */


/*****************************************************************************/
/*                                                                           */
/*  Plain_CoordScale(ratio, dim)                                             */
/*                                                                           */
/*  Scale coordinate system by ratio in the given dimension.                 */
/*                                                                           */
/*****************************************************************************/

static void Plain_CoordScale(float hfactor, float vfactor)
{
  assert(FALSE, "Plain_CoordScale: should never be called!");
} /* end Plain_CoordScale */


/*****************************************************************************/
/*                                                                           */
/*  Plain_SaveGraphicState(x)                                                */
/*                                                                           */
/*  Save current coord system on stack for later restoration.                */
/*  Object x is just for error reporting, not really used at all.            */
/*                                                                           */
/*****************************************************************************/

static void Plain_SaveGraphicState(OBJECT x)
{ debug0(DPT, D, "Plain_SaveGraphicState()");
  assert(FALSE, "Plain_SaveGraphicState: should never be called!" );
  debug0(DPT, D, "Plain_SaveGraphicState returning.");
} /* end Plain_SaveGraphicState */


/*****************************************************************************/
/*                                                                           */
/*  Plain_RestoreGraphicState()                                              */
/*                                                                           */
/*  Restore previously saved coordinate system.                              */
/*                                                                           */
/*****************************************************************************/

static void Plain_RestoreGraphicState(void)
{ debug0(DPT, D, "Plain_RestoreGraphicState()");
  assert(FALSE, "Plain_RestoreGraphicState: should never be called!" );
  debug0(DPT, D, "Plain_RestoreGraphicState returning.");
} /* end Plain_RestoreGraphicState */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintGraphicObject(x)                                              */
/*                                                                           */
/*  Print object x on out_fp                                                 */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintGraphicObject(OBJECT x)
{
  debug3(DPT, D, "Plain_PrintGraphicObject(%s %s %s)",
    EchoFilePos(&fpos(x)), Image(type(x)), EchoObject(x));
  assert(FALSE, "Plain_PrintGraphicObject: should never be called!" );
  debug0(DPT, D, "Plain_PrintGraphicObject returning");
} /* end Plain_PrintGraphicObject */


/*****************************************************************************/
/*                                                                           */
/*  Plain_DefineGraphicNames(x)                                              */
/*                                                                           */
/*  Generate PostScript for xsize, ysize etc. names of graphic object.       */
/*                                                                           */
/*****************************************************************************/

static void Plain_DefineGraphicNames(OBJECT x)
{
  debug1(DPT, D, "Plain_DefineGraphicNames( %s )", EchoObject(x));
  debug1(DPT, DD, "  style = %s", EchoStyle(&save_style(x)));
  assert(FALSE, "Plain_DefineGraphicNames: should never be called!" );
  debug0(DPT, D, "Plain_DefineGraphicNames returning.");
} /* end Plain_DefineGraphicNames */


/*****************************************************************************/
/*                                                                           */
/*  Plain_SaveTranslateDefineSave(x, xdist, ydist)                           */
/*                                                                           */
/*  Equivalent to the sequence of calls                                      */
/*                                                                           */
/*      SaveGraphicState(x)                                                  */
/*      CoordTranslate(xdist, ydist)                                         */
/*      DefineGraphicNames(x)                                                */
/*      SaveGraphicState(x)                                                  */
/*                                                                           */
/*  but offers opportunities for optimization.                               */
/*                                                                           */
/*****************************************************************************/

static void Plain_SaveTranslateDefineSave(OBJECT x, FULL_LENGTH xdist,
  FULL_LENGTH ydist)
{
  assert(FALSE, "Plain_SaveTranslateDefineSave: should never be called!" );
} /* end Plain_SaveTranslateDefineSave */


/*****************************************************************************/
/*                                                                           */
/*  Plain_PrintGraphicInclude(x, colmark, rowmark)                           */
/*                                                                           */
/*  Print graphic include file, with appropriate surrounds.                  */
/*                                                                           */
/*****************************************************************************/

static void Plain_PrintGraphicInclude(OBJECT x, FULL_LENGTH colmark,
  FULL_LENGTH rowmark)
{
  debug0(DPT, D, "Plain_PrintGraphicInclude(x)");
  assert(FALSE, "Plain_PrintGraphicInclude: should never be called!" );
  debug0(DPT, D, "Plain_PrintGraphicInclude returning.");
} /* end Plain_PrintGraphicInclude */


/*****************************************************************************/
/*                                                                           */
/*  Plain_LinkSource(name, llx, lly, urx, ury)                               */
/*                                                                           */
/*  Print a link source point.                                               */
/*                                                                           */
/*****************************************************************************/

static void Plain_LinkSource(OBJECT name, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{
  debug5(DPT, D, "Plain_LinkSource(%s, %d, %d, %d, %d)", EchoObject(name),
    llx, lly, urx, ury);
  /* do nothing; no links in plain text output */
  debug0(DPT, D, "Plain_LinkSource returning.");
} /* end Plain_LinkSource */


/*****************************************************************************/
/*                                                                           */
/*  Plain_LinkDest(name, llx, lly, urx, ury)                                 */
/*                                                                           */
/*  Print a link dest point.                                                 */
/*                                                                           */
/*  Still to do: check that the name has not been used by a previous         */
/*  dest point.                                                              */
/*                                                                           */
/*****************************************************************************/

static void Plain_LinkDest(OBJECT name, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{
  debug5(DPT, D, "Plain_LinkDest(%s, %d, %d, %d, %d)", EchoObject(name),
    llx, lly, urx, ury);
  /* do nothing; no links in plain text output */
  debug0(DPT, D, "Plain_LinkDest returning.");
} /* end Plain_LinkDest */


/*****************************************************************************/
/*                                                                           */
/*  Plain_LinkURL(url, llx, lly, urx, ury)                                   */
/*                                                                           */
/*  Print an external link.                                                  */
/*                                                                           */
/*****************************************************************************/

static void Plain_LinkURL(OBJECT url, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{
  debug5(DPT, D, "Plain_LinkURL(%s, %d, %d, %d, %d)", EchoObject(url),
    llx, lly, urx, ury);
  /* do nothing; no links in plain text output */
  debug0(DPT, D, "Plain_LinkURL returning.");
} /* end Plain_LinkDest */


/*****************************************************************************/
/*                                                                           */
/*  Plain_LinkCheck(void)                                                    */
/*                                                                           */
/*  Called at end of run; will check that for every link source point there  */
/*  is a link dest point.                                                    */
/*                                                                           */
/*****************************************************************************/

static void Plain_LinkCheck(void)
{
  debug0(DPT, D, "Plain_LinkCheck()");
  /* do nothing; no links in plain text output */
  debug0(DPT, D, "Plain_LinkCheck returning.");
} /* end Plain_LinkCheck */


/*****************************************************************************/
/*                                                                           */
/*  Plain_BackEnd                                                            */
/*                                                                           */
/*  The record into which all of these functions are packaged.               */
/*                                                                           */
/*****************************************************************************/

static struct back_end_rec plain_back = {
  PLAINTEXT,				/* the code number of the back end   */
  STR_PLAINTEXT,			/* string name of the back end       */
  FALSE,				/* TRUE if @Scale is available       */
  FALSE,				/* TRUE if @Rotate is available      */
  FALSE,				/* TRUE if @VMirror, @HMirror avail  */
  FALSE,				/* TRUE if @Graphic is available     */
  FALSE,				/* TRUE if @IncludeGraphic is avail. */
  TRUE,					/* TRUE if @PlainGraphic is avail.   */
  FALSE,				/* TRUE if fractional spacing avail. */
  FALSE,				/* TRUE if actual font metrics used  */
  FALSE,				/* TRUE if colour is available       */
  Plain_PrintInitialize,
  Plain_PrintLength,
  Plain_PrintPageSetupForFont,
  Plain_PrintPageResourceForFont,
  Plain_PrintMapping,
  Plain_PrintBeforeFirstPage,
  Plain_PrintBetweenPages,
  Plain_PrintAfterLastPage,
  Plain_PrintWord,
  Plain_PrintPlainGraphic,
  Plain_PrintUnderline,
  Plain_CoordTranslate,
  Plain_CoordRotate,
  Plain_CoordScale,
  NULL,
  NULL,
  Plain_SaveGraphicState,
  Plain_RestoreGraphicState,
  Plain_PrintGraphicObject,
  Plain_DefineGraphicNames,
  Plain_SaveTranslateDefineSave,
  Plain_PrintGraphicInclude,
  Plain_LinkSource,
  Plain_LinkDest,
  Plain_LinkURL,
  Plain_LinkCheck,
};

BACK_END Plain_BackEnd = &plain_back;


/*****************************************************************************/
/*                                                                           */
/*  Plain_NullBackEnd                                                        */
/*                                                                           */
/*  The record into which all of these functions are packaged.               */
/*                                                                           */
/*****************************************************************************/

static void Plain_NullPrintInitialize(FILE *fp, BOOLEAN enc)
{}

static void Plain_NullPrintPageSetupForFont(OBJECT face, int font_curr_page,
  FULL_CHAR *font_name, FULL_CHAR *short_name)
{}

static void Plain_NullPrintPageResourceForFont(FULL_CHAR *font_name,
  BOOLEAN first)
{}

static void Plain_NullPrintMapping(MAPPING m)
{}

static void Plain_NullPrintBeforeFirstPage(FULL_LENGTH h, FULL_LENGTH v,
  FULL_CHAR *label)
{}

static void Plain_NullPrintBetweenPages(FULL_LENGTH h, FULL_LENGTH v,
  FULL_CHAR *label)
{}

static void Plain_NullPrintAfterLastPage(void)
{}

static void Plain_NullPrintWord(OBJECT x, int hpos, int vpos)
{}

static void Plain_NullPrintPlainGraphic(OBJECT x, FULL_LENGTH xmk,
  FULL_LENGTH ymk, OBJECT z)
{}

static void Plain_NullPrintUnderline(FONT_NUM fnum, COLOUR_NUM col,
  TEXTURE_NUM pat, FULL_LENGTH xstart, FULL_LENGTH xstop, FULL_LENGTH ymk)
{}

static void Plain_NullCoordTranslate(FULL_LENGTH xdist, FULL_LENGTH ydist)
{}

static void Plain_NullCoordRotate(FULL_LENGTH amount)
{}

static void Plain_NullCoordScale(float hfactor, float vfactor)
{}

static void Plain_NullSaveGraphicState(OBJECT x)
{}

static void Plain_NullRestoreGraphicState(void)
{}

static void Plain_NullPrintGraphicObject(OBJECT x)
{}

static void Plain_NullDefineGraphicNames(OBJECT x)
{}

static void Plain_NullSaveTranslateDefineSave(OBJECT x, FULL_LENGTH xdist,
  FULL_LENGTH ydist)
{}

static void Plain_NullPrintGraphicInclude(OBJECT x, FULL_LENGTH colmark,
  FULL_LENGTH rowmark)
{}

static void Plain_NullLinkSource(OBJECT name, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{}

static void Plain_NullLinkDest(OBJECT name, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{}

static void Plain_NullLinkURL(OBJECT url, FULL_LENGTH llx, FULL_LENGTH lly,
  FULL_LENGTH urx, FULL_LENGTH ury)
{}

static void Plain_NullLinkCheck(void)
{}

static struct back_end_rec plain_null_back = {
  PLAINTEXT,				/* the code number of the back end   */
  STR_PLAINTEXT,			/* string name of the back end       */
  FALSE,				/* TRUE if @Scale is available       */
  FALSE,				/* TRUE if @Rotate is available      */
  FALSE,				/* TRUE if @VMirror, @HMirror avail  */
  FALSE,				/* TRUE if @Graphic is available     */
  FALSE,				/* TRUE if @IncludeGraphic is avail. */
  TRUE,					/* TRUE if @PlainGraphic is avail.   */
  FALSE,				/* TRUE if fractional spacing avail. */
  FALSE,				/* TRUE if actual font metrics used  */
  FALSE,				/* TRUE if colour is available       */
  Plain_NullPrintInitialize,
  Plain_PrintLength,
  Plain_NullPrintPageSetupForFont,
  Plain_NullPrintPageResourceForFont,
  Plain_NullPrintMapping,
  Plain_NullPrintBeforeFirstPage,
  Plain_NullPrintBetweenPages,
  Plain_NullPrintAfterLastPage,
  Plain_NullPrintWord,
  Plain_NullPrintPlainGraphic,
  Plain_NullPrintUnderline,
  Plain_NullCoordTranslate,
  Plain_NullCoordRotate,
  Plain_NullCoordScale,
  NULL,
  NULL,
  Plain_NullSaveGraphicState,
  Plain_NullRestoreGraphicState,
  Plain_NullPrintGraphicObject,
  Plain_NullDefineGraphicNames,
  Plain_NullSaveTranslateDefineSave,
  Plain_NullPrintGraphicInclude,
  Plain_NullLinkSource,
  Plain_NullLinkDest,
  Plain_NullLinkURL,
  Plain_NullLinkCheck,
};

BACK_END Plain_NullBackEnd = &plain_null_back;
