| 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 |
cur_bits = wifi_da.win->portBits; |
| 128 |
SetPortBits(&wifi_da.win_shadow); |
| 129 |
|
| 130 |
if (!force) |
| 131 |
BeginUpdate(wifi_da.win); |
| 132 |
|
| 133 |
EraseRect(&wifi_da.win->portRect); |
| 134 |
DrawControls(wifi_da.win); |
| 135 |
|
| 136 |
/* system 6 does not seem to support popupMenuProc, fake it */ |
| 137 |
FrameRect(&wifi_da.ssid_menu_rect); |
| 138 |
MoveTo(wifi_da.ssid_menu_rect.left + 1, wifi_da.ssid_menu_rect.bottom); |
| 139 |
LineTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.bottom); |
| 140 |
MoveTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.top + 1); |
| 141 |
LineTo(wifi_da.ssid_menu_rect.right, wifi_da.ssid_menu_rect.bottom); |
| 142 |
|
| 143 |
TextFont(systemFont); |
| 144 |
TextSize(0); |
| 145 |
GetItem(wifi_da.ssid_menu, 1, &menuText); |
| 146 |
x = 15; |
| 147 |
MoveTo(wifi_da.ssid_menu_rect.left + x, 16); |
| 148 |
|
| 149 |
for (i = 1; i <= menuText[0]; i++) { |
| 150 |
w = CharWidth(menuText[i]); |
| 151 |
if (i < menuText[0] && x + w >= (wifi_da.ssid_menu_rect.right - |
| 152 |
wifi_da.ssid_menu_rect.left - 14)) { |
| 153 |
/* truncate */ |
| 154 |
GetPen(&p); |
| 155 |
MoveTo(p.h - 1, p.v); |
| 156 |
DrawChar('…'); |
| 157 |
break; |
| 158 |
} |
| 159 |
DrawChar(menuText[i]); |
| 160 |
x += w; |
| 161 |
} |
| 162 |
|
| 163 |
HLock(wifi_da.signal_icons); |
| 164 |
|
| 165 |
if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
| 166 |
icon = SIGNAL_NO_DEVICE; |
| 167 |
else if (wifi_scsi_id == WIFI_SCSI_ID_FINDING) |
| 168 |
icon = SIGNAL_FINDING_DEVICE; |
| 169 |
else if (wifi_cur_info.ssid[0] == '\0') |
| 170 |
icon = SIGNAL_NONE; |
| 171 |
else if (wifi_cur_info.rssi >= -60) |
| 172 |
icon = SIGNAL_4; |
| 173 |
else if (wifi_cur_info.rssi >= -70) |
| 174 |
icon = SIGNAL_3; |
| 175 |
else if (wifi_cur_info.rssi >= -75) |
| 176 |
icon = SIGNAL_2; |
| 177 |
else |
| 178 |
icon = SIGNAL_1; |
| 179 |
|
| 180 |
bm.baseAddr = (Ptr)(*(wifi_da.signal_icons))[icon]; |
| 181 |
bm.rowBytes = 2; |
| 182 |
SetRect(&bm.bounds, 0, 0, 16, 16); |
| 183 |
CopyBits(&bm, &wifi_da.win->portBits, &bm.bounds, &wifi_da.icon_rect, |
| 184 |
srcOr, NULL); |
| 185 |
|
| 186 |
HUnlock(wifi_da.signal_icons); |
| 187 |
|
| 188 |
if (!force) |
| 189 |
EndUpdate(wifi_da.win); |
| 190 |
|
| 191 |
SetPortBits(&cur_bits); |
| 192 |
|
| 193 |
CopyBits(&wifi_da.win_shadow, &wifi_da.win->portBits, |
| 194 |
&wifi_da.win_shadow.bounds, &wifi_da.win_shadow.bounds, srcCopy, nil); |
| 195 |
|
| 196 |
ValidRect(&wifi_da.win->portRect); |
| 197 |
SetPort(savePort); |
| 198 |
} |
| 199 |
|
| 200 |
void |
| 201 |
update_wifi_cur_info(void) |
| 202 |
{ |
| 203 |
struct wifi_network_entry old_info; |
| 204 |
|
| 205 |
if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
| 206 |
return; |
| 207 |
|
| 208 |
memcpy(&old_info, &wifi_cur_info, sizeof(old_info)); |
| 209 |
|
| 210 |
scsi_wifi_info(wifi_scsi_id, &wifi_cur_info); |
| 211 |
|
| 212 |
if (memcmp(&old_info, &wifi_cur_info, sizeof(old_info)) != 0) { |
| 213 |
if (memcmp(&old_info.ssid, &wifi_cur_info.ssid, |
| 214 |
sizeof(old_info.ssid)) == 0) { |
| 215 |
/* just updating RSSI */ |
| 216 |
logger_printf("update_wifi_cur_info: just updating rssi to %d", |
| 217 |
wifi_cur_info.rssi); |
| 218 |
update_window(true); |
| 219 |
} else { |
| 220 |
logger_printf("update_wifi_cur_info: updating ssid list"); |
| 221 |
update_wifi_ssid_list(false); |
| 222 |
} |
| 223 |
} |
| 224 |
} |
| 225 |
|
| 226 |
void |
| 227 |
update_wifi_ssid_list(bool update_networks) |
| 228 |
{ |
| 229 |
Str255 str; |
| 230 |
char ssid[64]; |
| 231 |
short n, m, mitem; |
| 232 |
|
| 233 |
if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
| 234 |
return; |
| 235 |
|
| 236 |
if (update_networks) { |
| 237 |
nwifi_scan_networks = scsi_wifi_scan_results(wifi_scsi_id, |
| 238 |
wifi_scan_networks, nitems(wifi_scan_networks)); |
| 239 |
logger_printf("scsi_wifi_scan_results: %d networks", |
| 240 |
nwifi_scan_networks); |
| 241 |
|
| 242 |
if (nwifi_scan_networks == 0) |
| 243 |
logger_printf("no networks found during scan"); |
| 244 |
} |
| 245 |
|
| 246 |
if (nwifi_scan_networks == 0) { |
| 247 |
/* use our current network (or none) as the only one found */ |
| 248 |
memcpy(&wifi_scan_networks, &wifi_cur_info, sizeof(wifi_cur_info)); |
| 249 |
nwifi_scan_networks = 1; |
| 250 |
} |
| 251 |
|
| 252 |
logger_printf("current ssid: %s", wifi_cur_info.ssid[0] == '\0' ? |
| 253 |
"(none)" : wifi_cur_info.ssid); |
| 254 |
|
| 255 |
/* |
| 256 |
* now start building the ssid menu from wifi_scan_networks |
| 257 |
*/ |
| 258 |
|
| 259 |
/* leave room for current network and trailing "(other network)" */ |
| 260 |
if (nwifi_scan_networks > MAX_WIFI_NETWORKS - 2) { |
| 261 |
nwifi_scan_networks = MAX_WIFI_NETWORKS - 2; |
| 262 |
logger_printf("capping wifi_scan_networks to %d", |
| 263 |
nwifi_scan_networks); |
| 264 |
} |
| 265 |
|
| 266 |
/* put the current network (if any) first in the menu */ |
| 267 |
logger_printf("menu[0]: %s", wifi_cur_info.ssid[0] ? |
| 268 |
wifi_cur_info.ssid : "(no network)"); |
| 269 |
memcpy(&wifi_menu_networks[0], &wifi_cur_info, |
| 270 |
sizeof(wifi_menu_networks[0])); |
| 271 |
nwifi_menu_networks = 1; |
| 272 |
|
| 273 |
/* add each additional network from the scan */ |
| 274 |
for (n = 0; n < nwifi_scan_networks; n++) { |
| 275 |
/* except current one, which we added first */ |
| 276 |
if (strcmp(wifi_scan_networks[n].ssid, wifi_cur_info.ssid) == 0) |
| 277 |
continue; |
| 278 |
|
| 279 |
memcpy(&wifi_menu_networks[nwifi_menu_networks], |
| 280 |
&wifi_scan_networks[n], sizeof(wifi_menu_networks[0])); |
| 281 |
logger_printf("menu[%d]: %s", nwifi_menu_networks, |
| 282 |
wifi_menu_networks[nwifi_menu_networks].ssid); |
| 283 |
nwifi_menu_networks++; |
| 284 |
} |
| 285 |
|
| 286 |
if (wifi_menu_networks[0].ssid[0] == '\0') { |
| 287 |
/* replace blank string with "(no network)" */ |
| 288 |
GetIndString(str, wifi_da.str_res_id, STR_NO_NETWORK_ID); |
| 289 |
PtoCstr(str); |
| 290 |
strlcpy(wifi_menu_networks[0].ssid, (char *)str, |
| 291 |
sizeof(wifi_menu_networks[0].ssid)); |
| 292 |
} |
| 293 |
|
| 294 |
/* add "other network" as last entry */ |
| 295 |
nwifi_menu_networks++; |
| 296 |
if (nwifi_menu_networks > MAX_WIFI_NETWORKS) |
| 297 |
panic("nwifi_menu_networks overflow"); |
| 298 |
GetIndString(str, wifi_da.str_res_id, STR_OTHER_NETWORK_ID); |
| 299 |
PtoCstr(str); |
| 300 |
strlcpy(wifi_menu_networks[nwifi_menu_networks - 1].ssid, |
| 301 |
(char *)str, sizeof(wifi_menu_networks[0].ssid)); |
| 302 |
wifi_menu_networks[nwifi_menu_networks - 1].flags = |
| 303 |
WIFI_NETWORK_FLAG_AUTH | WIFI_NETWORK_FLAG_HIDDEN; |
| 304 |
logger_printf("menu[%d]: %s", nwifi_menu_networks - 1, |
| 305 |
"(other network)"); |
| 306 |
|
| 307 |
/* |
| 308 |
* leave the first item and we'll set its text later but delete all |
| 309 |
* others |
| 310 |
*/ |
| 311 |
while (CountMItems(wifi_da.ssid_menu) > 1) |
| 312 |
DelMenuItem(wifi_da.ssid_menu, 2); |
| 313 |
|
| 314 |
for (n = 0, mitem = 1; n < nwifi_menu_networks; n++) { |
| 315 |
/* |
| 316 |
* InsMenuItem supports meta chars in item text which can |
| 317 |
* have side effects, so insert a blank item and then set its |
| 318 |
* name with SetItem which does not suport meta chars. |
| 319 |
*/ |
| 320 |
strlcpy(ssid, wifi_menu_networks[n].ssid, sizeof(ssid)); |
| 321 |
CtoPstr(ssid); |
| 322 |
|
| 323 |
if (n > 0) |
| 324 |
InsMenuItem(wifi_da.ssid_menu, "\p...", mitem); |
| 325 |
|
| 326 |
SetItem(wifi_da.ssid_menu, mitem, ssid); |
| 327 |
|
| 328 |
if (wifi_cur_info.ssid[0] == '\0' && n == 0) |
| 329 |
CheckItem(wifi_da.ssid_menu, mitem, true); |
| 330 |
else |
| 331 |
CheckItem(wifi_da.ssid_menu, mitem, |
| 332 |
(strcmp(wifi_menu_networks[n].ssid, |
| 333 |
wifi_cur_info.ssid) == 0)); |
| 334 |
|
| 335 |
mitem++; |
| 336 |
} |
| 337 |
|
| 338 |
update_window(true); |
| 339 |
} |
| 340 |
|
| 341 |
void |
| 342 |
activate_window(bool activate) |
| 343 |
{ |
| 344 |
#if 0 |
| 345 |
Rect r; |
| 346 |
GrafPtr savePort; |
| 347 |
|
| 348 |
GetPort(&savePort); |
| 349 |
SetPort(win); |
| 350 |
r = win->portRect; |
| 351 |
r.top = r.bottom - 16; |
| 352 |
r.left = r.left - 16; |
| 353 |
InvalRect(&r); |
| 354 |
SetPort(savePort); |
| 355 |
#endif |
| 356 |
} |
| 357 |
|
| 358 |
void |
| 359 |
destroy_windows(void) |
| 360 |
{ |
| 361 |
ReleaseResource(wifi_da.signal_icons); |
| 362 |
|
| 363 |
if (wifi_da.win) { |
| 364 |
DisposeWindow(wifi_da.win); |
| 365 |
wifi_da.win = 0; |
| 366 |
} |
| 367 |
|
| 368 |
if (wifi_da.logger) { |
| 369 |
DisposeWindow(wifi_da.logger); |
| 370 |
wifi_da.logger = 0; |
| 371 |
} |
| 372 |
} |
| 373 |
|
| 374 |
void |
| 375 |
window_mousedown(Point p) |
| 376 |
{ |
| 377 |
Str255 str, password, ssid; |
| 378 |
Rect menu_r, icon_r, r, irect; |
| 379 |
GrafPtr savePort; |
| 380 |
short mitems, n, selitem, hit, itype; |
| 381 |
long new_net; |
| 382 |
struct wifi_network_entry *net; |
| 383 |
struct wifi_join_request wjr; |
| 384 |
DialogPtr dg; |
| 385 |
ControlHandle ihandle; |
| 386 |
|
| 387 |
GetPort(&savePort); |
| 388 |
SetPort(wifi_da.win); |
| 389 |
|
| 390 |
icon_r = wifi_da.icon_rect; |
| 391 |
LocalToGlobal(&icon_r); |
| 392 |
|
| 393 |
/* XXX: why does PtInRect not work? */ |
| 394 |
|
| 395 |
if (p.h >= icon_r.left && p.h <= icon_r.left + icon_r.right && |
| 396 |
p.v >= icon_r.top && p.v <= icon_r.top + icon_r.bottom) { |
| 397 |
if (wifi_da.logger) { |
| 398 |
DisposeWindow(wifi_da.logger); |
| 399 |
wifi_da.logger = 0; |
| 400 |
} else |
| 401 |
create_logger(); |
| 402 |
return; |
| 403 |
} |
| 404 |
|
| 405 |
menu_r = wifi_da.ssid_menu_rect; |
| 406 |
LocalToGlobal(&menu_r); |
| 407 |
|
| 408 |
if (!(p.h >= menu_r.left && p.h <= menu_r.left + menu_r.right && |
| 409 |
p.v >= menu_r.top && p.v <= menu_r.top + menu_r.bottom)) { |
| 410 |
SetPort(savePort); |
| 411 |
return; |
| 412 |
} |
| 413 |
|
| 414 |
if (wifi_scsi_id == WIFI_SCSI_ID_NONE) |
| 415 |
return; |
| 416 |
|
| 417 |
InsertMenu(wifi_da.ssid_menu, -1); |
| 418 |
|
| 419 |
mitems = CountMItems(wifi_da.ssid_menu); |
| 420 |
selitem = 1; |
| 421 |
for (n = 0; n < mitems; n++) { |
| 422 |
if (strcmp(wifi_menu_networks[n].ssid, wifi_cur_info.ssid) == 0) { |
| 423 |
selitem = n + 1; |
| 424 |
break; |
| 425 |
} |
| 426 |
} |
| 427 |
|
| 428 |
new_net = PopUpMenuSelect(wifi_da.ssid_menu, menu_r.top + 1, |
| 429 |
menu_r.left + 1, selitem); |
| 430 |
|
| 431 |
DeleteMenu((*(wifi_da.ssid_menu))->menuID); |
| 432 |
if (hiword(new_net) == 0 || loword(new_net) == selitem || |
| 433 |
loword(new_net) > nwifi_menu_networks) |
| 434 |
goto menu_done; |
| 435 |
net = &wifi_menu_networks[loword(new_net) - 1]; |
| 436 |
logger_printf("clicked %s (item %d, flags 0x%x)", |
| 437 |
wifi_menu_networks[loword(new_net) - 1].ssid, loword(new_net), |
| 438 |
wifi_menu_networks[loword(new_net) - 1].flags); |
| 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 |
} |