|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.