/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 22-Dec-91 | [1.499] <jmn> Created
* 24-Dec-91 | [1.550] <jmn> added leading space suppression to line
*****************************************************************************/
#include "stdlib.h"
#include "stdio.h"
#include "boolean.h"
#include "string.h"

#include "pr.h"
#include "form.h"
#include "printers.h"

/*****************************************************************************
				 Channel Tape

The channel tape controls the printer vertical formatting control.  The
layout here is restricted to 11" page at 6 lines per inch (66 line) 
maximum.  The format for a tape is shown below:

	| 12-11-10--9--8--7-o--6--5--4--3--2--1 |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |--+--+--+--+--+-o--+--+--+--+--+--+ |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	|  |  |  |  |  |  | o  |  |  |  |  |  | |
	| 12-11-10--9--8--7-o--6--5--4--3--2--1-|

This is encoded as a 16-bit integer whose bit shift position is the column
control, e.g., bit 1 is channel 1, bit 9 is channel 9, etc.  Bit 0 
(the low order bit) is unused, as are bits 13-15.

*/

short standard_channels[] = 	{ 0,		/* line 1 */
	                          0,		/* line 2 */
	                          0,		/* line 3 */
/* CHAN 1 = 4
   CHAN 2 = 4
   ...
   CHAN 8 = 4
   CHAN 10 = 4
   CHAN 11 = 4
*/
				   (1<<11) | (1<<10) 
				 | (1<<8)  | (1<<7)
				 | (1<<6)  | (1<<5)
				 | (1<<4)  | (1<<3) 
				 | (1<<2)  | (1<<1),
	  						     /* line 4 */
	                  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* lines 5-20 */
	          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* lines 21-40 */
	          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* lines 41-60 */
/* CHAN 9 = 61 */
		  1<<9,					    /* line 61 */
	                            0,			    /* line 62 */
/* CHAN 12 = 63 */
	          1<<12,				    /* line 63 */
		  		    0,		   	    /* line 64 */
				    0,			    /* line 65 */
				    0	   		    /* line 66 */
				};

channel_tape standard_tape = {
				66, standard_channels
			     };

/****************************************************************************
*			      parse_channel_args
* Inputs:
*       channel_tape * t: Channel tape spec
*	int chn: Channel number, an integer in the range 1..12
*	char * line: Input line
* Result: void
*       
* Effect: 
*       Parses a channel specification of the form
*	CHAN nn = l1 ... ln
*	If li has the form +nn then nn is added to li-1 to get the
*	new row value.
****************************************************************************/

void parse_channel_args(channel_tape * t, int chn, char * line)
    {
     char * p;
     int last_n;
     int n;

     p = strchr(line,'=');
     if(p == NULL)
        { /* error - missing = */
	 /* report error - NYI */
	 return;
	} /* error - missing = */
     p++;
     
     last_n = 1;

     for(p = strtok(p, " \t\r\n"); p != NULL; p = strtok(NULL," \t\r\n"))
        { /* scan args */
	 if(p == NULL)
	    return; /* list is completed */
         n = atoi(p);
	 if(*p == '+')
	    n += last_n;
	 if(n == 0 || n >= t->pagelength)
	    continue;
         t->tape[n - 1] |= (1 << chn);
	 last_n = n;
	} /* scan args */
        
    }

/****************************************************************************
*                                  load_form
* Inputs:
*       char * formname: Form file name
* Result: channel_tape
*       A pointer to a successfully allocated channel tape object,
*	or NULL if there was an error making the construction impossible
* Effect: 
*       Loads the form file and if successful, sets the new control tape
*	to that specified by the form
* Syntax:
*	LENGTH nn
*	CHAN n: l1 l2 ... ln
****************************************************************************/

channel_tape * load_form(char * formname)
    {
     channel_tape * t = NULL;
     FILE * f;
#define LINELENGTH 256
     char line[LINELENGTH];
     char * p;

     f = fopen(formname,"r");
     if(f == NULL)
        { /* failed */
	 char fname[100];
	 strcpy(fname,formname);
	 strcat(fname,".frm");
	 f = fopen(fname,"r");
	 if(f == NULL)
	    { /* default failed */
	     /* issue error ... NYI */
	     return NULL;
	    } /* default failed */
	} /* failed */

     while(!feof(f))
        { /* scan file */
	 fgets(line, LINELENGTH, f);
	 if(feof(f))
	    break;

	 if(line[0] == '*')
	    continue;		/* comment */

	 p = line;
	 while(*p && (*p == ' ' || *p == '\t'))
	    p++;

         if(strnicmp(p,"LENGTH", 6) == 0)
	    { /* length spec */
	     int len;
	     if(t != NULL)
	        { /* duplicate */
		 /* report error... NYI */
		 continue;
		} /* duplicate */
	     len = atoi(&p[6]);
	     if(len < 5 || len > 500)
	        { /* error */
		 /* report error ... NYI */
		 continue;
		} /* error */
	     t = (channel_tape *)calloc(1,sizeof(channel_tape));
	     if(t == NULL)
	        { /* out of memory */
		 /* report error ... NYI */
		 goto exit;
		} /* out of memory */
	     t->pagelength = len;
	     t->tape = (short *) calloc(len, sizeof(short));
	     if(t->tape == NULL)
	        { /* out of memory */
		 /* report error ... NYI */
		 free(t);
		 t = NULL; /* invalidate pointer */
		 goto exit;
		} /* out of memory */
	     continue;
	    } /* length spec */

	 if(strnicmp(p,"CHAN",4) == 0)
	    { /* channel spec */
	     /* CHAN nn = l1 l2 ... ln */
	     int chn;
	     chn = atoi(&p[5]);
	     if(chn < 1 || chn > 12)
	        { /* bad channel */
		 /* report error... NYI */
		 continue;
		} /* bad channel */
	     parse_channel_args(t,chn, p);
	     continue;
	    } /* channel spec */
	} /* scan file */

     /* If we get here, there have been no fatal errors */

exit:
     fclose(f);
     return t;
    }
