--- nono/wx/wxlogmonitor.cpp 2026/04/29 17:04:39 1.1.1.4 +++ nono/wx/wxlogmonitor.cpp 2026/04/29 17:04:59 1.1.1.8 @@ -6,6 +6,7 @@ #include "wxlogmonitor.h" #include "logger.h" +#include "sjis.h" // // ログモニター @@ -18,14 +19,18 @@ wxBEGIN_EVENT_TABLE(WXLogMonitor, inheri wxEND_EVENT_TABLE() // コンストラクタ -WXLogMonitor::WXLogMonitor(wxWindow *parent, wxWindowID id) - : inherited(parent, id, _("Log")) +WXLogMonitor::WXLogMonitor(wxWindow *parent) + : inherited(parent, wxID_ANY, _("Log")) { col = 80; row = 40; - // バックログは今の所固定長 - logbuf.resize(col * backlog, ' '); + monitor.obj = &log; + monitor.func = (MonitorCallback_t)&LogMonitor::MonitorUpdate; + monitor.SetSize(col, row); + // プライベート利用なので Regist() は不要 + + log.Init(this); // → // +--+-----------------------+--+--+ @@ -38,9 +43,9 @@ WXLogMonitor::WXLogMonitor(wxWindow *par // | | +------------------+ | | | // +--+-----------------------+--+--+ - topsizer = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer *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 +56,15 @@ WXLogMonitor::WXLogMonitor(wxWindow *par // だが、上下の余白はその時点のフォントサイズによって変更する必要がある。 // 先にサイズ不定のパネルだけ置いといて、フォントサイズ確定後に大きさを // 確定させる。DoSize() 参照。 - padding1 = new wxPanel(this, wxID_ANY); - padding2 = new wxPanel(this, wxID_ANY); - vbox->Add(padding1); - screen = new WXTextScreen(this, *this); + padding1 = new WXPaddingPanel(this); + padding2 = new WXPaddingPanel(this); + screen = new WXTextScreen(this, monitor); + 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); @@ -110,8 +115,7 @@ WXLogMonitor::SetScroll() int range; int pagesize; - const wxSize& size = screen->GetSize(); - row = size.GetHeight(); + row = screen->GetRow(); if (lines <= row) { pos = 0; @@ -183,32 +187,43 @@ WXLogMonitor::DoScroll(int pos) vscroll->SetThumbPosition(pos); } -// モニターサイズ取得 -nnSize -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) +// +// モニターオブジェクト +// + +// コンストラクタ +LogMonitor::LogMonitor() + : inherited("LogMonitor") +{ +} + +// デストラクタ +LogMonitor::~LogMonitor() +{ +} + +void +LogMonitor::Init(WXLogMonitor *parent_) +{ + parent = parent_; + + // バックログは今の所固定長 + logbuf.Init(parent->col, backlog); + logbuf.Mode = TextScreen::Ring; +} // モニターテキストを更新 void -WXLogMonitor::MonitorUpdate(TextScreen& text) +LogMonitor::MonitorUpdate(Monitor *, TextScreen& screen) { char buf[1024]; // どこでどうするかはあるけど、 // とりあえず row は常に現在の TextScreen の高さということにしておく - row = text.GetRow(); + parent->row = screen.GetRow(); + + // XXX: 生成時にやるべき + screen.Mode = TextScreen::Ring; // キューから読めるだけバックログに書き込む。 // 読めるだけと言っても while ループで読めるだけ読んでしまうと、 @@ -216,66 +231,53 @@ WXLogMonitor::MonitorUpdate(TextScreen& // (可能性としては) あるので、適当に1画面分くらいで打ち切る。 // 取り込み残した分は次回取り込まれるし、その流速も上回るようだと // どのみち gLogger の固定長キューで落ちる。 - for (int i = 0; i < row; i++) { + for (int i = 0; i < parent->row; i++) { if (gLogger.Read(buf, sizeof(buf)) == false) break; Append(buf); } - text.Clear(); + screen.Clear(); // スクロールバー(vpos)による表示位置計算 - // vpos は行数、v は logbuf[] 先頭からのバイトオフセット - int v = cursor - col * vpos; + // vpos は行数、v は logbuf の Y 座標 + int v = cursor - parent->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 - parent->row; + if (srcY < 0) { + srcY += backlog; + } + + // 画面コピー + logbuf.Locate(0, srcY); + for (int i = 0; i < parent->col * parent->row; i++) { + screen.Putc(logbuf.Getc()); } } // 1行追加された時の共通処理 void -WXLogMonitor::IncLines() +LogMonitor::IncLines() { - // カーソルを次行先頭に移動 - cursor += col; - // バッファ末尾まで来たら折り返し - if (cursor >= col * backlog) { - cursor = 0; - } - // スクロールバーが下端にない時(バックログを見ている時)は // ログが追加されても現在位置をキープする。 - if (vpos > 0) { + if (parent->vpos > 0) { // 上端に達したら増加させない - if (vpos < backlog - vscroll->GetThumbSize()) { - vpos++; + if (parent->vpos < backlog - parent->vscroll->GetThumbSize()) { + parent->vpos++; } } // 有効行数を増やす - if (lines < backlog) { - lines++; + if (parent->lines < backlog) { + parent->lines++; // 行数が変わったのでスクロールバーを更新 - SetScroll(); + parent->SetScroll(); } } @@ -299,46 +301,47 @@ WXLogMonitor::IncLines() // | // +------------------------ void -WXLogMonitor::Append(const char *utfbuf) +LogMonitor::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() >= parent->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(); }