/* * Copyright (c) 2022 joshua stein * * 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 #include #include "detritus.h" #include "focusable.h" #include "tcp.h" #include "util.h" /* be sure this is NULL terminated */ const struct default_bookmark default_bookmarks[] = { { "Floodgap Gopher", "gopher://gopher.floodgap.com/", }, { "SDF Gopher", "gopher://sdf.org/", }, { "Gemini Protocol", "gemini://geminiprotocol.net/", }, { 0 }, }; MenuHandle apple_menu, file_menu, edit_menu, bookmarks_menu; Cursor finger_cursor; bool quitting = false; bool handle_menu(long menu_id); void handle_exit(void); short main(void) { Handle mbar; EventRecord event; WindowPtr event_win; GrafPtr old_port; RgnHandle mouse_region; CursHandle cursh; struct focusable *found_focusable; short event_in, n; char key; InitGraf(&thePort); InitFonts(); FlushEvents(everyEvent, 0); InitWindows(); InitMenus(); TEInit(); InitDialogs(0); InitCursor(); MaxApplZone(); util_init(); _atexit(handle_exit); mbar = GetNewMBar(MBAR_ID); SetMenuBar(mbar); apple_menu = GetMHandle(APPLE_MENU_ID); AddResMenu(apple_menu, 'DRVR'); file_menu = GetMHandle(FILE_MENU_ID); edit_menu = GetMHandle(EDIT_MENU_ID); bookmarks_menu = GetMHandle(BOOKMARKS_MENU_ID); menu_defaults(); DrawMenuBar(); if (_TCPInit() != 0) panic("Failed initializing MacTCP"); settings_load(); menu_load_bookmarks(); cursh = GetCursor(CURSOR_FINGER_ID); if (cursh == NULL) panic("Can't find my finger!"); finger_cursor = **cursh; /* browser before scsi so the user can look at something while we poll */ browser_init(); scsi_find_tls(); while (!quitting) { WaitNextEvent(everyEvent, &event, 5L, NULL); switch (event.what) { case nullEvent: for (n = 0; n < nfocusables; n++) { if (focusables[n]->idle) focusables[n]->idle(focusables[n], &event); } break; case keyDown: case autoKey: key = event.message & charCodeMask; if ((event.modifiers & cmdKey) != 0 && handle_menu(MenuKey(key)) == true) break; if (nfocusables && focusables[0]->visible && focusables[0]->key_down) focusables[0]->key_down(focusables[0], &event); break; case mouseDown: event_in = FindWindow(event.where, &event_win); found_focusable = focusable_find(event_win); if (found_focusable) focusable_show(found_focusable); switch (event_in) { case inMenuBar: handle_menu(MenuSelect(event.where)); break; case inSysWindow: SystemClick(&event, event_win); break; case inDrag: DragWindow(event_win, event.where, &screenBits.bounds); break; case inGrow: if (found_focusable && found_focusable->resize) found_focusable->resize(found_focusable, &event); break; case inGoAway: if (TrackGoAway(event_win, event.where) && found_focusable) focusable_close(found_focusable); break; case inContent: if (found_focusable && found_focusable->mouse_down) found_focusable->mouse_down(found_focusable, &event); break; } break; case updateEvt: case activateEvt: event_win = (WindowPtr)event.message; found_focusable = focusable_find(event_win); GetPort(&old_port); SetPort(event_win); if (event.what == updateEvt) BeginUpdate(event_win); if (found_focusable && found_focusable->update) found_focusable->update(found_focusable, &event); if (event.what == updateEvt) EndUpdate(event_win); SetPort(old_port); break; case app4Evt: if (HiWord(event.message) & (1 << 8)) { /* multifinder suspend/resume */ switch (event.message & (1 << 0)) { case 0: /* suspend */ for (n = 0; n < nfocusables; n++) { if (focusables[n]->suspend) focusables[n]->suspend(focusables[n], &event); } break; case 1: /* resume */ for (n = 0; n < nfocusables; n++) { if (focusables[n]->resume) focusables[n]->resume(focusables[n], &event); } break; } } break; } } return 0; } bool handle_menu(long menu_id) { struct browser *browser; struct focusable *focused; short menu, item, n; menu = HiWord(menu_id); item = LoWord(menu_id); if ((focused = focusable_focused()) && focused->menu && focused->menu(focused, menu, item)) goto handled; browser = (struct browser *)focused->cookie; switch (menu) { case APPLE_MENU_ID: switch (item) { case APPLE_MENU_ABOUT_ID: about(PROGRAM_NAME); break; default: { Str255 da; GrafPtr save_port; GetItem(apple_menu, LoWord(menu_id), &da); GetPort(&save_port); OpenDeskAcc(da); SetPort(save_port); break; } } break; case FILE_MENU_ID: switch (item) { case FILE_MENU_QUIT_ID: if (focusables_quit()) quitting = true; break; } break; case BOOKMARKS_MENU_ID: switch (item) { case BOOKMARKS_MENU_EDIT_ID: bookmarks_dialog(); break; default: n = item - BOOKMARKS_MENU_SEP_ID - 1; if (settings.bookmark_uris[n][0] != '\0') browser_go_uri_str(browser, settings.bookmark_uris[n]); break; } break; } handled: HiliteMenu(0); return true; } void menu_defaults(void) { DisableItem(edit_menu, EDIT_MENU_CUT_ID); DisableItem(edit_menu, EDIT_MENU_COPY_ID); DisableItem(edit_menu, EDIT_MENU_PASTE_ID); DisableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID); } void menu_load_bookmarks(void) { Str255 title; short count, n; count = CountMItems(bookmarks_menu); while (count >= BOOKMARKS_MENU_SEP_ID) { DelMenuItem(bookmarks_menu, count); count--; } for (n = 0; n < BOOKMARKS_COUNT; n++) { if (settings.bookmark_uris[n][0] == '\0') break; if (count < BOOKMARKS_MENU_SEP_ID) { AppendMenu(bookmarks_menu, "\p(-"); count++; } if (settings.bookmark_names[n][0] == '\0') strlcpy((char *)&title, (char *)&settings.bookmark_uris[n], sizeof(title)); else strlcpy((char *)&title, (char *)&settings.bookmark_names[n], sizeof(title)); CtoPstr(title); AppendMenu(bookmarks_menu, "\p."); count++; SetItem(bookmarks_menu, count, title); } } void handle_exit(void) { focusables_quit(); }