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

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)
1.1.1.2 ! root       21:        : inherited(parent, id, wxT("ログモニター"))
1.1       root       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.