Change to the linux kernel coding style
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
2 *
3 * WPrefs - Window Maker Preferences Program
4 *
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
6 *
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
21 */
22
23 #include "config.h" /* for HAVE_XCONVERTCASE */
24
25 #include "WPrefs.h"
26 #include <ctype.h>
27
28 #include <X11/keysym.h>
29
30 typedef struct _Panel {
31 WMBox *box;
32
33 char *sectionName;
34
35 char *description;
36
37 CallbackRec callbacks;
38
39 WMWidget *parent;
40
41 WMLabel *actL;
42 WMList *actLs;
43
44 WMFrame *shoF;
45 WMTextField *shoT;
46 WMButton *cleB;
47 WMButton *defB;
48
49 WMLabel *instructionsL;
50
51 WMColor *white;
52 WMColor *black;
53 WMColor *gray;
54 WMFont *font;
55
56 /**/ char capturing;
57 char **shortcuts;
58 int actionCount;
59 } _Panel;
60
61 #define ICON_FILE "keyshortcuts"
62
63 /* must be in the same order as the corresponding items in actions list */
64 static char *keyOptions[] = {
65 "RootMenuKey",
66 "WindowListKey",
67 "WindowMenuKey",
68 "HideKey",
69 "HideOthersKey",
70 "MiniaturizeKey",
71 "CloseKey",
72 "MaximizeKey",
73 "VMaximizeKey",
74 "HMaximizeKey",
75 "RaiseKey",
76 "LowerKey",
77 "RaiseLowerKey",
78 "ShadeKey",
79 "MoveResizeKey",
80 "SelectKey",
81 "FocusNextKey",
82 "FocusPrevKey",
83 "NextWorkspaceKey",
84 "PrevWorkspaceKey",
85 "NextWorkspaceLayerKey",
86 "PrevWorkspaceLayerKey",
87 "Workspace1Key",
88 "Workspace2Key",
89 "Workspace3Key",
90 "Workspace4Key",
91 "Workspace5Key",
92 "Workspace6Key",
93 "Workspace7Key",
94 "Workspace8Key",
95 "Workspace9Key",
96 "Workspace10Key",
97 "WindowShortcut1Key",
98 "WindowShortcut2Key",
99 "WindowShortcut3Key",
100 "WindowShortcut4Key",
101 "WindowShortcut5Key",
102 "WindowShortcut6Key",
103 "WindowShortcut7Key",
104 "WindowShortcut8Key",
105 "WindowShortcut9Key",
106 "WindowShortcut10Key",
107 "ScreenSwitchKey",
108 #ifdef VIRTUAL_DESKTOP
109 "VirtualEdgeLeftKey",
110 "VirtualEdgeRightKey",
111 "VirtualEdgeUpKey",
112 "VirtualEdgeDownKey",
113 #endif
114 "ClipRaiseKey",
115 "ClipLowerKey",
116 #ifndef XKB_MODELOCK
117 "ClipRaiseLowerKey"
118 #else
119 "ClipRaiseLowerKey",
120 "ToggleKbdModeKey"
121 #endif /* XKB_MODELOCK */
122 };
123
124 #ifndef HAVE_XCONVERTCASE
125 /* from Xlib */
126
127 static void XConvertCase(register KeySym sym, KeySym * lower, KeySym * upper)
128 {
129 *lower = sym;
130 *upper = sym;
131 switch (sym >> 8) {
132 case 0: /* Latin 1 */
133 if ((sym >= XK_A) && (sym <= XK_Z))
134 *lower += (XK_a - XK_A);
135 else if ((sym >= XK_a) && (sym <= XK_z))
136 *upper -= (XK_a - XK_A);
137 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
138 *lower += (XK_agrave - XK_Agrave);
139 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
140 *upper -= (XK_agrave - XK_Agrave);
141 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
142 *lower += (XK_oslash - XK_Ooblique);
143 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
144 *upper -= (XK_oslash - XK_Ooblique);
145 break;
146 case 1: /* Latin 2 */
147 /* Assume the KeySym is a legal value (ignore discontinuities) */
148 if (sym == XK_Aogonek)
149 *lower = XK_aogonek;
150 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
151 *lower += (XK_lstroke - XK_Lstroke);
152 else if (sym >= XK_Scaron && sym <= XK_Zacute)
153 *lower += (XK_scaron - XK_Scaron);
154 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
155 *lower += (XK_zcaron - XK_Zcaron);
156 else if (sym == XK_aogonek)
157 *upper = XK_Aogonek;
158 else if (sym >= XK_lstroke && sym <= XK_sacute)
159 *upper -= (XK_lstroke - XK_Lstroke);
160 else if (sym >= XK_scaron && sym <= XK_zacute)
161 *upper -= (XK_scaron - XK_Scaron);
162 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
163 *upper -= (XK_zcaron - XK_Zcaron);
164 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
165 *lower += (XK_racute - XK_Racute);
166 else if (sym >= XK_racute && sym <= XK_tcedilla)
167 *upper -= (XK_racute - XK_Racute);
168 break;
169 case 2: /* Latin 3 */
170 /* Assume the KeySym is a legal value (ignore discontinuities) */
171 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
172 *lower += (XK_hstroke - XK_Hstroke);
173 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
174 *lower += (XK_gbreve - XK_Gbreve);
175 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
176 *upper -= (XK_hstroke - XK_Hstroke);
177 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
178 *upper -= (XK_gbreve - XK_Gbreve);
179 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
180 *lower += (XK_cabovedot - XK_Cabovedot);
181 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
182 *upper -= (XK_cabovedot - XK_Cabovedot);
183 break;
184 case 3: /* Latin 4 */
185 /* Assume the KeySym is a legal value (ignore discontinuities) */
186 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
187 *lower += (XK_rcedilla - XK_Rcedilla);
188 else if (sym >= XK_rcedilla && sym <= XK_tslash)
189 *upper -= (XK_rcedilla - XK_Rcedilla);
190 else if (sym == XK_ENG)
191 *lower = XK_eng;
192 else if (sym == XK_eng)
193 *upper = XK_ENG;
194 else if (sym >= XK_Amacron && sym <= XK_Umacron)
195 *lower += (XK_amacron - XK_Amacron);
196 else if (sym >= XK_amacron && sym <= XK_umacron)
197 *upper -= (XK_amacron - XK_Amacron);
198 break;
199 case 6: /* Cyrillic */
200 /* Assume the KeySym is a legal value (ignore discontinuities) */
201 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
202 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
203 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
204 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
205 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
206 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
207 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
208 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
209 break;
210 case 7: /* Greek */
211 /* Assume the KeySym is a legal value (ignore discontinuities) */
212 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
213 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
214 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
215 sym != XK_Greek_iotaaccentdieresis && sym != XK_Greek_upsilonaccentdieresis)
216 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
217 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
218 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
219 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && sym != XK_Greek_finalsmallsigma)
220 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
221 break;
222 case 0x14: /* Armenian */
223 if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
224 *lower = sym | 1;
225 *upper = sym & ~1;
226 }
227 break;
228 }
229 }
230 #endif
231
232 static char *captureShortcut(Display * dpy, _Panel * panel)
233 {
234 XEvent ev;
235 KeySym ksym, lksym, uksym;
236 char buffer[64];
237 char *key = NULL;
238
239 while (panel->capturing) {
240 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
241 WMNextEvent(dpy, &ev);
242 if (ev.type == KeyPress && ev.xkey.keycode != 0) {
243 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
244 if (!IsModifierKey(ksym)) {
245 XConvertCase(ksym, &lksym, &uksym);
246 key = XKeysymToString(uksym);
247
248 panel->capturing = 0;
249 break;
250 }
251 }
252 WMHandleEvent(&ev);
253 }
254
255 if (!key)
256 return NULL;
257
258 buffer[0] = 0;
259
260 if (ev.xkey.state & ControlMask) {
261 strcat(buffer, "Control+");
262 }
263 if (ev.xkey.state & ShiftMask) {
264 strcat(buffer, "Shift+");
265 }
266 if (ev.xkey.state & Mod1Mask) {
267 strcat(buffer, "Mod1+");
268 }
269 if (ev.xkey.state & Mod2Mask) {
270 strcat(buffer, "Mod2+");
271 }
272 if (ev.xkey.state & Mod3Mask) {
273 strcat(buffer, "Mod3+");
274 }
275 if (ev.xkey.state & Mod4Mask) {
276 strcat(buffer, "Mod4+");
277 }
278 if (ev.xkey.state & Mod5Mask) {
279 strcat(buffer, "Mod5+");
280 }
281 strcat(buffer, key);
282
283 return wstrdup(buffer);
284 }
285
286 static void captureClick(WMWidget * w, void *data)
287 {
288 _Panel *panel = (_Panel *) data;
289 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
290 char *shortcut;
291
292 if (!panel->capturing) {
293 panel->capturing = 1;
294 WMSetButtonText(w, _("Cancel"));
295 WMSetLabelText(panel->instructionsL,
296 _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
297 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
298 shortcut = captureShortcut(dpy, panel);
299 if (shortcut) {
300 int row = WMGetListSelectedItemRow(panel->actLs);
301
302 WMSetTextFieldText(panel->shoT, shortcut);
303 if (row >= 0) {
304 if (panel->shortcuts[row])
305 wfree(panel->shortcuts[row]);
306 panel->shortcuts[row] = shortcut;
307
308 WMRedisplayWidget(panel->actLs);
309 } else {
310 wfree(shortcut);
311 }
312 }
313 }
314 panel->capturing = 0;
315 WMSetButtonText(w, _("Capture"));
316 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
317 XUngrabKeyboard(dpy, CurrentTime);
318 }
319
320 static void clearShortcut(WMWidget * w, void *data)
321 {
322 _Panel *panel = (_Panel *) data;
323 int row = WMGetListSelectedItemRow(panel->actLs);
324
325 WMSetTextFieldText(panel->shoT, NULL);
326
327 if (row >= 0) {
328 if (panel->shortcuts[row])
329 wfree(panel->shortcuts[row]);
330 panel->shortcuts[row] = NULL;
331 WMRedisplayWidget(panel->actLs);
332 }
333 }
334
335 static void typedKeys(void *observerData, WMNotification * notification)
336 {
337 _Panel *panel = (_Panel *) observerData;
338 int row = WMGetListSelectedItemRow(panel->actLs);
339
340 if (row < 0)
341 return;
342
343 if (panel->shortcuts[row])
344 wfree(panel->shortcuts[row]);
345 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
346 if (strlen(panel->shortcuts[row]) == 0) {
347 wfree(panel->shortcuts[row]);
348 panel->shortcuts[row] = NULL;
349 }
350 WMRedisplayWidget(panel->actLs);
351 }
352
353 static void listClick(WMWidget * w, void *data)
354 {
355 _Panel *panel = (_Panel *) data;
356 int row = WMGetListSelectedItemRow(w);
357
358 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
359 }
360
361 static char *trimstr(char *str)
362 {
363 char *p = str;
364 int i;
365
366 while (isspace(*p))
367 p++;
368 p = wstrdup(p);
369 i = strlen(p);
370 while (isspace(p[i]) && i > 0) {
371 p[i] = 0;
372 i--;
373 }
374
375 return p;
376 }
377
378 static void showData(_Panel * panel)
379 {
380 char *str;
381 int i;
382
383 for (i = 0; i < panel->actionCount; i++) {
384
385 str = GetStringForKey(keyOptions[i]);
386 if (panel->shortcuts[i])
387 wfree(panel->shortcuts[i]);
388 if (str)
389 panel->shortcuts[i] = trimstr(str);
390 else
391 panel->shortcuts[i] = NULL;
392
393 if (panel->shortcuts[i] &&
394 (strcasecmp(panel->shortcuts[i], "none") == 0 || strlen(panel->shortcuts[i]) == 0)) {
395 wfree(panel->shortcuts[i]);
396 panel->shortcuts[i] = NULL;
397 }
398 }
399 WMRedisplayWidget(panel->actLs);
400 }
401
402 static void paintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
403 {
404 int width, height, x, y;
405 _Panel *panel = (_Panel *) WMGetHangedData(lPtr);
406 WMScreen *scr = WMWidgetScreen(lPtr);
407 Display *dpy = WMScreenDisplay(scr);
408 WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
409
410 width = rect->size.width;
411 height = rect->size.height;
412 x = rect->pos.x;
413 y = rect->pos.y;
414
415 XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
416
417 if (panel->shortcuts[index]) {
418 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
419 WMSize size = WMGetPixmapSize(pix);
420
421 WMDrawPixmap(pix, d, x + (20 - size.width) / 2, (height - size.height) / 2 + y);
422 WMReleasePixmap(pix);
423 }
424
425 WMDrawString(scr, d, panel->black, panel->font, x + 20, y, text, strlen(text));
426 }
427
428 static void createPanel(Panel * p)
429 {
430 _Panel *panel = (_Panel *) p;
431 WMScreen *scr = WMWidgetScreen(panel->parent);
432 WMColor *color;
433 WMFont *boldFont;
434
435 panel->capturing = 0;
436
437 panel->white = WMWhiteColor(scr);
438 panel->black = WMBlackColor(scr);
439 panel->gray = WMGrayColor(scr);
440 panel->font = WMSystemFontOfSize(scr, 12);
441
442 panel->box = WMCreateBox(panel->parent);
443 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
444
445 boldFont = WMBoldSystemFontOfSize(scr, 12);
446
447 /* **************** Actions **************** */
448 panel->actL = WMCreateLabel(panel->box);
449 WMResizeWidget(panel->actL, 280, 20);
450 WMMoveWidget(panel->actL, 20, 10);
451 WMSetLabelFont(panel->actL, boldFont);
452 WMSetLabelText(panel->actL, _("Actions"));
453 WMSetLabelRelief(panel->actL, WRSunken);
454 WMSetLabelTextAlignment(panel->actL, WACenter);
455 color = WMDarkGrayColor(scr);
456 WMSetWidgetBackgroundColor(panel->actL, color);
457 WMReleaseColor(color);
458 WMSetLabelTextColor(panel->actL, panel->white);
459
460 panel->actLs = WMCreateList(panel->box);
461 WMResizeWidget(panel->actLs, 280, 190);
462 WMMoveWidget(panel->actLs, 20, 32);
463 WMSetListUserDrawProc(panel->actLs, paintItem);
464 WMHangData(panel->actLs, panel);
465
466 WMAddListItem(panel->actLs, _("Open applications menu"));
467 WMAddListItem(panel->actLs, _("Open window list menu"));
468 WMAddListItem(panel->actLs, _("Open window commands menu"));
469 WMAddListItem(panel->actLs, _("Hide active application"));
470 WMAddListItem(panel->actLs, _("Hide other applications"));
471 WMAddListItem(panel->actLs, _("Miniaturize active window"));
472 WMAddListItem(panel->actLs, _("Close active window"));
473 WMAddListItem(panel->actLs, _("Maximize active window"));
474 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
475 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
476 WMAddListItem(panel->actLs, _("Raise active window"));
477 WMAddListItem(panel->actLs, _("Lower active window"));
478 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
479 WMAddListItem(panel->actLs, _("Shade active window"));
480 WMAddListItem(panel->actLs, _("Move/Resize active window"));
481 WMAddListItem(panel->actLs, _("Select active window"));
482 WMAddListItem(panel->actLs, _("Focus next window"));
483 WMAddListItem(panel->actLs, _("Focus previous window"));
484 WMAddListItem(panel->actLs, _("Switch to next workspace"));
485 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
486 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
487 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
488 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
489 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
490 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
491 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
492 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
493 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
494 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
495 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
496 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
497 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
498 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
499 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
500 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
501 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
502 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
503 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
504 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
505 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
506 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
507 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
508 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
509 #ifdef VIRTUAL_DESKTOP
510 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next left edge"));
511 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next right edge"));
512 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next top edge"));
513 WMAddListItem(panel->actLs, _("Move VirtualDesktop to next bottom edge"));
514 #endif
515 WMAddListItem(panel->actLs, _("Raise Clip"));
516 WMAddListItem(panel->actLs, _("Lower Clip"));
517 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
518 #ifdef XKB_MODELOCK
519 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
520 #endif /* XKB_MODELOCK */
521
522 WMSetListAction(panel->actLs, listClick, panel);
523
524 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
525 panel->shortcuts = wmalloc(sizeof(char *) * panel->actionCount);
526 memset(panel->shortcuts, 0, sizeof(char *) * panel->actionCount);
527
528 /***************** Shortcut ****************/
529
530 panel->shoF = WMCreateFrame(panel->box);
531 WMResizeWidget(panel->shoF, 190, 210);
532 WMMoveWidget(panel->shoF, 315, 10);
533 WMSetFrameTitle(panel->shoF, _("Shortcut"));
534
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);
539
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);
545
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);
551
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."));
558
559 WMMapSubwidgets(panel->shoF);
560
561 WMReleaseFont(boldFont);
562
563 WMRealizeWidget(panel->box);
564 WMMapSubwidgets(panel->box);
565
566 showData(panel);
567 }
568
569 static void storeData(_Panel * panel)
570 {
571 int i;
572 char *str;
573
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;
581 }
582 }
583 if (str) {
584 SetStringForKey(str, keyOptions[i]);
585 wfree(str);
586 } else {
587 SetStringForKey("None", keyOptions[i]);
588 }
589 }
590 }
591
592 Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent)
593 {
594 _Panel *panel;
595
596 panel = wmalloc(sizeof(_Panel));
597 memset(panel, 0, sizeof(_Panel));
598
599 panel->sectionName = _("Keyboard Shortcut Preferences");
600
601 panel->description = _("Change the keyboard shortcuts for actions such\n"
602 "as changing workspaces and opening menus.");
603
604 panel->parent = parent;
605
606 panel->callbacks.createWidgets = createPanel;
607 panel->callbacks.updateDomain = storeData;
608
609 AddSection(panel, ICON_FILE);
610
611 return panel;
612 }