1 /* Nitfol - z-machine interpreter using Glk for output.
2 Copyright (C) 1999 Evin Robertson
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
18 The author can be reached at nitfol@deja.com
23 typedef enum { z6_text, z6_picture, z6_rectangle } z6_type;
26 struct graph_piece *next;
27 struct graph_piece *prev;
36 int color; /* -1 means erase to background color */
39 static struct graph_piece *older_pieces;
42 static zwinid lower_win;
44 static zword window_props[8][16];
45 static int current_window;
47 typedef enum { w_y_coord, w_x_coord, w_y_size, w_x_size,
48 w_y_cursor, w_x_cursor, w_l_margin, w_r_margin,
49 w_nl_routine, w_int_count, w_text_style, w_colour_data,
50 w_font_number, w_font_size, w_attributes, w_line_count
53 typedef enum { wa_wrapping, wa_scrolling, wa_transcript, wa_buffered } win_attributes;
56 static int get_window_num(int arg)
58 if(numoperands <= arg || operand[arg] == neg(3))
59 return current_window;
60 if(operand[arg] > 7) {
61 n_show_error(E_OUTPUT, "illegal window number", operand[arg]);
62 return current_window;
67 static BOOL check_window_prop(int prop_num)
70 n_show_error(E_OUTPUT, "illegal wind_prop number", prop_num);
77 int is_in_bounds(glui32 x1, glui32 y1, glui32 width1, glui32 height1,
78 glui32 x2, glui32 y2, glui32 width2, glui32 height2)
80 return (x1 >= x2 && y1 >= y2 &&
81 x1 + width1 <= x2 + width2 && y1 + height1 <= y2 + height2);
85 static void add_piece(struct graph_piece new_piece)
87 struct graph_piece *p, *q;
91 if(new_piece.x + new_piece.width >
92 window_props[current_window][w_x_coord] +
93 window_props[current_window][w_x_size]) {
94 new_piece.width = window_props[current_window][w_x_coord] +
95 window_props[current_window][w_x_size] -
99 if(new_piece.y + new_piece.height >
100 window_props[current_window][w_y_coord] +
101 window_props[current_window][w_y_size]) {
102 new_piece.height = window_props[current_window][w_y_coord] +
103 window_props[current_window][w_y_size] -
110 if(is_in_bounds(p->x, p->y, p->width, p->height,
111 new_piece.x, new_piece.y,
112 new_piece.width, new_piece.height)) {
118 LEremove(older_pieces);
128 LEadd(older_pieces, new_piece);
135 void v6_main_window_is(zwinid win)
141 void op_set_window6(void)
143 int win = get_window_num(0);
144 current_window = win;
148 void op_set_margins(void)
150 int win = get_window_num(2);
153 n_show_debug(E_OUTPUT, "set_margins w=", operand[2]);
154 n_show_debug(E_OUTPUT, "set_margins l=", operand[0]);
155 n_show_debug(E_OUTPUT, "set_margins r=", operand[1]);
158 window_props[win][w_l_margin] = operand[0];
159 window_props[win][w_r_margin] = operand[1];
161 /* FIXME: move cursor */
165 void op_move_window(void)
167 int win = get_window_num(0);
170 n_show_debug(E_OUTPUT, "move_window w=", operand[0]);
171 n_show_debug(E_OUTPUT, "move_window y=", operand[1]);
172 n_show_debug(E_OUTPUT, "move_window x=", operand[2]);
175 window_props[win][w_y_coord] = operand[1];
176 window_props[win][w_x_coord] = operand[2];
180 void op_window_size(void)
182 int win = get_window_num(0);
185 n_show_debug(E_OUTPUT, "window_size w=", operand[0]);
186 n_show_debug(E_OUTPUT, "window_size y=", operand[1]);
187 n_show_debug(E_OUTPUT, "window_size x=", operand[2]);
190 window_props[win][w_y_size] = operand[1];
191 window_props[win][w_x_size] = operand[2];
195 void op_window_style(void)
198 int win = get_window_num(0);
203 attr = window_props[win][w_attributes];
205 case 0: attr = operand[1]; break;
206 case 1: attr |= operand[1]; break;
207 case 2: attr &= ~(operand[1]); break;
208 case 3: attr ^= operand[1]; break;
209 default: n_show_error(E_OUTPUT, "invalid flag operation", operand[2]);
212 window_props[win][w_attributes] = attr;
216 void op_get_wind_prop(void)
218 int win = get_window_num(0);
220 if(!check_window_prop(operand[1])) {
224 mop_store_result(window_props[win][operand[1]]);
228 void op_put_wind_prop(void)
230 int win = get_window_num(0);
232 if(!check_window_prop(operand[1])) {
236 window_props[win][operand[1]] = operand[2];
240 void op_scroll_window(void)
246 void op_read_mouse(void)
252 void op_mouse_window(void)
258 void op_print_form(void)
264 void op_make_menu(void)
270 void op_picture_table(void)
272 ; /* Glk contains no image prefetching facilities, so nothing to do here */
276 void op_draw_picture(void)
278 struct graph_piece new_piece;
279 glui32 width, height;
281 z_put_char(lower_win, 13); /* Work around a bug in xglk */
282 draw_intext_picture(lower_win, operand[0], imagealign_MarginLeft);
287 new_piece.window = current_window;
288 new_piece.x = operand[2] + window_props[current_window][w_x_coord];
289 new_piece.y = operand[1] + window_props[current_window][w_y_coord];
291 wrap_glk_image_get_info(operand[0], &width, &height);
293 new_piece.width = width;
294 new_piece.height = height;
296 new_piece.type = z6_picture;
297 new_piece.picnum = operand[0];
299 add_piece(new_piece);
305 void op_picture_data(void)
307 if(glk_gestalt(gestalt_Graphics, 0)) {
308 glui32 width, height;
310 if(operand[0] == 0) {
311 LOWORDwrite(operand[1], imagecount);
312 LOWORDwrite(operand[1], 42); /* FIXME: where do I get picture release? */
314 else if(wrap_glk_image_get_info(operand[0], &width, &height)) {
315 LOWORDwrite(operand[1], height);
316 LOWORDwrite(operand[1] + ZWORD_SIZE, width);
325 void op_erase_picture(void)
327 struct graph_piece new_piece;
328 glui32 width, height;
330 new_piece.window = current_window;
331 new_piece.x = operand[2] + window_props[current_window][w_x_coord];
332 new_piece.y = operand[1] + window_props[current_window][w_y_coord];
334 wrap_glk_image_get_info(operand[0], &width, &height);
336 new_piece.width = width;
337 new_piece.height = height;
339 new_piece.type = z6_rectangle;
340 new_piece.color = -1;
342 add_piece(new_piece);