/
lib/banish/
lib/d/coronos/
lib/d/coronos/w/alena/
lib/d/coronos/w/angel/
lib/d/coronos/w/angel/caves/
lib/d/coronos/w/angel/caves/monst/
lib/d/coronos/w/angel/city/chambers/
lib/d/coronos/w/angel/city/monst/
lib/d/coronos/w/angel/city/obj/
lib/d/coronos/w/angel/city/streets/
lib/d/coronos/w/angel/farms/plains/
lib/d/coronos/w/angel/monst/
lib/d/tempus/
lib/d/tempus/w/angel/
lib/d/tempus/w/kingbill/
lib/d/tempus/w/mirak/
lib/d/tempus/w/mirak/monst/
lib/d/tempus/w/mirak/obj/
lib/d/tempus/w/relgar/planes/baat/
lib/d/tempus/w/sarak/
lib/d/tempus/w/serepion/mon/
lib/d/tempus/w/valrejn/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/include/fn_specs/
lib/info/
lib/inherit/base/
lib/log/
lib/log/mailbox/
lib/log/main/
lib/news/
lib/obj/party/
lib/objects/componen/
lib/open/
lib/open/party/
lib/open/paste/
lib/open/spells/
lib/open/valrejn/
lib/players/
lib/players/alena/
lib/players/alena/obj/
lib/players/alena/open/
lib/players/alena/private/
lib/players/angel/
lib/players/angel/obj/
lib/players/ash/
lib/players/biggs/
lib/players/biggs/food/
lib/players/biggs/gobkeep/
lib/players/biggs/mnstr/
lib/players/biggs/town/caves/
lib/players/biggs/town/tower/
lib/players/biggs/wpns/
lib/players/calris/
lib/players/deathurg/
lib/players/deathurg/open/
lib/players/deathurg/private/thief/
lib/players/dogberry/
lib/players/dogberry/library/
lib/players/dogberry/open/
lib/players/epsilon/
lib/players/epsilon/private/
lib/players/farewell/
lib/players/hippo/
lib/players/hippo/open/
lib/players/hippo/tools/
lib/players/jimpa/
lib/players/josh/
lib/players/josh/room/
lib/players/josh/room/mage/dungeon/
lib/players/josh/room/mage/dungeon/obj/
lib/players/josh/wep/
lib/players/kingbill/
lib/players/metatron/
lib/players/miette/
lib/players/mirak/
lib/players/mirak/open/
lib/players/parsilan/
lib/players/relgar/
lib/players/relgar/private/
lib/players/sarak/
lib/players/sarak/bugs/
lib/players/sarak/feelings/
lib/players/sarak/magical/
lib/players/sarak/minotaur/island/
lib/players/sarak/open/
lib/players/sarak/private/
lib/players/serepion/
lib/players/serepion/open/
lib/players/serepion/private/
lib/players/spike/
lib/players/spike/open/
lib/players/spike/private/
lib/players/spike/seaworld/
lib/players/valrejn/
lib/players/valrejn/open/
lib/players/valrejn/private/
lib/players/virus/
lib/players/wrath/
lib/players/wrath/arm/
lib/players/wrath/mon/
lib/players/wrath/room/
lib/players/wrath/room/entry/
lib/players/wrath/room/zolgath/
lib/players/wrath/weap/
lib/players/zil/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/library/
lib/room/city/library/open/books/
lib/room/city/shop/
lib/room/death/
lib/room/death/open/
lib/room/island/
lib/room/keeps/
lib/room/registry/
lib/room/ships/crew/
lib/room/ships/open/
lib/room/ships/open/types/bounty/
lib/room/ships/open/types/nebula/
lib/room/ships/open/types/phoenix/
lib/secure/udp_cmd_/
lib/skills/
lib/skills/fighter/
lib/skills/psionici/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/no_banis/
lib/usr/players/
/* Bulletin Board 2 */

/*
   This board gives the player greater control over notices. It uses 
   /obj/editor (a string editor), and /obj/pager (a 'more' for strings).
   These are also used by the mailer 
 */

#include <mudlib.h>
inherit BASE;

#include <ansi.h>

#ifndef EDITOR
#define EDITOR "obj/editor"
#endif

#ifndef PAGER
#define PAGER "obj/pager"
#endif

#define NAME    (string)this_player()->query_name()
#define REAL    (string)this_player()->query_name(1)
#define HEADER  0
#define AUTHOR  1
#define MESSAGE 2
#define TIME    ctime(time())[4..15]
#define PASTE   "/"+ PASTE_DIR +"/"+ REAL

/* bulletins */

mixed *bulletins;    /* ({ ({ header, author, message, }), }) */
static string save_file; 

/* new notice */

static object new_author;
static string new_header;
static int edit_old;

#ifdef NATIVE_MODE
void create() {
#else
void reset(status arg) {
  if(arg) return;
#endif /* native */
  set_name("bulletin board");
  set_alt_name("board");
  set_extra_long("There is a bulletin board here.\n");
  bulletins = ({});
}

 
void long(status wiz) { 
    int i;

    if(query_long()) ::long(wiz);
    write("You can set up new notes with the command 'note headline'.\n"); 
    write("Read a note with 'read num', and remove an old note(s) with\n"); 
    write("'remove num{,num2}'.  You can clip a note to your clipboard with\n"+
          "'clip num'. You can edit one of your old notes with\n"+
          "'edit num'.\n");
    if(!sizeof(bulletins)) {
      write("It is Empty.\n");
    }
    else if(sizeof(bulletins) == 1) {
      write("The Bulletin Board contains 1 note:\n\n");
    }
    else {
      write("The Bulletin Board contains "+ sizeof(bulletins) +" notes:\n\n");
    }
    say(NAME +" studies the bulletin board.\n"); 
    for(i = 0; i < sizeof(bulletins); i++) {
      write((i+1) +".\t"+ bulletins[i][HEADER] +"\n");
    }
} 
 
void set_save_file(string file) { 
  save_file = file; 
  if(save_file) restore_object(save_file); 
} 

 
status get() { 
  write("It is secured to the ground.\n"); 
  return 0; 
} 

status drop() { return 1; }
 

init() { 
   if(!bulletins) bulletins = ({});
   add_action ("new", "note"); 
   add_action ("read", "read"); 
   add_action ("remove", "remove"); 
   add_action ("bo", "bo"); 
   add_action ("read", "clip");
   add_action ("edit", "edit");
} 


status bo() {
  long(0);
  return 1;
}

/*************************************************************************/


void add_message(string arg) {  /* quit and save from editor */
  if(new_author != this_player()) return;
  if(edit_old) { /* was editing old notice */
    bulletins = bulletins[0..(edit_old-2)]
              + bulletins[edit_old..(sizeof(bulletins)-1)];
    edit_old = 0;
  }
  bulletins += ({
                 ({
                   new_header,
                         REAL,
                          arg,
                 })
               });
  if(save_file) save_object(save_file);
  new_author = 0;
  new_header = 0;
}


void editor_quit(string arg) {  /* quit, no save from editor */
  edit_old = 0;
  new_author = 0;
  new_header = 0;
}


/***********************************************************************/
/* edit old notice */


status edit(string str) {
  int i;
  string rest;

  if(!str || !(sscanf(str, "%d", i) || sscanf(str, "note %d", i))) return 0; 
  if(i < 1 || i > sizeof(bulletins)) { 
    write("Not that number of messages.\n"); 
    return 1; 
  } 
  i -= 1;
  if(!this_player()->id(bulletins[i][AUTHOR])) {
    write("Sorry, you can only edit your own notice.\n");
    return 1;
  }
  if(new_author && environment(new_author) == environment()) {
    write((string)new_author->query_name() +" is busy writing.\n"); 
    return 1; 
  } 
  sscanf(bulletins[i][HEADER],"%s("+capitalize(REAL)+", %s",new_header,rest);
  new_header += "("+capitalize(REAL) +", "+ TIME +")";
  new_author = this_player();
  edit_old = i + 1;
  clone_object(EDITOR)->edit("add_message",bulletins[i][MESSAGE],1);
  return 1;
}


/*************************************************************************/
/* add new notice */

status new(string hd) { 
  if(!hd) {
    notify_fail("You must give a title.\n");
    return 0; 
  }
  if(new_author && environment(new_author) == environment()) {
    write((string)new_author->query_name() +" is busy writing.\n"); 
    return 1; 
  } 
  if(sizeof(bulletins) == 30) { 
    write("You have to remove an old message first.\n"); 
    return 1; 
  } 
  if(strlen(hd) > 50) { 
    write("Too long header to fit the paper.\n"); 
    return 1; 
  } 
  hd = (string)this_player()->filter_ansi(hd); /* all headers filtered */
  new_author = this_player();  
  new_header = hd +"                                             ";
  new_header = extract(new_header,0,25);
  new_header += "["+ capitalize(REAL)+"                         ";
  new_header = extract(new_header,0,30);
  new_header += " "+ TIME +"]";
  clone_object(EDITOR)->edit("add_message",0,1);
  return 1; 
} 

/**************************************************************************/
/* read notice */

status read(string str) { 
  int i, k; 
  object pager_ob; 

  if(!str || (sscanf(str, "%d", i) && sscanf(str, "note %d", i))) { 
    if(query_verb() == "clip") 
      notify_fail("Usage: clip <note number>\n");
    return 0;
  }
  if(i < 1 || i > sizeof(bulletins)) { 
    write("Not that number of messages.\n"); 
    return 1; 
  }
  i -= 1;
  say(NAME +" reads a note titled '"+ bulletins[i][HEADER] +"'.\n"); 
  if(query_verb() == "clip") {
    str = bulletins[i][MESSAGE];
  }
  else if(this_player()->ansi_on()) {
    str = bulletins[i][MESSAGE] + OFF;
  }
  else {
    str = (string)this_player()->filter_ansi(bulletins[i][MESSAGE]);
  }
  if(query_verb() == "clip") {
    rm(PASTE);
    write("The note is titled '" + bulletins[i][HEADER] + 
          "' has been copied to your Clipboard.\n"); 
    write_file(PASTE, str);
  }
  else {
    write("The note is titled '" + bulletins[i][HEADER] + "':\n\n"); 
#ifdef PAGER
    pager_ob = clone_object(PAGER);
#ifdef NATIVE_MODE
    pager_ob->move(this_player());
#else
    move_object(pager_ob, this_player());
#endif /* NATIVE_MODE */
    pager_ob->page(str);
#else
    write(str); 
#endif
  }
  return 1; 
} 
 

status remove(string str) { 
  int i, j, k; 
 
  if(!str || !(sscanf(str, "%d,%d", i, j) || sscanf(str, "note %d", i)
  || sscanf(str, "%d", i))) {
    notify_fail("remove <number>\nremove <number1,number2>\n");
    return 0; 
  }
  if(i < 1 || i > sizeof(bulletins)) { 
    notify_fail("Not that number of messages.\n"); 
    return 0; 
  }
  if(j < i) j = i;
  if(j > sizeof(bulletins)) j = sizeof(bulletins);
  for(i -= 1, j -= 1; j >= i; j--) {
    if(!(this_player()->id(bulletins[j][AUTHOR]) ||
         this_player()->query_security_level())) {
       write("Sorry, you will have to ask a creator to remove the message "+
             (j+1) +"for you.\n");
       continue;
    }
    say(NAME +" removed a note titled '"+ bulletins[j][HEADER] +"'.\n"); 
    write("You remove the note "+ bulletins[j][HEADER] +"...\n");
    bulletins = bulletins[0..j-1]+bulletins[j+1..sizeof(bulletins)-1];
  }
  if(save_file) save_object(save_file);
  return 1;
}