Annotation of nono/wx/wxlogmonitor.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2018 [email protected]
        !             4: //
        !             5: 
        !             6: #include "wxheader.h"
        !             7: #include "wxlogmonitor.h"
        !             8: #include "logger.h"
        !             9: 
        !            10: //
        !            11: // ログモニター
        !            12: //
        !            13: 
        !            14: // イベントテーブル
        !            15: wxBEGIN_EVENT_TABLE(WXLogMonitor, inherited)
        !            16:        EVT_TIMER(wxID_ANY, WXLogMonitor::OnTimer)
        !            17: wxEND_EVENT_TABLE()
        !            18: 
        !            19: // コンストラクタ
        !            20: WXLogMonitor::WXLogMonitor(wxWindow *parent, wxWindowID id)
        !            21:        : inherited(parent, id, "ログモニター")
        !            22: {
        !            23:        col = 80;
        !            24:        row = 40;
        !            25: 
        !            26:        logbuf = new uint8 [row * col];
        !            27:        memset(logbuf, 0x20, row * col);
        !            28:        text.Init(col, row);
        !            29: 
        !            30:        // テキストスクリーン
        !            31:        screen = new WXTextScreen(this, col, row, text.GetBuf());
        !            32: 
        !            33:        // 大きさを固定
        !            34:        Layout();
        !            35:        Fit();
        !            36: 
        !            37:        // 最初に一度描画しておく。
        !            38:        // ウィンドウが表示されてもまだログが出てない場合、タイマーイベントが
        !            39:        // おきても更新が起きず、グレーの背景が見えてしまうため。
        !            40:        // (ウィンドウの表示が早い場合や、ログレベルが低い場合は有り得る)
        !            41:        screen->Refresh();
        !            42: 
        !            43:        // 更新タイマーは適当な短さにしておく
        !            44:        timer.SetOwner(this);
        !            45:        timer.Start(10);
        !            46: }
        !            47: 
        !            48: // デストラクタ
        !            49: WXLogMonitor::~WXLogMonitor()
        !            50: {
        !            51:        if (logbuf) {
        !            52:                delete logbuf;
        !            53:        }
        !            54: }
        !            55: 
        !            56: // タイマーイベント
        !            57: void
        !            58: WXLogMonitor::OnTimer(wxTimerEvent& event)
        !            59: {
        !            60:        char buf[1024];
        !            61:        bool updated = false;
        !            62: 
        !            63:        // キューから読めるだけ全部ログバッファに書き込む
        !            64:        while (gLogger->Read(buf, sizeof(buf))) {
        !            65:                Append(buf);
        !            66:                updated = true;
        !            67:        }
        !            68: 
        !            69:        // ログの追加がなければここまで
        !            70:        if (!updated) {
        !            71:                return;
        !            72:        }
        !            73: 
        !            74:        // ここは TextScreen の内部構造に直接書き込むことにする。
        !            75:        uint16 *textbuf = text.GetRawBuf();
        !            76: 
        !            77:        // ログバッファ(循環バッファ)をテキストバッファに再構成。
        !            78:        // target は logbuf のうち今表示されるべき一番古い行の先頭を指している
        !            79:        // のでこれがテキストバッファの先頭になる。そこから logbuf の末尾まで。
        !            80:        // target == 0 の時に限りこの1回のコピーで終わり。それ以外の場合は必ず
        !            81:        // logbuf の先頭から target までの後半部分のコピーが発生する。
        !            82:        for (int i = 0; i < col * row - target; i++) {
        !            83:                textbuf[i] = logbuf[target + i];
        !            84:        }
        !            85:        if (target != 0) {
        !            86:                for (int i = 0; i < target; i++) {
        !            87:                        textbuf[col * row - target + i] = logbuf[i];
        !            88:                }
        !            89:        }
        !            90: 
        !            91:        // 更新指示
        !            92:        screen->Refresh();
        !            93: }
        !            94: 
        !            95: // フォントサイズ変更
        !            96: void
        !            97: WXLogMonitor::SetFontSize(fontsize_t fontsize)
        !            98: {
        !            99:        screen->SetFontSize(fontsize);
        !           100:        // ログの再描画は自前で行う必要がある
        !           101:        screen->Refresh();
        !           102:        // 大きさを変更
        !           103:        Layout();
        !           104:        Fit();
        !           105: }
        !           106: 
        !           107: // 表示用のログバッファに buf を追加
        !           108: //
        !           109: // logbuf は textbuf(, prevbuf) とかと同じ col * row バイトの単純バッファ
        !           110: // 形式。ただしこれを行ごとの循環バッファとして使っていて開始位置が target。
        !           111: // target は logbuf からの距離 (logbuf[] のインデックス) で表し、行は必ず
        !           112: // ウィンドウの行頭から追加することにすると target は col の倍数をとる。
        !           113: //
        !           114: //           +---------------------------+
        !           115: // logbuf -> |                           |
        !           116: //           |前行                       |
        !           117: // target -> |次に書く行 (今表示されてる一番古い行)
        !           118: //           |                           |
        !           119: //           |                           |
        !           120: //           |                           |
        !           121: //           +---------------------------+
        !           122: //
        !           123: // ついでに utfbuf は UTF-8 だが、表示用バッファ(textbuf) は Shift_JIS
        !           124: // なのでここで変換する。
        !           125: void
        !           126: WXLogMonitor::Append(const char *utfbuf)
        !           127: {
        !           128:        const char *sjis;
        !           129:        int sjislen;
        !           130:        int spos;
        !           131: 
        !           132:        // 文字コードの変換
        !           133:        wxString utfstr(utfbuf, wxConvUTF8);
        !           134:        sjis = (const char *)utfstr.mb_str(conv);
        !           135:        sjislen = strlen(sjis);
        !           136: 
        !           137:        // XXX 行末残り1桁で漢字が来た場合は?
        !           138: 
        !           139:        spos = 0;
        !           140:        for (;;) {
        !           141:                // この行に書き込む長さ
        !           142:                int len = std::min(sjislen - spos, col);
        !           143:                if (len < 1) {
        !           144:                        break;
        !           145:                }
        !           146: 
        !           147:                // コピー。残りは空白で埋める
        !           148:                memcpy(logbuf + target, sjis + spos, len);
        !           149:                if (len < col) {
        !           150:                        memset(logbuf + target + len, 0x20, col - len);
        !           151:                }
        !           152: 
        !           153:                spos += len;
        !           154:                target += col;
        !           155: 
        !           156:                // 折り返し
        !           157:                if (target >= col * row) {
        !           158:                        target = 0;
        !           159:                }
        !           160:        }
        !           161: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.