jcs
/amend
/amendments
/82
focusable: Import focusable framework
jcs made amendment 82 over 2 years ago
--- focusable.c Tue Aug 16 14:20:54 2022
+++ focusable.c Tue Aug 16 14:20:54 2022
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "focusable.h"
+#include "util.h"
+
+struct focusable **focusables = NULL;
+short nfocusables = 0;
+
+struct focusable *
+focusable_find(GrafPtr win)
+{
+ short n;
+
+ for (n = 0; n < nfocusables; n++) {
+ if (focusables[n]->win == win)
+ return focusables[n];
+ }
+
+ return NULL;
+}
+
+struct focusable *
+focusable_focused(void)
+{
+ if (nfocusables && focusables[0]->visible)
+ return focusables[0];
+
+ return NULL;
+}
+
+void
+focusable_add(struct focusable *focusable)
+{
+ short n;
+
+ nfocusables++;
+ focusables = xreallocarray(focusables, sizeof(struct focusable *),
+ nfocusables);
+
+ if (nfocusables > 1)
+ for (n = nfocusables - 1; n > 0; n--)
+ focusables[n] = focusables[n - 1];
+
+ focusables[0] = focusable;
+
+ focusable_show(focusable);
+}
+
+bool
+focusable_show(struct focusable *focusable)
+{
+ struct focusable *last, *tmp;
+ short n;
+
+ if (nfocusables > 1 && focusables[0] != focusable) {
+ last = focusables[0];
+
+ if (last->modal)
+ /* other focusables cannot steal focus from modals */
+ return false;
+
+ focusables[0] = focusable;
+ for (n = 1; n < nfocusables; n++) {
+ tmp = focusables[n];
+ focusables[n] = last;
+ last = tmp;
+ if (last == focusable)
+ break;
+ }
+ }
+
+ if (!focusable->visible) {
+ focusable->visible = true;
+ ShowWindow(focusable->win);
+ }
+
+ SelectWindow(focusable->win);
+ SetPort(focusable->win);
+
+ return true;
+}
+
+bool
+focusable_close(struct focusable *focusable)
+{
+ short n;
+
+ if (focusable->close) {
+ if (!focusable->close(focusable))
+ return false;
+ } else
+ DisposeWindow(focusable->win);
+
+ for (n = 0; n < nfocusables; n++) {
+ if (focusables[n] == focusable) {
+ for (; n < nfocusables - 1; n++)
+ focusables[n] = focusables[n + 1];
+ break;
+ }
+ }
+
+ nfocusables--;
+ if (nfocusables)
+ focusables = xreallocarray(focusables, sizeof(Ptr), nfocusables);
+ else {
+ free(focusables);
+ focusables = NULL;
+ }
+
+ if (nfocusables && focusables[0]->visible)
+ focusable_show(focusables[0]);
+
+ return true;
+}
+
+void
+focusable_hide(struct focusable *focusable)
+{
+ short n;
+
+ HideWindow(focusable->win);
+ focusable->visible = false;
+
+ for (n = 0; n < nfocusables; n++) {
+ if (focusables[n] == focusable) {
+ for (; n < nfocusables - 1; n++)
+ focusables[n] = focusables[n + 1];
+ break;
+ }
+ }
+ focusables[nfocusables - 1] = focusable;
+}
+
+bool
+focusables_quit(void)
+{
+ short tnfocusables = nfocusables;
+ short n;
+ struct focusable **tfocusables;
+ bool quit = true;
+
+ if (nfocusables) {
+ /*
+ * nfocusables and focusables array will probably be
+ * modified as each focusable quits
+ */
+ tfocusables = xcalloc(sizeof(Ptr), tnfocusables);
+ memcpy(tfocusables, focusables, sizeof(Ptr) * tnfocusables);
+
+ for (n = 0; n < tnfocusables; n++) {
+ if (tfocusables[n] && !focusable_close(tfocusables[n])) {
+ quit = false;
+ break;
+ }
+ }
+
+ free(tfocusables);
+ }
+
+ return quit;
+}
--- focusable.h Tue Aug 16 13:33:08 2022
+++ focusable.h Tue Aug 16 13:33:08 2022
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021-2022 joshua stein <jcs@jcs.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FOCUSABLE_H__
+#define __FOCUSABLE_H__
+
+#include "util.h"
+
+struct focusable {
+ WindowPtr win;
+ bool visible;
+ void *cookie;
+ bool modal;
+ short (*wait_type)(struct focusable *focusable);
+ void (*idle)(struct focusable *focusable, EventRecord *event);
+ void (*update)(struct focusable *focusable, EventRecord *event);
+ void (*key_down)(struct focusable *focusable, EventRecord *event);
+ void (*mouse_down)(struct focusable *focusable, EventRecord *event);
+ bool (*menu)(struct focusable *focusable, short menu, short item);
+ void (*suspend)(struct focusable *focusable, EventRecord *event);
+ void (*resume)(struct focusable *focusable, EventRecord *event);
+ bool (*close)(struct focusable *focusable);
+ void (*atexit)(struct focusable *focusable);
+};
+extern struct focusable **focusables;
+extern short nfocusables;
+
+struct focusable * focusable_find(GrafPtr win);
+struct focusable * focusable_focused(void);
+void focusable_add(struct focusable *focusable);
+bool focusable_show(struct focusable *focusable);
+bool focusable_close(struct focusable *focusable);
+void focusable_hide(struct focusable *focusable);
+bool focusables_quit(void);
+
+#endif