1 /* redirect.c - Output redirection to Z-machine memory
2  *	Copyright (c) 1995-1997 Stefan Jokisch
3  *
4  * This file is part of Frotz.
5  *
6  * Frotz is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Frotz is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "frotz.h"
22 
23 #define MAX_NESTING 16
24 
25 extern zword get_max_width(zword);
26 
27 static int depth = -1;
28 
29 static struct {
30 	zword xsize;
31 	zword table;
32 	zword width;
33 	zword total;
34 } redirect[MAX_NESTING];
35 
36 
37 /*
38  * memory_open
39  *
40  * Begin output redirection to the memory of the Z-machine.
41  *
42  */
memory_open(zword table,zword xsize,bool buffering)43 void memory_open(zword table, zword xsize, bool buffering)
44 {
45 	if (++depth < MAX_NESTING) {
46 		if (!buffering)
47 			xsize = 0xffff;
48 		else {
49 			if ((short)xsize >= 0)
50 				xsize = get_max_width(xsize);
51 			else
52 				xsize = -xsize;
53 		}
54 		storew(table, 0);
55 		redirect[depth].table = table;
56 		redirect[depth].width = 0;
57 		redirect[depth].total = 0;
58 		redirect[depth].xsize = xsize;
59 		ostream_memory = TRUE;
60 	} else
61 		runtime_error(ERR_STR3_NESTING);
62 } /* memory_open */
63 
64 
65 /*
66  * memory_new_line
67  *
68  * Redirect a newline to the memory of the Z-machine.
69  *
70  */
memory_new_line(void)71 void memory_new_line(void)
72 {
73 	zword size;
74 	zword addr;
75 
76 	redirect[depth].total += redirect[depth].width;
77 	redirect[depth].width = 0;
78 
79 	addr = redirect[depth].table;
80 
81 	LOW_WORD(addr, size)
82 	addr += 2;
83 
84 	if (redirect[depth].xsize != 0xffff) {
85 		redirect[depth].table = addr + size;
86 		size = 0;
87 
88 	} else
89 		storeb((zword) (addr + (size++)), 13);
90 
91 	storew(redirect[depth].table, size);
92 } /* memory_new_line */
93 
94 
95 /*
96  * memory_word
97  *
98  * Redirect a string of characters to the memory of the Z-machine.
99  *
100  */
memory_word(const zchar * s)101 void memory_word(const zchar * s)
102 {
103 	zword size;
104 	zword addr;
105 	zchar c;
106 
107 	if (z_header.version == V6) {
108 		int width = os_string_width(s);
109 
110 		if (redirect[depth].xsize != 0xffff)
111 			if (redirect[depth].width + width >
112 			    redirect[depth].xsize) {
113 				if (*s == ' ' || *s == ZC_INDENT ||
114 				    *s == ZC_GAP)
115 					width = os_string_width(++s);
116 				memory_new_line();
117 			}
118 		redirect[depth].width += width;
119 	}
120 	addr = redirect[depth].table;
121 	LOW_WORD(addr, size)
122 	addr += 2;
123 
124 	while ((c = *s++) != 0)
125 		storeb((zword) (addr + (size++)), translate_to_zscii(c));
126 
127 	storew(redirect[depth].table, size);
128 } /* memory_word */
129 
130 
131 /*
132  * memory_close
133  *
134  * End of output redirection.
135  *
136  */
memory_close(void)137 void memory_close(void)
138 {
139 	if (depth >= 0) {
140 		if (redirect[depth].xsize != 0xffff)
141 			memory_new_line();
142 		if (z_header.version == V6) {
143 
144 			z_header.line_width = (redirect[depth].xsize != 0xffff) ?
145 			    redirect[depth].total : redirect[depth].width;
146 
147 			SET_WORD(H_LINE_WIDTH, z_header.line_width)
148 		}
149 		if (depth == 0)
150 			ostream_memory = FALSE;
151 		depth--;
152 	}
153 } /* memory_close */
154