xref: /csrg-svn/games/adventure/io.c (revision 6736)
1*6736Srrh #
2*6736Srrh /*      Re-coding of advent in C: file i/o and user i/o                 */
3*6736Srrh 
4*6736Srrh static char sccsid[] = "	io.c	1.1	82/05/11	";
5*6736Srrh 
6*6736Srrh #include "hdr.h"
7*6736Srrh #include <stdio.h>
8*6736Srrh 
9*6736Srrh 
10*6736Srrh getin(wrd1,wrd2)                        /* get command from user        */
11*6736Srrh char **wrd1,**wrd2;                     /* no prompt, usually           */
12*6736Srrh {       register char *s;
13*6736Srrh 	static char wd1buf[MAXSTR],wd2buf[MAXSTR];
14*6736Srrh 	int first, numch;
15*6736Srrh 
16*6736Srrh 	*wrd1=wd1buf;                   /* return ptr to internal string*/
17*6736Srrh 	*wrd2=wd2buf;
18*6736Srrh 	wd2buf[0]=0;                    /* in case it isn't set here    */
19*6736Srrh 	for (s=wd1buf, first=1, numch=0;;)
20*6736Srrh 	{       if ((*s=getchar())>='A' && *s <='Z') *s = *s - ('A' -'a');
21*6736Srrh 					/* convert to upper case        */
22*6736Srrh 		switch(*s)              /* start reading from user      */
23*6736Srrh 		{   case '\n':
24*6736Srrh 			*s=0;
25*6736Srrh 			return;
26*6736Srrh 		    case ' ':
27*6736Srrh 			if (s==wd1buf||s==wd2buf)  /* initial blank   */
28*6736Srrh 				continue;
29*6736Srrh 			*s=0;
30*6736Srrh 			if (first)      /* finished 1st wd; start 2nd   */
31*6736Srrh 			{       first=numch=0;
32*6736Srrh 				s=wd2buf;
33*6736Srrh 				break;
34*6736Srrh 			}
35*6736Srrh 			else            /* finished 2nd word            */
36*6736Srrh 			{       FLUSHLINE;
37*6736Srrh 				*s=0;
38*6736Srrh 				return;
39*6736Srrh 			}
40*6736Srrh 		    default:
41*6736Srrh 			if (++numch>=MAXSTR)    /* string too long      */
42*6736Srrh 			{       printf("Give me a break!!\n");
43*6736Srrh 				wd1buf[0]=wd2buf[0]=0;
44*6736Srrh 				FLUSHLINE;
45*6736Srrh 				return;
46*6736Srrh 			}
47*6736Srrh 			s++;
48*6736Srrh 		}
49*6736Srrh 	}
50*6736Srrh }
51*6736Srrh 
52*6736Srrh 
53*6736Srrh confirm(mesg)                           /* confirm irreversible action  */
54*6736Srrh char *mesg;
55*6736Srrh {       register int result;
56*6736Srrh 	printf("%s",mesg);              /* tell him what he did         */
57*6736Srrh 	if (getchar()=='y')             /* was his first letter a 'y'?  */
58*6736Srrh 		result=1;
59*6736Srrh 	else    result=0;
60*6736Srrh 	FLUSHLINE;
61*6736Srrh 	return(result);
62*6736Srrh }
63*6736Srrh 
64*6736Srrh yes(x,y,z)                              /* confirm with rspeak          */
65*6736Srrh int x,y,z;
66*6736Srrh {       register int result;
67*6736Srrh 	register char ch;
68*6736Srrh 	for (;;)
69*6736Srrh 	{       rspeak(x);                     /* tell him what we want*/
70*6736Srrh 		if ((ch=getchar())=='y')
71*6736Srrh 			result=TRUE;
72*6736Srrh 		else if (ch=='n') result=FALSE;
73*6736Srrh 		FLUSHLINE;
74*6736Srrh 		if (ch=='y'|| ch=='n') break;
75*6736Srrh 		printf("Please answer the question.\n");
76*6736Srrh 	}
77*6736Srrh 	if (result==TRUE) rspeak(y);
78*6736Srrh 	if (result==FALSE) rspeak(z);
79*6736Srrh 	return(result);
80*6736Srrh }
81*6736Srrh 
82*6736Srrh yesm(x,y,z)                             /* confirm with mspeak          */
83*6736Srrh int x,y,z;
84*6736Srrh {       register int result;
85*6736Srrh 	register char ch;
86*6736Srrh 	for (;;)
87*6736Srrh 	{       mspeak(x);                     /* tell him what we want*/
88*6736Srrh 		if ((ch=getchar())=='y')
89*6736Srrh 			result=TRUE;
90*6736Srrh 		else if (ch=='n') result=FALSE;
91*6736Srrh 		FLUSHLINE;
92*6736Srrh 		if (ch=='y'|| ch=='n') break;
93*6736Srrh 		printf("Please answer the question.\n");
94*6736Srrh 	}
95*6736Srrh 	if (result==TRUE) mspeak(y);
96*6736Srrh 	if (result==FALSE) mspeak(z);
97*6736Srrh 	return(result);
98*6736Srrh }
99*6736Srrh 
100*6736Srrh FILE *inbuf,*outbuf;
101*6736Srrh 
102*6736Srrh int adrptr;                             /* current seek adr ptr         */
103*6736Srrh int outsw = 0;				/* putting stuff to data file?  */
104*6736Srrh 
105*6736Srrh char iotape[] = "Ax3F'tt$8hqer*hnGKrX:!l";
106*6736Srrh char *tape = iotape;			/* pointer to encryption tape   */
107*6736Srrh 
108*6736Srrh next()                                  /* next char frm file, bump adr */
109*6736Srrh {       register char ch,t;
110*6736Srrh 	adrptr++;                       /* seek address in file         */
111*6736Srrh 	ch=getc(inbuf);
112*6736Srrh 	if (outsw)                      /* putting data in tmp file     */
113*6736Srrh 	{       if (*tape==0) tape=iotape; /* rewind encryption tape    */
114*6736Srrh 		putc(ch ^ *tape++,outbuf); /* encrypt & output char     */
115*6736Srrh 	}
116*6736Srrh 	return(ch);
117*6736Srrh }
118*6736Srrh 
119*6736Srrh 
120*6736Srrh char breakch;                           /* tell which char ended rnum   */
121*6736Srrh 
122*6736Srrh 
123*6736Srrh rdata()                                 /* read all data from orig file */
124*6736Srrh {       register int sect;
125*6736Srrh 	register char ch;
126*6736Srrh 	if ((inbuf=fopen(DATFILE,"r"))==NULL)     /* all the data lives in here   */
127*6736Srrh 	{       printf("Cannot open data file %s\n",DATFILE);
128*6736Srrh 		exit(0);
129*6736Srrh 	}
130*6736Srrh 	if ((outbuf=fopen(TMPFILE,"w"))==NULL)   /* the text lines will go here  */
131*6736Srrh 	{       printf("Cannot create output file %s\n",TMPFILE);
132*6736Srrh 		exit(0);
133*6736Srrh 	}
134*6736Srrh 	setup=clsses=1;
135*6736Srrh 	for (;;)                        /* read data sections           */
136*6736Srrh 	{       sect=next()-'0';        /* 1st digit of section number  */
137*6736Srrh 		printf("Section %c",sect+'0');
138*6736Srrh 		if ((ch=next())!=LF)    /* is there a second digit?     */
139*6736Srrh 		{       FLUSHLF;
140*6736Srrh 			putchar(ch);
141*6736Srrh 			sect=10*sect+ch-'0';
142*6736Srrh 		}
143*6736Srrh 		putchar('\n');
144*6736Srrh 		switch(sect)
145*6736Srrh 		{   case 0:             /* finished reading database    */
146*6736Srrh 			fclose(inbuf);
147*6736Srrh 			fclose(outbuf);
148*6736Srrh 			return;
149*6736Srrh 		    case 1:             /* long form descriptions       */
150*6736Srrh 			rdesc(1);
151*6736Srrh 			break;
152*6736Srrh 		    case 2:             /* short form descriptions      */
153*6736Srrh 			rdesc(2);
154*6736Srrh 			break;
155*6736Srrh 		    case 3:             /* travel table                 */
156*6736Srrh 			rtrav();   break;
157*6736Srrh 		    case 4:             /* vocabulary                   */
158*6736Srrh 			rvoc();
159*6736Srrh 			break;
160*6736Srrh 		    case 5:             /* object descriptions          */
161*6736Srrh 			rdesc(5);
162*6736Srrh 			break;
163*6736Srrh 		    case 6:             /* arbitrary messages           */
164*6736Srrh 			rdesc(6);
165*6736Srrh 			break;
166*6736Srrh 		    case 7:             /* object locations             */
167*6736Srrh 			rlocs();   break;
168*6736Srrh 		    case 8:             /* action defaults              */
169*6736Srrh 			rdflt();   break;
170*6736Srrh 		    case 9:             /* liquid assets                */
171*6736Srrh 			rliq();    break;
172*6736Srrh 		    case 10:            /* class messages               */
173*6736Srrh 			rdesc(10);
174*6736Srrh 			break;
175*6736Srrh 		    case 11:            /* hints                        */
176*6736Srrh 			rhints();  break;
177*6736Srrh 		    case 12:            /* magic messages               */
178*6736Srrh 			rdesc(12);
179*6736Srrh 			break;
180*6736Srrh 		    default:
181*6736Srrh 			printf("Invalid data section number: %d\n",sect);
182*6736Srrh 			for (;;) putchar(next());
183*6736Srrh 		}
184*6736Srrh 		if (breakch!=LF)        /* routines return after "-1"   */
185*6736Srrh 			FLUSHLF;
186*6736Srrh 	}
187*6736Srrh }
188*6736Srrh 
189*6736Srrh char nbf[12];
190*6736Srrh 
191*6736Srrh 
192*6736Srrh rnum()                                  /* read initial location num    */
193*6736Srrh {       register char *s;
194*6736Srrh 	tape = iotape;                  /* restart encryption tape      */
195*6736Srrh 	for (s=nbf,*s=0;; s++)
196*6736Srrh 		if ((*s=next())==TAB || *s=='\n' || *s==LF)
197*6736Srrh 			break;
198*6736Srrh 	breakch= *s;                    /* save char for rtrav()        */
199*6736Srrh 	*s=0;                           /* got the number as ascii      */
200*6736Srrh 	if (nbf[0]=='-') return(-1);    /* end of data                  */
201*6736Srrh 	return(atoi(nbf));              /* convert it to integer        */
202*6736Srrh }
203*6736Srrh 
204*6736Srrh int seekhere = 1;			/* initial seek for output file */
205*6736Srrh 
206*6736Srrh rdesc(sect)                             /* read description-format msgs */
207*6736Srrh int sect;
208*6736Srrh {       register char *s,*t;
209*6736Srrh 	register int locc;
210*6736Srrh 	int  seekstart, maystart, adrstart;
211*6736Srrh 	char *entry;
212*6736Srrh 	outsw=1;                        /* these msgs go into tmp file  */
213*6736Srrh 	if (sect==1) putc('X',outbuf);  /* so seekadr > 0               */
214*6736Srrh 	adrptr=0;
215*6736Srrh 	for (oldloc= -1, seekstart=seekhere;;)
216*6736Srrh 	{       maystart=adrptr;        /* maybe starting new entry     */
217*6736Srrh 		if ((locc=rnum())!=oldloc && oldloc>=0  /* finished msg */
218*6736Srrh 		    && ! (sect==5 && (locc==0 || locc>=100)))/* unless sect 5*/
219*6736Srrh 		{       switch(sect)    /* now put it into right table  */
220*6736Srrh 			{   case 1:     /* long descriptions            */
221*6736Srrh 				ltext[oldloc].seekadr=seekhere;
222*6736Srrh 				ltext[oldloc].txtlen=maystart-seekstart;
223*6736Srrh 				break;
224*6736Srrh 			    case 2:     /* short descriptions           */
225*6736Srrh 				stext[oldloc].seekadr=seekhere;
226*6736Srrh 				stext[oldloc].txtlen=maystart-seekstart;
227*6736Srrh 				break;
228*6736Srrh 			    case 5:     /* object descriptions          */
229*6736Srrh 				ptext[oldloc].seekadr=seekhere;
230*6736Srrh 				ptext[oldloc].txtlen=maystart-seekstart;
231*6736Srrh 				break;
232*6736Srrh 			    case 6:     /* random messages              */
233*6736Srrh 				if (oldloc>RTXSIZ)
234*6736Srrh 				{       printf("Too many random msgs\n");
235*6736Srrh 					exit(0);
236*6736Srrh 				}
237*6736Srrh 				rtext[oldloc].seekadr=seekhere;
238*6736Srrh 				rtext[oldloc].txtlen=maystart-seekstart;
239*6736Srrh 				break;
240*6736Srrh 			    case 10:    /* class messages               */
241*6736Srrh 				ctext[clsses].seekadr=seekhere;
242*6736Srrh 				ctext[clsses].txtlen=maystart-seekstart;
243*6736Srrh 				cval[clsses++]=oldloc;
244*6736Srrh 				break;
245*6736Srrh 			    case 12:    /* magic messages               */
246*6736Srrh 				if (oldloc>MAGSIZ)
247*6736Srrh 				{       printf("Too many magic msgs\n");
248*6736Srrh 					exit(0);
249*6736Srrh 				}
250*6736Srrh 				mtext[oldloc].seekadr=seekhere;
251*6736Srrh 				mtext[oldloc].txtlen=maystart-seekstart;
252*6736Srrh 				break;
253*6736Srrh 			    default:
254*6736Srrh 				printf("rdesc called with bad section\n");
255*6736Srrh 				exit(0);
256*6736Srrh 			}
257*6736Srrh 			seekhere += maystart-seekstart;
258*6736Srrh 		}
259*6736Srrh 		if (locc<0)
260*6736Srrh 		{       outsw=0;        /* turn off output              */
261*6736Srrh 			seekhere += 3;  /* -1<delimiter>                */
262*6736Srrh 			return;
263*6736Srrh 		}
264*6736Srrh 		if (sect!=5 || (locc>0 && locc<100))
265*6736Srrh 		{       if (oldloc!=locc)/* starting a new message       */
266*6736Srrh 				seekstart=maystart;
267*6736Srrh 			oldloc=locc;
268*6736Srrh 		}
269*6736Srrh 		FLUSHLF;                /* scan the line                */
270*6736Srrh 	}
271*6736Srrh }
272*6736Srrh 
273*6736Srrh 
274*6736Srrh rtrav()                                 /* read travel table            */
275*6736Srrh {       register int locc;
276*6736Srrh 	register struct travlist *t;
277*6736Srrh 	register char *s;
278*6736Srrh 	char buf[12];
279*6736Srrh 	int len,m,n,entries;
280*6736Srrh 	for (oldloc= -1;;)              /* get another line             */
281*6736Srrh 	{       if ((locc=rnum())!=oldloc && oldloc>=0) /* end of entry */
282*6736Srrh 		{
283*6736Srrh 			t->next = 0;    /* terminate the old entry      */
284*6736Srrh 		/*      printf("%d:%d entries\n",oldloc,entries);       */
285*6736Srrh 		/*      twrite(oldloc);                                 */
286*6736Srrh 		}
287*6736Srrh 		if (locc== -1) return;
288*6736Srrh 		if (locc!=oldloc)        /* getting a new entry         */
289*6736Srrh 		{       t=travel[locc]=(struct travlist *) malloc(sizeof (struct travlist));
290*6736Srrh 		/*      printf("New travel list for %d\n",locc);        */
291*6736Srrh 			entries=0;
292*6736Srrh 			oldloc=locc;
293*6736Srrh 		}
294*6736Srrh 		for (s=buf;; *s++)      /* get the newloc number /ASCII */
295*6736Srrh 			if ((*s=next())==TAB || *s==LF) break;
296*6736Srrh 		*s=0;
297*6736Srrh 		len=length(buf)-1;      /* quad long number handling    */
298*6736Srrh 	/*      printf("Newloc: %s (%d chars)\n",buf,len);              */
299*6736Srrh 		if (len<4)              /* no "m" conditions            */
300*6736Srrh 		{       m=0;
301*6736Srrh 			n=atoi(buf);    /* newloc mod 1000 = newloc     */
302*6736Srrh 		}
303*6736Srrh 		else                    /* a long integer               */
304*6736Srrh 		{       n=atoi(buf+len-3);
305*6736Srrh 			buf[len-3]=0;   /* terminate newloc/1000        */
306*6736Srrh 			m=atoi(buf);
307*6736Srrh 		}
308*6736Srrh 		while (breakch!=LF)     /* only do one line at a time   */
309*6736Srrh 		{       if (entries++) t=t->next=(struct travlist *) malloc(sizeof (struct travlist));
310*6736Srrh 			t->tverb=rnum();/* get verb from the file       */
311*6736Srrh 			t->tloc=n;      /* table entry mod 1000         */
312*6736Srrh 			t->conditions=m;/* table entry / 1000           */
313*6736Srrh 		/*      printf("entry %d for %d\n",entries,locc);       */
314*6736Srrh 		}
315*6736Srrh 	}
316*6736Srrh }
317*6736Srrh 
318*6736Srrh 
319*6736Srrh twrite(loq)                             /* travel options from this loc */
320*6736Srrh int loq;
321*6736Srrh {       register struct travlist *t;
322*6736Srrh 	printf("If");
323*6736Srrh 	speak(&ltext[loq]);
324*6736Srrh 	printf("then\n");
325*6736Srrh 	for (t=travel[loq]; t!=0; t=t->next)
326*6736Srrh 	{       printf("verb %d takes you to ",t->tverb);
327*6736Srrh 		if (t->tloc<=300)
328*6736Srrh 			speak(&ltext[t->tloc]);
329*6736Srrh 		else if (t->tloc<=500)
330*6736Srrh 			printf("special code %d\n",t->tloc-300);
331*6736Srrh 		else
332*6736Srrh 			rspeak(t->tloc-500);
333*6736Srrh 		printf("under conditions %d\n",t->conditions);
334*6736Srrh 	}
335*6736Srrh }
336*6736Srrh 
337*6736Srrh 
338*6736Srrh 
339*6736Srrh rvoc()
340*6736Srrh {       register char *s;               /* read the vocabulary          */
341*6736Srrh 	register int index;
342*6736Srrh 	char buf[6];
343*6736Srrh 	for (;;)
344*6736Srrh 	{       index=rnum();
345*6736Srrh 		if (index<0) break;
346*6736Srrh 		for (s=buf,*s=0;; s++)  /* get the word                 */
347*6736Srrh 			if ((*s=next())==TAB || *s=='\n' || *s==LF
348*6736Srrh 				|| *s==' ') break;
349*6736Srrh 			/* terminate word with newline, LF, tab, blank  */
350*6736Srrh 		if (*s!='\n' && *s!=LF) FLUSHLF;  /* can be comments    */
351*6736Srrh 		*s=0;
352*6736Srrh 	/*      printf("\"%s\"=%d\n",buf,index);*/
353*6736Srrh 		vocab(buf,-2,index);
354*6736Srrh 	}
355*6736Srrh /*	prht();	*/
356*6736Srrh }
357*6736Srrh 
358*6736Srrh 
359*6736Srrh rlocs()                                 /* initial object locations     */
360*6736Srrh {	for (;;)
361*6736Srrh 	{       if ((obj=rnum())<0) break;
362*6736Srrh 		plac[obj]=rnum();       /* initial loc for this obj     */
363*6736Srrh 		if (breakch==TAB)       /* there's another entry        */
364*6736Srrh 			fixd[obj]=rnum();
365*6736Srrh 		else    fixd[obj]=0;
366*6736Srrh 	}
367*6736Srrh }
368*6736Srrh 
369*6736Srrh rdflt()                                 /* default verb messages        */
370*6736Srrh {	for (;;)
371*6736Srrh 	{       if ((verb=rnum())<0) break;
372*6736Srrh 		actspk[verb]=rnum();
373*6736Srrh 	}
374*6736Srrh }
375*6736Srrh 
376*6736Srrh rliq()                                  /* liquid assets &c: cond bits  */
377*6736Srrh {       register int bitnum;
378*6736Srrh 	for (;;)                        /* read new bit list            */
379*6736Srrh 	{       if ((bitnum=rnum())<0) break;
380*6736Srrh 		for (;;)                /* read locs for bits           */
381*6736Srrh 		{       cond[rnum()] |= setbit[bitnum];
382*6736Srrh 			if (breakch==LF) break;
383*6736Srrh 		}
384*6736Srrh 	}
385*6736Srrh }
386*6736Srrh 
387*6736Srrh rhints()
388*6736Srrh {       register int hintnum,i;
389*6736Srrh 	hntmax=0;
390*6736Srrh 	for (;;)
391*6736Srrh 	{       if ((hintnum=rnum())<0) break;
392*6736Srrh 		for (i=1; i<5; i++)
393*6736Srrh 			hints[hintnum][i]=rnum();
394*6736Srrh 		if (hintnum>hntmax) hntmax=hintnum;
395*6736Srrh 	}
396*6736Srrh }
397*6736Srrh 
398*6736Srrh 
399*6736Srrh rspeak(msg)
400*6736Srrh int msg;
401*6736Srrh {       if (msg!=0) speak(&rtext[msg]);
402*6736Srrh }
403*6736Srrh 
404*6736Srrh 
405*6736Srrh mspeak(msg)
406*6736Srrh int msg;
407*6736Srrh {       if (msg!=0) speak(&mtext[msg]);
408*6736Srrh }
409*6736Srrh 
410*6736Srrh 
411*6736Srrh doseek(offset)  /* do 2 seeks to get to right place in the file         */
412*6736Srrh unsigned offset;
413*6736Srrh {
414*6736Srrh 	extern unsigned filesize;
415*6736Srrh 	lseek(datfd,(long)offset+(long)filesize, 0);
416*6736Srrh #ifdef notdef
417*6736Srrh 	blockadr=chadr=0;
418*6736Srrh 	if (offset<0)                   /* right place is offset+filesize*/
419*6736Srrh 	{       blockadr += 64;         /* take off 32768 bytes         */
420*6736Srrh 		chadr += offset+32768;  /* & make them into 64 blocks   */
421*6736Srrh 	}
422*6736Srrh 	else chadr += offset;
423*6736Srrh 	if (filesize<0)                 /* data starts after file       */
424*6736Srrh 	{       blockadr += 64;         /* which may also be large      */
425*6736Srrh 		chadr += filesize+32768;
426*6736Srrh 	}
427*6736Srrh 	else chadr += filesize;
428*6736Srrh 	if (chadr<0)                    /* and the leftovers may be lge */
429*6736Srrh 	{       blockadr += 64;
430*6736Srrh 		chadr += 32768;
431*6736Srrh 	}
432*6736Srrh 	seek(datfd,blockadr,3);         /* get within 32767             */
433*6736Srrh 	seek(datfd,chadr,1);            /* then the rest of the way     */
434*6736Srrh #endif
435*6736Srrh }
436*6736Srrh 
437*6736Srrh 
438*6736Srrh speak(msg)       /* read, decrypt, and print a message (not ptext)      */
439*6736Srrh struct text *msg;/* msg is a pointer to seek address and length of mess */
440*6736Srrh {       register char *s,nonfirst;
441*6736Srrh 	register char *tbuf;
442*6736Srrh 	doseek(msg->seekadr);
443*6736Srrh 	if ((tbuf=(char *) malloc(msg->txtlen+1))<0) bug(109);
444*6736Srrh 	read(datfd,tbuf,msg->txtlen);
445*6736Srrh 	s=tbuf;
446*6736Srrh 	nonfirst=0;
447*6736Srrh 	while (s-tbuf<msg->txtlen)      /* read a line at a time        */
448*6736Srrh 	{       tape=iotape;            /* restart decryption tape      */
449*6736Srrh 		while ((*s++^*tape++)!=TAB); /* read past loc num       */
450*6736Srrh 		/* assume tape is longer than location number           */
451*6736Srrh 		/*   plus the lookahead put together                    */
452*6736Srrh 		if ((*s^*tape)=='>' &&
453*6736Srrh 			(*(s+1)^*(tape+1))=='$' &&
454*6736Srrh 			(*(s+2)^*(tape+2))=='<') break;
455*6736Srrh 		if (blklin&&!nonfirst++) putchar('\n');
456*6736Srrh 		do
457*6736Srrh 		{       if (*tape==0) tape=iotape;/* rewind decryp tape */
458*6736Srrh 			putchar(*s^*tape);
459*6736Srrh 		} while ((*s++^*tape++)!=LF);   /* better end with LF   */
460*6736Srrh 	}
461*6736Srrh 	free(tbuf);
462*6736Srrh }
463*6736Srrh 
464*6736Srrh 
465*6736Srrh pspeak(msg,skip) /* read, decrypt an print a ptext message              */
466*6736Srrh int msg;         /* msg is the number of all the p msgs for this place  */
467*6736Srrh int skip;       /* assumes object 1 doesn't have prop 1, obj 2 no prop 2 &c*/
468*6736Srrh {       register char *s,nonfirst;
469*6736Srrh 	register char *tbuf;
470*6736Srrh 	char *numst;
471*6736Srrh 	int lstr;
472*6736Srrh 	doseek(ptext[msg].seekadr);
473*6736Srrh 	if ((tbuf=(char *) malloc((lstr=ptext[msg].txtlen)+1))<0) bug(108);
474*6736Srrh 	read(datfd,tbuf,lstr);
475*6736Srrh 	s=tbuf;
476*6736Srrh 	nonfirst=0;
477*6736Srrh 	while (s-tbuf<lstr)             /* read a line at a time        */
478*6736Srrh 	{       tape=iotape;            /* restart decryption tape      */
479*6736Srrh 		for (numst=s; (*s^= *tape++)!=TAB; s++); /* get number  */
480*6736Srrh 		*s++=0; /* decrypting number within the string          */
481*6736Srrh 		if (atoi(numst)!=100*skip && skip>=0)
482*6736Srrh 		{       while ((*s++^*tape++)!=LF) /* flush the line    */
483*6736Srrh 				if (*tape==0) tape=iotape;
484*6736Srrh 			continue;
485*6736Srrh 		}
486*6736Srrh 		if ((*s^*tape)=='>' && (*(s+1)^*(tape+1))=='$' &&
487*6736Srrh 			(*(s+2)^*(tape+2))=='<') break;
488*6736Srrh 		if (blklin && ! nonfirst++) putchar('\n');
489*6736Srrh 		do
490*6736Srrh 		{       if (*tape==0) tape=iotape;
491*6736Srrh 			putchar(*s^*tape);
492*6736Srrh 		} while ((*s++^*tape++)!=LF);   /* better end with LF   */
493*6736Srrh 		if (skip<0) break;
494*6736Srrh 	}
495*6736Srrh 	free(tbuf);
496*6736Srrh }
497*6736Srrh 
498