1 /*
2  *  A Z-Machine
3  *  Copyright (C) 2000 Andrew Hunter
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 /*
21  * Some functions to do with menus
22  */
23 
24 #include "../config.h"
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <dirent.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <string.h>
34 
35 #include "zmachine.h"
36 #include "menu.h"
37 #include "display.h"
38 #include "rc.h"
39 #include "file.h"
40 
41 #if WINDOW_SYSTEM != 2
42 
center(char * text,int columns)43 static void center(char* text, int columns)
44 {
45   display_set_cursor((columns>>1)-(strlen(text)>>1), display_get_cur_y());
46   display_prints_c(text);
47 }
48 
49 struct game_struct {
50   char* filename;
51   char* storyname;
52 };
53 
game_compare(const void * a,const void * b)54 static int game_compare(const void* a, const void* b)
55 {
56   const struct game_struct *ga, *gb;
57 
58   ga = a; gb = b;
59 
60   return strcmp(ga->storyname, gb->storyname);
61 }
62 
menu_get_story(void)63 char* menu_get_story(void)
64 {
65   char*     dirname;
66   DIR*      gamedir;
67   ZDisplay* di;
68   int       n_games = 0;
69   int       x;
70   struct game_struct* game = NULL;
71   struct dirent* dent;
72   int       selection, start, end, height;
73   char      format[10];
74   int       read;
75 
76   di = display_get_info();
77 
78   display_set_window(0);
79   display_split(di->height, 1);
80   display_set_window(1);
81   display_set_colour(7, 4);
82   display_erase_window();
83 
84   rc_set_game("xxxxxx", 65535, 65535);
85 
86   dirname = rc_get_gamedir();
87   gamedir = opendir(dirname);
88 
89   if (gamedir == NULL)
90     zmachine_fatal("Unable to find game directory '%s'", dirname);
91 
92   chdir(dirname);
93 
94   /* Read the files in this directory, and work out their names */
95   while ((dent=readdir(gamedir)))
96     {
97       int len;
98 
99       len = strlen(dent->d_name);
100 
101       if (len > 2)
102 	{
103 	  if (dent->d_name[len-2] == 'z' && dent->d_name[len-3]=='.')
104 	    {
105 	      ZFile* file;
106 
107 	      file = open_file(dent->d_name);
108 
109 	      if (file)
110 		{
111 		  int x,len;
112 		  ZByte* header;
113 
114 		  header = read_block(file, 0, 64);
115 
116 		  game =
117 		    realloc(game, sizeof(struct game_struct)*(n_games+1));
118 		  game[n_games].filename =
119 		    malloc(sizeof(char)*(strlen(dent->d_name)+1));
120 		  strcpy(game[n_games].filename, dent->d_name);
121 
122 		  game[n_games].storyname =
123 		    rc_get_game_name((char*)(header + ZH_serial),
124 				     GetWord(header, ZH_release));
125 
126 		  if (game[n_games].storyname == NULL)
127 		    {
128 		      len = strlen(game[n_games].filename);
129 
130 		      game[n_games].storyname = malloc(len+1);
131 		      for (x=0; x<len-3; x++)
132 			{
133 			  game[n_games].storyname[x] =
134 			    game[n_games].filename[x];
135 			}
136 		      game[n_games].storyname[x] = 0;
137 		    }
138 
139 		  free(header);
140 
141 		  n_games++;
142 
143 		  close_file(file);
144 		}
145 	    }
146 	}
147     }
148 
149   closedir(gamedir);
150 
151   qsort(game, n_games, sizeof(struct game_struct), game_compare);
152 
153   selection = 0;
154   height = (di->lines-6)&~1;
155   sprintf(format, " %%.%is ", di->columns-6);
156 
157   if (n_games < 1)
158     zmachine_fatal("No game file available in %s", dirname);
159 
160   do
161     {
162       start = selection - (height>>1);
163       end = selection + (height>>1);
164 
165       display_erase_window();
166       display_set_cursor(0,1);
167       display_set_font(3);
168       center("Zoom " VERSION " Menu of games", di->columns);
169       display_set_cursor(0,di->lines-2);
170       center("Use the UP and DOWN arrow keys to select a game", di->columns);
171       display_set_cursor(0,di->lines-1);
172       center("Press RETURN to load the selected game", di->columns);
173 
174       if (start < 0)
175 	{
176 	  end -= start;
177 	  start = 0;
178 	}
179       if (end > n_games)
180 	{
181 	  end = n_games;
182 	  start = end - height;
183 	  if (start < 0)
184 	    start = 0;
185 	}
186 
187       for (x=0; x<(end-start); x++)
188 	{
189 	  display_set_cursor(2, 3+x);
190 	  display_set_cursor(2, 3+x);
191 	  display_printf(format, game[x+start].storyname);
192 	}
193       display_set_cursor(2, 3+(selection-start));
194       display_set_colour(0, 3);
195       display_printf(format, game[selection].storyname);
196       display_set_colour(7, 4);
197 
198       read = display_readchar(0);
199 
200       switch (read)
201 	{
202 	case 'Q':
203 	case 'q':
204 	  display_exit(1);
205 
206 	case 129:
207 	  selection--;
208 	  if (selection<0)
209 	    selection = 0;
210 	  break;
211 
212 	case 130:
213 	  selection++;
214 	  if (selection>=n_games)
215 	    selection = n_games-1;
216 	  break;
217 	}
218     }
219   while (read != 13 && read != 10);
220 
221   return game[selection].filename;
222 }
223 
224 #else
225 
226 #include <windows.h>
227 #include <commdlg.h>
228 #include "windisplay.h"
229 
menu_get_story(void)230 char* menu_get_story(void)
231 {
232   OPENFILENAME fn;
233   static char filter[] = "Z-Code files (*.z[34578])\0*.z3;*.z4;*.z5;*.z7;*.z8\0All files (*.*)\0*.*\0\0";
234   static char fname[256];
235 
236   if (rc_get_gamedir() == NULL)
237     zmachine_fatal("No default game directory set");
238 
239   strcpy(fname, "");
240   fn.lStructSize       = sizeof(fn);
241   fn.hwndOwner         = mainwin;
242   fn.hInstance         = NULL;
243   fn.lpstrFilter       = filter;
244   fn.lpstrCustomFilter = NULL;
245   fn.nFilterIndex      = 1;
246   fn.lpstrFile         = fname;
247   fn.nMaxFile          = 256;
248   fn.lpstrFileTitle    = NULL;
249   fn.lpstrInitialDir   = rc_get_gamedir();
250   fn.lpstrTitle        = NULL;
251   fn.nFileOffset       = 0;
252   fn.nFileExtension    = 0;
253   fn.Flags             = OFN_HIDEREADONLY|OFN_FILEMUSTEXIST;
254   fn.lpstrDefExt       = "qut";
255 
256   if (GetOpenFileName(&fn))
257     {
258       return fname;
259     }
260   else
261     {
262       zmachine_fatal("Unable to open story file");
263     }
264 
265   return NULL;
266 }
267 
268 #endif
269