Download
jcs
/amend
/main.c
(View History)
jcs committer: Add Command+W shortcut to cancel commit | Latest amendment: 103 on 2022-09-12 |
1 | /* |
2 | * Copyright (c) 2020-2021 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 <stdio.h> |
18 | #include <string.h> |
19 | |
20 | #include "amend.h" |
21 | #include "browser.h" |
22 | #include "committer.h" |
23 | #include "focusable.h" |
24 | #include "repo.h" |
25 | #include "settings.h" |
26 | #include "util.h" |
27 | |
28 | MenuHandle apple_menu, file_menu, edit_menu, repo_menu, amendment_menu; |
29 | Handle amendment_list_ldef_h; |
30 | bool quitting = false; |
31 | |
32 | bool handle_menu(long menu_id); |
33 | |
34 | int |
35 | main(void) |
36 | { |
37 | Handle mbar; |
38 | EventRecord event; |
39 | WindowPtr event_win; |
40 | GrafPtr old_port; |
41 | AppFile finder_file; |
42 | struct repo *repo; |
43 | struct focusable *focusable; |
44 | short event_in, n, finder_action, finder_count; |
45 | bool did_initial_open = false; |
46 | char key; |
47 | |
48 | InitGraf(&thePort); |
49 | InitFonts(); |
50 | FlushEvents(everyEvent, 0); |
51 | InitWindows(); |
52 | InitMenus(); |
53 | TEInit(); |
54 | InitDialogs(0); |
55 | InitCursor(); |
56 | MaxApplZone(); |
57 | |
58 | util_init(); |
59 | settings_load(); |
60 | |
61 | mbar = GetNewMBar(MBAR_ID); |
62 | SetMenuBar(mbar); |
63 | apple_menu = GetMHandle(APPLE_MENU_ID); |
64 | AddResMenu(apple_menu, 'DRVR'); |
65 | file_menu = GetMHandle(FILE_MENU_ID); |
66 | edit_menu = GetMHandle(EDIT_MENU_ID); |
67 | repo_menu = GetMHandle(REPO_MENU_ID); |
68 | amendment_menu = GetMHandle(AMENDMENT_MENU_ID); |
69 | menu_defaults(); |
70 | DrawMenuBar(); |
71 | |
72 | /* dynamically patch list LDEF to point to our *_list_ldef funcs */ |
73 | amendment_list_ldef_h = GetResource('LDEF', AMENDMENT_LDEF_ID); |
74 | if (!amendment_list_ldef_h) |
75 | err(1, "Can't find amendment list LDEF %d", AMENDMENT_LDEF_ID); |
76 | HLock(amendment_list_ldef_h); |
77 | ((tCodeStub *)*amendment_list_ldef_h)->addr = &amendment_list_ldef; |
78 | |
79 | /* see if we were started by double-clicking a .repo file */ |
80 | CountAppFiles(&finder_action, &finder_count); |
81 | |
82 | while (!quitting) { |
83 | WaitNextEvent(everyEvent, &event, 5L, 0L); |
84 | |
85 | switch (event.what) { |
86 | case nullEvent: |
87 | for (n = 0; n < nfocusables; n++) { |
88 | if (focusables[n]->idle) |
89 | focusables[n]->idle(focusables[n], &event); |
90 | } |
91 | if (!did_initial_open) { |
92 | if (finder_count) { |
93 | GetAppFiles(1, &finder_file); |
94 | ClrAppFiles(1); |
95 | finder_count = 0; |
96 | repo = repo_open(&finder_file); |
97 | } else |
98 | repo = repo_open(NULL); |
99 | |
100 | if (repo) |
101 | browser_init(repo); |
102 | |
103 | did_initial_open = true; |
104 | } |
105 | break; |
106 | case keyDown: |
107 | case autoKey: |
108 | key = event.message & charCodeMask; |
109 | if ((event.modifiers & cmdKey) != 0) { |
110 | if (handle_menu(MenuKey(key))) |
111 | break; |
112 | } |
113 | if ((focusable = focusable_focused()) && |
114 | focusable->key_down) |
115 | focusable->key_down(focusable, &event); |
116 | break; |
117 | case mouseDown: |
118 | event_in = FindWindow(event.where, &event_win); |
119 | |
120 | switch (event_in) { |
121 | case inMenuBar: |
122 | handle_menu(MenuSelect(event.where)); |
123 | break; |
124 | case inSysWindow: |
125 | SystemClick(&event, event_win); |
126 | break; |
127 | case inDrag: |
128 | if ((focusable = focusable_find(event_win)) != NULL) { |
129 | if (!focusable_show(focusable)) |
130 | break; |
131 | |
132 | DragWindow(event_win, event.where, &screenBits.bounds); |
133 | } |
134 | break; |
135 | case inGoAway: |
136 | if (TrackGoAway(event_win, event.where)) { |
137 | if ((focusable = focusable_find(event_win)) != NULL) |
138 | focusable_close(focusable); |
139 | } |
140 | break; |
141 | case inContent: |
142 | if ((focusable = focusable_find(event_win)) != NULL) { |
143 | if (!focusable_show(focusable)) |
144 | break; |
145 | if (focusable->mouse_down) |
146 | focusable->mouse_down(focusable, &event); |
147 | } |
148 | break; |
149 | } |
150 | break; |
151 | case updateEvt: |
152 | event_win = (WindowPtr)event.message; |
153 | |
154 | GetPort(&old_port); |
155 | SetPort(event_win); |
156 | BeginUpdate(event_win); |
157 | |
158 | focusable = focusable_find(event_win); |
159 | if (focusable && focusable->update) |
160 | focusable->update(focusable, &event); |
161 | |
162 | EndUpdate(event_win); |
163 | SetPort(old_port); |
164 | break; |
165 | case activateEvt: |
166 | break; |
167 | case app4Evt: |
168 | if (HiWord(event.message) & (1 << 8)) { |
169 | /* multifinder suspend/resume */ |
170 | switch (event.message & (1 << 0)) { |
171 | case 0: |
172 | /* suspend */ |
173 | for (n = 0; n < nfocusables; n++) { |
174 | if (focusables[n]->suspend) |
175 | focusables[n]->suspend(focusables[n], &event); |
176 | } |
177 | break; |
178 | case 1: |
179 | /* resume */ |
180 | for (n = 0; n < nfocusables; n++) { |
181 | if (focusables[n]->resume) |
182 | focusables[n]->resume(focusables[n], &event); |
183 | } |
184 | break; |
185 | } |
186 | } |
187 | break; |
188 | } |
189 | } |
190 | |
191 | return 0; |
192 | } |
193 | |
194 | bool |
195 | handle_menu(long menu_id) |
196 | { |
197 | struct focusable *focused; |
198 | short menu, item; |
199 | bool ret = true; |
200 | |
201 | menu = HiWord(menu_id); |
202 | item = LoWord(menu_id); |
203 | |
204 | if (menu && item && (focused = focusable_focused()) && |
205 | focused->menu && focused->menu(focused, menu, item)) |
206 | goto handled; |
207 | |
208 | switch (menu) { |
209 | case APPLE_MENU_ID: |
210 | switch (item) { |
211 | case APPLE_MENU_ABOUT_ID: |
212 | about(PROGRAM_NAME); |
213 | break; |
214 | default: { |
215 | Str255 da; |
216 | GrafPtr save_port; |
217 | |
218 | GetItem(apple_menu, LoWord(menu_id), &da); |
219 | GetPort(&save_port); |
220 | OpenDeskAcc(da); |
221 | SetPort(save_port); |
222 | break; |
223 | } |
224 | } |
225 | break; |
226 | case FILE_MENU_ID: |
227 | switch (item) { |
228 | case FILE_MENU_NEW_ID: { |
229 | struct repo *repo; |
230 | if ((repo = repo_create())) |
231 | browser_init(repo); |
232 | break; |
233 | } |
234 | case FILE_MENU_OPEN_ID: { |
235 | struct repo *repo; |
236 | if ((repo = repo_open(NULL))) |
237 | browser_init(repo); |
238 | break; |
239 | } |
240 | case FILE_MENU_SETTINGS_ID: |
241 | settings_edit(); |
242 | break; |
243 | case FILE_MENU_QUIT_ID: |
244 | if (focusables_quit()) |
245 | quitting = true; |
246 | break; |
247 | } |
248 | break; |
249 | default: |
250 | ret = false; |
251 | } |
252 | |
253 | handled: |
254 | HiliteMenu(0); |
255 | return ret; |
256 | } |
257 | |
258 | void |
259 | menu_defaults(void) |
260 | { |
261 | DisableItem(edit_menu, EDIT_MENU_CUT_ID); |
262 | DisableItem(edit_menu, EDIT_MENU_COPY_ID); |
263 | DisableItem(edit_menu, EDIT_MENU_PASTE_ID); |
264 | DisableItem(edit_menu, EDIT_MENU_SELECT_ALL_ID); |
265 | |
266 | DisableItem(repo_menu, REPO_MENU_ADD_FILE_ID); |
267 | DisableItem(repo_menu, REPO_MENU_DISCARD_CHANGES_ID); |
268 | DisableItem(repo_menu, REPO_MENU_APPLY_PATCH_ID); |
269 | |
270 | DisableItem(amendment_menu, AMENDMENT_MENU_EDIT_ID); |
271 | DisableItem(amendment_menu, AMENDMENT_MENU_EXPORT_ID); |
272 | } |