Download
jcs
/wikipedia
/focusable.c
(View History)
jcs focusable: Sync with upstream | Latest amendment: 40 on 2023-08-28 |
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 | free(focusables); |
123 | focusables = NULL; |
124 | } |
125 | |
126 | if (nfocusables && focusables[0]->visible) |
127 | focusable_show(focusables[0]); |
128 | |
129 | return true; |
130 | } |
131 | |
132 | void |
133 | focusable_hide(struct focusable *focusable) |
134 | { |
135 | short n; |
136 | |
137 | HideWindow(focusable->win); |
138 | focusable->visible = false; |
139 | |
140 | for (n = 0; n < nfocusables; n++) { |
141 | if (focusables[n] == focusable) { |
142 | for (; n < nfocusables - 1; n++) |
143 | focusables[n] = focusables[n + 1]; |
144 | break; |
145 | } |
146 | } |
147 | focusables[nfocusables - 1] = focusable; |
148 | } |
149 | |
150 | bool |
151 | focusables_quit(void) |
152 | { |
153 | short tnfocusables = nfocusables; |
154 | short n; |
155 | struct focusable **tfocusables; |
156 | bool quit = true; |
157 | |
158 | if (nfocusables) { |
159 | /* |
160 | * nfocusables and focusables array will probably be |
161 | * modified as each focusable quits |
162 | */ |
163 | tfocusables = xcalloc(sizeof(Ptr), tnfocusables); |
164 | if (tfocusables == NULL) |
165 | panic("Out of memory!"); |
166 | memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables); |
167 | |
168 | for (n = 0; n < tnfocusables; n++) { |
169 | if (tfocusables[n] && !focusable_close(tfocusables[n])) { |
170 | quit = false; |
171 | break; |
172 | } |
173 | } |
174 | |
175 | free(tfocusables); |
176 | } |
177 | |
178 | return quit; |
179 | } |
180 | |
181 | void |
182 | focusables_atexit(void) |
183 | { |
184 | short n; |
185 | short tnfocusables = nfocusables; |
186 | struct focusable **tfocusables; |
187 | |
188 | if (!nfocusables) |
189 | return; |
190 | |
191 | tfocusables = xcalloc(sizeof(Ptr), tnfocusables); |
192 | if (tfocusables == NULL) |
193 | panic("Out of memory!"); |
194 | memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables); |
195 | |
196 | for (n = 0; n < tnfocusables; n++) { |
197 | if (tfocusables[n] && tfocusables[n]->atexit) |
198 | tfocusables[n]->atexit(tfocusables[n]); |
199 | } |
200 | |
201 | free(tfocusables); |
202 | } |