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

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

unix.superglobalmegacorp.com

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