~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to include/menus.h

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
! -------------------------------------------------------------------------
2
 
!   Menus.h           A library extension providing easier and better menus
3
 
!                                                      Graham Nelson 961113
4
 
!                                                       Kevin Bracey 011128
5
 
!
6
 
!   A menu is a tree of objects of class Option.  A Menu is an Option which
7
 
!   launches a fresh menu when chosen.  To choose option O, send the
8
 
!   message:
9
 
!
10
 
!       O.select();
11
 
!
12
 
!   So to start off a menu session, send this message to the top menu.
13
 
!
14
 
!   Here's a simple menu structure:
15
 
!
16
 
!       Menu "Instructions for playing Mordred";
17
 
!       Menu   -> "How to play adventure games";
18
 
!       Option -> -> "Looking around"
19
 
!                     with description "I am your eyes and ears ...";
20
 
!       Option -> -> "Taking and Dropping"
21
 
!                     with description "When you find items ...";
22
 
!       Option -> "About the author"
23
 
!                  with description "The author was born in ...";
24
 
!
25
 
!   Menus produced in this code are automatically divided into pages
26
 
!   so that they'll always fit on the screen, whatever size the screen is
27
 
!   and however many options there are.
28
 
!
29
 
!   Note that since objects can always be moved about in play, it's easy
30
 
!   to create new menu structures to fit the circumstances of the moment.
31
 
!   (For example, a hints menu which gives hints only on currently open
32
 
!   puzzles.)
33
 
!
34
 
!   You can instead write a routine to receive the "description" message.
35
 
!   Then the text printed when an option is chosen can also vary.
36
 
!
37
 
!   If you return 2 from such a routine, then the game does not prompt
38
 
!   the player to press a key before going back into the menu.
39
 
!   If you return 3, then the whole menu is closed up immediately.
40
 
!
41
 
!   Finally, you can always give your own "select" routine for an Option.
42
 
!   The rules for return values are the same; what's different is that
43
 
!   this way the screen will not be cleared and given a nice banner when
44
 
!   the option is chosen.  (Nothing visible will happen unless you do
45
 
!   it yourself.)  The SwitchOption class is an example of the kind of
46
 
!   gadget you might want this for:
47
 
!
48
 
!       Menu "Game settings";
49
 
!       SwitchOption -> FullRoomD   "full room descriptions" has on;
50
 
!       SwitchOption -> WordyP      "wordier prompts";
51
 
!       SwitchOption -> AllowSavedG "allow saved games" has on;
52
 
!
53
 
!   Choosing any of these switch-options flips them between on and off.
54
 
!   In your program, you can test
55
 
!
56
 
!       if (WordyP has on) ...
57
 
!
58
 
!   and so forth to check the current state.
59
 
! -------------------------------------------------------------------------
60
 
 
61
 
Ifndef PKEY__TX;
62
 
 
63
 
Constant LIB_PRE_63;
64
 
 
65
 
!   Then we are using library 6/1 or 6/2, which won't have defined these:
66
 
 
67
 
Constant NKEY__TX     = "  N = next option";
68
 
Constant PKEY__TX     = "P = previous";
69
 
Constant QKEY1__TX    = "  Q = resume game";
70
 
Constant QKEY2__TX    = "Q = previous menu";
71
 
Constant RKEY__TX     = "RETURN = select option";
72
 
 
73
 
Constant NKEY1__KY    = 'N';
74
 
Constant NKEY2__KY    = 'n';
75
 
Constant PKEY1__KY    = 'P';
76
 
Constant PKEY2__KY    = 'p';
77
 
Constant QKEY1__KY    = 'Q';
78
 
Constant QKEY2__KY    = 'q';
79
 
 
80
 
Endif;
81
 
 
82
 
Global screen_width;
83
 
Global screen_height;
84
 
Global char_width;
85
 
Global char_height;
86
 
 
87
 
Array ForUseByOptions -> 129;
88
 
 
89
 
#Iftrue #version_number==6;
90
 
[ Menus_Measure s;
91
 
    @output_stream 3 ForUseByOptions;
92
 
    print (string) s;
93
 
    @output_stream -3;
94
 
    return 0-->24;
95
 
];
96
 
#Endif;
97
 
 
98
 
Class Option
99
 
 with emblazon
100
 
      [ bar_height page pages temp;
101
 
 
102
 
          screen_width = 0->33;
103
 
 
104
 
          !   Clear screen:
105
 
 
106
 
          @erase_window -1;
107
 
          #Iftrue #version_number==6;
108
 
          @set_cursor -1;
109
 
          @mouse_window -1;
110
 
          temp = bar_height * char_height;
111
 
          @split_window temp;
112
 
          #Ifnot;
113
 
          @split_window bar_height;
114
 
          #Endif;
115
 
 
116
 
          !   Black out top line in reverse video:
117
 
          @set_window 1;
118
 
          @set_cursor 1 1;
119
 
          #Iftrue #version_number==6;
120
 
          @set_font 4 -> temp;
121
 
          #Endif;
122
 
          style reverse; spaces(screen_width);
123
 
          #Iftrue #version_number==6;
124
 
          @set_font 1 -> temp;
125
 
          #Endif;
126
 
 
127
 
          if (#version_number ~= 6 && standard_interpreter == 0)
128
 
              @set_cursor 1 1;
129
 
          else
130
 
          {   ForUseByOptions-->0 = 128;
131
 
              @output_stream 3 ForUseByOptions;
132
 
              print (name) self;
133
 
              if (pages ~= 1) print " [", page, "/", pages, "]";
134
 
              @output_stream -3;
135
 
              #Iftrue #version_number==6;
136
 
              temp = 1 + (screen_width*char_width - 0-->24)/2;
137
 
              #Ifnot;
138
 
              temp = (screen_width - ForUseByOptions-->0)/2;
139
 
              #Endif;
140
 
              @set_cursor 1 temp;
141
 
          }
142
 
 
143
 
          print (name) self;
144
 
          if (pages ~= 1) print " [", page, "/", pages, "]";
145
 
 
146
 
          return ForUseByOptions-->0;
147
 
      ],
148
 
      select
149
 
      [;  self.emblazon(1, 1, 1);
150
 
 
151
 
          style roman; @set_window 0; font on; new_line; new_line;
152
 
 
153
 
          if (self provides description)
154
 
              return self.description();
155
 
 
156
 
          "[No text written for this option.]^";
157
 
      ];    
158
 
 
159
 
Class Menu class Option
160
 
 with select
161
 
      [ count j obj pkey  line oldline top_line bottom_line
162
 
                            page pages options top_option y x;
163
 
 
164
 
          screen_width = 0->33;
165
 
          screen_height = 0->32;
166
 
          #Iftrue #version_number==6;
167
 
          @set_font 4 -> x;
168
 
          char_width = 0->39;
169
 
          char_height = 0->38;
170
 
          @set_font x -> x;
171
 
          #Ifnot;
172
 
          char_width = 0->38;
173
 
          char_height = 0->39;
174
 
          #Endif;
175
 
          if (screen_height == 0 or 255) screen_height = 18;
176
 
          screen_height = screen_height - 7;
177
 
 
178
 
          options = 0;
179
 
          objectloop (obj in self && obj ofclass Option) options++;
180
 
          if (options == 0) return 2;
181
 
 
182
 
          pages = options/screen_height;
183
 
          if (options%screen_height ~= 0) pages++;
184
 
 
185
 
          top_line = 6;
186
 
 
187
 
          page = 1;
188
 
 
189
 
          line = top_line;
190
 
 
191
 
          .ReDisplay;
192
 
 
193
 
          top_option = (page - 1) * screen_height;
194
 
 
195
 
          self.emblazon(5 + options, page, pages);
196
 
          
197
 
          #Iftrue #version_number==6;
198
 
          x = 1 + char_width; y = 1 + char_height; @set_cursor y 1;
199
 
          @set_font 4->j; spaces(screen_width); @set_font 1->j;
200
 
          @set_cursor y x; print (string) NKEY__TX;
201
 
          j = 1+screen_width*char_width - Menus_Measure(PKEY__TX) - char_width;
202
 
          @set_cursor y j; print (string) PKEY__TX;
203
 
          
204
 
          y = y + char_height; @set_cursor y 1;
205
 
          @set_font 4->j; spaces(screen_width); @set_font 1->j;
206
 
          @set_cursor y x; print (string) RKEY__TX;
207
 
          if (sender ofclass Option) j = QKEY2__TX; else j = QKEY1__TX;
208
 
          j = 1+screen_width*char_width - Menus_Measure(j) - char_width;
209
 
          @set_cursor y j;
210
 
          #Ifnot;
211
 
          @set_cursor 2 1; spaces(screen_width);
212
 
          @set_cursor 2 2; print (string) NKEY__TX;
213
 
          j = screen_width-12; @set_cursor 2 j; print (string) PKEY__TX;
214
 
 
215
 
          @set_cursor 3 1; spaces(screen_width);
216
 
          @set_cursor 3 2; print (string) RKEY__TX;
217
 
          j = screen_width-17; @set_cursor 3 j;
218
 
          #Endif;
219
 
 
220
 
          if (sender ofclass Option)
221
 
              print (string) QKEY2__TX;
222
 
          else
223
 
              print (string) QKEY1__TX;
224
 
          style roman;
225
 
 
226
 
          count = top_line; j = 0;
227
 
          objectloop (obj in self && obj ofclass Option)
228
 
          {   if (j >= top_option && j < (top_option + screen_height))
229
 
              {   
230
 
                  #Iftrue #version_number==6;
231
 
                  y = 1 + (count-1)*char_height;
232
 
                  x = 1 + 4*char_width;
233
 
                  @set_cursor y x;
234
 
                  print (char) ' ';
235
 
                  #Ifnot;
236
 
                  @set_cursor count 6;
237
 
                  #Endif;
238
 
                  print (name) obj;
239
 
                  count++;
240
 
              }
241
 
              j++;
242
 
          }
243
 
          bottom_line = count - 1;
244
 
          oldline = 0;
245
 
 
246
 
          for(::)
247
 
          {   !   Move or create the > cursor:
248
 
 
249
 
              if (line~=oldline)
250
 
              {   #Iftrue #version_number == 6;
251
 
                  x = 1 + 4*char_width;
252
 
                  count = top_line; j = 0;
253
 
                  objectloop (obj in self && obj ofclass Option)
254
 
                  {   if (j >= top_option && j < (top_option + screen_height))
255
 
                      {   if (j - top_option + top_line == oldline or line)
256
 
                          {   if (j - top_option + top_line == line)
257
 
                                  style reverse;
258
 
                              y = 1 + (count-1)*char_height;
259
 
                              @set_cursor y x;
260
 
                              print (char) ' ', (name) obj, (char) ' ';
261
 
                              style roman;
262
 
                          }
263
 
                          count++;
264
 
                      }
265
 
                      j++;
266
 
                  }
267
 
                  #Ifnot;
268
 
                  if (oldline~=0) { @set_cursor oldline 4; print " "; }
269
 
                  @set_cursor line 4; print ">";
270
 
                  #Endif;
271
 
              }
272
 
              oldline = line;
273
 
 
274
 
              @read_char 1 -> pkey;
275
 
              
276
 
              if (pkey == 253 or 254)
277
 
              {   !   Mouse click:
278
 
                  x = (0-->27-->1 - 1) / char_width + 1;
279
 
                  y = (0-->27-->2 - 1) / char_height + 1;
280
 
                  if (y >= top_line && y <= bottom_line)
281
 
                  {   line = y;
282
 
                      if (pkey == 253)
283
 
                         pkey = 13;
284
 
                      
285
 
                  }
286
 
                  else if (y == 2)
287
 
                  {   if (x <= screen_width / 2)
288
 
                          pkey = 130;
289
 
                      else
290
 
                          pkey = 129;
291
 
                  }
292
 
                  else if (y == 3)
293
 
                  {   if (x <= screen_width / 2)
294
 
                          pkey = 13;
295
 
                      else
296
 
                          pkey = 27;
297
 
                  }
298
 
                  else
299
 
                      @sound_effect 1;
300
 
              }
301
 
 
302
 
              if (pkey == NKEY1__KY or NKEY2__KY or 130)
303
 
              {   !   Cursor down:
304
 
                  line++;
305
 
                  if (line > bottom_line)
306
 
                  {   line = top_line;
307
 
                      if (pages > 1)
308
 
                      {   if (page == pages) page = 1; else page++;
309
 
                          jump ReDisplay;
310
 
                      }
311
 
                  }    
312
 
                  continue;
313
 
              }
314
 
 
315
 
              if (pkey == PKEY1__KY or PKEY2__KY or 129)
316
 
              {   !   Cursor up:
317
 
                  line--;
318
 
                  if (line < top_line)
319
 
                  {   line = bottom_line;
320
 
                      if (pages > 1)
321
 
                      {   if (page == 1)
322
 
                          {   page = pages;
323
 
                              line = top_line
324
 
                                     + (options % screen_height) - 1;
325
 
                          }
326
 
                          else
327
 
                          {   page--; line = top_line + screen_height - 1;
328
 
                          }
329
 
                          jump ReDisplay;
330
 
                      }
331
 
                  }    
332
 
                  continue;
333
 
              }
334
 
 
335
 
              if (pkey==QKEY1__KY or QKEY2__KY or 27 or 131) break;
336
 
 
337
 
              if (pkey==10 or 13 or 132)
338
 
              {   count = 0;
339
 
                  objectloop (obj in self && obj ofclass Option)
340
 
                  {   if (count == top_option + line - top_line) break;
341
 
                      count++;
342
 
                  }
343
 
 
344
 
                  switch(obj.select())
345
 
                  {   2: jump ReDisplay;
346
 
                      3: jump ExitMenu;
347
 
                  }
348
 
 
349
 
                  #ifdef LIB_PRE_63;
350
 
                  print "[Please press SPACE to continue.]^";
351
 
                  #ifnot;
352
 
                  L__M(##Miscellany, 53);
353
 
                  #endif;
354
 
                  @read_char 1 -> pkey;
355
 
                  jump ReDisplay;
356
 
              }
357
 
          }
358
 
 
359
 
          .ExitMenu;
360
 
 
361
 
          if (sender ofclass Option) return 2;
362
 
 
363
 
          #Iftrue #version_number==6;
364
 
          @set_font 1 -> x;
365
 
          #Ifnot;
366
 
          font on;
367
 
          #Endif;
368
 
          @set_cursor 1 1;
369
 
          @erase_window -1; @set_window 0;
370
 
          #Iftrue #version_number==6;
371
 
          @set_cursor -2;
372
 
          #Endif;
373
 
          new_line; new_line; new_line;
374
 
          if (deadflag==0) <<Look>>;
375
 
          return 2;
376
 
      ];
377
 
 
378
 
Class SwitchOption class Option
379
 
  with short_name
380
 
       [;  print (object) self, " ";
381
 
           if (self has on) print "(on)"; else print "(off)";
382
 
           rtrue;
383
 
       ],
384
 
       select
385
 
       [;  if (self has on) give self ~on; else give self on;
386
 
           return 2;
387
 
       ];
388
 
 
389
 
! ------------------------------------------------------------------------