toc/
toc/account/a/
toc/area/backup/
toc/area/imc/
toc/caste/
toc/caste/backup/
toc/clans/
toc/classes/
toc/crash/
toc/gods/
toc/guilds/
toc/lname/s/
toc/maps/backup/
toc/player/a/
toc/src/
toc/system/backup/
toc/tableprog/
/****************************************************************************
 * [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[MSL];
   char arg[MIL];
   char arg1[MIL];
   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);
      set_editor_desc(ch, "A player comment.");
      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.
*/