lotos123/
lotos123/datafiles/conffiles/
lotos123/datafiles/counters/
lotos123/datafiles/fonts/
lotos123/datafiles/helpfiles/
lotos123/datafiles/killmsgs/
lotos123/datafiles/mapfiles/
lotos123/datafiles/motds/motd1/
lotos123/datafiles/motds/motd2/
lotos123/datafiles/pictfiles/
lotos123/datafiles/plfiles/
lotos123/datafiles/plfiles/helpfiles/
lotos123/datafiles/screens/
lotos123/datafiles/textfiles/
lotos123/datafiles/trfiles/
lotos123/datafiles/votefiles/
lotos123/datafiles/votefiles/1/
lotos123/datafiles/votefiles/2/
lotos123/src/plugins/
lotos123/userfiles/
lotos123/userfiles/bin/
/* vi: set ts=4 sw=4 ai: */
/*
 * fonts.c
 *
 *   Lotos v1.2.3  : (c) 1999-2003 Pavol Hluchy (Lopo)
 *   last update   : 30.1.2003
 *   email         : lotos@losys.sk
 *   homepage      : lotos.losys.sk
 */

#ifndef __FONTS_C__
#define __FONTS_C__ 1

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <ctype.h>

#include "define.h"
#include "prototypes.h"
#include "obj_ur.h"
#include "obj_rm.h"
#include "obj_sys.h"
#include "fonts.h"


#ifdef __STDC__
char *myalloc(size_t size)
#else
char *myalloc(int size)
#endif
{
	char *ptr;
#ifndef __STDC__
	extern void *malloc();
#endif

	set_crash();
	if ((ptr = (char*)malloc(size))==NULL) {
		write_room(NULL,"~FR~OLSYSTEM: Malloc failed in figlet().\n");
		return NULL;
		}
	return ptr;
}


/****************************************************************************
  readfontchar

  Reads a font character from the font file, and places it in a
  newly-allocated entry in the list.
****************************************************************************/
void readfontchar(FILE *file, long theord, char *line, int maxlen)
{
	int row,k;
	char endchar;
	fcharnode *fclsave=fcharlist;

	set_crash();
	fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
	fcharlist->ord = theord;
	fcharlist->thechar = (char**)myalloc(sizeof(char*)*charheight);
	fcharlist->next = fclsave;

	for (row=0;row<charheight;row++) {
		if (fgets(line,maxlen+1,file)==NULL) line[0] = '\0';
		k = MYSTRLEN(line)-1;
		while (k>=0 && isspace(line[k]))
			k--;
		if (k>=0) {
			endchar = line[k];
			while (k>=0 ? line[k]==endchar : 0)
				k--;
			}
		line[k+1] = '\0';
		fcharlist->thechar[row] = (char*)myalloc(sizeof(char)*(k+2));
		strcpy(fcharlist->thechar[row],line);
		}
}


/****************************************************************************
	skiptoeol

	Skips to the end of a line, given a stream.
****************************************************************************/
void skiptoeol(FILE *fp)
{
	int dummy;

	set_crash();
	while (dummy=getc(fp), dummy!='\n'&&dummy!=EOF) ;
}


/****************************************************************************
  readfont

  Allocates memory, initializes variables, and reads in the font.
  Called near beginning of main().
****************************************************************************/
int readfont(char *fontname)
{
	int i,row,numsread;
	long theord;
	int maxlen,cmtlines,ffright2left;
	char *fileline,magicnum[5];
	FILE *fontfile;
	char fontpath[FNAME_LEN];

	set_crash();
	sprintf(fontpath, "%s/%s.flf", FIGLET_FONTS, fontname);

	fontfile=fopen(fontpath,"r");

	if (!fontfile) return -1;

	fscanf(fontfile,"%4s",magicnum);
	fileline = (char*)myalloc(sizeof(char)*(MAXFIRSTLINELEN+1));
	if (fgets(fileline,MAXFIRSTLINELEN+1,fontfile)==NULL) fileline[0] = '\0';

	if (MYSTRLEN(fileline)>0 ? fileline[MYSTRLEN(fileline)-1]!='\n' : 0)
		skiptoeol(stdin);

	numsread = sscanf(fileline,"%*c%c %d %*d %d %d %d%*[ \t]%d",
		&hardblank, &charheight, &maxlen,
		&defaultmode, &cmtlines, &ffright2left
		);
	free(fileline);

	for (i=1;i<=cmtlines;i++)
		skiptoeol(fontfile);

	if (numsread<6) ffright2left = 0;
	if (charheight<1) charheight = 1;
	if (maxlen<1) maxlen = 1;
	maxlen += 100; /* Give ourselves some extra room */

	if (right2left<0) right2left = ffright2left;
	if (justification<0) justification = 2*right2left;

	fileline = (char*)myalloc(sizeof(char)*(maxlen+1));
	/* Allocate "missing" character */
	fcharlist = (fcharnode*)myalloc(sizeof(fcharnode));
	fcharlist->ord = 0;
	fcharlist->thechar = (char**)myalloc(sizeof(char*)*charheight);
	fcharlist->next = NULL;
	for (row=0;row<charheight;row++) {
		fcharlist->thechar[row] = (char*)myalloc(sizeof(char));
		fcharlist->thechar[row][0] = '\0';
		}
	for (theord=' ';theord<='~';theord++)
		readfontchar(fontfile,theord,fileline,maxlen);
	for (theord= -255;theord<= -249;theord++)
		readfontchar(fontfile,theord,fileline,maxlen);
	while (fgets(fileline,maxlen+1,fontfile)==NULL?0:sscanf(fileline,"%li",&theord)==1)
		readfontchar(fontfile,theord,fileline,maxlen);
	fclose(fontfile);
	free(fileline);
	return 0;
}


/*** Write text figlets & intros ***/
void write_text_figlet(UR_OBJECT user, UR_OBJECT u, RM_OBJECT rm, char *fig_text, char *name, char *font)
{
	char fig1[ARR_SIZE];
	char fig2[ARR_SIZE];

	set_crash();
	if (strcmp(font,"standard"))
		sprintf(fig1,"~FRBanner od ~OL%s~RS~FR (%s font): ~RS%s\n", name, font, fig_text);
	else sprintf(fig1,"~FRBanner od ~OL%s~RS~FR: ~RS%s\n", name, fig_text);
	sprintf(fig2,"~FRBanner od ~OL%s~RS~FR:\n",name);

	if (rm) {
		if (!user->vis) write_monitor(user, rm, 0);
		write_room(rm, fig2);
		record(rm, fig1);
		return;
		}
	if (u) {
		if (u==user) return;
		if (u->afk) record_afk(u, fig1);
		else if (u->editing) record_edit(u, fig1);
		record_tell(u, fig1);
		sprintf(u->ltell, user->name);
		if (strcmp(font,"standard"))
			sprintf(text, "~FRBanner pre ~OL%s~RS~FR (%s font): ~RS%s\n",
				u->name, font, fig_text
				);
		else 
			sprintf(text, "~FRBanner pre ~OL%s~RS~FR: ~RS%s\n",
				u->name, fig_text
				);
		write_user(user, text);
		record_tell(user, text);
		if (u->afk || u->editing) return;
		write_user(u, fig2);
		return;
		}

	for (rm=room_first; rm!=NULL; rm=rm->next)
		record(rm, fig1);
	if (!user->vis) write_monitor(user, NULL, 0);
	write_room_except(NULL, fig2, user);
	write_user(user, fig2);
}


/****************************************************************************
	clearline

  Clears both the input (inchrline) and output (outline) storage.
****************************************************************************/
void fclearline(void)
{
	int i;

	set_crash();
	for (i=0;i<charheight;i++)
		outline[i][0] = '\0';
	outlinelen = 0;
	inchrlinelen = 0;
}


/*** Write figlet lines to users that want them ***/
void write_broadcast_figlet(UR_OBJECT user, UR_OBJECT u, RM_OBJECT rm, char *fig_text)
{
	set_crash();
	if (u) {
		write_user(u, fig_text);
		return;
		}
	if (rm) {
		write_room(rm, fig_text);
		return;
		}
	write_room_except(NULL, fig_text, user);
	write_user(user, fig_text);
}


/****************************************************************************
  putstring

  Prints out the given null-terminated string, substituting blanks
  for hardblanks.  If outputwidth is 1, prints the entire string;
  otherwise prints at most outputwidth-1 characters.  Prints a newline
  at the end of the string.  The string is left-justified, centered or
  right-justified (taking outputwidth as the screen width) if
  justification is 0, 1 or 2, respectively.
****************************************************************************/
void putstring(UR_OBJECT user, UR_OBJECT u, RM_OBJECT rm, char *string)
{
	int i,j=0,len;
	char t;

	set_crash();
	len = MYSTRLEN(string);
	if (outputwidth>1) {
		if (len>outputwidth-1) len = outputwidth-1;
		if (justification>0) {
			for (i=1;(3-justification)*i+len+justification-2<outputwidth;i++) {
				text[j]=' ';
				j++;
				}
			}
		}
	for (i=0;i<len;i++) {
		t=string[i]==hardblank?' ':string[i];
		text[j]=t;
		j++;
		}
	text[j]='\n';
	text[j+1]='\0';
	write_broadcast_figlet(user, u, rm, text);
}


/****************************************************************************
  printline

  Prints outline using putstring, then clears the current line.
****************************************************************************/
void printline(UR_OBJECT user, UR_OBJECT u, RM_OBJECT rm)
{
	int i;

	set_crash();
	for (i=0;i<charheight;i++)
		putstring(user, u, rm, outline[i]);
	fclearline();
}


/****************************************************************************
  getletter

  Sets currchar to point to the font entry for the given character.
  Sets currcharwidth to the width of this character.
****************************************************************************/
void getletter(long c)
{
	fcharnode *charptr;

	set_crash();
	for (charptr=fcharlist; charptr==NULL?0:charptr->ord!=c; charptr=charptr->next) ;
	if (charptr!=NULL) currchar = charptr->thechar;
	else {
		for (charptr=fcharlist;charptr==NULL?0:charptr->ord!=0;charptr=charptr->next) ;
		currchar = charptr->thechar;
		}
	currcharwidth = MYSTRLEN(currchar[0]);
}


/****************************************************************************
  addchar

	Attempts to add the given character onto the end of the current line.
  Returns 1 if this can be done, 0 otherwise.
****************************************************************************/
int addchar(long c)
{
  int smushamount=0,row;
  char *templine;

	set_crash();
  getletter(c);
  if (outlinelen+currcharwidth>outlinelenlimit
      ||inchrlinelen+1>inchrlinelenlimit) {
    return 0;
  }
  
  templine = (char*)myalloc(sizeof(char)*(outlinelenlimit+1));
  for (row=0;row<charheight;row++) {
    if (right2left) {
      strcpy(templine,currchar[row]);
      strcat(templine,outline[row]+smushamount);
      strcpy(outline[row],templine);
    }
    else
      strcat(outline[row],currchar[row]+smushamount);
    
  }
  free(templine);
  outlinelen = MYSTRLEN(outline[0]);
  inchrline[inchrlinelen++] = c;
  return 1;
}


/****************************************************************************
  splitline

  Splits inchrline at the last word break (bunch of consecutive blanks).
  Makes a new line out of the first part and prints it using
	printline.  Makes a new line out of the second part and returns.
****************************************************************************/
void splitline(UR_OBJECT user, UR_OBJECT u, RM_OBJECT rm)
{
	int i,gotspace=0,lastspace=0,len1,len2;
	long *part1,*part2;

	set_crash();
	part1 = (long*)myalloc(sizeof(long)*(inchrlinelen+1));
	part2 = (long*)myalloc(sizeof(long)*(inchrlinelen+1));
	for (i=inchrlinelen-1;i>=0;i--) {
		if (!gotspace && inchrline[i]==' ') {
			gotspace = 1;
			lastspace = i;
			}
		if (gotspace && inchrline[i]!=' ') break;
		}
	len1 = i+1;
	len2 = inchrlinelen-lastspace-1;
	for (i=0;i<len1;i++)
		part1[i] = inchrline[i];
	for (i=0;i<len2;i++)
		part2[i] = inchrline[lastspace+1+i];
	fclearline();
	for (i=0;i<len1;i++)
		addchar(part1[i]);
	printline(user, u, rm);
	for (i=0;i<len2;i++)
		addchar(part2[i]);
	free(part1);
	free(part2);
}



void figlet(UR_OBJECT user, char *inpstr, int typ)
{
	UR_OBJECT u=NULL;
	RM_OBJECT rm=NULL;
	long c;
	int i=0, row, wordbreakmode, char_not_added;
	char *p=inpstr, *name;
	fcharnode *fclsave;
	char fontname[256]="standard";

	set_crash();
	if (user->muzzled) {
		write_user(user, "Si muzzled, nemozes bannerovat\n");
		return;
		}
	if (word_count<2) {
		write_user(user,"Pozri si najprv help ...\n");
		return;
		}
	if (!strcmp(inpstr, "/l")) {
		show_file(user, FONTLIST);
		return;
		}
	if (typ==0) rm=user->room;
	if (typ==1) {
		if (word_count<3) {
			write_usage(user, "tbanner /<user> [-<font>] text");
			return;
			}
		/* Check to see if a username is specified */
		i=0;
		if (*p=='/') {
			/* Get size of font name */
			while (*(p+i)!=' ') {
				i++;
				if (i==100) break;
				}
			strncpy(text, p+1, i);
			*(text+i-1)='\0';
			name=text;
			p=p+i+1;
			}
		else {
			write_usage(user, "tbanner /<user> [-<font>] text");
			return;
			}
		if ((u=get_user_name(user, name))==NULL) {
			write_user(user, notloggedon);
			return;
			}
		if ((check_igusers(u,user))!=-1
		     && (user->level<GOD
			 || user->level<u->level)) {
			vwrite_user(user,"%s~RS is ignoring tells from you.\n",u->recap);
			return;
			}
		if (u->ignore.tells && (user->level<WIZ || u->level>user->level)) {
			vwrite_user(user,"%s~RS is ignoring tells at the moment.\n",u->recap);
			return;
			}
		if (u->ignore.all && (user->level<WIZ || u->level>user->level)) {
			if (u->malloc_start!=NULL) vwrite_user(user,"%s~RS is using the editor at the moment.\n",u->recap);
			else vwrite_user(user,"%s~RS is ignoring everyone at the moment.\n",u->recap);
			return;
			}
#ifdef NETLINKS
		if (u->room==NULL) {
			vwrite_user(user,"%s~RS is offsite and would not be able to reply to you.\n",u->recap);
			return;
			}
#endif
		if (u->afk) {
			if (u->afk_mesg[0]) vwrite_user(user,"%s~RS is ~FRAFK~RS, message is: %s\n",u->recap,u->afk_mesg);
			else vwrite_user(user,"%s~RS is ~FRAFK~RS at the moment.\n",u->recap);
			write_user(user,"Sending message to their afk review buffer.\n");
			}
		if (u->editing) {
			vwrite_user(user,"%s~RS is in ~FTEDIT~RS mode at the moment (using the line editor).\n",u->recap);
			write_user(user,"Sending message to their edit review buffer.\n");
			}
		}

	/* Check to see if a font is specified */
	i=0;
	if (*p=='-') {
		/* Get size of font name */
		while (*(p+i)!=' ') {
			i++;
			if (i==100) break;
			}
		strncpy(fontname, p+1, i);
		*(fontname+i-1)='\0';
		p=p+i+1;

		if ((word_count<3 && typ!=1)
		    || (word_count<4 && typ==1)
		    ) {
			write_user(user,"Co zabannerovat ?\n");
			return;
			}
		}

	if (amsys->ban_swearing && contains_swearing(p) && user->level<MIN_LEV_NOSWR) {
		switch(amsys->ban_swearing) {
			case SBMIN:
				p=censor_swear_words(p);
				break;
			case SBMAX:
				write_user(user,noswearing);
				return;
			default : break; /* do nothing as ban_swearing is off */
			}
		}

	justification = 0;
	right2left = -1;

	outputwidth = 80;

	outlinelenlimit = outputwidth-1;

	if ((i=readfont(fontname))==-1) {
		sprintf(text,"Nemozem nahrat font %s\n",fontname);
		write_user(user,text);
		return;
		}

	name=invisname;
	if ((typ==1 && u->level>=user->level) || user->vis) name=user->name;

	write_text_figlet(user, u, rm, p, name, fontname);

	/* Line alloc... */
	outline = (char**)myalloc(sizeof(char*)*charheight);
	for (row=0;row<charheight;row++) {
		outline[row] = (char*)myalloc(sizeof(char)*(outlinelenlimit+1));
		}
	inchrlinelenlimit = outputwidth*4+100;
	inchrline = (long*)myalloc(sizeof(long)*(inchrlinelenlimit+1));
	fclearline();
	wordbreakmode = 0;

	while (*p) { 
		c=*p;
		p=p+1;
  
		if (isascii(c) && isspace(c)) {
			c = (c=='\t' || c==' ') ? ' ' : '\n';
			}

		if ( (c>'\0' && c<' ' && c!='\n' ) || c==127) continue;

		/*
		Note: The following code is complex and thoroughly tested.
		Be careful when modifying!
		*/

		do {
			char_not_added = 0;

			if (wordbreakmode== -1) {
				if (c==' ') break;
				else if (c=='\n') {
					wordbreakmode = 0;
					break;
					}
				wordbreakmode = 0;
				}

			if (c=='\n') {
				printline(user, u, rm);
				wordbreakmode = 0;
				}
			else if (addchar(c)) {
				if (c!=' ') wordbreakmode = (wordbreakmode>=2)?3:1;
				else wordbreakmode = (wordbreakmode>0)?2:0;
				}
			else if (outlinelen==0) {
				for (i=0;i<charheight;i++) {
					if (right2left && outputwidth>1)
						putstring(user, u, rm, currchar[i]+MYSTRLEN(currchar[i])-outlinelenlimit);
					else
						putstring(user, u, rm, currchar[i]);
					}
				wordbreakmode = -1;
				}
    
			else if (c==' ') {
				if (wordbreakmode==2) splitline(user, u, rm);
				else printline(user, u, rm);
				wordbreakmode = -1;
				}
			else {
				if (wordbreakmode>=2) splitline(user, u, rm);
				else printline(user, u, rm);
				wordbreakmode = (wordbreakmode==3)?1:0;
				char_not_added = 1;
				}
			} while (char_not_added);
		}
	if (outlinelen!=0) printline(user, u, rm);

	/* Free up memory... */
	free(inchrline);
	for (row=0;row<charheight;row++)
		free(outline[row]);
	free(outline);
	/* Free up font memory... */
	do {
		/* Save pointer to next node */
		fclsave=fcharlist->next;
		/* Free memory used by this node */
		for (row=0;row<charheight;row++)
			free(fcharlist->thechar[row]);
		free(fcharlist->thechar);
		free(fcharlist);
		fcharlist=fclsave;
		} while (fclsave!=NULL);
	return;
}

#endif /* __FONTS_C__ */