diff --git a/.gitignore b/.gitignore
index fbdc4d0..f40418b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+.idea/
# User-specific files
*.suo
diff --git a/Bukva/Bukva/Bukva.csproj b/Bukva/Bukva/Bukva.csproj
index 381e987..5ac26d1 100644
--- a/Bukva/Bukva/Bukva.csproj
+++ b/Bukva/Bukva/Bukva.csproj
@@ -56,6 +56,12 @@
MSBuild:Compile
Designer
+
+
+
+
+ PackageManager.xaml
+
MSBuild:Compile
@@ -67,12 +73,15 @@
-
MainWindow.xaml
Code
+
+ Designer
+ MSBuild:Compile
+
@@ -100,5 +109,6 @@
+
\ No newline at end of file
diff --git a/Bukva/Bukva/KeyPressListener.cs b/Bukva/Bukva/KeyPressListener.cs
index b86381f..0cf61cc 100644
--- a/Bukva/Bukva/KeyPressListener.cs
+++ b/Bukva/Bukva/KeyPressListener.cs
@@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
@@ -15,7 +17,12 @@ abstract class KeyPressListener
protected void RaiseKeyPressedEvent(string keyPressed)
{
- OnKeyPressed(this, new KeyPressedEventArgs(keyPressed));
+ OnKeyPressed(this, new KeyPressedEventArgs(keyPressed, false));
+ }
+
+ protected void RaiseKeyPressedEvent(string keyPressed, bool scrollLockPressed)
+ {
+ OnKeyPressed(this, new KeyPressedEventArgs(keyPressed, scrollLockPressed));
}
public abstract void DeleteLastKeyPressed();
@@ -24,14 +31,17 @@ protected void RaiseKeyPressedEvent(string keyPressed)
class LowLevelKeyboardHook : KeyPressListener , IDisposable
{
-
private Win32.CallBackHandler callBackHandler;
private IntPtr hookID = IntPtr.Zero;
private bool trap;
+ private byte[] keyboardState;
+ private StringBuilder converterBuffer;
+
public LowLevelKeyboardHook()
{
+
callBackHandler = HookCallback;
trap = false;
HookKeyboard();
@@ -51,6 +61,19 @@ public void Dispose()
Win32.UnhookWindowsHookEx(hookID);
}
+ private string VirtualKeyToString(int virtualKeyCode)
+ {
+ keyboardState = new byte[256];
+ if (Control.ModifierKeys.HasFlag(Keys.Shift))
+ keyboardState[(int) Keys.ShiftKey] = 0xff;
+ //else
+ //keyboardState[(int) Keys.ShiftKey] = 0x0;
+
+ converterBuffer = new StringBuilder(256);
+ Win32.ToUnicode((uint)virtualKeyCode, 0, keyboardState, converterBuffer, 256, 0);
+ return converterBuffer.ToString();
+ }
+
private bool userKey = true;
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
@@ -62,26 +85,16 @@ private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
if (nCode >= 0 && (wParam == (IntPtr)Win32.WM_KEYDOWN || wParam == (IntPtr)Win32.WM_SYSKEYDOWN) && Listen)
{
int virtualKeyCode = Marshal.ReadInt32(lParam);
- Console.WriteLine(virtualKeyCode.ToString());
- Key pressedKey = KeyInterop.KeyFromVirtualKey(virtualKeyCode);
- string key;
-
- if (Control.ModifierKeys.HasFlag(Keys.Shift))
- {
- key = pressedKey.ToString().ToUpper();
- }
- else
- {
- key = pressedKey.ToString().ToLower();
- }
+ string key = VirtualKeyToString(virtualKeyCode);
+ Console.WriteLine(key);
if (key.ToUpper() == "OEMPERIOD")
{
key = ".";
}
- RaiseKeyPressedEvent(key);
+ RaiseKeyPressedEvent(key, virtualKeyCode == 145 ? true : false);
if(trap) {
trap = false;
@@ -98,6 +111,7 @@ private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
public override void DeleteLastKeyPressed()
{
trap = true;
+ //Backspace();
}
public override void EmitBackspace()
@@ -180,10 +194,12 @@ public override void EmitBackspace()
public class KeyPressedEventArgs : EventArgs
{
public string KeyPressed { get; private set; }
+ public bool ScrollLockPressed { get; private set; }
- public KeyPressedEventArgs(string key)
+ public KeyPressedEventArgs(string key, bool scrollLockPressed)
{
KeyPressed = key;
+ ScrollLockPressed = scrollLockPressed;
}
}
}
\ No newline at end of file
diff --git a/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs b/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs
new file mode 100644
index 0000000..3c96748
--- /dev/null
+++ b/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bukva
+{
+ interface IKeyTranslator
+ {
+ void Start();
+ void Stop();
+ void SetLetterTable(LetterTable newLetterTable);
+ }
+}
diff --git a/Bukva/Bukva/KeyTranslator.cs b/Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs
similarity index 91%
rename from Bukva/Bukva/KeyTranslator.cs
rename to Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs
index 2dbe604..6fd8353 100644
--- a/Bukva/Bukva/KeyTranslator.cs
+++ b/Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs
@@ -1,29 +1,33 @@
using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Bukva
{
- class KeyTranslator
+
+ class KeyStateKeyTranslator
{
FixedLengthQueue buffer;
LetterTable letterTable;
KeyPressListener keyPressListener;
- public KeyTranslator(LetterTable letterTable)
+ public KeyStateKeyTranslator(LetterTable letterTable)
{
buffer = new FixedLengthQueue(3);
buffer.Clear("");
this.letterTable = letterTable;
-
+
//keyPressListener = new KeyStateListener();
- keyPressListener = new LowLevelKeyboardHook();
+ keyPressListener = new KeyStateListener();
keyPressListener.Listen = false;
keyPressListener.OnKeyPressed += OnKeyPressed;
}
+ public void SetLetterTable(LetterTable newLetterTable)
+ {
+ letterTable = newLetterTable;
+ }
+
public void Start()
{
keyPressListener.Listen = true;
@@ -42,7 +46,9 @@ private void OnKeyPressed(object sender, KeyPressedEventArgs e)
if (Control.ModifierKeys.HasFlag(Keys.Control) || key == "none")
return;
- if (key == "back")
+ Console.WriteLine(key);
+
+ if (key == "\b" || key == "back")
{
HandleUndo();
}
diff --git a/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs b/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs
new file mode 100644
index 0000000..ebbd02e
--- /dev/null
+++ b/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Windows.Forms;
+
+namespace Bukva
+{
+ class LowLevelKeyTranslator : IKeyTranslator
+ {
+ FixedLengthQueue buffer;
+ LetterTable letterTable;
+
+ KeyPressListener keyPressListener;
+
+ public LowLevelKeyTranslator(LetterTable letterTable)
+ {
+ buffer = new FixedLengthQueue(3);
+ buffer.Clear("");
+ this.letterTable = letterTable;
+
+ //keyPressListener = new KeyStateListener();
+ keyPressListener = new LowLevelKeyboardHook();
+ keyPressListener.Listen = false;
+ keyPressListener.OnKeyPressed += OnKeyPressed;
+ }
+
+ public void SetLetterTable(LetterTable newLetterTable)
+ {
+ letterTable = newLetterTable;
+ }
+
+ public void Start()
+ {
+ keyPressListener.Listen = true;
+ }
+
+ public void Stop()
+ {
+ keyPressListener.Listen = false;
+ buffer.Clear(""); //What if OnKeyPressed is being executed at this time?
+ }
+
+ private void OnKeyPressed(object sender, KeyPressedEventArgs e)
+ {
+ string key = e.KeyPressed;
+
+
+ if (Control.ModifierKeys.HasFlag(Keys.Control) || key == "none" || key == "")
+ return;
+
+ Console.WriteLine(key);
+
+ if (key == "\b" || key == "back")
+ {
+ HandleUndo();
+ }
+ else
+ {
+ HandleKeyPress(key);
+ }
+
+ buffer.Insert(key);
+ }
+
+ private void HandleKeyPress(string key)
+ {
+ if (letterTable.ContainsKey(buffer.At(1) + buffer.At(2) + key))
+ {
+ if (letterTable.ContainsKey(buffer.At(2)) || letterTable.ContainsKey(buffer.At(1) + buffer.At(2)))
+ {
+ keyPressListener.EmitBackspace(); //Replace previous translation with new one, if it existed
+ }
+
+ if (!letterTable.ContainsKey(buffer.At(1) + buffer.At(2)))
+ keyPressListener.EmitBackspace();
+
+ keyPressListener.DeleteLastKeyPressed();
+
+ SendKeys.SendWait(letterTable[buffer.At(1) + buffer.At(2) + key]);
+ }
+ else if (letterTable.ContainsKey(buffer.At(2) + key))
+ {
+ keyPressListener.DeleteLastKeyPressed();
+
+ if (letterTable.ContainsKey(buffer.At(2)))
+ keyPressListener.EmitBackspace(); //Replace previous translation with new one, if it existed
+
+
+ SendKeys.SendWait(letterTable[buffer.At(2) + key]);
+ }
+ else if (letterTable.ContainsKey(key))
+ {
+ keyPressListener.DeleteLastKeyPressed();
+
+ SendKeys.SendWait(letterTable[key]);
+ }
+ }
+
+ private void HandleUndo()
+ {
+ keyPressListener.EmitBackspace();
+ keyPressListener.DeleteLastKeyPressed();
+
+ if (letterTable.ContainsKey(buffer.At(0) + buffer.At(1) + buffer.At(2)))
+ {
+ if (letterTable.ContainsKey(buffer.At(0) + buffer.At(1)))
+ {
+ SendKeys.SendWait(letterTable[buffer.At(0) + buffer.At(1)]);
+
+ if (letterTable.ContainsKey(buffer.At(2)))
+ SendKeys.SendWait(letterTable[buffer.At(2)]);
+ else
+ SendKeys.SendWait(buffer.At(2));
+ }
+ else
+ {
+ if (letterTable.ContainsKey(buffer.At(0)))
+ SendKeys.SendWait(letterTable[buffer.At(0)]);
+ else
+ SendKeys.SendWait(buffer.At(0));
+
+
+ if (letterTable.ContainsKey(buffer.At(1)))
+ SendKeys.SendWait(letterTable[buffer.At(1)]);
+ else
+ SendKeys.SendWait(buffer.At(1));
+
+
+ if (letterTable.ContainsKey(buffer.At(2)))
+ SendKeys.SendWait(letterTable[buffer.At(2)]);
+ else
+ SendKeys.SendWait(buffer.At(2));
+ }
+ }
+ else if (letterTable.ContainsKey(buffer.At(1) + buffer.At(2)))
+ {
+ SendKeys.SendWait(letterTable[buffer.At(1)]);
+ SendKeys.SendWait(letterTable[buffer.At(2)]);
+ }
+ }
+ }
+}
diff --git a/Bukva/Bukva/LetterTable.cs b/Bukva/Bukva/LetterTable.cs
index b115460..f44db73 100644
--- a/Bukva/Bukva/LetterTable.cs
+++ b/Bukva/Bukva/LetterTable.cs
@@ -8,11 +8,17 @@ class LetterTable : Dictionary
{
public string Filename { get; private set; }
+
+ //Empty Letter table
public LetterTable() : base()
{
- List list = GetCandidateFiles();
- Filename = list[0].Split('\\').Last();
- ReadInFromFile(list[0]);
+
+ }
+
+ public LetterTable(string filename) : base()
+ {
+ Filename = filename.Split('\\').Last();
+ ReadInFromFile(filename);
}
public void ReadInFromFile(string filename)
@@ -34,7 +40,7 @@ public void ReadInFromFile(string filename)
}
}
- List GetCandidateFiles()
+ public static List GetCandidateFiles()
{
List languageFiles = new List();
string[] files = Directory.GetFiles(".");
diff --git a/Bukva/Bukva/MainWindow.xaml b/Bukva/Bukva/MainWindow.xaml
index 839b3fc..d45090e 100644
--- a/Bukva/Bukva/MainWindow.xaml
+++ b/Bukva/Bukva/MainWindow.xaml
@@ -5,10 +5,13 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Bukva"
mc:Ignorable="d"
- Title="Bukva" Height="127.768" Width="244.905" ResizeMode="CanMinimize">
+ Title="Bukva" Height="150" Width="310" ResizeMode="CanMinimize">
-
+
-
+
+
+
+
diff --git a/Bukva/Bukva/MainWindow.xaml.cs b/Bukva/Bukva/MainWindow.xaml.cs
index b2faa98..4a7345b 100644
--- a/Bukva/Bukva/MainWindow.xaml.cs
+++ b/Bukva/Bukva/MainWindow.xaml.cs
@@ -5,6 +5,9 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Forms;
+using System.Threading.Tasks;
+using System.Net;
+using System.IO;
namespace Bukva
{
@@ -13,38 +16,133 @@ namespace Bukva
///
public partial class MainWindow : Window
{
- KeyTranslator keyTranslator;
- LetterTable letterTable;
+ IKeyTranslator keyTranslator;
bool Enabled;
+ LowLevelKeyboardHook scrollLockListener;
+
+
+ List translationTables;
+ int index;
+
+ PackageManager packageManager;
public MainWindow()
{
+
+
+ translationTables = new List();
+ index = 0;
+
InitializeComponent();
Enabled = false;
+ keyTranslator = new LowLevelKeyTranslator(new LetterTable());
+
+ LoadFiles();
+ UpdateLetterTableToCurrentIndex();
+
+ scrollLockListener = new LowLevelKeyboardHook();
+ scrollLockListener.Listen = true;
+ scrollLockListener.OnKeyPressed += OnKeyPressed;
- letterTable = new LetterTable();
- keyTranslator = new KeyTranslator(letterTable);
- StatusLabel.Content = "Language: \n" + letterTable.Filename;
-
}
+ private void LoadFiles()
+ {
+ translationTables = new List();
+
+ List foundFiles = LetterTable.GetCandidateFiles();
+
+ foreach (string filename in foundFiles)
+ {
+ translationTables.Add(new LetterTable(filename));
+ }
+
+
+ index = index % translationTables.Count;
+ }
+
+ private void UpdateLetterTableToCurrentIndex()
+ {
+ LanguageLabel.Content = translationTables[index].Filename;
+ keyTranslator.SetLetterTable(translationTables[index]);
+ }
+
+
private void ToggleButtonClick(object sender, RoutedEventArgs e)
+ {
+ Toggle();
+ }
+
+
+
+ private void Toggle()
{
if (!Enabled)
{
- keyTranslator.Start();
- ToggleButton.Background = Brushes.DeepSkyBlue;
- ToggleButton.Content = "On";
- Enabled = true;
+ Enable();
}
else
{
- keyTranslator.Stop();
- ToggleButton.Background = Brushes.SteelBlue;
- ToggleButton.Content = "Off";
- Enabled = false;
+ Disable();
}
+
+ }
+
+ private void Enable()
+ {
+ keyTranslator.Start();
+ ToggleButton.Background = Brushes.DeepSkyBlue;
+ ToggleButton.Content = "On";
+ Enabled = true;
+ }
+
+ private void Disable()
+ {
+ keyTranslator.Stop();
+ ToggleButton.Background = Brushes.SteelBlue;
+ ToggleButton.Content = "Off";
+ Enabled = false;
+ }
+
+ private void OnKeyPressed(object sender, KeyPressedEventArgs e)
+ {
+ if (e.ScrollLockPressed)
+ Toggle();
+ }
+
+
+
+ private void MoveRightClick(object sender, RoutedEventArgs e)
+ {
+ index = (index + 1) % translationTables.Count;
+
+ UpdateLetterTableToCurrentIndex();
+ }
+
+ private void MoveLeftClick(object sender, RoutedEventArgs e)
+ {
+ index = index - 1;
+
+ if (index == -1)
+ {
+ index = translationTables.Count - 1;
+ }
+
+ UpdateLetterTableToCurrentIndex();
+ }
+
+ private void PackageManagerClosed(object sender, System.EventArgs e)
+ {
+ LoadFiles();
+ UpdateLetterTableToCurrentIndex();
+ }
+
+ private void ManageLanguagesClicked(object sender, RoutedEventArgs e)
+ {
+ PackageManager pm = new PackageManager();
+ pm.Show();
+ pm.Closed += PackageManagerClosed;
}
}
}
diff --git a/Bukva/Bukva/PackageManager.xaml b/Bukva/Bukva/PackageManager.xaml
new file mode 100644
index 0000000..dfe0837
--- /dev/null
+++ b/Bukva/Bukva/PackageManager.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Bukva/Bukva/PackageManager.xaml.cs b/Bukva/Bukva/PackageManager.xaml.cs
new file mode 100644
index 0000000..b61029e
--- /dev/null
+++ b/Bukva/Bukva/PackageManager.xaml.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using System.Net;
+using System.IO;
+
+namespace Bukva
+{
+ ///
+ /// Interaction logic for PackageManager.xaml
+ ///
+ public partial class PackageManager : Window
+ {
+ private List Online;
+ private List Local;
+
+ public PackageManager()
+ {
+ InitializeComponent();
+
+ RefreshOnline();
+ RefreshLocal();
+ }
+
+ void RefreshOnline()
+ {
+ Online = GetManifest();
+ OnlineFiles.ItemsSource = Online;
+ }
+
+ void RefreshLocal()
+ {
+ Local = LetterTable.GetCandidateFiles();
+ LocalFiles.ItemsSource = Local;
+ }
+
+ List GetManifest()
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://raw.githubusercontent.com/vzyrianov/Bukva/master/Languages/manifest.txt");
+
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ using (Stream stream = response.GetResponseStream())
+ using (StreamReader streamReader = new StreamReader(stream))
+ {
+ string result = streamReader.ReadToEnd();
+
+ var resultingList = new List(result.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None));
+ resultingList.RemoveAt(resultingList.Count - 1);
+ return resultingList;
+ }
+ }
+
+ void DownloadFile(string filename)
+ {
+ string fileContent;
+
+
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"https://raw.githubusercontent.com/vzyrianov/Bukva/master/Languages/{filename}.buk");
+
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+ using (Stream stream = response.GetResponseStream())
+ using (StreamReader streamReader = new StreamReader(stream))
+ {
+ fileContent = streamReader.ReadToEnd();
+ }
+
+ System.IO.File.WriteAllText($@".\{filename}.buk", fileContent);
+ }
+
+ void DownloadButtonClick(object sender, RoutedEventArgs e)
+ {
+ var selectedItem = (string)OnlineFiles.SelectedItem;
+
+ if (selectedItem != null)
+ {
+ DownloadFile(selectedItem);
+ }
+
+ RefreshLocal();
+ }
+
+ string GetCurrentPath()
+ {
+ return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
+ }
+
+ void OpenDirectorButton(object sender, RoutedEventArgs e)
+ {
+ System.Diagnostics.Process.Start("explorer.exe", GetCurrentPath());
+ }
+
+ void DeleteButton(object sender, RoutedEventArgs e)
+ {
+ string filename = (string)LocalFiles.SelectedItem;
+
+
+ if (filename != null)
+ {
+ System.IO.File.Delete($@"{filename}");
+ }
+ RefreshLocal();
+ }
+ }
+}
diff --git a/Bukva/Bukva/Win32.cs b/Bukva/Bukva/Win32.cs
index 3b9ab0d..c6a0dbc 100644
--- a/Bukva/Bukva/Win32.cs
+++ b/Bukva/Bukva/Win32.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using System.Text;
namespace Bukva
{
@@ -25,5 +26,10 @@ public class Win32
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
public delegate IntPtr CallBackHandler(int nCode, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ public static extern int ToUnicode(uint virtualKeyCode, uint scanCode, byte[] keyboardState,
+ [Out, MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)] StringBuilder receivingBuffer,
+ int bufferSize, uint flags);
}
}
diff --git a/Languages/ru2en.buk b/Languages/ru2en.buk
new file mode 100644
index 0000000..bdaa6aa
--- /dev/null
+++ b/Languages/ru2en.buk
@@ -0,0 +1,65 @@
+б,b
+а,a
+ц,c
+д,d
+е,e
+ф,f
+г,g
+х,h
+и,i
+й,j
+к,k
+л,l
+м,m
+н,n
+о,o
+п,p
+р,r
+с,s
+т,t
+у,u
+в,v
+щ,w
+ы,y
+з,z
+ya,YA
+э,e
+ё,yo
+zh,ж
+ch,ч
+sh,ш
+yu,ю
+ju,ю
+ye,э
+
+А,A
+Б,B
+Ц,C
+Д,D
+Е,E
+Ф,F
+Г,G
+Х,H
+И,I
+Й,J
+К,K
+Л,L
+М,M
+Н,N
+О,O
+П,P
+Я,YA
+Р,R
+С,S
+Т,T
+У,U
+В,V
+Щ,W
+Ы,Y
+З,Z
+Э,EH
+Ё,YO
+Ж,ZH
+Ч,CH
+Ш,SH
+Ю,YU
\ No newline at end of file