Download
jcs
/amend
/focusable.c
(View History)
jcs *: Bring in util from Subtext with malloc debugging, integrate it | Latest amendment: 92 on 2022-08-18 |
1 | /* |
2 | * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #include <string.h> |
18 | |
19 | #include "focusable.h" |
20 | #include "util.h" |
21 | |
22 | struct focusable **focusables = NULL; |
23 | short nfocusables = 0; |
24 | |
25 | struct focusable * |
26 | focusable_find(GrafPtr win) |
27 | { |
28 | short n; |
29 | |
30 | for (n = 0; n < nfocusables; n++) { |
31 | if (focusables[n]->win == win) |
32 | return focusables[n]; |
33 | } |
34 | |
35 | return NULL; |
36 | } |
37 | |
38 | struct focusable * |
39 | focusable_focused(void) |
40 | { |
41 | if (nfocusables && focusables[0]->visible) |
42 | return focusables[0]; |
43 | |
44 | return NULL; |
45 | } |
46 | |
47 | void |
48 | focusable_add(struct focusable *focusable) |
49 | { |
50 | short n; |
51 | |
52 | nfocusables++; |
53 | focusables = xreallocarray(focusables, sizeof(struct focusable *), |
54 | nfocusables); |
55 | |
56 | if (nfocusables > 1) |
57 | for (n = nfocusables - 1; n > 0; n--) |
58 | focusables[n] = focusables[n - 1]; |
59 | |
60 | focusables[0] = focusable; |
61 | |
62 | focusable_show(focusable); |
63 | } |
64 | |
65 | bool |
66 | focusable_show(struct focusable *focusable) |
67 | { |
68 | struct focusable *last, *tmp; |
69 | short n; |
70 | |
71 | if (nfocusables > 1 && focusables[0] != focusable) { |
72 | last = focusables[0]; |
73 | |
74 | if (last->modal) |
75 | /* other focusables cannot steal focus from modals */ |
76 | return false; |
77 | |
78 | focusables[0] = focusable; |
79 | for (n = 1; n < nfocusables; n++) { |
80 | tmp = focusables[n]; |
81 | focusables[n] = last; |
82 | last = tmp; |
83 | if (last == focusable) |
84 | break; |
85 | } |
86 | } |
87 | |
88 | if (!focusable->visible) { |
89 | focusable->visible = true; |
90 | ShowWindow(focusable->win); |
91 | } |
92 | |
93 | SelectWindow(focusable->win); |
94 | SetPort(focusable->win); |
95 | |
96 | return true; |
97 | } |
98 | |
99 | bool |
100 | focusable_close(struct focusable *focusable) |
101 | { |
102 | short n; |
103 | |
104 | if (focusable->close) { |
105 | if (!focusable->close(focusable)) |
106 | return false; |
107 | } else |
108 | DisposeWindow(focusable->win); |
109 | |
110 | for (n = 0; n < nfocusables; n++) { |
111 | if (focusables[n] == focusable) { |
112 | for (; n < nfocusables - 1; n++) |
113 | focusables[n] = focusables[n + 1]; |
114 | break; |
115 | } |
116 | } |
117 | |
118 | nfocusables--; |
119 | if (nfocusables) |
120 | focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables); |
121 | else |
122 | xfree(&focusables); |
123 | |
124 | if (nfocusables && focusables[0]->visible) |
125 | focusable_show(focusables[0]); |
126 | |
127 | return true; |
128 | } |
129 | |
130 | void |
131 | focusable_hide(struct focusable *focusable) |
132 | { |
133 | short n; |
134 | |
135 | HideWindow(focusable->win); |
136 | focusable->visible = false; |
137 | |
138 | for (n = 0; n < nfocusables; n++) { |
139 | if (focusables[n] == focusable) { |
140 | for (; n < nfocusables - 1; n++) |
141 | focusables[n] = focusables[n + 1]; |
142 | break; |
143 | } |
144 | } |
145 | focusables[nfocusables - 1] = focusable; |
146 | } |
147 | |
148 | bool |
149 | focusables_quit(void) |
150 | { |
151 | short tnfocusables = nfocusables; |
152 | short n; |
153 | struct focusable **tfocusables; |
154 | bool quit = true; |
155 | |
156 | if (nfocusables) { |
157 | /* |
158 | * nfocusables and focusables array will probably be |
159 | * modified as each focusable quits |
160 | */ |
161 | tfocusables = xcalloc(sizeof(Ptr), tnfocusables, "tfocusables"); |
162 | memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables); |
163 | |
164 | for (n = 0; n < tnfocusables; n++) { |
165 | if (tfocusables[n] && !focusable_close(tfocusables[n])) { |
166 | quit = false; |
167 | break; |
168 | } |
169 | } |
170 | |
171 | xfree(&tfocusables); |
172 | } |
173 | |
174 | return quit; |
175 | } |