dbna/clans/
dbna/councils/
dbna/deity/
dbna/gods/
dbna/houses/
dbna/space/
/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |   \\._.//   *
 * -----------------------------------------------------------|   (0...0)   *
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998  by Derek Snider      |    ).:.(    *
 * -----------------------------------------------------------|    {o o}    *
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |   / ' ' \   *
 * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek,      |~'~.VxvxV.~'~*
 * Tricops and Fireblade                                      |             *
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.     *
 * ------------------------------------------------------------------------ *
 * Comments: 'notes' attached to players to keep track of outstanding       * 
 *           and problem players.  -haus 6/25/1995                          * 
 ****************************************************************************/

/*  INSTALLATION: 1) Add following stuff to mud.h
 *
 *  NOTE_DATA *      comments;   (* inside char_data definition *)
 *  DECLARE_DO_FUN( do_comment      );
 *
 *                2) Add do_comment to interp.c, as usual
 *
 *                3) in save.c the following must be added
 *
 * save.c:107:     if ( ch->comments )                                              (* saves comments *)
 * save.c:108:       fwrite_comments( ch, fp );                                           (*  in file *)
 *
 *
 * save.c:411:    ch->comments                        = NULL;                   (* nulls ch->comments *)
 *
 *
 * save.c:457:         else if ( !str_cmp( word, "COMMENT") ) fread_comment(ch, fp ); (*snags #COMMENT*)
 *
 *                4) That looks like it to these eyes.  Lemme know if i forgot anything.
 *
 *
 * EXAMPLE:  See end of this file.
 *
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"


void note_attach( CHAR_DATA * ch );

void comment_remove( CHAR_DATA * ch, CHAR_DATA * victim, NOTE_DATA * pnote )
{
  if( !victim->comments )
  {
    bug( "comment remove: null board", 0 );
    return;
  }

  if( !pnote )
  {
    bug( "comment remove: null pnote", 0 );
    return;
  }

  /*
   * Remove comment from linked list.
   */
  if( !pnote->prev )
    victim->comments = pnote->next;
  else
    pnote->prev->next = pnote->next;

  STRFREE( pnote->text );
  STRFREE( pnote->subject );
  STRFREE( pnote->to_list );
  STRFREE( pnote->date );
  STRFREE( pnote->sender );
  DISPOSE( pnote );

  /*
   * Rewrite entire list.
   */
  save_char_obj( victim );

  return;
}

void do_comment( CHAR_DATA * ch, char *argument )
{
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  char arg1[MAX_INPUT_LENGTH];
  NOTE_DATA *pnote;
  CHAR_DATA *victim;
  int vnum;
  int anum;

  if( IS_NPC( ch ) )
  {
    send_to_char( "Mobs can't use the comment command.\n\r", ch );
    return;
  }

  if( !ch->desc )
  {
    bug( "do_comment: no descriptor", 0 );
    return;
  }

  /*
   * Put in to prevent crashing when someone issues a comment command
   * from within the editor. -Narn 
   */
  if( ch->desc->connected == CON_EDITING )
  {
    send_to_char( "You can't use the comment command from within the editor.\n\r", ch );
    return;
  }

  switch ( ch->substate )
  {
    default:
      break;
    case SUB_WRITING_NOTE:
      if( !ch->pnote )
      {
        bug( "do_comment: note got lost?", 0 );
        send_to_char( "Your note got lost!\n\r", ch );
        stop_editing( ch );
        return;
      }
      if( ch->dest_buf != ch->pnote )
        bug( "do_comment: sub_writing_note: ch->dest_buf != ch->pnote", 0 );
      STRFREE( ch->pnote->text );
      ch->pnote->text = copy_buffer( ch );
      stop_editing( ch );
      return;
  }

  set_char_color( AT_NOTE, ch );
  argument = one_argument( argument, arg );
  smash_tilde( argument );

  if( !str_cmp( arg, "about" ) )
  {

    victim = get_char_world( ch, argument );
    if( !victim )
    {
      send_to_char( "They're not logged on!\n\r", ch ); /* maybe fix this? */
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "No comments about mobs\n\r", ch );
      return;
    }


  }


  if( !str_cmp( arg, "list" ) )
  {
    victim = get_char_world( ch, argument );
    if( !victim )
    {
      send_to_char( "They're not logged on!\n\r", ch ); /* maybe fix this? */
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "No comments about mobs\n\r", ch );
      return;
    }

    if( get_trust( victim ) >= get_trust( ch ) )
    {
      send_to_char( "You're not of the right caliber to do this...\n\r", ch );
      return;
    }

    if( !victim->comments )
    {
      send_to_char( "There are no relevant comments.\n\r", ch );
      return;
    }

    vnum = 0;
    for( pnote = victim->comments; pnote; pnote = pnote->next )
    {
      vnum++;
      sprintf( buf, "%2d) %-10s [%s] %s\n\r", vnum, pnote->sender, pnote->date, pnote->subject );
/* Brittany added date to comment list and whois with above change */
      send_to_char( buf, ch );
    }

    /*
     * act( AT_ACTION, "$n glances over the notes.", ch, NULL, NULL, TO_ROOM ); 
     */
    return;
  }

  if( !str_cmp( arg, "read" ) )
  {
    bool fAll;

    argument = one_argument( argument, arg1 );
    victim = get_char_world( ch, arg1 );
    if( !victim )
    {
      send_to_char( "They're not logged on!\n\r", ch ); /* maybe fix this? */
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "No comments about mobs\n\r", ch );
      return;
    }

    if( get_trust( victim ) >= get_trust( ch ) )
    {
      send_to_char( "You're not of the right caliber to do this...\n\r", ch );
      return;
    }

    if( !victim->comments )
    {
      send_to_char( "There are no relevant comments.\n\r", ch );
      return;
    }



    if( !str_cmp( argument, "all" ) )
    {
      fAll = TRUE;
      anum = 0;
    }
    else if( is_number( argument ) )
    {
      fAll = FALSE;
      anum = atoi( argument );
    }
    else
    {
      send_to_char( "Note read which number?\n\r", ch );
      return;
    }

    vnum = 0;
    for( pnote = victim->comments; pnote; pnote = pnote->next )
    {
      vnum++;
      if( vnum == anum || fAll )
      {
        sprintf( buf, "[%3d] %s: %s\n\r%s\n\rTo: %s\n\r", vnum, pnote->sender, pnote->subject, pnote->date, pnote->to_list );
        send_to_char( buf, ch );
        send_to_char( pnote->text, ch );
        /*
         * act( AT_ACTION, "$n reads a note.", ch, NULL, NULL, TO_ROOM ); 
         */
        return;
      }
    }

    send_to_char( "No such comment.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "write" ) )
  {
    note_attach( ch );
    ch->substate = SUB_WRITING_NOTE;
    ch->dest_buf = ch->pnote;
    start_editing( ch, ch->pnote->text );
    return;
  }

  if( !str_cmp( arg, "subject" ) )
  {
    note_attach( ch );
    STRFREE( ch->pnote->subject );
    ch->pnote->subject = STRALLOC( argument );
    send_to_char( "Ok.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "to" ) )
  {
    note_attach( ch );
    STRFREE( ch->pnote->to_list );
    ch->pnote->to_list = STRALLOC( argument );
    send_to_char( "Ok.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "clear" ) )
  {
    if( ch->pnote )
    {
      STRFREE( ch->pnote->text );
      STRFREE( ch->pnote->subject );
      STRFREE( ch->pnote->to_list );
      STRFREE( ch->pnote->date );
      STRFREE( ch->pnote->sender );
      DISPOSE( ch->pnote );
    }
    ch->pnote = NULL;

    send_to_char( "Ok.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "show" ) )
  {
    if( !ch->pnote )
    {
      send_to_char( "You have no comment in progress.\n\r", ch );
      return;
    }

    sprintf( buf, "%s: %s\n\rTo: %s\n\r", ch->pnote->sender, ch->pnote->subject, ch->pnote->to_list );
    send_to_char( buf, ch );
    send_to_char( ch->pnote->text, ch );
    return;
  }

  if( !str_cmp( arg, "post" ) )
  {
    char *strtime;

    if( !ch->pnote )
    {
      send_to_char( "You have no comment in progress.\n\r", ch );
      return;
    }

    argument = one_argument( argument, arg1 );
    victim = get_char_world( ch, arg1 );
    if( !victim )
    {
      send_to_char( "They're not logged on!\n\r", ch ); /* maybe fix this? */
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "No comments about mobs\n\r", ch );
      return;
    }

    if( get_trust( victim ) > get_trust( ch ) )
    {
      send_to_char( "You're not of the right caliber to do this...\n\r", ch );
      return;
    }

    /*
     * act( AT_ACTION, "$n posts a note.", ch, NULL, NULL, TO_ROOM ); 
     */

    strtime = ctime( &current_time );
    strtime[strlen( strtime ) - 1] = '\0';
    ch->pnote->date = STRALLOC( strtime );

    pnote = ch->pnote;
    ch->pnote = NULL;


    /*
     * LIFO to make life easier 
     */
    pnote->next = victim->comments;
    if( victim->comments )
      victim->comments->prev = pnote;
    pnote->prev = NULL;
    victim->comments = pnote;

    save_char_obj( victim );


#ifdef NOTDEFD
    fclose( fpReserve );
    sprintf( notefile, "%s/%s", BOARD_DIR, board->note_file );
    if( ( fp = fopen( notefile, "a" ) ) == NULL )
    {
      perror( notefile );
    }
    else
    {
      fprintf( fp, "Sender  %s~\nDate    %s~\nTo      %s~\nSubject %s~\nText\n%s~\n\n",
               pnote->sender, pnote->date, pnote->to_list, pnote->subject, pnote->text );
      fclose( fp );
    }
    fpReserve = fopen( NULL_FILE, "r" );
#endif

    send_to_char( "Ok.\n\r", ch );
    return;
  }

  if( !str_cmp( arg, "remove" ) )
  {
    argument = one_argument( argument, arg1 );
    victim = get_char_world( ch, arg1 );
    if( !victim )
    {
      send_to_char( "They're not logged on!\n\r", ch ); /* maybe fix this? */
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "No comments about mobs\n\r", ch );
      return;
    }

    if( ( get_trust( victim ) >= get_trust( ch ) ) || ( get_trust( ch ) < 58 ) )  /* switch to some LEVEL_ thingie */
    {
      send_to_char( "You're not of the right caliber to do this...\n\r", ch );
      return;
    }

    /*
     * argument = one_argument(argument, arg); 
     */
    if( !is_number( argument ) )
    {
      send_to_char( "Comment remove which number?\n\r", ch );
      return;
    }

    anum = atoi( argument );
    vnum = 0;
    for( pnote = victim->comments; pnote; pnote = pnote->next )
    {
      vnum++;
      if( ( 58 <= get_trust( ch ) ) /* switch to some LEVEL_ thingie */
          && ( vnum == anum ) )
      {
        comment_remove( ch, victim, pnote );
        send_to_char( "Ok.\n\r", ch );
        /*
         * act( AT_ACTION, "$n removes a note.", ch, NULL, NULL, TO_ROOM ); 
         */
        return;
      }
    }

    send_to_char( "No such comment.\n\r", ch );
    return;
  }

  send_to_char( "Huh?  Type 'help comment' for usage (i hope!).\n\r", ch );
  return;
}


void fwrite_comments( CHAR_DATA * ch, FILE * fp )
{
  NOTE_DATA *pnote;

  if( !ch->comments )
    return;

  for( pnote = ch->comments; pnote; pnote = pnote->next )
  {
    fprintf( fp, "#COMMENT\n" );
    fprintf( fp, "sender	%s~\n", pnote->sender );
    fprintf( fp, "date  	%s~\n", pnote->date );
    fprintf( fp, "to     	%s~\n", pnote->to_list );
    fprintf( fp, "subject	%s~\n", pnote->subject );
    fprintf( fp, "text\n%s~\n", pnote->text );
  }
  return;
}

void fread_comment( CHAR_DATA * ch, FILE * fp )
{
  NOTE_DATA *pnote;

  for( ;; )
  {
    char letter;

    do
    {
      letter = getc( fp );
      if( feof( fp ) )
      {
        fclose( fp );
        return;
      }
    }
    while( isspace( letter ) );
    ungetc( letter, fp );

    CREATE( pnote, NOTE_DATA, 1 );

    if( str_cmp( fread_word( fp ), "sender" ) )
      break;
    pnote->sender = fread_string( fp );

    if( str_cmp( fread_word( fp ), "date" ) )
      break;
    pnote->date = fread_string( fp );

    if( str_cmp( fread_word( fp ), "to" ) )
      break;
    pnote->to_list = fread_string( fp );

    if( str_cmp( fread_word( fp ), "subject" ) )
      break;
    pnote->subject = fread_string( fp );

    if( str_cmp( fread_word( fp ), "text" ) )
      break;
    pnote->text = fread_string( fp );

    pnote->next = ch->comments;
    pnote->prev = NULL;
    ch->comments = pnote;
    return;
  }

  bug( "fread_comment: bad key word. strap in!", 0 );
  /*
   * exit( 1 ); 
   */
}




/*
<758hp 100m 690mv> <#10316> loadup boo
Log: Haus: loadup boo
Log: Reading in player data for: Boo
Done.
<758hp 100m 690mv> <#10316> poke boo
You poke him in the ribs.
<758hp 100m 690mv> <#10316> comment subject boo's a nutcase!
Ok.
<758hp 100m 690mv> <#10316> comment to all
Ok.
<758hp 100m 690mv> <#10316> comment write
Begin entering your text now (/? = help /s = save /c = clear /l = list)
-----------------------------------------------------------------------
> He transed shimmy to temple square!
> /s
Done.
<758hp 100m 690mv> <#10316> comment post boo
Ok.
<758hp 100m 690mv> <#10316> comment list boo
 1) Haus: boo's a nutcase!
<758hp 100m 690mv> <#10316> comment read boo 1
[  1] Haus: boo's a nutcase!
Sun Jun 25 18:26:54 1995
To: all
He transed shimmy to temple square!
<758hp 100m 690mv> <#10316> comment remove boo 1
Ok.
<758hp 100m 690mv> <#10316> comment list boo
There are no relevent comments.
*/