! Menu code purloined from DM4
! + cursor up code
! + fix to ensure Menus expand window -1 to the entire screen instead of just
!   the first few lines, to prevent it writing outside the window and annoying
!   some interpreters

System_file;

Global screen_width;
Global screen_height;
Array ForUseByOptions -> 129;

Class Option
 with select [;
             self.emblazon(1, 1, 1);
             @set_window 0; font on; style roman; new_line; new_line;
             if (self provides description) return self.description();
             "[No text written for this option.]^";
       ],
       emblazon [ bar_height page pages temp;
             screen_width = 0->33;
             !    Clear screen:
             @erase_window -1;
             @split_window bar_height;
             !    Black out top line in reverse video:
             @set_window 1;
             @set_cursor 1 1;
             style reverse; spaces(screen_width);
             if (standard_interpreter == 0)
                  @set_cursor 1 1;
             else {
                  ForUseByOptions-->0 = 128;
                  @output_stream 3 ForUseByOptions;
                  print (name) self;
                  if (pages ~= 1) print " [", page, "/", pages, "]";
                  @output_stream -3;
                  temp = (screen_width - ForUseByOptions-->0)/2;
                  @set_cursor 1 temp;
             }
             print (name) self;
             if (pages ~= 1) print " [", page, "/", pages, "]";
             return ForUseByOptions-->0;
       ];

Class Menu class Option
 with select [ count j obj pkey line oldline top_line bottom_line
         page pages options top_option;
           screen_width = 0->33;
           screen_height = 0->32;
           if (screen_height == 0 or 255) screen_height = 18;
           screen_height = screen_height - 7;
           options = 0;
           objectloop (obj in self && obj ofclass Option) options++;
           if (options == 0) return 2;
           pages = options/screen_height;
           if (options%screen_height ~= 0) pages++;
           top_line = 6;
           page = 1;
           line = top_line;
           .ReDisplay;
           top_option = (page - 1) * screen_height;
!           self.emblazon(7 + count, page, pages);
           self.emblazon(screen_height,page,pages);
           @set_cursor 2 1; spaces(screen_width);
           @set_cursor 2 2; print "N = next subject";
           j = screen_width-12; @set_cursor 2 j; print "P = previous";
           @set_cursor 3 1; spaces(screen_width);
           @set_cursor 3 2; print "RETURN = read subject";
           j = screen_width-17; @set_cursor 3 j;
           if (sender ofclass Option) print "Q = previous menu";
           else print                       "  Q = resume game";
           style roman;
           count = top_line; j = 0;
           objectloop (obj in self && obj ofclass Option) {
                 if (j >= top_option && j < (top_option+screen_height)) {
                      @set_cursor count 6;
                      print (name) obj;
                      count++;
                 }
                 j++;
           }
           bottom_line = count - 1;
           oldline = 0;
           for (::) {
                 ! Move or create the > cursor:
                 if (line ~= oldline) {
                      if (oldline ~= 0) {
                           @set_cursor oldline 4; print " ";
                      }
                      @set_cursor line 4; print ">";
                }
                oldline = line;
                @read_char 1 -> pkey;
                if (pkey == 'N' or 'n' or 130) {
                     ! Cursor down:
                     line++;
                     if (line > bottom_line) {
                          line = top_line;
                          if (pages > 1) {
                                if (page == pages) page = 1; else page++;
                                jump ReDisplay;
                          }
                     }
                     continue;
                }
                if (pkey == 'P' or 'p' or 129) {
                     ! Cursor up:
                     line--;
                     if (line < top_line) {
                          line = bottom_line;
                          if (pages > 1) {
                                if (page == 1) page = pages; else page--;
                                jump ReDisplay;
                          }
                     }
                     continue;
                }
                if (pkey == 'Q' or 'q' or 27 or 131) break;
                if (pkey == 10 or 13 or 132) {
                     count = 0;
                     objectloop (obj in self && obj ofclass Option) {
                          if (count == top_option + line - top_line) break;
                          count++;
                     }
                     switch (obj.select()) {
                          2: jump ReDisplay;
                          3: jump ExitMenu;
                     }
                     print "[Please press SPACE to continue.]^";
                     @read_char 1 -> pkey;
                     jump ReDisplay;
                }
           }
           .ExitMenu;
           if (sender ofclass Option) return 2;
           font on; @set_cursor 1 1;
           @erase_window -1; @set_window 0;
           new_line; new_line; new_line;
           if (deadflag == 0) <<Look>>;
           return 2;
        ];

Class SwitchOption class Option
  with short_name [;
                print (object) self, " ";
                if (self has on) print "(on)"; else print "(off)";
                rtrue;
         ],
         select [;
                if (self has on) give self ~on; else give self on;
                return 2;
         ];
