AmendHub

Download

jcs

/

wifi_da

/

window.c

 

(View History)

jcs   *: Release 1.4 Latest amendment: 44 on 2025-08-19

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 }