!==============================================================================
! notepad.h by Gunther Schmidl <gschmidl@gmx.at>               Release 1.000227
!==============================================================================
!
! This class defines a notepad item that can be filled in by the game player.
! Special Thanks to Admiral Jota for suggesting most of the things in here.
!
!------------------------------------------------------------------------------
! CUSTOMIZATION
!------------------------------------------------------------------------------
!
! If you want to change any strings, you will have to modify the library itself;
! the number of strings made an approach of exchangable string constants
! too complicated.
!
!------------------------------------------------------------------------------
! HOW TO USE IT
!------------------------------------------------------------------------------
!
! Use "Notepad objectname" to define the object.
!
! Put "Constant NOTEPAD_OBJECT object" somewhere in your game file, before you
! include this library.
!
! That's it! The player can now use 'WRITE "..."' to scribble up to 100 notes
! (each to a maximum of 60 characters) on the pad. The number of notes is
! arbitrarily chosen, and can be changed below.
!
! The player can also use 'ERASE number' to erase a certain note. The other
! notes are automatically re-numbered. 'ERASE ALL' or 'EMPTY object' will 
! delete all notes.
!
! Use object.addnote("...") to add a note yourself; be careful, as this doesn't
! check if there's still a note available. It returns an unique identifier, 
! which you can use to delete the note again, by calling object.delnote(ident).
! Use object.empty() to delete all notes, and object.isdeleted(ident) to see
! if a note has already been deleted. 
!
! Example:
!
! Notepad -> np "notepad"
!  with
!  name 'notepad' 'pad',
!  description "A small blue notepad made of recycled paper.";
!
!
!==============================================================================

Global from_char;
Global to_char;
Global unique_identifier = 1;

Class Notepad
 with
  description "",
  addnote
  [ x y;
   y = NPPage.create();
   (x).print_to_array(y.&text, 60);
   y.&text-->0 = 60;
   Pmove(y, NOTEPAD_OBJECT);  
   return y.ident;
  ],  
  delnote
  [ num x y;
   x = child(NOTEPAD_OBJECT);
   while (x.ident ~= num)
    x = sibling(x);
   y = sibling(x);
   NPPage.destroy(x);
   while (y ~= nothing)
   {
    y.number--;
    y = sibling(y);
   }  
  ],                  
  isdeleted
  [ num x;
   x = child(NOTEPAD_OBJECT);
   while (x ~= nothing && x.ident ~= num)
    x = sibling(x);
   return (x == nothing);
  ],          
  empty
  [ i o;
   i = child(NOTEPAD_OBJECT);
   while (i ~= nothing)
   {
    o = i;            
    i = sibling(i);
    NPPage.destroy(o);
   }
  ],    
  before
  [ o;
   Empty:
    PurgeSub();    
    rtrue;
   Examine:
    self.description();
    if (children(self) == 0)
    {
     print "^The notepad is empty.^";
     if (self hasnt general)
     {
      give self general;
      "[To write on it, try WRITE ~note...~]";
     }
     rtrue;
    }
    print "^You have made the following note";
    if (children(self) ~= 1) print "s";
    print ":^";
    objectloop (o in self)
    {
     print "^(", o.number, ") ";
     o.describe();
    }
    rtrue;
  ];

Class NPPage(100)
 with
  describe
  [ i f;
    for (i = 2 : i <= self.&text-->0 : i++)
    {
     f = self.&text->i;
     if (f ~= 0) print (char) f;
    }
    new_line;
    rtrue;
  ],
  number 0,
  ident 0,
  text 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,
  create
  [;
   self.&text-->0 = 60;
   self.number = 100 - NPPage.remaining();  
   self.ident = unique_identifier++;
  ],
 has static;

[ QuotedText i j f;
 i = WordAddress(wn++);
 i = i - buffer;
 if (buffer->i == '"')
 {
  for (j = i + 1 : j <= (buffer->1) + 1 : j++)
   if (buffer->j == '"')
    f = j;
  if (f == 0) return -1;
  from_char = i + 1;
  to_char = f - 1;
  if (from_char > to_char) return -1;
  while (buffer + f > WordAddress(wn))
   wn++;
  wn++;
  return 1;
 }
 return -1;
];

[ WriteEmptySub;   
 if (noun == nothing || noun == NOTEPAD_OBJECT)
  "What do you want to write?";
 if (noun ~= NOTEPAD_OBJECT)
  "You can't write on ", (the) noun, "!";  
];

[ WriteSub i j x;
 if (second == nothing)                        
 {
  print "(on ", (the) NOTEPAD_OBJECT, ".)^";
  second = NOTEPAD_OBJECT;
 }
 if (second ~= NOTEPAD_OBJECT)
  "You can't write on ", (the) second, "!";  
 if (NOTEPAD_OBJECT notin player)
  "You need to be holding ", (the) NOTEPAD_OBJECT, " to be able to write on
   it.";
 if (NPPage.remaining() == 0)
  "[Sorry, but the notepad is full.]";
 x = NPPage.create();
 for (i = from_char, j = 2 : i <= to_char && j < x.&text-->0 : i++, j++)
  x.&text->j = buffer->i;
 for ( : j < x.&text->0 : j++)
  x.&text->j = 0;

 Pmove(x, NOTEPAD_OBJECT);
 print_ret "[Note ", x.number, " added; ", NPPage.remaining(),
  " notes available.]";
];

[ EraseSub x y;  
 if (children(NOTEPAD_OBJECT) < noun)
  "[That note doesn't exist.]";
 x = child(NOTEPAD_OBJECT);
 while (x.number ~= noun)
  x = sibling(x);
 y = sibling(x);
 NPPage.destroy(x);
 while (y ~= nothing)
 {
  y.number--;
  y = sibling(y);
 }
 print_ret "[Note ", noun, " erased; ", NPPage.remaining(), " notes
  available.]";
];

[ PurgeSub;
 NOTEPAD_OBJECT.empty();    
 "[All notes have been erased; ", NPPage.remaining(), " notes available.]";
];

#IFNDEF temp_obj;
 Object temp_obj;
#ENDIF;

#IFNDEF Pmove;
 [ Pmove obj1 obj2 o;
  for (o = child(obj2) : o ofclass Object : o = child(obj2))
   { move o to temp_obj; };
  move obj1 to obj2;
  for (o = child(temp_obj) : o ofclass Object : o = child(temp_obj))
   { move o to obj2; };
 ];
#ENDIF;

Verb "write"
 *                       -> WriteEmpty
 * 'on' noun             -> WriteEmpty
 * QuotedText            -> Write
 * QuotedText 'on' noun  -> Write;

Verb "erase"
 * 'all'                 -> Purge
 * number                -> Erase;
