/*

F.C - Rick Stiles, 1988

See UEP-DOC for a description of this program.

*/



#include "stdlib.h"
#include "string.h"
#include "functions.h"
#include "exec/execbase.h"
#include "intuition/intuitionbase.h"


#define UCHAR unsigned char

UCHAR pixeltable[256];              /* see UEP-DOC about this table */
long IntuitionBase;
short len, maxLen, pixels, spaces, inSpace,spaceWidth;
short rightJust = 0;
UCHAR *fd,*fp;
UCHAR buf[256];


main(argc,argv)
int   argc;
char **argv;
{
    IntuitionBase   = (long)OpenLibrary("intuition.library",0L);

    if (IntuitionBase==0L || argc<4) {
USAGE:
        puts("USAGE: f infile outfile lineLength");
        puts("              infile     = input text file to be filtered");
        puts("              outfile    = a file or PAR: (don't use PRT:)");
        puts("              lineLength = the lineLength used in UEP");
        puts("UEP.table file (256 bytes) must be in the current or S: directory");
        exit(0);
    }
    maxLen = (short)atol(argv[3]) + 1;
    if (maxLen<10 || maxLen>256) goto USAGE;
    maxLen *= 24;

    /* load in the proportionality table */
    fp = (UCHAR *)Open("UEP.table",(long)MODE_OLDFILE);
    if (fp==NULL) fp = (UCHAR *)Open("S:UEP.table",(long)MODE_OLDFILE);
    if (fp==NULL) {
        puts("Can't fine UEP.table in current or S: directory");
        goto OUT;
    }
    if (Read((long)fp,pixeltable,256L)!=256L) {
        puts("UEP.table < 256 bytes in size - aborting");
        goto OUT;
    }
    Close((long)fp);
    spaceWidth = pixeltable[32];

    /* open infile & outfile */
    fd = (UCHAR *)Open(argv[1],(long)MODE_OLDFILE);
    fp = (UCHAR *)Open(argv[2],(long)MODE_NEWFILE);
    if (fd==NULL || fp==NULL) goto OUT;

/*
                ****** EDIT THIS for your printer ******
You may not need this line.  If any printer initialization is needed, do it
here.
*/
    Write((long)fp,(UCHAR *)"Xf",5L);         /* init Canon BJ130 printer */

    /* read, process, output the text file */
    while (readLine()) printLine();

OUT:
    if (fd!=NULL) Close((long)fd);
    if (fp!=NULL) Close((long)fp);
    CloseLibrary((void *)IntuitionBase);
    exit(0);
}

readLine()
{
register long  i;
register short inEsc,lastCh;
UCHAR          ch;

    len = pixels = 0;
    inEsc = 0;
    inSpace = spaces = 0;
    lastCh = -1;
    rightJust = FALSE;
    while ( (i=Read((long)fd,&ch,1L))==1L) {
        if (lastCh==-1 && ch=='@') {
            rightJust = TRUE;
            lastCh = 0;
            continue;
        }
        if (ch==12) { buf[len++] = ch;  return(TRUE); }
        if (ch==10) {
            if (lastCh==' ')
                    { len--; spaces--; pixels -= spaceWidth; lastCh = buf[len-1]; }
            if (lastCh=='`') { inSpace = 0; len--; pixels -= spaceWidth; }
            buf[len++] = 10;
            break;
        }
        lastCh = ch;
        if (ch==27 || ch==28) {
            if (!inEsc) inEsc = TRUE;
            else { inEsc = FALSE; continue; } /* don't store end esc */
        }
        if (!inEsc) {
            if (ch>' ' && inSpace==0) inSpace = len + 1;
            if (inSpace && ch==' ') spaces++;
            if (ch<=135) pixels += pixeltable[ch];
            else pixels += 24;
        }
        buf[len++] = ch;
    }
    buf[len]=0x00;

    if (i==1L) return(TRUE);
    else return(FALSE);
}

printLine()
{
register short i,j;
UCHAR ch;
register short delta;
short sp[256];

    if (len==0) return;
    if (len<=2) Write((long)fp,buf,(long)len);
    else {
        delta = maxLen - pixels;
        if (rightJust) { makeSpace(delta); delta = 0; }
        else if (inSpace && (delta + spaces * spaceWidth) >= (maxLen >> 2)) delta = 0;
        if (spaces==0 || delta<=0) inSpace = 0;
        if (inSpace==0) delta = 0;
        if (inSpace && spaces) delta += (spaces * spaceWidth);
        for (i=0; i<256; i++) sp[i] = 0;
        if (delta<=0) goto SKIPIT;
AGAIN:
        for (i=0; i<len; i++) {
            if (delta<1) break;
            if (buf[i]==' ') {
                    if (i>=inSpace) {
                        sp[i] += 1;
                        delta -= 1;
                    }
            }
        }
        if (delta>=1 && inSpace) goto AGAIN;
SKIPIT:
        for (i=0; i<len; i++) {
            ch = buf[i];

            if (ch==127) makeSpace(24);
            else if (ch!=' ') Write((long)fp,&ch,1L);
            else {
                j = sp[i];
                if (j==0) j = spaceWidth;
                if (buf[i+1]==' ') {
                    if (sp[i+1]==0) sp[i+1] = spaceWidth;
                    sp[i+1] += j;
                    continue;
                }
                makeSpace(j);
            }
        }
    }
}

makeSpace(j)
register short j;
{
register short i;
UCHAR ch;

    /* send ascii 32 spaces to the printer for each 24 dots in j */
    while (j>=24) { Write((long)fp," ",1L); j -= 24; }
    if (j<=0) return;

/*
        ****** EDIT THIS SECTION for your printer type ******
The following lines tell the Canon BJ130 printer to advance the print head j
increments (pixels, dots, resolution elements).  What we are doing is
creating a space between words of the desired length.  The object is to
stretch the spacing between words by the same amount to right-justify the
line.  The amount of space needed between words is calculated in printLine()
above.
*/

    Write((long)fp,"Z",2L);
    ch = j & 255;
    Write((long)fp,&ch,1L);
    ch = j >> 8;
    Write((long)fp,&ch,1L);

/*
you may not need the following lines, which send j nulls to the output - this
is for the Canon BJ130 printer
*/
    ch = 0;
    for (i=0; i<j; i++) Write((long)fp,&ch,1L);
}

