NUnicode::NPrivate::TComposition::TComposition() {
    for (size_t i = 0; i != RawDataSize; ++i) {
        const TRawData& data = RawData[i];

        if (DecompositionCombining(data.Lead) != 0)
            continue;

        Data[TKey(data.Lead, data.Tail)] = data.Comp;
    }

    for (wchar32 s = 0xAC00; s != 0xD7A4; ++s) {
        const wchar32* decompBegin = NUnicode::Decomposition<true>(s);

        if (decompBegin == NULL)
            continue;

        wchar32 lead = *(decompBegin++);
        while (*decompBegin) {
            wchar32 tail = *(decompBegin++);
            wchar32 comp = ComposeHangul(lead, tail);
            YASSERT(comp != 0);

            Data[TKey(lead, tail)] = comp;

            lead = comp;
        }
    }
}
Exemple #2
0
/**
 *  응용프로그램의 C 언어 엔트리 포인트
 */
int Main( char* pcArgument )
{
    QWORD qwWindowID;
    int iX;
    int iY;
    int iWidth;
    int iHeight;
    EVENT stReceivedEvent;
    KEYEVENT* pstKeyEvent;
    WINDOWEVENT* pstWindowEvent;
    RECT stScreenArea;
    BUFFERMANAGER stBufferManager;
    BOOL bHangulMode;
    
    //--------------------------------------------------------------------------
    // 그래픽 모드 판단
    //--------------------------------------------------------------------------
    // MINT64 OS가 그래픽 모드로 시작했는지 확인
    if( IsGraphicMode() == FALSE )
    {        
        // MINT64 OS가 그래픽 모드로 시작하지 않았다면 실패
        printf( "This task can run only GUI mode~!!!\n" );
        return -1;
    }
    
    //--------------------------------------------------------------------------
    // 윈도우와 입력 위치를 나타내는 커서를 생성
    //--------------------------------------------------------------------------
    // 윈도우를 화면 가운데에 가로 X 세로 크기를 60문자 X 40 픽셀로 생성
    GetScreenArea( &stScreenArea );
    iWidth = MAXOUTPUTLENGTH * FONT_ENGLISHWIDTH + 5;
    iHeight = 40;
    iX = ( GetRectangleWidth( &stScreenArea ) - iWidth ) / 2;
    iY = ( GetRectangleHeight( &stScreenArea ) - iHeight ) / 2;
    qwWindowID = CreateWindow(iX, iY, iWidth, iHeight, WINDOW_FLAGS_DEFAULT,
                              "한 줄 메모장(한/영 전환은 Alt 키)" );
    
    // 버퍼의 정보를 초기화하고 영문 입력 모드로 설정
    memset( &stBufferManager, 0, sizeof( stBufferManager ) );
    bHangulMode = FALSE;

    // 커서를 메모 입력 영역 앞쪽에 세로로 길게 출력하고 윈도우를 다시 표시
    DrawRect( qwWindowID, 3, 4 + WINDOW_TITLEBAR_HEIGHT, 5,
        3 + WINDOW_TITLEBAR_HEIGHT + FONT_ENGLISHHEIGHT, RGB( 0, 250, 0 ), TRUE );
    ShowWindow( qwWindowID, TRUE );

    //--------------------------------------------------------------------------
    // GUI 태스크의 이벤트 처리 루프
    //--------------------------------------------------------------------------
    while( 1 )
    {
        // 이벤트 큐에서 이벤트를 수신
        if( ReceiveEventFromWindowQueue( qwWindowID, &stReceivedEvent ) == FALSE )
        {
            Sleep( 10 );
            continue;
        }
        
        // 수신된 이벤트를 타입에 따라 나누어 처리
        switch( stReceivedEvent.qwType )
        {
            // 키 눌림 처리
        case EVENT_KEY_DOWN:
            // 키 이벤트를 추출
            pstKeyEvent = &( stReceivedEvent.stKeyEvent );

            // 입력된 키로 한글을 조합하거나 영문을 출력
            switch( pstKeyEvent->bASCIICode )
            {
            //------------------------------------------------------------------
            // 한/영 모드 전환 처리
            //------------------------------------------------------------------
            case KEY_LALT:
                // 한글 입력 모드 중에 Alt 키가 눌러지면 한글 조합을 종료
                if( bHangulMode == TRUE )
                {
                    // 키 입력 버퍼를 초기화
                    stBufferManager.iInputBufferLength = 0;

                    if( ( stBufferManager.vcOutputBufferForProcessing[ 0 ] != '\0' ) &&
                        ( stBufferManager.iOutputBufferLength + 2 < MAXOUTPUTLENGTH ) )
                    {
                        // 조합 중인 한글을 윈도우 화면에 출력하는 버퍼로 복사
                        memcpy( stBufferManager.vcOutputBuffer +
                                stBufferManager.iOutputBufferLength,
                                stBufferManager.vcOutputBufferForProcessing, 2 );
                        stBufferManager.iOutputBufferLength += 2;

                        // 조합 중인 한글을 저장하는 버퍼를 초기화
                        stBufferManager.vcOutputBufferForProcessing[ 0 ] = '\0';
                    }
                }
                // 영문 입력 모드 중에 Alt 키가 눌러지면 한글 조합용 버퍼를 초기화
                else
                {
                    stBufferManager.iInputBufferLength = 0;
                    stBufferManager.vcOutputBufferForComplete[ 0 ] = '\0';
                    stBufferManager.vcOutputBufferForProcessing[ 0 ] = '\0';
                }
                bHangulMode = TRUE - bHangulMode;
                break;

            //------------------------------------------------------------------
            // 백스페이스 키 처리
            //------------------------------------------------------------------
            case KEY_BACKSPACE:
                // 한글을 조합하는 중이면 입력 버퍼의 내용을 삭제하고 남은
                // 키 입력 버퍼의 내용으로 한글을 조합
                if( ( bHangulMode == TRUE ) &&
                    ( stBufferManager.iInputBufferLength > 0 ) )
                {
                    // 키 입력 버퍼의 내용을 하나 제거하고 한글을 다시 조합
                    stBufferManager.iInputBufferLength--;
                    ComposeHangul( stBufferManager.vcInputBuffer,
                            &stBufferManager.iInputBufferLength,
                            stBufferManager.vcOutputBufferForProcessing,
                            stBufferManager.vcOutputBufferForComplete );
                }
                // 한글 조합 중이 아니면 윈도우 화면에 출력하는 버퍼의 내용을 삭제
                else
                {
                    if( stBufferManager.iOutputBufferLength > 0 )
                    {
                        // 화면 출력 버퍼에 들어있는 내용이 2바이트 이상이고 버퍼에
                        // 저장된 값에 최상위 비트가 켜져 있으면 한글로 간주하고
                        // 마지막 2바이트를 모두 삭제
                        if( ( stBufferManager.iOutputBufferLength >= 2 ) &&
                            ( stBufferManager.vcOutputBuffer[
                                  stBufferManager.iOutputBufferLength - 1 ] & 0x80 ) )
                        {
                            stBufferManager.iOutputBufferLength -= 2;
                            memset( stBufferManager.vcOutputBuffer +
                                    stBufferManager.iOutputBufferLength, 0, 2 );
                        }
                        // 한글이 아니면 마지막 1바이트만 삭제
                        else
                        {
                            stBufferManager.iOutputBufferLength--;
                            stBufferManager.vcOutputBuffer[
                                stBufferManager.iOutputBufferLength ] = '\0';
                        }
                    }
                }
                break;

            //------------------------------------------------------------------
            // 나머지 키들은 현재 입력 모드에 따라 한글을 조합하거나
            // 윈도우 화면에 출력하는 버퍼로 직접 삽입
            //------------------------------------------------------------------
            default:
                // 특수 키들은 모두 무시
                if( pstKeyEvent->bASCIICode & 0x80 )
                {
                    break;
                }

                // 한글 조합 중이면 한글 조합 처리(한글을 화면 출력 버퍼에 저장할
                // 공간이 충분한지도 확인)
                if( ( bHangulMode == TRUE ) &&
                    ( stBufferManager.iOutputBufferLength + 2 <= MAXOUTPUTLENGTH ) )
                {
                    // 자/모음이 시프트와 조합되는 경우를 대비하여 쌍자음이나
                    // 쌍모음을 제외한 나머지는 소문자로 변환
                    ConvertJaumMoumToLowerCharactor( &pstKeyEvent->bASCIICode );

                    // 입력 버퍼에 키 입력 값을 채우고 데이터의 길이를 증가
                    stBufferManager.vcInputBuffer[
                        stBufferManager.iInputBufferLength ] = pstKeyEvent->bASCIICode;
                    stBufferManager.iInputBufferLength++;

                    // 한글 조합에 필요한 버퍼를 넘겨줘서 한글을 조합
                    if( ComposeHangul( stBufferManager.vcInputBuffer,
                        &stBufferManager.iInputBufferLength,
                        stBufferManager.vcOutputBufferForProcessing,
                        stBufferManager.vcOutputBufferForComplete) == TRUE )
                    {
                        // 조합이 완료된 버퍼에 값이 있는가 확인하여 윈도우 화면에
                        // 출력할 버퍼로 복사
                        if( stBufferManager.vcOutputBufferForComplete[ 0 ] != '\0' )
                        {
                           memcpy( stBufferManager.vcOutputBuffer +
                                   stBufferManager.iOutputBufferLength,
                                   stBufferManager.vcOutputBufferForComplete, 2 );
                           stBufferManager.iOutputBufferLength += 2;

                           // 조합된 한글을 복사한 뒤에 현재 조합 중인 한글을 출력할
                           // 공간이 없다면 키 입력 버퍼와 조합 중인 한글 버퍼를 모두 초기화
                           if( stBufferManager.iOutputBufferLength + 2 > MAXOUTPUTLENGTH )
                           {
                               stBufferManager.iInputBufferLength = 0;
                               stBufferManager.vcOutputBufferForProcessing[ 0 ] = '\0';
                           }
                        }
                    }
                    // 조합에 실패하면 입력 버퍼에 마지막으로 입력된 값이 한글 자/모음이
                    // 아니므로 한글 조합이 완료된 버퍼의 값과 입력 버퍼에 있는 값을 모두
                    // 출력 버퍼로 복사
                    else
                    {
                        // 조합이 완료된 버퍼에 값이 있는가 확인하여 윈도우 화면에
                        // 출력할 버퍼로 복사
                        if( stBufferManager.vcOutputBufferForComplete[ 0 ] != '\0' )
                        {
                            // 완성된 한글을 출력 버퍼로 복사
                            memcpy( stBufferManager.vcOutputBuffer +
                                    stBufferManager.iOutputBufferLength,
                                    stBufferManager.vcOutputBufferForComplete, 2 );
                            stBufferManager.iOutputBufferLength += 2;
                        }

                        // 윈도우 화면에 출력하는 버퍼의 공간이 충분하면 키 입력 버퍼에
                        // 마지막으로 입력된 한글 자/모가 아닌 값을 복사
                        if( stBufferManager.iOutputBufferLength < MAXOUTPUTLENGTH )
                        {
                            stBufferManager.vcOutputBuffer[
                                stBufferManager.iOutputBufferLength ] =
                                        stBufferManager.vcInputBuffer[ 0 ];
                            stBufferManager.iOutputBufferLength++;
                        }

                        // 키 입력 버퍼를 비움
                        stBufferManager.iInputBufferLength = 0;
                    }
                }
                // 한글 입력 모드가 아닌 경우
                else if( ( bHangulMode == FALSE ) &&
                         ( stBufferManager.iOutputBufferLength + 1 <= MAXOUTPUTLENGTH ) )
                {
                    // 키 입력을 그대로 윈도우 화면에 출력하는 버퍼로 저장
                    stBufferManager.vcOutputBuffer[
                        stBufferManager.iOutputBufferLength ] = pstKeyEvent->bASCIICode;
                    stBufferManager.iOutputBufferLength++;
                }
                break;
            }

            //------------------------------------------------------------------
            // 화면 출력 버퍼에 있는 문자열과 조합 중인 한글을 출력하고 커서의
            // 위치를 갱신
            //------------------------------------------------------------------
            // 화면 출력 버퍼에 있는 문자열을 전부 출력
            DrawText( qwWindowID, 2, WINDOW_TITLEBAR_HEIGHT + 4, RGB( 0, 0, 0 ),
                      RGB( 255, 255, 255 ), stBufferManager.vcOutputBuffer,
                      MAXOUTPUTLENGTH );
            // 현재 조합 중인 한글이 있다면 화면 출력 버퍼의 내용이 출력된
            // 다음 위치에 조합중인 한글을 출력
            if( stBufferManager.vcOutputBufferForProcessing[ 0 ] != '\0' )
            {
                DrawText( qwWindowID, 2 + stBufferManager.iOutputBufferLength *
                          FONT_ENGLISHWIDTH, WINDOW_TITLEBAR_HEIGHT + 4,
                          RGB( 0, 0, 0 ), RGB( 255, 255, 255 ),
                          stBufferManager.vcOutputBufferForProcessing, 2 );
            }

            // 커서를 세로로 길게 출력
            DrawRect( qwWindowID, 3 + stBufferManager.iOutputBufferLength *
                      FONT_ENGLISHWIDTH, 4 + WINDOW_TITLEBAR_HEIGHT,
                      5 + stBufferManager.iOutputBufferLength * FONT_ENGLISHWIDTH,
                      3 + WINDOW_TITLEBAR_HEIGHT + FONT_ENGLISHHEIGHT,
                      RGB( 0, 250, 0 ), TRUE );

            ShowWindow( qwWindowID, TRUE );
            break;

            // 윈도우 닫기 버튼 처리
        case EVENT_WINDOW_CLOSE:
            // 윈도우를 삭제하고 메모리를 해제
            DeleteWindow( qwWindowID );
            return 0;
            break;
            
            // 그 외 정보
        default:
            break;
        }
    }
    
    return 0;
}