* Added support for selecting the dead key trigger characters from a menubar,
offering two choices for acute and diaeresis as well as allowing to switch off each dead key completely. * moved the textview on a line of its own such that the dead key menu and the modifier-switching button live together on one line * added enum dead_key_index and used it at a couple of places instead of having to use the magic numbers 1-5 * refactored the actual updating of the fChars buffer from SetKey() into _SetChars(), which is now being invoked by SetDeadKeyTrigger(), too git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30718 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -446,6 +446,78 @@ Keymap::SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers, bool enabled)
|
||||
}
|
||||
|
||||
|
||||
/*! Returns the trigger character string that is currently set for the dead
|
||||
key with the given index (which is 1..5).
|
||||
*/
|
||||
void
|
||||
Keymap::GetDeadKeyTrigger(dead_key_index deadKeyIndex, BString& outTrigger)
|
||||
{
|
||||
outTrigger = "";
|
||||
if (deadKeyIndex < 1 || deadKeyIndex > 5)
|
||||
return;
|
||||
|
||||
int32 deadOffsets[] = {
|
||||
fKeys.acute_dead_key[1],
|
||||
fKeys.grave_dead_key[1],
|
||||
fKeys.circumflex_dead_key[1],
|
||||
fKeys.dieresis_dead_key[1],
|
||||
fKeys.tilde_dead_key[1]
|
||||
};
|
||||
|
||||
int32 offset = deadOffsets[deadKeyIndex - 1];
|
||||
if (offset < 0 || offset >= (int32)fCharsSize)
|
||||
return;
|
||||
|
||||
uint32 deadNumBytes = fChars[offset];
|
||||
if (!deadNumBytes)
|
||||
return;
|
||||
|
||||
outTrigger.SetTo(&fChars[offset + 1], deadNumBytes);
|
||||
}
|
||||
|
||||
|
||||
/*! Sets the trigger character string that shall be used for the dead key
|
||||
with the given index (which is 1..5).
|
||||
*/
|
||||
void
|
||||
Keymap::SetDeadKeyTrigger(dead_key_index deadKeyIndex, const BString& trigger)
|
||||
{
|
||||
if (deadKeyIndex < 1 || deadKeyIndex > 5)
|
||||
return;
|
||||
|
||||
int32 deadOffsets[] = {
|
||||
fKeys.acute_dead_key[1],
|
||||
fKeys.grave_dead_key[1],
|
||||
fKeys.circumflex_dead_key[1],
|
||||
fKeys.dieresis_dead_key[1],
|
||||
fKeys.tilde_dead_key[1]
|
||||
};
|
||||
|
||||
int32 offset = deadOffsets[deadKeyIndex - 1];
|
||||
if (offset < 0 || offset >= (int32)fCharsSize)
|
||||
return;
|
||||
|
||||
if (_SetChars(offset, trigger.String(), trigger.Length())) {
|
||||
// reset modifier table such that new dead key is enabled wherever
|
||||
// it is available
|
||||
uint32* deadTables[] = {
|
||||
&fKeys.acute_tables,
|
||||
&fKeys.grave_tables,
|
||||
&fKeys.circumflex_tables,
|
||||
&fKeys.dieresis_tables,
|
||||
&fKeys.tilde_tables
|
||||
};
|
||||
*deadTables[deadKeyIndex - 1]
|
||||
= B_CONTROL_TABLE | B_OPTION_CAPS_SHIFT_TABLE | B_OPTION_CAPS_TABLE
|
||||
| B_OPTION_SHIFT_TABLE | B_OPTION_TABLE | B_CAPS_SHIFT_TABLE
|
||||
| B_CAPS_TABLE | B_SHIFT_TABLE | B_NORMAL_TABLE;
|
||||
|
||||
if (fModificationMessage != NULL)
|
||||
fTarget.SendMessage(fModificationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Get the char for a key given modifiers and active dead key
|
||||
void
|
||||
Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey,
|
||||
@@ -487,11 +559,21 @@ Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey,
|
||||
// here we take an potential active dead key
|
||||
int32 *deadKey;
|
||||
switch (activeDeadKey) {
|
||||
case 1: deadKey = fKeys.acute_dead_key; break;
|
||||
case 2: deadKey = fKeys.grave_dead_key; break;
|
||||
case 3: deadKey = fKeys.circumflex_dead_key; break;
|
||||
case 4: deadKey = fKeys.dieresis_dead_key; break;
|
||||
case 5: deadKey = fKeys.tilde_dead_key; break;
|
||||
case kDeadKeyAcute:
|
||||
deadKey = fKeys.acute_dead_key;
|
||||
break;
|
||||
case kDeadKeyGrave:
|
||||
deadKey = fKeys.grave_dead_key;
|
||||
break;
|
||||
case kDeadKeyCircumflex:
|
||||
deadKey = fKeys.circumflex_dead_key;
|
||||
break;
|
||||
case kDeadKeyDiaeresis:
|
||||
deadKey = fKeys.dieresis_dead_key;
|
||||
break;
|
||||
case kDeadKeyTilde:
|
||||
deadKey = fKeys.tilde_dead_key;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// if not dead, we copy and return the char
|
||||
@@ -556,54 +638,10 @@ Keymap::SetKey(uint32 keyCode, uint32 modifiers, int8 deadKey,
|
||||
if (numBytes > 6)
|
||||
return;
|
||||
|
||||
int32 oldNumBytes = fChars[offset];
|
||||
|
||||
if (oldNumBytes == numBytes
|
||||
&& !memcmp(&fChars[offset + 1], bytes, numBytes)) {
|
||||
// nothing to do
|
||||
return;
|
||||
if (_SetChars(offset, bytes, numBytes)) {
|
||||
if (fModificationMessage != NULL)
|
||||
fTarget.SendMessage(fModificationMessage);
|
||||
}
|
||||
|
||||
// TODO: handle dead keys!
|
||||
|
||||
int32 diff = numBytes - oldNumBytes;
|
||||
if (diff != 0) {
|
||||
fCharsSize += diff;
|
||||
|
||||
if (diff > 0) {
|
||||
// make space for the new data
|
||||
char* chars = new(std::nothrow) char[fCharsSize];
|
||||
if (chars != NULL) {
|
||||
memcpy(chars, fChars, offset + oldNumBytes + 1);
|
||||
memcpy(&chars[offset + 1 + numBytes],
|
||||
&fChars[offset + 1 + oldNumBytes],
|
||||
fCharsSize - 2 - offset - diff);
|
||||
delete[] fChars;
|
||||
fChars = chars;
|
||||
} else
|
||||
return;
|
||||
} else if (diff < 0) {
|
||||
// shrink table
|
||||
memmove(&fChars[offset + numBytes], &fChars[offset + oldNumBytes],
|
||||
fCharsSize - offset - 2 - diff);
|
||||
}
|
||||
|
||||
// update offsets
|
||||
|
||||
int32* data = fKeys.control_map;
|
||||
int32 size = sizeof(fKeys.control_map) / 4 * 9
|
||||
+ sizeof(fKeys.acute_dead_key) / 4 * 5;
|
||||
for (int32 i = 0; i < size; i++) {
|
||||
if (data[i] > offset)
|
||||
data[i] += diff;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&fChars[offset + 1], bytes, numBytes);
|
||||
fChars[offset] = numBytes;
|
||||
|
||||
if (fModificationMessage != NULL)
|
||||
fTarget.SendMessage(fModificationMessage);
|
||||
}
|
||||
|
||||
|
||||
@@ -693,6 +731,56 @@ Keymap::_Offset(uint32 keyCode, uint32 modifiers, uint32* _table)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Keymap::_SetChars(int32 offset, const char* bytes, int32 numBytes)
|
||||
{
|
||||
int32 oldNumBytes = fChars[offset];
|
||||
|
||||
if (oldNumBytes == numBytes
|
||||
&& !memcmp(&fChars[offset + 1], bytes, numBytes)) {
|
||||
// nothing to do
|
||||
return false;
|
||||
}
|
||||
|
||||
int32 diff = numBytes - oldNumBytes;
|
||||
if (diff != 0) {
|
||||
fCharsSize += diff;
|
||||
|
||||
if (diff > 0) {
|
||||
// make space for the new data
|
||||
char* chars = new(std::nothrow) char[fCharsSize];
|
||||
if (chars != NULL) {
|
||||
memcpy(chars, fChars, offset + oldNumBytes + 1);
|
||||
memcpy(&chars[offset + 1 + numBytes],
|
||||
&fChars[offset + 1 + oldNumBytes],
|
||||
fCharsSize - 2 - offset - diff);
|
||||
delete[] fChars;
|
||||
fChars = chars;
|
||||
} else
|
||||
return false;
|
||||
} else if (diff < 0) {
|
||||
// shrink table
|
||||
memmove(&fChars[offset + numBytes], &fChars[offset + oldNumBytes],
|
||||
fCharsSize - offset - 2 - diff);
|
||||
}
|
||||
|
||||
// update offsets
|
||||
int32* data = fKeys.control_map;
|
||||
int32 size = sizeof(fKeys.control_map) / 4 * 9
|
||||
+ sizeof(fKeys.acute_dead_key) / 4 * 5;
|
||||
for (int32 i = 0; i < size; i++) {
|
||||
if (data[i] > offset)
|
||||
data[i] += diff;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&fChars[offset + 1], bytes, numBytes);
|
||||
fChars[offset] = numBytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
Keymap::_GetDeadKeyIndex(int32 offset)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,16 @@
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Entry.h>
|
||||
#include <Messenger.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
enum dead_key_index {
|
||||
kDeadKeyAcute = 1,
|
||||
kDeadKeyGrave,
|
||||
kDeadKeyCircumflex,
|
||||
kDeadKeyDiaeresis,
|
||||
kDeadKeyTilde
|
||||
};
|
||||
|
||||
|
||||
class Keymap {
|
||||
@@ -39,6 +49,11 @@ public:
|
||||
uint8 activeDeadKey);
|
||||
void SetDeadKeyEnabled(uint32 keyCode, uint32 modifiers,
|
||||
bool enabled);
|
||||
void GetDeadKeyTrigger(dead_key_index deadKeyIndex,
|
||||
BString& outTrigger);
|
||||
void SetDeadKeyTrigger(dead_key_index deadKeyIndex,
|
||||
const BString& trigger);
|
||||
|
||||
void GetChars(uint32 keyCode, uint32 modifiers,
|
||||
uint8 activeDeadKey, char** chars,
|
||||
int32* numBytes);
|
||||
@@ -57,6 +72,8 @@ public:
|
||||
private:
|
||||
int32 _Offset(uint32 keyCode, uint32 modifiers,
|
||||
uint32* _table = NULL);
|
||||
bool _SetChars(int32 offset, const char* bytes,
|
||||
int32 numBytes);
|
||||
uint8 _GetDeadKeyIndex(int32 offset);
|
||||
|
||||
char* fChars;
|
||||
|
||||
@@ -51,6 +51,14 @@ static const uint32 kMsgUseKeymap = 'UkyM';
|
||||
static const uint32 kMsgRevertKeymap = 'Rvrt';
|
||||
static const uint32 kMsgKeymapUpdated = 'upkM';
|
||||
|
||||
static const uint32 kMsgDeadKeyAcuteChanged = 'dkAc';
|
||||
static const uint32 kMsgDeadKeyCircumflexChanged = 'dkCc';
|
||||
static const uint32 kMsgDeadKeyDiaeresisChanged = 'dkDc';
|
||||
static const uint32 kMsgDeadKeyGraveChanged = 'dkGc';
|
||||
static const uint32 kMsgDeadKeyTildeChanged = 'dkTc';
|
||||
|
||||
static const char* kDeadKeyTriggerNone = "<none>";
|
||||
|
||||
|
||||
KeymapWindow::KeymapWindow()
|
||||
: BWindow(BRect(80, 50, 880, 380), "Keymap", B_TITLED_WINDOW,
|
||||
@@ -80,8 +88,10 @@ KeymapWindow::KeymapWindow()
|
||||
.Add(fKeyboardLayoutView)
|
||||
//.Add(new BStringView("text label", "Sample and Clipboard:"))
|
||||
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
|
||||
.Add(fTextControl)
|
||||
.Add(_CreateDeadKeyMenu(), 0.0)
|
||||
.AddGlue()
|
||||
.Add(fSwitchShortcutsButton))
|
||||
.Add(fTextControl)
|
||||
.AddGlue(0.0)
|
||||
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
|
||||
.AddGlue(0.0)
|
||||
@@ -153,6 +163,7 @@ KeymapWindow::KeymapWindow()
|
||||
fAppliedMap = fCurrentMap;
|
||||
fCurrentMap.SetTarget(this, new BMessage(kMsgKeymapUpdated));
|
||||
|
||||
_UpdateDeadKeyMenu();
|
||||
_UpdateSwitchShortcutButton();
|
||||
|
||||
Unlock();
|
||||
@@ -307,6 +318,71 @@ KeymapWindow::MessageReceived(BMessage* message)
|
||||
fUserListView->Select(0L);
|
||||
break;
|
||||
|
||||
case kMsgDeadKeyAcuteChanged:
|
||||
{
|
||||
BMenuItem *item = fAcuteMenu->FindMarked();
|
||||
if (item != NULL) {
|
||||
const char* trigger = item->Label();
|
||||
if (strcmp(trigger, kDeadKeyTriggerNone) == 0)
|
||||
trigger = NULL;
|
||||
fCurrentMap.SetDeadKeyTrigger(kDeadKeyAcute, trigger);
|
||||
fKeyboardLayoutView->Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgDeadKeyCircumflexChanged:
|
||||
{
|
||||
BMenuItem *item = fCircumflexMenu->FindMarked();
|
||||
if (item != NULL) {
|
||||
const char* trigger = item->Label();
|
||||
if (strcmp(trigger, kDeadKeyTriggerNone) == 0)
|
||||
trigger = NULL;
|
||||
fCurrentMap.SetDeadKeyTrigger(kDeadKeyCircumflex, trigger);
|
||||
fKeyboardLayoutView->Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgDeadKeyDiaeresisChanged:
|
||||
{
|
||||
BMenuItem *item = fDiaeresisMenu->FindMarked();
|
||||
if (item != NULL) {
|
||||
const char* trigger = item->Label();
|
||||
if (strcmp(trigger, kDeadKeyTriggerNone) == 0)
|
||||
trigger = NULL;
|
||||
fCurrentMap.SetDeadKeyTrigger(kDeadKeyDiaeresis, trigger);
|
||||
fKeyboardLayoutView->Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgDeadKeyGraveChanged:
|
||||
{
|
||||
BMenuItem *item = fGraveMenu->FindMarked();
|
||||
if (item != NULL) {
|
||||
const char* trigger = item->Label();
|
||||
if (strcmp(trigger, kDeadKeyTriggerNone) == 0)
|
||||
trigger = NULL;
|
||||
fCurrentMap.SetDeadKeyTrigger(kDeadKeyGrave, trigger);
|
||||
fKeyboardLayoutView->Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgDeadKeyTildeChanged:
|
||||
{
|
||||
BMenuItem *item = fTildeMenu->FindMarked();
|
||||
if (item != NULL) {
|
||||
const char* trigger = item->Label();
|
||||
if (strcmp(trigger, kDeadKeyTriggerNone) == 0)
|
||||
trigger = NULL;
|
||||
fCurrentMap.SetDeadKeyTrigger(kDeadKeyTilde, trigger);
|
||||
fKeyboardLayoutView->Invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
@@ -372,6 +448,61 @@ KeymapWindow::_CreateMenu()
|
||||
}
|
||||
|
||||
|
||||
BMenuBar*
|
||||
KeymapWindow::_CreateDeadKeyMenu()
|
||||
{
|
||||
BMenuBar* menuBar = new BMenuBar("deadkeymenubar");
|
||||
fDeadKeyMenu = new BMenu("Select Dead Keys");
|
||||
menuBar->AddItem(fDeadKeyMenu);
|
||||
|
||||
fAcuteMenu = new BMenu("Acute Trigger");
|
||||
fAcuteMenu->SetRadioMode(true);
|
||||
fAcuteMenu->AddItem(new BMenuItem("\xC2\xB4",
|
||||
new BMessage(kMsgDeadKeyAcuteChanged)));
|
||||
fAcuteMenu->AddItem(new BMenuItem("'",
|
||||
new BMessage(kMsgDeadKeyAcuteChanged)));
|
||||
fAcuteMenu->AddItem(new BMenuItem(kDeadKeyTriggerNone,
|
||||
new BMessage(kMsgDeadKeyAcuteChanged)));
|
||||
fDeadKeyMenu->AddItem(fAcuteMenu);
|
||||
|
||||
fCircumflexMenu = new BMenu("Circumflex Trigger");
|
||||
fCircumflexMenu->SetRadioMode(true);
|
||||
fCircumflexMenu->AddItem(new BMenuItem("^",
|
||||
new BMessage(kMsgDeadKeyCircumflexChanged)));
|
||||
fCircumflexMenu->AddItem(new BMenuItem(kDeadKeyTriggerNone,
|
||||
new BMessage(kMsgDeadKeyCircumflexChanged)));
|
||||
fDeadKeyMenu->AddItem(fCircumflexMenu);
|
||||
|
||||
fDiaeresisMenu = new BMenu("Diaeresis Trigger");
|
||||
fDiaeresisMenu->SetRadioMode(true);
|
||||
fDiaeresisMenu->AddItem(new BMenuItem("\xC2\xA8",
|
||||
new BMessage(kMsgDeadKeyDiaeresisChanged)));
|
||||
fDiaeresisMenu->AddItem(new BMenuItem("\"",
|
||||
new BMessage(kMsgDeadKeyDiaeresisChanged)));
|
||||
fDiaeresisMenu->AddItem(new BMenuItem(kDeadKeyTriggerNone,
|
||||
new BMessage(kMsgDeadKeyDiaeresisChanged)));
|
||||
fDeadKeyMenu->AddItem(fDiaeresisMenu);
|
||||
|
||||
fGraveMenu = new BMenu("Grave Trigger");
|
||||
fGraveMenu->SetRadioMode(true);
|
||||
fGraveMenu->AddItem(new BMenuItem("`",
|
||||
new BMessage(kMsgDeadKeyGraveChanged)));
|
||||
fGraveMenu->AddItem(new BMenuItem(kDeadKeyTriggerNone,
|
||||
new BMessage(kMsgDeadKeyGraveChanged)));
|
||||
fDeadKeyMenu->AddItem(fGraveMenu);
|
||||
|
||||
fTildeMenu = new BMenu("Tilde Trigger");
|
||||
fTildeMenu->SetRadioMode(true);
|
||||
fTildeMenu->AddItem(new BMenuItem("~",
|
||||
new BMessage(kMsgDeadKeyTildeChanged)));
|
||||
fTildeMenu->AddItem(new BMenuItem(kDeadKeyTriggerNone,
|
||||
new BMessage(kMsgDeadKeyTildeChanged)));
|
||||
fDeadKeyMenu->AddItem(fTildeMenu);
|
||||
|
||||
return menuBar;
|
||||
}
|
||||
|
||||
|
||||
BView*
|
||||
KeymapWindow::_CreateMapLists()
|
||||
{
|
||||
@@ -457,12 +588,57 @@ KeymapWindow::_UpdateSwitchShortcutButton()
|
||||
}
|
||||
|
||||
|
||||
/*! Marks the menu items corresponding to the dead key state of the current
|
||||
key map.
|
||||
*/
|
||||
void
|
||||
KeymapWindow::_UpdateDeadKeyMenu()
|
||||
{
|
||||
BString trigger;
|
||||
fCurrentMap.GetDeadKeyTrigger(kDeadKeyAcute, trigger);
|
||||
if (!trigger.Length())
|
||||
trigger = kDeadKeyTriggerNone;
|
||||
BMenuItem* menuItem = fAcuteMenu->FindItem(trigger.String());
|
||||
if (menuItem)
|
||||
menuItem->SetMarked(true);
|
||||
|
||||
fCurrentMap.GetDeadKeyTrigger(kDeadKeyCircumflex, trigger);
|
||||
if (!trigger.Length())
|
||||
trigger = kDeadKeyTriggerNone;
|
||||
menuItem = fCircumflexMenu->FindItem(trigger.String());
|
||||
if (menuItem)
|
||||
menuItem->SetMarked(true);
|
||||
|
||||
fCurrentMap.GetDeadKeyTrigger(kDeadKeyDiaeresis, trigger);
|
||||
if (!trigger.Length())
|
||||
trigger = kDeadKeyTriggerNone;
|
||||
menuItem = fDiaeresisMenu->FindItem(trigger.String());
|
||||
if (menuItem)
|
||||
menuItem->SetMarked(true);
|
||||
|
||||
fCurrentMap.GetDeadKeyTrigger(kDeadKeyGrave, trigger);
|
||||
if (!trigger.Length())
|
||||
trigger = kDeadKeyTriggerNone;
|
||||
menuItem = fGraveMenu->FindItem(trigger.String());
|
||||
if (menuItem)
|
||||
menuItem->SetMarked(true);
|
||||
|
||||
fCurrentMap.GetDeadKeyTrigger(kDeadKeyTilde, trigger);
|
||||
if (!trigger.Length())
|
||||
trigger = kDeadKeyTriggerNone;
|
||||
menuItem = fTildeMenu->FindItem(trigger.String());
|
||||
if (menuItem)
|
||||
menuItem->SetMarked(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeymapWindow::_UpdateButtons()
|
||||
{
|
||||
fUseButton->SetEnabled(!fCurrentMap.Equals(fAppliedMap));
|
||||
fRevertButton->SetEnabled(!fCurrentMap.Equals(fPreviousMap));
|
||||
|
||||
_UpdateDeadKeyMenu();
|
||||
_UpdateSwitchShortcutButton();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ protected:
|
||||
void _UseKeymap();
|
||||
void _RevertKeymap();
|
||||
|
||||
BMenuBar* _CreateDeadKeyMenu();
|
||||
void _UpdateDeadKeyMenu();
|
||||
|
||||
void _FillSystemMaps();
|
||||
void _FillUserMaps();
|
||||
void _SetListViewSize(BListView* listView);
|
||||
@@ -64,6 +67,12 @@ protected:
|
||||
KeyboardLayoutView* fKeyboardLayoutView;
|
||||
BTextControl* fTextControl;
|
||||
BButton* fSwitchShortcutsButton;
|
||||
BMenu* fDeadKeyMenu;
|
||||
BMenu* fAcuteMenu;
|
||||
BMenu* fCircumflexMenu;
|
||||
BMenu* fDiaeresisMenu;
|
||||
BMenu* fGraveMenu;
|
||||
BMenu* fTildeMenu;
|
||||
|
||||
Keymap fCurrentMap;
|
||||
Keymap fPreviousMap;
|
||||
|
||||
Reference in New Issue
Block a user