ダブルクォート、シングルクォート
 
 
[ index | 前のドキュメント | 次のドキュメント | このドキュメントのソース ]
■ ダブルクォート
次にダブルクォートも認識し、指定色で表示するようにしよう。
ダブルクォートもHTMLタグと同様で、論理行内でのみ有効とする(複数行に渡る記述も無いとは言えないが、かなりイリーガルなケースだと思うので、想定外とする)。したがって、HTMLタグと同様に、非コメント状態で '"' を発見した場合は、dQuote フラグを立て、dQuote フラグが立っている場合は、指定色で描画すればよい。

void CViewView::OnDraw(CDC* pDC)
{
    .....
    uchar dQuote = 0;       //  ダブルクォート
    .....
                if( lineComment ) {     //  コメント状態
                    .....
                } else if( dQuote ) {           //  ダブルクォート中
                    textColor = RGB(0x80, 0x80, 0); //  文字色は黒黄色
                    while( dQuote > 0 && ptr < eolptr && *ptr != '\t' ) {
                        if( *ptr++ == '"' )
                            dQuote -= 1;
                    }
                } else {
                    .....
                    while( ptr < eolptr && *ptr != '\t' ) {
                        if( __iscsym((uchar)*ptr) ) {
                            .....
                        } else {
                            .....
                            if( *ptr == '"' ) {
                                dQuote = 2;
                                break;
                            }
                        }
                    }
                }
    .....
}
上記のコードでたいていの場合はうまくいくのだが、文字列中にバックスラッシュによりエスケープされたダブルクォートがあるとうまくいかない。それに対応するには、ダブルクォートが修了したかどうかを判定する部分を以下のように修正するとよい。

                    while( dQuote > 0 && ptr < eolptr && *ptr != '\t' ) {
                        uchar uch = *ptr++;
                        if( uch == '\\' && ptr < eolptr )
                            ptr += 1;
                        else if( uch == '"' )
                            dQuote -= 1;
                        else if( IsDBCSLeadByte(uch) && ptr < eolptr )
                            ptr += 1;
                    }
文字列中のダブルクォートはダブルクォート2つで表記する場合もあるが、その場合は、文字列修了、開始と判断されるので、何も特別な処理をしなくてもよい。エスケープを処理するかどうかはオプションで設定可能にすべきである。
■ シングルクォート
上記プログラムのソースを本プログラムで表示させると、シングルクォートで囲まれたダブルクォートが文字列開始と解釈されよろしくない。なので、シングルクォートもちゃんと認識するようにしよう。シングルクォート部分が論理行をまたぐことはないとしても問題はないので、ダブルクォートと同じようにコーディングすればよい。が、シングルクォートで囲まれた部分を特別に処理する必要性は低いと考えられるので、シングルクォートと認識した時点で、表示長を取得し、キーワード表示のロジックでシングルクォートを処理することが出来る。プログラムは以下のように記述できる。kwlen, kwcol という変数名がちょっと気になるが、当面は気にしないでいることにしよう。

bool isSingleQuote(cchar *srcptr, int srclen, int &kwlen, COLORREF &kwcol)
{
    if( *srcptr == '\'' ) {
        kwcol = RGB(0xf0, 0, 0);
        if( srclen >= 3 && srcptr[1] != '\\' &&
            !IsDBCSLeadByte((uchar)srcptr[1]) && srcptr[2] == '\'' )
        {
            kwlen = 3;
            return true;
        }
        if( srclen >= 4 && srcptr[1] == '\\' &&
            !IsDBCSLeadByte((uchar)srcptr[2]) && srcptr[3] == '\'' )
        {
            kwlen = 4;
            return true;
        }
        if( srclen >= 4 && IsDBCSLeadByte((uchar)srcptr[1]) && srcptr[3] == '\'' ) {
            kwlen = 4;
            return true;
        }
    }
    return false;
}

void CViewView::OnDraw(CDC* pDC)
{
    .....
                            if( *ptr == '"' ) {
                                .....
                            }
                            if( isSingleQuote(ptr, endptr-ptr, kwlen, kwcol) )
                                break;
    .....
}
■ 演習問題
[1] ダブルクォート中のキーワードを指定可能にしなさい。
[2] ダブルクォート中のにバックスラッシュでエスケープされたダブルクォートがあり、バックスラッシュの次でレイアウト改行されたいる場合でも、上記プログラムは問題ないか?問題があれば対処しなさい。
[ index | 前のドキュメント | 次のドキュメント | このドキュメントのソース ]