/*
	Schrodinger's Box Haven  code version -0.1 alpha
        Copyright (C) 1994, Gordon Chan

	You can do whatever ya want with this code as long as you leave this
        copyright & disclaimer intact.  You can hack it up all you want, etc...
        No guarantees.

	Send comments, flames, bug reports, etc ... to
		au233@freenet.carleton.ca  <---- (preferred address for now)
		gjc@achilles.net
		gchan@ccs.carleton.ca
*/


/* Here's the copyrights & disclaimers from the Opium Den and unixCB codes */

/* Opium Den */
/*
  val's haven code v -0.85

        Copyright (C) 1994 Joel Ward

        Warranty:
                Don't blame me for anything.

        You can do whatever the fuck you want with this code as long as you
don't remove this copyright/disclaimer notice.
*/

/* unixCB */
/*
  
  cbd.c
  
  "cbd.c" is the main code for the CB simulator.
  
  Copyright (c) 1992, Gary Grossman.  All rights reserved.
  Send comments and questions to: garyg@soda.berkeley.edu
  
  */

#include<stdio.h>

#include "user_output.h"
#include "linked_lists.h"
#include "main.h"
#include "toggle_comm.h"
#include "misc_commands.h"
#include "security.h"


void talk (user, mesg)
	struct user *user;
	char *mesg;
{
	struct user *u;
	char tempbuffer[600];
	
	sprintf (tempbuffer, "\033[1;%dm(%d, %s) %s\033[0;37m\r\n", 
user->colour, user->desc, user->name, mesg); 

	/* handle_talk_output (user, tempbuffer); */
	handle_talk_output (user, mesg);
}



void greeting (user)
	struct user *user;
{
	struct user *u;
	char tempbuffer[200];
	
	write_file_to (user, INTRO, "\r\nNo intro screen.  YAWN.  ;) :)\r\n\n");
#ifdef LOGIN_SCREEN
/*
	sprintf (tempbuffer, "\033[1;33;44m>> %s on line %d has arrived from %s.\033[0;37;40m\r\n", 
	  user->name, user->desc, user->site);
*/
	sprintf (tempbuffer, ">> %s on line %d has arrived from %s.\r\n", 
	  user->name, user->desc, user->site);

#else
/*
	sprintf (tempbuffer, "\033[1;33;44mm>> New arrival on line %d from %s.\033[0;37;40m\r\n", 
	  user->name, user->desc, user->site);
*/
	sprintf (tempbuffer, ">> New arrival on line %d from %s.\r\n", 
	 user->desc, user->site);
#endif
	handle_message_output (tempbuffer);
}


/* various output handlers */

void handle_talk_output(user, buffer)
  struct user *user;
  char *buffer;
{
  struct user *u;
	
  for (u=firstuser; u; u=u->next)
    if (user->channel == u->channel ||
     (is_user(u, Fmonitor) && !strcmp(user->channel->name, "blah")))
      if (!user || ((!u->gags || !testbit(u->gags, user->desc-1)) &&
       (!user->reverse_gags || !testbit(user->reverse_gags, u->desc-1))))
        process_output(u, process_message(u, user, buffer, TALK));
}


void handle_channel_output(user, buffer)
  struct user *user;
  char *buffer;
{
  struct user *u;
	
  for (u=firstuser; u; u=u->next)
    if (user->channel == u->channel ||
     (is_user(u, Fmonitor) && !strcmp(user->channel->name, "blah")))
      if (!user || ((!u->gags || !testbit(u->gags, user->desc-1)) &&
       (!user->reverse_gags || !testbit(user->reverse_gags, u->desc-1))))
        process_output(u, buffer);

}


void handle_yells_output(user, buffer)
  struct user *user;
  char *buffer;
{
  struct user *u;
	
  for (u=firstuser; u; u=u->next)
    if (is_user_not(u, Fhush))
      if (!user || ((!u->gags || !testbit(u->gags, user->desc-1)) &&
       (!user->reverse_gags || !testbit(user->reverse_gags, u->desc-1))))
        process_output(u, process_message(u, user, buffer, YELL));
}


void handle_message_output (buffer)
	char *buffer;
{
	struct user *u;
	
	for (u = firstuser; u; u = u->next)
		if (is_user_not (u, Fmess_supp) )
			process_output (u, buffer);

}


void process_output(user, buffer)
  struct user *user;
  char *buffer;
{
  if (is_user(user, Flogged_in)) {
    if (is_user_not(user, Flinewrap))
      choose_output(user, buffer);
    else
      write_linewrap(user, buffer);
  }
}			

	
void choose_output(user, buffer)
  struct user *user;
  char *buffer;
{
  if (is_user_not(user, Ftyping)) 
    write_user(user->desc, buffer);
  else
    write_to_output_buffer(user, buffer);
}


void write_linewrap(u, text)
  struct user *u;
  char *text;
{
  int n, cl, w, width = u->line_width;
  char *s=text, *s2, tempbuffer[150];

  --width;
  *tempbuffer = '\0';

  /* if there are ansi colour characters present, copy them into tempbuffer */
  cl = 0;
  if (is_user(u, Fcolour) || is_user(u, Fhilite)) {
    while (*s!='m')
      s++;
    s++;
    cl = s-text;
    strncat (tempbuffer, text, cl);
    tempbuffer[cl] = '\0';
  }
  if ((n = strlen(s)) > width) { 
    while (n > width) {
      s2 = s+width;
      while (s2>s && *s2!=' ')
        s2--;
      if (s==s2) 
        w = width;
      else
        w = s2-s;
      strncat(tempbuffer, s, w); 
      tempbuffer[w+cl] = '\0';
      strcat(tempbuffer, "\r\n ");
      choose_output(u, tempbuffer);
      cl = 0;
      *tempbuffer = '\0';
      s+=w;
      if (*s==' ')
        s++;
      n = strlen(s);
    }
    choose_output(u, s);
  } else
    choose_output(u, text); 
}


void write_to_output_buffer (u, buffer)
	struct user *u;
	char *buffer;
{
	char tempbuffer[OUTPUTMAX], *ptr;
	int overflow, length;

	tempbuffer[0] = '\0';
	length = u->output->length+ strlen(buffer);
	overflow = length - OUTPUTMAX;

	sprintf (err, "line %d: u->output->length= %d, length = %d, overflow = %d\r\n", 
 u->desc, u->output->length, length, overflow);
	write_err (err);

	if (overflow > 0) {
		ptr = u->output->begin + overflow;

		while (*ptr && (*ptr != '\n') )
			ptr++;
		if (*ptr)
			ptr++;

		strcpy (tempbuffer, ptr);
		clear_queue (u->output);
		strcat (tempbuffer, buffer);
		strcpy (u->output->queue, tempbuffer);
		u->output->length = strlen (tempbuffer);
	} else { 
		strcat (u->output->queue, buffer);
		u->output->length = length;
	} 
}


/* routines that are used to put together messages

   message type goes as follows
	0 = normal talk
	1 = yells
	2 = private message
	3 = global system message
	4 = blank message
*/

char buffer[1024];

char *process_message(to_user, from_user, message, type)
  struct user *to_user, *from_user;
  char *message;
  int type;
{
  char *fmt, *b = buffer;
  *b = '\0';

  if (*message == ':' || *message == ';') {
    message++;
    fmt = to_user->action_format; 
  } else
    fmt = to_user->message_format;

  if (is_user(to_user, Fcolour) || is_user(to_user, Fhilite))
    b = (char *)handle_colour(from_user->colour, type);
    
  while (*fmt) {
    switch (*fmt) {
    case '%':
      fmt++;
      b = (char *)handle_macro(to_user, from_user, message, b, fmt, type);
      fmt++;
      break;
    case '_':
      fmt++;
      fmt = (char *)handle_yell(fmt, b, type);
      fmt++;
      b = buffer + strlen(buffer);
      break;
    case '\\':
      fmt++;
      fmt = (char *)handle_private_message(fmt, b, type);
      fmt++;
      b = buffer + strlen(buffer);
      break;
    default:
      *b = *fmt;
      b++;
      *b = '\0';
      fmt++;
      break;
    }
  }
  if (is_user(to_user, Fcolour))
    strcat(buffer, OFFCOLOUR);
  else if (is_user(to_user, Fhilite))
    strcat(buffer, HILITE_OFF);
  strcat(buffer, "\r\n");
  return buffer;
}


char *handle_macro(to_user, from_user, text, spot, field, type)
  struct user *to_user, *from_user;
  char *text, *spot, *field;
  int type;
{  
  static char bra[] = "(([{<";
  static char ket[] = "))]}>";

  switch(*field) {
  case '<':
    if (to_user->sec_level >= COSYSOP)
      *(spot++) = bra[from_user->sec_level];
    else
      *(spot++) = '(';
    *spot = '\0';
    return spot;
    break;
  case '>':
    if (to_user->sec_level >= COSYSOP)	
      *(spot++) = ket[from_user->sec_level];
    else
      *(spot++) = ')';
    *spot = '\0';
    return spot;
    break;
  case 'l':
    strcat(buffer, int2str(from_user->desc));
    return buffer + strlen(buffer);
    break;
  case 'n':
    strcat(buffer, from_user->name);
    return buffer + strlen(buffer);
    break;
  case 'd':
    strcat(buffer, from_user->description);
    return buffer + strlen(buffer);
    break;
  case 'm':
    strcat(buffer, text);
    return buffer + strlen(buffer);
  }
}


char *handle_colour(colour, type)
  int colour, type;
{
  char temp[15];

  switch (type) {
  case TALK:
    sprintf(temp, "\033[1;%dm", colour);
    strcpy(buffer, temp);
    return buffer + strlen(buffer);
    break;
  case YELL:
    sprintf(temp, "\033[0;%dm", colour);
    strcpy(buffer, temp);
    return buffer + strlen(buffer);
    break;
  case PRIVATE:
    strcpy(buffer, HILITE_ON);
    return buffer + strlen(buffer);    
    break;
  default:
    return buffer;
    break;
  }
}


char *handle_yell(string, spot, type)
  char *string, *spot;
  int type;
{
  char *ptr = string;
  int length;

  while (*ptr && (*ptr != '_'))
    ptr++;
  if (!*ptr) {
    strcat(buffer, "\r\n");
    return ptr;
  }
  length = ptr - string; 
  if (length && type==YELL) {
    strcat(buffer, string, length);
    *(spot+length) = '\0';
  } 
  return ptr;
}  


char *handle_private_message(string, spot, type)
  char *string, *spot;
  int type;
{
  char *ptr = string;
  int length;

  while (*ptr && (*ptr != '\\'))
    ptr++;
  if (!*ptr) {
    strcat(buffer, "\r\n");
    return ptr;
  }
  length = ptr - string; 
  if (length && type==PRIVATE) {
    strcat(buffer, string, length);
    *(spot+length) = '\0';
  } 
  return ptr;
}  

