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