/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:line.c 12.0$ */
/* $ACIS:line.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/lpfilter/txt3812/RCS/line.c,v $ */

#ifndef lint
static char *rcsid = "$Header:line.c 12.0$";
#endif

#include <stdio.h>
#include <ctype.h>
#include <utils.h>
#include <pmp/pmp.h>
#include "line.h"

/***===================================================================***/

int ln_debug;

/***===================================================================***/

line *
ln_New(len)
register2 int len;
{
register1 line *tmp;

   D_ENTRY1(ln_debug,"ln_New(%d)\n",len);
   tmp= (line *)u_malloc(sizeof(line));
   tmp->ln_chars= u_malloc(len+1);
   tmp->ln_start= 0;
   tmp->ln_max=   len;
   tmp->ln_len=   0;
   tmp->ln_next=  NULL;
   RETURN(tmp);
}

/***===================================================================***/

static
_ln_Addch(ln,pos,ch)
register1 line *ln;
register2 int   pos;
register3 int   ch;
{

    if (isprint(ch))
        D_ENTRY3(ln_debug,"_ln_Addch(0x%x,%d,%c)\n",ln,pos,ch);
    else
	D_ENTRY3(ln_debug,"_ln_Addch(0x%x,%d,%2d)\n",ln,pos,ch);
    if (pos==ln->ln_len) { /* add at end of line -- easy */
	ln->ln_chars[pos]= ch;
	ln->ln_len++;
    }
    else if (pos>ln->ln_len) { /* add past end of line -- still easy */
    	register4 int knt= ln->ln_len;
	if (knt<ln->ln_start)
	   knt= ln->ln_start;
	while (knt<pos) {
	    ln->ln_chars[knt++]= ' ';
	}
	ln->ln_chars[pos]= ch;
	ln->ln_len= pos+1;
    }
    else { /* overstrike somebody -- oh no! */
	if (ln->ln_chars[pos]==' ') { /* a space, whew! */
	    ln->ln_chars[pos]= ch;
	}
	else { /* a "real" overstrike. bummer */
	    register4 line *ostk= ln->ln_next;
	    
	    if (!ostk) {
	        ostk= ln->ln_next= ln_New(ln->ln_max);
	        ostk->ln_start= pos;
	    }
	    else if (pos<ostk->ln_start) {
		register4 int knt= pos;

		for (knt=ostk->ln_start-1;knt>pos;knt++)
		   ln->ln_chars[knt]= ' ';
	    }
	    _ln_Addch(ostk,pos,ch);
	}
    }
    RETURN(TRUE);
}

/***===================================================================***/

ln_Scan(fil,ln)
register3 FILE *fil;
register2 line *ln;
{
register1 line *tmpln=ln;

    D_ENTRY2(ln_debug,"ln_Scan(0x%x,0x%x)\n",fil,ln);
    if ((!fil)||(!ln))
       RETURN(FALSE);
    do {
  	tmpln->ln_len= 0;
        tmpln->ln_start=  0;
	tmpln->ln_curpos= 0;
	tmpln= tmpln->ln_next;
    } while (tmpln);
    RETURN(ln_Append(fil,ln));
}

/***===================================================================***/

ln_Append(fil,ln)
register4 FILE *fil;
register3 line *ln;
{
register1 int ch;
register2 int ndx;
register3 int maxlen= (ln?ln->ln_max:0);
register5 int done=FALSE;

    D_ENTRY2(ln_debug,"ln_Append(0x%x,0x%x)\n",fil,ln);
    ndx= ln->ln_curpos;
DEBUG2(ln_debug,2,"ndx= %d, maxlen= %d\n",ndx,maxlen);
    while ((ndx<maxlen)&&(!done)) {
	ch= getc(fil);
	switch (ch) {
	    when '\n':
	    or   EOF:
	    or   '\f':  done= TRUE;
	    when '\t':	ndx= ((ndx/8)+1)*8;
	    when '\b':	ndx--;
	    		if (ndx<0) ndx=0;
	    when '\r':	ndx= 0;
	    otherwise:  _ln_Addch(ln,ndx++,ch);
	}
    }
    ln->ln_curpos= ndx;
    RETURN(ch);
}

/***===================================================================***/

ln_SScan(str,ln)
register3 char *str;
register2 line *ln;
{
register1 line *tmpln=ln;

    D_ENTRY2(ln_debug,"ln_SScan(%s,0x%x)\n",str,ln);
    if ((!str)||(!ln))
       RETURN(FALSE);
    do {
  	tmpln->ln_len= 0;
        ln->ln_start=  0;
	ln->ln_curpos= 0;
	tmpln= tmpln->ln_next;
    } while (tmpln);
    RETURN(ln_SAppend(str,ln));
}

/***===================================================================***/

ln_SAppend(str,ln)
register4 char *str;
register3 line *ln;
{
register1 int ch;
register2 int ndx;
register3 int maxlen= (ln?ln->ln_max:0);
register5 int done=FALSE;

    D_ENTRY2(ln_debug,"ln_SAppend(%s,0x%x)\n",str,ln);
    ndx= ln->ln_curpos;
    while ((ndx<maxlen)&&(!done)) {
	ch= *str;
	str++;
	switch (ch) {
	    when '\n':
	    or   EOF:
	    or   '\0':
	    or   '\f':  done= TRUE;
	    when '\t':	ndx= ((ndx/8)+1)*8;
	    when '\b':	ndx--;
	    		if (ndx<0) ndx=0;
	    otherwise:  _ln_Addch(ln,ndx++,ch);
	}
    }
    ln->ln_curpos= ndx;
    RETURN(ch);
}

/***===================================================================***/

ln_Print(ln)
register4 line		*ln;
{
register1 int	 	 ndx;
register2 int	 	 len;
register3 int	 	 ostk;
register4 cursor_reg	*reg= NULL;

    D_ENTRY1(ln_debug,"ln_Print(0x%x)\n",ln);
					/* where do we overstrike? */
    if ((ln->ln_next)&&(ln->ln_next->ln_len)) {
    		reg=	p_cr_mark();
		ostk=	ln->ln_next->ln_start;
    }
    else	ostk=	-1;			/* nowhere */

    len=	ln->ln_len;
    ndx=	ln->ln_start;
    while (ndx<len) {
	if ((ostk==-1)||(ndx>=ostk)) {
	    p_putnstring(&ln->ln_chars[ndx],len-ndx);
	    ndx=	len;
	}
	else {
	    p_putnstring(&ln->ln_chars[ndx],ostk-ndx);
	    ndx=	ostk;
	    p_cr_remark(reg);
	}
    }
    if (ostk!= -1) {
       p_cr_return(reg,P_FREE_CURSOR_REG);
       ndx=	ln_Print(ln->ln_next);
       if (ndx>len)
           ndx=	len;
    }
    RETURN(len);
}

