2 * Copyright 1999-2009 Jeremy Friesner
3 * Copyright 2009-2010 Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
12 #include "ShortcutsWindow.h"
18 #include <Application.h>
21 #include <Clipboard.h>
22 #include <ColumnListView.h>
23 #include <ColumnTypes.h>
24 #include <ControlLook.h>
26 #include <FilePanel.h>
27 #include <FindDirectory.h>
29 #include <LayoutBuilder.h>
35 #include <MessageFilter.h>
37 #include <PopUpMenu.h>
39 #include <ScrollBar.h>
40 #include <ScrollView.h>
42 #include <SupportDefs.h>
44 #include "EditWindow.h"
46 #include "MetaKeyStateMap.h"
47 #include "ParseCommandLine.h"
48 #include "PopUpColumn.h"
49 #include "ShortcutsFilterConstants.h"
50 #include "ShortcutsSpec.h"
53 // Window sizing constraints
54 #define MAX_WIDTH 10000
55 #define MAX_HEIGHT 10000
56 // SetSizeLimits does not provide a mechanism for specifying an
57 // unrestricted maximum. 10,000 seems to be the most common value used
58 // in other Haiku system applications.
60 #define WINDOW_SETTINGS_FILE_NAME "Shortcuts_window_settings"
61 // Because the "shortcuts_settings" file (SHORTCUTS_SETTING_FILE_NAME) is
62 // already used as a communications method between this configurator and
63 // the "shortcut_catcher" input_server filter, it should not be overloaded
64 // with window position information, instead, a separate file is used.
66 #undef B_TRANSLATION_CONTEXT
67 #define B_TRANSLATION_CONTEXT "ShortcutsWindow"
69 #define ERROR "Shortcuts error"
70 #define WARNING "Shortcuts warning"
73 // Creates a pop-up-menu that reflects the possible states of the specified
76 CreateMetaPopUp(int column
)
78 MetaKeyStateMap
& map
= GetNthKeyMap(column
);
79 BPopUpMenu
* popup
= new BPopUpMenu(NULL
, false);
80 int stateCount
= map
.GetNumStates();
82 for (int i
= 0; i
< stateCount
; i
++)
83 popup
->AddItem(new BMenuItem(map
.GetNthStateDesc(i
), NULL
));
89 // Creates a pop-up that allows the user to choose a key-cap visually
93 BPopUpMenu
* popup
= new BPopUpMenu(NULL
, false);
94 int numKeys
= GetNumKeyIndices();
95 for (int i
= 0; i
< numKeys
; i
++) {
96 const char* next
= GetKeyName(i
);
98 popup
->AddItem(new BMenuItem(next
, NULL
));
105 ShortcutsWindow::ShortcutsWindow()
107 BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Shortcuts"),
108 B_TITLED_WINDOW
, B_AUTO_UPDATE_SIZE_LIMITS
),
112 fKeySetModified(false),
113 fLastOpenWasAppend(false)
115 ShortcutsSpec::InitializeMetaMaps();
117 BMenuBar
* menuBar
= new BMenuBar("Menu Bar");
119 BMenu
* fileMenu
= new BMenu(B_TRANSLATE("File"));
120 fileMenu
->AddItem(new BMenuItem(B_TRANSLATE("Open KeySet" B_UTF8_ELLIPSIS
),
121 new BMessage(OPEN_KEYSET
), 'O'));
122 fileMenu
->AddItem(new BMenuItem(
123 B_TRANSLATE("Append KeySet" B_UTF8_ELLIPSIS
),
124 new BMessage(APPEND_KEYSET
), 'A'));
125 fileMenu
->AddItem(new BMenuItem(B_TRANSLATE("Revert to saved"),
126 new BMessage(REVERT_KEYSET
), 'A'));
127 fileMenu
->AddItem(new BSeparatorItem
);
128 fileMenu
->AddItem(new BMenuItem(
129 B_TRANSLATE("Save KeySet as" B_UTF8_ELLIPSIS
),
130 new BMessage(SAVE_KEYSET_AS
), 'S'));
131 fileMenu
->AddItem(new BSeparatorItem
);
132 fileMenu
->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
133 new BMessage(B_QUIT_REQUESTED
), 'Q'));
134 menuBar
->AddItem(fileMenu
);
136 BRect tableBounds
= Bounds();
137 tableBounds
.top
= menuBar
->Bounds().bottom
+ 1;
138 tableBounds
.right
-= B_V_SCROLL_BAR_WIDTH
;
139 tableBounds
.bottom
-= B_H_SCROLL_BAR_HEIGHT
;
141 fColumnListView
= new BColumnListView(NULL
,
142 B_WILL_DRAW
| B_FRAME_EVENTS
, B_FANCY_BORDER
);
144 float cellWidth
= be_plain_font
->StringWidth("Either") + 20;
145 // ShortcutsSpec does not seem to translate the string "Either".
147 for (int i
= 0; i
< ShortcutsSpec::NUM_META_COLUMNS
; i
++) {
148 const char* name
= ShortcutsSpec::GetColumnName(i
);
149 float headerWidth
= be_plain_font
->StringWidth(name
) + 20;
150 float width
= max_c(headerWidth
, cellWidth
);
152 fColumnListView
->AddColumn(new PopUpColumn(CreateMetaPopUp(i
), name
,
153 width
, width
- 1, width
* 1.5, B_TRUNCATE_END
, false, true, 1),
154 fColumnListView
->CountColumns());
157 float keyCellWidth
= be_plain_font
->StringWidth("Caps Lock") + 20;
158 fColumnListView
->AddColumn(new PopUpColumn(CreateKeysPopUp(),
159 B_TRANSLATE("Key"), keyCellWidth
, keyCellWidth
- 10,
160 keyCellWidth
+ 30, B_TRUNCATE_END
),
161 fColumnListView
->CountColumns());
162 BPopUpMenu
* popup
= new BPopUpMenu(NULL
, false);
163 popup
->AddItem(new BMenuItem(
164 B_TRANSLATE("(Choose application with file requester)"), NULL
));
165 popup
->AddItem(new BMenuItem(
166 B_TRANSLATE("*InsertString \"Your Text Here\""), NULL
));
167 popup
->AddItem(new BMenuItem(
168 B_TRANSLATE("*MoveMouse +20 +0"), NULL
));
169 popup
->AddItem(new BMenuItem(B_TRANSLATE("*MoveMouseTo 50% 50%"), NULL
));
170 popup
->AddItem(new BMenuItem(B_TRANSLATE("*MouseButton 1"), NULL
));
171 popup
->AddItem(new BMenuItem(
172 B_TRANSLATE("*LaunchHandler text/html"), NULL
));
173 popup
->AddItem(new BMenuItem(
174 B_TRANSLATE("*Multi \"*MoveMouseTo 100% 0\" \"*MouseButton 1\""),
176 popup
->AddItem(new BMenuItem(B_TRANSLATE("*MouseDown"), NULL
));
177 popup
->AddItem(new BMenuItem(B_TRANSLATE("*MouseUp"), NULL
));
178 popup
->AddItem(new BMenuItem(
179 B_TRANSLATE("*SendMessage application/x-vnd.Be-TRAK 'Tfnd'"), NULL
));
180 popup
->AddItem(new BMenuItem(B_TRANSLATE("*Beep"), NULL
));
181 fColumnListView
->AddColumn(new PopUpColumn(popup
, B_TRANSLATE("Application"),
182 300.0, 223.0, 324.0, B_TRUNCATE_END
, true),
183 fColumnListView
->CountColumns());
185 fColumnListView
->SetSelectionMessage(new BMessage(HOTKEY_ITEM_SELECTED
));
186 fColumnListView
->SetSelectionMode(B_SINGLE_SELECTION_LIST
);
187 fColumnListView
->SetTarget(this);
189 fAddButton
= new BButton("add", B_TRANSLATE("Add new shortcut"),
190 new BMessage(ADD_HOTKEY_ITEM
), B_FOLLOW_BOTTOM
);
192 fRemoveButton
= new BButton("remove",
193 B_TRANSLATE("Remove selected shortcut"),
194 new BMessage(REMOVE_HOTKEY_ITEM
), B_FOLLOW_BOTTOM
);
195 fRemoveButton
->SetEnabled(false);
197 fSaveButton
= new BButton("save", B_TRANSLATE("Save & apply"),
198 new BMessage(SAVE_KEYSET
), B_FOLLOW_BOTTOM
| B_FOLLOW_RIGHT
);
199 fSaveButton
->SetEnabled(false);
203 entry_ref windowSettingsRef
;
204 if (_GetWindowSettingsFile(&windowSettingsRef
)) {
205 // The window settings file is not accepted via B_REFS_RECEIVED; this
206 // is a behind-the-scenes file that the user will never see or
208 BFile
windowSettingsFile(&windowSettingsRef
, B_READ_ONLY
);
209 BMessage loadMessage
;
210 if (loadMessage
.Unflatten(&windowSettingsFile
) == B_OK
)
211 _LoadWindowSettings(loadMessage
);
215 if (_GetSettingsFile(&keySetRef
)) {
216 BMessage
message(B_REFS_RECEIVED
);
217 message
.AddRef("refs", &keySetRef
);
218 message
.AddString("startupRef", "please");
219 PostMessage(&message
);
220 // tell ourselves to load this file if it exists
223 fColumnListView
->ResizeAllColumnsToPreferred();
225 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 0)
227 .AddGroup(B_VERTICAL
)
228 .SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, B_SIZE_UNSET
))
229 .SetInsets(B_USE_WINDOW_SPACING
)
230 .Add(fColumnListView
)
231 .AddGroup(B_HORIZONTAL
)
232 .AddGroup(B_HORIZONTAL
)
233 .SetExplicitAlignment(BAlignment(B_ALIGN_LEFT
, B_ALIGN_TOP
))
237 .AddGroup(B_HORIZONTAL
)
238 .SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT
, B_ALIGN_TOP
))
248 ShortcutsWindow::~ShortcutsWindow()
253 be_app
->PostMessage(B_QUIT_REQUESTED
);
258 ShortcutsWindow::QuitRequested()
262 if (fKeySetModified
) {
263 BAlert
* alert
= new BAlert(WARNING
,
264 B_TRANSLATE("Save changes before closing?"),
265 B_TRANSLATE("Cancel"), B_TRANSLATE("Don't save"),
266 B_TRANSLATE("Save"));
267 alert
->SetShortcut(0, B_ESCAPE
);
268 alert
->SetShortcut(1, 'd');
269 alert
->SetShortcut(2, 's');
270 switch (alert
->Go()) {
280 // Save: automatically if possible, otherwise go back and open
281 // up the file requester
282 if (fLastSaved
.InitCheck() == B_OK
) {
283 if (_SaveKeySet(fLastSaved
) == false) {
284 BAlert
* alert
= new BAlert(ERROR
,
285 B_TRANSLATE("Shortcuts was unable to save your "
287 B_TRANSLATE("Oh no"));
288 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
290 result
= true; // quit anyway
293 PostMessage(SAVE_KEYSET
);
301 fColumnListView
->DeselectAll();
303 // Save the window position.
305 if (_GetWindowSettingsFile(&ref
)) {
307 _SaveWindowSettings(entry
);
316 ShortcutsWindow::_GetSettingsFile(entry_ref
* eref
)
319 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
) != B_OK
)
322 path
.Append(SHORTCUTS_SETTING_FILE_NAME
);
324 if (BEntry(path
.Path(), true).GetRef(eref
) == B_OK
)
331 // Saves a settings file to (saveEntry). Returns true iff successful.
333 ShortcutsWindow::_SaveKeySet(BEntry
& saveEntry
)
335 BFile
saveTo(&saveEntry
, B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
);
336 if (saveTo
.InitCheck() != B_OK
)
339 BMessage saveMessage
;
340 for (int i
= 0; i
< fColumnListView
->CountRows(); i
++) {
342 if (((ShortcutsSpec
*)fColumnListView
->RowAt(i
))->Archive(&next
)
344 saveMessage
.AddMessage("spec", &next
);
346 printf("Error archiving ShortcutsSpec #%i!\n", i
);
349 bool result
= (saveMessage
.Flatten(&saveTo
) == B_OK
);
352 fKeySetModified
= false;
353 fSaveButton
->SetEnabled(false);
360 // Appends new entries from the file specified in the "spec" entry of
361 // (loadMessage). Returns true iff successful.
363 ShortcutsWindow::_LoadKeySet(const BMessage
& loadMessage
)
367 while (loadMessage
.FindMessage("spec", i
++, &message
) == B_OK
) {
369 = (ShortcutsSpec
*)ShortcutsSpec::Instantiate(&message
);
371 fColumnListView
->AddRow(spec
);
373 printf("_LoadKeySet: Error parsing spec!\n");
380 // Gets the filesystem location of the "Shortcuts_window_settings" file.
382 ShortcutsWindow::_GetWindowSettingsFile(entry_ref
* eref
)
385 if (find_directory(B_USER_SETTINGS_DIRECTORY
, &path
) != B_OK
)
388 path
.Append(WINDOW_SETTINGS_FILE_NAME
);
390 return BEntry(path
.Path(), true).GetRef(eref
) == B_OK
;
394 // Saves the application settings file to (saveEntry). Because this is a
395 // non-essential file, errors are ignored when writing the settings.
397 ShortcutsWindow::_SaveWindowSettings(BEntry
& saveEntry
)
399 BFile
saveTo(&saveEntry
, B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
);
400 if (saveTo
.InitCheck() != B_OK
)
404 saveMsg
.AddRect("window frame", Frame());
406 for (int i
= 0; i
< fColumnListView
->CountColumns(); i
++) {
407 BColumn
* column
= fColumnListView
->ColumnAt(i
);
408 saveMsg
.AddFloat("column width", column
->Width());
411 saveMsg
.Flatten(&saveTo
);
415 // Loads the application settings file from (loadMessage) and resizes
416 // the interface to match the previously saved settings. Because this
417 // is a non-essential file, errors are ignored when loading the settings.
419 ShortcutsWindow::_LoadWindowSettings(const BMessage
& loadMessage
)
422 if (loadMessage
.FindRect("window frame", &frame
) == B_OK
) {
423 // ensure the frame does not resize below the computed minimum.
424 float width
= max_c(Bounds().right
, frame
.right
- frame
.left
);
425 float height
= max_c(Bounds().bottom
, frame
.bottom
- frame
.top
);
426 ResizeTo(width
, height
);
428 // ensure the frame is not placed outside of the screen.
429 BScreen
screen(this);
430 float left
= min_c(screen
.Frame().right
- width
, frame
.left
);
431 float top
= min_c(screen
.Frame().bottom
- height
, frame
.top
);
435 for (int i
= 0; i
< fColumnListView
->CountColumns(); i
++) {
436 BColumn
* column
= fColumnListView
->ColumnAt(i
);
438 if (loadMessage
.FindFloat("column width", i
, &columnWidth
) == B_OK
)
439 column
->SetWidth(max_c(column
->Width(), columnWidth
));
444 // Creates a new entry and adds it to the GUI. (defaultCommand) will be the
445 // text in the entry, or NULL if no text is desired.
447 ShortcutsWindow::_AddNewSpec(const char* defaultCommand
)
449 _MarkKeySetModified();
452 BRow
* curSel
= fColumnListView
->CurrentSelection();
454 spec
= new ShortcutsSpec(*((ShortcutsSpec
*)curSel
));
456 spec
= new ShortcutsSpec("");
457 for (int i
= 0; i
< fColumnListView
->CountColumns(); i
++)
458 spec
->SetField(new BStringField(""), i
);
461 fColumnListView
->AddRow(spec
);
462 fColumnListView
->AddToSelection(spec
);
463 fColumnListView
->ScrollTo(spec
);
465 spec
->SetCommand(defaultCommand
);
470 ShortcutsWindow::MessageReceived(BMessage
* message
)
472 switch (message
->what
) {
475 fLastOpenWasAppend
= (message
->what
== APPEND_KEYSET
);
479 BMessenger
messenger(this);
480 fOpenPanel
= new BFilePanel(B_OPEN_PANEL
, &messenger
, NULL
,
484 fOpenPanel
->SetButtonLabel(B_DEFAULT_BUTTON
, fLastOpenWasAppend
?
485 B_TRANSLATE("Append") : B_TRANSLATE("Open"));
488 // send a message to myself, to get me to reload the settings file
491 fLastOpenWasAppend
= false;
492 BMessage
reload(B_REFS_RECEIVED
);
494 _GetSettingsFile(&eref
);
495 reload
.AddRef("refs", &eref
);
496 reload
.AddString("startupRef", "yeah");
497 PostMessage(&reload
);
501 // respond to drag-and-drop messages here
507 while (message
->FindRef("refs", i
++, &ref
) == B_OK
) {
509 if (entry
.InitCheck() == B_OK
) {
512 if (path
.InitCheck() == B_OK
) {
513 // Add a new item with the given path.
514 BString
str(path
.Path());
515 DoStandardEscapes(str
);
516 _AddNewSpec(str
.String());
523 // respond to FileRequester's messages here
524 case B_REFS_RECEIVED
:
528 bool isStartMsg
= message
->HasString("startupRef");
529 if (message
->FindRef("refs", &ref
) == B_OK
) {
530 // load the file into (fileMsg)
533 BFile
file(&ref
, B_READ_ONLY
);
534 if ((file
.InitCheck() != B_OK
)
535 || (fileMsg
.Unflatten(&file
) != B_OK
)) {
537 // use this to save to anyway
538 fLastSaved
= BEntry(&ref
);
541 BAlert
* alert
= new BAlert(ERROR
,
542 B_TRANSLATE("Shortcuts was couldn't open your "
543 "KeySet file!"), B_TRANSLATE("OK"));
544 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
551 if (fLastOpenWasAppend
== false) {
553 while (fColumnListView
->CountRows()) {
555 static_cast<ShortcutsSpec
*>(fColumnListView
->RowAt(0));
556 fColumnListView
->RemoveRow(row
);
561 if (_LoadKeySet(fileMsg
)) {
562 if (isStartMsg
) fLastSaved
= BEntry(&ref
);
563 fSaveButton
->SetEnabled(isStartMsg
== false);
565 // If we just loaded in the Shortcuts settings file, then
566 // no need to tell the user to save on exit.
568 _GetSettingsFile(&eref
);
569 if (ref
== eref
) fKeySetModified
= false;
571 BAlert
* alert
= new BAlert(ERROR
,
572 B_TRANSLATE("Shortcuts was unable to parse your "
573 "KeySet file!"), B_TRANSLATE("OK"));
574 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
582 // these messages come from the pop-up menu of the Applications column
583 case SELECT_APPLICATION
:
586 static_cast<ShortcutsSpec
*>(fColumnListView
->CurrentSelection());
589 if (message
->FindRef("refs", &aref
) == B_OK
) {
591 if (ent
.InitCheck() == B_OK
) {
593 if ((ent
.GetPath(&path
) == B_OK
)
595 ProcessColumnTextString(ShortcutsSpec::STRING_COLUMN_INDEX
,
597 _MarkKeySetModified();
607 bool showSaveError
= false;
611 if ((message
->FindString("name", &name
) == B_OK
)
612 && (message
->FindRef("directory", &entry
) == B_OK
)) {
613 BDirectory
dir(&entry
);
614 BEntry
saveTo(&dir
, name
, true);
615 showSaveError
= ((saveTo
.InitCheck() != B_OK
)
616 || (_SaveKeySet(saveTo
) == false));
617 } else if (fLastSaved
.InitCheck() == B_OK
) {
618 // We've saved this before, save over previous file.
619 showSaveError
= (_SaveKeySet(fLastSaved
) == false);
621 PostMessage(SAVE_KEYSET_AS
);
622 // open the save requester...
625 BAlert
* alert
= new BAlert(ERROR
,
626 B_TRANSLATE("Shortcuts wasn't able to save your keyset."),
628 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
639 BMessage
message(SAVE_KEYSET
);
640 BMessenger
messenger(this);
641 fSavePanel
= new BFilePanel(B_SAVE_PANEL
, &messenger
, NULL
, 0,
648 case ADD_HOTKEY_ITEM
:
652 case REMOVE_HOTKEY_ITEM
:
654 BRow
* item
= fColumnListView
->CurrentSelection();
656 int index
= fColumnListView
->IndexOf(item
);
657 fColumnListView
->RemoveRow(item
);
659 _MarkKeySetModified();
661 // Rules for new selection: If there is an item at (index),
662 // select it. Otherwise, if there is an item at (index-1),
663 // select it. Otherwise, select nothing.
664 int num
= fColumnListView
->CountRows();
667 fColumnListView
->AddToSelection(
668 fColumnListView
->RowAt(index
));
673 fColumnListView
->AddToSelection(
674 fColumnListView
->RowAt(index
));
681 // Received when the user clicks on the ColumnListView
682 case HOTKEY_ITEM_SELECTED
:
684 if (fColumnListView
->CountRows() > 0)
685 fRemoveButton
->SetEnabled(true);
687 fRemoveButton
->SetEnabled(false);
691 // Received when an entry is to be modified in response to GUI activity
692 case HOTKEY_ITEM_MODIFIED
:
696 if ((message
->FindInt32("row", &row
) == B_OK
)
697 && (message
->FindInt32("column", &column
) == B_OK
)) {
702 ShortcutsSpec
* item
= (ShortcutsSpec
*)
703 fColumnListView
->RowAt(row
);
704 bool repaintNeeded
= false; // default
706 if (message
->HasInt32("mouseClick")) {
707 repaintNeeded
= item
->ProcessColumnMouseClick(column
);
708 } else if ((message
->FindString("bytes", &bytes
) == B_OK
)
709 && (message
->FindInt32("key", &key
) == B_OK
)) {
710 repaintNeeded
= item
->ProcessColumnKeyStroke(column
,
712 } else if (message
->FindInt32("unmappedkey", &key
) ==
714 repaintNeeded
= ((column
== item
->KEY_COLUMN_INDEX
)
715 && ((key
> 0xFF) || (GetKeyName(key
) != NULL
))
716 && (item
->ProcessColumnKeyStroke(column
, NULL
,
718 } else if (message
->FindString("text", &bytes
) == B_OK
) {
719 if ((bytes
[0] == '(')&&(bytes
[1] == 'C')) {
721 fSelectPanel
->Show();
723 BMessage
message(SELECT_APPLICATION
);
725 fSelectPanel
= new BFilePanel(B_OPEN_PANEL
, &m
,
726 NULL
, 0, false, &message
);
727 fSelectPanel
->Show();
729 fSelectPanel
->SetButtonLabel(B_DEFAULT_BUTTON
,
730 B_TRANSLATE("Select"));
732 repaintNeeded
= item
->ProcessColumnTextString(
737 fColumnListView
->Invalidate(row
);
738 _MarkKeySetModified();
746 BWindow::MessageReceived(message
);
753 ShortcutsWindow::_MarkKeySetModified()
755 if (fKeySetModified
== false) {
756 fKeySetModified
= true;
757 fSaveButton
->SetEnabled(true);
763 ShortcutsWindow::Quit()
770 ShortcutsWindow::DispatchMessage(BMessage
* message
, BHandler
* handler
)
772 switch (message
->what
) {
774 MessageReceived(message
);
779 if (be_clipboard
->Lock()) {
781 static_cast<ShortcutsSpec
*>(fColumnListView
->CurrentSelection());
783 BMessage
* data
= be_clipboard
->Data();
784 data
->RemoveName("text/plain");
785 data
->AddData("text/plain", B_MIME_TYPE
,
786 row
->GetCellText(ShortcutsSpec::STRING_COLUMN_INDEX
),
787 strlen(row
->GetCellText(ShortcutsSpec::STRING_COLUMN_INDEX
)));
788 be_clipboard
->Commit();
790 if (message
->what
== B_CUT
) {
791 row
->ProcessColumnTextString(
792 ShortcutsSpec::STRING_COLUMN_INDEX
, "");
793 _MarkKeySetModified();
796 be_clipboard
->Unlock();
801 if (be_clipboard
->Lock()) {
802 BMessage
* data
= be_clipboard
->Data();
805 if (data
->FindData("text/plain", B_MIME_TYPE
, (const void**)
806 &text
, &textLen
) == B_OK
) {
808 static_cast<ShortcutsSpec
*>(fColumnListView
->CurrentSelection());
810 for (ssize_t i
= 0; i
< textLen
; i
++) {
811 char buf
[2] = {text
[i
], 0x00};
812 row
->ProcessColumnKeyStroke(
813 ShortcutsSpec::STRING_COLUMN_INDEX
, buf
, 0);
816 _MarkKeySetModified();
818 be_clipboard
->Unlock();
823 ShortcutsSpec
* selected
;
824 if (message
->GetInt32("modifiers", 0) != 0)
825 BWindow::DispatchMessage(message
, handler
);
826 else if (handler
== fColumnListView
828 static_cast<ShortcutsSpec
*>(fColumnListView
->CurrentSelection()))) {
829 selected
->ProcessColumnTextString(
830 ShortcutsSpec::KEY_COLUMN_INDEX
,
831 GetKeyName(message
->GetInt32("key", 0)));
832 _MarkKeySetModified();
837 BWindow::DispatchMessage(message
, handler
);