Яндекс.Метрика

    Подсознание

    История Orfo Switcher

    Доброго времени суток, дорогие хаброжители!

    Как-то давным давно, в августе 2006-ого года, будучи студентом, я загорелся идеей написать программу, которая бы перенесла клавиши перемещения курсора (стрелки) на клавиатуре из привычного места прямо на алфавитную клавиатуру. Идея фикс была в том, чтобы навигация по редактору, в котором я программировал происходила без отрыва рук от привычного положения «ФЫВА-ОЛДЖ». Достаточно было зажать Caps-Lock и клавиши I,J,K,L превращались в клавиши управление курсором. Это было здорово! Пришлось разобраться с хуками Windows, с особенностью перехвата и подделкой сообщений от клавиатуры, и, несмотря на то, что идея с упрощенной навигацией не прижилась даже у меня самого (сложно было заставить себя использовать новые клавиши), я был рад проделанной работе, потому что у меня уже было все необходимое чтобы создать свой переключатель клавиатуры, который бы заменил бестолковый (как мне тогда казалось) Punto Switcher.
    Приблизительно в то же время, я познакомился c языком программирования D и полюбил его за возможность писать как на С++ и в то же время наслаждаться автоматической сборкой мусора, интерфейсами, замыканиями и прочими модным фичами. Это было круто! Я решил переписать перехватчик клавиатуры на D, дополнив его таким образом, чтобы он переключал раскладку клавиатуры, если я начинал набор, забыв переключить язык. Не просто переключал, а стирал уже набранную мной абракадабру и вставлял исправленный текст. Ну вы все знаете, как это делает Punto.

    И вот через некоторое время все было готово. У меня был файл, в котором через символ переноса строки были перечислены комбинации символов, встретив которые, программа автоматически переключала раскладку. Послушав Сергея Москалева (автор Punto) по радио, я решил что секрет успеха правильного переключения кроется в «невозможностях» языка, которые, как он говорил, скопились у него, пока он работал с «причесыванием» результата распознавания сканированных страниц текста. Ну все вы знаете эту историю.

    Я попытался разобраться со словарем невозможностей из дистрибутива Punto, но у меня ничего не вышло. Не удалось разгадать формат файла ps.dat, а собирать статистику невозможных сочетаний символов, обрабатывая объемы текста, мне показалось каким-то незаконченным методом, который всегда будет стремиться к совершенству, но никогда его не достигнет. И я решил пойти другим путем — включить абсолютно все слова языка в программу. Это казалось решением всех проблем! В тот момент я решил, что программа еще будет и проверять орфографию, коли в ней уже будут содержаться все слова в правильной форме.

    Скачав с какого-то сайта список всех русских слов со всеми возможными окончаниями и приставками, я обнаружил, что их гораздо больше чем я ожидал — около 800 000 слов! Файл русского языка весил около 15 мегабайт, а поиск в нем слова занимал десятки миллисекунд! Это никуда не годилось, ведь для того чтобы найти похожее слово, нужно проделать более сотни операций поиска и эти миллисекунды превратились бы в секунды, а никто не захочет ждать секунду, пока появится меню с правильными вариантом слова. Дело было близко к провалу.

    Чуть позже я обнаружил, что мне повезло, ведь большинство слов русского языка, является продолжением какого-то другого, уже существующего слова. Это было отличной новостью!

    Если расположить все слова в виде особого дерева, в котором корневыми узлами будут буквы алфавита, на которые могут начинаться слова, узлами второго уровня буквы, которые могут находиться на второй позиции в словах и так далее до самой последней буквы самого длинного слова, можно не только сократить размер файла словаря в несколько раз, но и создать идеальные условия для поиска, ведь каждый узел содержит размер всей ветки целиком, и если буква узла не соответствует искомому слову, мы можем перешагнуть всю ветку целиком, без необходимости перебора всего её содержимого. Так я и сделал. Получился отличный словарь! Сколь угодно много итераций поиска занимали 0 миллисекунд времени, и мои руки наконец были полностью развязаны. Размер русского словаря составил всего 5 мб, а английского 1.4 мб. В архиве же, оба словаря вместе с исполняемым файлом orfoswitcher.exe занимали всего 1.1 мегабайт. Отличный размер для такой программы. Я был очень доволен работой!

    Имея это, придумать алгоритм переключения раскладки оказалось очень просто. Достаточно было смотреть, существует ли набранная комбинация в одном словаре и не существует ли она в другом. Если это так и раскладка не соответствует найденному слову, то производится переключение. Это отлично работало, а все неправильные переключения решались путем добавления какого-то нового слова в словарь. Тут же выяснилось, например, что слово «ща», постоянно переключается на английское «of», и, несмотря на словарь из восьмисот тысяч слов, его пришлось дополнять вручную такими вот разными популярными словечками.

    Следующей любопытной задачей было создание меню, которое бы могло работать в любом приложении. В этом меню предположительно должны были появиться варианты правильных написаний слов, и возможно что-то еще. Интегрироваться в запущенные приложения с помощью хуков Windows я уже умел, но с меню возникали проблемы. Первые попытки были неудачными. Создание стандартного меню Windows из пространства активного приложения работало не всегда — некоторые приложения зависали и вели себя непредсказуемо, ведь у каждого приложения свой принцип работы, и не было никаких гарантий что меню корректно будет обработано и сообщения от него успешно попадут в петлю сообщений программы. Создание же меню из процесса orfoswitcher-a приводило к потере фокуса текущего приложения, что тоже было некрасиво. Ведь даже верни я фокус после отображения меню назад в активное приложение, нет гарантий, что приложение не проделает какую-то работу, на снятие или установку фокуса. Любое решение было либо нестабильным, либо работало не везде.

    В очередной раз мне повезло. Подсмотрев с помощью Spy++ как работает приложение Экранная клавиатура (osk.exe), я обнаружил, что создатели Windows предусмотрели особый стиль окна под названием WS_EX_NOACTIVATE, благодаря которому созданное окно никогда не становится активным, даже если на нем кликнуть мышью. Это было чудесно, ведь на базе этого окна я смог сделать меню, по которому можно было ходить как мышью так и клавиатурой, и при этом курсор ввода оставался в текущем приложении. Это меню идеально подходило для отображения правильных слов при проверке орфографии, но я понимал, что у него могут быть и другие полезные применения.

    Первое пришедшее на ум применение — это сохранять историю всего, что было скопировано и отображать отображать в виде пунктов меню. По одному пункту на каждый попавший в буфер обмена текстовый фрагмент. Так появилась в программе история буфера обмена. Оказалось удобно всегда иметь под рукой последние фрагменты текста, особенно когда нужно было скопировать откуда-то сначала логин, потом пароль, а потом вставить их в поля ввода. Можно было не беспокоиться, что буфер обмена будет затерт новым скопированным текстом, ведь в истории все сохранялось, даже после выключения компьютера. Друг мне сказал, что история буфера обмена — это единственная функция орфосвитчера, которая останавливает его перед тем, чтобы удалить программу. Я всегда ценил его откровенность.

    Потом в программе появились заметки, функция автозамены, всякого рода исключения для работы в приложениях и орфосвичер постепенно пришел к виду, в котором его можно видеть сейчас. Такая вот история. Надеюсь кому-то тоже пригодилась эта программа.

    Сайт программы: orfoswitcher.ru