wtext killing spree
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blob1d708545b6ede2dc2444facbe3fd112b1a9a55ec
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "config.h" /* for HAVE_XCONVERTCASE */
24 #include "WPrefs.h"
25 #include <ctype.h>
27 #include <X11/keysym.h>
29 typedef struct _Panel {
30 WMBox *box;
32 char *sectionName;
34 char *description;
36 CallbackRec callbacks;
38 WMWidget *parent;
40 WMLabel *actL;
41 WMList *actLs;
43 WMFrame *shoF;
44 WMTextField *shoT;
45 WMButton *cleB;
46 WMButton *defB;
48 WMLabel *instructionsL;
50 WMColor *white;
51 WMColor *black;
52 WMColor *gray;
53 WMFont *font;
55 /**/ char capturing;
56 char **shortcuts;
57 int actionCount;
58 } _Panel;
60 #define ICON_FILE "keyshortcuts"
63 * Must be in the same order as the corresponding items in
64 * "actions list" in createPanel()
66 static char *keyOptions[] = {
67 "RootMenuKey",
68 "WindowListKey",
69 "WindowMenuKey",
70 "HideKey",
71 "HideOthersKey",
72 "MiniaturizeKey",
73 "MinimizeAllKey",
74 "CloseKey",
75 "MaximizeKey",
76 "VMaximizeKey",
77 "HMaximizeKey",
78 "LHMaximizeKey",
79 "RHMaximizeKey",
80 "MaximusKey",
81 "RaiseKey",
82 "LowerKey",
83 "RaiseLowerKey",
84 "ShadeKey",
85 "MoveResizeKey",
86 "SelectKey",
87 "FocusNextKey",
88 "FocusPrevKey",
89 "GroupNextKey",
90 "GroupPrevKey",
91 "NextWorkspaceKey",
92 "PrevWorkspaceKey",
93 "NextWorkspaceLayerKey",
94 "PrevWorkspaceLayerKey",
95 "Workspace1Key",
96 "Workspace2Key",
97 "Workspace3Key",
98 "Workspace4Key",
99 "Workspace5Key",
100 "Workspace6Key",
101 "Workspace7Key",
102 "Workspace8Key",
103 "Workspace9Key",
104 "Workspace10Key",
105 "WindowShortcut1Key",
106 "WindowShortcut2Key",
107 "WindowShortcut3Key",
108 "WindowShortcut4Key",
109 "WindowShortcut5Key",
110 "WindowShortcut6Key",
111 "WindowShortcut7Key",
112 "WindowShortcut8Key",
113 "WindowShortcut9Key",
114 "WindowShortcut10Key",
115 "ScreenSwitchKey",
116 "DockRaiseLowerKey",
117 #ifndef XKB_MODELOCK
118 "ClipRaiseLowerKey"
119 #else
120 "ClipRaiseLowerKey",
121 "ToggleKbdModeKey"
122 #endif /* XKB_MODELOCK */
125 #ifndef HAVE_XCONVERTCASE
126 /* from Xlib */
128 static void XConvertCase(register KeySym sym, KeySym * lower, KeySym * upper)
130 *lower = sym;
131 *upper = sym;
132 switch (sym >> 8) {
133 case 0: /* Latin 1 */
134 if ((sym >= XK_A) && (sym <= XK_Z))
135 *lower += (XK_a - XK_A);
136 else if ((sym >= XK_a) && (sym <= XK_z))
137 *upper -= (XK_a - XK_A);
138 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
139 *lower += (XK_agrave - XK_Agrave);
140 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
141 *upper -= (XK_agrave - XK_Agrave);
142 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
143 *lower += (XK_oslash - XK_Ooblique);
144 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
145 *upper -= (XK_oslash - XK_Ooblique);
146 break;
147 case 1: /* Latin 2 */
148 /* Assume the KeySym is a legal value (ignore discontinuities) */
149 if (sym == XK_Aogonek)
150 *lower = XK_aogonek;
151 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
152 *lower += (XK_lstroke - XK_Lstroke);
153 else if (sym >= XK_Scaron && sym <= XK_Zacute)
154 *lower += (XK_scaron - XK_Scaron);
155 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
156 *lower += (XK_zcaron - XK_Zcaron);
157 else if (sym == XK_aogonek)
158 *upper = XK_Aogonek;
159 else if (sym >= XK_lstroke && sym <= XK_sacute)
160 *upper -= (XK_lstroke - XK_Lstroke);
161 else if (sym >= XK_scaron && sym <= XK_zacute)
162 *upper -= (XK_scaron - XK_Scaron);
163 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
164 *upper -= (XK_zcaron - XK_Zcaron);
165 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
166 *lower += (XK_racute - XK_Racute);
167 else if (sym >= XK_racute && sym <= XK_tcedilla)
168 *upper -= (XK_racute - XK_Racute);
169 break;
170 case 2: /* Latin 3 */
171 /* Assume the KeySym is a legal value (ignore discontinuities) */
172 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
173 *lower += (XK_hstroke - XK_Hstroke);
174 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
175 *lower += (XK_gbreve - XK_Gbreve);
176 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
177 *upper -= (XK_hstroke - XK_Hstroke);
178 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
179 *upper -= (XK_gbreve - XK_Gbreve);
180 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
181 *lower += (XK_cabovedot - XK_Cabovedot);
182 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
183 *upper -= (XK_cabovedot - XK_Cabovedot);
184 break;
185 case 3: /* Latin 4 */
186 /* Assume the KeySym is a legal value (ignore discontinuities) */
187 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
188 *lower += (XK_rcedilla - XK_Rcedilla);
189 else if (sym >= XK_rcedilla && sym <= XK_tslash)
190 *upper -= (XK_rcedilla - XK_Rcedilla);
191 else if (sym == XK_ENG)
192 *lower = XK_eng;
193 else if (sym == XK_eng)
194 *upper = XK_ENG;
195 else if (sym >= XK_Amacron && sym <= XK_Umacron)
196 *lower += (XK_amacron - XK_Amacron);
197 else if (sym >= XK_amacron && sym <= XK_umacron)
198 *upper -= (XK_amacron - XK_Amacron);
199 break;
200 case 6: /* Cyrillic */
201 /* Assume the KeySym is a legal value (ignore discontinuities) */
202 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
203 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
204 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
205 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
206 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
207 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
208 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
209 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
210 break;
211 case 7: /* Greek */
212 /* Assume the KeySym is a legal value (ignore discontinuities) */
213 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
214 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
215 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
216 sym != XK_Greek_iotaaccentdieresis && sym != XK_Greek_upsilonaccentdieresis)
217 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
218 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
219 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
220 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && sym != XK_Greek_finalsmallsigma)
221 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
222 break;
223 case 0x14: /* Armenian */
224 if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
225 *lower = sym | 1;
226 *upper = sym & ~1;
228 break;
231 #endif
233 static char *captureShortcut(Display * dpy, _Panel * panel)
235 XEvent ev;
236 KeySym ksym, lksym, uksym;
237 char buffer[64];
238 char *key = NULL;
240 while (panel->capturing) {
241 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
242 WMNextEvent(dpy, &ev);
243 if (ev.type == KeyPress && ev.xkey.keycode != 0) {
244 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
245 if (!IsModifierKey(ksym)) {
246 XConvertCase(ksym, &lksym, &uksym);
247 key = XKeysymToString(uksym);
249 panel->capturing = 0;
250 break;
253 WMHandleEvent(&ev);
256 if (!key)
257 return NULL;
259 buffer[0] = 0;
261 if (ev.xkey.state & ControlMask) {
262 strcat(buffer, "Control+");
264 if (ev.xkey.state & ShiftMask) {
265 strcat(buffer, "Shift+");
267 if (ev.xkey.state & Mod1Mask) {
268 strcat(buffer, "Mod1+");
270 if (ev.xkey.state & Mod2Mask) {
271 strcat(buffer, "Mod2+");
273 if (ev.xkey.state & Mod3Mask) {
274 strcat(buffer, "Mod3+");
276 if (ev.xkey.state & Mod4Mask) {
277 strcat(buffer, "Mod4+");
279 if (ev.xkey.state & Mod5Mask) {
280 strcat(buffer, "Mod5+");
282 strcat(buffer, key);
284 return wstrdup(buffer);
287 static void captureClick(WMWidget * w, void *data)
289 _Panel *panel = (_Panel *) data;
290 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
291 char *shortcut;
293 if (!panel->capturing) {
294 panel->capturing = 1;
295 WMSetButtonText(w, _("Cancel"));
296 WMSetLabelText(panel->instructionsL,
297 _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
298 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
299 shortcut = captureShortcut(dpy, panel);
300 if (shortcut) {
301 int row = WMGetListSelectedItemRow(panel->actLs);
303 WMSetTextFieldText(panel->shoT, shortcut);
304 if (row >= 0) {
305 if (panel->shortcuts[row])
306 wfree(panel->shortcuts[row]);
307 panel->shortcuts[row] = shortcut;
309 WMRedisplayWidget(panel->actLs);
310 } else {
311 wfree(shortcut);
315 panel->capturing = 0;
316 WMSetButtonText(w, _("Capture"));
317 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
318 XUngrabKeyboard(dpy, CurrentTime);
321 static void clearShortcut(WMWidget * w, void *data)
323 _Panel *panel = (_Panel *) data;
324 int row = WMGetListSelectedItemRow(panel->actLs);
326 WMSetTextFieldText(panel->shoT, NULL);
328 if (row >= 0) {
329 if (panel->shortcuts[row])
330 wfree(panel->shortcuts[row]);
331 panel->shortcuts[row] = NULL;
332 WMRedisplayWidget(panel->actLs);
336 static void typedKeys(void *observerData, WMNotification * notification)
338 _Panel *panel = (_Panel *) observerData;
339 int row = WMGetListSelectedItemRow(panel->actLs);
341 if (row < 0)
342 return;
344 if (panel->shortcuts[row])
345 wfree(panel->shortcuts[row]);
346 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
347 if (strlen(panel->shortcuts[row]) == 0) {
348 wfree(panel->shortcuts[row]);
349 panel->shortcuts[row] = NULL;
351 WMRedisplayWidget(panel->actLs);
354 static void listClick(WMWidget * w, void *data)
356 _Panel *panel = (_Panel *) data;
357 int row = WMGetListSelectedItemRow(w);
359 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
362 static char *trimstr(char *str)
364 char *p = str;
365 int i;
367 while (isspace(*p))
368 p++;
369 p = wstrdup(p);
370 i = strlen(p);
371 while (isspace(p[i]) && i > 0) {
372 p[i] = 0;
373 i--;
376 return p;
379 static void showData(_Panel * panel)
381 char *str;
382 int i;
384 for (i = 0; i < panel->actionCount; i++) {
386 str = GetStringForKey(keyOptions[i]);
387 if (panel->shortcuts[i])
388 wfree(panel->shortcuts[i]);
389 if (str)
390 panel->shortcuts[i] = trimstr(str);
391 else
392 panel->shortcuts[i] = NULL;
394 if (panel->shortcuts[i] &&
395 (strcasecmp(panel->shortcuts[i], "none") == 0 || strlen(panel->shortcuts[i]) == 0)) {
396 wfree(panel->shortcuts[i]);
397 panel->shortcuts[i] = NULL;
400 WMRedisplayWidget(panel->actLs);
403 static void paintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
405 int width, height, x, y;
406 _Panel *panel = (_Panel *) WMGetHangedData(lPtr);
407 WMScreen *scr = WMWidgetScreen(lPtr);
408 Display *dpy = WMScreenDisplay(scr);
409 WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
411 width = rect->size.width;
412 height = rect->size.height;
413 x = rect->pos.x;
414 y = rect->pos.y;
416 XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
418 if (panel->shortcuts[index]) {
419 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
420 WMSize size = WMGetPixmapSize(pix);
422 WMDrawPixmap(pix, d, x + (20 - size.width) / 2, (height - size.height) / 2 + y);
423 WMReleasePixmap(pix);
426 WMDrawString(scr, d, panel->black, panel->font, x + 20, y, text, strlen(text));
429 static void createPanel(Panel * p)
431 _Panel *panel = (_Panel *) p;
432 WMScreen *scr = WMWidgetScreen(panel->parent);
433 WMColor *color;
434 WMFont *boldFont;
436 panel->capturing = 0;
438 panel->white = WMWhiteColor(scr);
439 panel->black = WMBlackColor(scr);
440 panel->gray = WMGrayColor(scr);
441 panel->font = WMSystemFontOfSize(scr, 12);
443 panel->box = WMCreateBox(panel->parent);
444 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
446 boldFont = WMBoldSystemFontOfSize(scr, 12);
448 /* **************** Actions **************** */
449 panel->actL = WMCreateLabel(panel->box);
450 WMResizeWidget(panel->actL, 280, 20);
451 WMMoveWidget(panel->actL, 20, 10);
452 WMSetLabelFont(panel->actL, boldFont);
453 WMSetLabelText(panel->actL, _("Actions"));
454 WMSetLabelRelief(panel->actL, WRSunken);
455 WMSetLabelTextAlignment(panel->actL, WACenter);
456 color = WMDarkGrayColor(scr);
457 WMSetWidgetBackgroundColor(panel->actL, color);
458 WMReleaseColor(color);
459 WMSetLabelTextColor(panel->actL, panel->white);
461 panel->actLs = WMCreateList(panel->box);
462 WMResizeWidget(panel->actLs, 280, 190);
463 WMMoveWidget(panel->actLs, 20, 32);
464 WMSetListUserDrawProc(panel->actLs, paintItem);
465 WMHangData(panel->actLs, panel);
467 WMAddListItem(panel->actLs, _("Open applications menu"));
468 WMAddListItem(panel->actLs, _("Open window list menu"));
469 WMAddListItem(panel->actLs, _("Open window commands menu"));
470 WMAddListItem(panel->actLs, _("Hide active application"));
471 WMAddListItem(panel->actLs, _("Hide other applications"));
472 WMAddListItem(panel->actLs, _("Miniaturize active window"));
473 WMAddListItem(panel->actLs, _("Miniaturize all windows"));
474 WMAddListItem(panel->actLs, _("Close active window"));
475 WMAddListItem(panel->actLs, _("Maximize active window"));
476 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
477 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
478 WMAddListItem(panel->actLs, _("Maximize active window left half"));
479 WMAddListItem(panel->actLs, _("Maximize active window right half"));
480 WMAddListItem(panel->actLs, _("Maximus: Tiled maximization "));
481 WMAddListItem(panel->actLs, _("Raise active window"));
482 WMAddListItem(panel->actLs, _("Lower active window"));
483 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
484 WMAddListItem(panel->actLs, _("Shade active window"));
485 WMAddListItem(panel->actLs, _("Move/Resize active window"));
486 WMAddListItem(panel->actLs, _("Select active window"));
487 WMAddListItem(panel->actLs, _("Focus next window"));
488 WMAddListItem(panel->actLs, _("Focus previous window"));
489 WMAddListItem(panel->actLs, _("Focus next group window"));
490 WMAddListItem(panel->actLs, _("Focus previous group window"));
491 WMAddListItem(panel->actLs, _("Switch to next workspace"));
492 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
493 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
494 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
495 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
496 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
497 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
498 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
499 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
500 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
501 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
502 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
503 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
504 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
505 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
506 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
507 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
508 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
509 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
510 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
511 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
512 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
513 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
514 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
515 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
516 WMAddListItem(panel->actLs, _("Raise/Lower Dock"));
517 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
518 #ifdef XKB_MODELOCK
519 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
520 #endif /* XKB_MODELOCK */
522 WMSetListAction(panel->actLs, listClick, panel);
524 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
525 panel->shortcuts = wmalloc(sizeof(char *) * panel->actionCount);
526 memset(panel->shortcuts, 0, sizeof(char *) * panel->actionCount);
528 /***************** Shortcut ****************/
530 panel->shoF = WMCreateFrame(panel->box);
531 WMResizeWidget(panel->shoF, 190, 210);
532 WMMoveWidget(panel->shoF, 315, 10);
533 WMSetFrameTitle(panel->shoF, _("Shortcut"));
535 panel->shoT = WMCreateTextField(panel->shoF);
536 WMResizeWidget(panel->shoT, 160, 20);
537 WMMoveWidget(panel->shoT, 15, 65);
538 WMAddNotificationObserver(typedKeys, panel, WMTextDidChangeNotification, panel->shoT);
540 panel->cleB = WMCreateCommandButton(panel->shoF);
541 WMResizeWidget(panel->cleB, 75, 24);
542 WMMoveWidget(panel->cleB, 15, 95);
543 WMSetButtonText(panel->cleB, _("Clear"));
544 WMSetButtonAction(panel->cleB, clearShortcut, panel);
546 panel->defB = WMCreateCommandButton(panel->shoF);
547 WMResizeWidget(panel->defB, 75, 24);
548 WMMoveWidget(panel->defB, 100, 95);
549 WMSetButtonText(panel->defB, _("Capture"));
550 WMSetButtonAction(panel->defB, captureClick, panel);
552 panel->instructionsL = WMCreateLabel(panel->shoF);
553 WMResizeWidget(panel->instructionsL, 160, 55);
554 WMMoveWidget(panel->instructionsL, 15, 140);
555 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
556 WMSetLabelWraps(panel->instructionsL, True);
557 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
559 WMMapSubwidgets(panel->shoF);
561 WMReleaseFont(boldFont);
563 WMRealizeWidget(panel->box);
564 WMMapSubwidgets(panel->box);
566 showData(panel);
569 static void storeData(_Panel * panel)
571 int i;
572 char *str;
574 for (i = 0; i < panel->actionCount; i++) {
575 str = NULL;
576 if (panel->shortcuts[i]) {
577 str = trimstr(panel->shortcuts[i]);
578 if (strlen(str) == 0) {
579 wfree(str);
580 str = NULL;
583 if (str) {
584 SetStringForKey(str, keyOptions[i]);
585 wfree(str);
586 } else {
587 SetStringForKey("None", keyOptions[i]);
592 Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent)
594 _Panel *panel;
596 panel = wmalloc(sizeof(_Panel));
597 memset(panel, 0, sizeof(_Panel));
599 panel->sectionName = _("Keyboard Shortcut Preferences");
601 panel->description = _("Change the keyboard shortcuts for actions such\n"
602 "as changing workspaces and opening menus.");
604 panel->parent = parent;
606 panel->callbacks.createWidgets = createPanel;
607 panel->callbacks.updateDomain = storeData;
609 AddSection(panel, ICON_FILE);
611 return panel;