올해 초 언젠가 부터 5에서 vim의 커서가 한글 위에서 제대로 안 움직이고, 신택스 하이라이트도 제대로 동작하지 않고 있습니다. 저는 그냥 이것 저것 해 보다가, LC_CTYPE=C로 하면 되는 것을 발견해서 우선 셸 스크립트로 감싸서 쓰고 있었지만.. 얼마전 코드 페스트에서 최준호님도 같은 문제에 고심하고 계신 것을 알고, 같이 옆에서 좀 뒤져 보았더니, 일본 사람들도 같은 문제가 있고 이미 여러가지 해결 방법을 찾고 있었던 것을 찾을 수 있었습니다.
자세히 읽어본 결과, FreeBSD의mblen함수는 EINVAL (incomplete multibyte sequence)를 발생시킬 때 이전에 들어온 글자를 저장하는 방식으로 되어 있습니다. 즉,iconv에서 커서를 안 넣은 상태 처럼 다음 바이트를 넣어 주면 진행을 할 수 있는 방법으로 구현되어 있는 상황입니다. 그러나 반면, 리눅스의 구현은 EINVAL이 리턴되는 상황이면 state도 변환되지 않고, 다음 바이트를 입력하는 상태가 아니라 이전 바이트와 다음 바이트를 묶어서 한꺼번에 날려야 하는 구현으로 되어 있습니다. 그런데, vim은 리눅스의 구현을 기준으로 그냥 mblen에 있는 state를 따로 생각하지 않고 항상 1바이트씩 mblen을 하도록 되어 있어서, FreeBSD에서는 state가 계속 왔다갔다 해서 생긴 문제이군용.
이 문제에 대해서, POSIX의mblen에 대한 정의는 아무리 곱씹어 읽어보아도, EINVAL을 리턴하는 상황에서 state를 저장해야 할 지 아니면 그냥 무시해야할 지는 해석이 어렵군요. 우흑흑.
일단 이 vim문제를 해결하기 위한 여러가지 방법을 나열해 보자면,
-
FreeBSD mblen함수를 EINVAL을 리턴할 때 state를 저장하지 않도록 한다. (lib/libc/locale/euc.c 의 mbrtowc에서 return -2 위의 state 저장부분 삭제)
-
vim의 mbyte.c에서 mblen으로 다음 글자 계산하는 부분에서 mblen 들어가기 전에 항상 state를 초기화 해준다.
-
vim의 mbyte.c에서 mblen을 읽을 때 항상 MB_CUR_MAX 길이로 줘서, 최대한 길이를 계산할 수 있도록 한다.
각각의 방법 중 하나만 적용해도 되기는 하지만.. 나름대로 다 장단점이 있고, 표준에 완전히 맞는 것이 어느 것인지 매우 혼란스럽군요 -.-;; 그래서 생각한 다른 방법은..
-
vim에 utf-8처럼 euc 인코딩 루틴을 집어 넣어서 mblen 안 쓰게 한다.
흐.. -o- 고치는 방법은 다들 간단한데.. 어느 것이 제대로 된 것인지 알 수가 없어서… (아이고)
vim 안 쓰고, 기본 vi 를 쓰던지 emacs 쓴다
후다락~~
물론 저도 emacs쓰고 말면 되지만 ^^ 상식적인 기능에 버그가 있다는 것이 많은 vime user의 공분을 사겠죠. 가장 쉬운건 vim 패치를 만들어 아무도 몰래 넣는게 아닐까… 이럴때 일본애들에게 물어봐도 괜찮을 텐데요. 아님 그네들이 해결할 때 까지 기다리거나…
두 분 생각에 적당한 방법으로 해결하시면 누구든 두 분의 내공에 감사드릴겁니다. 도와드리고 싶지만 아직은 내공이 미흡하여…