AmendHub

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 }