1 #include "settings.h"
2 
3 #include "../debug.h"
4 #include "../flist.h"
5 #include "../macros.h"
6 #include "../self.h"
7 #include "../theme.h"
8 #include "../tox.h"
9 
10 #include "../av/video.h"
11 
12 #include "../native/clipboard.h"
13 #include "../native/dialog.h"
14 #include "../native/filesys.h"
15 #include "../native/keyboard.h"
16 #include "../native/notify.h"
17 #include "../native/os.h"
18 
19 #include "../ui/button.h"
20 #include "../ui/contextmenu.h"
21 #include "../ui/draw.h"
22 #include "../ui/dropdown.h"
23 #include "../ui/edit.h"
24 #include "../ui/scrollable.h"
25 #include "../ui/svg.h"
26 #include "../ui/switch.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 /* Top bar for user settings */
draw_settings_header(int x,int y,int w,int UNUSED (height))33 static void draw_settings_header(int x, int y, int w, int UNUSED(height)) {
34     (void)w; // Silence an irreverent warning when GIT_VERSION is undefined
35     setcolor(COLOR_MAIN_TEXT);
36     setfont(FONT_SELF_NAME);
37     drawstr(x + SCALE(10), y + SCALE(10), UTOX_SETTINGS);
38 #ifdef GIT_VERSION
39     setfont(FONT_TEXT);
40     char ver_string[64];
41     int  ver_string_len;
42 
43     snprintf(ver_string, sizeof(ver_string), "Toxcore v%u.%u.%u",
44              tox_version_major(), tox_version_minor(), tox_version_patch());
45     ver_string_len = strnlen(ver_string, sizeof(ver_string) - 1);
46 
47     drawtextwidth_right(x + w - textwidth(ver_string, ver_string_len),
48                         textwidth(ver_string, ver_string_len), SCALE(10),
49                         ver_string, ver_string_len);
50 
51     setfont(FONT_SELF_NAME); // x adjustment depends on the font type being set first
52     x += SCALE(25) + UTOX_STR_WIDTH(UTOX_SETTINGS);
53     setfont(FONT_TEXT);
54     drawtext(x, SCALE(10), GIT_VERSION, strlen(GIT_VERSION));
55 #endif
56 }
57 
58 #define DRAW_UNDERLINE() drawhline(x, y + SCALE(28), next_x, COLOR_EDGE_NORMAL)
59 #define DRAW_OVERLINE()  drawhline(x, y + SCALE(0), next_x, COLOR_EDGE_ACTIVE); \
60                          drawhline(x, y + SCALE(1), next_x, COLOR_EDGE_ACTIVE)
61 
draw_settings_sub_header(int x,int y,int width,int UNUSED (height))62 static void draw_settings_sub_header(int x, int y, int width, int UNUSED(height)) {
63     drawhline(x, y, x + width, COLOR_EDGE_NORMAL);
64 
65     setfont(FONT_SELF_NAME);
66     int last_x = x + width;
67 
68     /* Draw the text and bars for general settings */
69     setcolor(!button_settings_sub_profile.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
70     int next_x = x + SCALE(20) + UTOX_STR_WIDTH(PROFILE_BUTTON);
71     drawstr(x + SCALE(10), y + SCALE(10), PROFILE_BUTTON);
72 
73     if (panel_settings_profile.disabled) {
74         DRAW_UNDERLINE();
75     } else {
76         DRAW_OVERLINE();
77     }
78     drawvline(next_x, y, y + SCALE(28), COLOR_EDGE_NORMAL);
79     x = next_x;
80 
81     /* Draw the text and bars for device settings */
82     #ifdef ENABLE_MULTIDEVICE
83     setcolor(!button_settings_sub_devices.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
84     next_x += SCALE(20) + UTOX_STR_WIDTH(DEVICES_BUTTON);
85     drawstr(x + SCALE(10), y, + SCALE(10), DEVICES_BUTTON);
86     if (panel_settings_devices.disabled) {
87         DRAW_UNDERLINE();
88     } else {
89         DRAW_OVERLINE();
90     }
91     drawvline(next_x, y, y, + SCALE(28), COLOR_EDGE_NORMAL);
92     x = next_x;
93     #endif
94 
95     /* Draw the text and bars for User interface settings */
96     setcolor(!button_settings_sub_ui.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
97     next_x += SCALE(20) + UTOX_STR_WIDTH(USER_INTERFACE_BUTTON);
98     drawstr(x + SCALE(10), y + SCALE(10), USER_INTERFACE_BUTTON);
99     if (panel_settings_ui.disabled) {
100         DRAW_UNDERLINE();
101     } else {
102         DRAW_OVERLINE();
103     }
104     drawvline(next_x, y, y + SCALE(28), COLOR_EDGE_NORMAL);
105     x = next_x;
106 
107     /* Draw the text and bars for A/V settings */
108     setcolor(!button_settings_sub_av.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
109     next_x += SCALE(20) + UTOX_STR_WIDTH(AUDIO_VIDEO_BUTTON);
110     drawstr(x + SCALE(10), y + SCALE(10), AUDIO_VIDEO_BUTTON);
111     if (panel_settings_av.disabled) {
112         DRAW_UNDERLINE();
113     } else {
114         DRAW_OVERLINE();
115     }
116     drawvline(next_x, y, y + SCALE(28), COLOR_EDGE_NORMAL);
117     x = next_x;
118 
119     /* Draw the text and bars for notification settings */
120     setcolor(!button_settings_sub_notifications.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
121     next_x += SCALE(20) + UTOX_STR_WIDTH(NOTIFICATIONS_BUTTON);
122     drawstr(x + SCALE(10), y + SCALE(10), NOTIFICATIONS_BUTTON);
123     if (panel_settings_notifications.disabled) {
124         DRAW_UNDERLINE();
125     } else {
126         DRAW_OVERLINE();
127     }
128     drawvline(next_x, y, y + SCALE(28), COLOR_EDGE_NORMAL);
129     x = next_x;
130 
131     /* Draw the text and bars for advanced settings */
132     setcolor(!button_settings_sub_adv.mouseover ? COLOR_MAIN_TEXT : COLOR_MAIN_TEXT_SUBTEXT);
133     next_x += SCALE(20) + UTOX_STR_WIDTH(ADVANCED_BUTTON);
134     drawstr(x + SCALE(10), y + SCALE(10), ADVANCED_BUTTON);
135     if (panel_settings_adv.disabled) {
136         DRAW_UNDERLINE();
137     } else {
138         DRAW_OVERLINE();
139     }
140     drawvline(next_x, y, y + SCALE(28), COLOR_EDGE_NORMAL);
141     x = next_x;
142 
143     next_x = last_x;
144     DRAW_UNDERLINE();
145 }
146 
147 /* draw switch profile top bar */
148 /* Text content for settings page */
draw_settings_text_profile(int x,int y,int UNUSED (w),int UNUSED (h))149 static void draw_settings_text_profile(int x, int y, int UNUSED(w), int UNUSED(h)) {
150     setcolor(COLOR_MAIN_TEXT);
151     setfont(FONT_SELF_NAME);
152     drawstr(x + SCALE(10), y + SCALE(10), NAME);
153     drawstr(x + SCALE(10), y + SCALE(65), STATUSMESSAGE);
154     drawstr(x + SCALE(10), y + SCALE(120), TOXID);
155 
156     if (self.qr_image && !button_qr.disabled) {
157         // Enlarge original QR for better recognition
158         const double image_scale = SCALE(4);
159         const uint32_t image_size = self.qr_image_size * image_scale;
160 
161         button_qr.panel.width = button_qr.panel.height = UN_SCALE(self.qr_image_size * image_scale);
162 
163         image_set_scale(self.qr_image, image_scale);
164         draw_image(self.qr_image, x + SCALE(10), y + SCALE(175), image_size, image_size, 0, 0);
165         image_set_scale(self.qr_image, 1.0);
166     }
167 }
168 
169 // Devices settings page
draw_settings_text_devices(int x,int y,int UNUSED (w),int UNUSED (h))170 static void draw_settings_text_devices(int x, int y, int UNUSED(w), int UNUSED(h)) {
171     setcolor(COLOR_MAIN_TEXT);
172     setfont(FONT_SELF_NAME);
173     drawstr(x + SCALE(10), y + SCALE(10), DEVICES_ADD_NEW);
174 
175     drawstr(x + SCALE(10), y + SCALE(60), DEVICES_NUMBER);
176 
177     char   str[10];
178 
179     snprintf(str, sizeof(str), "%zu", self.device_list_count);
180     size_t str_len = strnlen(str, sizeof(str) - 1);
181 
182     drawtext(x + SCALE(10), y + SCALE(75), str, str_len);
183 }
184 
draw_settings_text_password(int x,int y,int UNUSED (w),int UNUSED (h))185 static void draw_settings_text_password(int x, int y, int UNUSED(w), int UNUSED(h)) {
186     setcolor(COLOR_MAIN_TEXT);
187     setfont(FONT_SELF_NAME);
188     drawstr(x + SCALE(10), y + SCALE(215), PROFILE_PASSWORD);
189 
190     setfont(FONT_MISC);
191     setcolor(C_RED);
192     drawstr(x + SCALE(10), y + SCALE(289), PROFILE_PW_WARNING);
193     drawstr(x + SCALE(10), y + SCALE(301), PROFILE_PW_NO_RECOVER);
194 }
195 
draw_nospam_settings(int x,int y,int UNUSED (w),int UNUSED (h))196 static void draw_nospam_settings(int x, int y, int UNUSED(w), int UNUSED(h)){
197     setfont(FONT_MISC);
198     setcolor(C_RED);
199     drawstr(x + SCALE(95), y + SCALE(218), NOSPAM_WARNING);
200 
201     setcolor(COLOR_MAIN_TEXT);
202     setfont(FONT_SELF_NAME);
203 
204     drawstr(x + SCALE(10), y + SCALE(215), NOSPAM);
205 }
206 
207 // UI settings page
draw_settings_text_ui(int x,int y,int UNUSED (w),int UNUSED (height))208 static void draw_settings_text_ui(int x, int y, int UNUSED(w), int UNUSED(height)) {
209     setcolor(COLOR_MAIN_TEXT);
210     setfont(FONT_SELF_NAME);
211     drawstr(x + SCALE(10), y + SCALE(10), LANGUAGE);
212     drawstr(x + SCALE(150), y + SCALE(65),  DPI);
213     drawstr(x + SCALE(10),  y + SCALE(65),  THEME);
214     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH,  y + SCALE(120),  SAVE_CHAT_HISTORY);
215     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH,  y + SCALE(150),  CLOSE_TO_TRAY);
216     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH,  y + SCALE(180), START_IN_TRAY);
217     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH,  y + SCALE(210), AUTO_STARTUP);
218     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH,  y + SCALE(240), SETTINGS_UI_MINI_ROSTER);
219     #if PLATFORM_ANDROID
220         drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(270), SETTINGS_UI_AUTO_HIDE_SIDEBAR);
221     #endif
222 }
223 
224 // Audio/Video settings page
draw_settings_text_av(int x,int y,int UNUSED (w),int UNUSED (height))225 static void draw_settings_text_av(int x, int y, int UNUSED(w), int UNUSED(height)) {
226     setcolor(COLOR_MAIN_TEXT);
227     setfont(FONT_SELF_NAME);
228 
229     // The element is draw_pos_y_inc units apart and they start draw_pos_y down.
230     uint16_t draw_pos_y = 15;
231     uint16_t draw_pos_y_inc = 30;
232 
233     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(draw_pos_y), PUSH_TO_TALK);
234     draw_pos_y += draw_pos_y_inc;
235 #ifdef AUDIO_FILTERING
236     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(draw_pos_y), AUDIOFILTERING);
237     draw_pos_y += draw_pos_y_inc;
238 #endif
239 
240     // These are 60 apart as there needs to be room for a dropdown between them.
241     draw_pos_y_inc = 60;
242 
243     drawstr(x + SCALE(10), y + SCALE(draw_pos_y), AUDIOINPUTDEVICE);
244     draw_pos_y += draw_pos_y_inc;
245     drawstr(x + SCALE(10), y + SCALE(draw_pos_y - 7), AUDIOOUTPUTDEVICE);
246     draw_pos_y += draw_pos_y_inc;
247     drawstr(x + SCALE(10), y + SCALE(draw_pos_y - 15), VIDEOFRAMERATE);
248     draw_pos_y += draw_pos_y_inc;
249     drawstr(x + SCALE(10), y + SCALE(draw_pos_y - 23), VIDEOINPUTDEVICE);
250     draw_pos_y += draw_pos_y_inc;
251     drawstr(x + SCALE(10), y + SCALE(draw_pos_y - 30), PREVIEW);
252 }
253 
254 // Notification settings page
draw_settings_text_notifications(int x,int y,int UNUSED (w),int UNUSED (height))255 static void draw_settings_text_notifications(int x, int y, int UNUSED(w), int UNUSED(height)) {
256     setcolor(COLOR_MAIN_TEXT);
257     setfont(FONT_SELF_NAME);
258 
259     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(15), RINGTONE);
260     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(45), STATUS_NOTIFICATIONS);
261     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(75), SEND_TYPING_NOTIFICATIONS);
262     drawstr(x + SCALE(10), y + SCALE(105), GROUP_NOTIFICATIONS);
263 }
264 
draw_settings_text_adv(int x,int y,int UNUSED (w),int UNUSED (height))265 static void draw_settings_text_adv(int x, int y, int UNUSED(w), int UNUSED(height)) {
266     setfont(FONT_MISC);
267     setcolor(C_RED);
268     drawstr(x + SCALE(10), y + SCALE(5), WARNING);
269 
270     setcolor(COLOR_MAIN_TEXT);
271     setfont(FONT_SELF_NAME);
272 
273     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(30),  IPV6);
274     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(60),  UDP);
275     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(90),  PROXY);
276     drawstr(x + SCALE(20) + BM_SWITCH_WIDTH, y + SCALE(120), PROXY_FORCE); // TODO draw ONLY when settings.use_proxy = true
277     drawtext(x + SCALE(353), y + SCALE(89), ":", 1); // Little addr port separator
278 
279     drawstr(x + SCALE(20)+ BM_SWITCH_WIDTH, y + SCALE(150), BLOCK_FRIEND_REQUESTS);
280 }
281 
282 
283 SCROLLABLE scrollbar_settings = {
284     .panel = { .type = PANEL_SCROLLABLE, },
285     .color = C_SCROLL,
286 };
287 
288 /* Draw the text for profile password window */
draw_profile_password(int x,int UNUSED (y),int UNUSED (w),int UNUSED (height))289 static void draw_profile_password(int x, int UNUSED(y), int UNUSED(w), int UNUSED(height)) {
290     setcolor(COLOR_MAIN_TEXT);
291     setfont(FONT_SELF_NAME);
292     drawstr(x + SCALE(10), SCALE(10), PROFILE_PASSWORD);
293 
294     setcolor(COLOR_MAIN_TEXT_SUBTEXT);
295     setfont(FONT_TEXT);
296     drawstr(x + SCALE(10), SCALE(MAIN_TOP + 5), PROFILE_PASSWORD);
297 }
298 
299 PANEL
300 boxfor_password_entry_login = {
301     .type = PANEL_NONE,
302     .x = 0, .y = 0,
303     .child = (PANEL*[]) {
304         (PANEL*)&edit_profile_password,
305         NULL
306     }
307 },
308 boxfor_password_entry_change = {
309     .type = PANEL_NONE,
310     .x = 0, .y = 180,
311     .child = (PANEL*[]) {
312         (PANEL*)&edit_profile_password,
313         NULL
314     }
315 },
316 panel_profile_password = {
317     .type = PANEL_NONE,
318     .disabled = 0,
319     .drawfunc = draw_profile_password,
320     .child = (PANEL*[]) {
321         (PANEL*)&boxfor_password_entry_login,
322         NULL
323     }
324 },
325 panel_nospam_settings = {
326     .type = PANEL_NONE,
327     .disabled = true,
328     .drawfunc = draw_nospam_settings,
329     .content_scroll = &scrollbar_settings,
330     .child = (PANEL*[]) {
331         (PANEL*)&edit_nospam,
332         (PANEL*)&button_change_nospam,
333         (PANEL*)&button_revert_nospam,
334         NULL
335      }
336 },
337 panel_profile_password_settings = {
338     .type     = PANEL_NONE,
339     .disabled = 1,
340     .drawfunc = draw_settings_text_password,
341     .child = (PANEL*[]) {
342         (PANEL*)&boxfor_password_entry_change,
343         (PANEL*)&button_lock_uTox,
344         NULL
345     }
346 },
347 panel_settings_master = {
348     .type = PANEL_NONE,
349     .disabled = 1,
350     .drawfunc = draw_settings_header,
351     .child = (PANEL*[]) {
352         &panel_settings_subheader,
353         NULL
354     }
355 },
356     panel_settings_subheader = {
357         .y = MAIN_TOP_FRAME_THIN,
358         .type = PANEL_NONE,
359         .disabled = 0,
360         .drawfunc = draw_settings_sub_header,
361         .child = (PANEL*[]) {
362             (PANEL*)&button_settings_sub_profile,
363             (PANEL*)&button_settings_sub_devices,
364             (PANEL*)&button_settings_sub_ui,
365             (PANEL*)&button_settings_sub_av,
366             (PANEL*)&button_settings_sub_notifications,
367             (PANEL*)&button_settings_sub_adv,
368             (PANEL*)&scrollbar_settings,
369             &panel_settings_profile,
370             &panel_settings_devices,
371             &panel_settings_ui,
372             &panel_settings_av,
373             &panel_settings_notifications,
374             &panel_settings_adv,
375             NULL
376         }
377     },
378     /* Panel to draw settings page */
379     panel_settings_profile = {
380         .type = PANEL_NONE,
381         .disabled = 0,
382         .drawfunc = draw_settings_text_profile,
383         .content_scroll = &scrollbar_settings,
384         .child = (PANEL*[]) {
385             (PANEL*)&edit_name,
386             (PANEL*)&edit_status_msg,
387             // Text: Tox ID
388             (PANEL*)&edit_toxid,
389             (PANEL*)&button_copyid,
390             (PANEL*)&button_show_qr,
391             (PANEL*)&button_qr,
392             NULL
393         }
394     },
395     /* Panel to draw settings page */
396     panel_settings_devices = {
397         .type = PANEL_NONE,
398         .disabled = 1,
399         .drawfunc = draw_settings_text_devices,
400         .content_scroll = &scrollbar_settings,
401         .child = NULL,
402     },
403     panel_settings_ui = {
404         .type = PANEL_NONE,
405         .drawfunc = draw_settings_text_ui,
406         .disabled = 1,
407         .content_scroll = &scrollbar_settings,
408         .child = (PANEL*[]) {
409             (PANEL*)&dropdown_language,
410             (PANEL*)&dropdown_dpi,
411             (PANEL*)&dropdown_theme,
412             (PANEL*)&switch_save_chat_history,
413             (PANEL*)&switch_close_to_tray,
414             (PANEL*)&switch_start_in_tray,
415             (PANEL*)&switch_auto_startup,
416             (PANEL*)&switch_mini_contacts,
417             #if PLATFORM_ANDROID
418                 (PANEL*)&switch_magic_sidebar,
419             #endif
420             NULL
421         }
422     },
423     panel_settings_av = {
424         .type = PANEL_NONE,
425         .disabled = 1,
426         .drawfunc = draw_settings_text_av,
427         .content_scroll = &scrollbar_settings,
428         .child = (PANEL*[]) {
429             (PANEL*)&button_callpreview,
430             (PANEL*)&switch_push_to_talk,
431             (PANEL*)&button_videopreview,
432             (PANEL*)&edit_video_fps,
433             (PANEL*)&dropdown_audio_in,
434             (PANEL*)&dropdown_audio_out,
435             (PANEL*)&dropdown_video,
436             (PANEL*)&switch_audio_filtering,
437             NULL
438         }
439     },
440 
441     panel_settings_notifications = {
442         .type = PANEL_NONE,
443         .disabled = true,
444         .drawfunc = draw_settings_text_notifications,
445         .content_scroll = &scrollbar_settings,
446         .child = (PANEL*[]) {
447             (PANEL*)&dropdown_global_group_notifications,
448             (PANEL*)&switch_status_notifications,
449             (PANEL*)&switch_typing_notes,
450             (PANEL*)&switch_audible_notifications,
451             NULL
452         }
453     },
454 
455     panel_settings_adv = {
456         .type = PANEL_NONE,
457         .disabled = true,
458         .drawfunc = draw_settings_text_adv,
459         .content_scroll = &scrollbar_settings,
460         .child = (PANEL*[]) {
461             (PANEL*)&edit_proxy_ip,
462             (PANEL*)&edit_proxy_port,
463             (PANEL*)&switch_proxy,
464             (PANEL*)&switch_proxy_force,
465             (PANEL*)&switch_ipv6,
466             (PANEL*)&switch_udp,
467             (PANEL*)&button_show_password_settings,
468             &panel_profile_password_settings,
469             (PANEL*)&switch_block_friend_requests,
470             (PANEL*)&button_show_nospam,
471             &panel_nospam_settings,
472             NULL,
473         }
474     };
475 
476 
477 extern SCROLLABLE scrollbar_settings;
478 
button_bottommenu_update(BUTTON * b)479 static void button_bottommenu_update(BUTTON *b) {
480     b->c1  = COLOR_BKGRND_MENU;
481     b->c2  = COLOR_BKGRND_MENU_HOVER;
482     b->c3  = COLOR_BKGRND_MENU_ACTIVE;
483     b->ct1 = COLOR_MENU_TEXT;
484     b->ct2 = COLOR_MENU_TEXT;
485     if (b->mousedown || b->disabled) {
486         b->ct1 = COLOR_MENU_TEXT_ACTIVE;
487         b->ct2 = COLOR_MENU_TEXT_ACTIVE;
488     }
489     b->cd = COLOR_BKGRND_MENU_ACTIVE;
490 }
491 
button_settings_on_mup(void)492 static void button_settings_on_mup(void) {
493     if (tox_thread_init == UTOX_TOX_THREAD_INIT_SUCCESS) {
494         flist_selectsettings();
495     }
496 }
497 
update_show_nospam_button_text(void)498 static void update_show_nospam_button_text(void) {
499     if (panel_nospam_settings.disabled) {
500         maybe_i18nal_string_set_i18nal(&button_show_nospam.button_text, STR_SHOW_NOSPAM);
501     } else {
502         maybe_i18nal_string_set_i18nal(&button_show_nospam.button_text, STR_HIDE_NOSPAM);
503     }
504 }
505 
update_show_password_button_text(void)506 static void update_show_password_button_text(void) {
507     if (panel_profile_password_settings.disabled) {
508         maybe_i18nal_string_set_i18nal(&button_show_password_settings.button_text, STR_SHOW_UI_PASSWORD);
509         maybe_i18nal_string_set_i18nal(&button_show_password_settings.tooltip_text, STR_SHOW_UI_PASSWORD_TOOLTIP);
510     } else {
511         maybe_i18nal_string_set_i18nal(&button_show_password_settings.button_text, STR_HIDE_UI_PASSWORD);
512         maybe_i18nal_string_set_i18nal(&button_show_password_settings.tooltip_text, STR_HIDE_UI_PASSWORD_TOOLTIP);
513     }
514 }
515 
516 BUTTON button_settings = {
517     .panel = {
518         .type   = PANEL_BUTTON,
519         .x      = SIDEBAR_BUTTON_LEFT,
520         .y      = ROSTER_BOTTOM,
521         .width  = SIDEBAR_BUTTON_WIDTH,
522         .height = SIDEBAR_BUTTON_HEIGHT,
523     },
524     .bm_icon          = BM_SETTINGS,
525     .icon_w       = _BM_ADD_WIDTH,
526     .icon_h       = _BM_ADD_WIDTH,
527     .update       = button_bottommenu_update,
528     .on_mup       = button_settings_on_mup,
529     .disabled     = false,
530     .nodraw       = false,
531     .tooltip_text = {.i18nal = STR_USERSETTINGS },
532 };
533 
close_dropdowns(PANEL * p)534 static void close_dropdowns(PANEL *p) {
535     if (!p->child) {
536         return;
537     }
538 
539     PANEL *ch;
540     for (int i = 0; (ch = p->child[i]); ++i)
541     {
542         PANEL_TYPE type = ch->type;
543         if (type == PANEL_DROPDOWN) {
544             dropdown_close((DROPDOWN*)ch);
545         } else if (type == PANEL_NONE) {
546             close_dropdowns(ch);
547         }
548     }
549 }
550 
reset_settings_controls(void)551 void reset_settings_controls(void) {
552     update_show_nospam_button_text();
553     update_show_password_button_text();
554     close_dropdowns(&panel_settings_master);
555 }
556 
disable_all_setting_sub(void)557 static void disable_all_setting_sub(void) {
558     flist_selectsettings();
559     panel_settings_profile.disabled         = true;
560     panel_settings_devices.disabled         = true;
561     panel_settings_ui.disabled              = true;
562     panel_settings_av.disabled              = true;
563     panel_settings_notifications.disabled   = true;
564     panel_settings_adv.disabled             = true;
565     reset_settings_controls();
566 }
567 
button_settings_sub_profile_on_mup(void)568 static void button_settings_sub_profile_on_mup(void) {
569     scrollbar_settings.content_height = SCALE(260);
570     disable_all_setting_sub();
571     panel_settings_profile.disabled = false;
572 }
573 
button_settings_sub_devices_on_mup(void)574 static void button_settings_sub_devices_on_mup(void) {
575     scrollbar_settings.content_height = SCALE(260);
576     disable_all_setting_sub();
577     panel_settings_devices.disabled = false;
578 }
579 
button_settings_sub_ui_on_mup(void)580 static void button_settings_sub_ui_on_mup(void) {
581     scrollbar_settings.content_height = SCALE(280);
582     disable_all_setting_sub();
583     panel_settings_ui.disabled = false;
584 }
585 
button_settings_sub_av_on_mup(void)586 static void button_settings_sub_av_on_mup(void) {
587     scrollbar_settings.content_height = SCALE(350);
588     disable_all_setting_sub();
589     panel_settings_av.disabled = false;
590 }
591 
button_settings_sub_adv_on_mup(void)592 static void button_settings_sub_adv_on_mup(void) {
593     scrollbar_settings.content_height = SCALE(300);
594     disable_all_setting_sub();
595     panel_settings_adv.disabled = false;
596 }
597 
button_settings_sub_notifications_on_mup(void)598 static void button_settings_sub_notifications_on_mup(void){
599     scrollbar_settings.content_height = SCALE(300);
600     disable_all_setting_sub();
601     panel_settings_notifications.disabled = false;
602 }
603 
604 
button_add_device_to_self_mdown(void)605 static void button_add_device_to_self_mdown(void) {
606 #ifdef ENABLE_MULTIDEVICE
607     devices_self_add(edit_add_new_device_to_self.data, edit_add_new_device_to_self.length);
608     edit_resetfocus();
609 #endif
610 }
611 
612 BUTTON
613 button_settings_sub_profile = {
614     .nodraw = true,
615     .on_mup = button_settings_sub_profile_on_mup,
616     .tooltip_text = {.i18nal = STR_PROFILE_BUTTON },
617     .button_text  = {.i18nal = STR_PROFILE_BUTTON },
618 },
619 
620 button_settings_sub_devices = {
621     .nodraw = true,
622     .on_mup = button_settings_sub_devices_on_mup,
623     .tooltip_text = {.i18nal = STR_DEVICES_BUTTON },
624     .button_text  = {.i18nal = STR_DEVICES_BUTTON },
625 },
626 
627 button_settings_sub_ui = {
628     .nodraw = true,
629     .on_mup = button_settings_sub_ui_on_mup,
630     .tooltip_text = {.i18nal = STR_USER_INTERFACE_BUTTON },
631     .button_text  = {.i18nal = STR_USER_INTERFACE_BUTTON },
632 },
633 
634 button_settings_sub_av = {
635     .nodraw = true,
636     .on_mup = button_settings_sub_av_on_mup,
637     .tooltip_text = {.i18nal = STR_AUDIO_VIDEO_BUTTON },
638     .button_text  = {.i18nal = STR_AUDIO_VIDEO_BUTTON },
639 },
640 
641 button_settings_sub_notifications = {
642     .nodraw = true,
643     .on_mup = button_settings_sub_notifications_on_mup,
644     .tooltip_text = {.i18nal = STR_NOTIFICATIONS_BUTTON },
645     .button_text  = {.i18nal = STR_NOTIFICATIONS_BUTTON },
646 },
647 
648 button_settings_sub_adv = {
649     .nodraw = true,
650     .on_mup = button_settings_sub_adv_on_mup,
651     .tooltip_text = {.i18nal = STR_ADVANCED_BUTTON },
652     .button_text  = {.i18nal = STR_ADVANCED_BUTTON },
653 },
654 
655 button_add_new_device_to_self = {
656     .bm_fill         = BM_SBUTTON,
657     .button_text = {.i18nal = STR_ADD },
658     // .update   = button_setcolors_success,
659     .on_mup      = button_add_device_to_self_mdown,
660 };
661 
662 #include "../tox.h"
button_lock_uTox_on_mup(void)663 static void button_lock_uTox_on_mup(void) {
664     if (tox_thread_init && edit_profile_password.length > 3) {
665         flist_selectsettings();
666         panel_profile_password.disabled = false;
667         panel_settings_master.disabled  = true;
668         tox_settingschanged();
669     } else {
670         show_messagebox(NULL, 0, S(PASSWORD_TOO_SHORT), SLEN(PASSWORD_TOO_SHORT));
671         memset(edit_profile_password.data, '\0', edit_profile_password.data_size);
672         edit_profile_password.length = 0;
673     }
674     button_show_password_settings.disabled = false;
675     button_show_password_settings.nodraw = false;
676     update_show_nospam_button_text();
677     update_show_password_button_text();
678 }
679 
button_show_password_settings_on_mup(void)680 static void button_show_password_settings_on_mup(void) {
681     panel_nospam_settings.disabled = true;
682     panel_profile_password_settings.disabled = !panel_profile_password_settings.disabled;
683     update_show_nospam_button_text();
684     update_show_password_button_text();
685 }
686 
687 
688 #include "../chatlog.h"
689 #include "../flist.h"
690 #include "../friend.h"
button_export_chatlog_on_mup(void)691 static void button_export_chatlog_on_mup(void) {
692     FRIEND *f = flist_get_friend();
693     if (!f) {
694         LOG_ERR("Settings", "Could not get selected friend.");
695         return;
696     }
697     utox_export_chatlog_init(f->number);
698 }
699 
button_change_nospam_on_mup(void)700 static void button_change_nospam_on_mup(void) {
701     button_revert_nospam.disabled = false;
702     long int nospam = rand() | rand() << 16;
703     postmessage_toxcore(TOX_SELF_CHANGE_NOSPAM, nospam, 0, NULL);
704 }
705 
button_revert_nospam_on_mup(void)706 static void button_revert_nospam_on_mup(void) {
707     if (button_revert_nospam.disabled) {
708         return;
709     }
710 
711     if (self.old_nospam == 0 || self.nospam == self.old_nospam) { //nospam can not be 0
712         LOG_ERR("Settings", "Invalid or current nospam: %u.", self.old_nospam);
713         return;
714     }
715     postmessage_toxcore(TOX_SELF_CHANGE_NOSPAM, self.old_nospam, 0, NULL);
716     button_revert_nospam.disabled = true;
717 }
718 
button_revert_nospam_on_update(BUTTON * b)719 static void button_revert_nospam_on_update(BUTTON *b) {
720     if (button_revert_nospam.disabled) {
721         button_setcolors_disabled(b);
722     } else {
723         button_setcolors_success(b);
724     }
725 }
726 
button_show_nospam_on_mup(void)727 static void button_show_nospam_on_mup(void) {
728     panel_profile_password_settings.disabled = true;
729     panel_nospam_settings.disabled = !panel_nospam_settings.disabled;
730     update_show_nospam_button_text();
731     update_show_password_button_text();
732 }
733 
button_copyid_on_mup(void)734 static void button_copyid_on_mup(void) {
735     edit_setfocus(&edit_toxid);
736     copy(0);
737 }
738 
button_show_qr_on_mup(void)739 static void button_show_qr_on_mup(void) {
740     if (button_qr.disabled) {
741         maybe_i18nal_string_set_i18nal(&button_show_qr.button_text, STR_HIDE_QR);
742     } else {
743         maybe_i18nal_string_set_i18nal(&button_show_qr.button_text, STR_SHOW_QR);
744     }
745 
746     button_qr.disabled = !button_qr.disabled;
747     button_qr.panel.disabled = button_qr.disabled;
748 }
749 
contextmenu_qr_onselect(uint8_t i)750 static void contextmenu_qr_onselect(uint8_t i) {
751     if (i == 0) {
752         if (!native_save_image_png(self.name, self.qr_data, self.qr_data_size)) {
753             LOG_ERR("Self", "Unable to save QR code.");
754         }
755     }
756 }
757 
button_qr_on_mright(void)758 static void button_qr_on_mright(void) {
759     static UTOX_I18N_STR menu[] = { STR_SAVE_QR };
760     contextmenu_new(COUNTOF(menu), menu, contextmenu_qr_onselect);
761 }
762 
763 #include "../settings.h"
764 #include "../av/utox_av.h"
button_audiopreview_on_mup(void)765 static void button_audiopreview_on_mup(void) {
766     if (!settings.audio_preview) {
767         postmessage_utoxav(UTOXAV_START_AUDIO, 1, 0, NULL);
768     } else {
769         postmessage_utoxav(UTOXAV_STOP_AUDIO, 1, 0, NULL);
770     }
771     settings.audio_preview = !settings.audio_preview;
772 }
773 
button_audiopreview_update(BUTTON * b)774 static void button_audiopreview_update(BUTTON *b) {
775     if (settings.audio_preview) {
776         button_setcolors_danger(b);
777     } else {
778         button_setcolors_success(b);
779     }
780 }
781 
button_videopreview_on_mup(void)782 static void button_videopreview_on_mup(void) {
783     if (settings.video_preview) {
784         postmessage_utoxav(UTOXAV_STOP_VIDEO, UINT16_MAX, 1, NULL);
785     } else if (video_width && video_height) {
786         postmessage_utoxav(UTOXAV_START_VIDEO, UINT16_MAX, 1, NULL);
787     } else {
788         LOG_ERR("Button", "Video_width = 0, can't preview\n");
789         return;
790     }
791     settings.video_preview = !settings.video_preview;
792 }
793 
button_videopreview_update(BUTTON * b)794 static void button_videopreview_update(BUTTON *b) {
795     if (settings.video_preview) {
796         button_setcolors_danger(b);
797     } else {
798         button_setcolors_success(b);
799     }
800 }
801 
button_show_qr_update(BUTTON * b)802 static void button_show_qr_update(BUTTON *b) {
803     button_setcolors_success(b);
804     b->panel.x = 85 + UN_SCALE(UTOX_STR_WIDTH(COPY_TOX_ID));
805 }
806 
807 BUTTON button_copyid = {
808     .panel = {
809         .type   = PANEL_BUTTON,
810         .x      =  66,
811         .y      = 117,
812         .width  = _BM_SBUTTON_WIDTH,
813         .height = _BM_SBUTTON_HEIGHT,
814     },
815     .bm_fill  = BM_SBUTTON,
816     .update   = button_setcolors_success,
817     .on_mup   = button_copyid_on_mup,
818     .disabled = false,
819     .button_text = {.i18nal = STR_COPY_TOX_ID },
820 };
821 
822 BUTTON button_show_qr = {
823     .panel = {
824         .type   = PANEL_BUTTON,
825         .x      = 85 + _BM_SBUTTON_WIDTH,
826         .y      = 117,
827         .width  = _BM_SBUTTON_WIDTH,
828         .height = _BM_SBUTTON_HEIGHT
829     },
830     .bm_fill  = BM_SBUTTON,
831     .update   = button_show_qr_update,
832     .on_mup   = button_show_qr_on_mup,
833     .disabled = false,
834     .button_text = {.i18nal = STR_SHOW_QR },
835 };
836 
837 BUTTON button_qr = {
838     .panel = {
839         .type   = PANEL_BUTTON,
840         .x      = 10,
841         .y      = 175,
842         .disabled = true,
843     },
844     .nodraw   = true,
845     .disabled = true,
846     .onright  = button_qr_on_mright,
847 };
848 
849 BUTTON button_callpreview = {
850     .bm_fill  = BM_LBUTTON,
851     .bm_icon  = BM_CALL,
852     .icon_w   = _BM_LBICON_WIDTH,
853     .icon_h   = _BM_LBICON_HEIGHT,
854     .on_mup   = button_audiopreview_on_mup,
855     .update   = button_audiopreview_update,
856     .disabled = false,
857 };
858 
859 BUTTON button_videopreview = {
860     .bm_fill  = BM_LBUTTON,
861     .bm_icon  = BM_VIDEO,
862     .icon_w   = _BM_LBICON_WIDTH,
863     .icon_h   = _BM_LBICON_HEIGHT,
864     .on_mup   = button_videopreview_on_mup,
865     .update   = button_videopreview_update,
866     .disabled = false,
867 };
868 
869 BUTTON button_lock_uTox = {
870     .panel = {
871         .type   = PANEL_BUTTON,
872         .x      =  10,
873         .y      = 265,
874         .width  = _BM_SBUTTON_WIDTH,
875         .height = _BM_SBUTTON_HEIGHT,
876     },
877     .bm_fill      = BM_SBUTTON,
878     .update       = button_setcolors_success,
879     .on_mup       = button_lock_uTox_on_mup,
880     .button_text  = {.i18nal = STR_LOCK },
881     .tooltip_text = {.i18nal = STR_LOCK_UTOX },
882 };
883 
884 BUTTON button_show_password_settings = {
885     .panel = {
886         .type   = PANEL_BUTTON,
887         .x      =  10,
888         .y      = 177,
889         .width  = _BM_SBUTTON_WIDTH,
890         .height = _BM_SBUTTON_HEIGHT,
891     },
892     .bm_fill      = BM_SBUTTON,
893     .update       = button_setcolors_success,
894     .on_mup       = button_show_password_settings_on_mup,
895     .button_text  = {.i18nal = STR_SHOW_UI_PASSWORD },
896     .tooltip_text = {.i18nal = STR_SHOW_UI_PASSWORD_TOOLTIP },
897 };
898 
899 BUTTON button_export_chatlog = {
900     .panel = {
901         .type   = PANEL_BUTTON,
902         .x      =  10,
903         .y      = 208,
904         .width  = _BM_SBUTTON_WIDTH,
905         .height = _BM_SBUTTON_HEIGHT,
906     },
907     .bm_fill      = BM_SBUTTON,
908     .update       = button_setcolors_success,
909     .on_mup       = button_export_chatlog_on_mup,
910     .disabled     = false,
911     .button_text  = {.i18nal = STR_FRIEND_EXPORT_CHATLOG },
912     .tooltip_text = {.i18nal = STR_FRIEND_EXPORT_CHATLOG },
913 };
914 
915 BUTTON button_change_nospam = {
916     .panel = {
917         .type   = PANEL_BUTTON,
918         .x      =  10,
919         .y      = 265,
920         .width  = _BM_SBUTTON_WIDTH,
921         .height = _BM_SBUTTON_HEIGHT,
922     },
923     .bm_fill      = BM_SBUTTON,
924     .update       = button_setcolors_success,
925     .on_mup       = button_change_nospam_on_mup,
926     .button_text  = {.i18nal = STR_RANDOMIZE_NOSPAM},
927     .tooltip_text = {.i18nal = STR_RANDOMIZE_NOSPAM},
928 };
929 
930 BUTTON button_revert_nospam = {
931     .bm_fill      = BM_SBUTTON,
932     .update       = button_revert_nospam_on_update,
933     .on_mup       = button_revert_nospam_on_mup,
934     .disabled     = true,
935     .button_text  = {.i18nal = STR_REVERT_NOSPAM},
936     .tooltip_text = {.i18nal = STR_REVERT_NOSPAM},
937 };
938 
939 BUTTON button_show_nospam = {
940     .bm_fill      = BM_SBUTTON,
941     .update       = button_setcolors_success,
942     .tooltip_text = {.i18nal = STR_SHOW_NOSPAM},
943     .button_text  = {.i18nal = STR_SHOW_NOSPAM},
944     .on_mup       = button_show_nospam_on_mup,
945 };
946 
switchfxn_logging(void)947 static void switchfxn_logging(void) {
948     settings.logging_enabled = !settings.logging_enabled;
949 }
950 
switchfxn_mini_contacts(void)951 static void switchfxn_mini_contacts(void) {
952     settings.use_mini_flist = !settings.use_mini_flist;
953     flist_re_scale();
954 }
955 
switchfxn_ipv6(void)956 static void switchfxn_ipv6(void) {
957     settings.enable_ipv6 = !settings.enable_ipv6;
958     tox_settingschanged();
959 }
960 
switchfxn_udp(void)961 static void switchfxn_udp(void) {
962     settings.enable_udp = !settings.enable_udp;
963     tox_settingschanged();
964 }
965 
switchfxn_close_to_tray(void)966 static void switchfxn_close_to_tray(void) {
967     settings.close_to_tray = !settings.close_to_tray;
968 }
969 
switchfxn_start_in_tray(void)970 static void switchfxn_start_in_tray(void) {
971     settings.start_in_tray = !settings.start_in_tray;
972 }
973 
switchfxn_auto_startup(void)974 static void switchfxn_auto_startup(void) {
975     settings.start_with_system = !settings.start_with_system;
976     launch_at_startup(settings.start_with_system);
977 }
978 
switchfxn_typing_notes(void)979 static void switchfxn_typing_notes(void) {
980     settings.send_typing_status = !settings.send_typing_status;
981 }
982 
switchfxn_audible_notifications(void)983 static void switchfxn_audible_notifications(void) { settings.ringtone_enabled = !settings.ringtone_enabled; }
984 
switchfxn_push_to_talk(void)985 static void switchfxn_push_to_talk(void) {
986     if (!settings.push_to_talk) {
987         init_ptt();
988     } else {
989         exit_ptt();
990     }
991 }
992 
switchfxn_audio_filtering(void)993 static void switchfxn_audio_filtering(void) { settings.audiofilter_enabled = !settings.audiofilter_enabled; }
994 
switchfxn_status_notifications(void)995 static void switchfxn_status_notifications(void) { settings.status_notifications = !settings.status_notifications; }
996 
switchfxn_block_friend_requests(void)997 static void switchfxn_block_friend_requests(void) { settings.block_friend_requests = !settings.block_friend_requests; }
998 
999 UISWITCH switch_save_chat_history = {
1000     .panel = {
1001         .type   = PANEL_SWITCH,
1002         .x      =  10,
1003         .y      = 115,
1004         .width  = _BM_SWITCH_WIDTH,
1005         .height = _BM_SWITCH_HEIGHT,
1006     },
1007     .style_outer    = BM_SWITCH,
1008     .style_toggle   = BM_SWITCH_TOGGLE,
1009     .style_icon_off = BM_NO,
1010     .style_icon_on  = BM_YES,
1011     .update         = switch_update,
1012     .on_mup         = switchfxn_logging,
1013     .tooltip_text   = {.i18nal = STR_SAVE_CHAT_HISTORY },
1014 };
1015 
1016 UISWITCH switch_mini_contacts = {
1017     .panel = {
1018         .type   = PANEL_SWITCH,
1019         .x      =  10,
1020         .y      = 235,
1021         .width  = _BM_SWITCH_WIDTH,
1022         .height = _BM_SWITCH_HEIGHT,
1023     },
1024     .style_outer    = BM_SWITCH,
1025     .style_toggle   = BM_SWITCH_TOGGLE,
1026     .style_icon_off = BM_NO,
1027     .style_icon_on  = BM_YES,
1028     .update         = switch_update,
1029     .on_mup         = switchfxn_mini_contacts,
1030     .tooltip_text   = {.i18nal = STR_SETTINGS_UI_MINI_ROSTER },
1031 };
1032 
1033 
switchfxn_magic_sidebar(void)1034 static void switchfxn_magic_sidebar(void) {
1035     settings.magic_flist_enabled = !settings.magic_flist_enabled;
1036 }
1037 
1038 UISWITCH switch_magic_sidebar = {
1039     .panel = {
1040         .type   = PANEL_SWITCH,
1041         .x      = -10 - _BM_SWITCH_WIDTH,
1042         .y      = 210,
1043         .width  = _BM_SWITCH_WIDTH,
1044         .height = _BM_SWITCH_HEIGHT
1045     },
1046     .style_outer    = BM_SWITCH,
1047     .style_toggle   = BM_SWITCH_TOGGLE,
1048     .style_icon_off = BM_NO,
1049     .style_icon_on  = BM_YES,
1050     .update         = switch_update,
1051     .on_mup         = switchfxn_magic_sidebar,
1052     .tooltip_text   = {.i18nal = STR_SETTINGS_UI_AUTO_HIDE_SIDEBAR },
1053 };
1054 
1055 UISWITCH switch_ipv6 = {
1056     .panel = {
1057         .type   = PANEL_SWITCH,
1058         .x      = 10,
1059         .y      = 27,
1060         .width  = _BM_SWITCH_WIDTH,
1061         .height = _BM_SWITCH_HEIGHT,
1062     },
1063     .style_outer    = BM_SWITCH,
1064     .style_toggle   = BM_SWITCH_TOGGLE,
1065     .style_icon_off = BM_NO,
1066     .style_icon_on  = BM_YES,
1067     .update         = switch_update,
1068     .on_mup         = switchfxn_ipv6,
1069     .tooltip_text   = {.i18nal = STR_IPV6 },
1070 };
1071 
1072 UISWITCH switch_udp = {
1073     .panel = {
1074         .type   = PANEL_SWITCH,
1075         .x      = 10,
1076         .y      = 57,
1077         .width  = _BM_SWITCH_WIDTH,
1078         .height = _BM_SWITCH_HEIGHT,
1079     },
1080     .style_outer    = BM_SWITCH,
1081     .style_toggle   = BM_SWITCH_TOGGLE,
1082     .style_icon_off = BM_NO,
1083     .style_icon_on  = BM_YES,
1084     .update         = switch_update,
1085     .on_mup         = switchfxn_udp,
1086     .tooltip_text   = {.i18nal = STR_UDP },
1087 };
1088 
1089 UISWITCH switch_close_to_tray = {
1090     .panel = {
1091         .type   = PANEL_SWITCH,
1092         .x      =  10,
1093         .y      = 145,
1094         .width  = _BM_SWITCH_WIDTH,
1095         .height = _BM_SWITCH_HEIGHT,
1096     },
1097     .style_outer    = BM_SWITCH,
1098     .style_toggle   = BM_SWITCH_TOGGLE,
1099     .style_icon_off = BM_NO,
1100     .style_icon_on  = BM_YES,
1101     .update         = switch_update,
1102     .on_mup         = switchfxn_close_to_tray,
1103     .tooltip_text   = {.i18nal = STR_CLOSE_TO_TRAY },
1104 };
1105 
1106 UISWITCH switch_start_in_tray = {
1107     .panel = {
1108         .type   = PANEL_SWITCH,
1109         .x      =  10,
1110         .y      = 175,
1111         .width  = _BM_SWITCH_WIDTH,
1112         .height = _BM_SWITCH_HEIGHT,
1113     },
1114     .style_outer    = BM_SWITCH,
1115     .style_toggle   = BM_SWITCH_TOGGLE,
1116     .style_icon_off = BM_NO,
1117     .style_icon_on  = BM_YES,
1118     .update         = switch_update,
1119     .on_mup         = switchfxn_start_in_tray,
1120     .tooltip_text   = {.i18nal = STR_START_IN_TRAY },
1121 };
1122 
1123 UISWITCH switch_auto_startup = {
1124     .panel = {
1125         .type   = PANEL_SWITCH,
1126         .x      =  10,
1127         .y      = 205,
1128         .width  = _BM_SWITCH_WIDTH,
1129         .height = _BM_SWITCH_HEIGHT,
1130     },
1131     .style_outer    = BM_SWITCH,
1132     .style_toggle   = BM_SWITCH_TOGGLE,
1133     .style_icon_off = BM_NO,
1134     .style_icon_on  = BM_YES,
1135     .update         = switch_update,
1136     .on_mup         = switchfxn_auto_startup,
1137     .tooltip_text   = {.i18nal = STR_AUTO_STARTUP },
1138 };
1139 
1140 UISWITCH switch_typing_notes = {
1141     .panel = {
1142         .type   = PANEL_SWITCH,
1143         .x      = 10,
1144         .y      = 70,
1145         .width  = _BM_SWITCH_WIDTH,
1146         .height = _BM_SWITCH_HEIGHT,
1147     },
1148     .style_outer    = BM_SWITCH,
1149     .style_toggle   = BM_SWITCH_TOGGLE,
1150     .style_icon_off = BM_NO,
1151     .style_icon_on  = BM_YES,
1152     .update         = switch_update,
1153     .on_mup         = switchfxn_typing_notes,
1154     .tooltip_text   = {.i18nal = STR_SEND_TYPING_NOTIFICATIONS },
1155 };
1156 
1157 UISWITCH switch_audible_notifications = {
1158     .panel = {
1159         .type   = PANEL_SWITCH,
1160         .x      = 10,
1161         .y      = 10,
1162         .width  = _BM_SWITCH_WIDTH,
1163         .height = _BM_SWITCH_HEIGHT,
1164     },
1165     .style_outer    = BM_SWITCH,
1166     .style_toggle   = BM_SWITCH_TOGGLE,
1167     .style_icon_off = BM_NO,
1168     .style_icon_on  = BM_YES,
1169     .update         = switch_update,
1170     .on_mup         = switchfxn_audible_notifications,
1171     .tooltip_text   = {.i18nal = STR_AUDIONOTIFICATIONS },
1172 };
1173 
1174 UISWITCH switch_push_to_talk = {
1175     .panel = {
1176         .type   = PANEL_SWITCH,
1177         .x      = 10,
1178         .y      = 10,
1179         .width  = _BM_SWITCH_WIDTH,
1180         .height = _BM_SWITCH_HEIGHT,
1181     },
1182     .style_outer    = BM_SWITCH,
1183     .style_toggle   = BM_SWITCH_TOGGLE,
1184     .style_icon_off = BM_NO,
1185     .style_icon_on  = BM_YES,
1186     .update         = switch_update,
1187     .on_mup         = switchfxn_push_to_talk,
1188     .tooltip_text   = {.i18nal = STR_PUSH_TO_TALK },
1189 };
1190 
1191 UISWITCH switch_audio_filtering = {
1192     .style_outer    = BM_SWITCH,
1193     .style_toggle   = BM_SWITCH_TOGGLE,
1194     .style_icon_off = BM_NO,
1195     .style_icon_on  = BM_YES,
1196     .update         = switch_update,
1197     .on_mup         = switchfxn_audio_filtering,
1198     .tooltip_text   = {.i18nal = STR_AUDIOFILTERING },
1199 };
1200 
1201 UISWITCH switch_status_notifications = {
1202     .panel = {
1203         .type   = PANEL_SWITCH,
1204         .x      = 10,
1205         .y      = 40,
1206         .width  = _BM_SWITCH_WIDTH,
1207         .height = _BM_SWITCH_HEIGHT,
1208     },
1209     .style_outer    = BM_SWITCH,
1210     .style_toggle   = BM_SWITCH_TOGGLE,
1211     .style_icon_off = BM_NO,
1212     .style_icon_on  = BM_YES,
1213     .update         = switch_update,
1214     .on_mup         = switchfxn_status_notifications,
1215     .tooltip_text   = {.i18nal = STR_STATUS_NOTIFICATIONS },
1216 };
1217 
1218 UISWITCH switch_block_friend_requests = {
1219     .panel = {
1220         .type   = PANEL_SWITCH,
1221         .x      =  10,
1222         .y      = 147,
1223         .width  = _BM_SWITCH_WIDTH,
1224         .height = _BM_SWITCH_HEIGHT,
1225     },
1226     .style_outer    = BM_SWITCH,
1227     .style_toggle   = BM_SWITCH_TOGGLE,
1228     .style_icon_off = BM_NO,
1229     .style_icon_on  = BM_YES,
1230     .update         = switch_update,
1231     .on_mup         = switchfxn_block_friend_requests,
1232     .tooltip_text   = {.i18nal = STR_BLOCK_FRIEND_REQUESTS },
1233 };
1234 
switchfxn_proxy(void)1235 static void switchfxn_proxy(void) {
1236     settings.use_proxy   = !settings.use_proxy;
1237 
1238     if (settings.use_proxy) {
1239         switch_proxy_force.panel.disabled = false;
1240     } else {
1241         settings.force_proxy              = false;
1242         switch_proxy_force.switch_on      = false;
1243         switch_proxy_force.panel.disabled = true;
1244         switch_udp.panel.disabled         = false;
1245     }
1246 
1247     memcpy(proxy_address, edit_proxy_ip.data, edit_proxy_ip.length);
1248     proxy_address[edit_proxy_ip.length] = 0;
1249 
1250     edit_proxy_port.data[edit_proxy_port.length] = 0;
1251     settings.proxy_port = strtol((char *)edit_proxy_port.data, NULL, 0);
1252 
1253     tox_settingschanged();
1254 }
1255 
switchfxn_proxy_force(void)1256 static void switchfxn_proxy_force(void) {
1257     settings.force_proxy = !settings.force_proxy;
1258 
1259     if (settings.force_proxy) {
1260         switch_udp.switch_on      = false;
1261         settings.enable_udp       = false;
1262         switch_udp.panel.disabled = true;
1263     } else {
1264         switch_udp.panel.disabled = false;
1265     }
1266 
1267     edit_proxy_port.data[edit_proxy_port.length] = 0;
1268     settings.proxy_port = strtol((char *)edit_proxy_port.data, NULL, 0);
1269 
1270     tox_settingschanged();
1271 }
1272 
1273 UISWITCH switch_proxy = {
1274     .panel = {
1275         .type   = PANEL_SWITCH,
1276         .x      = 10,
1277         .y      = 87,
1278         .width  = _BM_SWITCH_WIDTH,
1279         .height = _BM_SWITCH_HEIGHT,
1280     },
1281     .style_outer    = BM_SWITCH,
1282     .style_toggle   = BM_SWITCH_TOGGLE,
1283     .style_icon_off = BM_NO,
1284     .style_icon_on  = BM_YES,
1285     .update         = switch_update,
1286     .on_mup         = switchfxn_proxy,
1287     .tooltip_text   = {.i18nal = STR_PROXY }
1288 };
1289 
1290 UISWITCH switch_proxy_force = {
1291     .panel = {
1292         .type   = PANEL_SWITCH,
1293         .x      =  10,
1294         .y      = 117,
1295         .width  = _BM_SWITCH_WIDTH,
1296         .height = _BM_SWITCH_HEIGHT,
1297     },
1298     .style_outer    = BM_SWITCH,
1299     .style_toggle   = BM_SWITCH_TOGGLE,
1300     .style_icon_off = BM_NO,
1301     .style_icon_on  = BM_YES,
1302     .update         = switch_update,
1303     .on_mup         = switchfxn_proxy_force,
1304     .tooltip_text   = {.i18nal = STR_PROXY_FORCE },
1305 };
1306 
dropdown_audio_in_onselect(uint16_t i,const DROPDOWN * dm)1307 static void dropdown_audio_in_onselect(uint16_t i, const DROPDOWN *dm) {
1308     DROP_ELEMENT *e      = &((DROP_ELEMENT *)dm->userdata)[i];
1309     void *        handle = e->handle;
1310     postmessage_utoxav(UTOXAV_SET_AUDIO_IN, 0, 0, handle);
1311 }
1312 
dropdown_audio_out_onselect(uint16_t i,const DROPDOWN * dm)1313 static void dropdown_audio_out_onselect(uint16_t i, const DROPDOWN *dm) {
1314     DROP_ELEMENT *e      = &((DROP_ELEMENT *)dm->userdata)[i];
1315     void *        handle = e->handle;
1316     postmessage_utoxav(UTOXAV_SET_AUDIO_OUT, 0, 0, handle);
1317 }
1318 
edit_video_fps_onlosefocus(EDIT * UNUSED (edit))1319 static void edit_video_fps_onlosefocus(EDIT *UNUSED(edit)) {
1320     edit_video_fps.data[edit_video_fps.length] = '\0';
1321 
1322     char *temp;
1323     uint16_t value = strtol((char *)edit_video_fps.data, &temp, 10);
1324 
1325     if (*temp == '\0' && value >= 1 && value <= UINT8_MAX) {
1326         settings.video_fps = value;
1327         return;
1328     }
1329 
1330     LOG_WARN("Settings", "FPS value (%s) is invalid. It must be integer in range of [1,%u]. Setting default value (%u).",
1331              edit_video_fps.data, UINT8_MAX, DEFAULT_FPS);
1332 
1333     settings.video_fps = DEFAULT_FPS;
1334     snprintf((char *)edit_video_fps.data, edit_video_fps.data_size,
1335              "%u", DEFAULT_FPS);
1336     edit_video_fps.length = strnlen((char *)edit_video_fps.data, edit_video_fps.data_size - 1);
1337 }
1338 
1339 #include "../screen_grab.h"
dropdown_video_onselect(uint16_t i,const DROPDOWN * UNUSED (dm))1340 static void dropdown_video_onselect(uint16_t i, const DROPDOWN *UNUSED(dm)) {
1341     if (i == 1) {
1342         utox_screen_grab_desktop(1);
1343     } else {
1344         postmessage_utoxav(UTOXAV_SET_VIDEO_IN, i, 0, NULL);
1345     }
1346 }
1347 
dropdown_dpi_onselect(uint16_t i,const DROPDOWN * UNUSED (dm))1348 static void dropdown_dpi_onselect(uint16_t i, const DROPDOWN *UNUSED(dm)) {
1349     ui_rescale(i + 5);
1350 }
1351 
dropdown_language_onselect(uint16_t i,const DROPDOWN * UNUSED (dm))1352 static void dropdown_language_onselect(uint16_t i, const DROPDOWN *UNUSED(dm)) {
1353     settings.language = (UTOX_LANG)i;
1354     /* The draw functions need the fonts' and scale to be reset when changing languages. */
1355     ui_rescale(ui_scale);
1356 }
dropdown_language_ondisplay(uint16_t i,const DROPDOWN * UNUSED (dm))1357 static STRING *dropdown_language_ondisplay(uint16_t i, const DROPDOWN *UNUSED(dm)) {
1358     UTOX_LANG tmp_language = (UTOX_LANG)i;
1359     return SPTRFORLANG(tmp_language, STR_LANG_NATIVE_NAME);
1360 }
1361 
dropdown_theme_onselect(const uint16_t i,const DROPDOWN * UNUSED (dm))1362 static void dropdown_theme_onselect(const uint16_t i, const DROPDOWN *UNUSED(dm)) {
1363     theme_load(i);
1364     settings.theme = i;
1365 }
1366 
1367 #include"../groups.h"
dropdown_notify_groupchats_onselect(const uint16_t i,const DROPDOWN * UNUSED (dm))1368 static void dropdown_notify_groupchats_onselect(const uint16_t i, const DROPDOWN *UNUSED(dm)) {
1369     GROUPCHAT *g = flist_get_groupchat();
1370     if (!g) {
1371         LOG_ERR("Settings", "Could not get selected groupchat.");
1372         return;
1373     }
1374 
1375     g->notify    = i;
1376     LOG_INFO("Settings", "g->notify = %u\n", i);
1377 }
1378 
dropdown_global_group_notifications_onselect(const uint16_t i,const DROPDOWN * UNUSED (dm))1379 static void dropdown_global_group_notifications_onselect(const uint16_t i, const DROPDOWN *UNUSED(dm)) {
1380     settings.group_notifications = i;
1381 }
1382 
1383 static UTOX_I18N_STR dpidrops[] = {
1384     STR_DPI_TINY, STR_DPI_060,   STR_DPI_070, STR_DPI_080, STR_DPI_090, STR_DPI_NORMAL, STR_DPI_110,
1385     STR_DPI_120,  STR_DPI_130,   STR_DPI_140, STR_DPI_BIG, STR_DPI_160, STR_DPI_170,    STR_DPI_180,
1386     STR_DPI_190,  STR_DPI_LARGE, STR_DPI_210, STR_DPI_220, STR_DPI_230, STR_DPI_240,    STR_DPI_HUGE,
1387 };
1388 
1389 DROPDOWN dropdown_audio_in = {
1390     .ondisplay = dropdown_list_ondisplay,
1391     .onselect = dropdown_audio_in_onselect
1392 };
1393 
1394 DROPDOWN dropdown_audio_out = {
1395     .ondisplay = dropdown_list_ondisplay,
1396     .onselect = dropdown_audio_out_onselect
1397 };
1398 
1399 DROPDOWN dropdown_video = {
1400     .ondisplay = dropdown_list_ondisplay,
1401     .onselect = dropdown_video_onselect,
1402 };
1403 
1404 DROPDOWN dropdown_dpi = {
1405     .panel = {
1406         .type   = PANEL_DROPDOWN,
1407         .x      = 150,
1408         .y      =  85,
1409         .width  = 200,
1410         .height =  24,
1411     },
1412     .ondisplay = simple_dropdown_ondisplay,
1413     .onselect  = dropdown_dpi_onselect,
1414     .dropcount = COUNTOF(dpidrops),
1415     .userdata  = dpidrops
1416 };
1417 
1418 DROPDOWN dropdown_language = {
1419     .panel = {
1420         .type   = PANEL_DROPDOWN,
1421         .x      = 10,
1422         .y      = 30,
1423         .width  = -10,
1424         .height = 24
1425     },
1426     .ondisplay = dropdown_language_ondisplay,
1427     .onselect  = dropdown_language_onselect,
1428     .dropcount = NUM_LANGS,
1429 };
1430 
1431 
1432 static UTOX_I18N_STR themedrops[] = {
1433     STR_THEME_DEFAULT,
1434     STR_THEME_LIGHT,
1435     STR_THEME_DARK,
1436     STR_THEME_HIGHCONTRAST,
1437     STR_THEME_CUSTOM,
1438     STR_THEME_ZENBURN,
1439     STR_THEME_SOLARIZED_LIGHT,
1440     STR_THEME_SOLARIZED_DARK,
1441 };
1442 
1443 DROPDOWN dropdown_theme = {
1444     .panel = {
1445         .type   = PANEL_DROPDOWN,
1446         .x      =  10,
1447         .y      =  85,
1448         .width  = 120,
1449         .height =  24,
1450     },
1451     .ondisplay = simple_dropdown_ondisplay,
1452     .onselect  = dropdown_theme_onselect,
1453     .dropcount = COUNTOF(themedrops),
1454     .userdata  = themedrops
1455 };
1456 
1457 static UTOX_I18N_STR notifydrops[] = {
1458     STR_GROUP_NOTIFICATIONS_OFF, STR_GROUP_NOTIFICATIONS_MENTION, STR_GROUP_NOTIFICATIONS_ON,
1459 };
1460 
1461 DROPDOWN dropdown_notify_groupchats = {
1462     .panel = {
1463         .type   = PANEL_DROPDOWN,
1464         .x      = 10,
1465         .y      = 138,
1466         .width  = 100,
1467         .height = 24
1468     },
1469     .ondisplay = simple_dropdown_ondisplay,
1470     .onselect  = dropdown_notify_groupchats_onselect,
1471     .dropcount = COUNTOF(notifydrops),
1472     .userdata  = notifydrops
1473 };
1474 
1475 DROPDOWN dropdown_global_group_notifications = {
1476     .panel = {
1477         .type   = PANEL_DROPDOWN,
1478         .x      =  10,
1479         .y      = 125,
1480         .width  = 100,
1481         .height =  24,
1482     },
1483     .ondisplay = simple_dropdown_ondisplay,
1484     .onselect  = dropdown_global_group_notifications_onselect,
1485     .dropcount = COUNTOF(notifydrops),
1486     .userdata  = notifydrops
1487 };
1488 
1489 static char edit_name_data[128],
1490             edit_status_msg_data[128],
1491             edit_proxy_ip_data[256],
1492             edit_proxy_port_data[8],
1493             edit_video_fps_data[3 + 1], /* range is [1-255] */
1494             edit_profile_password_data[65535],
1495             edit_nospam_data[(sizeof(uint32_t) * 2) + 1] = { 0 };
1496 #ifdef ENABLE_MULTIDEVICE
1497 static char edit_add_self_device_data[TOX_ADDRESS_SIZE * 4];
1498 #endif
1499 
1500 
edit_name_onenter(EDIT * edit)1501 static void edit_name_onenter(EDIT *edit) {
1502     char *   data   = edit->data;
1503     uint16_t length = edit->length;
1504 
1505     memcpy(self.name, data, length);
1506     self.name_length = length;
1507     update_tray();
1508 
1509     postmessage_toxcore(TOX_SELF_SET_NAME, length, 0, self.name);
1510 }
1511 
edit_name_ontab(EDIT * UNUSED (edit))1512 static void edit_name_ontab(EDIT *UNUSED(edit)) {
1513     edit_setfocus(&edit_status_msg);
1514 }
1515 
edit_name_onshifttab(EDIT * UNUSED (edit))1516 static void edit_name_onshifttab(EDIT *UNUSED(edit)) {
1517     edit_setfocus(&edit_toxid);
1518 }
1519 
1520 EDIT edit_name = {
1521     .panel = {
1522         .type   = PANEL_EDIT,
1523         .x      =  10,
1524         .y      =  30,
1525         .width  = -10,
1526         .height =  24,
1527     },
1528     .data        = edit_name_data,
1529     .data_size   = sizeof edit_name_data,
1530     .onenter     = edit_name_onenter,
1531     .onlosefocus = edit_name_onenter,
1532     .ontab       = edit_name_ontab,
1533     .onshifttab  = edit_name_onshifttab,
1534 };
1535 
edit_status_msg_onenter(EDIT * edit)1536 static void edit_status_msg_onenter(EDIT *edit) {
1537     char *   data   = edit->data;
1538     uint16_t length = edit->length;
1539 
1540     if (length) {
1541         length = (length <= TOX_MAX_STATUS_MESSAGE_LENGTH) ? length : TOX_MAX_STATUS_MESSAGE_LENGTH;
1542         memcpy(self.statusmsg, data, length);
1543         self.statusmsg_length = length;
1544     } else {
1545         self.statusmsg_length = length;
1546     }
1547 
1548     update_tray();
1549 
1550     postmessage_toxcore(TOX_SELF_SET_STATUS, length, 0, self.statusmsg); //!
1551 }
1552 
edit_status_msg_ontab(EDIT * UNUSED (edit))1553 static void edit_status_msg_ontab(EDIT *UNUSED(edit)) {
1554     edit_setfocus(&edit_toxid);
1555 }
1556 
edit_status_msg_onshifttab(EDIT * UNUSED (edit))1557 static void edit_status_msg_onshifttab(EDIT *UNUSED(edit)) {
1558     edit_setfocus(&edit_name);
1559 }
1560 
1561 EDIT edit_status_msg = {
1562     .panel = {
1563         .type   = PANEL_EDIT,
1564         .x      =  10,
1565         .y      =  85,
1566         .width  = -10,
1567         .height =  24,
1568     },
1569     .data        = edit_status_msg_data,
1570     .data_size   = sizeof edit_status_msg_data,
1571     .onenter     = edit_status_msg_onenter,
1572     .onlosefocus = edit_status_msg_onenter,
1573     .ontab       = edit_status_msg_ontab,
1574     .onshifttab  = edit_status_msg_onshifttab,
1575 };
1576 
1577 
edit_proxy_ip_port_onlosefocus(EDIT * UNUSED (edit))1578 static void edit_proxy_ip_port_onlosefocus(EDIT *UNUSED(edit)) {
1579     edit_proxy_port.data[edit_proxy_port.length] = 0;
1580 
1581     settings.proxy_port = strtol((char *)edit_proxy_port.data, NULL, 0);
1582 
1583     if (memcmp(proxy_address, edit_proxy_ip.data, edit_proxy_ip.length) == 0 && proxy_address[edit_proxy_ip.length] == 0) {
1584         return;
1585     }
1586 
1587     memset(proxy_address, 0, 256); /* Magic number from toxcore */
1588     memcpy(proxy_address, edit_proxy_ip.data, edit_proxy_ip.length);
1589     proxy_address[edit_proxy_ip.length] = 0;
1590 
1591 
1592     if (settings.use_proxy) {
1593         tox_settingschanged();
1594     }
1595 }
1596 
edit_proxy_ip_ontab(EDIT * UNUSED (edit))1597 static void edit_proxy_ip_ontab(EDIT *UNUSED(edit)) {
1598     edit_setfocus(&edit_proxy_port);
1599 }
1600 
1601 EDIT edit_proxy_ip = {
1602     .panel = {
1603         .type   = PANEL_EDIT,
1604         .x      = 230,
1605         .y      =  87,
1606         .width  = 120,
1607         .height =  24,
1608     },
1609     .data        = edit_proxy_ip_data,
1610     .data_size   = sizeof edit_proxy_ip_data,
1611     .empty_str = {.i18nal = STR_PROXY_EDIT_HINT_IP },
1612     .onlosefocus = edit_proxy_ip_port_onlosefocus,
1613     .ontab       = edit_proxy_ip_ontab,
1614     .onshifttab  = edit_proxy_ip_ontab,
1615 };
1616 
edit_proxy_port_ontab(EDIT * UNUSED (edit))1617 static void edit_proxy_port_ontab(EDIT *UNUSED(edit)) {
1618     edit_setfocus(&edit_proxy_ip);
1619 }
1620 
1621 EDIT edit_proxy_port = {
1622     .panel = {
1623         .type   = PANEL_EDIT,
1624         .x      = 360,
1625         .y      =  87,
1626         .width  =  60,
1627         .height =  24,
1628     },
1629     .data        = edit_proxy_port_data,
1630     .data_size   = sizeof edit_proxy_port_data,
1631     .empty_str = {.i18nal = STR_PROXY_EDIT_HINT_PORT },
1632     .onlosefocus = edit_proxy_ip_port_onlosefocus,
1633     .ontab       = edit_proxy_port_ontab,
1634     .onshifttab  = edit_proxy_port_ontab,
1635 };
1636 
1637 EDIT edit_video_fps = {
1638     .data        = edit_video_fps_data,
1639     .data_size   = sizeof edit_video_fps_data,
1640     .onlosefocus = edit_video_fps_onlosefocus,
1641     /* .empty_str = {.i18nal = STR_PROXY_EDIT_HINT_PORT }, */
1642 };
1643 
edit_profile_password_update(EDIT * UNUSED (edit))1644 static void edit_profile_password_update(EDIT *UNUSED(edit)) {
1645     if (tox_thread_init) {
1646         postmessage_toxcore(TOX_SAVE, 0, 0, NULL);
1647     }
1648 }
1649 
1650 EDIT edit_profile_password = {
1651     .panel = {
1652         .type   = PANEL_EDIT,
1653         .x      =  10,
1654         .y      =  55,
1655         .width  = -10,
1656         .height =  24,
1657     },
1658     .data_size = sizeof edit_profile_password_data,
1659     .data      = edit_profile_password_data,
1660     // .onchange    = edit_profile_password_update,
1661     .onlosefocus = edit_profile_password_update,
1662     .password    = 1,
1663 };
1664 
edit_toxid_ontab(EDIT * UNUSED (edit))1665 static void edit_toxid_ontab(EDIT *UNUSED(edit)) {
1666     edit_setfocus(&edit_name);
1667 }
1668 
edit_toxid_onshifttab(EDIT * UNUSED (edit))1669 static void edit_toxid_onshifttab(EDIT *UNUSED(edit)) {
1670     edit_setfocus(&edit_status_msg);
1671 }
1672 
1673 EDIT edit_toxid = {
1674     .panel = {
1675         .type   = PANEL_EDIT,
1676         .x      =  10,
1677         .y      = 140,
1678         .width  = -10,
1679         .height =  24,
1680     },
1681     .length = TOX_ADDRESS_SIZE * 2,
1682     .data = self.id_str,
1683     .readonly = 1,
1684     .noborder = 0,
1685     .select_completely = 1,
1686     .ontab      = edit_toxid_ontab,
1687     .onshifttab = edit_toxid_onshifttab,
1688 };
1689 
edit_change_nospam_onenter(EDIT * edit)1690 static void edit_change_nospam_onenter(EDIT *edit) {
1691     char *endptr;
1692     edit_nospam_data[edit->length] = '\0';
1693     long int nospam = strtol(edit_nospam_data, &endptr, 16);
1694     if (nospam == 0 || nospam < 0) {
1695         LOG_ERR("Nospam", "Invalid nospam value: %lu", nospam);
1696         return;
1697     } else if (endptr == edit_nospam_data) {
1698         LOG_ERR("Nospam", "No numbers found.");
1699         return;
1700     }
1701     postmessage_toxcore(TOX_SELF_CHANGE_NOSPAM, nospam, 0, NULL);
1702 }
1703 
1704 EDIT edit_nospam = {
1705     .panel = {
1706         .type   = PANEL_EDIT,
1707         .x      =  10,
1708         .y      = 235,
1709         .width  = -10,
1710         .height =  24,
1711     },
1712     .data_size    = sizeof edit_nospam_data,
1713     .data         = edit_nospam_data,
1714     .noborder     = false,
1715     .onenter      = edit_change_nospam_onenter,
1716     .onlosefocus  = edit_change_nospam_onenter,
1717 };
1718 
1719 
1720 static char edit_add_new_device_to_self_data[TOX_ADDRESS_SIZE * 4];
edit_add_new_device_to_self_onenter(EDIT * UNUSED (edit))1721 static void edit_add_new_device_to_self_onenter(EDIT *UNUSED(edit)) {
1722 #ifdef ENABLE_MULTIDEVICE
1723     devices_self_add(edit_add_new_device_to_self.data, edit_add_new_device_to_self.length);
1724 #endif
1725 }
1726 
1727 EDIT edit_add_new_device_to_self = {
1728     .data      = edit_add_new_device_to_self_data,
1729     .data_size = sizeof edit_add_new_device_to_self_data,
1730     .onenter   = edit_add_new_device_to_self_onenter,
1731 };
1732