! ---------------------------------------------------------------------------- !
!   WriteList.h by Roger Firth ([email protected])
!       with thanks to Cedric Knight, Andrew Plotkin, Neil Cerutti
!       and Sonja Kesserich.
!
!       1.1 Apr 2003
!           WriteListFrom enhanced to be re-entrant.
!
!       1.0 Oct 2001
!           Original version.
!
! ---------------------------------------------------------------------------- !
!   Installation: add the line:
!
!       Include "WriteList";
!
!   between the Include "Parser" and Include "VerbLib" lines.
!
! ---------------------------------------------------------------------------- !
!
!   WriteList contains replacements for the generalised object list-writer
!   Library routine WriteListFrom(), to make it re-entrant (callable a second
!   time while a previous call is still in progress), and for the two
!   subsidiary Library routines WriteBeforeEntry() and WriteAfterEntry().
!   These routines, used by WriteListFrom(), have been modified to
!   invoke an object's invent property -- if it has one -- in response both to
!   LOOK (this is the purpose of the enhancement) as well as to INVENTORY
!   (which is standard behaviour). The modifications are very small, though
!   I have also reformatted the routines in an attempt to aid readability.
!
!   If an object has an invent property, it will be invoked in the usual way
!   (with inventory_stage first set to 1, and then set to 2) both when
!   mentioning that object in a room description, and when listing it in the
!   player's inventory. By default you'll get the same output each time.
!   If you need to distinguish between the two occasions, you can test
!   (c_style&PARTINV_BIT) -- true during a room description -- or
!   (c_style&FULLINV_BIT) -- true during an inventory. Here's an example:
!
!   Include "Parser";
!   Include "WriteList";
!   Include "VerbLib";
!
!   Object  -> "sack"
!     with  name 'sack',
!           invent [;
!               ! When listing objects in the player's inventory
!               if (c_style&FULLINV_BIT) rfalse;
!
!               ! When listing objects at the end of a room description
!               if (inventory_stage == 1) switch (children(self)) {
!                 0: print "an empty sack";
!                 1: print "a sack containing ", (a) child(self);
!                 default: print "an assortment of objects in a sack";
!               }
!               rtrue;
!           ],
!     has   container open;
!
! ---------------------------------------------------------------------------- !

Replace  WriteListFrom;
Replace  WriteBeforeEntry;
Replace  WriteAfterEntry;

! ---------------------------------------------------------------------------- !

[ WriteListFrom o style depth;

   @push c_style;      @push lt_value;   @push listing_together;   ! Lines
   @push listing_size; @push wlf_indent; @push inventory_stage;    ! added

   if (o == child(parent(o))) {
       SortOutList(o);
       o = child(parent(o));
   }
   c_style = style;
   wlf_indent = 0;
   WriteListR(o, depth);

   @pull inventory_stage;  @pull wlf_indent; @pull listing_size;   ! Lines
   @pull listing_together; @pull lt_value;   @pull c_style;        ! added
];

! ---------------------------------------------------------------------------- !

[ WriteBeforeEntry o depth sentencepos
   flag;

   inventory_stage = 1;
   if (c_style & INDENT_BIT) Print__Spaces(2*(depth+wlf_indent));
   if (o.invent && (c_style & (PARTINV_BIT|FULLINV_BIT))) {    ! This line changed
       flag = PrintOrRun(o, invent, 1);
       if (flag) {
           if (c_style & ENGLISH_BIT) {
               if (sentencepos == -1) print (string) AND__TX;
               if (sentencepos <  -1) print ", ";
           }
           if (c_style & NEWLINE_BIT) new_line;
       }
   }
   return flag;
];

! ---------------------------------------------------------------------------- !

[ WriteAfterEntry o depth stack_p
   p recurse_flag parenth_flag eldest_child child_count combo;

   inventory_stage = 2;
   if (c_style & PARTINV_BIT) {
       if (o.invent && RunRoutines(o, invent))                 ! These lines
           if (c_style & NEWLINE_BIT) ""; else rtrue;          ! added

       combo = 0;
       if (o has light && location hasnt light) combo=combo+1;
       if (o has container && o hasnt open)     combo=combo+2;
       if ((o has container && (o has open || o has transparent))
           && (child(o)==0))                    combo=combo+4;
       if (combo) L__M(##ListMiscellany, combo, o);
   }   ! end of PARTINV_BIT processing

   if (c_style & FULLINV_BIT) {
       if (o.invent && RunRoutines(o, invent))
           if (c_style & NEWLINE_BIT) ""; else rtrue;

       if (o has light && o has worn) { L__M(##ListMiscellany, 8);     parenth_flag = true; }
       else {
           if (o has light)           { L__M(##ListMiscellany, 9, o);  parenth_flag = true; }
           if (o has worn)            { L__M(##ListMiscellany, 10, o); parenth_flag = true; }
       }

       if (o has container)
           if (o has openable) {
               if (parenth_flag) print (string) AND__TX;
               else              L__M(##ListMiscellany, 11, o);
               if (o has open)
                   if (child(o)) L__M(##ListMiscellany, 12, o);
                   else          L__M(##ListMiscellany, 13, o);
               else
                   if (o has lockable && o has locked) L__M(##ListMiscellany, 15, o);
                   else                                L__M(##ListMiscellany, 14, o);
               parenth_flag = true;
           }
           else
               if (child(o)==0 && o has transparent)
                   if (parenth_flag) L__M(##ListMiscellany, 16, o);
                   else              L__M(##ListMiscellany, 17, o);

       if (parenth_flag) print ")";
   }   ! end of FULLINV_BIT processing

   if (c_style & CONCEAL_BIT) {
       child_count = 0;
       objectloop (p in o)
           if (p hasnt concealed && p hasnt scenery) { child_count++; eldest_child = p; }
   }
   else { child_count = children(o); eldest_child = child(o); }

   if (child_count && (c_style & ALWAYS_BIT)) {
       if (c_style & ENGLISH_BIT) L__M(##ListMiscellany, 18, o);
       recurse_flag = true;
   }

   if (child_count && (c_style & RECURSE_BIT)) {
       if (o has supporter) {
           if (c_style & ENGLISH_BIT) {
               if (c_style & TERSE_BIT) L__M(##ListMiscellany, 19, o);
               else                     L__M(##ListMiscellany, 20, o);
               if (o has animate)       print (string) WHOM__TX;
               else                     print (string) WHICH__TX;
           }
           recurse_flag = true;
       }
       if (o has container && (o has open || o has transparent)) {
           if (c_style & ENGLISH_BIT) {
               if (c_style & TERSE_BIT) L__M(##ListMiscellany, 21, o);
               else                     L__M(##ListMiscellany, 22, o);
               if (o has animate)       print (string) WHOM__TX;
               else                     print (string) WHICH__TX;
               }
           recurse_flag = true;
       }
   }

   if (recurse_flag && (c_style & ENGLISH_BIT))
       if (child_count > 1 || eldest_child has pluralname) print (string) ARE2__TX;
       else                                                print (string) IS2__TX;

   if (c_style & NEWLINE_BIT) new_line;

   if (recurse_flag) {
       o = child(o);
       @push lt_value; @push listing_together; @push listing_size;
       lt_value = 0;   listing_together = 0;   listing_size = 0;
       WriteListR(o, depth+1, stack_p);
       @pull listing_size; @pull listing_together; @pull lt_value;
       if (c_style & TERSE_BIT) print ")";
   }
];

! ---------------------------------------------------------------------------- !