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