3 #include <libchimara/glk.h>
5 #define SPACE_FACTOR 1.8
7 void center_text(winid_t win, char *text)
10 glk_window_get_size(win, &width, &height);
13 glk_window_clear(win);
15 if(glk_window_get_type(win) == wintype_TextGrid) {
16 glk_window_move_cursor(win, width / 2 - strlen(text) / 2, height / 2);
18 } else if(glk_window_get_type(win) == wintype_TextBuffer) {
20 for(count = 0; count < height / 2; count++)
23 count < (int)(SPACE_FACTOR * (width / 2 - strlen(text) / 2));
30 void print_two_rows(winid_t win)
33 glk_window_get_size(win, &width, &height);
36 glk_window_clear(win);
38 glui32 x = width / 2 - 3;
39 glui32 y = (height - 1) / 2;
45 glk_window_move_cursor(win, x, y);
46 glk_put_string("C: 2");
47 glk_window_move_cursor(win, x + 3, y + 1);
48 glk_put_string("rows");
51 void wait_for_key(winid_t win)
54 glk_request_char_event(win);
57 while(ev.type != evtype_CharInput);
62 winid_t win_a = NULL, win_b = NULL, win_c = NULL, win_d = NULL;
64 fprintf(stderr, "TEST CASES FROM GLK SPEC\n\n"
65 "(Press a key in window A to continue each time)\n\n"
66 "Say you do two splits, each a 50-50 percentage split. You start\n"
67 "with the original window A, and split that into A and B; then\n"
68 "you split B into B and C.\n\n");
70 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
71 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
72 50, wintype_TextBuffer, 0);
73 win_c = glk_window_open(win_b, winmethod_Proportional | winmethod_Below,
74 50, wintype_TextBuffer, 0);
75 if(!win_a || !win_b || !win_c)
77 center_text(win_a, "A");
78 center_text(win_b, "B");
79 center_text(win_c, "C");
82 glk_window_close(glk_window_get_root(), NULL);
84 fprintf(stderr, "Or, you could split A into A and B, and then split A\n"
85 "again into A and C.\n\n");
87 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
88 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
89 50, wintype_TextBuffer, 0);
90 win_c = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
91 50, wintype_TextBuffer, 0);
92 if(!win_a || !win_b || !win_c)
94 center_text(win_a, "A");
95 center_text(win_b, "B");
96 center_text(win_c, "C");
99 glk_window_close(glk_window_get_root(), NULL);
101 fprintf(stderr, "Here are more ways to perform the first example; all of\n"
102 "them have the same tree structure, but look different on the\n"
103 "screen. Here, we turn the second split (B into B/C) upside down;\n"
104 "we put the new window (C) above the old window (B).\n\n");
106 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
107 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
108 50, wintype_TextBuffer, 0);
109 win_c = glk_window_open(win_b, winmethod_Proportional | winmethod_Above,
110 50, wintype_TextBuffer, 0);
111 if(!win_a || !win_b || !win_c)
113 center_text(win_a, "A");
114 center_text(win_b, "B");
115 center_text(win_c, "C");
118 glk_window_close(glk_window_get_root(), NULL);
120 fprintf(stderr, "Here, we mess with the percentages. The first split (A\n"
121 "into A/B) is a 25-75 split, which makes B three times the size\n"
122 "of A. The second (B into B/C) is a 33-66 split, which makes C\n"
123 "twice the size of B. This looks rather like the second example,\n"
124 "but has a different internal structure.\n\n");
126 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
127 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
128 75, wintype_TextBuffer, 0);
129 win_c = glk_window_open(win_b, winmethod_Proportional | winmethod_Below,
130 67, wintype_TextBuffer, 0);
131 if(!win_a || !win_b || !win_c)
133 center_text(win_a, "A");
134 center_text(win_b, "B");
135 center_text(win_c, "C");
138 glk_window_close(glk_window_get_root(), NULL);
140 fprintf(stderr, "Here, the second split (B into B/C) is vertical instead\n"
141 "of horizontal, with the new window (C) on the left of the old\n"
144 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
145 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
146 50, wintype_TextBuffer, 0);
147 win_c = glk_window_open(win_b, winmethod_Proportional | winmethod_Left,
148 50, wintype_TextBuffer, 0);
149 if(!win_a || !win_b || !win_c)
151 center_text(win_a, "A");
152 center_text(win_b, "B");
153 center_text(win_c, "C");
156 glk_window_close(glk_window_get_root(), NULL);
158 fprintf(stderr, "In the following two-split process, you can see that\n"
159 "when a window is split, it is replaced by a new pair window, and\n"
160 "moves down to become one of its two children.\n\n");
162 if(!(win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0)))
164 center_text(win_a, "A");
167 if(!(win_b = glk_window_open(win_a,
168 winmethod_Proportional | winmethod_Below,
169 50, wintype_TextBuffer, 0)))
171 center_text(win_a, "A");
172 center_text(win_b, "B");
175 if(!(win_c = glk_window_open(win_b, winmethod_Proportional | winmethod_Left,
176 50, wintype_TextBuffer, 0)))
178 center_text(win_a, "A");
179 center_text(win_b, "B");
180 center_text(win_c, "C");
183 glk_window_close(glk_window_get_root(), NULL);
185 fprintf(stderr, "What happens when there is a conflict? The rules are\n"
186 "simple. Size control always flows down the tree, and the player\n"
187 "is at the top. Let's bring out an example: first we split A into\n"
188 "A and B, with a 50%% proportional split. Then we split A into A\n"
189 "and C, with C above, being a text grid window, and C gets a\n"
190 "fixed size of two rows (as measured in its own font size). A\n"
191 "gets whatever remains of the 50%% it had before.\n\n");
193 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
194 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below,
195 50, wintype_TextBuffer, 0);
196 win_c = glk_window_open(win_a, winmethod_Fixed | winmethod_Above,
197 2, wintype_TextGrid, 0);
198 if(!win_a || !win_b || !win_c)
200 center_text(win_a, "A");
201 center_text(win_b, "B: 50%");
202 print_two_rows(win_c);
205 fprintf(stderr, "(Stage 1) Now the player stretches the window\n"
210 fprintf(stderr, "(Stage 2) Then the user maliciously starts squeezing the\n"
211 "window down, in stages.\n\n");
213 center_text(win_a, "A");
214 center_text(win_b, "B: 50%");
215 print_two_rows(win_c);
218 fprintf(stderr, "(Stage 3) The logic remains the same. At stage 3,\n"
219 "there's no room left for A, so it winds up with zero height.\n"
220 "Nothing displayed in A will be visible.\n\n");
222 center_text(win_a, "A");
223 center_text(win_b, "B");
224 center_text(win_c, "C");
227 fprintf(stderr, "(Stage 4) At stage 4, there isn't even room in the upper\n"
228 "50%% to give C its two rows; so it only gets one.\n\n");
230 center_text(win_a, "A");
231 center_text(win_b, "B");
232 center_text(win_c, "C");
235 fprintf(stderr, "(Stage 5) Finally, C is squashed out of existence as\n"
238 center_text(win_a, "A");
239 center_text(win_b, "B");
242 glk_window_close(glk_window_get_root(), NULL);
244 fprintf(stderr, "What happens when you split a fixed-size window? The\n"
245 "resulting pair window retains the same size constraint as the\n"
246 "original window that was split. The key window for the original\n"
247 "split is still the key window for that split, even though it's\n"
248 "now a grandchild instead of a child.\n\n");
250 if(!(win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0)))
252 center_text(win_a, "A");
255 fprintf(stderr, "After the first split, the new pair window (O1, which\n"
256 "covers the whole screen) knows that its first child (A) is above\n"
257 "the second, and gets 50%% of its own area. (A is the key window\n"
258 "for this split, but a proportional split doesn't care about key\n"
261 if(!(win_b = glk_window_open(win_a,
262 winmethod_Proportional | winmethod_Below,
263 50, wintype_TextBuffer, 0)))
265 center_text(win_a, "A: 50%");
266 center_text(win_b, "B");
269 fprintf(stderr, "After the second split, all this remains true; O1 knows\n"
270 "that its first child gets 50%% of its space, and A is O1's key\n"
271 "window. But now O1's first child is O2 instead of A. The newer\n"
272 "pair window (O2) knows that its first child (C) is above the\n"
273 "second, and gets a fixed size of two rows. (As measured in C's\n"
274 "font, because C is O2's key window.)\n\n");
276 if(!(win_c = glk_window_open(win_a, winmethod_Fixed | winmethod_Above, 2,
277 wintype_TextGrid, 0)))
279 center_text(win_a, "A");
280 center_text(win_b, "B");
281 print_two_rows(win_c);
284 fprintf(stderr, "If we split C, now, the resulting pair will still be two\n"
285 "C-font rows high -- that is, tall enough for two lines of\n"
286 "whatever font C displays. For the sake of example, we'll do this\n"
289 if(!(win_d = glk_window_open(win_c,
290 winmethod_Proportional | winmethod_Right,
291 50, wintype_TextBuffer, 0)))
293 center_text(win_a, "A");
294 center_text(win_b, "B");
295 center_text(win_c, "C");
296 center_text(win_d, "D");
299 fprintf(stderr, "When you close a window (and it is not the root window),\n"
300 "the other window in its pair takes over all the freed-up area.\n"
301 "Let's close D, in the current example:\n\n");
303 glk_window_close(win_d, NULL);
304 center_text(win_a, "A");
305 center_text(win_b, "B");
306 center_text(win_c, "C");
309 fprintf(stderr, "But what if we had closed C instead of D? We would have\n"
312 glk_window_close(glk_window_get_root(), NULL);
313 win_a = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
314 win_b = glk_window_open(win_a, winmethod_Proportional | winmethod_Below, 50,
315 wintype_TextBuffer, 0);
316 win_c = glk_window_open(win_a, winmethod_Fixed | winmethod_Above, 2,
317 wintype_TextGrid, 0);
318 win_d = glk_window_open(win_c, winmethod_Proportional | winmethod_Right, 50,
319 wintype_TextBuffer, 0);
320 glk_window_close(win_c, NULL);
321 center_text(win_a, "A");
322 center_text(win_b, "B");
323 center_text(win_d, "D");
326 fprintf(stderr, "Consider the example above, where D had collapsed to\n"
327 "zero height. Say D was a text buffer window. You could make a\n"
328 "more useful layout:\n\n");
329 winid_t o2 = glk_window_get_parent(win_d);
330 glk_window_set_arrangement(o2, winmethod_Above | winmethod_Fixed, 3, win_d);
331 center_text(win_a, "A");
332 center_text(win_b, "B");
333 center_text(win_d, "D");
336 fprintf(stderr, "If you later wanted to expand D to five rows:\n\n");
337 glk_window_set_arrangement(o2, winmethod_Above | winmethod_Fixed, 5, NULL);
338 center_text(win_a, "A");
339 center_text(win_b, "B");
340 center_text(win_d, "D");
343 fprintf(stderr, "This changes the constraint to be on the lower child of\n"
344 "O2, which is A. The key window is still D; so A would then be\n"
345 "three rows high as measured in D's font, and D would get the\n"
346 "rest of O2's space. That may not be what you want.\n\n");
347 glk_window_set_arrangement(o2, winmethod_Below | winmethod_Fixed, 3, NULL);
348 center_text(win_a, "A");
349 center_text(win_b, "B");
350 center_text(win_d, "D");
353 fprintf(stderr, "To set A to be three rows high as measured in A's font,\n"
354 "you would do:\n\n");
355 glk_window_set_arrangement(o2, winmethod_Below | winmethod_Fixed, 3, win_a);
356 center_text(win_a, "A");
357 center_text(win_b, "B");
358 center_text(win_d, "D");
361 fprintf(stderr, "Or you could change O2 to a proportional split:\n\n");
362 glk_window_set_arrangement(o2, winmethod_Below | winmethod_Proportional, 30,
364 center_text(win_a, "A");
365 center_text(win_b, "B");
366 center_text(win_d, "D");
369 fprintf(stderr, "Or:\n\n");
370 glk_window_set_arrangement(o2, winmethod_Above | winmethod_Proportional, 70,
372 center_text(win_a, "A");
373 center_text(win_b, "B");
374 center_text(win_d, "D");
377 glk_window_close(win_d, NULL);
378 glk_window_close(win_b, NULL);
379 glk_window_clear(win_a);
380 glk_set_window(win_a);
381 glk_put_string("That's all, folks...");