Download
jcs
/wifi_da
/window.c
(View History)
jcs *: Don't rely on our static wifi_da persisting | Latest amendment: 40 on 2025-01-07 |
1 | /* |
2 | * Copyright (c) 2023 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 | #include "wi-fi.h" |
20 | |
21 | short nwifi_scan_networks = 0; |
22 | struct wifi_network_entry wifi_menu_networks[MAX_WIFI_NETWORKS]; |
23 | short nwifi_menu_networks = 0; |
24 | |
25 | void create_logger(void); |
26 | pascal Boolean WiFiPasswordDialogFieldFilter(DialogPtr dlg, |
27 | EventRecord *event, short *hit); |
28 | |
29 | void |
30 | create_window(short ctlrefnum) |
31 | { |
32 | Str255 str; |
33 | GrafPtr savePort, tport; |
34 | |
35 | memset(&wifi_menu_networks, 0, sizeof(wifi_menu_networks)); |
36 | wifi_da.str_res_id = find_str_res_id(); |
37 | |
38 | GetPort(&savePort); |
39 | |
40 | /* screenBits is not available from a DA */ |
41 | tport = (GrafPtr)NewPtr(sizeof(GrafPort)); |
42 | OpenPort(tport); |
43 | /* upper right corner, but leave space for desktop icon */ |
44 | wifi_da.bounds.top = 45; |
45 | wifi_da.bounds.bottom = wifi_da.bounds.top + DA_HEIGHT; |
46 | wifi_da.bounds.left = tport->portRect.right - DA_WIDTH - 70; |
47 | wifi_da.bounds.right = wifi_da.bounds.left + DA_WIDTH; |
48 | ClosePort(tport); |
49 | |
50 | wifi_da.win = NewWindow(0L, &wifi_da.bounds, "\pWi-Fi", true, |
51 | rDocProc, 0L, true, 0L); |
52 | ((WindowPeek)(wifi_da.win))->windowKind = ctlrefnum; |
53 | |
54 | wifi_da.win_shadow.rowBytes = (((DA_WIDTH - 1) / 16) + 1) * 2; |
55 | wifi_da.win_shadow.baseAddr = |
56 | xmalloczero(wifi_da.win_shadow.rowBytes * DA_HEIGHT); |
57 | SetRect(&wifi_da.win_shadow.bounds, 0, 0, DA_WIDTH, DA_HEIGHT); |
58 | |
59 | wifi_da.signal_icons = (SICNHandle)GetResource('SICN', |
60 | OwnedResourceID(0)); |
61 | if (wifi_da.signal_icons == NULL) |
62 | panic("Can't find SICN"); |
63 | |
64 | SetRect(&wifi_da.icon_rect, 6, 4, 22, 20); /* ltrb */ |
65 | |
66 | wifi_da.ssid_menu = NewMenu(OwnedResourceID(10), "\p"); |
67 | GetIndString(str, wifi_da.str_res_id, STR_FINDING_WIFI_ID); |
68 | InsMenuItem(wifi_da.ssid_menu, str, 1); |
69 | |
70 | SetRect(&wifi_da.ssid_menu_rect, 30, 3, 170, 21); /* ltrb */ |
71 | |
72 | #if 0 /* system 6 does not seem to support popupMenuProc */ |
73 | ssid_list = NewControl(wifi_da.win, &wifi_da.ssid_menu_rect, 0, true, |
74 | 0, OwnedResourceID(SSID_MENU_ID), 0, popupMenuProc + popupFixedWidth, |
75 | 0L); |
76 | #endif |
77 | |
78 | update_window(true); |
79 | |
80 | if (wifi_scsi_id == WIFI_SCSI_ID_FINDING) |
81 | wifi_scsi_id = scsi_find_wifi(); |
82 | |
83 | if (wifi_scsi_id == WIFI_SCSI_ID_NONE) { |
84 | wifi_da.state = STATE_IDLE; |
85 | GetIndString(str, wifi_da.str_res_id, STR_NO_DEVICE_FOUND_ID); |
86 | SetItem(wifi_da.ssid_menu, 1, str); |
87 | update_window(true); |
88 | } else { |
89 | scsi_wifi_info(wifi_scsi_id, &wifi_cur_info); |
90 | wifi_da.state = STATE_SCANNING; |
91 | scsi_wifi_scan(wifi_scsi_id); |
92 | } |
93 | |
94 | SetPort(savePort); |
95 | } |
96 | |
97 | void |
98 | create_logger(void) |
99 | { |
100 | Str255 str; |
101 | Rect bounds; |
102 | |
103 | bounds.top = 150; |
104 | bounds.bottom = 320; |
105 | bounds.left = 20; |
106 | bounds.right = 400; |
107 | GetIndString(str, wifi_da.str_res_id, STR_DEBUG_LOGS_ID); |
108 | wifi_da.logger = NewWindow(0L, &bounds, str, true, rDocProc, 0L, |
109 | false, 0L); |
110 | ((WindowPeek)wifi_da.logger)->windowKind = dce->dCtlRefNum; |
111 | } |
112 | |
113 | void |
114 | update_window(bool force) |
115 | { |
116 | Str255 menuText; |
117 | GrafPtr savePort; |
118 | Point p; |
119 | short i, icon, x, w; |
120 | RgnHandle tmpRgn; |
121 | Rect r, destRect; |
122 | BitMap bm, cur_bits; |
123 | |
124 | GetPort(&savePort); |
125 | SetPort(wifi_da.win); |
126 | |
127 | //logger_printf("redrawing window"); |
128 | cur_bits = wifi_da.win->portBits; |
129 | SetPortBits(&wifi_da.win_shadow); |
130 | |
131 | if (!force) |
132 | BeginUpdate(wifi_da.win); |
133 | |
134 | EraseRect(&wifi_da.win->portRect); |
135 | DrawControls(wifi_da.win); |
136 | |
137 | /* system 6 does not seem to support popupMenuProc, fake it */ |
138 | FrameRect(&wifi_da.ssid_menu_rect); |
139 | MoveTo(wifi_da.ssid_menu_rect.left + 1, wifi_da.ssid_menu_rect.bottom); |
140 | LineTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.bottom); |
141 | MoveTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.top + 1); |
142 | LineTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.bottom); |
143 | |
144 | TextFont(systemFont); |
145 | TextSize(0); |
146 | GetItem(wifi_da.ssid_menu, 1, &menuText); |
147 | x = 15; |
148 | MoveTo(wifi_da.ssid_menu_rect.left + x, 16); |
149 | |
150 | for (i = 1; i <= menuText[0]; i++) { |
151 | w = CharWidth(menuText[i]); |
152 | if (i < menuText[0] && x + w >= (wifi_da.ssid_menu_rect.right - |
153 | wifi_da.ssid_menu_rect.left - 14)) { |
154 | /* truncate */ |
155 | GetPen(&p); |
156 | MoveTo(p.h - 1, p.v); |
157 | DrawChar('…'); |
158 | break; |
159 | } |
160 | DrawChar(menuText[i]); |
161 | x += w; |
162 | } |
163 | |
164 | HLock(wifi_da.signal_icons); |
165 | |
166 | if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
167 | icon = SIGNAL_NO_DEVICE; |
168 | else if (wifi_scsi_id == WIFI_SCSI_ID_FINDING) |
169 | icon = SIGNAL_FINDING_DEVICE; |
170 | else if (wifi_cur_info.ssid[0] == '\0') |
171 | icon = SIGNAL_NONE; |
172 | else if (wifi_cur_info.rssi >= -60) |
173 | icon = SIGNAL_4; |
174 | else if (wifi_cur_info.rssi >= -70) |
175 | icon = SIGNAL_3; |
176 | else if (wifi_cur_info.rssi >= -75) |
177 | icon = SIGNAL_2; |
178 | else |
179 | icon = SIGNAL_1; |
180 | |
181 | bm.baseAddr = (Ptr)(*(wifi_da.signal_icons))[icon]; |
182 | bm.rowBytes = 2; |
183 | SetRect(&bm.bounds, 0, 0, 16, 16); |
184 | CopyBits(&bm, &wifi_da.win->portBits, &bm.bounds, &wifi_da.icon_rect, |
185 | srcOr, NULL); |
186 | |
187 | HUnlock(wifi_da.signal_icons); |
188 | |
189 | if (!force) |
190 | EndUpdate(wifi_da.win); |
191 | |
192 | SetPortBits(&cur_bits); |
193 | |
194 | CopyBits(&wifi_da.win_shadow, &wifi_da.win->portBits, |
195 | &wifi_da.win_shadow.bounds, &wifi_da.win_shadow.bounds, srcCopy, nil); |
196 | |
197 | ValidRect(&wifi_da.win->portRect); |
198 | SetPort(savePort); |
199 | } |
200 | |
201 | void |
202 | update_wifi_cur_info(void) |
203 | { |
204 | struct wifi_network_entry old_info; |
205 | |
206 | if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
207 | return; |
208 | |
209 | memcpy(&old_info, &wifi_cur_info, sizeof(old_info)); |
210 | |
211 | scsi_wifi_info(wifi_scsi_id, &wifi_cur_info); |
212 | |
213 | if (memcmp(&old_info, &wifi_cur_info, sizeof(old_info)) != 0) { |
214 | if (memcmp(&old_info.ssid, &wifi_cur_info.ssid, |
215 | sizeof(old_info.ssid)) == 0) { |
216 | /* just updating RSSI */ |
217 | logger_printf("update_wifi_cur_info: just updating rssi to %d", |
218 | wifi_cur_info.rssi); |
219 | update_window(true); |
220 | } else { |
221 | logger_printf("update_wifi_cur_info: updating ssid list"); |
222 | update_wifi_ssid_list(false); |
223 | } |
224 | } |
225 | } |
226 | |
227 | void |
228 | update_wifi_ssid_list(bool update_networks) |
229 | { |
230 | Str255 str; |
231 | char ssid[64]; |
232 | short n, m, mitem; |
233 | |
234 | if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
235 | return; |
236 | |
237 | if (update_networks) { |
238 | nwifi_scan_networks = scsi_wifi_scan_results(wifi_scsi_id, |
239 | wifi_scan_networks, nitems(wifi_scan_networks)); |
240 | logger_printf("scsi_wifi_scan_results: %d networks", |
241 | nwifi_scan_networks); |
242 | |
243 | if (nwifi_scan_networks == 0) |
244 | logger_printf("no networks found during scan"); |
245 | } |
246 | |
247 | if (nwifi_scan_networks == 0) { |
248 | /* use our current network (or none) as the only one found */ |
249 | memcpy(&wifi_scan_networks, &wifi_cur_info, sizeof(wifi_cur_info)); |
250 | nwifi_scan_networks = 1; |
251 | } |
252 | |
253 | logger_printf("current ssid: %s", wifi_cur_info.ssid[0] == '\0' ? |
254 | "(none)" : wifi_cur_info.ssid); |
255 | |
256 | /* |
257 | * now start building the ssid menu from wifi_scan_networks |
258 | */ |
259 | |
260 | /* leave room for current network and trailing "(other network)" */ |
261 | if (nwifi_scan_networks > MAX_WIFI_NETWORKS - 2) { |
262 | nwifi_scan_networks = MAX_WIFI_NETWORKS - 2; |
263 | logger_printf("capping wifi_scan_networks to %d", |
264 | nwifi_scan_networks); |
265 | } |
266 | |
267 | /* put the current network (if any) first in the menu */ |
268 | logger_printf("menu[0]: %s", wifi_cur_info.ssid[0] ? |
269 | wifi_cur_info.ssid : "(no network)"); |
270 | memcpy(&wifi_menu_networks[0], &wifi_cur_info, |
271 | sizeof(wifi_menu_networks[0])); |
272 | nwifi_menu_networks = 1; |
273 | |
274 | /* add each additional network from the scan */ |
275 | for (n = 0; n < nwifi_scan_networks; n++) { |
276 | /* except current one, which we added first */ |
277 | if (strcmp(wifi_scan_networks[n].ssid, wifi_cur_info.ssid) == 0) |
278 | continue; |
279 | |
280 | memcpy(&wifi_menu_networks[nwifi_menu_networks], |
281 | &wifi_scan_networks[n], sizeof(wifi_menu_networks[0])); |
282 | logger_printf("menu[%d]: %s", nwifi_menu_networks, |
283 | wifi_menu_networks[nwifi_menu_networks].ssid); |
284 | nwifi_menu_networks++; |
285 | } |
286 | |
287 | if (wifi_menu_networks[0].ssid[0] == '\0') { |
288 | /* replace blank string with "(no network)" */ |
289 | GetIndString(str, wifi_da.str_res_id, STR_NO_NETWORK_ID); |
290 | PtoCstr(str); |
291 | strlcpy(wifi_menu_networks[0].ssid, (char *)str, |
292 | sizeof(wifi_menu_networks[0].ssid)); |
293 | } |
294 | |
295 | /* add "other network" as last entry */ |
296 | nwifi_menu_networks++; |
297 | if (nwifi_menu_networks > MAX_WIFI_NETWORKS) |
298 | panic("nwifi_menu_networks overflow"); |
299 | GetIndString(str, wifi_da.str_res_id, STR_OTHER_NETWORK_ID); |
300 | PtoCstr(str); |
301 | strlcpy(wifi_menu_networks[nwifi_menu_networks - 1].ssid, |
302 | (char *)str, sizeof(wifi_menu_networks[0].ssid)); |
303 | wifi_menu_networks[nwifi_menu_networks - 1].flags = |
304 | WIFI_NETWORK_FLAG_AUTH | WIFI_NETWORK_FLAG_HIDDEN; |
305 | logger_printf("menu[%d]: %s", nwifi_menu_networks - 1, |
306 | "(other network)"); |
307 | |
308 | /* |
309 | * leave the first item and we'll set its text later but delete all |
310 | * others |
311 | */ |
312 | while (CountMItems(wifi_da.ssid_menu) > 1) |
313 | DelMenuItem(wifi_da.ssid_menu, 2); |
314 | |
315 | for (n = 0, mitem = 1; n < nwifi_menu_networks; n++) { |
316 | /* |
317 | * InsMenuItem supports meta chars in item text which can |
318 | * have side effects, so insert a blank item and then set its |
319 | * name with SetItem which does not suport meta chars. |
320 | */ |
321 | strlcpy(ssid, wifi_menu_networks[n].ssid, sizeof(ssid)); |
322 | CtoPstr(ssid); |
323 | |
324 | if (n > 0) |
325 | InsMenuItem(wifi_da.ssid_menu, "\p...", mitem); |
326 | |
327 | SetItem(wifi_da.ssid_menu, mitem, ssid); |
328 | |
329 | if (wifi_cur_info.ssid[0] == '\0' && n == 0) |
330 | CheckItem(wifi_da.ssid_menu, mitem, true); |
331 | else |
332 | CheckItem(wifi_da.ssid_menu, mitem, |
333 | (strcmp(wifi_menu_networks[n].ssid, |
334 | wifi_cur_info.ssid) == 0)); |
335 | |
336 | mitem++; |
337 | } |
338 | |
339 | update_window(true); |
340 | } |
341 | |
342 | void |
343 | activate_window(bool activate) |
344 | { |
345 | Rect r; |
346 | GrafPtr savePort; |
347 | |
348 | #if 0 |
349 | GetPort(&savePort); |
350 | SetPort(win); |
351 | r = win->portRect; |
352 | r.top = r.bottom - 16; |
353 | r.left = r.left - 16; |
354 | InvalRect(&r); |
355 | SetPort(savePort); |
356 | #endif |
357 | } |
358 | |
359 | void |
360 | destroy_windows(void) |
361 | { |
362 | ReleaseResource(wifi_da.signal_icons); |
363 | |
364 | if (wifi_da.win) { |
365 | DisposeWindow(wifi_da.win); |
366 | wifi_da.win = 0; |
367 | } |
368 | |
369 | if (wifi_da.logger) { |
370 | DisposeWindow(wifi_da.logger); |
371 | wifi_da.logger = 0; |
372 | } |
373 | } |
374 | |
375 | void |
376 | window_mousedown(Point p) |
377 | { |
378 | Str255 str, password, ssid; |
379 | Rect menu_r, icon_r, r, irect; |
380 | GrafPtr savePort; |
381 | short mitems, n, selitem, hit, itype; |
382 | long new_net; |
383 | struct wifi_network_entry *net; |
384 | struct wifi_join_request wjr; |
385 | DialogPtr dg; |
386 | ControlHandle ihandle; |
387 | |
388 | GetPort(&savePort); |
389 | SetPort(wifi_da.win); |
390 | |
391 | icon_r = wifi_da.icon_rect; |
392 | LocalToGlobal(&icon_r); |
393 | |
394 | /* XXX: why does PtInRect not work? */ |
395 | |
396 | if (p.h >= icon_r.left && p.h <= icon_r.left + icon_r.right && |
397 | p.v >= icon_r.top && p.v <= icon_r.top + icon_r.bottom) { |
398 | if (wifi_da.logger) { |
399 | DisposeWindow(wifi_da.logger); |
400 | wifi_da.logger = 0; |
401 | } else |
402 | create_logger(); |
403 | return; |
404 | } |
405 | |
406 | menu_r = wifi_da.ssid_menu_rect; |
407 | LocalToGlobal(&menu_r); |
408 | |
409 | if (!(p.h >= menu_r.left && p.h <= menu_r.left + menu_r.right && |
410 | p.v >= menu_r.top && p.v <= menu_r.top + menu_r.bottom)) { |
411 | SetPort(savePort); |
412 | return; |
413 | } |
414 | |
415 | if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
416 | return; |
417 | |
418 | InsertMenu(wifi_da.ssid_menu, -1); |
419 | |
420 | mitems = CountMItems(wifi_da.ssid_menu); |
421 | selitem = 1; |
422 | for (n = 0; n < mitems; n++) { |
423 | if (strcmp(wifi_menu_networks[n].ssid, wifi_cur_info.ssid) == 0) { |
424 | selitem = n + 1; |
425 | break; |
426 | } |
427 | } |
428 | |
429 | new_net = PopUpMenuSelect(wifi_da.ssid_menu, menu_r.top + 1, |
430 | menu_r.left + 1, selitem); |
431 | |
432 | DeleteMenu((*(wifi_da.ssid_menu))->menuID); |
433 | if (hiword(new_net) == 0 || loword(new_net) == selitem || |
434 | loword(new_net) > nwifi_menu_networks) |
435 | goto menu_done; |
436 | net = &wifi_menu_networks[loword(new_net) - 1]; |
437 | logger_printf("clicked %s (item %d)", |
438 | wifi_menu_networks[loword(new_net) - 1].ssid, loword(new_net)); |
439 | |
440 | memset(&wjr, 0, sizeof(wjr)); |
441 | |
442 | if (net->flags & WIFI_NETWORK_FLAG_HIDDEN) { |
443 | dg = GetNewDialog(OwnedResourceID(PROMPT_DIALOG_ID), 0L, |
444 | (WindowPtr)-1L); |
445 | center_in_screen(((DialogPeek)dg)->window.port.portRect.right, |
446 | ((DialogPeek)dg)->window.port.portRect.bottom, false, &r); |
447 | MoveWindow(dg, r.left, r.top, false); |
448 | |
449 | GetIndString(str, wifi_da.str_res_id, STR_SSID_DIALOG_TITLE_ID); |
450 | SetWTitle(dg, str); |
451 | |
452 | /* continue button */ |
453 | GetDItem(dg, ok, &itype, &ihandle, &irect); |
454 | GetIndString(str, wifi_da.str_res_id, STR_CONTINUE_ID); |
455 | SetCTitle(ihandle, str); |
456 | |
457 | /* cancel button */ |
458 | GetDItem(dg, cancel, &itype, &ihandle, &irect); |
459 | GetIndString(str, wifi_da.str_res_id, STR_CANCEL_ID); |
460 | SetCTitle(ihandle, str); |
461 | |
462 | /* "SSID:" */ |
463 | GetDItem(dg, PROMPT_DIALOG_INPUT_LABEL_ID, &itype, &ihandle, |
464 | &irect); |
465 | GetIndString(str, wifi_da.str_res_id, STR_SSID_ID); |
466 | SetIText(ihandle, str); |
467 | |
468 | /* "Enter the Wi-Fi network SSID:" */ |
469 | GetDItem(dg, PROMPT_DIALOG_TITLE_LABEL_ID, &itype, &ihandle, |
470 | &irect); |
471 | GetIndString(str, wifi_da.str_res_id, STR_ENTER_SSID_ID); |
472 | SetIText(ihandle, str); |
473 | |
474 | ShowWindow(dg); |
475 | SetPort(dg); |
476 | |
477 | /* outline continue button */ |
478 | GetDItem(dg, ok, &itype, &ihandle, &irect); |
479 | PenSize(3, 3); |
480 | InsetRect(&irect, -4, -4); |
481 | FrameRoundRect(&irect, 16, 16); |
482 | PenNormal(); |
483 | |
484 | for (;;) { |
485 | ModalDialog(ModalDialogFilter, &hit); |
486 | if (hit == ok || hit == cancel) |
487 | break; |
488 | } |
489 | |
490 | if (hit != ok) { |
491 | DisposDialog(dg); |
492 | goto menu_done; |
493 | } |
494 | |
495 | GetDItem(dg, PROMPT_DIALOG_INPUT_FIELD_ID, &itype, &ihandle, |
496 | &irect); |
497 | GetIText(ihandle, &ssid); |
498 | PtoCstr(ssid); |
499 | strlcpy(wjr.ssid, (char *)ssid, sizeof(wjr.ssid)); |
500 | |
501 | DisposDialog(dg); |
502 | } else |
503 | strlcpy(wjr.ssid, net->ssid, sizeof(wjr.ssid)); |
504 | |
505 | if (net->flags & WIFI_NETWORK_FLAG_AUTH) { |
506 | dg = GetNewDialog(OwnedResourceID(PROMPT_DIALOG_ID), 0L, |
507 | (WindowPtr)-1L); |
508 | center_in_screen(((DialogPeek)dg)->window.port.portRect.right, |
509 | ((DialogPeek)dg)->window.port.portRect.bottom, false, &r); |
510 | MoveWindow(dg, r.left, r.top, false); |
511 | |
512 | GetIndString(str, wifi_da.str_res_id, STR_PASSWORD_DIALOG_TITLE_ID); |
513 | SetWTitle(dg, str); |
514 | |
515 | /* continue button */ |
516 | GetDItem(dg, ok, &itype, &ihandle, &irect); |
517 | GetIndString(str, wifi_da.str_res_id, STR_CONTINUE_ID); |
518 | SetCTitle(ihandle, str); |
519 | |
520 | /* cancel button */ |
521 | GetDItem(dg, cancel, &itype, &ihandle, &irect); |
522 | GetIndString(str, wifi_da.str_res_id, STR_CANCEL_ID); |
523 | SetCTitle(ihandle, str); |
524 | |
525 | /* "Password:" */ |
526 | GetDItem(dg, PROMPT_DIALOG_INPUT_LABEL_ID, &itype, &ihandle, |
527 | &irect); |
528 | GetIndString(str, wifi_da.str_res_id, STR_PASSWORD_ID); |
529 | SetIText(ihandle, str); |
530 | |
531 | /* "\"^0\" requires a password:" */ |
532 | GetDItem(dg, PROMPT_DIALOG_TITLE_LABEL_ID, &itype, &ihandle, |
533 | &irect); |
534 | GetIndString(str, wifi_da.str_res_id, STR_REQUIRES_PASSWORD_ID); |
535 | SetIText(ihandle, str); |
536 | |
537 | strlcpy((char *)ssid, wjr.ssid, sizeof(ssid)); |
538 | CtoPstr(ssid); |
539 | ParamText(ssid, "\p", "\p", "\p"); |
540 | |
541 | ShowWindow(dg); |
542 | SetPort(dg); |
543 | |
544 | GetDItem(dg, PROMPT_DIALOG_PASSWORD_STORAGE_ID, &itype, &ihandle, |
545 | &irect); |
546 | SetIText(ihandle, "\p"); |
547 | |
548 | /* outline ok button */ |
549 | GetDItem(dg, ok, &itype, &ihandle, &irect); |
550 | PenSize(3, 3); |
551 | InsetRect(&irect, -4, -4); |
552 | FrameRoundRect(&irect, 16, 16); |
553 | PenNormal(); |
554 | |
555 | for (;;) { |
556 | ModalDialog(WiFiPasswordDialogFieldFilter, &hit); |
557 | if (hit == ok || hit == cancel) |
558 | break; |
559 | } |
560 | |
561 | if (hit != ok) { |
562 | DisposDialog(dg); |
563 | goto menu_done; |
564 | } |
565 | |
566 | GetDItem(dg, PROMPT_DIALOG_PASSWORD_STORAGE_ID, &itype, &ihandle, |
567 | &irect); |
568 | GetIText(ihandle, &password); |
569 | PtoCstr(password); |
570 | //DEBUG_LOG(("pass is \"%s\"", password)); |
571 | strlcpy(wjr.key, (char *)password, sizeof(wjr.key)); |
572 | |
573 | DisposDialog(dg); |
574 | } else |
575 | logger_printf("network %s does not have auth rssi:%d channel:%d flags:0x%x", |
576 | net->ssid, (short)net->rssi, (short)net->channel, (short)net->flags); |
577 | |
578 | scsi_wifi_join(wifi_scsi_id, &wjr); |
579 | |
580 | /* force an update of the list */ |
581 | scsi_wifi_info(wifi_scsi_id, &wifi_cur_info); |
582 | update_wifi_ssid_list(false); |
583 | |
584 | menu_done: |
585 | SetPort(savePort); |
586 | } |
587 | |
588 | pascal Boolean |
589 | WiFiPasswordDialogFieldFilter(DialogPtr dlg, EventRecord *event, |
590 | short *hit) |
591 | { |
592 | Str255 password; |
593 | DialogPeek dlgp; |
594 | ControlHandle ihandle; |
595 | Rect irect; |
596 | short sel_start, sel_end, itype; |
597 | char key; |
598 | |
599 | dlgp = (DialogPeek)dlg; |
600 | |
601 | switch (event->what) { |
602 | case keyDown: |
603 | case autoKey: |
604 | sel_start = (*(dlgp->textH))->selStart; |
605 | sel_end = (*(dlgp->textH))->selEnd; |
606 | |
607 | key = event->message & charCodeMask; |
608 | if (event->modifiers & cmdKey) { |
609 | /* TODO: implement DlgPaste for cmd+v? */ |
610 | event->what = nullEvent; |
611 | return FALSE; |
612 | } |
613 | |
614 | GetDItem(dlg, PROMPT_DIALOG_PASSWORD_STORAGE_ID, &itype, |
615 | &ihandle, &irect); |
616 | GetIText(ihandle, &password); |
617 | PtoCstr(password); |
618 | |
619 | if (key == 8) { |
620 | /* backspace */ |
621 | if (sel_start == sel_end && sel_start > 0) |
622 | memmove(password + sel_start - 1, password + sel_start, |
623 | sizeof(password) - sel_start - 1); |
624 | else if (sel_start != sel_end) |
625 | memmove(password + sel_start, password + sel_end, |
626 | sizeof(password) - sel_end - 1); |
627 | } else if (sel_start >= sizeof(password)) { |
628 | event->what = nullEvent; |
629 | return FALSE; |
630 | } else if (key >= ' ' && key <= '~') { |
631 | if (sel_start != sel_end) |
632 | /* delete selection before making space for new char */ |
633 | memmove(password + sel_start, password + sel_end, |
634 | sizeof(password) - sel_end - 1); |
635 | memmove(password + sel_start + 1, password + sel_start, |
636 | sizeof(password) - sel_start - 1); |
637 | password[sel_start] = key; |
638 | event->message = '•'; |
639 | } |
640 | password[(*(dlgp->textH))->teLength + 1] = '\0'; |
641 | CtoPstr(password); |
642 | |
643 | SetIText(ihandle, password); |
644 | sel_start = 0; |
645 | break; |
646 | } |
647 | |
648 | return ModalDialogFilter(dlg, event, hit); |
649 | } |