오랜만에 또 <날개셋> 한글 입력기의 다음 버전 개발 근황을 올릴 때가 됐으니 관련 소식을 전하도록 하겠다.
이제 <날개셋> 한글 입력기는 7.x 후반이나 8.0에서 진짜로 고정판, 최종 완성판에 도달하는 걸 목표로 하고 있다. 고지가 얼마 안 남았다. 그 뒤로는 그냥 그때 그때 생각 난 기능이나 버그 수정 정도로만 유지 보수가 될 것이다. 그리고 신규 기능 개발보다는 이미 만들어 놓은 기능에 대한 홍보와 문서화, 포팅에 더 비중을 둘 것이다.
지난 7.4와 7.5는 한글 입력 엔진 쪽을 갈아엎느라 GUI 부분을 살펴볼 여유가 상대적으로 부족했다. 그래서 7.5를 공개하자마자 지체없이 다음과 같은 작업이 진행되었다.
1. 다국어 UI 지원 체계 개편
<날개셋> 한글 입력기가 허접하게나마 다국어 GUI를 지원한 건 2.32 버전부터였다. 그러나 영어 한 언어로 한정이었고 편집기 프로그램만 임시방편으로 지원하는 것이었다.
그러다가 2007년에 나온 4.55 버전부터 자체적인 다국어 UI 컬렉션 파일과 함께 임의의 언어를 지원하는 길이 열렸다. 물론 구조만 그렇게 만들어 놨지, 지금까지 실질적으로 제공된 외국어는 영어 하나뿐이긴 했지만 말이다.
하지만 그 구조는 완전하지 못했다. 고유 포맷을 사용하는 다국어 UI 컬렉션 파일은 자작한 툴을 이용해서 비교적 복잡한 과정을 거쳐야만 생성할 수 있어서 비효율적이었다. 그리고 그 파일에 모든 외국어 UI가 들어가는 건 아니었으며, 기존 Help, Dic 같은 데이터 디렉터리에 다국어 구분이 필요한 파일과 그렇지 않은 파일이 섞여 있었다.
프로그램 디렉터리 한 곳에다가 압축만 쭉 풀어 줌으로써 중국어나 일본어 같은 새로운 언어를 손쉽게 추가할 수 있게 하는 게 내 목표였는데.. 실질적으로는 그렇게 되지 못했다.
그래서 다 바꿨다.
일단 언어 식별을 kor, eng 같은 자체적인 명칭으로 하는 게 아니라, 1033 (영어 미국), 1042 (대한민국) 같은 운영체제가 사용하는 숫자를 그대로 따르도록 하고, 'lang/숫자' 아래에.. Help나 Dic 같은 디렉터리를 다시 둬서 언어 구분이 필요한 파일들이 들어가게 했다. 언어 구분을 파일 이름으로 하는 게 아니라 한 디렉터리 아래에서 한꺼번에 되게 한 것이다.
그리고 고유 포맷을 사용하는 파일을 버리고 각 모듈별로(ngs3, ngsedit 등) 역시나 전통적인 리소스 DLL을 사용하게 했다. 리소스 DLL은 비주얼 C++ 같은 툴에서나 손쉽게 고치고 생성할 수 있다.
이걸 뜯어고치는 과정에서 프로그램 내부의 여러 부분을 리팩터링하고 잠재적 버그들을 고쳤다. 특히 프로그램의 주 인스턴스 핸들과 리소스 DLL 핸들 사이의 구분이 더욱 엄밀하게 바뀌었다. 예전에는 별도의 파일을 썼으니 그 정도 구분이 필요하지 않았기 때문이다.
단적인 예로, 대화상자를 생성할 때 별 생각 없이 넘겨 주던 인스턴스 핸들은 리소스 DLL이 아니라 자기 프로그램의 인스턴스를 넘겨 줘야 한다. 안 그러면 자기 프로그램이 만든 내부 custom control (CS_GLOBALCLASS가 지정되지 않은 것)조차도 생성되지 않는 참사가 벌어진다.
언어 구분이 없는 리소스이기 때문에 FindResource만 쓰면 되는 부분과, FindResourceEx로 반드시 구분을 해야 하는 곳도 용례를 다시 살펴봤다. FindResource는 어찌 된 일인지 함수 인자가 모듈, 이름, 카테고리의 순인 반면, Ex 버전은 "모듈, 카테고리, 이름"으로 순서가 더 자연스럽게 바뀌기도 했다. LOAD_LIBRARY_AS_DATAFILE 옵션을 주고 불러온 DLL은 그저 훌륭한 데이터 셔틀일 뿐이긴 하다.
이걸 뜯어고치는 것은 결과적으로 <날개셋> 한글 입력기 소스를 더욱 질서정연하게 만든 나름 즐거운 작업이었다.
덤으로, 지금까지 제어판의 '외부 모듈 관리'에서 중국어 입력기들의 언어를 간체/번체를 구분 못 하던 버그도 잡았다. 3.0 이래로 sub-language가 지금까지 제대로 처리되고 있지 않은 듯했다. 한 작업 덕분에 여기저기서 관련 버그들이 일망타진된 것이다.
2. 작은 차이이지만..
날개셋문자를 입력받는 대화상자에서..
한글 자모를 구성하는 타입을 지정하면 아래의 그림과 같이 한글 자모를 입력받는 콤보 박스가 초중종 순으로 나란히 뜬다.
그런데, '한글 중종/초'나 '한글 종/초중' 타입을 지정했을 때는 그 콤보 박스도 초중종 순이 아니라 중종초나 종초중 순으로 뜨게 했다. 이들 날개셋문자는 세 성분을 그렇게 두 음절에 걸쳐서 문자 생성기로 전달하기 때문이다.
문득 생각이 떠올라서 구현해 봤는데 이렇게 하는 게 훨씬 더 직관적이고 좋다.
3. 단축글쇠 규칙
편집기 계층의 단축글쇠 규칙과, 기본 입력 스키마의 추가 글쇠 규칙 리스트에서..
아이템들을 선택한 후 드래그 드롭으로 순서를 조정할 수 있으며, 헤더를 클릭한 경우 정렬이 되게 했다.
리스트 컨트롤의 아이템들을 정렬하는 메시지는 LVM_SORTITEMS인데, 나중에 LVM_SORTITEMSEX도 추가되었다. 그 이유로는.. LVM_SORTITEMS는 정렬 비교용 콜백 함수에다가 LVITEM에 있던 lParam값만을 달랑 넘겨 줬기 때문이다.
그렇기 때문에 lParam만으로는 각 아이템이 원래 갖고 있던 문자열 같은 걸 참조할 수 없었으며, 이 때문에 lParam이 아니라 아예 아이템 인덱스 값을 넘겨주는 EX 버전이 윈도 98 즈음에 추가되었다. API 내력이 다소 안습하다.
단, qsort와는 달리 콜백 함수에 사용자가 지정한 user data도 같이 넘어오게 되어 있는 것은 바람직한 디자인이라 여겨진다. 이것은 EX뿐만 아니라 오리지널 버전도 처음부터 그랬다.
인덱스 번호를 받았다 하더라도 매번 2개의 LVITEM 구조체를 세팅하는 건 상당히 번거로우니, 정렬 비교를 위한 클래스를 따로 만들어서 LVITEM 구조체를 세팅해 놓고(mask, pszText, cchTextMax 따위), 비교 함수 호출 때는 인덱스 번호(iItem)만 세팅한 뒤에 곧바로 LVM_GETITEM를 호출하는 게 효율적일 것이다.
그리고, 트리 및 리스트 컨트롤에서 아이템의 드래그 드롭을 구현하는 것은 굉장히 노가다스러운 작업으로 Windows 프로그래밍 업계에서 악명이 높았다. 운영체제는 그저 아이템 드래그가 시작되었다는 이벤트만 날려 줄 뿐, 그 뒤부터 실질적인 드래그 드롭 처리는 전적으로 프로그래머가 알아서 해야 한다.
그 처리는 뭔가 패턴이 있는 것 같으면서도 상황별로 제각각 customize해야 하는 것도 미묘하게 있어서 더욱 까다로운데, 본인은 이미 드래그 드롭이 구현되어 있는(입력 항목의 이동 및 복사) '분야' 트리의 코드를 적극 재활용했다.
공통된 부분은 클래스로 만들고, 드래그 이미지를 생성하는 부분, 마우스 포인터로부터 hit test, 특정 아이템을 드래그 타겟으로 지정하는 부분처럼 customize가 필요한 부분만 가상 함수로 빼냈다. 그리고 트리 컨트롤의 HTREEITEM이든 리스트 컨트롤의 int 인덱스이든 구애받지 않는 추상적인 인덱스 자료구조를 설계했다.
드래그 함수는 드래그 중에 복사의 허용 여부 (0. 불능, 1. Ctrl 눌렀을 때 가능, 2. 읽기 전용 컨텐츠이기 때문에 무조건 복사)를 인자로 받아서 타겟 아이템과 복사 여부를 되돌린다.
이번 글은 기능 설명뿐만이 아니라 유난히 코딩 디테일 설명이 많은 듯한데, 아무튼 그런 과정을 거쳐 해당 기능이 깔끔하게 잘 구현됐다.
4. 입력 설정 테스트 대화상자
제어판의 시스템 메뉴에 딸려 있는 '입력 설정 테스트' 기능에다, 현재 사용 중인 입력 항목을 표시하고 굳이 단축글쇠 없이도 손쉽게 바꾸는 기능을 추가했다.
이 대화상자의 입력란은 <날개셋> 편집기 같은 다른 프로그램과는 별도의 컨텍스트에서 동작하기 때문에 내부적인 입력 상태를 알 방법이 없어서 불편했는데.. 이걸 추가해 주니 아주 편하다.
5. 수식 입력란에 풍선 도움말
그리고 이건 번개같이 아이디어가 떠올라서 집어넣었다. Bravo!
이 간단한 풍선 도움말을 왜 지금까지 넣을 생각을 안 했는지 모르겠다~!
암호 같은 각종 수식들에서 최소한 사용할 수 있는 변수들이 무엇이고 그게 의미하는 값이 뭔지는 간단히 바로 알 수 있게 했다.
그래도 연산자라든가 날개셋문자 notation (H3, C0, G_, BS 등등..)에 대해서는.. 지면이 부족해서 도저히 실을 수 없으니 추가적으로 도움말을 보고 공부를 해야겠지만..
이런 간단한 도움말이라도 있는 게, 없는 것보다는 백만 배 낫지 않으신지..?? ^^;;
풍선 도움말은 수식 입력란이 포커스를 받는 순간 나타나며, 한 세션당 총 3회만 나타난다. 매번 무조건 뜨는 것도 번거로울 수 있으니까.
글쇠배열처럼 날개셋문자를 받는 수식 입력란에는 근처에 날개셋문자를 만드는 대화상자를 꺼내는 버튼이 따로 있다. 글쇠배열뿐만 아니라 편집기 계층의 단축글쇠 규칙에도 글자판(입력 항목) 전환뿐만 아니라 날개셋문자를 보내는 기능이 있기 때문에 날개셋문자 생성 대화상자를 여는 기능이 사용자 편의 차원에서 마련돼 있다.
그런데, 단축글쇠 규칙을 통해서 날개셋문자 대화상자를 열고 나면.. '특수글쇠(특수 코드)' 용도로 갔을 때 특수글쇠가 bksp나 후보 변환 같은 아주 기본적인 것 몇 개밖에 있지가 않다.
이것은 특수글쇠가 원래는 편집기 계층이 아니라 입력기 계층 아래에 있는 문자 생성기의 관할에 있기 때문이다.
글쇠배열이야 입력 스키마 계층이고 자신에게 연결된 문자 생성기를 바탕으로 지원되는 특수글쇠를 얻어 오면 되지만, 편집기 계층에서는 이 단축글쇠가 무슨 문자 생성기와 연결될지 알 수 없기 때문에 아무 문자 생성기에나 공통적으로 적용되는 것만 가져오게 했기 때문이다.
이것이 불편한 점으로 인식되어 다음 버전에서는 개선이 이뤄졌다.
단축글쇠 규칙을 통해 날개셋문자 대화상자를 연 경우, 현재 '활성화돼 있는' 입력 항목을 기준으로 그 문자 생성기가 지원하는 특수글쇠들을 모두 가져온다.
따라서 빈 입력기나 영문 쿼티/드보락 같은 걸 사용하다가 제어판을 열면 예전처럼 기본적인 것밖에 있지 않을 것이고, 한글 입력을 기준으로 제어판을 열면 <날개셋> 기본 입력기가 지원하는 특수글쇠들을 모두 보면서 고를 수 있게 된다.
편집기 계층에다가 단축글쇠로 날개셋문자를 강제 입력할 정도라면 일반적인 평범한 문자보다는 조합 강제 종료 같은 특수글쇠일 가능성이 높은데 이런 조치를 통해 프로그램을 사용하기기 더 편리해질 것이다.
7. 제어판 편집기 계층 탭의 GUI 일부 개선
이것도 사소하다면 사소한 것이지만..
<날개셋> 한글 입력기는 1.0 시절부터 한글 조합 중에 Del/화살표 키가 입력됐을 때 cursor 이동을 어디를 기준으로 할지를 지정하는 옵션이 존재했다.
1.0부터 지금까지 그 옵션은 체크 형태로 어설프게 존재하였으나.. 이번 버전에서는 드디어 이렇게 콤보 박스로 바뀌었다.
아무리 이분법적인 간단한 옵션이라고 해도.. 남자 여자 성별을 고르는 UI를 체크 박스로 처리할 수는 없는 노릇 아닌가.
Posted by 사무엘