--- nono/wx/wxlogmonitor.cpp 2026/04/29 17:04:51 1.1.1.5 +++ nono/wx/wxlogmonitor.cpp 2026/04/29 17:04:53 1.1.1.6 @@ -6,6 +6,7 @@ #include "wxlogmonitor.h" #include "logger.h" +#include "sjis.h" // // ログモニター @@ -25,7 +26,8 @@ WXLogMonitor::WXLogMonitor(wxWindow *par row = 40; // バックログは今の所固定長 - logbuf.resize(col * backlog, ' '); + logbuf.Init(col, backlog); + logbuf.Mode = TextScreen::Ring; // → // +--+-----------------------+--+--+ @@ -40,7 +42,7 @@ WXLogMonitor::WXLogMonitor(wxWindow *par topsizer = new wxBoxSizer(wxHORIZONTAL); // 左余白 - topsizer->AddSpacer(DefaultPadding); + topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); // 中列の縦 sizer auto *vbox = new wxBoxSizer(wxVERTICAL); topsizer->Add(vbox, 0, wxEXPAND); @@ -51,15 +53,15 @@ WXLogMonitor::WXLogMonitor(wxWindow *par // だが、上下の余白はその時点のフォントサイズによって変更する必要がある。 // 先にサイズ不定のパネルだけ置いといて、フォントサイズ確定後に大きさを // 確定させる。DoSize() 参照。 - padding1 = new wxPanel(this, wxID_ANY); - padding2 = new wxPanel(this, wxID_ANY); - vbox->Add(padding1); + padding1 = new WXPaddingPanel(this); + padding2 = new WXPaddingPanel(this); screen = new WXTextScreen(this, *this); + vbox->Add(padding1, 0, wxEXPAND); vbox->Add(screen, 1, wxEXPAND); - vbox->Add(padding2); + vbox->Add(padding2, 0, wxEXPAND); // 右余白 - topsizer->AddSpacer(DefaultPadding); + topsizer->Add(new WXPaddingPanel(this), 0, wxEXPAND); // スクロールバー vscroll = new wxScrollBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL); @@ -190,16 +192,6 @@ WXLogMonitor::GetMonitorSize() return nnSize(col, row); } -// バックログから TextScreen へのコピー -#define CopyText(text, row) do { \ - for (int i = 0; i < (row); i++) { \ - text.Locate(0, y++); \ - for (int x = 0; x < col; x++) { \ - text.Putc(*s++); \ - } \ - } \ -} while (0) - // モニターテキストを更新 void WXLogMonitor::MonitorUpdate(TextScreen& text) @@ -210,6 +202,9 @@ WXLogMonitor::MonitorUpdate(TextScreen& // とりあえず row は常に現在の TextScreen の高さということにしておく row = text.GetRow(); + // XXX: 生成時にやるべき + text.Mode = TextScreen::Ring; + // キューから読めるだけバックログに書き込む。 // 読めるだけと言っても while ループで読めるだけ読んでしまうと、 // 流速が早すぎた場合にこのループから抜けるタイミングがなくなる可能性が @@ -225,28 +220,22 @@ WXLogMonitor::MonitorUpdate(TextScreen& text.Clear(); // スクロールバー(vpos)による表示位置計算 - // vpos は行数、v は logbuf[] 先頭からのバイトオフセット - int v = cursor - col * vpos; + // vpos は行数、v は logbuf の Y 座標 + int v = cursor - vpos; if (v < 0) { - v += col * backlog; + v += backlog; } // 表示位置(v)の Row 行分手前から順に表示 - int size = col * row; - int y = 0; - uint8 *s; - if (v >= size) { - // 折り返しなし - s = &logbuf[v - size]; - CopyText(text, row); - } else { - // 折り返しあり - int row1 = (size - v) / col; - int row2 = row - row1; - s = &logbuf[col * backlog - (size - v)]; - CopyText(text, row1); - s = &logbuf[0]; - CopyText(text, row2); + int srcY = v - row; + if (srcY < 0) { + srcY += backlog; + } + + // 画面コピー + logbuf.Locate(0, srcY); + for (int i = 0; i < col * row; i++) { + text.Putc(logbuf.Getc()); } } @@ -254,13 +243,6 @@ WXLogMonitor::MonitorUpdate(TextScreen& void WXLogMonitor::IncLines() { - // カーソルを次行先頭に移動 - cursor += col; - // バッファ末尾まで来たら折り返し - if (cursor >= col * backlog) { - cursor = 0; - } - // スクロールバーが下端にない時(バックログを見ている時)は // ログが追加されても現在位置をキープする。 if (vpos > 0) { @@ -304,41 +286,42 @@ WXLogMonitor::Append(const char *utfbuf) const char *sjis; const char *s; int x; - bool iskanji; // 文字コードの変換 wxString utfstr(utfbuf, wxConvUTF8); sjis = (const char *)utfstr.mb_str(conv); - iskanji = false; - s = sjis; - x = 0; - for (; *s; ) { - // Shift_JIS の1文字目は上位ニブルが 8,9,E。 + logbuf.Locate(0, cursor); + + for (s = sjis; *s; ) { // 最終桁で2バイト文字の1バイト目が来たら // 代わりに1文字空白を入れる (それによってこの後改行が起きる) - if (iskanji == false && - (int16)(0b00000000'11000010 << (*s >> 4)) < 0 && - x >= col - 1) - { - logbuf[cursor + x] = ' '; + if (SJIS::IsZenkaku(*s)) { + // 漢字ならば 2 バイトセットで扱う + if (logbuf.GetX() >= col - 1) { + // 最終桁には出せないので空白で次の行に送る + logbuf.Putc(' '); + IncLines(); + } + logbuf.Putc(*s++); + // 万が一に備える + if (__predict_true(*s)) { + logbuf.Putc(*s++); + } } else { // そうでなければそのまま出力 - logbuf[cursor + x] = *s++; - iskanji = false; - } - x++; - - // 行端まで来たら改行 - if (x >= col) { - IncLines(); - // 行頭 - x = 0; + logbuf.Putc(*s++); } } - // 1行追加し終わって行頭でなければ、改行 + // 行の終わりまでは空白でクリアする + x = logbuf.GetX(); if (x > 0) { + for (; x < logbuf.GetCol(); x++) { + logbuf.Putc(' '); + } IncLines(); } + // 次回書き込みの Y 座標 + cursor = logbuf.GetY(); }