!==============================================================================
! notepad.h by Gunther Schmidl <[email protected]>               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;