home · contact · privacy
Simplified window configuration view.
[plomrogue] / src / wincontrol.c
1 /* wincontrol.c */
2
3 #include "wincontrol.h"
4 #include <stdlib.h> /* for free() */
5 #include <string.h> /* for strlen() */
6 #include <stdint.h> /* for uint8_t, uint16_t */
7 #include <stdio.h> /* for fwrite() */
8 #include <unistd.h> /* for access(), unlink() */
9 #include "windows.h" /* for suspend_win(), append_win(), reset_pad_offset(),
10                       * resize_active_win(), init_win(), free_win(),
11                       * structs Win, WinMeta
12                       */
13 #include "yx_uint16.h" /* for yx_uint16 struct */
14 #include "main.h" /* for Wins struct */
15 #include "readwrite.h" /* for get_linemax(), try_fopen(), try_fclose(),
16                         * try_fgets(), try_fclose_unlink_rename()
17                         */
18 #include "rexit.h" /* for exit_err() */
19 #include "main.h" /* for World, Wins structs */
20 #include "draw_wins.h" /* for draw_keys_win(), draw_info_win(), draw_log_win(),
21                         * draw_map_win
22                         */
23 #include "misc.h" /* for try_malloc() */
24
25
26
27 /* Return string "prefix" + "id"; malloc()'s string, remember to call free()! */
28 static char * string_prefixed_id(struct World * world, char * prefix, char id);
29
30
31
32 /* Create Winconf, initialize ->view/height_type/width_type to 0, ->id to "id"
33  * and ->draw to f.
34  */
35 static void create_winconf(char id, struct WinConf * wcp,
36                            void (* f) (struct Win *));
37
38 /* Initialize Winconf of "id" from appropriate config file.*/
39 static void init_winconf_from_file(struct World * world, char id);
40
41 /* Wrapper around init_win() called with values from Winconf of "id". */
42 static void init_win_from_winconf(struct World * world, char id);
43
44 /* Save title, size of window identified by "id" to its configuration file. */
45 static void save_win_config(struct World * world, char id);
46
47
48
49 /* Write size of a window to its WinConf, as positive or negative values
50  * (dependent on state ofWinConf->height_type / WinConf->width_type).
51  */
52 static void set_winconf(struct World * world, char id);
53
54
55
56 /* Get WinConf by "id"; get id of WinConf mothering "win". */
57 static struct WinConf * get_winconf_by_id(struct World * world, char id);
58 static char get_id_by_win(struct World * world, struct Win * win);
59
60
61
62 static char * string_prefixed_id(struct World * world, char * prefix, char id)
63 {
64     uint8_t size = strlen(prefix) + 2;
65     char * path = try_malloc(size, world, "string_prefixed_id()");
66     sprintf(path, "%s_", prefix);
67     path[size - 2] = id;
68     return path;
69 }
70
71
72
73 static void create_winconf(char id, struct WinConf * wcp,
74                            void (* f) (struct Win *))
75 {
76     wcp->id = id;
77     wcp->draw = f;
78     wcp->view = 0;
79     wcp->height_type = 0;
80     wcp->width_type = 0;
81 }
82
83
84
85 static void init_winconf_from_file(struct World * world, char id)
86 {
87     char * f_name = "init_winconf_from_file()";
88
89     char * path = string_prefixed_id(world, "config/windows/Win_", id);
90     FILE * file = try_fopen(path, "r", world, f_name);
91     free(path);
92     uint16_t linemax = get_linemax(file, world, f_name);
93     char line[linemax + 1];
94
95     struct WinConf * winconf = get_winconf_by_id(world, id);
96     try_fgets(line, linemax + 1, file, world, f_name);
97     winconf->title = try_malloc(strlen(line), world, f_name);
98     memcpy(winconf->title, line, strlen(line) - 1); /* Eliminate newline char */
99     winconf->title[strlen(line) - 1] = '\0';        /* char at end of string. */
100     try_fgets(line, linemax + 1, file, world, f_name);
101     winconf->height = atoi(line);
102     if (0 >= winconf->height)
103     {
104         winconf->height_type = 1;
105     }
106     try_fgets(line, linemax + 1, file, world, f_name);
107     winconf->width = atoi(line);
108     if (0 >= winconf->width)
109     {
110         winconf->width_type = 1;
111     }
112
113     try_fclose(file, world, f_name);
114 }
115
116
117
118 static void init_win_from_winconf(struct World * world, char id)
119 {
120     char * err = "Trouble in init_win_from_file() with init_win().";
121     struct WinConf * winconf = get_winconf_by_id(world, id);
122     exit_err(init_win(world->wmeta, &winconf->win, winconf->title,
123                       winconf->height, winconf->width, world, winconf->draw),
124              world, err);
125 }
126
127
128
129 extern void save_win_config(struct World * world, char id)
130 {
131     char * f_name = "save_win_config()";
132
133     char * path_tmp = string_prefixed_id(world, "config/windows/Win_tmp_", id);
134     FILE * file = try_fopen(path_tmp, "w", world, f_name);
135
136     struct WinConf * wc = get_winconf_by_id(world, id);
137     uint8_t size = strlen(wc->title) + 2;
138     if (size < 7)
139     {
140         size = 7;
141     }
142     char line[size];
143     sprintf(line, "%s\n", wc->title);
144     fwrite(line, sizeof(char), strlen(line), file);
145     sprintf(line, "%d\n", wc->height);
146     fwrite(line, sizeof(char), strlen(line), file);
147     sprintf(line, "%d\n", wc->width);
148     fwrite(line, sizeof(char), strlen(line), file);
149
150     char * path = string_prefixed_id(world, "config/windows/Win_", id);
151     try_fclose_unlink_rename(file, path_tmp, path, world, f_name);
152     free(path);
153     free(path_tmp);
154 }
155
156
157
158 static void set_winconf(struct World * world, char id)
159 {
160     struct WinConf * wcp = get_winconf_by_id(world, id);
161     if      (0 == wcp->height_type)
162     {
163         wcp->height = wcp->win->frame.size.y;
164     }
165     else if (1 == wcp->height_type)
166     {
167         wcp->height = wcp->win->frame.size.y - world->wmeta->padframe.size.y
168                       + 1;
169     }
170     if      (0 == wcp->width_type)
171     {
172         wcp->width = wcp->win->frame.size.x;
173     }
174     else if (1 == wcp->width_type)
175     {
176         wcp->width = wcp->win->frame.size.x - world->wmeta->padframe.size.x;
177     }
178 }
179
180
181
182 static struct WinConf * get_winconf_by_id(struct World * world, char id)
183 {
184     uint8_t i = 0;
185     while (1)
186     {
187         if (id == world->winconfs[i].id)
188         {
189             return &world->winconfs[i];
190         }
191         i++;
192     }
193 }
194
195
196
197 static char get_id_by_win(struct World * world, struct Win * win)
198 {
199     struct WinConf * wc = get_winconf_by_win(world, win);
200     return wc->id;
201 }
202
203
204
205 extern struct WinConf * get_winconf_by_win(struct World * world,
206                                            struct Win * win)
207 {
208     uint8_t i = 0;
209     while (1)
210     {
211         if (win == world->winconfs[i].win)
212         {
213             return &world->winconfs[i];
214         }
215         i++;
216     }
217 }
218
219
220
221 extern struct Win * get_win_by_id(struct World * world, char id)
222 {
223     struct WinConf * wc = get_winconf_by_id(world, id);
224     return wc->win;
225 }
226
227
228
229 extern void init_winconfs(struct World * world)
230 {
231     char * f_name = "init_winconfs()";
232     struct WinConf * winconfs = try_malloc(4 * sizeof(struct WinConf),
233                                            world, f_name);
234     create_winconf('i', &winconfs[0], draw_info_win);
235     create_winconf('k', &winconfs[1], draw_keys_win);
236     create_winconf('l', &winconfs[2], draw_log_win);
237     create_winconf('m', &winconfs[3], draw_map_win);
238     world->winconfs = winconfs;
239     init_winconf_from_file(world, 'i');
240     init_winconf_from_file(world, 'k');
241     init_winconf_from_file(world, 'l');
242     init_winconf_from_file(world, 'm');
243 }
244
245
246
247 extern void free_winconf(struct World * world, char id)
248 {
249     struct WinConf * wc = get_winconf_by_id(world, id);
250     free(wc->title);
251 }
252
253
254
255 extern void free_winconfs(struct World * world)
256 {
257     free_winconf(world, 'i');
258     free_winconf(world, 'k');
259     free_winconf(world, 'l');
260     free_winconf(world, 'm');
261     free(world->winconfs);
262 }
263
264
265
266 extern void init_wins(struct World * world)
267 {
268     init_win_from_winconf(world, 'i');
269     init_win_from_winconf(world, 'k');
270     init_win_from_winconf(world, 'l');
271     init_win_from_winconf(world, 'm');
272 }
273
274
275
276 extern void free_wins(struct World * world)
277 {
278     free_win(get_win_by_id(world, 'i'));
279     free_win(get_win_by_id(world, 'k'));
280     free_win(get_win_by_id(world, 'l'));
281     free_win(get_win_by_id(world, 'm'));
282 }
283
284
285
286 extern void sorted_wintoggle(struct World * world)
287 {
288     char * f_name = "sorted_wintoggle()";
289     char * path = "config/windows/toggle_order";
290     FILE * file = try_fopen(path, "r", world, f_name);
291     uint16_t linemax = get_linemax(file, world, f_name);
292     char win_order[linemax + 1];
293     try_fgets(win_order, linemax + 1, file, world, f_name);
294     try_fclose(file, world, f_name);
295     uint8_t i = 0;
296     for (; i < linemax - 1; i++)
297     {
298         toggle_window(world->wmeta, get_win_by_id(world, win_order[i]));
299     }
300 }
301
302
303
304 extern void reload_win_config(struct World * world)
305 {
306     while (0 != world->wmeta->active)
307     {
308         suspend_win(world->wmeta, world->wmeta->active);
309     }
310     free_wins(world);
311     free_winconfs(world);
312     init_winconfs(world);
313     init_wins(world);
314     sorted_wintoggle(world);
315 }
316
317
318
319 extern void save_win_configs(struct World * world)
320 {
321     char * f_name = "save_win_configs()";
322
323     save_win_config(world, 'i');
324     save_win_config(world, 'k');
325     save_win_config(world, 'l');
326     save_win_config(world, 'm');
327
328     char * path     = "config/windows/toggle_order";
329     char * path_tmp = "config/windows/toggle_order_tmp";
330     FILE * file = try_fopen(path_tmp, "w", world, f_name);
331
332     char line[6];
333     struct Win * w_p = world->wmeta->_chain_start;
334     uint8_t i = 0;
335     while (0 != w_p)
336     {
337         line[i] = get_id_by_win(world, w_p);
338         w_p = w_p->_next;
339         i++;
340     }
341     line[i] = '\n';
342     fwrite(line, sizeof(char), strlen(line), file);
343
344     try_fclose_unlink_rename(file, path_tmp, path, world, f_name);
345 }
346
347
348
349 extern uint8_t toggle_window(struct WinMeta * win_meta, struct Win * win)
350 {
351     if (0 != win->frame.curses_win)
352     {
353         return suspend_win(win_meta, win);
354     }
355     else
356     {
357         return append_win(win_meta, win);
358     }
359 }
360
361
362
363 extern void toggle_winconfig(struct World * world, struct Win * win)
364 {
365     struct WinConf * wcp = get_winconf_by_win(world, win);
366     if (0 == wcp->view)
367     {
368         win->_draw = draw_winconf;
369         wcp->view = 1;
370     }
371     else
372     {
373         win->_draw = wcp->draw;
374         wcp->view = 0;
375     }
376 }
377
378
379
380 extern void toggle_win_height_type(struct World * world, struct Win * win)
381 {
382     struct WinConf * wcp = get_winconf_by_win(world, win);
383     if (0 == wcp->height_type)
384     {
385         wcp->height_type = 1;
386     }
387     else
388     {
389         wcp->height_type = 0;
390     }
391     set_winconf(world, wcp->id);
392 }
393
394
395
396 extern void toggle_win_width_type(struct World * world, struct Win * win)
397 {
398     struct WinConf * wcp = get_winconf_by_win(world, win);
399     if (   0 == wcp->width_type
400         && win->frame.size.x <= world->wmeta->padframe.size.x)
401     {
402         wcp->width_type = 1;
403     }
404     else
405     {
406         wcp->width_type = 0;
407     }
408     set_winconf(world, wcp->id);
409 }
410
411
412
413 extern void scroll_pad(struct WinMeta * win_meta, char dir)
414 {
415     if      ('+' == dir)
416     {
417         reset_pad_offset(win_meta, win_meta->pad_offset + 1);
418     }
419     else if ('-' == dir)
420     {
421         reset_pad_offset(win_meta, win_meta->pad_offset - 1);
422     }
423 }
424
425
426
427 extern uint8_t growshrink_active_window(struct World * world, char change)
428 {
429     if (0 != world->wmeta->active)
430     {
431         struct yx_uint16 size = world->wmeta->active->frame.size;
432         if      (change == '-')
433         {
434             size.y--;
435         }
436         else if (change == '+')
437         {
438             size.y++;
439         }
440         else if (change == '_')
441         {
442             size.x--;
443         }
444         else if (change == '*')
445         {
446             size.x++;
447         }
448         uint8_t x = resize_active_win(world->wmeta, size);
449         struct WinConf * wcp = get_winconf_by_win(world, world->wmeta->active);
450         if (   1 == wcp->width_type
451             && world->wmeta->active->frame.size.x
452                > world->wmeta->padframe.size.x)
453         {
454             wcp->width_type = 0;
455         }
456         set_winconf(world, wcp->id);
457         return x;
458     }
459     return 0;
460 }