Initial commit to new repository
This commit is contained in:
264
.decompiledproj/AxCopilot/Core/SnippetExpander.cs
Normal file
264
.decompiledproj/AxCopilot/Core/SnippetExpander.cs
Normal file
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using AxCopilot.Models;
|
||||
using AxCopilot.Services;
|
||||
|
||||
namespace AxCopilot.Core;
|
||||
|
||||
public class SnippetExpander
|
||||
{
|
||||
private struct INPUT
|
||||
{
|
||||
public int type;
|
||||
|
||||
public InputUnion u;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct InputUnion
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public MOUSEINPUT mi;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public KEYBDINPUT ki;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public HARDWAREINPUT hi;
|
||||
}
|
||||
|
||||
private struct KEYBDINPUT
|
||||
{
|
||||
public ushort wVk;
|
||||
|
||||
public ushort wScan;
|
||||
|
||||
public uint dwFlags;
|
||||
|
||||
public uint time;
|
||||
|
||||
public nint dwExtraInfo;
|
||||
}
|
||||
|
||||
private struct MOUSEINPUT
|
||||
{
|
||||
public int dx;
|
||||
|
||||
public int dy;
|
||||
|
||||
public uint mouseData;
|
||||
|
||||
public uint dwFlags;
|
||||
|
||||
public uint time;
|
||||
|
||||
public nint dwExtraInfo;
|
||||
}
|
||||
|
||||
private struct HARDWAREINPUT
|
||||
{
|
||||
public uint uMsg;
|
||||
|
||||
public ushort wParamL;
|
||||
|
||||
public ushort wParamH;
|
||||
}
|
||||
|
||||
private readonly SettingsService _settings;
|
||||
|
||||
private readonly StringBuilder _buffer = new StringBuilder();
|
||||
|
||||
private bool _tracking;
|
||||
|
||||
private const ushort VK_BACK = 8;
|
||||
|
||||
private const int VK_ESCAPE = 27;
|
||||
|
||||
private const int VK_SPACE = 32;
|
||||
|
||||
private const int VK_RETURN = 13;
|
||||
|
||||
private const int VK_OEM_1 = 186;
|
||||
|
||||
private const int VK_SHIFT = 16;
|
||||
|
||||
private const int VK_CONTROL = 17;
|
||||
|
||||
private const int VK_MENU = 18;
|
||||
|
||||
private const ushort VK_CTRL_US = 17;
|
||||
|
||||
private static readonly HashSet<int> ClearKeys = new HashSet<int> { 33, 34, 35, 36, 37, 38, 39, 40, 46 };
|
||||
|
||||
public SnippetExpander(SettingsService settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public bool HandleKey(int vkCode)
|
||||
{
|
||||
if (!_settings.Settings.Launcher.SnippetAutoExpand)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((GetAsyncKeyState(17) & 0x8000) != 0)
|
||||
{
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
return false;
|
||||
}
|
||||
if ((GetAsyncKeyState(18) & 0x8000) != 0)
|
||||
{
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
return false;
|
||||
}
|
||||
if (vkCode == 186 && (GetAsyncKeyState(16) & 0x8000) == 0)
|
||||
{
|
||||
_tracking = true;
|
||||
_buffer.Clear();
|
||||
_buffer.Append(';');
|
||||
return false;
|
||||
}
|
||||
if (!_tracking)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((vkCode >= 65 && vkCode <= 90) || (vkCode >= 48 && vkCode <= 57) || (vkCode >= 96 && vkCode <= 105) || vkCode == 189)
|
||||
{
|
||||
bool shifted = (GetAsyncKeyState(16) & 0x8000) != 0;
|
||||
char c = VkToChar(vkCode, shifted);
|
||||
if (c != 0)
|
||||
{
|
||||
_buffer.Append(char.ToLowerInvariant(c));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
switch (vkCode)
|
||||
{
|
||||
case 8:
|
||||
if (_buffer.Length > 1)
|
||||
{
|
||||
_buffer.Remove(_buffer.Length - 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
if (vkCode != 13)
|
||||
{
|
||||
if (vkCode == 27 || ClearKeys.Contains(vkCode) || vkCode >= 112)
|
||||
{
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
goto case 32;
|
||||
case 32:
|
||||
if (_buffer.Length > 1)
|
||||
{
|
||||
string keyword = _buffer.ToString(1, _buffer.Length - 1);
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
SnippetEntry snippetEntry = _settings.Settings.Snippets.FirstOrDefault((SnippetEntry s) => s.Key.Equals(keyword, StringComparison.OrdinalIgnoreCase));
|
||||
if (snippetEntry != null)
|
||||
{
|
||||
string expanded = ExpandVariables(snippetEntry.Content);
|
||||
int deleteCount = keyword.Length + 1;
|
||||
((DispatcherObject)Application.Current).Dispatcher.BeginInvoke((Delegate)(Action)delegate
|
||||
{
|
||||
PasteExpansion(expanded, deleteCount);
|
||||
}, Array.Empty<object>());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_tracking = false;
|
||||
_buffer.Clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void PasteExpansion(string text, int deleteCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
INPUT[] array = new INPUT[deleteCount * 2];
|
||||
for (int i = 0; i < deleteCount; i++)
|
||||
{
|
||||
array[i * 2] = MakeKeyInput(8, keyUp: false);
|
||||
array[i * 2 + 1] = MakeKeyInput(8, keyUp: true);
|
||||
}
|
||||
SendInput((uint)array.Length, array, Marshal.SizeOf<INPUT>());
|
||||
Clipboard.SetText(text);
|
||||
INPUT[] array2 = new INPUT[4]
|
||||
{
|
||||
MakeKeyInput(17, keyUp: false),
|
||||
MakeKeyInput(86, keyUp: false),
|
||||
MakeKeyInput(86, keyUp: true),
|
||||
MakeKeyInput(17, keyUp: true)
|
||||
};
|
||||
SendInput((uint)array2.Length, array2, Marshal.SizeOf<INPUT>());
|
||||
LogService.Info($"스니펫 확장 완료: {deleteCount}자 삭제 후 붙여넣기");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Warn("스니펫 확장 실패: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static INPUT MakeKeyInput(ushort vk, bool keyUp)
|
||||
{
|
||||
INPUT result = new INPUT
|
||||
{
|
||||
type = 1
|
||||
};
|
||||
result.u.ki.wVk = vk;
|
||||
result.u.ki.dwFlags = (keyUp ? 2u : 0u);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string ExpandVariables(string content)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
return content.Replace("{date}", now.ToString("yyyy-MM-dd")).Replace("{time}", now.ToString("HH:mm:ss")).Replace("{datetime}", now.ToString("yyyy-MM-dd HH:mm:ss"))
|
||||
.Replace("{year}", now.Year.ToString())
|
||||
.Replace("{month}", now.Month.ToString("D2"))
|
||||
.Replace("{day}", now.Day.ToString("D2"));
|
||||
}
|
||||
|
||||
private static char VkToChar(int vk, bool shifted)
|
||||
{
|
||||
if (vk >= 65 && vk <= 90)
|
||||
{
|
||||
return shifted ? ((char)vk) : char.ToLowerInvariant((char)vk);
|
||||
}
|
||||
if (vk >= 48 && vk <= 57)
|
||||
{
|
||||
return shifted ? ")!@#$%^&*("[vk - 48] : ((char)vk);
|
||||
}
|
||||
if (vk >= 96 && vk <= 105)
|
||||
{
|
||||
return (char)(48 + (vk - 96));
|
||||
}
|
||||
if (vk == 189)
|
||||
{
|
||||
return shifted ? '_' : '-';
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern short GetAsyncKeyState(int vKey);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||||
}
|
||||
Reference in New Issue
Block a user