<날개셋> 한글 입력기

- 한글의 경쟁력을 200% 높여 주는 문자 도구-

버전 1.2 (2001년 9월)

제작□ 글: 김 용묵 (sebulsik@dreamwiz.com)

※ 이 설명서는 제 17회 한국 정보 올림피아드 고등부 공모부문에 출품했던 작품인 <날개셋> 한글 입력기의 설명서를 기반으로 하여, 대회가 끝나고 본 프로그램이 1.2로 버전업하면서 바뀐 사항을 새로 반영한 것입니다. 따라서 이 문서에는 2000년 7월에 작성한 글과, 2001년 9월에 작성한 글이 섞여 였습니다.

개정판을 내면서

안녕하십니까?

제 17회 한국 정보 올림피아드가 끝난지도, <날개셋> 한글 입력기 1.0이 완성된 지도 1년이 지났습니다. 그동안 <날개셋> 한글 입력기는 세벌식 사랑 모임과 제 홈페이지를 통해 뜻있는 사람들에게 제법 알려지고, 여러 차례 판올림하면서 많은 사람들에게 세벌식의 가능성을 보여주었습니다. 하지만 제가 만든 프로그램들이 그렇듯이 프로그램의 사용법이 잘 문서화되지 않았다는 점이 그동안 아쉬움으로 남아 있었습니다.

사실 <날개셋> 한글 입력기는 제가 만들었던 어떤 프로그램보다도 문서화가 잘된 프로젝트였습니다. 도움말은 없지만, 명색이 정보 올림피아드 출품작이다 보니 제 프로그램을 심사 위원들에게 잘 알릴 수 있는 문서가 있어야 했습니다. 그래서 제 프로그램의 개념과 사용법을 설명해 놓은 46쪽에 달하는 설명서를 만들었지요. 하지만 일반 사용자보다는 올림피아드 심사 위원을 고려해서 만들어진 설명서는 제 프로그램을 효과적으로 소개하는 데 한계가 있었고, 1년 동안 생긴 변화들을 새롭게 반영할 수 있는 설명서가 절실히 필요해졌습니다.

이번에 개정한 설명서는 이런 요구사항을 잘 만족해 줄 것입니다. 공모전 설명서의 뼈대와 편집 구성은 그대로 유지하면서 바뀌어야 할 내용, 추가해야 할 내용을 모두 반영했습니다. 그동안 설명이 부족했던 특수 키에 대한 내용도 절을 하나 추가하여 충분히 실었고, 뭐라 정의내리기 힘든 제 프로그램이 어떤 목적으로 무엇을 해낸 것인지를 요약문에 완전히 소개하고자 노력했습니다. 원래 설명서를 웹 문서와 HTML 도움말로도 제공하려고 했지만, 설명서 자체가 분량이 많고, 완성형 코드에 없는 한글이 쓰인 곳도 많아서 아직까지는 □글 문서로 제공하기로 했습니다.

본 문서는 공모전 설명서를 바탕으로 만들어져 있는 만큼, 여전히 프로그래머를 위한 내용이 많이 들어있습니다. 프로그램을 쓰기만 하려는 분이라면 <날개셋> 프로그래밍과 관련된 내용이나, 액티브X 컨트롤의 프로퍼티□ 메소드 같은 건 읽지 않아도 될 것입니다. 단지 제 입력기가 제공하는 기능과 그 동작 원리에 대해서 잘 이해해 보셨으면 합니다.

언젠가는 해야 할 일이었는데 이렇게 해내어 참 기쁩니다. 이제 <날개셋> 입력기의 기능에 대한 궁금증이 이 문서로 모두 풀렸으면 좋겠습니다. 이 프로그램이 의도하고 있는 이상과 개념이 이 글을 읽는 분들에게 잘 전달될 수 있었으면 합니다. 이 프로그램이 세벌식을 처음 익히는 분에게는 자판을 바꾸는 좋은 동기가 되고, 한글을 연구하는 분들에게는 색다른 영감을 줄 수 있다면 개발자에겐 무한한 영광일 것입니다.

그동안 제 프로그램에 관심을 보여 준 세사모 회원들에게 고맙다는 말씀 드립니다.

세벌식을 표준으로! 한글날을 국경일로!

2001년 9월 17일

개발자 올림

홈페이지: http://user.chollian.net/~pjykym/

전자우편: sebulsik@dreamwiz.com

차 례

I. 요약문	1

1. 이 프로젝트는３1	3. 특징３4

2. 구현 형태３3	4. 기대되는 효과３4

II. 프로젝트 소개	5

1. 개발 동기３5	4. 프로젝트 구성３7

2. 개발 과정３5	5. 세벌식 자판 소개３7

3. 기능 설계 기준３6

III. 입력기 구조	9

1. 한글 입력에 필요한 것３9	5. 윗글쇠３15

2. 지우기３10	6. 커서 이동３15

3. 한글 입력３12	7. 편집 기능３16

4. 고치기３14	8. 세벌식 자판 전용 설정３18

IV. <날개셋> 프로그래밍	19

1. 소개３19	6. CHanInput３22

2. CHanLetter３19	7. CHanEditor３23

3. CUniHanLet, CKsHanLet３20	8. CHanLib３24

4. CHanString３21	9. 환경설정 API３25

5. CHanKeybrd３21

V. ActivHan.ocx	26

1. 소개３26	4. 메소드와 이벤트３29

2. 사용법３27	5. 사용례３30

3. 프로퍼티３27

VI. MyEdit.exe	33

1. 소개/사용법３33	3. 입력과 관련된 부가기능３37

2. 입력기 설정３34	4. 특수 키 설명３38

VII. 결론	40

1. 기대되는 효과３40	3. 맺음말３43

2. 제안３42

VIII. 부록	44

1. 세벌식 최종 자판 배열３44	3. 참고 자료３55

2. 클래스 라이브러리 헤더３45

요약문

이 프로젝트는

세계에서 가장 우수하고 과학적이며 독창적인 문자가 한글이라는데, 한글을 입력하는 게 영어를 치거나 한글 음소를 풀어쓰는 것보다 훨씬 불편하다고 느낀 적은 없습니까? 한글이 영타에 비해 장문 타속과 단문 타속의 차이가 큰 이유가 무엇 때문이라고 생각하십니까? 컴퓨터에서 한글은 치다가 오타가 나면 글자 전체를 지우고 맞는 음소까지 처음부터 다시 입력해야 할 때가 많습니다. 그것을 어쩔 수 없는 한글 탓으로 돌리고 컴퓨터 생활을 해 오지는 않았는지요? 이것은 일단 조합만 끝나면 한글을 한자처럼 그림 문자 취급하는 입력기 탓이지 절대 한글 탓이 아닙니다. 로마자의 관점이 아닌 세벌 모아쓰기 문자 한글의 관점에서 입력기를 만들면 상황은 이렇게 달라집니다.

정타: 한ㄱ

오타: 하ㄱ (글쇠 빠뜨림)

기존 입력기: 하 → → ㅎ → 하 → 한 → 한ㄱ (6타)

<날개셋> 입력기: 하 → 한 → 한ㄱ (3타)

해설:  현재 글자를 다 지우면 커서를 자동으로 앞 글자를 조합하던 상태로 가게 할 수 있습니다.

정타: 꽥

오타: |꽉 (이미 입력된 오자를 수정)

기존 입력기: ㄱ → ㄲ → 꼬 → 꽤 → 꽥 (5타)

<날개셋> 입력기: 꼭 → 꽥 (2타)

해설:  음소 수정 기능을 쓰면 틀린 음소만 고칠 수 있습니다. □가을□을 □겨울□로 고치는 데도 두 타면 충분합니다. 물론 기존의 음절 전체 지우기 기능도 쓸 수 있습니다.

정타: 산

오타: 샌 (틀린 음소를 입력하고 한 타를 더 누름)

기존 입력기: 새 → ㅅ → 사 → 산 (4타)

<날개셋> 입력기: 산 (1타)

해설:  무한 음소 수정 기능을 사용하면 조합 중인 글자의 음소를 마음대로 고칠 수 있습니다.

정타: 한

오타: 하□ (글쇠를 더 눌러 글자 형태가 깨짐)

기존 입력기: 하ㅐ → 하 →  → ㅎ → 하 → 한 (6타)

<날개셋> 입력기: 한 (1타)

해설:  무한 음소 수정 기능과 초성만 다음 글자 음소로 인정하게 하는 옵션을 사용하면 중성, 종성 글쇠를 눌러서는 다음 글자로 넘어가지 않습니다. 그래서 □핸□을 □한□으로만 고치면 됩니다.

정타: 한

오타: ㅏ□ (키 누르는 순서가 바뀜)

기존 입력기: ㅏㅎ → ㅏ →  → ㅎ → 하 → 한 (6타)

<날개셋> 입력기: (0타)

해설: 모아치기 기능을 쓰면 이런 오타는 생기지 않습니다.

정타: 없애

오타: 억애 (앞 글자에서 오타를 내고 또 글자를 만듦)

기존 입력기: 억ㅇ → 억 →  → ㅇ → 어 → 없 → 없ㅇ → 없애 (8타)

<날개셋> 입력기: 억애 → 없애 → 없애 (3타)

해설:  앞 글자와 뒷 글자를 조합하는 상태로 가게 하는 특수 키를 각각 배당하여 앞 글자로 간 뒤, 틀린 음소만 다시 입력하고 다시 원래 글자로 돌아왔습니다.

비고:  화살표 키를 쓰면 이보다 키를 덜 누르고 동일한 동작을 행할 수는 있지만 화살표 키가 멀리 떨어져 있기 때문에 이 방법은 잘 쓰이지 않습니다.

정타: 안심

오타: ㅏ□□ㅣ| (음소 입력 순서를 안 지킨 오타. 이미 단어는 완성됨)

기존 입력기: 6타 (단어 다시 입력)

<날개셋> 입력기: 2타 (블록 잡고 음소 재결합 명령 실행)

해설: 본 입력기에는 모아치기나 풀어쓰기 형태로 한글 음소를 다시 결합시켜 주는 기능이 있습니다.

본 프로그램은 기본적으로 공 병우 세벌식 자판을 중심으로 가장 효율적이고 빠른 입력 환경을 구현한 입력기이고, 동시에 입력 환경입니다. 초□ 중□ 종성을 모아쓰는 한글을 입력하는 방식이 로마자를 입력하는 방식과 같아서는 안 됩니다. 그러면 능률이 로마자보다 떨어지면 떨어졌지 결코 더 나아질 수 없습니다. 그리고 이게 바로 두벌식 자판의 방식이기도 합니다.

이제까지 한글에 관심있는 많은 분들이 한글 입력기를 개선하려는 시도를 해 왔습니다. 하지만 기존의 경우, 세벌식 자판의 장점을 살리기보다는 세벌식 자판의 단점을 절충한 예가 많았습니다. 세벌식 자판을 본 관점에서 제 입력기는 다른 □개선 입력기□와 구분됩니다. 한글을 입력하는 기능을 구현하다 보니 한글을 처리하고 입출력하는 코드까지 필요하게 되었고, 본 입력기는 프로그래머 관점에서는 윈도우즈용 한글 라이브러리의 역할도 하고 있습니다.

그렇다고 한글 입력 방식을 무조건 제가 제안한 방식으로 바꿔야 하는가 하면 그렇지도 않습니다. 지금과 같은 입력 방식이 좋을 때도 있고, 심지어 한글을 로마자처럼 음소를 풀어써야 할 때도 있습니다. 한글 입력기라면 다양한 옵션과 입력 방식을 지원해야 합니다. 그래서 <날개셋> 한글 입력기는 한글 입력기의 가능성을 모두 수용하는 쪽으로 확장하게 됩니다. 이게 <날개셋> 입력기의 기본 개념입니다. 그래서 제 프로그램의 뜻매김은 다음과 같습니다.

□ 언뜻 보기에는: 자체 한글을 지원하는 간단한 에디터

□ 세벌식 사용자에게는: 완벽한 세벌식 최종 자판과 모아치기를 지원하는 멋진 에디터

□ 소프트웨어 개발자에게는: 윈도우즈용 한글 라이브러리, 에디트 컨트롤 액티브X 컴포넌트

□ 한글에 관심 있는 사람에게는: 풀어쓰기, 모아치기 등 다양한 방법으로 한글을 입력할 수 있는 에디터

□ 나 자신에게 묻는다면: 한글 프로그래밍의 이상, 가장 바람직한 한글 입력기의 모습을 세벌식 자판을 바탕으로 다양하게 구현해 본 컨셉트 프로젝트

구현 형태

본 프로젝트는 한글 처리와 입력 기능을 제공하는 DLL을 중심으로, 이 DLL을 사용해서 제작한 ActiveX 자체한글 에디트 컨트롤과 이 컨트롤을 사용한 에디터 프로그램 이렇게 세 개의 모듈로 이루어져 있습니다. 1.13 버전부터 이 DLL과 액티브X 컨트롤 파일은 하나로 합쳐졌습니다. 사실 액티브X 컨트롤 자체도 DLL이기 때문에 두 모듈을 합치는 게 경제적이라고 판단했기 때문입니다.

<날개셋> 입력기는 □글처럼 자체적인 입력기 클래스를 통해 프로그래머로 하여금 그 입력기를 C++ 소스 코드 차원에서 조작하게 해 주거나, 그 입력기를 쓴 에디트 컨트롤을 제공함으로써 기능을 쓰게 해 줍니다. 다시 말해 이 프로그램은 윈도우즈의 기본 입력기에는 조금도 영향을 주지 않습니다. <날개셋> 입력기의 기능을 쓰려면 프로그래머가 애초부터―소스 코드 수준에서― 이 입력기 클래스나 에디트 컨트롤을 사용해서 프로그램을 만들어야 합니다.

윈도우즈의 일반적인 환경에서 제 입력기가 기능을 제공하지 못한다는 것은 사뭇 아쉬운 점입니다. 하지만 불안정한 IME 환경과, 한글을 제대로 표현하지 못하는 완성형 코드 체계에서는 제 프로그램의 복잡한 기능을 제대로 구현할 수 없다는 점을 이해해 주셨으면 합니다. 그래서 저는 액티브X 컨트롤이라는, 그래도 좀 열린 환경에서 제 입력기를 구현할 수 있는 환경을 새로 만들기로 한 것입니다. 액티브X 컨트롤의 클래스를 살펴보면 글자-입력기-문장-텍스트-편집기의 단계로 클래스가 계층화되어 있음을 알 수 있습니다.

액티브X 컨트롤이나 라이브러리만으로는 사용자에게 뭔가 보여줄 만한 프로그램이 될 수 없기 때문에 <날개셋> 입력기는 이 라이브러리를 쓴 간단한 에디터를 제공하고 있습니다. ActivHan.ocx를 윈도우나 윈도우 시스템 디렉토리에 복사하십시오. 그리고 윈도우 시스템 디렉토리의 Regsvr32.exe에 ActivHan.ocx 인자를 주어 실행해서 OCX 파일을 등록하면 에디터 프로그램인 MyEdit.exe를 실행할 수 있습니다. 당장 실행 프로그램을 써 보고 싶다면, MyEdit.exe에 대한 설명을 보다가 필요할 때마다 앞부분에 있는 기능 설명을 참고하시면 좋을 것입니다.

모든 프로젝트는 Win32 환경에서 비주얼 C++로 MFC를 사용하여 제작했습니다. 본 프로젝트의 핵심인 OCX에는 독자적인 자료 구조와 알고리즘을 사용하여 한글을 자유롭게 입력하고 고칠 수 있는 입력기 핵심 루틴이 C++ 클래스 형태로 들어 있습니다. 모든 기능은 음소와 글자, 문장, 글자 입력기, 문장 편집기 수준으로 잘 조직되어 있으며, 주요 함수를 오버라이딩함으로써 프로그래머가 자유롭게 자기가 원하는 대로 클래스를 다룰 수 있습니다. 한글 입력 기능 뿐만 아니라 그 기능을 구현하기 위해 부가적으로 만들어 둔 한글 처리 클래스(코드 변환, 음소 분리 등)도 관련 분야의 프로그램을 만드는 프로그래머에게 매우 유용할 것입니다.

특징

이 프로젝트의 이름에서 <날개>는 새가 이것으로 하늘을 날듯 한글이 정보 세계를 자유자재로 날아다닐 수 있게 해주는 도구임을 뜻하며, <셋>은 한글이 초성, 중성, 종성의 독창적인 세벌 구조로 되어 있음을 뜻합니다. 이 입력기가 갖는 가장 큰 의의는 다음과 같이 요약할 수 있습니다.

첫째, 한국어의 특성을 거의 사용하지 않고, 오직 한글의 특성만을 이용해 능률적인 타자 환경을 제공한다는 것입니다. 기존 입력기와 기본적인 입력 동작은 100%호환됩니다. 상용 워드 프로세서들이 탑재하고 있는 기존의 빠른 교정 기능이나 상용구는 등록된 오타나 약어가 입력되었을 때만 동작하며, 방송국 등에서 쓰이고 있는 전문 타자 속기 프로그램 역시 입력된 글의 언어적 특성을 파악하여 자동으로 문장을 완성하거나 글을 띄어 줍니다. 즉, 특정한 글을 입력하는 데 맞게 설계되었다는 말이죠. 따라서 이러한 보조 기능은 동작하는 데 언어학적인 자료가 필요하며, 언제나 오동작할 가능성을 가지고 있었습니다. 또 그 기능 자체에 대한 학습도 필요합니다. 하지만 이 입력기는 동작 방식이 직관적이고 한글다움 그 자체이며, 한글 입력기의 기본적인 동작 방식의 표준을 새로 제정할 것을 제안합니다.

둘째, 특수 용도로 제작된 타자 속기 프로그램과는 달리 범용성을 가지며, 기존 한글 입력기의 대안으로 개발되었습니다. 이전에도 기존 한글 입력기의 틀을 깨고 좀더 한글의 원리에 근접한 한글 입력기가 일부 제작되기도 했습니다. 그러나 이들은 두벌식 자판을 중심으로 모든 걸 구현하려고 해서 근본적인 한계가 있었고, OS도 도스에 국한되어 있었으며 한글 코드나 사용 방법이 기존 시스템과 호환되지 않아 널리 보급되지 못했습니다. 사용자도 일부 타자 속기사나 관련 직종 종사자에 한정되어 있었지요. 반면 이 라이브러리는 이들보다 더 독창적이고 뛰어난 기능을 갖추고 있을 뿐만 아니라 윈도우나 웹 환경에서 자유자재로 쓰일 수 있는 구조를 가졌으며, 누구에게나 당장 실용화될 수 있게 개발되었습니다. 부가 옵션을 끄면 이 입력기 역시 기존 입력기와 완전히 똑같이 동작하기 때문에 호환성도 완벽합니다.

결론적으로, 이런 한글 입력기는 <날개셋> 입력기뿐입니다.

기대되는 효과

본 입력기는 기존 입력기보다 훨씬 한글의 성능을 잘 살리면서 한글을 입력하게 함으로써 타자 능률을 향상시키고, 사용자의 타자 작업 또는 연습을 훨씬 즐겁게 해줄 것입니다. 채팅에서부터 회사에서는 제품 설명서 제작, 정부에서는 행정 문서 작성, 전쟁 중에는 작전 명령 문서 입력까지―이 모든 활동의 소요 시간이 줄어들면서 오는 생산성 향상은 엄청날 것입니다. 이는 우리 나라 국민의 정보화 수준의 향상에 기여하고, 한글의 우수성을 세계에 과시하며, 이 입력기를 채택한 소프트웨어의 경쟁력도 향상시켜 줄 것입니다. 특히 세벌식 자판의 능률을 두벌식과는 비교할 수 없이 끌어 올려주기 때문에 세벌식 자판을 홍보하고, 세벌식 사용자를 늘리는 데도 한몫 할 것으로 예상됩니다. (†쪽)

프로젝트 소개

개발 동기

이 프로젝트를 시작하는데 가장 근본적인 영감을 제공한 사건은 98년 초 제가 현행 표준인 두벌식 자판을 버리고 세벌식을 쓰기 시작한 일이었습니다.

세벌식은 알다시피 한글 구성 원리에 맞고 능률적이며 세계에서 가장 빠른 자판입니다. 그러나 저도 처음엔 세벌식의 진수를 제대로 깨닫지 못하고 타자 속도도 옛 두벌식 속도를 되찾지 못한 채 그저 남보다 나은 자판을 쓴다는 사실 하나에 만족하며 지내 왔습니다.

그런데 99년 중반, PC 통신에서 세사모(세벌식 사랑 모임)와, 타자사랑 소모임의 세벌파에 들면서 이런 상황은 완전히 달라졌습니다. 인터넷 세사모에 올라온 글을 읽고, 한글학회 홈페이지에서 <한글새소식>을 읽으면서 한글과 세벌식에 대한 자부심은 한층 커졌고, 우리 나라의 정보화 현실에 대해서도 생각하게 됐습니다. 타자 속도도 계속 빨라져 옛 두벌식 속도를 훨씬 넘어섰지요.

저는 컴퓨터 속에서 한글은 개척 혹은 개선할 게 정말 많음을 느꼈습니다. 한글이 아직 컴퓨터에서 제 성능의 반도 발휘되지 못하고 있다는 말은 사실이었습니다. 한글 코드, 글자판, 글꼴, 입력기 등... 저는 그중 사람들에게 가장 많은 영향을 주고, 당장 개선이 시급한 게 한글 입력기라는 기초 소프트웨어라고 판단했습니다. 왜 한글타자는 오타 하나만 났다 하면 기록이 금세 떨어질까? 왜 틀린 곳만을 고치지 못하고 애써 입력한 글자를 다 지우고 새로 입력해야 하나? 좀더 융통성 있게 글자를 조합할 수는 없는가?

여기서 동기가 떠올라 저는 새로운 입력기와 범용성 있는 한글 라이브러리를 같이 만들어 보았습니다. □한글 정보 입력 능률을 로마자보다 훨씬 앞서게 만들어 줄 정보화 무기□라는 목표를 정하고, 외국 소프트웨어 회사에 결코 빼앗겨서는 안될 아이디어를 생각해 내어 이를 구현했습니다. 글꼴, 코드, 자판 이 모든 요소에 가장 한글다운 길만을 택했습니다. 이렇게 해서 이 입력기가 태어났습니다.

개발 과정

□ 1999년 9월 개발자, 세벌식 최종으로 사용 자판을 바꿈. 세벌식 사랑 모임을 알게 됨

□ 1999년 10월 윈도우용 한글 출력 라이브러리 제작(훗날 CHanLib 클래스로 발전), 간단한 문서 뷰어를 만듦

□ 1999년 12월 세벌식 최종에 모아치기만 지원되는 자체 한글 에디트 커스텀 컨트롤 만듦. 모아치기의 중요성을 깨우침. (CHanInput, CHanEditWnd)

□ 2000년 2월 커스텀 컨트롤을 액티브X 컨트롤로 옮기고 CHanEditWnd에서 에디터와 관련된 기능을 CHanEditor로 따로 빼냄.

□ 2000년 3월 이 프로그램을 정보 올림피아드에 출전하기로 결정. 프로그램을 정비하고 □세벌식 무한 음소 수정□이라는 입력 방식을 고안함.

□ 2000년 4월 하순에 EXE 파일 없이 이 프로그램을 도 예선에 출전. (액티브X 컨트롤을 시연한 HTML 문서가 전부였음) 설명서는 24쪽. 결과는 금상.

□ 2000년 5월 한 줄밖에 입력이 안 되던 에디트 컨트롤을 여러 줄 편집이 가능하게 확장. 지금의 MyEdit 프로젝트 개설.

□ 2000년 6월 여러 가지 입력 옵션 추가. MyEdit의 GUI 완성.

□ 2000년 7월 24일 프로그램 드디어 완성하여 교육청에 제출. 설명서는 36쪽+부록 10쪽

□ 2000년 9월 제 17회 한국 정보 올림피아드 고등부 공모부문에서 대상 수상.

□ 2000년 11월 그 동안 발견된 버그를 해결하고, 완성형 글꼴과 입력기 유형 관리 기능을 추가한 1.1 출시. 미공개작.

□ 2001년 4월 세벌식 사랑 모임에 본 프로그램의 1.11패치를 공개.

□ 2001년 5월 개발자 홈페이지 개설. 1.12패치 완성

□ 2001년 6월 여러 가지 기능이 추가된 1.13패치 완성. Hancore.dll은 ActivHan.ocx와 합쳐짐.

□ 2001년 9월 1.2버전 완성.

기능 설계 기준

□ 프로그램은 개체를 중심으로 설계하되, 그것을 논리 계층과 물리 계층으로 구분했습니다. 논리 계층은 어떤 플랫폼으로 이식하든지 변하지 않는 알고리즘을 담당하며, 물리 계층은 운영체제에 종속적인 명령을 사용해서 이들을 화면에 출력하는 역할을 합니다. 또한 C++의 특성을 살려, 이식이나 기능 재정의가 최대한 쉽도록 클래스를 설계했습니다.

□ 입력기의 기능 추가에만 급급하다 보면 사용법이 복잡해지고, 타자와 별도로 사용법을 익혀야 하는 타자 속기 전용 프로그램의 성격을 띠게 됩니다. 저는 한글 입력의 능률성 못지않게 범용성, 호환성, 타자 초보의 편의를 고려했고, 기능을 최대한 직관적이고 알기 쉽게 설계했습니다. 반면, 초보적인 기능에 만족하지 못하는 사람은 얼마든지 고급 기능을 추가하여 더 빠르고 편하게 타자를 할 수 있게 했습니다.

□ 한글에서 모아쓰기와 풀어쓰기의 장점을 모두 수용하려고 노력했습니다. 한글의 가장 독창적인 특징이 세벌 모아쓰기인데 □세벌식□이라고 입력하는 것이 로마자처럼 □ㅅㅔㅂㅓㄹㅅㅣㄱ□이라고 입력하는 것보다 편하면 더 편하지 불편하지는 않아야 하지 않겠습니까? 저는 한글을 입력하고 고치는 방식이 풀어쓰는 것보다 편하게 하려고 최대한 배려했습니다.

□ 사용자는 자기가 원하는 일을 즉시 할 수 없을 때 답답함을 느낍니다. 본 입력기는 조합 중인 한글이든 완성된 한글이든 글자를 음소 단위, 음절 단위 어떻게든지 자유롭게 다루고, 틀린 부분만 바로 고칠 수 있게 했습니다. 글자를 조합하는 상태 역시 글자를 만들 때뿐만 아니라 글자를 지울 때나 특수 키를 눌렀을 때 등 다양한 상황에서 재현할 수 있게 했습니다.

□ 일반적으로 초성-중성 또는 초성-중성-종성으로 이루어지지 않은 한글은 미완성 한글이며 오타로 간주됩니다. 이 점을 이용해서 <날개셋> 입력기는 글쇠를 누르는 순서가 바뀌어서 난 오타를 최대한 보완해 주고, 미완성 한글이 입력되는 경로를 차단하여 오타가 나지 않게 했습니다.

□ 모든 성분의 음소가 각각 글쇠에 배당되어 있는 세벌식 자판의 성능을 최대한 살릴 수 있게 했습니다. 세벌식 자판을 고안하신 고 공병우 박사는 타자기나 텔레타이프 등 한글 관련 하드웨어를 주로 연구하셨습니다. 저는 □그분이라면 한글 입력기 소프트웨어를 어떻게 만드셨을까?□를 염두에 두고 기능을 설계했습니다.

프로젝트 구성

현재 <날개셋> 한글 입력기는 공모전에 제출하던 때와는 다른 형태로 보급되고 있습니다. 가장 먼저 소스 코드를 공개할 필요가 없고, 반면 업그레이드하기 쉬운 형태여야 하기 때문입니다. 압축 파일은 크게 세 가지로 나뉩니다. 다음은 이들에 대한 소개입니다.

Ngs120.zip

<날개셋> 한글 입력기 프로그램입니다. 라이브러리 파일인 ActivHan.ocx와, 이 라이브러리를 쓴 에디터 MyEdit.exe, 그리고 에디터 프로그램이 같이 제공하는 부가 파일(입력기 유형, 상용구 자료 등)이 본 압축 파일에 있습니다. 또한, 버전이 바뀌면서 생긴 변화를 알려놓은 ReadMe 파일도 제공합니다.

Ngsdata.zip

<날개셋> 입력기의 설명서, 에디터 프로그램에서 쓸 수 있는 여러 글꼴, 예제 텍스트 파일 등 말 그대로 데이터가 이 압축 파일에 들어있습니다. 본 입력기가 버전업되면 특별한 알림이 없는 한 Ngsdata는 받을 필요 없이 Ngs???라는 프로그램 압축 파일만 새로 받으면 됩니다.

Ngslib.zip

<날개셋> 입력기를 사용하려는 프로그래머를 위한 파일입니다. 본 라이브러리의 헤더와 라이브러리 파일이 들어있습니다. (비주얼 C++용) 그리고 에디트 컨트롤의 타입 라이브러리도 있습니다.

세벌식 자판 소개

제가 여기까지 본 입력기를 소개하면서 □세벌 구조□라는 말을 귀가 아프게 강조했습니다. 그리고 각종 오타도 모두 세벌식 자판을 기준으로 설명했죠. 그럼 도대체 세벌식 자판이란 무엇일까요?

현재 국내에 보급된 모든 컴퓨터에 인쇄되어 있는 글자판은 자음 한 벌, 모음 한 벌이 들어간 두벌식 자판입니다. 두벌식은 글쇠 수가 적고 기호와 숫자 배열이 영문 자판과 호환된다는 장점은 있지만 한글의 관점에서는 너무나 비능률적이고 한글과 세종대왕을 욕되게 하는 자판입니다. 초성과 종성을 구분할 수 없는 두벌식은 도깨비불 현상이라는 비정상적인 모습을 보이며 한글을 입력하고, 음소 단위 수정 등 한글의 응용 처리에 심각한 한계를 드러냅니다. 이는 배열만으로는 해결할 수 없는 두벌식 체계 자체의 문제입니다.

반면 세벌식은 한글을 이루는 초성, 중성, 종성을 모두 글자판에 구현한 구조로, 두벌식과는 달리 한글 구성 원리에 맞고 앞에서 언급한 모든 문제를 해결할 수 있는 능률적인 자판입니다. 본 입력기는 이 세벌식만의 특성을 살려서 그렇지 않아도 뛰어난 세벌식 자판 성능을 두벌식이 도저히 따라오지 못할 정도로 더 향상시킬 수 있게 했습니다. 그렇다고 본 입력기가 두벌식 자판은 제대로 지원해 주지 못한다는 말은 아닙니다. 두벌식 자판에서는 한글의 원리를 응용한 일부 기능만을 넣을 수 있지만 세벌식은 그뿐만 아니라 세벌식 자판 자체의 특성을 살린 편리한 기능들을 더 많이 넣을 수 있다는 거죠.

이 입력기가 기본적으로 사용하고 가장 권장하는 자판은 일명 공글판이라고도 불리는 세벌식 최종 자판입니다. 이 자판은 다음과 같은 특징을 갖습니다. (†쪽)

□ 글쇠가 한글의 각 음소와 1:1 대응하기 때문에 한글을 조합하는 느낌이 직관적이며, 도깨비불 현상 없이 한글이 생기기 때문에 눈이 편합니다.

□ 반드시 오른손에서 타자가 시작되어 99% 왼손에서 한 글자가 완성됩니다. 글자를 칠 때 손가락 움직임도 몇 가지 예외를 빼면 대부분 오른쪽에서 왼쪽으로 진행됩니다. 이는 초성, 중성, 종성이 오른쪽에서 왼쪽으로 배열되어 있기 때문에 가능합니다. 그래서 세벌식 타자는 자연스럽고 리듬감이 있으며, 글쇠를 마구 누르고 싶은 마음이 절로 납니다.

□ 기계간의 자판 통일을 고려한 구조이며, 어떤 자판보다도 구현하기가 간단하여 이 자판 그대로 기계식 타자기, 전동식 타자기, 컴퓨터 입력기 등 어떤 한글 관련 하드웨어나 소프트웨어도 일관되게 만들 수 있습니다.

□ 국어에서 가장 자주 등장하는 초성과 중성인 □ㅇ□과 □ㅏ□가 손가락이 가장 치기 좋은 검지손가락 기본 자리에 있습니다. 또한 자주 등장하는 겹받침 □ㅆ□은 아랫글쇠에 있으며, 다른 모든 겹받침도 윗글쇠를 이용한 한 타에 입력할 수 있습니다.

□ 두벌식보다 Shift를 반 이상 덜 누릅니다. 그리고 인접한 손가락의 연타는 두벌식의 1/3 이하밖에 발생하지 않습니다. 같은 손가락의 연속동작도 거의 생기지 않습니다.

□ 숫자가 다섯 개씩 두 단에 배치되어 있어 한 손만으로 모든 숫자를 칠 수 있습니다. 숫자만 입력하는 환경에서도 키패드를 쓸 필요가 없습니다.

□ 한글 문서에서 자주 쓰는 괄호와 쌍점이 아랫글쇠에 있으며, 물음표와 따옴표를 검지손가락으로 입력합니다. 그리고 ※와 가운뎃점이 글쇠에 배당되어 있습니다.

한글이 컴퓨터와 인터넷 시대에 적합한 문자인 가장 큰 이유는 세계 어느 나라 문자보다 빠른 속도로 문자를 만들 수 있는 자판이 있기 때문입니다. 세벌식이 외워야 할 글쇠가 너무 많다는 비판은 있지만 이는 하나만 알고 둘은 모르는 말입니다. 간단하다고 무조건 좋은 건 아닙니다. 한글을 이루는 음소가 글쇠에 모두 배당되어 있음으로써 한글을 입력하기가 얼마나 편해지는지는 이 설명서를 계속 읽다보면 느끼게 될 것입니다.

입력기 구조

한글 입력에 필요한 것

이제 <날개셋> 입력기가 어떤 개체로 이루어졌는지, 어떤 기능을 갖추었는지를 구체적으로 설명하겠습니다. 영문 입력기가 필요한 건 글자판이 전부입니다. 그러나 한글 입력기는 최소한 두 요소는 더 있어야 동작합니다. 글자판으로 들어오는 일련의 음소들을 어떻게 조합하고 어떻게 음절로 끊을지를 결정하는 음소 입력 순서 규정과, 글자판에 없는 음소를 만들기 위해 어떤 두 음소의 결합을 새 음소로 인정할지를 결정하는 음소 결합 규정입니다. 다음은 이들에 대한 설명입니다.

글자판

<날개셋> 한글 입력기가 지원하는 글자판은 네 종류로, 한글 두벌식, 한글 세벌식, 영문, 특수기호가 그것입니다. 한글 세벌식은 들어온 초+중+종성을 그대로 합성하여 한글을 만들며, 두벌식은 도깨비불 처리를 더 해서 한글을 만듭니다. 영문 자판과 특수 기호 자판은 글쇠에 배당된 글자가 특별한 변환 없이 그대로 나오는 것으로, 영문 자판은 윗글쇠와 아랫글쇠를 판단하는 데 Capslock키가 반영된다는 점만 빼면 두 자판 사이의 차이는 없습니다.

이 라이브러리는 기본적으로 한글 세벌식 최종, 세벌식 390, 세벌식 순아래, 두벌식과, 영문 Qwerty, Dvorak을 내장하고 있으나, 글자판을 마음대로 재정의할 수도 있습니다. 한 글쇠에 배당된 공간은 2바이트로, 어느 자판에나 전각 문자, 반각 문자, 혹은 반각 문자 2개를 마음대로 등록할 수 있습니다.

본 입력기는 단순히 문자만 입력하는 글쇠뿐만 아니라, 한글 입력기에게 뭔가 특수한 동작을 지시하는 특수 키도 지원합니다. 여기에 대해서는 뒤에서 차츰 다루겠습니다.

음소 결합 테이블

음소 결합 테이블은 종류가 같은 두 음소의 조합으로 입력했으면 하는 음소의 집합을 저장합니다. 이 테이블은 초성, 중성, 종성별로 따로 구비되어 있으며, 일반적으로 ㄴ+ㅎ=ㄶ, ㅗ+ㅏ=ㅘ와 같은 데이터가 있습니다. 본 입력기는 이 테이블을 편집할 수 있는 방법을 제공하기 때문에 사용자가 원하는 글쇠에 든 음소를 합성해서 새로운 음소를 만들게 할 수 있습니다. 예를 들어 ㅗ+ㅏ뿐만 아니라 ㅏ+ㅗ가 들어와도 ㅘ가 합성되게 할 수 있다는 것입니다.

그런데 음소 결합 테이블에 들어가 있는 데이터는 적을수록 좋습니다. 초성, 중성, 종성이 가능하면 정확하게 한 타에 대응하도록 하는 게 모아치기나 다른 한글 처리에 여러 모로 편하기 때문입니다. 그렇기 때문에 모든 겹받침이 글쇠에 배당되어 있는 세벌식 최종 자판의 경우 겹받침 결합 데이터는 없애버리고 써도 무방합니다.

음소 입력 순서 테이블

음소 입력 순서 테이블은 입력기가 한글을 조합하고 음절을 구분하는 기준을 결정합니다. 보통은 한글을 초성 최대 두 타(된소리일 때 최대), 중성 최대 두 타(겹모음일 때 최대), 종성 최대 두 타(겹받침일 때. 그러나 세벌식 자판은 한 타로 잡아도 무방)를 순서대로 눌러 입력합니다. 이를 □이어치기□라고 일컬으며, 이것을 일반성 있게 표현한 입력 순서 키는 1 1 2 2 3 3입니다. □깍두기□를 입력하면 키가 □1 1 2 3 1 2 1 2□의 순으로 들어온 셈이 됩니다. 그러면 입력기는 □1 1 2 2 3 3□의 일부가 순서대로 여러 번 반복된 것으로 간주하여 1 1 2 3 / 1 2 / 1 2로 음절을 구분합니다.

이 순서 키를 편집하면 입력기의 동작 방식도 바뀝니다. 키가 □1 1 2 2 3 3□ 대신 □1 1 2 2□와 □3 3□으로 이루어져 있으면 □깍두기□ 대신 □까ㄱ두기□가 입력되죠. 1과 2도 따로 갈라지면 □ㄲㅏㄱㄷㅜㄱㅣ□가 입력되고, 등록된 키가 하나도 없으면 이 입력기는 완전 풀어쓰기를 하여 □ㄱㄱㅏㄱㄷㅜㄱㅣ□가 되는 겁니다. 이해가 되십니까?

본 입력기는 한글 한 글자를 입력하는데 드는 최대 타수는 6타이고, 최대 2타면 어떤 음소도 입력할 수 있다는 것을 전제하고 만들었습니다. 그러므로 한 키에는 길이가 최대 6인 1, 2, 3의 중복순열이 들어갈 수 있습니다. 키는 최고 31개까지 등록할 수 있습니다.

입력 순서 테이블에 키를 적절하게 넣어 주면 굳이 초성-중성-종성의 순서뿐만 아니라 어떤 순서로든지 한글을 입력할 수 있게 됩니다. 이를 절묘하게 응용한 것이 이 입력기의 자랑 중 하나인 모아치기 기능입니다. (†쪽) 하지만 이어치기라는 제약이 있는 두벌식에서는 이 테이블을 아무렇게나 고치면 입력기가 오동작할 수도 있습니다. 예를 들어서 세벌식의 모아치기 순서 테이블을 두벌식에 그대로 적용하면 □공□을 조합하는 도중에 ㅣ가 들어왔을 때 □고이□가 되지 않고 □굉□이 됩니다.

지우기

음소, 음절 단위로 자유롭게 지우기

한글은 글쇠를 최소 두 개, 최대 여섯 개를 누를 때 한 글자가 완성됩니다. 타자 리듬도 한 글자를 주기로 되풀이되지요. 그렇기 때문에 한글을 빨리 치다 보면, 글자를 입력하다 한 음소에서 오타가 발생해도 손은 그 오타를 바로 지우기보다는 조합하고 있던 한글(물론 틀린 글자가 됩니다)을 완성하고 나서야 멈추게 됩니다. 즉, 글자로 따지면 앞 글자 또는 같은 글자이고, 글쇠로 따지면 두 타 이상 앞에 있는 오타를 고쳐야 하는 상황이 빈번히 발생합니다.

종성까지 다 입력해 버렸는데 앞 글자로 돌아가거나 초성을 입력하던 상태로 돌아가기 위해 Bksp키를 두 번 또는 세 번씩 연달아 누르는 건 너무 번거롭습니다. 화살표 키로 글자 조합 상태를 강제로 탈출하는 것도 타자 리듬을 많이 깨뜨립니다. 능률적인 한글 입력기라면 음소 단위로 지우는 기능뿐만 아니라 조합하던 글자 전체를 한번에 지우는 기능도 갖추고 있어야 합니다.

윈도우 95 이상의 한글 입력기는 입력기 설정에 음소 단위 삭제 또는 음절 단위 삭제를 지정하는 옵션이 있지만, <날개셋> 입력기는 그냥 Bksp키를 누르면 음소 단위로 글자를 지우고, Shift+Bksp키를 누르면 음절 단위로 글자를 지웁니다. 그리고 옵션을 통해서 각 기능을 하는 두 키를 맞바꿀 수도 있습니다.

앞 글자에 달라붙기

<날개셋> 입력기가 제공하는 매우 편리하고 우수한 기능 중 하나입니다. 이것은, Bksp키를 누른 결과 커서가 한글의 바로 뒤에 있게 되면 입력기가 자동으로 앞 글자를 조합하던 상태를 만들어 주는 옵션입니다. 저는 이를 간단히 □앞 글자에 달라붙는다□고 이름 붙였습니다. 아래 예를 보십시오.

□ 아기 → 아ㄱ → 아 → 안 (ㄴ 입력)

□ 안*| → 안 (*을 지운 뒤 그 앞에 있던 한글에 붙음)

□ 않| → 아 (세벌식, 바로 앞 글자는 마지막 음소만 삭제)

□ 않| → 안 (두벌식)

그뿐만이 아닙니다. 마지막 예제처럼 한글 바로 뒤에서 Bksp키를 누르면 그 글자가 모두 지워지는 게 아니라 마지막으로 입력됐던 음소만 지워지고, 입력기는 그 글자를 조합하던 상태를 만들어 줍니다. 기존 입력기처럼 글자를 모두 지우는 게 편하다면 Shift+Bksp를 누르면 됩니다. 마지막 음소를 지운 결과가 두벌식과 세벌식이 다른 이유는, 세벌식은 ㄶ을 한번에 입력하는 글쇠가 있지만 두벌식은 없기 때문입니다. 게다가 두벌식에서는 그 ㅎ이 다음 글자 초성으로 갈지도 모르니 ㄶ을 하나로 묶어서 처리할 수 없겠죠.

앞 글자에 달라붙는 동작은 매우 한글답고 자연스러운 모습입니다. 이제는 커서가 지금 조합 상태를 빠져나가든 말든 Bksp키만 누르면 바로 전 한글을 입력하던 상태가 재현됩니다. 이 입력기를 쓰는 데 익숙해지고 나면, 나중에는 현재 조합중인 글자를 지웠는데도 커서가 앞 한글에 달라붙어 있지 않는 기존 입력기가 이상하게 느껴지게 됩니다. 당연한 말이지만 이 기능은 한글 자판을 쓰고 있을 때만 동작합니다.

그런데, 두벌식에서는 아주 괴상한 일도 일어납니다. 아래 예를 보십시오.

□ 일기 → 읽 → 일

□ 떡보끼 → 떡볶

일부 두벌식을 고집하는 사람들은, 타자를 아주 빨리 치면 도깨비불 같은 건 그리 눈에 거슬리지 않는다고 주장합니다. 그렇지만 위와 같이 Bksp를 눌렀을 때 도깨비불 현상이 역으로 일어나는 모습을 보면, 두벌식을 오랫동안 쓴 사람도 매우 부자연스러워할 것입니다. 글자를 완전히 지우지도 않았는데 현재 조합중인 글자는 없어지고 전혀 엉뚱하게 변한 앞 글자에 커서가 있으니까요. 하지만 이 상태가 마지막 키를 누르기 바로 전이었는데 어떡합니까. 정 이 모습이 보기 싫다면, 두벌식에서는 □앞 글자에 달라붙기□기능을 쓰지 않거나, 사용자가 세벌식 자판을 써야 합니다.

특정 성분 음소 바로 지우기 (특수 키)

음소를 지우는 데 Bksp키를 써서 꼭 최근에 입력된 음소부터, 혹은 종성-중성-초성 순서대로만 지워야 할 필요가 있을까요? 본 입력기는 특수 키 세 개만 글자판에 배당하면 입력된 순서에 관계없이 지정한 성분의 음소를 바로 지울 수 있습니다. 초성 삭제 키, 중성 삭제 키, 종성 삭제 키가 그것입니다.

이제 조합중인 □갑□을 □압□으로 바꾸기 위해 애써 입력한 □갑□을 몽땅 지울 필요가 없습니다. 오른손을 Bksp키까지 옮길 필요도 없고요. 초성을 지우는 키를 눌러 □□□을 만든 뒤 □ㅇ□만 누르면 됩니다. 비단 조합중인 글자뿐만 아니라 완성된 □갑□ 앞에 커서를 두고 종성 삭제 키를 눌러도 □가□를 조합하는 상태가 되고, 초성과 중성까지 삭제하면 글자가 완전히 지워집니다. 이런 간단하고도 편리한 기능이 이제까지 컴퓨터에서 구현될 수 없었던 이유는 □□□과 같은 미완성 글자를 완성형 한글 코드에서 표현하기가 불가능했기 때문입니다. 조합중이 아닌 완성된 글자의 음소를 지울 때는 입력 상태가 □삽입□이 아닌 □겹침□이어야 글자를 고칠 수 있습니다.

단, 음소 지우기 기능은 원래 입력기가 지원하지 않는 조합 상황은 재현할 수 없습니다. 예를 들어 두벌식 자판에서 □갑□이라는 글자를 입력하다 초성과 중성을 지워서 □ㅂ□을 만들 수는 없습니다. 두벌식에서는 종성만 입력하는 게 불가능하잖아요? 같은 맥락에서 보면 종성까지 입력된 글자에서 중성만 제거하는 것도 어렵습니다.

그에 반해 세벌식 자판은 지우는 동작은 일단 완벽하게 지원됩니다. 하지만 뒤에서 설명할 모아치기 설정이 되어 있지 않으면 세벌식 자판이라고 해도 □ㅂ□을 바로 □갭□ 등으로 고칠 수는 없습니다. 왜냐 하면 종성→초성→중성 순으로 글자를 조합하는 순서가 인정되지 않기 때문입니다. 그래서 새로 들어온 □개□는 다음 글자로 넘어가게 되죠. 요컨대 음소 삭제 기능은 철저하게 현재의 입력기 설정에 종속적이며, 입력기의 글자 조합 규칙을 어길 수 없습니다. 그래서 세벌식 자판을 사용해야 기능을 제대로 활용할 수 있습니다.

한글 입력

모아치기

타자에 능숙하고 속도도 아주 빠른 사람들은 엉뚱한 글쇠를 누르는 일은 드뭅니다. 그렇지만 날타를 치다 보니 순서를 뒤바꿔 치는 오타를 잘 저지릅니다. 다음에 누르게 될 글쇠의 운지 거리가 지금 눌러야 하는 글쇠보다 짧으면 전자를 먼저 누르기 쉽게 되지요.

이런 오타를 잘 내는 사람들에게 기쁜 소식이 있습니다. <날개셋> 입력기는 모아치기를 지원합니다. 어떻게요? 입력 순서 테이블에 1 1 2 2 3 3뿐만 아니라 있을 수 있는 음소 순서를 모두 등록해 주면 됩니다. 예를 들어 1 1 3 3 2 2처럼 말입니다. 이 값이 있으면 초성-종성-중성 순으로도 한글을 조합할 수 있게 되죠.

세벌식 자판은 초성 된소리 같은 약간의 예외를 제외한 모든 음소가 글쇠와 1:1 대응한다고 앞서 말씀드린 바 있습니다. 그렇기 때문에 초성-중성-종성뿐만 아니라 중성-초성-종성 등 어느 순서로 글쇠를 눌러도 모호성 없이 한 글자를 만들 수 있습니다. 음소가 순서대로 들어오지 않아도 입력기는 현재 한글이 완성된 글자이면 다음 글자의 조합 상태로 넘어가고, 미완성 상태면 계속 현재 글자를 조합하기만 하면 되죠. 한글은 완성 형태와 미완성 형태 구분이 너무나 뚜렷하니까요. 이 기능을 쓰면 글자를 이루는 글쇠를 모아서 한꺼번에 쳐도 글자가 되기 때문에 이 기능을 □모아치기□라고 일컫습니다. 반면 두벌식에서는 말 그대로 초성과 중성의 두 벌 사이에만 모아치기가 됩니다. 초성과 중성 순서가 바뀐 정도만 보완이 되며, 그나마도 종성이 있는 글자와 이어지면 모아칠 수 없습니다. 초성을 입력하기 전엔 종성을 입력할 수 없다는 제약도 그대로 가지지요.

영문의 경우 BOY를 잘못해서 OBY라고 쳐도 빠른 교정 기능의 데이터에 이를 등록하지 않는 한 입력기가 그 오타를 고쳐줄 근거가 없습니다. 그러나 세벌식 자판 사용자들은 두벌식을 쓸 때처럼 초성, 중성, 종성 순서를 따져가며 타자를 치지 않아도 됩니다. 글쇠만 정확하게 누를 수 있다면 마음대로 마구 누르십시오. 그리고 외국 사람들에게도 여러분의 타자 실력과 한글과 세벌식 자판을 마음껏 뽐내십시오!

미완성 한글 입력 방지

글자를 입력하다가 글쇠를 하나 더 눌러버려 한 글자가 미완성 글자 여러 개로 분해되는 오타는 자주 내 보셨을 겁니다. □간□을 치려다가 잘못해서 □가□□과 같은 글자를 만든 상황 말입니다. 앞에서 소개한 우수한 기능만으로도 이 오타를 신속하게 고칠 수 있지만, 이런 오타를 근본적으로 차단하는 방법이 있습니다. 미완성 한글은 아예 만들지 못하게 하는 겁니다. 조합중인 글자가 미완성 한글이면 공백도 받아들이지 않습니다. 조합 상태를 탈출하려면 화살표 키로 커서를 움직여야 합니다. 따라서 문장 말미에서 자주 내는 □ㄷ .ㅏ□와 같은 오타도 예방됩니다. □ㄷ□은 미완성 한글이기 때문에 마침표와 공백이 모두 무시되고 키를 다 누르고 나면 결국 □다□를 조합하는 상태가 됩니다.

이 기능은 입력 순서 테이블의 상태에 따라 동작 방식이 달라집니다. □가□를 조합하고 있다가 □ㅐ□가 들어왔다고 합시다. □가□는 분명 완성 한글입니다. □ㅏ+ㅐ□로 결합할 수 있는 모음은 없으므로 □ㅐ□는 다음 글자로 가야 합니다. 그러나 입력 순서 테이블이 이어치기만 허용하게 되어 있다면 □ㅐ□로 새로 조합하기 시작한 한글은 무조건 □□□, □ㅐ□처럼 미완성 한글이 됩니다. 그러므로 이 □ㅐ□키는 무시됩니다. 그러나 모아치기가 허용된다면 □ㅐ□로 글자를 조합하기 시작했더라도 □갠□과 같은 글자를 얼마든지 만들 수 있기 때문에 키가 인식이 되죠.

한편, 미완성 한글 입력 조건에 걸리는 키를 무시하는 대신, 그 키의 글쇠를 현재 글자의 음소를 고치도록 옵션을 바꿔줄 수도 있습니다. 이 옵션을 □입력된 음소 수정 가능□이라고 일컬으며, 이것이 적용되면 □가□를 치다 □ㅐ□가 들어오면 조합중인 글자가 □개□로 바뀌게 됩니다.

현재 입력 순서 테이블을 풀어쓰기로 맞춰 두었다면 이 옵션을 끄셔야 합니다. 풀어쓰기 상태에서는 어떤 글쇠를 눌러도 초성과 중성이 갖춰진 한글을 만들 수 없기 때문에 이 옵션과 풀어쓰기 옵션을 같이 쓰면 한글이 전혀 입력되지 않게 됩니다.

무한 음소 수정 - 초성만 다음 글자로 인식

<날개셋> 입력기의 하이라이트입니다.

이어치기는 잘 지키지만 글쇠 자체를 잘못 누르는 경우가 많은 사람들은 모아치기가 그렇게 편리하게 느껴지지 않을 수도 있습니다. 그럼 이건 어떻습니까? 초성을 눌렀을 때만 다음 글자로 넘어가고 중성과 종성 글쇠는 현재 입력중인 글자의 음소를 고치도록 하는 겁니다. 이 기능과 □미완성 한글 입력 방지□ 옵션, 모아치기는 환상의 트리오입니다.

□밥□을 쳐야 하는데 잘못해서 □ㅂ□ 옆의 □ㅌ□을 눌러버렸다고 합시다. 그럼 Bksp를 누르지 말고 그냥 다시 □ㅂ□을 누르십시오. □미완성 한글 입력 방지□와 □입력된 음소 수정 가능□ 옵션에 걸려 □ㅂ□이 됩니다. □배□가 되었다면 다시 □ㅏ□를 누르세요. 같은 원리에 의해 □바□로 바뀝니다. □뱁□이 되어도 Bksp를 두 번 누를 필요가 없습니다. □ㅏ□만 누르면 □초성만 다음 글자로 인식□ 옵션에 걸려 □밥□이 되는 겁니다. 초성 글쇠를 누를 때만 커서가 다음 글자로 넘어가니까요. 그럼 조합중인 □갑□은 어떻게 □밥□으로 고칩니까? 이럴 때 앞에서 설명했던 초성 삭제 키를 씁니다. 바로 □ㅂ□을 누르면 다음 글자로 넘어가니까 먼저 □□□을 만들어 놓고 □ㅂ□을 누르면 모아치기 원칙에 따라 □□ㅂ□ 대신 □밥□이 된다는 말이죠.

이것은 단순히 눌러야 하는 타수가 줄어든다는 것만을 의미하지는 않습니다. 기본 자리에 있던 오른손을 옮겨 멀리 떨어져 있는 Bksp키를 누르는 게 얼마나 타자 리듬을 깨뜨리고 시간을 잡아먹는데요? 이 놀라운 기능이 <날개셋> 입력기의 세벌식 자판에서는 가능합니다. 모아치기 기능을 약간 포기해야 하지만 대부분의 경우 훨씬 더 편리함을 느낄 것입니다.

이미 입력된 글자의 음소를 고칠 수 있으려면 앞에서 설명한 음소 지우기 글쇠와 마찬가지로 입력 순서 테이블이 모아치기 구성을 하고 있어야 합니다. 아까 설명한 □뱁□을 □밥□으로 고치는 과정은 초성→종성→중성 순으로 한글을 입력하는 것으로 간주됩니다. 따라서 이렇게 고쳐진 □밥□을 Bksp로 지우면 □밥→□→ㅂ□순으로 지워집니다. 이어치기만 되는 상태에서 □뱁□+□ㅏ□가 들어오면 □ㅏ□는 다음 글자의 모음으로 간주되는데, □ㅏ□는 초성이 아니므로 다음 글자로 넘어가는 음소로도 인정되지 않아 결국 □뱁□이 사라지고 □ㅏ□를 새로 조합하는 상태가 됩니다. 또한 이 기능은 두벌식 자판에서는 제대로 사용할 수 없는데, 이는 조합 중인 글자가 종성까지 입력되어 있다면 새로 들어온 모음은 도깨비불 처리를 하는 데 써야 하고(□배바□), 새로 들어온 자음은 일단 다음 글자 초성으로 봐야 하므로, 이렇게 음소 수정 기능을 제공할 틈이 없기 때문입니다.

고치기

음소와 음절 어떤 단위로나 마음대로 수정

□간□을 □단□으로 바꾸는 데 몇 타를 쳐야 합니까? 당연히 한 타만으로 고쳐져야 하지 않을까요? 심지어 연필로 글씨를 잘못 써도 틀린 음소만 지우고 새로 쓰지 않습니까?

이 입력기는 지우기뿐만 아니라 고치기 역시 음절 단위와 음소 단위로 나누어 할 수 있습니다. 커서가 □아□ 앞에 있고 □ㅁ□키를 눌렀다면 음소 단위일 때는 □암□이 만들어지고, 음절 단위일 때는 □ㅁ□이 만들어집니다. 그리고 전자의 경우 입력기는 □조합 모드□와는 별도로 □수정 모드□로 들어갑니다.

□수정 모드□에 대해 설명을 하겠습니다. 우리가 모아치기를 비롯해 위에서 설명한 여러 편리한 기능을 사용해서 한글을 만들어 가는 상태는 모두 조합 모드입니다. 이때는 커서가 까맣게 변합니다. 그런데, 수정 모드는 이미 만들어진 글자에 추가로 입력된 음소를 집어넣어서 음소 단위로 글자를 고치는 상태입니다. 이때는 커서가 네모 테두리로 변합니다. 이렇게 모드를 따로 만든 이유는 음소를 수정할 때에도 결합 테이블에 있는 겹음소(자판에 배당되어 있지 않은 음소)를 사용할 수 있게 하기 위해서입니다. 또 음소를 수정할 때는 사용자가 모든 음소를 입력하는 게 아니라 틀린 음소만 입력하기 때문에 미완성 한글을 입력하는 동작을 입력기가 별도로 용납해야 하기 때문이기도 합니다.

수정 상태일 때는 입력 순서 테이블에 등록된 값 중 오름차순인 값만 유효하게 됩니다. 즉, 이어치기만 지원됩니다. 사실 오타를 고치는 상황에서 모아치기가 필요할 정도로 날타를 치는 사람은 없습니다. 이 때는 사용자는 글쇠를 초-중-종성 순으로 또박또박 이어 눌러서 음소를 고치겠죠. 그렇기 때문에 □고음□이란 단어 앞에서 □ㅏ□와 □ㅅ□을 차례로 누르면 단어는 모아치기가 가능하더라도 □고□가 □사□로 바뀌는 게 아니라 단어가 □가슴□으로 바뀌고, 커서는 □슴□을 수정하고 있는 상태가 됩니다. 이 때 또 초성을 누르면 커서는 다음 글자를 조합 또는 수정하는 상태가 되고, 중성이나 종성을 누르면 그 글자의 다음 음소를 고치게 됩니다.

이 기능은 두벌식에서는 제대로 사용할 수 없습니다. 두벌식에서는 종성을 고칠 수 없습니다. 음소 수정 기능은 일반적인 글자 입력 기능이 아니기 때문에 다음 글자로 넘어갈 때 입력기가 도깨비불 처리를 해주지 않습니다. 모음이 입력된 후 다시 자음이 들어오면 입력기는 다음 글자를 수정 혹은 조합하는 상태로 들어갑니다.

앞뒤 글자로 음소 옮기기 (특수 키)

음소의 입력 순서가 뒤바뀐 오타는 한글의 원리를 응용한 모아치기를 통해 저절로 보완이 될 수 있습니다. 하지만 앞뒤 글자의 음소가 뒤바뀐 건 달리 바로잡을 방법이 없습니다. 예를 들어 □바람□을 □밤라□과 같이 치는 경우를 말하는데, 이런 오타도 무심코 글을 칠 때 의외로 자주 발생하는 편입니다. 특히 종성에서 이런 현상이 심하죠.

로마자를 치는 경우 앞뒤 글자가 뒤바뀌었다면 오려두기/붙이기 기능을 사용하는 매크로를 만들어서 오타를 교정할 수 있습니다. 그렇다면 한글의 경우 입력기 차원에서 이 오타를 교정하는 방법을 열어주면 될 것입니다.

다음은 □여름□에서 □름□을 조합하다가 종성을 왼쪽으로 옮기는 특수 키를 눌렀을 때 이 키가 동작하는 방식을 나타낸 것입니다. 입력 모드(삽입/겹침)과 수정 단위(음소/음절)에 따라 동작 방식이 약간 다름을 알 수 있습니다. □의 ㅁ 상태에서 글자를 완성할 수 있으려면 모아치기가 지원돼야 할 것입니다.

□ 여름 → 여ㅁ르  (삽입 상태)

□ 여름 → 염르  (음소 겹침 상태)

□ 여름 → ㅁ르  (음절 겹침 상태)

윗글쇠

Shift 눌러두기

일반적으로 한글을 칠 때, 두벌식은 100타당 2~3타, 세벌식은 1타 정도를 Shift와 함께 누르게 됩니다. 윗글쇠는 타속과 타자 리듬을 크게 깨뜨리기 때문에 빈번하게 오타의 요인이 되는 게 사실이죠. 더구나 Shift는 새끼손가락으로 누르니까 타자하는데 더욱 부담이 됩니다. 손가락을 빨리 움직이다 보면 Shift를 확실히 누른 뒤 글쇠를 누르고 다시 Shift를 떼어 다음 글쇠를 누르기에는 너무 급한 때가 많은 게 사실입니다.

특수문자나 기호만 연달아 입력하는 상황이 아니라면 윗글쇠를 계속 입력하는 경우는 거의 발생하지 않습니다. 한 번만 누르고 말죠. 그렇기 때문에 일단 Shift가 눌러진 상황에서는 윗글쇠 인식을 한 번만 하고, Shift를 눌렀다 떼도 인식을 할 수 있게 하면 윗글쇠 쪽에서 오타를 잘 내는 사람들에게 도움이 될 겁니다.

□Shift 눌러두기□는 입력기가 Shift 키 인식을 그런 식으로 하도록 지시합니다. 이 기능을 사용하면 두벌식의 경우 □했따□, 세벌식의 경우 □없6ㅏ□와 같은 오타를 예방할 수 있으며, Shift와 글쇠를 꼭 같이 누르지 않아도 입력기가 윗글쇠를 인식하게 되기 때문에 한손 사용자에게도 편리합니다. 단, Bksp키, 세벌식에서 숫자를 입력하는 키, 화살표 키를 누를 때는 Shift를 누른 채로 여러 글쇠를 누를 수 있기 때문에 이 옵션이 적용되지 않습니다.

커서 이동

앞뒤 글자를 조합하는 상태로 (특수 키)

이 특수 키를 누르면 화살표 키를 누른 것처럼 커서가 왼쪽 또는 오른쪽으로 한 글자 단위로 이동하는데, 한글의 위치에 있게 되면 그 글자를 조합하는 상태를 자동으로 만들어 줍니다. 그래서 이제까지 설명했던 여러 가지 편리한 음소 수정 기능으로 그 글자를 빨리 고칠 수 있습니다.

다음은 깜빡 잊고 앞 글자의 종성을 입력하지 않은 채로 다음 글자로 넘어가 버렸을 때, 현재 입력중인 글자를 지우지 않고, 화살표 키도 쓰지 않고 앞글자를 재빨리 고치고 다시 원래 글자로 돌아온 모습을 나타낸 것입니다. 특수 키를 쓰는 데 익숙해지면 □자□를 지워서 앞글자로 가는 것보다 이렇게 고치는 게 속도가 더 빨라질 수도 있습니다.

와자 → 와자 → 왕자 → 왕자

조합 상태일 때의 커서 이동 처리

한글을 조합하고 있을 때 화살표 키가 들어오면 커서 위치를 어디로 둘 것인지는 한글 입력기를 만들 때 결정해야 하는 문제입니다. 예를 들어 다음과 같은 상태에서 왼쪽 화살표 키를 누른다면 커서가 어디로 가야 하는가 말입니다. 윈도우 IME의 경우 (1)과 같이 되고, □글 97의 경우 (2)와 같이 됩니다.

컴퓨 → 컴|퓨(1) or |컴퓨(2)

(1)과 같이 동작하면 현재 글자의 조합 상태를 재빨리 탈출해서 음소 수정으로 들어가 초성을 고치기가 쉬워지고, (2)와 같이 동작하면 앞 글자의 오타를 고치기가 더 수월해집니다. 제각기 장단점이 있기 때문에 이 입력기는 옵션을 통해 두 가지 방식을 모두 지원하게 했습니다.

또 비슷한 예로, 조합 도중에 Del키가 눌러지면 현재 조합중인 글자를 지워야 할지 다음 글자를 지워야 할지도 결정해야 하는 문제입니다. 역시 다음 두 가지 경우를 생각할 수 있습니다.

컴퓨터 → 컴퓨|(1) or 컴|터(2)

이 문제에 대한  답은 독자 대부분이 (1)이라고 결론 내릴 겁니다. □글, 윈도우 모두 (1)과 같이 동작합니다. Shift+Bksp키를 눌러도 (2)와 같은 결과를 얻을 수 있지요. 본 입력기는 이것 역시 두 가지 방식 모두 지원합니다.

참고로, 조합 모드가 아닌 음소 수정중일 때 사용자가 화살표 키나 Del키를 누르면 본 입력기는 모두 (2)와 같이 동작합니다. 음소 수정 모드는 커서가 □퓨□자 앞에 있을 때와 호환되거든요.

편집 기능

음소 재결합

□음소 재결합□ 기능은 로마자의 대소문자 변환 기능처럼 한글의 형태를 바꿔주는 일종의 편집 기능이며, 한글을 처리하는 프로그램이라면 반드시 있어야 할 기능입니다. 그뿐만 아니라 □음소 재결합□은 대소문자 바꾸기 기능과는 비교를 못할 정도로 더 흥미롭고 활용 가능성이 큰 기능입니다.

한 마디로 말하면 □음소 재결합□은 주어진 한글 데이터를 컴퓨터가 현재의 입력기 설정으로 다시 입력해 주는 기능입니다. □ㅇ□ㅇㅏ이ㅆ다□라는 단어를 블록으로 잡고 □음소 재결합□기능을 수행했다고 합시다. (두벌식에서는 □ㅇ□ㅇㅏ이ㅆ다□라고 해도 좋습니다.) 음절 구분을 안 한다고 생각하면 세벌식에서는 □JFeJFJD2UF□, 두벌식에서는 □DKSWSKSLtEK□라는 키를 눌러 이 단어를 입력할 수 있습니다. 이 키들을 컴퓨터가 그대로 눌러주는 겁니다. 한글이 아닌 문자는 그대로 통과하고요. 현재 입력기의 음소 입력 순서 테이블에 □1 1 2 2 3 3□이 등록되어 있어 모아쓰기가 된다면 음소를 재결합한 결과는 □앉아있다□가 되는 겁니다.

이 기능으로 가장 먼저 생각할 수 있는 활용 방법이 모아쓰기와 풀어쓰기 사이의 전환입니다. 입력 순서 테이블을 □1 1□, □2 2□, □3 3□으로 바꾸고 문장의 음소를 재결합시키면 결과는 아래처럼 됩니다.

짧다, 완전하다, 굵다

↔ ㅉㅏㄼㄷㅏ, ㅇㅘㄴㅈㅓㄴㅎㅏㄷㅏ, ㄱㅜㄺㄷㅏ (세벌식)

↔ ㅉㅏㄹㅂㄷㅏ, ㅇㅘㄴㅈㅓㄴㅎㅏㄷㅏ, ㄱㅜㄹㄱㄷㅏ (두벌식)

테이블이 □1□, □2□, □3□이라면 ㅉ, ㄼ, ㅘ, ㄺ도 두 음소로 갈라질 것입니다.

모아쓰기를 음소로 풀어쓰게 할 때는 □미완성 한글 입력 방지□, □초성만 다음 글자 음소로 인식□처럼 모아쓰기 성능과 관련된 같은 옵션을 반드시 모두 꺼야 합니다. 이는 낱음소만의 입력을 금지시키는 기능이기 때문입니다. 그리고 풀어쓰기를 다시 모아쓰기로 바꿀 때도 자판을 바르게 맞춰서 바꿔야 합니다. □ㅉㅏㄹㅂㄷㅏ□를 세벌식에서 모아쓰기로 재결합시키면 ㄹ과 ㅂ이 종성으로 알아서 바뀌지 않기 때문에, □짧다□ 대신 □짜ㄹㅂ다□가 생성됩니다.

한글을 풀어쓰기로 바꿔 놓으면 □ㄴ□으로 끝나는 단어, □ㅘ□라는 모음을 가진 글자 따위를 찾을 수도 있기 때문에 나름대로 매우 편리할 때가 있습니다. 한글 낱음소가 음소 재결합의 영향을 받지 않도록 하고 싶으면(예를 들어 번호를 매기는 데서 쓰일 때) 특수문자 영역에 있는 한글 낱음소를 쓰면 됩니다.

그런데 음소 재결합 기능이 모아쓰기와 풀어쓰기를 전환할 때만 필요한 건 아닙니다. 예를 들어 모아치기를 지원하지 않는 일반 입력기에서 입력한 오타 섞인 글을 본 입력기로 가져와서 모아치기 상태에서 음소를 재결합시키면 그 글의 오타를 말끔히 고칠 수 있습니다.

이 □ㅜ서는 모아ㅣㅊ기를 지□ㅝ하지 않는 ㅕ□집기ㅗㄹ ㅂㅣㅇ력했습니다.

→ 이 문서는 모아치기를 지원하지 않는 편집기로 입력했습니다.

위쪽 문장이 단축키 하나로 아래쪽 문장으로 단번에 바뀌는 게 신기하죠? 본 입력기의 성능이 당장 입력하고 있는 글뿐만 아니라 일반 입력기로 이미 입력된 글에 대해서도 멋지게 적용될 수 있음을 보여주는 예입니다.

화살표가 ↔가 아닌 →라는 사실을 주목하십시오. 모아치기에서는 한 글자를 만드는 방법이 두 가지 이상 존재할 수 있기 때문에 역변환이 불가능한 경우가 생깁니다. 한편, □무한 음소 수정□같은 <날개셋> 입력기의 몇 가지 옵션을 켜 놓으면 모아치기만으로는 보완하기 힘든 오타까지 바로잡을 수 있습니다.

아ㅣ제 세갸ㅖ 제일의 □ㅓ어ㄷ로 옹공ㄹ차게 ㅐㅈㅏ리ㅇ매김할 것앳□니다.

→ 이제 세계 제일의 언어로 옹골차게 자리매김할 것입니다.

한글 전용 음소 재결합

□음소 재결합□ 기능이 한글이 아닌 영문자, 숫자, 기호 등은 통과하여 그대로 입력되게 하는 반면, □한글 전용 음소 재결합□은 한글이 아닌 문자는 모두 무시하고 없는 것으로 간주합니다. 그래서 예를 들어 □ㅇK□□을 결합시키면 K가 무시되어 □안□이 생성됩니다.

글자를 완성하기 전에 마침표나 쉼표를 눌러버린다거나 세벌식에서 초성을 Shift를 누른 채 입력하여 숫자를 만드는 건 자주 발생하는 오타입니다. 이 기능은 공백도 모두 걸러주기 때문에, 한두 단어에 걸쳐서 난 특정한 오타를 고치는 데 국한하여 쓰면 좋을 것입니다.

1이ㄹ.□ㅅ ㅜ가  →  이럴수가

세벌식 자판 전용 설정

<날개셋> 입력기는 두벌식과 다른 세벌식 자판의 특징을 살려, 세벌식 사용자의 편의를 극대화할 수 있는 옵션 두 가지를 지원합니다.

숫자 글쇠를 아랫글쇠로

앞에서 세벌식 자판을 쓰면 숫자를 한 손만으로 입력할 수 있다고 말씀드렸습니다. 하지만 숫자 글쇠를 누르는 것 자체는 오른손만으로도 가능하나 왼손으로 Shift를 누르고 있어야 하기 때문에 숫자를 치는데 사실상 여전히 두 손이 필요합니다. 그래서 이 기능이 추가되었습니다. 이 옵션은 키보드의 Numlock 램프가 켜져 있으면 숫자 윗글쇠와 그 아래에 배당되어 있는 자음 글쇠의 위치를 뒤바꿔 줍니다. 예를 들어 세벌식 최종 자판에서 H를 누르면 0이 입력되고, Shift+H를 눌러야 □ㄴ□이 입력됩니다. 숫자 글쇠와 관계가 없는 다른 글쇠들은 배당 문자가 바뀌지 않습니다.

이 옵션을 사용하면 한 손에는 장부를 들고 있다 쪽을 넘기고, 한 손으로 숫자만을 계속 입력할 때도 로마자 자판을 쓸 때처럼 굳이 키패드가 필요하지 않습니다. 로마자 자판으로는 엄두도 못 내는 세벌식 자판의 자랑 중 하나인 숫자 배열을 적극 활용할 수 있을 것입니다.

□, □를 겹모음용과 홑모음용으로 구분

세벌식 자판에는 ㅜ와 ㅗ가 왼손과 오른손 위치에 각각 있습니다. 오른손으로 치는 ㅜ, ㅗ는 ㅟ나 ㅚ처럼 겹모음을 조합할 때 쓰며, 왼손으로 치는 것은 홑모음을 조합할 때 쓰게 되어 있습니다. 이는 본래 타자기와 호환성을 유지하기 위해 그렇게 설계되었지만, 실제로 그렇게 치는 게 손에도 더 잘 맞습니다.

윈도우나 □글의 세벌식 입력기는 두 키의 용도를 구분하지 않지만, <날개셋> 입력기에는 두 모음을 세벌식 취지에 맞게 구분해 주는 옵션이 있습니다. 이 옵션이 선택되면 V+F키를 누르면 □ㅗㅏ□가 되고, /+F를 눌러야 □ㅘ□가 생깁니다. □ㅡ□+□ㅣ□를 눌러도 결합이 되지 않으며, 숫자 8을 눌러야 □ㅢ□가 생깁니다.

이렇게 모음 종류를 구분해 주면 사용자가 세벌식을 올바르게 쓰는데도 도움이 되지만 한 가지 더 큰 이점이 생깁니다. □공□을 조합하고 있다고 합시다. 그리고 □ㅏ□가 들어왔습니다. 그렇다면 사용자가 의도하는 글자는 무엇일까요? □광□일 수도 있지만 모아치기인 경우 다음 글자의 □ㅏ□일 수도 있고, 무한 음소 수정 기능을 쓰는 경우 □강□일 수도 있습니다. 이 처리를 ㅗ를 /로 눌렀는지 혹은 V로 눌렀는지에 따라 다르게 할 수 있는 거죠.

<날개셋> 프로그래밍

소개

ActivHan.ocx는 이 프로젝트의 핵심 루틴이 들어 있는 MFC 확장 DLL이면서 동시에 그 핵심 루틴을 사용한 액티브X 컨트롤입니다. 모든 루틴은 C++ 클래스 형태로 들어 있으며, 프로그래머는 배포되고 있는 헤더 파일과 라이브러리 파일을 사용하여 이 클래스를 사용할 수 있습니다. 제공하는 주요 클래스는 대략 다음과 같습니다.

□ CHanLetter, CKsHanLetter, CUniHanLetter: 조합형, 완성형, 유니코드 한글 낱자 하나하나를 대상으로 음소를 읽고 쓰며, 이 개체가 올바른 한글이 맞는지 검사합니다.

□ CHanString: MBCS 한글 문자열을 다룰 때 필수적인 처리인 음절 구분, 한글 코드 판단 및 변환 등의 기능을 수행합니다.

□ CHanInput: 가장 중요한 클래스로, 들어온 키를 입력받아 한글을 조합해 주고, 그 결과를 외부로 출력하는 클래스입니다. 여러 가지 독창적이고 다양한 옵션은 한글 입력에 최고의 솔루션을 제공해 줄 것입니다.

□ CHanEditor: 한 글자를 입력받는 것만으로는 아직 처리해 줄 것이 많습니다. 본 클래스는 CHanInput을 이용한 강력한 에디터로, 이 클래스에 마우스와 키보드 입력을 전해 주고 본 클래스가 지시하는 대로 화면을 출력하기만 하면 한 줄짜리 에디터가 만들어집니다.

□ CHanLib: 조합형 한글을 비트맵 글꼴을 사용해서 윈도우 DC에 출력해 줍니다. 출력 함수를 따로 만든 이유는 미완성 한글도 지장 없이 출력할 수 있어야 하기 때문입니다.

CHanString계층부터 모든 클래스는 조합형 코드를 기준으로 작성했습니다. 그 밖에 이 라이브러리가 외부에 제공하는 데이터 클래스로는 CHanKeybrd, CStyle이 있습니다.

이 장에서는 본 클래스 라이브러리에 있는 한글 관련 클래스의 내용과 용도를 소개하고, 클래스의 공개 멤버 변수와 함수 중 중요한 것만을 설명하였습니다. 더 자세한 내용을 알고 싶으면 부록에 있는 클래스 헤더 파일의 내용을 참고십시오. 이 장은 <날개셋> 한글 입력기로 프로그램을 짜는 사람들이 읽을 만한 곳이므로, 일반 사용자라면 다음 장으로 건너 뛰어도 무방합니다.

CHanLetter

조합형 한글 낱자를 다루는 클래스로, 이 개체로부터 음소를 알아오거나 고치기, 이 글자가 어떤 종류의 문자인지 알아내기, 특정 조건을 만족하는 한글인지 판단하기 등 한글 낱자와 관련된 처리를 캡슐화하고 있습니다. 클래스를 상속받아 함수를 적절히 오버라이딩하면 코드가 다른 한글도 입출력하여 처리할 수 있습니다. (han.h)

□ m_nChoToJong[]: 정적 공개 멤버로, 초성 음소 번호를 종성 음소 번호에 대응시켜 주는 배열입니다. 예를 들어 이 배열에서 초성 ㄱ의 음소 번호에 해당하는 원소는 종성 ㄱ의 음소 번호입니다. 대응하는 값이 없는 초성(ㄸ, ㅃ, ㅉ)의 음소 번호에 해당하는 값은 0입니다.

□ m_nChoIdx[], m_nJungIdx[], m_nJongIdx[]: 정적 공개 멤버입니다. 조합형 코드는 음소가 정확하게 1 간격으로 배당이 되어 있지 않습니다. 예를 들어 □ㅘ□의 음소 번호는 14, □ㅙ□의 음소 번호는 15지만 다음 음소인 □ㅚ□의 음소 번호는 18입니다. 그 번호를 이 배열 원소에 대응시키면 정확하게 서열화된 음소 번호를 얻을 수 있습니다. □ㄱ□, □ㅏ□, □ㄱ□은 1에 대응하며, □ㅎ□은 19, □ㅣ□는 21, □ㅎ□은 27에 대응합니다.

□ Apply: 다른 CHanLetter 개체를 인자로 받아 글자를 합성합니다. 현재 개체가 □가□이고 인자로 □□□이라는 글자가 주어졌다면 현재 개체는 □갠□이 됩니다.

□ Read, Write: Read 함수는 포인터가 가리키는 2바이트를 읽어들여 개체가 나타내는 문자로 설정합니다. Write는 자기가 가리키는 문자를 출력합니다. 이 과정에서, 가상 함수이며 코드 변환을 수행하는 ToInternal, ToExternal 함수를 호출합니다.

□ GetCho, GetJung, GetJong, SetCho, SetJung, SetJong: 현재 글자의 초성, 중성, 종성 값을 얻거나 설정합니다.

□ MakeHan: 음소 세 개의 값을 한꺼번에 설정하여 한글을 만듭니다.

□ IsValidHan: 올바른 한글인지(초성, 중성, 종성의 비트값이 올바른지) 검사합니다. 가상 함수입니다.

□ IsHanja, IsSpecial, IsCompleted, IsEmptyHan: 각각 현재 문자의 종류를 판단하고, 조건에 맞는 한글인지를 되돌립니다. Completed는 완성 한글인지의 여부를 뜻하며, EmptyHan은 초성, 중성, 종성의 값이 Empty인지를 판단합니다.

□ IsInCode: 이 한글이 코드표에 배당이 되어 있는지의 여부를 되돌립니다. 가상 함수이며, 기본적으로 함수값은 항상 참입니다. 모든 한글이 코드에 배당되어 있지 않은 한글 코드를 지원하는 클래스를 CHanLetter를 상속받아 만든다면 이 함수를 오버라이딩할 필요가 있습니다. 이 함수는 IsValidHan의 함수값이 참인 글자에 대해서만 올바른 결과를 되돌린다고 전제합니다.

CUniHanLet, CKsHanLet

이 두 클래스는 CHanLetter의 파생 클래스이며, 각각 유니코드와 KS 완성형 한글을 입출력하는 역할을 합니다. 물론 모든 내부 처리는 조합형으로 행해집니다. (han.h)

CUniHanLet은 유니코드 한글을 입출력하는 클래스입니다. 원래 유니코드에는 완성 한글 11,172자만 배당되어 있지만 본 클래스는 미완성 한글의 코드를 유니코드 사용자 문자 영역인 0xe000이후에 독자적으로 배당했기 때문에, 이 클래스로도 어떤 미완성 한글도 자유롭게 표현할 수 있으며 모든 한글이 조합형 코드와 1:1 대응합니다. 올해 발표된 윈도우 2000은 윈도우 NT를 기반으로 개발되었기 때문에 앞으로 유니코드는 갈수록 비중이 커질 것으로 예상됩니다.

한편, CKsHanLet은 윈도우의 확장완성형 한글을 다루는 클래스입니다. 이 클래스는 완성형과 조합형의 변환 테이블, 확장완성형 한글 변환 테이블 리소스를 관리하는 기능을 글자를 다루는 기능과는 별도로 가지고 있습니다. 한글을 입출력하는 데 이 테이블을 참조해야 하니까 관리 기능은 자연히 이 클래스가 맡아야겠죠. 다만 테이블 관련 함수는 정적 함수이기 때문에 CKsHanLet의 인스턴스가 없어도 쓸 수 있습니다. CKsHanLet은 완성 한글 11,172자는 모두 구현할 수 있지만 조합형이나 유니코드 클래스와는 달리 □ㄱ□과 □ㄱ□을 구분하지 못하며, 미완성 한글을 구현하지 못합니다.

□ CKsHanLet::IsKsHangul: 이 글자가 완성형 중에서도 KS 완성형 2350자 안에 있는 한글인지 여부를 되돌려 줍니다. 확장완성형 한글이라면 값은 거짓이 됩니다.

□ CKsHanLet::IsInCode: 완성형으로 변환이 될 수 있는 한글인지 여부를 되돌립니다.

CHanString

텍스트의 한글 코드 변환, 인접한 한글 또는 영문자의 위치 알아내기, 음소 단위로 문자열 찾기, 단어 위치 구하기 등 조합형 한글과 영문이 섞인 문장을 처리하는 클래스입니다. 단, 이 클래스는 MFC의 CString처럼 자체적인 기억 장소를 갖지는 않습니다. (han.h)

□ GetNearestHan: n칸보다 앞에 있는 가장 가까운 문자의 위치를 구합니다. 지정한 위치가 한글의 두 번째 바이트인지 첫 번째 바이트인지 판단하는데 쓰일 수도 있습니다. 한글과 영문이 뒤섞인 문자열에서 글자 단위로 커서를 이동시킬 때 꼭 필요한 함수입니다.

□ GetCharLen: 한글을 한 글자로 쳐서 문자열의 길이를 돌려줍니다.

□ WanToJohap: 완성형 코드를 조합형 코드로 변환합니다. JohapToWan 함수도 있습니다.

□ MixUnits: □음소 재결합□ 명령을 실행합니다. (†쪽)

□ GetCharSizeAt: 문자열의 지정한 위치에 있는 문자의 크기를 돌려줍니다. 한글이면 2, 영문이면 1입니다.

□ DetermineCode: 문자열 개체의 한글 코드를 판단해 줍니다.

처리하고 싶은 문자열을 가리키는 포인터는 생성자 함수로 지정해 줘도 되고, 나중에 대입 연산자로 설정해 주어도 됩니다.

CHanKeybrd

CHanKeybrd 클래스는 본래 구조체로 설계되었습니다. 그러나 CHanInput 클래스가 덩치가 커지고, 입력기뿐만 아니라 자판 데이터와 관련된 구성원 함수가 많아지자 따로 클래스로 독립한 것입니다. (hanedit.h)

□ GetShiftedKey: 정적 함수로, 지정한 글쇠 문자를 Shift와 함께 눌렀을 때 나오는 글쇠 문자를 되돌립니다. 예를 들어 GetShiftedKey('$')의 실행 결과는 '4'입니다.

□ IsUnderKey: 정적 함수로, 영문 표준 글자판을 기준으로 들어온 문자에 해당하는 키가 아랫글쇠인지 여부를 되돌립니다. 예를 들어 □1□은 아랫글쇠이지만 □!□은 윗글쇠입니다. 로마자는 대문자가 아랫글쇠로 간주됩니다.

□ GetCharAt, SetCharAt: 지정한 글쇠에 배당된 문자를 되돌리거나 지정한 글쇠에 문자를 배당합니다.

□ GetType, SetType: 이 키보드의 종류를 지정합니다. 키보드의 종류에는 한글 세벌식, 한글 두벌식, 영문, 기타가 있다고 앞에서 설명드린 바 있습니다.

□ FindKey: 지정한 글자가 배당되어 있는 글쇠 문자를 되돌립니다. 예를 들어 세벌식 자판에서 FindKey( CHanLetter(cho_,19,jo_) )의 결과는 '4'가 됩니다. □ㅛ□에 해당하는 글쇠가 숫자 4니까요.

□ LoadKeyboard: Hancore.dll이 내장하고 있는 기본 자판 데이터를 이 개체에 읽어옵니다. CHanKeybrd::kb로 시작하는 상수를 설정해 주면 됩니다.

키보드를 나타내는 구조체는 han.h에도 선언되어 있습니다. 본 클래스는 Import, Export라는 함수를 통해 구조체에 있는 내용을 CHanKeybrd라는 클래스로 가져오거나 내보낼 수 있습니다.

CHanInput

이 프로젝트 전체를 통틀어 가장 중요하고, 그만큼 구성원이 많은 클래스입니다. CHanInput는 키보드 키를 접수받아 한글 글자를 조합, 생성해주는 일을 하는 입력기 클래스입니다. <날개셋> 입력기의 핵심 기능이 이 클래스에 구현되어 있습니다. (hanedit.h)

이 입력기의 동작 방식 중에 한 가지 알아야 할 중요한 개념이 있습니다. 상식적으로 입력기가 편집기는 아닙니다. 한글 입력기는 만들고 있는 한글 한 글자만 신경쓰면 되지 커서의 앞뒤에 있는 글자가 뭔지 알아야 할 필요는 전혀 없습니다. 그렇지만 3장에서 설명했던 □음소 수정 기능□, □앞 글자에 달라붙기 기능□ 등을 구현하려면 입력기는 자기를 조종하고 있는 에디터 프로그램이 가지고 있는 텍스트에 대한 정보를 얻을 수 있어야 합니다. 앞 글자가 뭔지 알아야 현재 조합중인 글자를 다 지운 뒤 그 글자를 조합하는 상태로 갈 수가 있죠. 또 현재 커서에 이미 있는 한글이 뭔지 알아야 그 글자의 음소만을 고칠 수 있잖아요?

그래서 이 클래스는 이 정보를 얻어올 콜백 함수 포인터를 가지고 있습니다. 그래서 한글을 조합하는 도중에 상황에 따라 콜백 함수를 호출해서, 자기 자신을 조종하는 편집기의 커서에서 최고 두 글자 앞부터 한 글자 뒤에 있는 문자가 무엇인지 묻습니다. 그렇기 때문에 CHanInput 클래스를 사용하기 전에 사용자는 콜백 함수와 관련된 설정을 초기화해줄 필요가 있습니다.

□ m_styProp: 입력기의 동작 방식을 여러 옵션 비트의 조합으로 저장합니다.

□ SetKeybrd: 입력기가 사용할 자판 데이터를 설정합니다. 인자는 CHanKeybrd개체입니다.

□ AttachHan: 지정한 글자를 조합하는 상태를 재현합니다. 여러 곳에서 쓰이는 함수입니다.

□ SetInfoFuncAndData: 앞에서 설명했던 콜백 함수를 초기화하는 함수입니다. 인자로 콜백 함수의 포인터와 콜백 함수 호출시 같이 전달할 4바이트 데이터를 받습니다. 부가 데이터로는 주로 편집기 클래스의 포인터가 들어갈 것입니다.

□ IsMakingChar: 현재 글자를 조합하고 있는지 여부를 되돌립니다.

□ GetCompletedChar: 완성된 글자를 되돌립니다. 영문자가 입력되었다면 이 함수를 호출해서 그 글자를 바로 얻어올 수 있습니다.

□ GetComposingChar: 조합하고 있는 한글을 되돌립니다.

□ GetSecondChar: 글자를 조합하고 있다가 공백이나 영문, 숫자가 입력되면 조합중인 글자뿐만 아니라 방금 들어온 문자가 한꺼번에 완성됩니다. 이 함수는 그 방금 들어와서 완성된 문자를 되돌립니다.

□ IdentifyKey: 키보드 입력이 들어왔을 때, 이것을 현재 설정되어 있는 글자판의 문자로 바꿔 그 키문자를 아래쪽 워드에 되돌려줍니다. 이때 위쪽 워드의 값은 0xffff가 됩니다. 하지만 만약 키패드의 숫자가 입력되었을 때처럼 자판과는 무관하게 어떤 문자가 강제로 입력되어야 한다면 그 문자가 위쪽 워드에 저장되고, 아래쪽 워드의 값은 0이 됩니다.

□ ProcessKey: PushKey함수를 호출하기 전에 Shift키와 관련된 전처리를 해 주는 함수입니다. 키보드 입력을 이 클래스로 전달하는 경우라면 반드시 IdentifyKey함수를 호출한 후 이 함수도 호출해 주어야 합니다. 함수값은 아직은 별 의미가 없으며, 언제나 1입니다.

□ PushKey: IdentifyKey함수의 리턴값을 그대로 전달받아 본격적인 한글 조합을 수행하는 함수입니다. 실행이 끝난 후 상황에 따라 다양한 지시를 비트 조합으로 되돌려 줍니다. GetCompletedChar를 호출해야 하는 경우, GetSecondChar를 호출해야 하는 경우, 커서를 앞으로 이동해야 하는 경우, 특수 키가 들어온 경우 등 많은 상황이 있습니다. 윈도우 IME가 윈도우 메시지로 전달하는 것을 이 클래스는 함수값의 비트 조합으로 전달합니다.

□ DoFinalConversion: Get...Char 관련 함수가 문자를 되돌리기 전에 한 번 호출하는 가상 함수로, 기본적으로 아무런 일도 하지 않습니다. 그러나 입력기에서 나오는 문자의 종류(예를 들어 전각 문자 ↔ 반각 문자, 한글 코드 변환)를 변환해야 할 일이 있다면 이 함수를 오버라이딩하여 사용자가 하고 싶은 작업을 코딩하면 됩니다.

□ Clear: 조합하던 글자를 완성된 글자로 넘기고, 한글 조합 상태를 초기화합니다.

그 밖에 본 클래스가 자체적으로 내부에서 호출하는 여러 구성원 함수가 있습니다.

CHanEditor

역시 중요한 클래스입니다. 내부로는 CHanInput 클래스를 조종하고(조합형 코드를 사용합니다), 외부로는 마우스와 키보드 입력을 접수받아 텍스트를 만드는 에디터 클래스입니다. 이 클래스를 사용하여 화면 출력만 프로그래머가 따로 하면 한 줄짜리 에디터도 손쉽게 만들 수 있습니다. 또한 이 클래스는 입력기만으로는 구현하기 힘든 특수 키 기능도 제공합니다.

이 클래스의 생성자는 기본적으로 CHanInput 개체를 인자로 받아들입니다. 사용할 한글 입력기를 지정해 줘야 한글 편집기를 구현할 수 있겠죠? (hanedit.h)

□ m_styProp: 편력기의 동작 방식을 여러 옵션 비트의 조합으로 저장합니다. 삽입/겹침 여부도 이 변수의 한 비트값으로 저장됩니다.

□ GetCharByCursor: 정적 함수로, LPVOID형 인자를 CHanEditor *형으로 치환한 후 이 에디터에 있는 문자를 인자에 맞게 되돌려 줍니다. CHanInput::SetInfoFuncAndData의 콜백 함수 인자로 이 함수의 포인터를 전달할 수 있습니다.

□ HandleSpecialKeys: 가상 함수입니다. 3장 설명했던 입력기의 기능 중에는 특수 키로 제공되는 기능이 있습니다. 특수 키 중에 글자의 음소를 지우는 키는 입력기(CHanInput)가 기능을 담당하지만, 그 외의 키는 입력기가 담당하지 않고 에디터 클래스가 맡습니다. 특수 키가 들어왔을 때 적절한 처리를 하는 함수가 이 함수입니다.

□ PushKey: 키보드 입력을 본 클래스로 전달합니다. 에디터는 적절한 전처리를 하여 이것을 입력기 클래스에도 전달하고, 지시에 따라 문자를 입력합니다. 키보드 처리를 하기 위해서는 지금 당장 들어온 키뿐만 아니라 Shift, Caps Lock, Num Lock키 등의 상태도 알아야 하기 때문에, 미래의 확장성을 위해 현재 키의 가상 키코드와 스캔코드뿐만 아니라 전체 키보드의 상태를 인자로 받게 했습니다. 키보드 상태를 배열에다 얻으려면 GetKeyboardState 윈도우 API 함수를 쓰면 됩니다. 이 함수는 들어온 키의 종류에 따라 □에디터 내용이 바뀌었다□, □화면을 새로 그려라□와 같은 지시를 여러 비트의 조합으로 되돌려 줍니다.

□ MouseMove, MouseLbDblClk, MouseLbDown, MouseLbUp: 마우스가 움직이거나 버튼이 눌렸을 때 MFC 메시지 핸들러 함수에 들어온 인자를 그대로 이 클래스로 전달하면 됩니다. 그러면 블록 선택, 화면 스크롤, 커서 이동 등 마우스와 관련된 적절한 동작을 이 클래스가 알아서 해 줍니다.

□ PasteText: 인자로 들어온 문자열을 커서 위치에 삽입해 줍니다.

□ CheckScroll: 커서가 보이도록 에디트 윈도우의 출력 좌표를 다시 계산해 줍니다. 출력 좌표가 바뀌었다면 □참□을, 그렇지 않으면 □거짓□을 되돌립니다.

□ SetPairKeybrd: Shift+Space를 눌렀을 때 전환되게 할 두 자판을 설정합니다.

□ GetKeystroke: CHanLetter 개체를 인자로 받아, 이 입력기 설정으로 그 글자를 입력하는데 차례대로 눌러야 하는 키보드 문자를 순서대로 WORD 배열에다가 되돌려줍니다. 되돌림값은 총 타수입니다.

그 밖에 블록 편집과 관련된 구동 함수, 커서 위치를 알아오거나 설정하는 함수, 화면 스크롤 위치를 설정하는 함수, 에디트 윈도우의 크기를 설정하는 함수 등 많은 구성원 함수가 있습니다.

CHanLib

윈도우 DC에 한글을 출력해 주는 함수입니다. 한 마디로 윈도우즈용 한글 라이브러리입니다. (hanlib.h)

□ SetLength: 본 라이브러리의 출력 함수를 쓰기 전에 반드시 호출해 줘야 합니다. 본 클래스가 사용할 버퍼의 크기를 지정하는 것으로, 한 번에 출력하게 될 한글의 최대 바이트수를 인자로 넘겨주면 됩니다. 예를 들어 800×600화면에 한글을 한줄 꽉 차게 출력할 필요가 있으면 800을 8로 나눈 100을 넘겨주면 되지요.

□ SetDestDC: 한글을 출력할 DC를 설정해 줍니다.

□ SetBackColor, SetCharColor: 배경색과 글자색을 설정합니다. 함수값은 예전에 설정돼 있던 값입니다.

□ SetHanFont, SetEngFont, SetHanjaFont: 글꼴을 설정하는 함수입니다. 각각 11520, 4096, 156416바이트짜리 글꼴 데이터를 가리키는 포인터를 인자로 받습니다. 글꼴이 바뀌고 나면, 이 함수들은 예전에 설정돼 있던 글꼴 포인터를 되돌려 줍니다. 한글과 영문 글꼴은 내장 글꼴이 있지만, 한자는 글꼴을 내장하고 있지 않습니다. 이 상태에서 한자를 출력하면 한자는 □로 바뀌어 나옵니다. 특수문자 역시 내장 글꼴을 갖추고 있습니다. SetHanFont와 SetEngFont에 널 포인터를 넘겨주면 그 언어의 글꼴은 내장 글꼴로 설정됩니다.

□ SetHanwanFont: 본 라이브러리는 KS 완성형 2350자의 모양을 음절 단위로 그려놓은 완성형 글꼴의 출력을 지원합니다. 완성형 11520바이트 조합형 글꼴을 같이 쓰고 싶으면 이 함수를 호출해서 75200바이트 글꼴을 가리키는 포인터를 넘겨주면 됩니다. (¶ 1.1부터 추가)

□ Eputs, Jputs, Wputs, Uputs, Hputs: 지정된 좌표에 포인터가 가리키는 문자열을 출력합니다. 왼쪽부터 차례대로 영문 전용, 조합형 한글, 완성형 한글, 유니코드를 뜻합니다. 그리고 Hputs는 아래 SetHanCode에 지정돼 있는 코드로 문자열을 출력합니다.

□ SetHanCode: 본 라이브러리가 기본적으로 사용할 문자 코드를 지정합니다. HC_ENG, HC_JOHAP, HC_WAN중 하나를 쓸 수 있습니다.

□ HputsClip: 매우 유용한 함수로, 지정된 문자열의 nStart위치부터 nLen개의 글자를 출력합니다. 한글 반쪽 잘림 출력을 지원하고, 문자열 길이가 nLen보다 짧아도 nLen개의 칸이 무조건 배경색으로 채워집니다. <날개셋> 에디트 컨트롤은 이 함수를 사용하여 에디트 화면을 출력합니다.

□ HputsTrans: 배경색을 투명하게 하여 글자를 출력합니다.

□ CursorPuts: 포인터가 가리키는 첫 글자를 커서 모양과 함께 조합하여 출력합니다. nType에는 밑줄, 세로줄 등 다양한 커서 모양을 지정할 수 있습니다. <날개셋> 에디트 컨트롤은 이 함수를 사용하여 커서를 출력합니다.

환경설정 API

ngssetup.h는 NGSSETUP_CONTET라는 구조체와, 아래 함수를 선언하고 있는 자그마한 헤더 파일입니다.

typedef struct {

DWORD dwSize;

DWORD dwInpStyle;

DWORD dwEditStyle;

WORD nChoConv[10][3];

WORD nJungConv[20][3];

WORD nJongConv[30][3];

char chOrdTable[32][6];

HANKEYBRD kbddata[2];

DWORD dwExtra1;

DWORD dwExtra2;

} NGSSETUP_CONTENT;

extern "C" NGSAPI BOOL DoNgsSetup(NGSSETUP_CONTENT *pData);

이 함수는 <날개셋> 한글 입력기의 모든 항목을 설정할 수 있는 환경설정 대화상자를 출력해서, 사용자가 설정한 값을 pData 구조체에 넣어줍니다. 그전에 pData->dwSize의 값을 본 구조체의 크기인 sizeof(NGSSETUP_CONTENT)로 설정해 줘야 합니다. 액티브X 컨트롤을 쓰는 경우, 이 구조체는 뒤에 나오는 ConfigureIME 메소드에서 쓸 수 있습니다.

이 함수는 사용자가 □확인□을 누를 경우 TRUE, □취소□를 누를 경우 FALSE를 되돌립니다. 하지만 사용자가 □취소□를 눌렀더라도 pData의 값은 사용자가 설정을 바꾼 대로 바뀌어 있다는 점을 유의하세요.

ActivHan.ocx

소개

이 컨트롤은

ActivHan.ocx에는 앞의 루틴들을 자체적으로 사용하여 구현한 한글 에디트 컨트롤과 라벨 컨트롤이 들어 있습니다. 라벨 컨트롤은 한글을 출력만 하지만 에디트 컨트롤은 본격적인 에디터로 써도 손색이 없는 컨트롤이며, 설명도 이 컨트롤을 중심으로 할 것입니다. 액티브X 컨트롤이기 때문에 비주얼 베이직 등 다른 툴에서도 이 컨트롤을 사용할 수 있을 뿐만 아니라 웹에서도 <날개셋> 입력기가 제공하는 우수한 기능을 사용해서 한글을 자유자재로 입력할 수 있습니다. 이 컨트롤은 앞장에서 소개한 여러 가지 입력기 옵션을 프로퍼티 형태로 캡슐화해서, 이들을 간단한 조작만으로 사용할 수 있게 했습니다.

동작 방식

에디팅에 필요한 대부분의 작업을 CHanEditor와 그 안의 CHanInput가 해줍니다. 그래서 이 컨트롤 자체는 키보드나 마우스 입력이 들어왔을 때 그것을 CHanEditor의 인스턴스에 전달해서 그 클래스가 전해준 결과에 따라 화면을 다시 그리고, 이벤트를 발생시키기는 일만 합니다. 하는 일이 더 있다면, 클립보드 관리나 여러 줄 단위의 블록 편집 등 운영체제에 종속적인 일과 동적 메모리의 관리 등이죠. 자세한 것은 소스 코드의 메시지 핸들러 부분을 참고하십시오.

본 컨트롤은 동작의 효율성을 위해 한 줄에 들어갈 수 있는 문자 수를 1023자로 제한했습니다.(1.11과 이전 버전에서는 255자였음) 그리고 워드랩을 지원하지 않으며, 탭 문자도 줄을 맞춘 공백이 아닌 탭 문자 그대로 보여준다는 것도 알아 두시기 바랍니다.

글꼴

본 컨트롤은 조합형 한글의 원활한 처리를 위해 윈도우가 제공하는 글꼴을 쓰지 않고 조합형 비트맵 글꼴을 씁니다. 세벌식 최종 자판에 ※, · 같은 문자가 있기 때문에 특수문자 글꼴도 내장하고 있지만, 한자 글꼴은 기본적으로 지원하지 않고 한자 처리가 필요한 컨테이너가 메소드를 호출해 글꼴을 설정하게 했습니다.

기본 한글 글꼴은 박정만님이 디자인한 공병우식 2×1×2벌 세벌 글꼴입니다. 명조나 고딕은 일본 글꼴의 획 모양을 베낀 한글답지 못한 글꼴로, 눈에 익어서 보기 좋을 뿐이지 덩치가 너무 크고, 글자 하나하나를 다 그려서 고해상도에서 출력해야 완성도 높은 자형을 얻을 수 있습니다. 그러나 세벌 직결식 글꼴은 크기가 네모 글꼴의 수십 분의 일에 지나지 않고, 복잡한 글자와 간단한 글자의 형태가 바로 구분되기 때문에 한글의 원리를 살리고 한글을 훨씬 날씬하게 만들어주는 글꼴입니다. 이 글꼴을 쓰면 이미 입력된 음소는 글자가 완성되어가도 모양이 거의 바뀌지 않기 때문에 타자칠 때 눈이 편하고, 글자의 빈 공간에 음소가 들어가는 모습이 매우 자연스럽게 느껴집니다. 이 말이 이해가 잘 안 가시는 분들은 글자 인식 프로그램을 만든다고 생각해 보세요. 컴퓨터는 명조와 안상수체 중에 어느 글꼴의 글자를 인식하기가 더 쉬울까요?

사용법

레지스트리에 등록하기

ActiveX 컨트롤은 레지스트리에 등록해야 쓸 수 있기 때문에 이 컨트롤을 쓰는 다른 프로그램이나 웹 문서를 열기 전에 OCX와 DLL파일을 한 디렉토리에 복사해 두고 Windows의 System 디렉토리에 있는 regsvr32라는 프로그램으로 이 컨트롤을 등록하는 것을 잊지 마시기 바랍니다.

사용 가능한 키

기본적으로 모든 단축키는 윈도우 메모장과 일치하게 했습니다. 그 밖에 본 컨트롤이 독자적으로 사용하는 키는 다음과 같습니다.

□ Shift+Space, 한/영: 한영 전환을 합니다. 더 정확하게 말하면 설정되어 있는 제 1자판과 제 2자판을 서로 전환합니다.

□ 한자: 커서를 한글 앞에 두고 이 키를 누르면 이 한글을 한자로 바꿀 수 있습니다. 본 컨트롤 자체에 한자가 지정되어 있지 않으면 본문에서 한자를 볼 수는 없습니다. 한자 앞에서 한자 키를 누르면 한자가 한글로 바뀝니다. (¶ 1.12에서 추가)

□ Ctrl+I: 특수문자를 입력하는 문자표를 호출합니다. 여러 자를 한꺼번에 입력하고 싶으면 □계속 입력□ 옵션을 선택한 뒤 계속 글자를 선택하면 됩니다. (¶ 1.12에서 추가)

□ Shift+F4, F4: 블록으로 선택되어 있는 한글을 현재 설정된 입력기 설정으로 다시 입력해주는 명령입니다. F4는 음소 재결합, Shift+F4는 한글전용 음소 재결합 명령을 실행합니다. (†쪽)

(1) 해□교 → 학교 (세벌식, 입력된 음소 고치기 옵션, 초성만 다음 글자로 인식하기 옵션)

(2) 컴퓨터 → ㅋㅓㅁㅍㅠㅌㅓ (두벌식, 풀어쓰기)

□ Shift+Ins: 음절 수정과 음소 수정 모드를 서로 전환합니다. (†쪽)

프로퍼티

3절부터는 프로그래머를 위한 설명입니다.

□ Appearance: 값이 1이면 컨트롤 가장자리에 움푹 들어간 듯한 입체 효과가 생깁니다.

□ BorderStyle: 값이 1이면 컨트롤 주위에 사각형 테두리가 생깁니다.

□ ForeColor, BackColor: 글자색과 배경색을 설정합니다.

□ HideSelection: 이 컨트롤이 비활성화되었을 때 블록을 감출 것인지 설정합니다. 이 값이 참이면 컨트롤이 비활성화된 경우 블록으로 선택된 영역이 반전되어 보이지 않습니다.

□ LineInterval: 윈도우가 제공하는 에디트 컨트롤의 큰 단점 중 하나가 줄간격 조절이 안 된다는 것입니다. 본 컨트롤은 이 프로퍼티를 통해 줄간격을 설정할 수 있습니다. 글꼴 크기는 16×16이므로 이 값이 16이면 줄간격이 없는 셈이 됩니다. 값은 16부터 48까지 지정 가능합니다.

□ TypeOrder: 한글의 음소 입력 순서 테이블의 내부 설정치를 고릅니다. 0은 모아치기, 1은 이어치기, 2는 풀어쓰기(겹음소 조합 가능), 3은 완전 풀어쓰기입니다. 사용자가 직접 테이블 값을 정의하고 싶으면 SetOrderTable 메소드를 호출해 작성한 배열을 직접 전달하도록 합니다.

□ InputStyle: 입력기의 동작 방식을 설정합니다. 부록의 Hanedit.h 소스에서 CHanInput ::m_styProp멤버 변수의 값을 지정하는 것으로, 이 설정치로 본 입력기의 동작 방식을 조종합니다. enum CHanInput::InputStyle의 상수값을 참고하십시오. 예를 들어 □무한 음소 수정□과 □앞 글자 달라붙기□ 기능을 쓰려면 이 값을 0x40+0x10(10진수로 80)으로 지정하면 됩니다.

□ EditorStyle: 에디터의 동작 방식을 설정합니다. CHanEditor::m_styProp멤버 변수의 값을 지정하는 것입니다. 예를 들어 초기에 겹침 모드를 설정하려면 CHanEditor::styOverwrite의 값인 4를 지정하면 됩니다. 값들이 지니는 의미는 역시 헤더 파일의 소스를 참고하십시오.

□ Keyboard1, Keyboard2: Shift+Space키를 눌렀을 때 전환되는 자판의 종류를 설정합니다. 0부터 시작해서 세벌식 최종, 세벌식 390, 세벌식 순아래, 두벌식, Qwerty, Dvorak을 뜻하며, 사용자 자판을 쓰려면 SetPairKeybrd 메소드를 호출해 사용자가 만든 자판 배열을 전달하면 됩니다.

□ Enabled: 이 컨트롤이 사용 가능해져 있는지를 나타냅니다.

□ MultiLine: 값이 참이면 여러 줄을 편집할 수 있고, 거짓이면 한 줄만 편집할 수 있습니다.

□ Col: 에디터의 커서 위치(칸)를 나타냅니다. 0부터 시작하는 값입니다.

□ Row: 에디터의 커서 위치(줄)를 나타냅니다. 역시 0부터 시작합니다.

□ Text: 에디터의 텍스트입니다.

□ UseWan: 이 컨트롤은 내부적으로 조합형 코드를 사용하기 때문에, 완성형 코드를 사용하는 윈도우와 호환을 유지하기 위해서 이 프로퍼티를 두었습니다. 이 값이 참이면 이 컨트롤로 들어가는 모든 한글은(Text 프로퍼티의 설정값, 윈도우 이름, 클립보드 붙여넣기 데이터 등) 완성형에서 조합형으로 코드 변환이 됩니다. 이 컨트롤에서 밖으로 나가는 모든 한글 역시 조합형이었다가 완성형으로 바뀌어 외부로 나갑니다. 다른 윈도우(프로그램, 컨트롤 등)와 원활하게 데이터 교류를 하려면 이 값은 참이어야 합니다. 반면 이 컨트롤끼리만 교환을 할 때는 거짓으로 설정해 두는 게 좋습니다. 변환 과정도 필요없고, 모든 한글을 구현할 수 있잖아요.

□ DirectUpdate: 이 값이 □거짓□이면, 각종 메소드 호출로 인해 에디트 컨트롤의 화면이 바뀌어도 DirectUpdate값이 □참□으로 바뀔 때까지 화면을 새로 그리지 않게 합니다. 에디트 컨트롤을 여러 메소드로 조작해야 할 일이 있을 때는 이 값을 □거짓□으로 바꿔두고 처리하는 게 화면이 깜빡거리는 현상을 방지할 수 있어서 좋겠죠? 또 처리 속도도 올릴 수 있고요.

□ TypePractice: 에디트 컨트롤을 타자연습 모드로 설정합니다. 타자연습 모드에서는 클립보드에서 내용을 블록으로 잡아 복사하거나 오려넣을 수는 있지만 붙여넣기를 할 수 없으며, 마우스 오른쪽 버튼을 눌러도 빠른메뉴가 나오지 않습니다. 그리고 한자 변환을 할 수 없습니다. (¶ 1.13에서 추가)

한글 코드를 변환하는 루틴과 변환 테이블은 Hancore.dll에 있습니다. 단, UseWan값이 1이더라도 □글과 본 컨트롤끼리는 미완성 한글을 포함한 어떤 한글도 아무 제약없이 주고받을 수 있습니다. □□□똠□이라는 문자열을 본 컨트롤로 입력하여 복사한 뒤, □글에 붙여넣었을 때와 MS 워드에 붙여넣었을 때의 결과를 비교해 보십시오.

프로퍼티들의 일부는 이 컨트롤의 등록 정보 대화상자를 통해서도 고칠 수 있습니다.

메소드와 이벤트

메소드를 쓰면 포인터를 전달해서 프로퍼티만으로는 할 수 없었던 좀더 저수준의 인터페이스 조절을 할 수 있습니다. 또한 컨트롤에게 특정한 명령을 내릴 때도 메소드를 씁니다.

이 컨트롤을 만들 때 고민했던 부분이 컨트롤로 글꼴이나 배열 데이터를 어떻게 전달하는가 하는 것이었습니다. 가변형을 쓸까도 생각해 보았지만 현재는 OCX가 인 프로세스 DLL이란 점을 착안하여 자료형을 short *로 간단하게 통일했습니다. 그러므로 인자로 데이터를 가리키는 포인터를 전달할 때 적절하게 형변환을 하시기 바랍니다.

□ SetHanFont, SetEngFont, SetHanjaFont: 각각 한글, 영문, 한자 글꼴을 설정합니다. 포인터는 각각 11520, 4096, 156416바이트의 데이터를 가리키고 있어야 하며, 이 메소드를 호출한 후에도 그 메모리 영역이 소멸되어서는 안됩니다. 다시 내장 글꼴을 쓰고 싶으면 널 포인터를 전달하면 됩니다.

□ SetHanwanFont: CHanLib 클래스와 마찬가지로 본 컨트롤도 완성형 한글 글꼴을 공용하는 메소드를 제공합니다. 완성형 글꼴을 쓰지 않으려면 역시 널 포인터를 전달하면 됩니다. (¶ 1.1에서 추가)

□ Refresh: 컨트롤을 다시 그리라고 지시합니다.

□ SetCurKeybrd: Keyboard1, Keyboard2에 배당된 자판과 상관없이 사용자가 직접 정의한 자판 배열을 사용하도록 합니다. 포인터는 CHanKeybrd형의 인스턴스를 가리킵니다. 이 메소드로 설정한 자판은 사용자가 Shift+Space키를 누르는 순간부터 다시 사용할 수 없게 되므로, 기본 자판을 바꾸려면 SetPairKeyboard를 쓰도록 하십시오.

□ SetPairKeybrd: Keyboard1, Keyboard2에 사용할 사용자 자판을 설정합니다. 인자는 CHanKeybrd 개체를 두 개의 포인터입니다.

□ SetOrderTable: 입력 순서 테이블을 설정합니다. 첫 번째 인자는 char (*)[6], 즉 원소 개수가 6인 배열을 가리키는 포인터입니다. 그리고 두 번째 인자에 원소의 개수를 설정해줍니다. 앞서 설명드렸지만 키는 최대 31개까지 등록할 수 있습니다.

□ SetCompTable: 음소 결합 테이블을 설정합니다. 첫 번째 인자는 short (*)[3]이며, 두 번째 인자는 이 수치가 어느 음소의 번호를 뜻하는지 나타내는 1부터 3까지의 숫자(초성, 중성, 종성), 마지막 인자는 원소 개수입니다. 결합 테이블의 원소는 초성의 경우 9개(예를 들어 현대어에서 초성 된소리 결합을 모두 등록하려면 5개의 공간이 필요하죠.), 중성은 19개, 종성은 29개까지 등록할 수 있습니다.

□ 기본 이벤트: 비주얼 베이직의 에디트 컨트롤처럼 Change, KeyDown, KeyUp, Click, DblClick, KeyPress, MouseMove, MouseDown, MouseUp을 생성합니다.

□ GetLineCount: 에디터에 들어가 있는 텍스트의 총 줄 수를 되돌립니다.

□ GetLineAt: 지정한 번째의 줄(0부터 시작)에 있는 문자열을 에디터의 내부 코드(조합형) 그대로 배열에다 기록하고, 이 줄의 문자열 수를 되돌립니다.

□ GetLine: 지정한 번째의 줄(0부터 시작)에 있는 문자열을 OLE 표준 문자열형(완성형 또는 유니코드)으로 되돌립니다.

□ SendMultiText: 조합형, 완성형 또는 유니코드로 된 문자열을 편집창의 현재 커서 위치에 붙여 넣습니다. 데이터는 포인터를 통해서 전달하며, 이 데이터의 한글 코드를 사용자가 직접 지정해 주거나, 컨트롤이 자동으로 판단하도록 할 수 있습니다.

□ SendText: OLE 표준 문자열형을 편집창에 붙여넣습니다. Text 프로퍼티를 바꾸는 것과 다른점은 텍스트를 현재 텍스트를 지우지 않고 커서 위치에다 붙여넣는다는 점입니다.

□ CharTable: □특수문자 문자표□ 대화상자를 호출합니다. 즉, 사용자가 Ctrl+I를 눌렀을 때와 똑같은 반응을 보이게 합니다. (¶ 1.13에서 추가)

□ ConfigureIME: 한글 입력기의 네 가지 구성 요소를 한꺼번에 설정할 수 있는 메소드입니다. NGSSETUP_CONTENT 구조체의 포인터를 인자로 받습니다. (¶ 1.2에서 추가)

그 밖에도 블록 조작과 관련된 것, 커서 위치를 얻어오거나 바꾸는 것 등 메소드가 더 있지만 설명은 생략하겠습니다. 다음은 KeyDown, MouseMove같은 기본 이벤트 외에, 본 컨트롤이 만들어내는 사용자 정의 이벤트입니다.

□ PosChange: 에디터의 커서 위치나 화면의 스크롤 위치가 바뀌었을 때 발생합니다. 이 컨트롤로 에디터를 만들고 있다면 이 이벤트가 생겼을 때 스크롤 바 위치를 바꾸고  커서 위치를 다시 표시해 주면 됩니다.

□ Change: 사용자가 글자를 입력해서 에디터의 내용이 바뀌었을 때 발생합니다.

사용례

비주얼 C++

비주얼 C++에서는 모든 OLE 컨트롤들은 컴포넌트/컨트롤 갤러리를 통해서 사용자의 프로젝트에 삽입할 수 있습니다. □OLE Controls□ 탭을 선택한 뒤 이 컨트롤을 삽입하면, CNgsEdit, CNgsStatic이라는 포장 클래스가 생깁니다. 삽입된 OLE 컨트롤은 대화상자 편집기의 팔레트에도 등록되기 때문에 대화상자에도 마음대로 이 컨트롤을 삽입하고, 이 컨트롤과 연결된 멤버 변수를 등록할 수 있습니다. 이 클래스에서 프로퍼티 값을 얻어오거나 바꾸는 함수는 모두 그 프로퍼티 이름 앞에 Get이나 Set만 붙인 형태입니다. 애플리케이션 초기화 코드에 AfxEnableControlContainer()함수를 호출하는 건 잊지 않으시겠죠?

다음 코드는 대화상자 클래스의 OnInitDialog()함수에서 이 컨트롤을 초기화한 예입니다. 연결된 멤버 변수는 m_wndInp이며, Control로 연결되어 있습니다. Control로 연결된 멤버 변수의 초기화는 CDialog::OnInitDialog()를 호출한 뒤에 하세요. 컨테이너가 직접 Hancore.dll을 사용하는 일이 없더라도 본 클래스 라이브러리의 헤더 파일을 인클루드해 두면 아래의 예처럼 헤더 파일에 정의되어 있는 각종 상수를 쓸 수 있습니다.

{

//...

static char m_pHft[11520]; //폰트를 저장하는 배열

CDialog::OnInitDialog();

CFile f("han.fnt", CFile::modeRead);

f.Read(m_pHft, 11520); //m_pHft는 지역변수여서는 안됩니다.

f.Close();

m_wndInp.SetHanFont((short *)m_pHft); //한글 글꼴 설정

m_wndInp.SetAppearance(1); //입체 테두리

m_wndInp.SetText("<날개셋> 컨트롤 사용 예제"); //초기값인 텍스트입니다.

m_wndInp.SetKeyboard1(1); //세벌식 390 자판을 씁니다. (디폴트값은 최종입니다.)

//초기에 겹침 상태로 동작합니다. (디폴트값은 삽입 상태입니다.)

m_wndInp.SetEditorStyle(m_wndInp.GetEditorStyle()|CHanEditor::styOverwrite);

return TRUE;

}

응용 프로그램에서 이 컨트롤을 쓰는 경우 이 컨트롤이 인식하는 키와 프로그램의 액셀러레이터에 등록된 키가 겹치지 않도록 주의하십시오. 예를 들어 컨테이너 프로그램의 액셀러레이터에 □붙여넣기□의 단축키인 Shift+Ins가 등록되어 있으면 이 컨트롤이 음소/음절 단위 수정 전환 글쇠로 그 키를 쓰지 못하게 됩니다. 음소 재결합을 하는 키인 F4, Shift+F4도 마찬가지입니다.

비주얼 베이직

컨트롤 팔레트에서 마우스 오른쪽 버튼을 누른 뒤, 팝업 메뉴에서 □구성 요소□(버전에 따라서는 □추가 컨트롤□)를 선택합니다. 다음, □날개셋 한글 입력기□ 혹은 □ActiveHan OLE Control Module□이라는 항목을 체크한 뒤 □확인□을 누르면 이 컨트롤을 쓸 수 있게 됩니다. 아이콘이 □한□인 것은 라벨 컨트롤이고, 입력란 모양인 것이 에디트 컨트롤입니다. 아래는 비주얼 베이직에서 폼에 본 컨트롤을 사용한 화면입니다.

인터넷 익스플로러

HTML 문서에서 <OBJECT>라는 태그를 쓰면 이 컨트롤을 웹에 삽입시킬 수 있습니다. 예를 들어 다음 코드는 웹문서에 <날개셋> 에디트 컨트롤을 생성합니다. UseWan프로퍼티의 값은 Text의 값에 설정된 한글이 완성형 코드인지의 여부에 따라 1 또는 0이 됩니다.

<OBJECT  CLASSID="clsid:302b1f23-2bbe-11d4-ba71-ddb3ce9ae61b"

ID=hanctrl  WIDTH=540  HEIGHT=100  ALIGN=center  HSPACE=0  VSPACE=0  >

<PARAM NAME="Text" value="여기를 마우스로 누르고 글을 입력해 보세요.">

<PARAM NAME="LineInterval" value=18>

<PARAM NAME="Appearance" value=1>

<PARAM NAME="BorderStyle" value=1>

<PARAM NAME="MultiLine" value=1>

<PARAM NAME="UseWan" value=1>

</OBJECT>

같이 들어있는 OCX파일은 서명을 받지 않은 상태입니다. 그렇기 때문에 익스플로러는 이 컨트롤을 읽어들일 때  잠재적 위험성이 있다며 초기화를 허용할 것인지 묻습니다. 물론 □예□를 선택해야 이 컨트롤을 쓸 수 있습니다.

<날개셋> 타자연습

제가 만든 이 프로그램은 세벌식 최종 자판을 익히는 사람에게는 더없이 좋은 도구인 동시에, <날개셋> 프로그래밍에 대해 가장 잘 보여주는 예제입니다. 본 프로그램은 소스 코드가 공개되어 있기 때문에, 관심있는 분은 분석해 보세요. <날개셋> 타자연습은 제 홈페이지와 세벌식 사랑 모임에서 구할 수 있습니다.

MyEdit.exe

소개/사용법

MyEdit는 <날개셋> 한글 입력기의 구성요소이며, 클라이언트 영역에 <날개셋> 에디트 컨트롤을 생성하여 텍스트 파일을 편집하는 MDI 에디터입니다. MyEdit 프로그램은 실행할 때는 ActivHan.ocx가 필요하며 이 컨트롤이 레지스트리에도 등록되어 있어야 합니다.

사용법 요약

키 사용법은 ActivHan.ocx에서 설명된 그대로입니다. 에디터의 동작 방식도 메모장 에디터와 거의 같습니다.

에디트 윈도우의 글꼴, 색상, 줄간격 등을 바꾸려면 □설정-편집창 설정□ 기능을 선택하면 됩니다. 글꼴을 바꾸려면 □바꾸기□ 단추를 누른 후 한글(11520□ 75200바이트), 영문(4096바이트), 한자(155416바이트) 글꼴을 구분 없이 선택하면 됩니다. 프로그램이 파일 크기를 살펴보고 글꼴의 종류를 자동으로 파악하기 때문입니다. □기본 글꼴로□ 단추를 누르면 <날개셋> 라이브러리가 내장하고 있는 글꼴―박정만 님의 빨랫줄 글꼴과 Fixedsys―이 선택됩니다. 한편, 편집창의 색깔은 사용자가 원하는 것을 선택할 수도 있지만 윈도우의 색상을 따라가게 할 수도 있습니다.

문서를 열고 나면 □설정□ 메뉴에 열린 문서에 해당하는 한글 코드가 체크 표시됩니다. 이 체크 설정을 바꾸면 한글 코드를 바꾸어 저장할 수 있습니다. 조합형, 완성형, 유니코드 사이에 변환을 자유롭게 할 수 있습니다. 단 유니코드는 한글과 영문만 지원합니다.

본 프로그램은 대부분의 경우 한글 코드를 정확하게 판단하지만, 문서 첫부분에 한글이 나오지 않는 문서의 경우(특히 소스 코드) 한글 코드를 잘못 판단할 수도 있습니다. 이 경우 □한글-한글코드 수동 지정□을 선택하십시오. 이 옵션이 선택되면 프로그램은 문서를 읽기 전에 한글 코드를 사용자가 수동으로 지정하게 해 줍니다. (¶ 1.12에서 추가)

□글과 마찬가지로 본 프로그램은 Alt+F1을 누르면 현재 글자판 배열을 보면서 타자를 할 수 있습니다. □보기-글자판보기) (¶ 1.2에서 추가)

입력기 설정

다음은 □한글-입력기 설정□ 프로퍼티 시트에 있는 네 개의 페이지에 대한 설명입니다. 이 대화상자는 <날개셋> 입력기에 설정해 줄 수 있는 옵션을 총괄적으로 관리합니다.

이 프로퍼티 시트는 MyEdit가 지원하는 게 아니라, <날개셋> 라이브러리의 환경설정 API (DoNgsSetup())가 제공하는 것입니다.

한글 입력기

3장에서 설명했던 입력기 옵션을 실제로 설정하는 페이지입니다. □입력기 설정□에 나와있는 옵션은 다음과 같습니다.

□ Bksp를 누르면 음소 단위로 글자 지움: 쪽 □지우기□의 설명을 참고하십시오.

□ Bksp로 현재 글자를 다 지우면 앞 한글에 달라붙음: 쪽 □지우기□의 설명을 참고하십시오.

□ Bksp로 이미 완성된 글자를 지울 때도 음소 단위로: 쪽 □지우기□의 설명을 참고하십시오.

□ 한글 조합 상태가 아니면 Shift+Bksp를 Bksp와 같게(¶ 1.2에서 추가): 앞에서 설명드렸듯이, 본 입력기는 Bksp와 Shift+Bksp가 한글을 지우는 단위가 다릅니다. 하지만 사람 취향에 따라서는 보통 입력기처럼 두 방식이 똑같이 동작하는 것을 더 선호하는 경우가 있습니다. 이 옵션이 켜져 있으면, 본 입력기는 커서가 한글을 조합하는 상태가 아닐 때 Shift를 누르든 안 누르든 Bksp가 똑같이 한글을 음소나 음절 단위로 지우게 합니다.

□ 미완성한글 입력을 막음: 쪽 □미완성 한글 입력 방지□의 설명을 참고하십시오.

□ 이미 입력된 음소도 다른 음소가 들어오면 고칠 수 있음: 쪽 □미완성 한글 입력 방지□의 설명을 참고하십시오.

□ 초성이 들어왔을 때만 다음 글자를 조합하기 시작: 쪽 □무한 음소 수정□의 설명을 참고하십시오.

□ 음소 단위로 수정: 겹침 상태에서 한글을 고칠 때 입력된 음소만 고칠지 음절을 다 지우고 새로 입력을 시작할지 설정합니다. 편집창에서도 Shift+Ins키를 눌러 두 상태를 전환할 수 있습니다. 쪽 □음소 단위 수정□의 설명을 참고하십시오.

□ Shift 눌러두기 가능: 쪽 □Shift 눌러두기□의 설명을 참고하십시오.

□ 초성 다음은 무조건 종성: 두벌식 자판에서 초성이 다 입력된 후 또 자음이 들어오면 이 자음을 다음 글자의 초성이 아닌 현재 글자의 종성으로 인식시킵니다. 현재 글자가 초성과 종성이 다 갖춰져야 자음이 다음 글자의 초성으로 인정됩니다.

□ 겹모음용 ㅗ, ㅜ와 홑모음용 ㅗ,ㅜ를 구분해서 인식: 세벌식 자판과 관련된 옵션입니다. 쪽 설명을 참고하십시오.

□ Numlock이 켜져 있으면 숫자 윗글쇠와 아랫글쇠 위치 서로 바꿈: 세벌식 자판과 관련된 옵션입니다. 쪽 설명을 참고하십시오.

□편집기 설정□에 있는 건 커서 이동과 관련된 설정, □삽입/겹침□ 모드 설정, 그리고 한영 전환 글쇠를 설정(¶ 1.12에서 추가)하는 것입니다. 별다른 설명이 필요없을 것입니다.

음소 결합 방식 설정

음소 결합 테이블(†쪽)을 편집하는 프로퍼티 페이지입니다. 고치거나 더하고 싶은 음소의 성분이 있는 곳을(초성, 중성, 종성) 선택한 후, 입력값을 직접 선택해서 등록해 주면 됩니다. 예를 들어 □여□에다가 □ㅣ□를 입력해서 □예□를 만들고 싶으면 □중성□을 선택하고 값을 입력받는 세 콤보 박스에 차례대로 □ㅕ□, □ㅣ□, □ㅖ□를 선택해서 □추가□를 누르면 되는 겁니다. 쉽죠? 반대로 등록된 값을 지우려면 지우고 싶은 값을 리스트박스에서 선택한 뒤 Del키를 누르거나 □삭제□를 누르면 됩니다.

그리고 본 프로그램은 가장 자주 쓰이는 음소 결합 테이블 구성표를 다섯 개 내장하고 있어 사용자가 편리하게 바로 불러다 쓸 수 있습니다.

□ 두벌식: 일반적으로 쓰이는 된소리, 겹모음, 겹받침 생성 조합이 모두 들어있습니다.

□ 세벌식: □두벌식□에 □ㄱ+ㄱ=ㄲ□, □ㅅ+ㅅ=ㅆ□이 추가되어 있습니다. □학교□라는 단어를 두벌식 자판으로 입력한다고 할 때, 결합 테이블을 □세벌식□으로 맞춰 놓으면 도깨비불이 생기지만 □두벌식□으로 맞춰 놓으면 생기지 않습니다. 반면 □세벌식□으로 맞춰 놓으면 두벌식 자판에서도 □깎□, □있□과 같은 글자를 Shift를 누르지 않고 입력할 수 있습니다.

□ 세벌식 자유 결합: 겹음소를 아무 순서대로 입력해도 조합이 됩니다. 예를 들어 ㅎ을 먼저 눌러도 ㅀ, ㄶ을 만들 수 있고, ㅓ를 먼저 눌러도 ㅝ를 만들 수 있습니다. 두벌식 자판에서는 □낙뢰□라는 단어를 입력할 때도 중간에 □낡□자가 생기기 때문에 굉장히 혼동을 줄 수 있습니다.

□ 세벌식 최종: 기본적으로 □세벌식□과 같지만, 세벌식 최종 자판은 모든 겹받침을 한 타에 입력할 수 있기 때문에 종성을 조합하는 경우를 뺐습니다. 그래서 이 설정을 쓰면 □무한 음소 수정□ 기능을 통해 □알□이란 글자를 □앎□을 거치지 않고 □암□으로 바로 고칠 수 있습니다.

□ 순아래 글자판: ㅖ, ㅒ는 두벌식과 세벌식 모두 입력하기 힘든 위치에 있습니다. □세벌식□ 설정에서 ㅖ, ㅒ, ㅑ, ㅕ를 ㅣ+모음으로 만드는 조합을 추가한 게 □순아래 글자판□ 설정입니다.

□역순 조합도 허용□이라는 옵션이 있습니다. (¶ 1.2에서 추가) 이것은 □ㄴ+ㅎ=ㄶ□이라는 값이 있다면, 그 역순인 □ㅎ+ㄴ=ㄶ□도 자동으로 허용하게 하는 옵션입니다. 즉, □세벌식 자유 결합□ 설정치를 훨씬 쉽게 만들 수 있게 해 줍니다.

음소 입력 순서 설정

음소 입력 순서 테이블(†쪽)을 편집하는 프로퍼티 페이지입니다. 사용하기가 □음소 결합 방식 페이지□보다 더 쉽습니다. □입력값□ 에디트박스에서 수열을 입력해서 □추가□를 누르면 값이 추가됩니다. 그리고 지우고 싶은 값을 리스트박스에서 선택해서 □삭제□를 누르면 선택된 값이 지워집니다.

내정값에는 다음과 같은 것이 있습니다.

□ 세벌식 모아치기: 20개가 넘는 키로 구성되어 있으며, 그야말로 한글 모아쓰기 입력의 무한자유를 구현해 주는 설정치입니다. 초성, 중성, 종성 어느 순서로나 마음대로 한글을 조합할 수 있습니다. 단, 두벌식 자판에서 이 설정치를 적용하면 입력기가 오동작할 수도 있습니다.

□ 이어치기: 일반 입력기가 한글을 입력하는 순서로, 키가 □1 1 2 2 3 3□ 하나만으로 구성되어 있습니다. 한 글자를 조합하는 방법은 한 가지만 존재합니다.

□ 풀어쓰기(겹음소 조합 가능): 겹음소의 조합을 허용하면서 한글을 풀어쓰게 합니다.

□ 완전 풀어쓰기: 어떤 조합도 하지 않고 한글을 완전히 풀어씁니다.

□모든 과정을 거쳐야 순서로 인정□ 옵션은(¶ 1.2에서 추가) <날개셋> 입력기가 제공하는 편리한 기능이 아니라, 기존 입력기의 방식을 수용하는 옵션입니다. 이 옵션이 켜져 있으면 □1 1 2 2 3 3□라는 값이 설정돼 있을 때, □1 2 3□을 거치지 않은 경우가 발견되면 곧바로 지금 글자 조합이 중단됩니다. □1 3□, □2 3□ 모두 허용이 안 되기 때문에, ㄱ+ㄴ, ㅏ+ㄱ 따위를 누르면 □이나 □이 되지 않고, □ㄱㄴ□, □ㅏㄱ□이 생성되는 것이죠.

글자판 설정

편집기가 사용하는 두 글자판을 편집하는 프로퍼티 페이지입니다. 두 자판이란 물론 편집창에서 한/영 키 또는 Shift+Space를 누를 때 번갈아가며 바뀌는 두 자판을 가리킵니다.

가장 먼저 글자판 이름과 글자판 종류를 바꿀 수 있습니다. 글자판의 종류에 따른 동작 방식 차이는 앞에서 이미 설명드렸습니다. 그리고 키보드 그림을 마우스로 두 번 누르거나 이 윈도우가 포커스를 받은 상태에서 편집하고 싶은 글쇠를 누르면 글쇠의 배당 문자를 편집하는 대화상자가 나타납니다. 로마자의 경우 대문자가 아랫글쇠를 나타냅니다. 영문 글쇠가 배당되어 있는 모습과는 반대임을 알아두세요.

□글쇠 위치□에서 편집하고 싶은 키를 누른 후 □배당할 글쇠-문자□에 배당하고 싶은 문자를 입력하십시오. 그리고 나서 □완료□를 선택해서 대화상자를 빠져나가거나, □글쇠 위치□로 가서 다른 글쇠를 계속 편집할 수 있습니다. 특수문자를 입력하려면 Ctrl+I를 누르면 됩니다. 특수 키를 배당하려면 □16진수로□란에 특수 키 코드를 입력하면 됩니다.

16진수로 2~e인 범위는 본 입력기가 특수 키를 배당해서 인식하는 영역입니다. 예를 들어 Shift+5에 □초성 삭제 키□를 배당하고 싶으면 □%□의 위치에 코드 번호 2를 배당하면 됩니다. 만약 글자판에 본 입력기가 제공하는 특수 키를 배당할 공간이 모자란다면 Ctrl+A, Ctrl+J처럼 Ctrl+문자 키 특수 키를 더 배당할 수 있습니다. 물론 Ctrl+N, Ctrl+I와 같이 다른 기능과 충돌하는 키에는 배당할 수 없지요. 특수 키의 번호 배당에 대한 설명은 □Ctrl글쇠에 배당할 특수 키□의 콤보 상자를 내려 보면 알 수 있습니다.

한편, 글자판은 파일로 저장하여 나중에 불러올 수 있습니다. 그리고 <날개셋> 라이브러리가 내장하고 있는 기본 글자판 6개를 사용할 수도 있습니다. Ngsdata.zip에는 이 프로그램이 읽어들일 수 있는 예제 글자판 파일이 있으므로 한 번 불러와서 써 보십시오.

□ North.key: 현재 북한의 표준 자판(두벌식)입니다.

□ Enhance3.key: 세벌식 최종 자판을 일부 변형하여 음소 삭제 등 특수 키를 배당한 자판으로, 제가 사용하는 자판입니다. Shift+T에 초성 삭제, Shift+5에 종성 삭제 키가 배당되어 있으며, Shift+7, Shift+8에는 종성을 왼쪽 오른쪽으로 옮기는 특수 키가 있고, Shift+,와 Shift+.에는 왼쪽 오른쪽 한글을 조합하는 상태로 만드는 특수 키가 있습니다.

□ Enhance2.key: 남한 표준 두벌식 자판에서 놀고 있는 윗글쇠의 일부에 특수 키를 배당한 자판입니다.

입력과 관련된 부가기능

1.2버전에서는 워드 프로세서처럼 간단한 상용구와 자동 교정 기능이 추가되었습니다. 다음 기능들은 ocx 컨트롤과는 무관하게 본 편집기 프로그램 차원에서 지원되는 기능입니다.

입력기 유형 (¶ 1.1에서 추가)

매번 입력기 설정 프로퍼티 시트를 꺼내서 여러 가지 설정을 일일이 바꾸는 건 무척 비효율적인 일입니다. 그래서 본 에디터는 현재 입력기 요소 설정의 전부나 일부를 파일로 저장해서 나중에 바로 불러올 수 있게 했고, 이 기능을 통해 제가 앞에서 말씀드렸던 □다양한 입력 방식□을 사용자가 편하게 골라 쓸 수 있게 했습니다. □한글-입력기 유형□을 선택하면 이 기능을 쓸 수 있습니다.

□새 유형□을 선택하면 이름을 입력받아 지금 입력기 설정을 저장할 수 있습니다. 입력기의 네 가지 구성 요소(각종 옵션, 음소 결합 테이블, 음소 입력 순서 테이블, 글자판) 중 필요한 사항만 저장할 수도 있습니다. 그밖에 유형의 이름을 바꾸거나 유형을 지울 수도 있고, 그리고 이미 있던 유형이 지금의 입력기 설정을 반영하도록 파일을 고칠 수도 있습니다. 유형은 MyEdit가 있는 디렉토리에 저장되며, 파일 이름이 그대로 유형 이름입니다. 단지 뒤에 set라는 확장자가 붙는다는 점만 다릅니다.

□ 세벌식 모아치기: 가장 평범한 환경. 세벌식 최종+모아치기.

□ 세벌식 무한음소 수정: 제가 3장에서 설명했던 기능이 모두 구현되어 있는 유형입니다. 세벌식 최종 자판에서 거의 쓰이지 않는 자리에 특수 키를 일부 배당한 □강화 세벌식□이라는 자판을 사용합니다.

□ 풀어쓰기: 지금 자판이 두벌식이든 세벌식이든 그대로 한글을 풀어쓸 수 있게 합니다.

상용구와 자동 교정 (¶ 1.2에서 추가)

본 프로그램에서 상용구를 동작시키는 글쇠는 Alt+K입니다. 준말을 입력하고 나서 Alt+K를 누르면 준말이 본말로 바뀝니다. 상용구 자료는 qidiom.txt (본 프로그램이 있는 디렉토리)에 있는 내용을 씁니다. 파일을 열어보면 파일이 어떤 구조로 되어있는지 이해가 바로 될 것입니다. 맨 첫줄에 자료 개수를 입력하고 다음 줄부터 준말와 본말을 번갈아가며 입력한 뒤, 이 파일을 저장합니다. 그다음 □삽입-상용구 정보 다시 읽기□ 명령을 실행해 주면 변경된 상용구 정보를 사용할 수 있습니다.

한편, 자동 교정 기능은 □삽입-빠른 교정 동작□ 옵션을 켜 놓으면 동작합니다. 자동 교정 데이터는 따로 있는게 아니라, □글 97의 qcorrect.dat를 본 프로그램이 사용합니다. (워디안의 빠른 교정 데이터가 97의 것과 같은지는 저도 모릅니다.) 그래서 □maked□라고 친 뒤 스페이스 바를 누르면 □made□로 바뀌고 □로보트가□라고 친 뒤 스페이스 바를 누르면 □로봇이□로 바뀝니다.

하지만 본 프로그램은 아직  받침만 있는 내용인 □-ㄹ 수 없다□ 따위는 인식하지 못하고, 엔터를 눌렀을 때는 빠른 교정이 동작하지 않는다는 한계가 있습니다. 빠른 교정 기능은 아직까지는 한글보다는 영어를 칠 때 더 편리한 것 같습니다.

특수 키 설명

본 입력기가 제공하는 특수 키는 다음과 같습니다. 있으면 편하겠다고 생각되는 특수 키가 있으면 Ctrl자리나 딴 곳에 배당해서 쓰면 됩니다. 단, 글자판 종류가 한글이나 로마자 자판이 아니고 □기타□일 때는 특수 키는 동작하지 않고, 그에 해당하는 아스키 번호 문자가 출력됩니다.

특수 키는 <날개셋> 입력기가 버전업됨에 따라 차츰 추가될 예정입니다.

끝글자 조합 (0x1)

커서를 줄 맨 끝으로 옮기고, 맨 마지막 글자가 한글이라면 그 글자를 조합하고 있는 상태로 만듭니다.

<날개|셋> 한글 입력기  →  <날개셋> 한글 입력기

특정 음소 삭제 (0x2~0x4)

3장에서도 설명이 되었습니다. 이 음소가 언제 입력되었든 상관없이 바로 그 음소를 지우고, 그 글자를 조합하는 상태로 만듭니다. 한글을 조합하고 있을 때는 언제든지 쓸 수 있지만, 조합하고 있지 않고 커서가 가리키는 한글을 지우는 건 □겹침□ 상태일 때만 동작합니다. 초성을 지우는 글쇠가 가장 유용할 것입니다. 다음은 초성을 지우는 키를 눌렀을 때의 모습입니다.

<날개셋> 한글 입력기  →  <날개셋> □글 입력기

이 상태에서 초성을 다시 입력할 수 있는 근거가 되는 원리가 □모아치기□라는 것은 이해할 수 있을 것입니다.

특정 음소를 글자 앞뒤로 빼기 (0x5~0xa)

이것 역시 3장에서 설명을 했습니다. 모아치기와 연동하는 기능이지요. 이 글쇠들 중에는 종성을 뒤로 빼는 글쇠가 가장 유용할 것입니다. □여름□이라고 칠 것을 받침을 먼저 눌러버려 □염□이 되었을 때, □ㅁ□을 뒤로 빼서 그 상태에서 □름□을 모아치기 원리로 완성하는 게 본 특수 키의 취지입니다. 이해가 가시죠?

커서 앞뒤 글자로 (0xb, 0xc, 0xf)

기본적인 원리는 3장에서 설명되었습니다. 커서를 앞 또는 뒤 글자로 옮기고, 이게 한글이면 그 글자를 조합하는 상태로 만들어 주는 글쇠입니다. 그런데 1.2에는 □커서 앞글자로 (2)□라는 특수 키가 0xf라는 번호에 또 추가되었습니다.

0xb와 0xf의 차이는 다음과 같습니다. 새로 추가된 0xf는 앞글자로 가서 글자를 고치고 나서 이 글자의 조합이 끝났을 때, 다음 글자의 조합을 그 글자 바로 뒤에서부터 하는 게 아니라, 다음 다음 글자에서 한다는 것이 다릅니다. 다음 예를 보십시오. □한글로□라고 칠 것을 □산글□이라고 쳤다고 칩시다. 커서는 □글□을 조합하고 있는 상태입니다. 그러면 0xf키를 눌러서 □산□을 조합하는 상태로 가는 게 좋겠죠. 그다음 초성을 지우는 특수 키를 눌러 □산□을 □□□으로 만든 뒤, □ㅎ□을 입력하면 세 타만에 앞 글자 □산□을 □한□으로 바꿀 수 있습니다.

산글  →  산글  →  □글  →  한글

그런데 문제는 그다음입니다. □로□를 치고 싶은데 커서는 □글□의 앞에 가 있습니다. 여기서 0xb와 0xf의 차이가 드러납니다. 이 상태에서 □ㄹ□를 누르면 0xb 특수 키는 □한ㄹ글□이 되지만, 0xf 특수 키는 □한글ㄹ□가 됩니다. 한 글자 건너뛴다고 말씀드렸죠? 그래서 0xf 특수 키를 쓰면 이런 타자가 가능해집니다. 앞 글자가 틀렸으면 일단 지금 글자부터 완성하고 나서 앞글자로 돌아갑니다. 그 글자를 고치고 나서 아무런 키 조작 없이 맨 끝 위치에서부터 타자를 원활하게 계속할 수 있는 거죠.

한글 조합 중단 (0xd, 0xe)

단순히 현재 한글 조합을 중단하고 커서를 한글 앞이나 한글 뒤에 놓는 특수 키입니다.

결론

기대되는 효과

한글 타자 초보에게

이 입력기는 컴퓨터로 한글의 원리를 어린이나 외국인에게 가르치는 데 더할 나위 없이 좋은 도구가 될 것입니다. 음절과 음소를 마음대로 오가는 데 아무런 제약이 없는 이 입력기로 한글을 자랑스럽게 입력해 보십시오. 세상에 글쇠 누르는 순서가 틀려도 글자가 만들어지고, 오타가 나도 그 성분의 음소만 다시 입력하면 오타가 고쳐지는 문자는 한글뿐입니다. 이런 편리한 기능은 한글을 너무나 한글답고 쉽고 편리하게 입력하게 해주기 때문에 타자를 얼마나 빨리 칠 수 있느냐를 떠나, 남녀노소를 막론하고 한글을 처음 배우는 외국인이나 타자를 처음 접하는 초보에게 큰 환영을 받을 것입니다. 우리의 것에 대한 자부심과 정보화의 편리함을 누리는 즐거움, 이 입력기가 그 기쁨을 두 배로 만들어줄 것입니다.

본 입력기는 기능이 많아서 사용법이 복잡하게 느껴질 수도 있습니다. 하지만 이 입력기는 언제까지나 인공지능이 아닌 일종의 기계입니다. 지정된 옵션대로, 지정된 음소 결합 규칙에 따라, 지정된 음소 입력 순서에 100% 충실하게 한글을 조합할 뿐입니다. 한글의 원리에 충실하게 만들어진 이 입력기는 어린이에게 한글의 오묘한 원리를 깨우치고, 논리력과 창의성, 한글과 나라 사랑하는 마음을 길러주는 데도 기여할 것입니다.

그리고 이 입력기를 사용했을 때 두벌식과 세벌식 자판의 능률이 얼마나 달라지는지 알게 된다면 세벌식에 대해 모르는 사람들도 선뜻 세벌식 자판으로 타자를 시작할 것입니다. 기존의 입력기를 썼을 때 두벌식과 세벌식의 능률이 2와 3정도였다면, 전 제 경험으로 미루어 봤을 때 이 입력기는 능률을 각각 최고 4, 9까지 끌어올려 줄 것으로 예상합니다. 최선과 최악의 경우를 비교하면 무려 네 배 이상 차이가 난다는 뜻입니다. 물론 같은 글을 치는데 걸리는 시간이 꼭 1/4 이하로 줄어든다는 것을 의미하지는 않겠지만, 비단 타속뿐만 아니라 타자수의 심리, 손가락의 피로 등 모든 요소를 감안하면 상대적으로 이 정도 차이까지 느낄 수 있을 것입니다.

타자에 능숙한 사람에게

이 입력기의 핵심 루틴이 □글, 윈도우, 리눅스 같이 대중화된 소프트웨어의 한글 입력기로 이식되고, 이 입력기를 사용하는 소프트웨어로 타자 대회를 개최한다면 우리 나라 국민 전체의 타자 속도와 타자 능률은 훨씬 올라갈 것입니다. 처음 보는 글을 자신의 최고 타자 속도로 오타 없이 10초 이상을 치는 사람은 사실 없으니까요. 국민들의 타자 속도가 향상되면 우리 나라의 전체적인 정보 생산 능력도 덩달아 올라가고, 이는 요약문에서 말씀드렸듯이 정보 생산성과 국가 경쟁력을 향상시키는 밑거름이 될 것입니다.

이 입력기의 성능은 글을 입력하는 시간이 길수록, 타자를 빨리 칠수록 두드러지며, 글을 입력해내는 속도나 능률면에서 두벌식 일반 입력기 사용자는 세벌식 <날개셋> 입력기 사용자와 도저히 경쟁하지 못할 것입니다. 두벌식이나 세벌식이나 그게 그거라는 말도 더 이상 나오지 못할 것입니다. 모아치기와 미완성 한글 입력 방지 및 무한 음소 수정 기능 등은 세벌식으로 자판을 바꾸는 충분한 동기를 사용자들에게 제공할 수 있습니다.

기존 입력기 사용자는 이 입력기를 많이 접해서 동작 방식에만 적응하면 됩니다. 이 입력기가 보완해줄 수 있는 오타가 났는데도 옛날처럼 무작정 지우면 별 능률이 안 오르겠죠. 그렇지만 동작 방식이 정말 한글 구성 원리에 잘 들어맞기 때문에 쉽게 적응할 것입니다. 이 입력기를 썼는데 별로 능률이 안 오른다고 생각하는 분은 기존 입력기로 글을 입력해 보면 옛날 입력기가 얼마나 둔하고 불편했는지 차이를 몸으로 느낄 수 있을 것입니다.

타자 속기를 할 필요가 있다면 본 입력기가 제공하는 특수 키를 자판에 배당하며 최적의 타자 환경을 구축해 보십시오. 본 입력기는 한글을 모아쓰는데 최적화되어 있지만 음소만 풀어써야 할 필요가 있다면 입력 순서 테이블을 고쳐서 풀어쓰기 전용 모드에서 입력을 하면 됩니다. 어떤 상황에서도 본 입력기는 한글을 입력하는 데 최상의 해결책을 제공할 것입니다.

소프트웨어 개발자에게

글을 입력하는 기능을 제공하는 프로그램은 화려한 기능을 제공하는 것도 중요하지만, 가장 기본적으로 나랏글을 편하고 능률적으로 입력할 수 있어야 합니다. 이런 점에서 이 입력기가 □글이나 이야기 같은 프로그램의 입력기로 이식된다면 이들 프로그램의 경쟁력은 크게 올라갈 것입니다. 더구나 자체 한글 라이브러리를 사용하는 국산 소프트웨어는 내부적으로 조합형 코드를 사용하기 때문에 MS 워드 같은 프로그램보다 이식하기에 더 유리한 위치에 있습니다.

꼭 워드 프로세서나 에디터가 아니어도 좋습니다. 통신 프로그램을 예로 들어보겠습니다. 이야기 2000이 세벌식 최종 자판을 100% 완벽하게 지원한다고 하자 실제로 세벌식 사용자들이 앞다투어 제품을 사고 단체 주문까지 검토하던 것을 저는 본 적이 있습니다. 그 동안 세벌식 최종 자판은 2바이트 특수문자 때문인지는 몰라도 완벽하게 지원하는 소프트웨어가 없다시피 했거든요. 이들은 모든 텍스트 파일들을 이야기 워드로 연결시켜 놓기까지 했습니다. 자판을 하나 추가해서 얻은 호응이 이 정도인데 고성능 한글 입력기까지 지원하는 통신 프로그램이 있다면 그 프로그램은 두벌식 사용자나 세벌식 사용자들 모두에게서(특히 타자방이나 대화방을 주로 이용하는 젊은 네티즌) 폭발적인 인기를 누릴 것입니다.

<날개셋> 입력기의 기능은 비단 응용 프로그램에만 한정되지 않습니다. 본 프로젝트에 있는 ActiveX 컨트롤이 그대로 혹은 기능이 일부 개선되어 이메일 쓰기나 전자 게시판을 지원하는 상용 사이트에서 쓰인다면, 사용자들은 글을 워드 프로세서로 미리 쳐서 웹으로 전송하기보다는 웹에서 직접 글을 입력하려고 할 것이고, 그러면 그 사이트의 방문 시간도 늘어날 것입니다.

제안

다음은 <날개셋> 입력기가 운영체제의 입력기로 이식되고 제 성능이 완벽하게 발휘되도록 하기 위해 한글 프로그래밍 관점에서 제가 드리고 싶은 제안입니다.

가장 먼저 세벌식 자판이 단독 표준이든 두벌식과 복수 표준이든 나라를 대표하는 표준이 되어야 합니다. 세벌식 자판이 우수함은 의심의 여지가 없는 사실입니다. <날개셋> 입력기에도 세벌식 자판과 관련되거나 세벌식 자판의 성능을 이용한 기능을 빼면 절반 정도밖에 성능을 발휘하지 못합니다. 더구나 세벌식의 표준화는 자판 통일의 관점에서도 매우 중요한 제안입니다.

최근 남북 정상 회담으로 통일에 대한 관심이 어느 때보다도 고조돼 있습니다. 남북한이 완전히 통일이 되려면 정치적으로도 하나가 되고, 경제도 균형을 이루어야겠지만, 무엇보다 말글부터가 하나로 되어야 할 것입니다. 특히 기계로 한글 정보를 생산하는 밑바탕이 되고, 세계에 대한민국 정보화 수준을 나타낼 한글 글자판은 하루빨리 통일되어야 할 것입니다. 막대한 비용을 들여 통일 자판을 또 제정할 필요는 전혀 없습니다. 이런 시대적 조류를 계기로 군사 정권 때 잘못 섰던 한글 표준이 지금이라도 바로잡혀야 하지 않을까요?

둘째, 공통적인 한글 처리 루틴을 운영체제 차원에서 공유하는 길이 열려야 합니다. 본 입력기 라이브러리는 독창적인 입력 기능뿐만 아니라, 한글 라이브러리라면 공통적으로 갖추어야 하는 기능도 많이 제공하고 있습니다. 예를 들어 완성형과 조합형을 변환하는 테이블이나 텍스트 파일의 한글 코드를 판단하는 루틴 정도는 제대로 된 한글 관련 프로그램을 만들 때 반드시 필요합니다. 운영 체제 환경이 이만큼 발전했다면, 한글 처리를 담당하는 코드와 리소스를 응용 프로그램들이 공유할 수 있는 공식적인 길이 운영체제 차원에서 열려야 하지 않을까요? 윈도우 SDK가 유니코드와 완성형을 서로 변환하는 API를 제공하듯, 완성형과 조합형을 변환하는 기능도 운영체제가 지원해 주면 좋을 것입니다. 저는 본 입력기 클래스 라이브러리가 운영체제 SDK와 함께 제공되어도 손색이 없다고 봅니다.

셋째, 유니코드에 미완성 한글 1148자 영역이 표준으로 배당되어야 합니다. 충분히 짐작하셨겠지만 완성된 한글을 모두 구현할 수 있다고 해도, 타자를 하는 과정에서 필연적으로 나타나게 되는 □□, □□과 같은 미완성 한글을 나타내는 방법이 없다면 <날개셋> 입력기는 거의 기능을 발휘하지 못합니다. ㄱ과 ㄱ이 구분이 안 되면 세벌식 자판 배열을 그리는 일조차 난감해집니다. 한글을 조합할 때 쓰이는 낱음소와 특수문자에 있는 한글 낱음소도 구분될 수 있어야 합니다. 이미 정해진 유니코드 한글 배열 순서를 바꾸기가 어렵다면 사용자 정의 영역에 추가하는 방식이라도 통일이 되어야 할 것입니다. (Handemo.zip의 Unicode.txt 파일을 보십시오.)

넷째, 조합형 코드 데이터를 클립보드로 공유하는 방법이 통일되어야 합니다. 아직까지 우리에게는 유니코드보다는 조합형이나 완성형 코드가 더 친숙합니다. <날개셋> 에디트 컨트롤과 □글이 조합형 한글을 자유롭게 교류할 수 있는 까닭은 두 프로그램이 □HNC/KSSM□이라는 클립보드 포맷을 등록하여, 조합형 코드를 클립보드에 완성형과는 별도로 저장하기 때문입니다. 이 명칭이 개발자 사이에 통일이 되고 널리 알려져야 비록 운영체제는 완성형을 쓰지만 조합형 코드가 명맥을 유지할 수 있고, 응용 프로그램들이 조합형 코드를 통해 번거로운 변환 과정 없이 한글 데이터를 공유할 수 있을 것입니다.

맺음말

로마자 입력기는 키보드를 누르는 대로 글자가 나오고, 철자법이 불규칙하기 때문에 영어의 특성을 살린 빠른 교정기나 상용구 기능 외에 더 입력 성능을 개선시킬 방법이 없습니다. 가나나 한자 입력기는 소리문자를 입력받아 변환해야 하니 말할 것도 없이 비능률 그 자체지요. 그러나 한글은 기계와 잘 어울리는 구조로 되어 있고, 얼마든지 독창적으로 발전시킬 길이 있습니다. 어차피 오토마타를 만들어야 한다면 로마자보다 훨씬 우수하게 만들 수 있죠. 저는 한글 프로그래밍의 매력이 이런 데 있지 않나 생각해 봅니다. 늘 한글이 독창적이고 과학적인 문자라고 말만 하면서 로마자나 한자 처리하는 식으로 한글을 처리해왔으니 이제까지 한글이 완성형 코드에 네모꼴 글꼴, 두벌식 자판을 쓰는 불편한 입력기 따위에 힘을 못 쓴 것이 아닐까요?

지금과 같은 인터넷 정보화 시대에는 얼마나 능률적이고 빠른 문자 생활을 하느냐에 나라와 문화의 존망 여부가 달려있다고 해도 과언이 아닙니다. 한자를 병용해 가며 채팅하는 사람이 우리 나라에 있을까요? 이건 비단 정보 생산성만을 얘기하는 건 아닙니다. 21세기에는 경제 문화 강대국의 언어에 휘말려 세계 언어의 90%가 사멸할 것이라고 다들 말합니다. 경제 위기보다 무서운 것은 언어 위기이며, 실리콘 밸리 벤처 기업들의 생존 경쟁보다 더 치열한 것은 문화의 생존 경쟁입니다. 이럴 때, 다루기 불편하고 느린 문자를 쓰는 언어와 그 언어로 이루어진 문화는 필연적으로 도태할 것입니다. 우리는 어서 한글의 우수성과 혜택의 사각 지대에서 나와 컴퓨터에 한글을 올바로 자리잡고 21세기 찬란한 한글 문화를 꽃피워야 할 것입니다.

100년이 넘게 걸려 이룩되었던 서양 문명을 우리 나라가 불과 30년만에 따라잡고, 이 땅에 민주주의를 지금과 같이 자리잡은 데는 과학적이며 쉽고 간편하여 누구에게나 지식을 빠르게 전달하게 해준 한글의 공이 컸습니다. 우리 나라에 기독교가 1세기동안 역사에 유래가 없이 빠르게 전파된 데에도, 불교나 유교 경전과는 달리 한글로만 쓰인 성경이 일등공신을 했습니다. 세계에서 가장 낮은 우리 나라 문맹률은 미국, 영국, 일본과 같은 선진국들도 부러워하고 있습니다. 우리 나라가 한글날을 기념일로 끌어내렸던 1990년 한글날에 유네스코(국제 연합 교육 문화 기구로, 국제 정보 올림피아드를 주관하기도 합니다.)는 국제적으로 글눈을 밝히는데 공을 세운 사람이나 단체에 주는 상인 <세종대왕상>을 제정하고, 첫 시상식을 가졌습니다. 유네스코는 1997년 훈민정음을 인류가 영원히 보전해야 할 문화 유산으로 지정하기도 했으며, 최근에는 사라져 가는 미국 인디언들의 언어를 한글로 채록하여 보존하려 하는 <세종 프로젝트>를 추진중이라고 합니다.

비록 지금 한글이 비과학적인 정책에 제 힘을 못 쓰고 있다고 해도, 한글은 그 남은 힘만으로도 지금까지 우리 나라를 미국 못지않은 정보화 강국으로 끌어올렸고, 앞으로도 인터넷 시대의 가장 믿음직스러운 꽃이 될 것을 약속하고 있습니다. 지금 상태가 이러한데 하물며 한글을 옭아매고 있던 구시대 족쇄들이 모두 사라져 100% 한글다운 빠르고 능률적인 글살이가 컴퓨터에서 실현된다면, 우리 나라가 세계 제일의 정보 선진국이 되고, 우리의 문화가 세계를 누비는 건 시간 문제가 될 것입니다. 저는 이 모든 이상을 담고 <날개셋> 입력기를 개발했습니다. <날개셋>에 대해서 한글에 관심 있는 분들의 진지한 비판을 바랍니다.

하루빨리 세벌식이 표준이 되길 바라며

21세기를 다섯 달 앞둔 어느 날 씀

부록

세벌식 최종 자판 배열

자판 배열

※ ~ * `	ㄲ ! ㅎ 1	ㄺ @ ㅆ 2	ㅈ # ㅂ 3	ㄿ $ ㅛ 4	ㄾ % ㅠ 5	= ^ ㅑ 6	□ & ㅖ 7	□ * ㅢ 8	' ( ㅜ 9	~ ) ㅋ 0	; _ ) -	+ + > =	\ | : \

ㅍ Q ㅅ	ㅌ W ㄹ	ㄵ E ㅕ	ㅀ R ㅐ	ㄽ T ㅓ	5 Y ㄹ	6 U ㄷ	7 I ㅁ	8 O ㅊ	9 P ㅍ	% { ( [	/ } < ]

ㄷ A ㅇ	ㄶ S ㄴ	ㄼ D ㅣ	ㄻ F ㅏ	ㅒ G ㅡ	0 H ㄴ	1 J ㅇ	2 K ㄱ	3 L ㅈ	4 : ㅂ ;	□ " ㅌ '

ㅊ Z ㅁ	ㅄ X ㄱ	ㅋ C ㅔ	ㄳ V ㅗ	? B ㅜ	- N ㅅ	" M ㅎ	, < , ,	. > . .	! ? ㅗ /

<한글 문화원, 1991>

영문 자판과의 글쇠 대조표 (~=Shift)

ㄱ	K
ㄴ	H
ㄷ	U
ㄹ	Y
ㅁ	I
ㅂ	;
ㅅ	N
ㅇ	J
ㅈ	L
ㅊ	O
ㅋ	0
ㅌ	'
ㅍ	P
ㅎ	M

ㅏ	F
ㅐ	R
ㅑ	6
ㅒ	~G
ㅓ	T
ㅔ	C
ㅕ	E
ㅖ	7
ㅗ	V or /
ㅛ	4
ㅜ	B or 9
ㅠ	5
ㅡ	G
ㅣ	D

ㄱ	X	ㅀ	~R
ㄲ	!	ㅁ	Z
ㄳ	~V	ㅂ	3
ㄴ	S	ㅄ	~X
ㄵ	~E	ㅅ	Q
ㄶ	~S	ㅆ	2
ㄷ	~A	ㅇ	A
ㄹ	W	ㅈ	#
ㄺ	@	ㅊ	~Z
ㄻ	~F	ㅋ	~C
ㄼ	~D	ㅌ	~W
ㄽ	~T	ㅍ	~Q
ㄾ	%	ㅎ	1
ㄿ	$

예) 방안 → ;FAJFS   과학 → K/FMFX

클래스 라이브러리 헤더

Han.h (CHanLetter, CHanString 등)

/*

<날개셋> 만능 한글 입력기 클래스 헤더

제 17회 한국 정보 올림피아드 공모부문 출품작

Programmed By 김용묵 (sebulsik@dreamwiz.com)

버전 1.01 - 2000년 9월 1일

버전 1.2  - 2001년 9월

*/

#ifndef HAN_H_INCLUDED

#define HAN_H_INCLUDED

#ifndef __cplusplus

#error This code requires C++ compilation

#endif

#ifndef NGSAPI

#define NGSAPI _declspec(dllimport)

#endif

//조합형 한글 처리 클래스

/*

중요한 정보: 한글 자소 코드

초성: NL(1) ㄱ(2) ㄲ(3) ㄴ(4) ㄷ(5) ㄸ(6) ㄹ(7) ㅁ(8) ㅂ(9) ㅃ(10) ㅅ(11) ㅆ(12)

ㅇ(13) ㅈ(14) ㅉ(15) ㅊ(16) ㅋ(17) ㅌ(18) ㅍ(19) ㅎ(20)

중성: NL(2) ㅏ(3) ㅐ(4) ㅑ(5) ㅒ(6) ㅓ(7) ㅔ(10) ㅕ(11) ㅖ(12) ㅗ(13) ㅘ(14)

ㅙ(15) ㅚ(18) ㅛ(19) ㅜ(20) ㅝ(21) ㅞ(22) ㅟ(23) ㅠ(26) ㅡ(27) ㅢ(28) ㅣ(29)

종성: NL(1)  ㄱ(2) ㄲ (3) ㄳ(4) ㄴ(5) ㄵ(6) ㄶ(7)  ㄷ(8) ㄹ(9) ㄺ(10) ㄻ(11) ㄼ(12)

ㄽ(13) ㄾ(14) ㄿ(15) ㅀ(16)  ㅁ(17)  ㅂ(19) ㅄ(20) ㅅ(21) ㅆ(22)  ㅇ(23)  ㅈ(24)

ㅊ(25)  ㅋ(26) ㅌ(27) ㅍ(28) ㅎ(29)

*/

enum EmptyUnit { cho_=1, ju_=2, jo_=1 }; //빈 음소를 나타내는 코드

//조합형 한글과 관련된 자료형

typedef char JSTR, *LPJSTR;

typedef const char *LPCJSTR;

//한글 한 글자 크기는 2바이트

#define HGSIZE 2

class NGSAPI CHanLetter {

protected:

union { WORD wImg; BYTE chLet[2];} m_Let;

//외부 한글 코드를 이 클래스가 쓰는 조합형으로 변환하여 저장. 오버라이드 가능

virtual void ToInternal(WORD n);

//반대. 외부 코드로 바뀐 값을 리턴한다..

virtual WORD ToExternal(WORD n) const;

public:

//조합형 한글 음소 변환과 관련된 정적 상수 배열

const static WORD m_nChoToJong[]; //초성과 종성이 대응하는 테이블

const static int m_nChoIdx[]; //음소번호를 서열로 바꾸는 테이블

const static int m_nJungIdx[];

const static int m_nJongIdx[];

const static char m_chChoSymb[];

const static char m_chJungSymb[];

const static char m_chJongSymb[];

CHanLetter(); //빈 문자 생성

CHanLetter(LPCTSTR pStr); //문자열에서 읽어옴

CHanLetter(WORD num); //숫자로

CHanLetter(int Cho, int Jung, int Jong=jo_); //음소 지정

WORD operator =(WORD wNum);

LPCTSTR operator =(LPCTSTR pStr);

void Read(LPCTSTR pStr);

//워프를 안 하는 입력

void SetValue(WORD wNum);

//초성자모 처리

int GetJong() const;

int GetCho() const;

int GetJung() const;

BOOL IsOnlyCho() const;

BOOL IsOnlyJung() const;

BOOL IsOnlyJong() const;

BOOL IsJohapChar() const;

BOOL IsEmptyHan() const;

BOOL IsCompleted() const; //완성된 글자인가? (초+중, 초+중+종)

BOOL IsHanja() const; //한자인가?

BOOL IsSpecial() const; //특수문자인가?

void MakeHan(int nCho, int nJung, int nJong);

void Apply(CHanLetter let);

void SetJong(int n);

void SetCho(int n);

void SetJung(int n);

//출력

operator WORD() const;

void Write(LPSTR pStr);

//워프를 안 하는 출력

WORD GetValue() const;

//오버라이드 가능한 함수

virtual BOOL IsValidHan() const; //범위에 맞는 한글인가.

//대소 비교. 음소 번호가 뒤죽박죽이 됐을 때만 오버라이드하면 된다.

virtual int Compare(CHanLetter let) const;

//이런 음소로 이루어진 글자가 코드에 배당되어 있나 판단.

//기본적으로 이 함수는 언제나 TRUE를 리턴한다. 조합형 코드니까

//어떤 글자든 표현할 수 있다. (IsValidHan()도 맞다고 전제함.)

virtual BOOL IsInCode(int nCho, int nJung, int nJong) const;

void Display(LPSTR str="") const; //디버깅용

};

class NGSAPI CUniHanLet: public CHanLetter {

protected: //조합<-> 유니코드 변환하는 루틴만 오버라이드해 준다.

void ToInternal(WCHAR n); WCHAR ToExternal(WORD n) const;

public:

BOOL IsHanja() const; BOOL IsSpecial() const;

};

class NGSAPI CKsHanLet: public CHanLetter {

protected: //조합<-> 완성형 변환.

void ToInternal(WCHAR n); WCHAR ToExternal(WORD n) const;

//완조 변환 테이블 리소스 저장변수

//확장완성형 한글 저장 테이블

static LPWORD m_lpwTab; static LPWORD m_lpwExtKs;

public:

BOOL IsInCode(int, int, int) const;

BOOL IsKsHangul() const; //이 글자가 2350자 안에 있는 한글인가.

//테이블을 초기화한다. CKsHanLet쓰기 전에 반드시 호출해 줄 것.

static BOOL EnableTable();

//테이블 참조 함수

static WORD GetKs2KssmAt(int nIndex); //이 함수를 쓰기 전에 EnableTable() 호출했는가?

static WORD GetExtKsAt(int nIndx);

};

//한글 출력 라이브러리

//한글 코드 상수

#define HC_UNICODE 3

#define HC_WAN 2

#define HC_JOHAP 1

#define HC_ENG 0

//비트형태의 스타일을 다루는 클래스

class NGSAPI CStyle {

protected:

DWORD m_dwStyle;

public:

CStyle(DWORD val=0);

DWORD Get() const;

void Set(DWORD val);

void ToggleStyle(DWORD val);

BOOL IsOn(DWORD val) const;

BOOL IsEveryStyleOn(DWORD val) const;

void SetStyle(DWORD val, BOOL bTurn); //지정한 옵션을 켜거나 끈다.

};

class CHanInput;

//한글이 들어간 MBCS 스트링을 다루는 클래스 (단, 메모리는 사용자가 직접 할당해줘야 함!)

class NGSAPI CHanString {

protected:

LPBYTE m_szBuf;

public:

BOOL Replace(int pos, LPCSTR with, int orglen);

CHanString(LPBYTE pStr=NULL);

CHanString(LPCSTR pStr);

LPBYTE operator +=(int nLen);

LPBYTE operator =(LPBYTE pStr);

LPBYTE operator =(LPSTR pStr);

operator LPBYTE() const;

int GetNearestHan(int nCur) const; //가장 앞 가까이에 있는 글자 위치를 구함

int GetNearestBackHan(int nCur) const; //가장 뒤 가까이에 있는 글자 위치를 구함

//금칙처리, 문단정렬 고려해서 다음줄로 자를 위치 구함

int GetWrapPos(int nLen, DWORD dwStyle) const;

//n번째 글자가 속하는 단어의 시작 위치, 다음 단어의 시작 위치를 되돌림

int GetCurrentWordPos(int n) const;

int GetNextWordPos(int n) const;

//한글 속에 있는 알파벳은 찾지 않는다. 문자열 검색.

int Find(LPBYTE, DWORD) const; //DWORD인자는 음소검색을 수행할지 여부

int GetCharLen() const; //한글을 한 자로 쳐서 문자열 길이를 얻는다. MBCS용

int DetermineCode() const;

LPBYTE WanToJohap(); //코드변환

LPBYTE JohapToWan();

//ㄱㅏㅁ -> '감' 결합해줌. 몇가지 옵션을 받아서. DWORD는 한글아닌 문자 무시할지 여부

LPBYTE MixUnits(DWORD, CHanInput&, int bufchars);

LPBYTE MakeReverse(); //홍 길동 -> 동길 홍

virtual BOOL IsHangul(int n=0) const; //2바이트 한글자인가 판단

int GetCharSizeAt(int n=0) const; //한글인 경우 2, 영어인 경우 1

};

//리소스 데이터를 얻는 매크로

#ifdef _WIN32

#define GetResourceData(Category, ID) \

::LockResource(::LoadResource(AfxGetResourceHandle(), \

::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(ID), Category)) )

#else

LPVOID GetResourceData(LPSTR szCategory, UINT nID);

#endif

//Ex range: 0일반, 1키 스타일, 2컨트롤

//NOTE: 한글 키보드의 조건: 모든 음소가 자판에 배당되어 있어서

//어떤 한글도 만들어낼 수 있어야 한다.

struct HANKEYBRD {

char m_szName[32]; int m_nType;

//키 데이타

WORD m_wKey[94]; BYTE m_byCtrlKey[94], m_byStyle[94];

};

#include "han.inl"

#endif

Hanedit.h (CHanInput, CHanEditor 등)

/*

<날개셋> 만능 한글 입력기 클래스 헤더

제 17회 한국 정보 올림피아드 공모부문 출품작

Programmed By 김용묵 (sebulsik@dreamwiz.com)

버전 1.01 - 2000년 9월 1일

버전 1.12 - 2001년 5월 14일

버전 1.13 - 2001년 6월 29일

버전 1.2  - 2001년 9월

*/

#ifndef HANEDIT_H_INCLUDED

#define HANEDIT_H_INCLUDED

#include "han.h"

class NGSAPI CHanKeybrd {

protected:

char m_szName[32]; int m_nType;

//키 데이타

WORD m_wKey[94]; BYTE m_byCtrlKey[94], m_byStyle[94];

const static char m_chShiftedKey[95];

const static char m_chUnderKey[48]; //글쇠 테이블

public:

CHanKeybrd();

CHanKeybrd(const HANKEYBRD& from) { Import(&from); }

CStyle m_styProp;

enum KeyStyle {

styPreventComp=1 //조합 방지

};

enum KeybrdType { //키보드 종류를 나타내는 상수

kbAscii=1, kbHan2, kbHan3, kbEtc

}; //영문(캡스록영향받음), 한글두벌식, 세벌식, 기타 자판임.

enum StockKeybrd { //DLL이 기본 지원하는 자판

kbd3bFinal, kbd3b390, kbd3bNoshift, kbd2bStd, kbdQwerty, kbdDvorak

};

//이 문자에 해당하는 키보드 키를 되돌린다. 이런 문자가 배당되지 않았다면 리턴값은 0.

//인라인 함수이다.

int FindKey(WORD let) const;

//키보드 자체와 관련된 함수

static char GetShiftedKey(UINT nChar);

static BOOL IsUnderKey(UINT nChar);

HANKEYBRD *Export(HANKEYBRD *to=NULL)

{

if(to==NULL) return (HANKEYBRD *)this;

else { ::CopyMemory(to, this, sizeof(HANKEYBRD)); return to; }

}

void Import(const HANKEYBRD *from) { *((HANKEYBRD *)this)=*from; }

BOOL LoadKeyboard(int nID); //기본내장 자판 6개 포인터를 얻는다.

int GetType() const;

void SetType(int);

BOOL IsHanKeyboard() const;

//글쇠 배당, 배당된 문자 얻어오기

WORD GetCharAt(int key) const;

void SetCharAt(int key, WORD wNewChar);

//확장 영역의 글쇠까지 읽고 쓰기

WORD GetCharAtEx(int key, int range) const; //이 키에 배당된 문자

void SetCharAtEx(int key, int range, WORD wNewChar);

void GetName(LPSTR pStr) const;

void SetName(LPSTR pStr);

//자판을 불러오고 저장한다.

void ReadFromFile(CFile& f);

void SaveToFile(CFile& f) const;

};

//NOTE: CHanInput클래스가 전제하고 있는 것

//1. 아무리 복잡한 한글도 6타면 입력된다. 배열사이즈를 결정하는 중요한 상수

//2. 음소별 결합은 세벌로 최대 두 번이다. 즉, 1 1 1 2 3같은  결합순서는 지원되지 않는다.

//3. 문자는 MBCS체계로, 한타에 최대 2바이트를 입력한다.

#define HAN_MAXSTEP 6

#define HEDIT_BUF   1024

typedef WORD (CALLBACK *CHARGETPROC)(UINT key, LPVOID context, int pos);

typedef WORD (CALLBACK *GETCANDIDATEPROC)(WORD orig, LPWORD data, int num, LPVOID context);

//한글 입력기 클래스 - 이 프로젝트의 심장부라고 할 수 있다.

class NGSAPI CHanInput {

protected:

CHanKeybrd m_Kbd;

WORD m_wInter, m_wCompl, m_wSynchr; //생성중인 글자, 완성된 글자, 동시완성글자

CHanLetter m_Let, m_OvrLet; //키입력 한글, 음소수정대상한글

//입력기 임시 스타일. 한 글자를 조합하고 있는동안만 유효하다 그 글자가

//완성되면 사라지는 스타일.

enum ContemporaryStyle {

itnJungCompNot=1, //겹모음 조합을 하지 말것.

itnUnitOvwr=2 //음소수정 모드를 시작한다. ('안'서 ㅅ 누르면 '산')

};

CStyle m_styEtc; //지금 글자 입력할 때만 적용되는 임시 스타일(내부적으로 관리)

//선택된 타자과정 테이블의 비트열

DWORD m_dwChosenWay; //타자과정에서, 현재 타자과정이 아닌 순서를 빼는 체크 비트

/*이 두 변수, 글자조합 단계를 기록하는 중요한 변수인데, 차이점은 다음과 같다.

m_nState: 입력단계상의 순서이다. 1 1 2 2 3 3에서 종성이 들어왔다면 이 값은 0부터

시작해서 4가 된다.

한편 m_nStep은 무조건 한 타가 들어올 때마다 1씩 늘어난다. 스택에 쌓인 단계를

나타낸다.*/

int m_nState, m_nStep;

CHARGETPROC m_pfnInfoFunc; LPVOID m_lpCallData; //콜백함수 설정

DWORD m_dwOtherInfo; //부가정보. Clear()과 관계없이 값이 유지됨.

//생성 과정을 담은 스택(Bksp눌렀을 시)

//wLet: 직전 글자, wLastKey: 직전에 눌러진 키, nState: 직전의 상태, dwWay: 선택된 과정테이블

//wLastChar: 직전에 눌러진 키문자

//wLastKey와 wLet은 음소지우는 것뿐만 아니라 도깨비불 처리에도 쓰인다.

struct {

WORD wLet, wLastKey, wLastChar; int nState; DWORD dwWay, dwEtc;

} m_Stack[HAN_MAXSTEP+1];

static WORD CALLBACK DefaultCallback(UINT, LPVOID, int);

public:

int GetKeystroke(CHanLetter let, LPWORD lpData) const; //현재 글자가 입력된 순서 키스트로크를 얻음

CHanKeybrd GetKeybrd() const;

void SetKeybrd(CHanKeybrd& kbd);

void DeleteUnit(int nType);

void ChangeUnit(int nType, int nNumb, UINT nKey=0);

BOOL IsAbleToMix(CHanLetter KeyLet, LPINT htype=NULL, LPINT hnum=NULL, LPINT final=NULL) const;

BOOL IsOtype(CHanLetter let) const;

//음소 결합 테이블.

static WORD m_nChoConv[10][3]; static WORD m_nJungConv[20][3]; static WORD m_nJongConv[30][3];

static char m_chTypeWay[32][HAN_MAXSTEP]; //타자과정 테이블

//음소결합 테이블 얻어옴: n=0 두벌식, 1 세벌식 2 자유 결합 3 세벌최종 4 순아래

static void LoadMixTable(int n, WORD (*cho)[3]=m_nChoConv, WORD (*jung)[3]=m_nJungConv,

WORD (*jong)[3]=m_nJongConv);

//입력순서 테이블을 얻어옴: n=0 모아치기 1 이어치기 2 겹음소 풀어쓰기 3 홑음소 풀어쓰기

//4 두벌 불완전 모아치기

static void LoadOrderTable(int n, char (*arg)[6]=m_chTypeWay);

enum InputStyle { //오토마타 동작방식을 제어하는 스타일

styBkspUnit=1, //Bksp는 한글을 음소단위로 삭제할 것

stySepaOw=2, //ㅗ와 ㅜ는 /와 9로만 겹모음 가능(세벌식 specific)

styReserveShift=4, //시프트 미리 눌러두기

styChoJong2bul=8, //두벌식에서 자음이 연달아 들어왔을때 동작방식

styBkspAttach=16, //Bksp 앞글자 달라붙기

styForceOtype=32, //미완성한글 입력방지

styChoOnly=64, //무한음소수정, 초성만 받아들이기

styUnitEdit=128, //음소 단위 수정

styReplUnit=256, //(미완성한글 입력방지 등 옵션에서) 음소 바꾸기

styNumber=512, //Numlock 숫자 키 윗글쇠를 아랫글쇠처럼(세벌식 specific)

styComplBkspUnit=1024, //이미 완성된 글자도 음소 단위로 삭제

styBkspAssim=2048, //한글조합상태가 아니면 Shift+Bksp를 Bksp와 같게

styOrderExclu=4096, //음소결합순서. 1 1 2 2 3 3에서 1 1 3 3을 허용안함

styReverseMix=8192, //음소결합테이블 역순조합도 모두 허용함

};

CStyle m_styProp; //언제까지나 적용되는 입력기 옵션

CStyle m_styProp2; //옵션이 아주 많아질 때를 대비하여

//입력기가 동작 과정에서 상태를 바꾸는데 쓰이는 스타일

//CPreparePushKey와 CHanEditor그리고 클래스 자신만 참조함.

enum InputerTempStyle {

itnRsrvBkspExpt=1, //숫자 윗글쇠에 대해서 Shift예약기능 적용안시킴

itnBksp2=2, //Shift+Bksp가 눌러진 효과를 낸다.

itnCallBack=4, //이 함수가 PushKey에 의해 호출된 상태다.

itnShift=8, //시프트 플래그가 켜졌다.

};

CStyle m_styTemp;

enum PushKeyResult { //PushKey함수가 리턴하는 값

pkEndCmp=1, //입력 중이던 글자가 완성됐다. (커서+1)

pkWithChar=2, //새로 들어온 글자까지 완성됐다. (커서+1)

//Bksp키 관련

pkBkspUsed=4, //백스페이스가 음소를 지우는데 쓰였다. (...)

pkGoBack=8, //커서를 한글 글자 앞으로 옮길 것. (커서-1)

pkGoBackTwice=16, //커서를 두 칸 앞으로 옮길 것.

pkPartial=32, //음소 일부만 지운다.

//기타

pkUser=64, //특수키 따위. 이 키의 처리는 에디터에게 달려 있다.

pkIgnored=128, //현재 들어온 키가 무시됐다.

};

CHanInput();

//결합 함수 - 특별한 한글 입력상태로 들어간다.

BOOL AttachHan(CHanLetter let);

void SetOvrChar(CHanLetter let);

/*음소수정, 글자 달라붙기 등... 이 입력기가 제공하는 기능 중에는 입력기 혼자만으로는

동작할 수 없고 입력기를 조종하는 에디터와 통신을 해야 지원할 수 있는 것도 있다.

이때 입력기는 이 콜백 함수를 호출해서 그 에디터의 커서가 가리키고 있는 글자,

혹은 커서 앞에 있는 글자를 알아온다.

이 함수는 입력기가 현재 처리하려고 하는 키, 그 정보를 얻어오는 콜백 함수의 포인터와,

함수를 호출할 때 입력기가 같이 보내줄 부가 정보를 설정하는 역할을 한다.*/

void SetInfoFuncAndData(CHARGETPROC pFunc, LPVOID lpData);

//한글 입력과 관련된 함수

BOOL IsMakingChar() const; //글자 생성중인가.

BOOL IsOvrwrMode() const; //음소수정 모드인가.

WORD GetCompletedChar() const; //완성된 글자 얻음

WORD GetMakingChar() const; //순수하게 키보드를 눌러 조합중인 글자 얻음

WORD GetComposingChar() const; //음소수정 대상 글자까지 고려해서 현재 만들고있는 글자..

WORD GetSecondChar() const; //동시에 완성된 글자 얻음

void Clear(); //오토마타 상태 초기화

//PushKey 호출하기 전에 키 정보를 처리할 기회를 준다.

//이 키 또는 문자를 집어넣음. 완성된글자에 대한 정보 둘을 되돌림

//wChar가 디폴트 인자가 아니면 눌러진 키와는 상관없이 지정한 문자를 입력

virtual int PushKey(UINT nKey, WORD wChar=0xffff);

//키코드 번역

virtual DWORD IdentifyKey(UINT nKey, UINT nFlags, LPBYTE byArr) const;

//PushKey 호출하기 전에 키 정보를 처리할 기회를 준다.

virtual UINT ProcessKey(UINT nKey, UINT nFlags, DWORD dwIdentified, LPBYTE byArr);

//입력기에 대한 추가정보 얻음.

//현재버전은 pkUser스타일 다음에 특수키 번호를 얻는데만 쓰임.

DWORD GetAdditionalInfo() const;

//오버라이드 가능한 함수

//Get..Char에서 문자를 변환할 기회를 줌. (한글코드, 영문 전/반각 등)

//기본적으로는 아무 변환도 안 함.

virtual WORD DoFinalConversion(WORD let) const;

};

//위 입력기를 멤버 변수로 가지는 에디터: 역시 정말 중요한 부분이다.

class NGSAPI CHanEditor

{

protected:

int m_nCol, m_nShowCol, m_nScrLen; //커서 위치와 화면표시 위치

//scrlen은 이 에디터가 화면에 표시되는 칸 수. 스크롤 계산하는데 쓰인다.

BYTE m_szBuf[HEDIT_BUF]; //데이터 버퍼

//단어단위로 블록잡는가? 잡는다면 선택을 시작한 위치(-1은 단어선택 없음)

int m_nSelCol, m_nWordSel;

BOOL m_bKeySet; //자판 포인터와 자판 종류

BOOL m_bMouseSel; //마우스로 블록을 잡고 있는가

CHanInput& m_Inputer; //사용하는 입력기

static CHanKeybrd m_DefKbd[2];

GETCANDIDATEPROC m_pfnCandFunc; LPVOID m_lpCandData;

//들어온 키를 세타 전 것까지 저장해두는 큐

//키 순서 바로잡기 등 특수키를 에디터에서 동작시키는데 필요하다.

struct { UINT nKey, nFlags, nOpt; } m_Queue[3];

int m_nQpos; //큐의 시작 위치와 현재 위치

BOOL HandleHanja();

public:

enum EditStyle { //에디터 스타일을 결정한다.

styDelMove=1, //커서 옮긴뒤 Del

styArrowMove=2, //커서 옮긴뒤 화살표

styOverwrite=4, //삽입/수정

styHanyoungkey=8, //한영키로 한영전환

styShiftspace=16 //Shift+Space로 한영전환

};

//한글 입력기 옵션을 제어하는 멤버

CStyle m_styProp;

enum EditTempStyle {

itnBackEdit=1, //앞글자 조합 상태로 가는 키가 눌러짐

itnCallBack=2 //PushKey가 콜백 상태이다. (큐를 건드리지 말 것.)

};

CStyle m_styTemp;

enum PushKeyReturn { //PushKey의 리턴값 - 주로 화면 업데이트 범위에 관한 것

valChanged=1, //에디터 내용이 바뀌었다.

valBlockDel=2, //블록이 지워지면서 내용이 입력됐다. DeleteBlock이 가상함수..

valRefresh=4, //글꼴이나 색깔이 바뀌었으므로 화면 전체를 다시 그릴 것

valScroll=8, //화면 스크롤. 스크롤 영역 안의 내용은 안 바뀌었음을 보증함

valLine=16, //(백스페이스, 수정) 줄 전체를 다시 그릴 것

valPrvCursor=32, //이전 커서 위치에 있던 글자를 다시 그릴것

valPrvNextHan=64 //이전 커서 위치 바로다음에 있던 글자를 다시 그릴것

};

//CHanInput 콜백에 응답할 수 있는 함수

static WORD CALLBACK GetCharByCursor(UINT, LPVOID, int);

CHanEditor(CHanInput &);

//동작 함수

virtual UINT PushKey(UINT nKey, UINT nFlags, LPBYTE pKeyState);

virtual UINT HandleSpecialKeys(DWORD dwCode);

virtual BOOL CheckScroll();

//인터페이스 함수

int GetCol() const;

void SetCol(int n);

int GetSelCol() const;

void SetSelCol(int n);

int GetShowCol() const;

void SetShowCol(int n);

int GetScrLen() const;

void SetScrLen(int n);

//NOTE: 문자열을 복사하는 게 아니라 포인터를 그대로 되돌림!

LPBYTE const GetText();

void SetText(LPSTR str);

operator LPBYTE();

void SetPairKeybrd(CHanKeybrd*, CHanKeybrd*);

//한자/특수문자 변환을 수행할 때 에디터가 호출할 함수

void SetCandFuncAndData(GETCANDIDATEPROC pFunc, LPVOID lpData);

CHanKeybrd GetPairKeybrd(int nIdx);

//블록 동작 함수

void SelectAll();

void PasteText(LPBYTE str);

virtual BOOL DeleteBlock();

virtual BOOL NoNullBlock();

virtual BOOL IsCursorEndBlock() const;

//마우스 구동 함수

UINT MouseMove(UINT, POINT);

UINT MouseLbDblClk(UINT, POINT);

UINT MouseLbDown(UINT, POINT);

UINT MouseLbUp(UINT, POINT);

};

#include "hanedit.inl"

#endif

참고 자료

□ MFC 레퍼런스와 비주얼 C++ 4.2의 예제 프로그램, 마이크로소프트, 1995~1996

□ <Visual C++ 5 완벽 가이드>, 이상엽 저, 영진출판사, 1997

□ <-Visual C++ 6 완벽 가이드>, 김용성 저, 영진출판사, 1998

□ <C++ 프로그래밍>, 황대준□ 엄영익 공저, 사이텍미디어, 1999