skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
#include <mail.h>
#include <board.h>;

inherit OBJECT_OBJ;

#define DEBUG_ME

string board_name;

// Variables used to temporarily save data re a post to transfer to other uses
// eg in 'close' archive it then transfer to closed board and mail it
private string post_body, post_rec, post_sub, post_time;
private int post_num;
private string post_to;

mapping being_written;
int action_pri;

class info_written {
   string subject;
   int note_num;
}

int do_read_next();
int do_read_new();
int do_read(int num);
int do_close(int num);
int do_close(string str);
int do_followup(int num);
int do_reply(int num);
int do_eat(int num);
int do_post(string str);

void setup() {
   set_name("board");
   set_short("bulletin board");
   add_adjective("bulletin");
   set_main_plural("boards");
   reset_get();
   add_property("there", "mounted on one wall");
   add_property("survive fire", 1);
   board_name = "general";
   being_written = ([ ]);
   action_pri = 0;
} /* setup() */

string query_plural() {
   mixed *stuff;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   switch (sizeof(stuff)) {
   case 0:
      return pluralize(::short(0))+" [ Empty ]";
   case 1:
      return pluralize(::short(0))+" [ 1 note ]";
   }
   return pluralize(::short(0))+" [ "+sizeof(stuff)+" notes ]";
} /* query_plural() */

string short(int dark) {
   mixed *stuff;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   switch (sizeof(stuff)) {
   case 0:
      return ::short(dark)+" [ Empty ]";
   case 1:
      return ::short(dark)+" [ 1 note ]";
   default:
      return ::short(dark)+" [ "+sizeof(stuff)+" notes ]";
   }
} /* short() */

string the_date(int i) {
   return ctime(i)[4..9];
} /* the_date() */

int do_subjects() {
   int i, size;
   mixed *stuff;
   string ret;
   mapping news_rc;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   if (!sizeof(stuff)) {
      add_failed_mess("The board is completely empty.\n");
      return 0;
   }
   news_rc = BOARD_H->query_newsrc(this_player()->query_name());
   if (!news_rc) {
      news_rc = ([ ]);
   }
   ret = "";
   size = sizeof(stuff);
   for (i=0; i < size; i++) {
      if (news_rc[board_name] < stuff[i][B_TIME]) {
         ret += sprintf("N %2d: %-=*s\n", i+1,
                     (int)TP->query_cols()-6,
                     stuff[i][B_SUBJECT]+" ("+
                     stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")");
     } else {
         ret += sprintf("  %2d: %-=*s\n", i+1,
                     (int)TP->query_cols()-6,
                     stuff[i][B_SUBJECT]+" ("+
                     stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")");
      }
   }
   TP->set_finish_func(0);
   TP->more_string(ret);
   return 1;
} /* subjects() */

string long(string str, int dark) {
   int i,newones, size;
   mixed *stuff;
   string ret;
   mapping news_rc;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   ret = "A bulletin board ("+board_name+").\n";
   ret += sprintf("%#-*s\n\n", TP->query_cols(),
                             "read [note number]\nsubjects\n"+
                      (TP->query_property("guest")?"":
                             "post <subject>\neat <note number>\n"+
                             "reply <note number>\nfollowup <note number>\n"));
   if (!sizeof(stuff))
      return ret+"The board is completely empty.\n";
   news_rc = BOARD_H->query_newsrc(TP->query_name());
   if (!news_rc)
      news_rc = ([ ]);
   newones = 0;
   size = sizeof(stuff);
   for (i = 0; i < size; i++)
      if (news_rc[board_name] < stuff[i][B_TIME]) {
         ret += sprintf("N %2d: %-=*s\n", i+1,
                     (int)TP->query_cols()-6,
                     stuff[i][B_SUBJECT]+" ("+
                     stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")");
         newones +=1;
      } else if (news_rc[board_name] < stuff[i][B_TIME]+(2*24*60*60))
         ret += sprintf("  %2d: %-=*s\n", i+1,
                     (int)TP->query_cols()-6,
                     stuff[i][B_SUBJECT]+" ("+
                     stuff[i][B_NAME]+" "+the_date(stuff[i][B_TIME])+")");
   if (!newones)
      ret += "\nNo new messages\n";
   return ret;
} /* long() */

void add_commands() {
   add_command("read", "[new]", (: do_read_new :));
   add_command("r", "[new]", (: do_read_new :));
   add_command("read", "<number>", (: do_read($4[0]) :));
   add_command("r", "<number>", (: do_read($4[0]) :));
   add_command("read", "next", (: do_read_next :));

   if( !TP->query_property("guest") ) {
       add_command("post", "<string>", (: do_post($4[0]) :));
       add_command("note", "<string>", (: do_post($4[0]) :));
       add_command("eat", "<number>", (: do_eat($4[0]) :));
       add_command("followup", "<number>", (: do_followup($4[0]) :));
       add_command("reply", "<number>", (: do_reply($4[0]) :));
   }

   if( creatorp(TP) )
       add_command("close", "<number>", (: do_close($4[0]) :));

   add_command("subjects", "");

} /* add_commands() */

void init() {
   if( TP && !present("board master", TP ) )
       add_commands();
} /* init() */

string query_post_to() { return post_to; }

void set_post_to(string val) { post_to = val; }

int do_close(int num){
  int i;
  int m;
  class info_written bing;

  mixed stuff = BOARD_H->get_subjects(board_name);
  string body;
  string s, pname = this_player() -> query_name();
  string close_to;

//  num = args[0];
  body = BOARD_H->get_message(board_name, num-1);

  TP->add_succeeded_mess(TO,"");

  if (num < 1 || num > sizeof(stuff))
    return notify_fail("No note of that number.\n");

  if (sscanf(stuff[num - 1][B_SUBJECT], "Re:#%d %s", i, s) != 2)
    being_written[pname] = "Re:#1 "+ stuff[num - 1][B_SUBJECT];
  else
    being_written[pname] = "Re:#"+ (i + 1) +" "+ s;

  if (body)
  {

// Truncate any signature.
    if ((m = strsrch(body, "\n\n--\n", 0)) != -1)
      body = body[0..m];

// Comment the post out.
    body = "> "+ replace(body, "\n", "\n> ") +"\n\n";
  } else {
    write("Unable to find a body for post "+ query_num(num) +
    ".\n");
    return 1;
  }

  if(!close_to = BOARD_H->query_close(board_name))
  {
    write("Unable to find a board to close to.\n");
    return 1;
  }

// Post copy to 'close board', amending as desired
  set_post_to(close_to);
  post_body = body;
  post_num=num;
  post_rec = stuff[num-1][B_NAME];
  post_sub = "Re : " + stuff[num-1][B_SUBJECT];
  post_time = ctime(stuff[num-1][B_TIME]);
  bing = new(class info_written);
  bing->subject = "Re: "+ stuff[num - 1][B_SUBJECT];
  bing->note_num = stuff[num - 1][B_NUM];
  being_written[(string)this_player()->query_name()] = bing;

  write(body);
  write("\nIs this the note you want to close (Y/N)?");
  input_to("do_close1");
  return 1;
} /* do_close() */

int do_close1(string str){
  if(!str || str ==""){
       write("\nIs this the note you want to close(Y/N)?");
       input_to("close1");
       return 1;
  }
  if(lower_case(str)!="y"){
     write("\nOkay close cancelled.\n");
     post_body = 0;
     post_rec = 0;
     post_sub = 0;
     post_time = 0;
     post_num=0;
     return 1;
  }

  write("\n-----------------------------------\n");
  write("TRANSFERRING COPY TO 'CLOSED' BOARD\n");
  write("ADD COMMENTS AS APPROPRIATE\n\n");
  write("-----------------------------------\n\n");
  this_player() -> do_edit(post_body +
      sprintf("\nRaised by %s %s\n", post_rec, post_time) +
      sprintf("\nClosed by %s %s\n", TP->query_cap_name(), ctime(time())),
      "end_of_close" );

// archive original copy
  BOARD_H->zap_message(board_name, post_num-1);

  return 1;
} /* do_close1() */

void end_of_close(string str)
{
  string body;
  TO->end_of_thing(str);

  body = post_body + sprintf("\nFixed by %s %s\n", TP->query_cap_name(), ctime(time()));
  post_body = body;
// mail copy to original bug reporter, saying 'fixed'
  write("\n----------------------------\n");
  write("MAILING COPY TO ORIGINATOR\n");
  write("ADD COMMENTS AS APPROPRIATE\n");
  write("----------------------------\n");

  this_player() -> do_edit(body,"end_of_mail_close" );

} /* end_of_close() */

void end_of_mail_close(string str){

  if(!str)
     str = post_body;

  MAIL_H->do_mail_message(post_rec, TP->query_name() , post_sub, 0,
                     str);

  post_body = 0;
  post_rec = 0;
  post_sub = 0;
  post_time = 0;
  post_num=0;
} /* mail_close() */

void mark_mine(mixed *stuff, mapping news_rc) {
   int i;
   string their_name;

   i = sizeof(stuff)-1;
   their_name = this_player()->query_name();
   while (i > 0 && stuff[i][B_TIME] > news_rc[board_name])
      i--;
   while ((i+1) < sizeof(stuff) && lower_case(stuff[i+1][B_NAME]) == their_name)
      i++;
   if (i >= sizeof(stuff)) {
      news_rc[board_name] = stuff[sizeof(stuff)-1][B_TIME];
      return;
   }
   if (news_rc[board_name] > stuff[i][B_TIME])
      return;
   news_rc[board_name] = stuff[i][B_TIME];
} /* mark_mine() */


int do_read_next()  {
   mapping  news_rc;
   mixed   *stuff;
   string   their_name, sub, next_sub;
   int      num, last_time;

   news_rc = BOARD_H->query_newsrc(this_player()->query_name());
   if (undefinedp(news_rc["last board"])  ||
       news_rc["last board"] != board_name)
   {
      add_failed_mess("You have not read a note on this board yet!\n");
      return 0;
   }

   stuff = BOARD_H->get_subjects(board_name);
   num = sizeof(stuff);
   their_name = this_player()->query_name();

write("last time: " + ctime(news_rc["last time"]) + "\n");
   last_time = news_rc["last time"];
   while (num  &&  stuff[num - 1][B_TIME] > last_time)  {
      num--;
   }

   sub = news_rc["last sub"];
   sscanf(sub, "Re:#%*d %s", sub);

   for (++num; num <= sizeof(stuff); num++)  {
      next_sub = stuff[num - 1][B_SUBJECT];
      sscanf(next_sub, "Re:#%*d %s", next_sub);
      if (next_sub == sub)  {
         return do_read(num);
      }
   }

   add_failed_mess("No further notes in the thread \"" + sub + "\".\n");
   return 0;
} /* do_read_next() */


int do_read_new() {
   int num;
   string their_name;
   mapping news_rc;
   mixed *stuff;

   news_rc = BOARD_H->query_newsrc(this_player()->query_name());
   if (!news_rc) {
      news_rc = ([ ]);
   }
   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   num = sizeof(stuff);
   their_name = (string)this_player()->query_name();
   while(num && (stuff[num - 1][B_TIME] > news_rc[board_name])) {
      num--;
   }
   while ((num < sizeof(stuff)) &&
          (lower_case(stuff[num][B_NAME]) == their_name)) {
      num++;
   }
   if (num == sizeof(stuff)) {
      add_failed_mess("No unread messages.\n");
      return 0;
   }
   num++;
   return do_read(num);
} /* do_read_new() */

int do_read(int num) {
   mapping news_rc;
   mixed *stuff;

   news_rc = BOARD_H->query_newsrc(this_player()->query_name());
   if (!news_rc) {
      news_rc = ([ ]);
   }
   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   if (num < 0) {
      num = sizeof(stuff) + num + 1;
   }
   if (num < 1 || (num > sizeof(stuff))) {
      add_failed_mess("No note of that number.\n");
      return 0;
   }
   num--;
   news_rc["last board"] = board_name;
   news_rc["last time"] = stuff[num][B_TIME];
   news_rc["last sub"] = stuff[num][B_SUBJECT];
   if (news_rc[board_name] < stuff[num][B_TIME]) {
      news_rc[board_name] = stuff[num][B_TIME];
   }
   BOARD_H->set_newsrc(this_player()->query_name(), news_rc);

   this_player()->more_string(sprintf("%s\nNote #%d by %s posted at %s%s\nTitle: "
                                     "\"%s\"\n\n%s",
                                     "%^BOLD%^",
                                     (num + 1),
                                     stuff[num][B_NAME],
                                     ctime(stuff[num][B_TIME]),
                                     "%^RESET%^",
                                     stuff[num]
                                     [B_SUBJECT][0..(int)this_player()->
                                                 query_cols() - 10],
                                     (string)BOARD_H->
                                       get_message(board_name, num)),
                             "[Note "+ (num + 1) +"]");
   //add_succeeded_mess(({ "", "$N $V a note.\n" }), ({ }));
   add_succeeded_mess("", ({ }));

   return 1;
} /* do_read() */

int do_post(string str) {
   class info_written bing;

   if (board_name=="announcements" && !creatorp(TP)) {
      add_failed_mess("Sorry. You can't post messages here.  "
            "It's for announcements "
            "from the creators only.  If you have a comment or flame, try "
            "the 'flame' board or the 'frog' board.  Bing\n");
      return 0;
   }
   if (!str) {
      return 0;
   }
   /*
    * ok shove the editing stuff in here.  Lets make it function string_edit
    * sound froggy?
    */
   /*
    string_edit("");
    body = string_edit_res;
    */
   if (!BOARD_H->test_can_write(board_name,
                                   this_object(),
                                   this_player()->query_name())) {
      add_failed_mess("You cannot write to this board.\n");
      return 0;
   }
   bing = new(class info_written);
   bing->subject = str;
   bing->note_num = 0;
   being_written[this_player()->query_name()] = bing;
   this_player()->do_edit(0, "end_of_thing");
   add_succeeded_mess(({ "", "$N looks like $r is "
                                        "contemplating a note.\n" }), ({ }) );
   return 1;
} /* do_post() */

void end_of_thing(string body) {
  class info_written bing;

  if(!post_to)
      post_to = board_name;
  if (body && body != "" &&
      being_written[this_player()->query_name()]) {
    if(board_name != "announcements")
      body = sprintf( "%-=78s", body ) + this_player()->append_signature();

    bing = (class info_written)being_written[ this_player()->query_name() ];
    if ( !BOARD_H->add_message( post_to,
         capitalize( (string)this_player()->query_name() ),
         bing->subject,
         body,
         bing->note_num ) ) {
      printf( "Error writing message.\n" );
    } else {
      printf("Message posted.\n");
    }
  } else {
    printf( "No message posted.\n" );
  }
  map_delete(being_written, this_player()->query_name());
  post_to = 0;
  return ;
} /* end_of_thing() */

int do_eat(int num) {
   object *users;

   if( !BOARD_H->delete_message( board_name, num - 1 ) ) {
       add_failed_mess("Failed to eat note.\n");
       return 0;
   }

   printf("You viciously tear off and eat note %d.\n", num );

   say( (string)TP->one_short()+" viciously tears off and eats note "+
        num +".\n");

   users = filter( users(), (:
           BOARD_H->test_can_read( board_name, TO, $1->query_name() ) :) );
   event( users, "inform", (string)TP->query_cap_name() +
        " eats a note off "+ board_name, "message", TP );
   return 1;

} /* eat() */

int do_followup(int num) {
   int i;
   mixed stuff;
   string s;
   class info_written bing;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   if (num < 1 || num > sizeof(stuff)) {
      add_failed_mess("No note of that number.\n", ({ }));
      return 0;
   }

   /*
    * If there is a reply type, means we do something other than
    * post to this board.
    */
   if (!stuff[num - 1][B_REPLY_TYPE] &&
       !BOARD_H->test_can_write( board_name, TO, TP->query_name() ) ) {
       add_failed_mess("You cannot followup to this board.\n", ({ }));
       return 0;
   }

   bing = new(class info_written);
   if (sscanf(stuff[num - 1][B_SUBJECT], "Re:#%d %s", i, s) != 2) {
      bing->subject = "Re:#1 "+ stuff[num - 1][B_SUBJECT];
   } else {
      bing->subject = "Re:#"+ ( i + 1 ) +" "+ s;
   }
   bing->note_num = stuff[num - 1][B_NUM];
   being_written[(string)this_player()->query_name()] = bing;
   printf("Include original post? (y/[n]) ");
   input_to("include_post", 0, num - 1, stuff[num - 1]);
   add_succeeded_mess(({ "", "$N looks like $r is "
                                        "contemplating a note.\n" }), ({ }) );
   return 1;
} /* do_followup() */

void include_post(string str, int num, mixed *stuff) {
  if (!str || str == ""  || lower_case(str)[0] != 'y') {
    printf("No.\n");
    this_player()->do_edit(0, "end_of_thing");
    return;
  }

  if (this_player()->query_name() == "macchirton") {
    printf("No including notes for pointless and repeated abuse.\n");
    this_player()->do_edit(0, "end_of_thing");
    return;
  }

  this_player()->
    do_edit("On " + ctime(stuff[B_TIME]) + ", " + stuff[B_NAME] +
            " wrote:\n> " +
            replace_string(BOARD_H->get_message(board_name, num),
                                  "\n", "\n> ") + "\n", "end_of_thing");
} /* include_post() */

int do_reply(int num) {
   mixed stuff;

   stuff = (mixed *)BOARD_H->get_subjects(board_name);
   if (num < 1 || num > sizeof(stuff)) {
      add_failed_mess("No note of that number.\n", ({ }));
      return 0;
   }
   MAIL_TRACK->mail(stuff[num-1][B_NAME], stuff[num-1][B_SUBJECT]);
   add_succeeded_mess(({ "", "$N looks like $r is "
                                        "contemplating a note.\n" }), ({ }) );
   return 1;
} /* reply() */

void set_board_name(string str) { board_name = str; }
void set_datafile(string str) { board_name = str; }

int query_new_messages() {
   mixed *notes;
   mapping news_rc;

   news_rc = BOARD_H->query_newsrc(this_player()->query_name());
   if (!news_rc)
      news_rc = ([ ]);
   notes = (mixed *)BOARD_H->get_subjects(board_name);
   if (!sizeof(notes))
      return 0;
   return (notes[sizeof(notes)-1][B_TIME] > news_rc[board_name]);
} /* query_new_messages() */