#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include "xregal.h"
#include "moviedb.h"
#include "printmovie.h"
#include "dbutils.h"
#include "utility.h"
#include "filmbuf.h"

typedef struct {
	char *tag;
	char *text;
	} HeadingInfo;

static Buffer *utilitybuf=NULL;

void printListEntry(struct titleListEntry *lrec, int listId) { 
	char  tmp[MXLINELEN];
	char  fmtline[MXLINELEN];
	char  *comma, *bracket;
	char hangindent[16];

	sprintf(hangindent, "<h %d>", app_data.hangingIndent);
	strcpy(tmp, lrec->name);
	if ((comma=strchr(tmp, ',')) != NULL) {
		if (*(comma + strlen(comma) - 1) == ')' &&
			(bracket = strstr(comma, " (")) != NULL) {
			*comma = '\0';
			*bracket = '\0';
			if (lrec->attr != NULL)
				sprintf(fmtline, "%s %s<e> %s <f2>%s<f1>", 
					comma+2, tmp, bracket+1, lrec->attr);
			else
				sprintf(fmtline, "%s %s<e> %s", comma + 2, tmp, bracket+1);
			}
		else {
			*comma = '\0' ;
			if (lrec->attr != NULL )
				sprintf(fmtline, "%s %s<e> <f2>%s<f1>", 
					comma + 2, tmp, lrec->attr);
			else
				sprintf ( fmtline, "%s %s<e>", comma + 2, tmp );
			}
		}
	else
		if (lrec->attr != NULL)
			sprintf ( fmtline, "%s<e> <f2>%s<f1>", 
				lrec->name, lrec->attr);
		else
			sprintf(fmtline, "%s<e>", lrec->name);

	if (listId == WRITER_LIST_ID) {
 		sprintf(tmp, "<l %d:%s>%s", listId, lrec->name, fmtline);
		AddToFilmbuf(tmp);
		return;
		}

	/* print out name/character name */
	if (lrec->cname == NULL)
 		sprintf(tmp, "<l %d:%s>%s\n", listId, lrec->name, fmtline);
  	else 
	    sprintf(tmp, "<l %d:%s>%s <d %d><w1>%s<w0><i0>\n", 
					listId, lrec->name, fmtline, 
					app_data.casttab, lrec->cname);

	AddToFilmbuf2(hangindent, tmp);
	}



void printCastList(struct titleSearchRec *trec) {
	int j, base, count;
	extern int castTitleResultSort(struct titleListEntry *e1, struct titleListEntry *e2);
	Boolean castOrdered;

	if (trec->results[0].base >= 0)
    	base = trec->results[0].base; 
  	else
    	base = trec->results[1].base;
  	count = trec->results[0].count + trec->results[1].count;

  	if (count <= 0) 
		return;

	/* sort the cast list */
   	qsort((void*) &(trec -> entries[base]), (size_t) count, 
			sizeof(struct titleListEntry), 
			(int (*) (const void*, const void*)) castTitleResultSort);

	/* print the heading */
   	if (trec->entries[base].position == 1) {
		castOrdered = TRUE ;
   		if (trec->castStatus == completed) 
			AddToFilmbuf("<f4><c4>Complete Cast: <f5>(credits order)\n<f1><c1>");
   		else if (trec->castStatus == verified) 
			AddToFilmbuf("<f4><c4>Verified Complete Cast: <f5>(credits order)\n<f1><c1>");
   		else 
       		AddToFilmbuf("<f4><c4>Cast: <f5>(credits order)\n<f1><c1>");
		}
   	else {
		castOrdered = FALSE ;
   		if (trec->castStatus == completed) 
			AddToFilmbuf("<f4><c4>Complete Cast: <f5>(alphabetical order)\n<f1><c1>");
   		else if (trec->castStatus == verified) 
			AddToFilmbuf("<f4><c4>Verified Complete Cast: <f5>(alphabetical order)\n<f1><c1>");
   		else 
			AddToFilmbuf("<f4><c4>Cast: <f5>(alphabetical order)\n<f1><c1>");
		}

	/* print out the cast list */
    for (j=0; j<count; j++) {
		if (castOrdered && trec->entries[base+j].position == MAXPOS) {
			castOrdered = FALSE ;
			AddToFilmbuf("\n<f5>Remainder of Cast: (alphabetical order)<f1>\n");
			}
		printListEntry(&(trec->entries[base+j]), ACRSRCH);
		}

	AddToFilmbuf("\n");
	}



void printWriters(struct titleSearchRec *trec, int base, int count) {
	Boolean writersOrdered;
	int linePrev, groupPrev, subgroupPrev, j;
	char hangindent[16];

	sprintf(hangindent, "<h %d>", app_data.hangingIndent);

	if (trec->entries[base].lineOrder == 1) {
		AddToFilmbuf(" <f5>(credits order)");
		writersOrdered = True;
		}
	else {
		AddToFilmbuf(" <f5>(alphabetical order)");
		writersOrdered = False;
		}
	AddToFilmbuf("\n<f1><c1><w1>");

	for ( j = 0 ; j < count ; j++ ) {
		if ( j == 0 ) {
			AddToFilmbuf(hangindent);
			printListEntry(&(trec->entries[base+j]), WRITER_LIST_ID);
			}
		else {
			if (linePrev != trec->entries[base+j].lineOrder 
					&& trec->entries[base+j].lineOrder != MAXPOS)
				AddToFilmbuf2("\n", hangindent);
			else if (groupPrev == trec->entries[base+j].groupOrder 
					&& trec->entries[base+j].groupOrder != MAXPOS)
				AddToFilmbuf(" & ");
			else if (trec->entries[base+j].subgroupOrder != MAXPOS)
				AddToFilmbuf(" and ");
			else {
				if (writersOrdered) {
					AddToFilmbuf("\n");
					writersOrdered = False;
					}
				AddToFilmbuf2("\n", hangindent);
				}
			printListEntry(&(trec->entries[base+j]), WRITER_LIST_ID);
			}

		linePrev = trec->entries[base+j].lineOrder;
		groupPrev = trec->entries[base+j].groupOrder;
		subgroupPrev = trec->entries[base+j].subgroupOrder;
		}

	AddToFilmbuf("\n\n<w0>");
	}


void printFilmographyLists(struct titleSearchRec *trec) {
	int i, j, base, count, listId ;
	extern int titleResultSort(struct titleListEntry *e1, struct titleListEntry *e2);
	char buf[1024];

	for (i=0; i<NO_OF_FILMOGRAPHY_LISTS-2; i++) {
    	listId = titleOrderData[i].listId;
    	base = trec->results[listId].base;
    	count = trec->results[listId].count;
    	if (count>0) {
      		if (count==1)
				sprintf(buf, "<f4><c4>%s", titleOrderData[i].description);
      		else {
        		sprintf(buf, "<f4><c4>%s", titleOrderData[i].pluralDesc);
        		qsort((void*) &(trec->entries[base]), 
					(size_t) count, 
					sizeof(struct titleListEntry), 
					(int (*) (const void*, const void*)) titleResultSort);
      			}
			AddToFilmbuf(buf);

			if ( listId == WRITER_LIST_ID ) 
				printWriters(trec, base, count);
			else {
				AddToFilmbuf("\n<w1><f1><c1>");
				for (j=0; j<count; j++)
			 		printListEntry(&(trec->entries[base+j]), listId);
				AddToFilmbuf("<w0>\n");
				}
			}
		}
	if (trec->crewStatus == completed)
		AddToFilmbuf("(Crew believed to be complete.)\n\n");
	else if (trec->crewStatus == verified)
		AddToFilmbuf("(Crew verified as complete.)\n\n");
	}



void printTagLines(struct lineRec *triv) {
	struct lineRec *line;

	if (triv==NULL) 
		return;

	AddToFilmbuf3("<m1><f2><w1>", triv->text+1, "<w0>");

    for (line=triv->next; line!=NULL; line=line->next) {
		if (*(line->text)=='\n')
			continue;

		AddToFilmbuf3("\n<w1>", line->text+1, "<w0>");
		}

	AddToFilmbuf("<f1><m0>\n");
	}

void printTechInfo(struct titleInfoRec *titleInfo, int listId) {
	struct titleInfoRec *line ;
	char currentTag[5];
	char *ptr;
	char buf[16];

	AddToFilmbuf3("<f4><c4>",  titleInfoDefs[listId].tag, "<f1><c1><w1>");

	sprintf(buf, "<d %d><i %d>", app_data.techtab, app_data.techtab);
	currentTag[0] = '\0';
	for (line=titleInfo; line != NULL; line = line->next) 
		if ((ptr=strchr(line->text, ':')) != NULL) {
			*ptr++ = '\0';
			if (strcmp(currentTag, line->text) != 0) {
				AddToFilmbuf("<i0>\n");
				strcpy(currentTag, line->text);
				if (strcmp(line->text, "CAM") == 0) 
					AddToFilmbuf3("Camera ", buf, ptr);
				else if (strcmp(line->text, "MET") == 0) 
					AddToFilmbuf3("Film Length ", buf, ptr);
				else if (strcmp(line->text, "OFM") == 0) 
					AddToFilmbuf3("Negative Format ", buf, ptr);
				else if (strcmp (line->text, "PFM") == 0) 
					AddToFilmbuf3("Print Format ", buf, ptr);
				else if (strcmp(line->text, "RAT") == 0) 
					AddToFilmbuf3("Aspect Ratio ", buf, ptr);
				else if (strcmp(line->text, "PCS") == 0) 
					AddToFilmbuf3("Process ", buf, ptr);
				else if (strcmp(line->text, "LAB") == 0) 
					AddToFilmbuf3("Laboratory ", buf, ptr);
				else 
					AddToFilmbuf3(line->text, buf, ptr);
				if (line->attr != NULL)
					AddToFilmbuf2(" ", line->attr);
			}
		else {
			AddToFilmbuf2(" ; ", ptr);
			if (line->attr != NULL) 
				AddToFilmbuf2(" ", line->attr);
			}
		}
	AddToFilmbuf("<i0><w0>\n\n" );
	}


void printTitleInfo(struct titleInfoRec *titleInfo, int listId) {
	struct titleInfoRec *line ;
	Boolean firstFlag = True;
	char indent[16];

	if (titleInfo == NULL)
		return;

	sprintf(indent, "<h %d>", app_data.hangingIndent);

	if (titleInfoDefs[listId].displayFormat == stdDisplay) {

		/* print genres, production co, certificates, running times, 
		   color info, sound mix, release date, locations */

		AddToFilmbuf3("<f4><c4>", titleInfoDefs[listId].tag, "\n<f1><c1>");
		for (line=titleInfo; line != NULL; line=line->next) {
			AddToFilmbuf3("<w1>", indent, line->text);
        	if (line->attr != NULL)
				AddToFilmbuf(line->attr);
			AddToFilmbuf("<w0>\n");
			}

		AddToFilmbuf("\n");
		}
    else if (titleInfoDefs[listId].displayFormat==mergeDisplay) {

 		/* print country of origin */

		AddToFilmbuf3("<f4><c4>", titleInfoDefs[listId].tag, "\n<f1><c1>");
		for (line=titleInfo; line!=NULL; line=line->next) {
	        if (firstFlag)
				AddToFilmbuf(line->text); 
			else
				AddToFilmbuf2(" / ", line->text); 
			if (line->attr!=NULL )
				AddToFilmbuf2(" ", line->attr);
			firstFlag = False;
			}
		AddToFilmbuf("\n\n");
		}
    else if (titleInfoDefs[listId].displayFormat==techDisplay)
		printTechInfo(titleInfo, listId);
	}


void printOutline(struct outlineRec *rec) {
	char *cp;

	if (rec->PL != NULL) {
		cp=insert_qv_links(rec->PL);
		AddToFilmbuf("<f4><c4>Summary:\n<f1><c1>");
		AddToFilmbuf3("<w1>", cp, "<w0>");
		if (rec->BY != NULL)
			AddToFilmbuf3("\n<w1>Summary by: ", rec->BY, "<w0>\n");
		}
	}


void printPlot(struct plotRec *rec) {
	struct outlineRec *oline;

	if (rec != NULL) {
		for (oline=rec->outline; oline != NULL; oline = oline->next)
			printOutline(oline);

		if (rec->RV != NULL)
			AddToFilmbuf3("Reviews (rec.arts.movies.revies index):\n  ", 
				rec->RV, "\n");
		}
	}


void printMovieLinks(int noOfEntries, struct movieLinkRec *links) {
	int i;
	char buf[16];

	if (noOfEntries <= 0) 
		return;

	AddToFilmbuf("<f4><c4>Movie Links\n<f1><c1><w1>");
	for (i=0; i<noOfEntries; i++) {
		AddToFilmbuf(movieLinkDefs[links[i].link].string);
		sprintf(buf, " <i %d>", app_data.hangingIndent);
		AddToFilmbuf(buf);
		AddToFilmbuf3("<l MOV:", links[i].title, ">");
		AddToFilmbuf2(links[i].title, "<e><i0>\n");
		}
	AddToFilmbuf("<w0>\n" );
	}

HeadingInfo trivia_items[] = {
	{"CAMEO(", "Cameo"},
	{"ACTTRADE(", "Actors trademark"},
	{"DIRTRADE(", "Directors trademark"},
	{"DIRCAMEO(", "Director cameo"},
	{"SMITHEE(", "Smithee"},
	{"BOOTH(", "Booth"},
	{NULL, NULL}
	};

void printTriviaItem(char *str, Boolean wrapit) {
	char *cp, *end;
	char linkbuf[128];
	int i;
	
	if (wrapit)
		trim_text2(str, str);
	cp=insert_qv_links(str);

	if (wrapit)
		AddToFilmbuf("\n\n");
	else
		AddToFilmbuf("\n");

	i=0;
	while (trivia_items[i].tag != NULL) {
		if (strncmp(cp, trivia_items[i].tag, strlen(trivia_items[i].tag))==0) {
			end=strstr(cp, "):");
			if (end!=NULL) {
				*end='\0';
				AddToFilmbuf2(trivia_items[i].text, " (");
				cp += strlen(trivia_items[i].tag);
				sprintf(linkbuf, "<l -1:%s>%s<e>", cp, cp);
				AddToFilmbuf(linkbuf);
				AddToFilmbuf("): ");
				cp=end+2;
				break;
				}
			}
		i++;
		}

	AddToFilmbuf(cp);
	}

void printTrivia(struct lineRec *triv, int listId) { 
	struct lineRec *line;
	Boolean wrapit[NO_OF_TRIV_LISTS-1] = {
		True,		/* trivia */
		False,		/* crazy credits */
		True,		/* goofs - printed with separate routine */
		True,		/* quotes - printed with separate routine */
		False,		/* soundtrack */
		True,		/* alternate versions */
		};
 
	if (triv == NULL) 
		return;

	AddToFilmbuf3("<f4><c4>", triviaDefs[listId].desc, "<f1><c1>");

	if (wrapit[listId])
		AddToFilmbuf("<w1>");
 
	ClearBuffer(utilitybuf);
	for (line=triv; line != NULL; line = line->next) {

		if (( *(line->text) == '-' ) && !EmptyBuffer(utilitybuf)) {
			printTriviaItem(utilitybuf->buf, wrapit[listId]);
			ClearBuffer(utilitybuf);
			}

		if ((*(line->text) == '-' ) && wrapit[listId])
			AddToBuffer(utilitybuf, line->text+2);
		else
			AddToBuffer(utilitybuf, line->text);
		}

	printTriviaItem(utilitybuf->buf, wrapit[listId]);
	AddToFilmbuf("<w0>\n\n");
	} 



static HeadingInfo goof_headings[] = {
		{"- CONT:", "Continuity"},
		{"- PLOT:", "Plot holes"},
		{"- FACT:", "Factual Errors"},
		{"- DATE:", "Anachronisms"},
		{"- FAKE:", "Revealing mistakes"},
		{"- BOOM:", "Visible boom mikes"},
		{"- CREW:", "Visible crew/equipment"},
		{"- SYNC:", "Audio/visual unsynchronised"},
		{"- GEOG:", "Geographical errors"},
		{"- FAIR:", "Incorrectly regarded as goofs"},
		{"- MISC:", "Miscellaneous"},
		{NULL, NULL}
		};

void printGoofs(struct lineRec *triv) { 
	struct lineRec *line;
	Boolean heading_printed;
	int i;
	char *cp;
 
	if (triv == NULL) 
		return;

	AddToFilmbuf("<f4><c4>Goofs<f1><c1><w1>\n\n");

	ClearBuffer(utilitybuf);
	i=0;
	while (goof_headings[i].tag != NULL) {
		heading_printed=False;
		for (line=triv; line != NULL; ) {

			/* ignore dividing lines in the goofs file */
			if ((strncmp(line->text, "- --------", 10)==0) ||
				(strncmp(goof_headings[i].tag, line->text, 7)!=0)) {
				line = line->next;
				continue;
				}

			if (!heading_printed) {
				AddToFilmbuf3("<f5>", goof_headings[i].text, "<f1>\n");
				heading_printed=True;
				}

			AddToBuffer(utilitybuf, "<b>");
			AddToBuffer(utilitybuf, line->text+8);
			line = line->next;
			while (line!=NULL) {
				if (*(line->text) == '-' )
					break;
				AddToBuffer(utilitybuf, line->text);
				line = line->next;
				}
			trim_text2(utilitybuf->buf, utilitybuf->buf);
			cp=insert_qv_links(utilitybuf->buf);
			AddToFilmbuf2(cp, "\n\n");
			ClearBuffer(utilitybuf);
			}
		i++;
		}

	AddToFilmbuf("<w0>\n");
	} 




void printQuoteLine(char *str) {
	char *cp;
	char buf[16];

	trim_text2(str, str);
	str=insert_qv_links(str);
	if (str[0]=='[') {
		AddToFilmbuf3("<f2>", str, "<f1>\n");
		return;
		}

	cp=strchr(str, ':');
	if (cp==NULL)
		AddToFilmbuf2(str, "\n");
	else {
		*cp='\0';
		AddToFilmbuf(str);
		sprintf(buf, ": <i %d>", app_data.quotetab);
		AddToFilmbuf(buf);
		cp++;
		while (*cp==' ') cp++;
		AddToFilmbuf2(cp, "<i0>\n");
		}
	}



void printQuotes(struct lineRec *triv) { 
	struct lineRec *line;
	char *cp;

	if (triv == NULL) 
		return;

	AddToFilmbuf("<f4><c4>Quotes<f1><c1><w1>\n");
 
	ClearBuffer(utilitybuf);
	for (line=triv; line != NULL; line = line->next) {

		if (( *(line->text) != ' ' ) && !EmptyBuffer(utilitybuf)) {
			printQuoteLine(utilitybuf->buf);
			ClearBuffer(utilitybuf);
			}

		cp=line->text;
		while (*cp==' ')
			cp++;
		AddToBuffer(utilitybuf, cp);
		}

	printQuoteLine(utilitybuf->buf);
	AddToFilmbuf("<w0>\n");
	} 



void printLiterature(struct lineRec *rec) {
	struct lineRec *current;
	char tag[5];

	if (rec == NULL)
		return;

	AddToFilmbuf("<f4><c4>Literature<f1><c1>\n");
	tag[0] = '\0';
	ClearBuffer(utilitybuf);
	for (current=rec; current!=NULL; current=current->next) {
		/* printf("'%s'\n", current->text); */
		if (strncmp(tag, current->text, 4) != 0 && *(current->text) != '\n' ) {
	        (void) strncpy(tag, current->text, 4);
			if (!EmptyBuffer(utilitybuf)) {
				trim_text2(utilitybuf->buf, utilitybuf->buf);
				AddToFilmbuf3("<w1>", utilitybuf->buf, "<w0>");
				ClearBuffer(utilitybuf);
				}
       		if (strncmp(current->text, "SCRP", 4) == 0)
				AddToFilmbuf("\n<f5>Script<f1>\n");
       		else if (strncmp(current->text, "NOVL", 4) == 0)
				AddToFilmbuf("\n<f5>Original Literary Source<f1>\n");
			else if (strncmp(current->text, "ADPT", 4) == 0)
				AddToFilmbuf("\n<f5>Adaptation of Literary Source<f1>\n");
			else if (strncmp(current->text, "BOOK", 4) == 0)
				AddToFilmbuf("\n<f5>Related Books<f1>\n");
			else if (strncmp(current->text, "PROT", 4) == 0)
				AddToFilmbuf("\n<f5>Production Process Protocol<f1>\n");
			else if (strncmp(current->text, "IVIW", 4) == 0)
				AddToFilmbuf("\n<f5>Interviews<f1>\n");
			else if (strncmp(current->text, "CRIT", 4) == 0)
				AddToFilmbuf("\n<f5>Printed Media Reviews<f1>\n");
			else if (strncmp(current->text, "ESSY", 4) == 0)
				AddToFilmbuf("\n<f5>Essays<f1>\n");
			else if (strncmp(current->text, "OTHR", 4 ) == 0)
				AddToFilmbuf("\n<f5>Other Information<f1>\n");
			else
				AddToFilmbuf("\n<f5>Unknown<f1>\n");
			}
		if ((*(current->text) == '\n') && !EmptyBuffer(utilitybuf)) {
			trim_text2(utilitybuf->buf, utilitybuf->buf);
			AddToFilmbuf3("<w1>", utilitybuf->buf, "<w0>\n\n");
			ClearBuffer(utilitybuf);
			}
		else if (strlen(current->text) >6)
			AddToBuffer(utilitybuf, current->text + 6);
		}

	if (!EmptyBuffer(utilitybuf)) {
		trim_text2(utilitybuf->buf, utilitybuf->buf);
		AddToFilmbuf3("<w1>", utilitybuf->buf, "<w0>\n");
		}

	AddToFilmbuf("\n\n");
	}



static HeadingInfo business_headings[] = {
	{"BT", "Budget"},
	{"GR", "Box Office Gross"},
	{"WG", "Weekend Box Office Gross"},
	{"OW", "Opening Weekend Box Office"},
	{"RT", "Rentals"},
	{"AD", "Admissions"},
	{"PD", "Production Dates"},
	{"SD", "Shooting Dates"},
	{"ST", "Studio"},
	{"CP", "Copyright Holder"},
	{NULL, "Unknown"}
	};

void printBusiness(struct lineRec *rec) {
	struct lineRec *current;
	int i;
	char tag[3];

	if (rec == NULL)
		return;

	AddToFilmbuf("<f4><c4>Business Information<f1><c1>\n");

	for (current=rec; current!=NULL; current=current->next) {
		if (strncmp(tag, current->text, 2) != 0 && *(current->text) != '\n') {
			(void) strncpy(tag, current->text, 2);

			/* print the heading */
			i=0;
			while (business_headings[i].tag != NULL) {
				if (strncmp(business_headings[i].tag, current->text, 2)==0) 
					break;
				i++;
				}

			if (business_headings[i].tag == NULL) {
				tag[2]='\0';
				AddToFilmbuf3("\n<f5>", tag, "<f1>\n");
				}
			else
				AddToFilmbuf3("\n<f5>", business_headings[i].text, "<f1>\n");
			}
		if (strlen(current->text) > 4)
			AddToFilmbuf2("<b>", current->text + 4);
		}

	AddToFilmbuf("\n\n");
	}


static HeadingInfo laser_headings[] = {
	{"OT", "Featured Title(s)"},
	{"PC", "Production Country"},
	{"YR", "Year"},
	{"CF", "Certification"},
	{"CA", "Category"},
	{"GR", "Group"},
	{"LA", "Language"},
	{"SU", "Subtitles"},
	{"LE", "Length"},
	{"RD", "Release Date"},
	{"ST", "Status"},
	{"PR", "Official Retail Price"},
	{"VS", "Video Standard"},
	{"CO", "Color Information"},
	{"SE", "Sound Encoding"},
	{"DS", "Digital Sound"},
	{"AL", "Analog Left"},
	{"AR", "Analog Right"},
	{"MF", "Master Format"},
	{"PP", "Pressing Plant"},
	{"SZ", "Disc Size"},
	{"SI", "Number of Sides"},
	{"DF", "Disc Format"},
	{"PF", "Picture Format"},
	{"AS", "Aspect Ratio"},
	{"CC", "Close Captions/Teletext/LD+G"},
	{"CS", "Number of Chapter Stops"},
	{"QP", "Quality Program"},
	{"TX", "THX"},
	{"IN", "Additional Information"},
	{NULL, "Unknown"}
	};

void printAdditionalInfo(struct lineRec **currentPtr) {
	struct lineRec *current=*currentPtr;
	struct lineRec *last=*currentPtr;
	char *cp;

	AddToFilmbuf("\n<w1>");
	ClearBuffer(utilitybuf);

	while ((current!=NULL) && strncmp(current->text, "IN", 2)==0) {
		if ((current->text)[4] == '\n') {
			trim_text2(utilitybuf->buf, utilitybuf->buf);
			cp=insert_qv_links(utilitybuf->buf);
			AddToFilmbuf3("<b>", cp, "\n\n");
			ClearBuffer(utilitybuf);
			}
		else 
			AddToBuffer(utilitybuf, current->text + 4);	
		last = current;
		current = current->next;
		}

	if (!EmptyBuffer(utilitybuf)) {
		trim_text2(utilitybuf->buf, utilitybuf->buf);
		cp=insert_qv_links(utilitybuf->buf);
		AddToFilmbuf3("<b>", cp, "\n");
		}

	AddToFilmbuf("\n<w0>");
	*currentPtr=last;
	}



void printLaserDisc(struct laserRec *rec) {
	struct laserRec *lrec ;
	struct lineRec *current ;
	char tag[5];
	char dindent[32];
	char indent[16];
	int i;

	if (rec == NULL)
		return;

	sprintf(dindent, "<d %d><w1><h %d>", app_data.casttab, app_data.casttab);
	sprintf(indent, "<i %d>", app_data.casttab);

	AddToFilmbuf("<f4><c4>Laserdisc Information<f1><c1>\n");
	for (lrec=rec; lrec!=NULL; lrec=lrec->next) {
		if (lrec->LN != NULL)
			AddToFilmbuf3("IMDb LaserDisc #  ", dindent, lrec->LN);
		if (lrec->LB != NULL)
			AddToFilmbuf3("Label  ", dindent, lrec->LB);
		if (lrec->CN != NULL)
			AddToFilmbuf3("Catalogue  ", dindent, lrec->CN);
		if (lrec->LT != NULL)
			AddToFilmbuf3("LaserDisc Title  ", dindent, lrec->LT);

		tag[0]='\0';
		for (current=lrec->misc; current!=NULL; current=current->next) {

			if (strncmp(tag, current->text, 2) != 0 && 	*(current->text) != '\n') {
				(void) strncpy(tag, current->text, 2);

				/* print the heading */
				i=0;
				while (laser_headings[i].tag != NULL) {
					if (strncmp(laser_headings[i].tag, current->text, 2)==0)
						break;
					i++;
					}
				AddToFilmbuf(laser_headings[i].text);
				if (strncmp(current->text, "IN", 2)!=0)
					AddToFilmbuf2("  ", dindent);
				}

			if (strncmp(current->text, "IN", 2)==0)
				printAdditionalInfo(&current);
			else if (strlen(current->text) < 4)
				AddToFilmbuf("\n");
			else 
				AddToFilmbuf3(indent, current->text + 4, "<i 0>");
			}
		AddToFilmbuf("\n\n");
		}
	}



void printMovie(struct titleSearchRec *trec) {
	struct akaRec *arec;
	int i;
	char buf[256];
	char hangindent[16];

	if (utilitybuf==NULL) 
		utilitybuf=CreateBuffer("utility", 4096, 2048, 65536);
	sprintf(hangindent, "<h %d>", app_data.hangingIndent);

	/* print the title */
	AddToFilmbuf3("\n<m1><f3><c3><w1>", trec->title, "\n\n<f1><c1><m0><w0>");

	/* print taglines */
    if (trec->trivlists[NO_OF_TRIV_LISTS-1] != NULL)
		printTagLines (trec->trivlists[NO_OF_TRIV_LISTS-1]);

	/* print a.k.a's */
    if (trec->aka != NULL) {
		AddToFilmbuf("<f4><c4>Also Known As\n<f1><c1><w1>");
		for (arec = trec->aka; arec != NULL; arec = arec->next) {
			AddToFilmbuf2(hangindent, "<w1>");
			AddToFilmbuf(arec->akaTitle);
			if (arec->akaAttr != NULL)
				AddToFilmbuf2("  ", arec->akaAttr);
			AddToFilmbuf("<w0>\n");
			}
		AddToFilmbuf("\n");
		}


	/* print awards info */
    if (trec->attr != NULL) 
		AddToFilmbuf3("<f4><c4>Awards Information\n<f1><c1>", trec->attr, "\n\n");

	/* print ratings */
    if (trec->mrr != NULL && trec->mrr->votes > 0) {
		sprintf(buf, "<f4><c4>Ratings\n<f1><c1>%s%8d   %2.1f\n\n", 
				trec->mrr->distribution, 
                trec->mrr->votes, 
				trec->mrr->rating);
		AddToFilmbuf(buf);
		}

	/* print information about the title */
    for (i=0; i<NO_OF_TITLE_INFO_LISTS; i++)
		if (trec->titleInfo[i] != NULL)
			printTitleInfo(trec->titleInfo[i], i);

	/* print plot summary */
	if (trec->searchparams.plotopt)
		printPlot(trec->plot);


	/* print cast list */
	printFilmographyLists(trec);
	printCastList(trec);

	/* print movie links */
	if (trec->searchparams.linkopt)
		printMovieLinks(trec->noOfLinks, trec->links);

	/* print trivia */
	for (i=0; i<NO_OF_TRIV_LISTS - 1; i++)
		if (trec->trivlists[i] != NULL) {
			if (i==2)
				printGoofs(trec->trivlists[i]);
			else if (i==3)
				printQuotes(trec->trivlists[i]);
			else
				printTrivia(trec->trivlists[i], i);
			}

	/* print literature references */
   if (trec->searchparams.litopt)
		printLiterature(trec->literature);


	/* print business info */
   if (trec->searchparams.businessopt)
		printBusiness(trec->business);

	/* print laser disc info */
	if (trec->searchparams.ldopt)
		printLaserDisc(trec->laserdisc); 

	AddToFilmbuf3("\n<m1><f2>", COPYRIGHT, "<f1><m0>");
	}
