• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

UART通信を用いた組み込みデバッグ用途向けメモリモニタ


Commit MetaInfo

修訂97280a04ffbc086af75d435e7883f579bd882f85 (tree)
時間2018-04-28 20:23:03
作者Yasushi Tanaka <tanaka_yasushi2008@yaho...>
CommiterYasushi Tanaka

Log Message

中間バージョン

Change Summary

差異

--- a/DebugMonitor/DebugMonitor.vcxproj
+++ b/DebugMonitor/DebugMonitor.vcxproj
@@ -1,5 +1,5 @@
11 <?xml version="1.0" encoding="utf-8"?>
2-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33 <ItemGroup Label="ProjectConfigurations">
44 <ProjectConfiguration Include="Debug|Win32">
55 <Configuration>Debug</Configuration>
@@ -19,13 +19,13 @@
1919 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
2020 <ConfigurationType>Application</ConfigurationType>
2121 <UseDebugLibraries>true</UseDebugLibraries>
22- <PlatformToolset>v120</PlatformToolset>
22+ <PlatformToolset>v140</PlatformToolset>
2323 <CharacterSet>Unicode</CharacterSet>
2424 </PropertyGroup>
2525 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
2626 <ConfigurationType>Application</ConfigurationType>
2727 <UseDebugLibraries>false</UseDebugLibraries>
28- <PlatformToolset>v120</PlatformToolset>
28+ <PlatformToolset>v140</PlatformToolset>
2929 <WholeProgramOptimization>true</WholeProgramOptimization>
3030 <CharacterSet>Unicode</CharacterSet>
3131 </PropertyGroup>
@@ -51,7 +51,7 @@
5151 </PrecompiledHeader>
5252 <WarningLevel>Level4</WarningLevel>
5353 <Optimization>Disabled</Optimization>
54- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
54+ <PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
5555 <SDLCheck>true</SDLCheck>
5656 <AdditionalIncludeDirectories>$(ProjectDir)src\framework;$(ProjectDir)src\comm;$(ProjectDir)src\user;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
5757 </ClCompile>
@@ -80,11 +80,18 @@
8080 </Link>
8181 </ItemDefinitionGroup>
8282 <ItemGroup>
83+ <ClInclude Include="src\framework\bdlist.h" />
84+ <ClInclude Include="src\framework\console.h" />
8385 <ClInclude Include="src\framework\header.h" />
86+ <ClInclude Include="src\framework\listbox.h" />
87+ <ClInclude Include="src\framework\monitor.h" />
8488 <ClInclude Include="src\framework\screen.h" />
8589 <ClInclude Include="src\framework\winmain.h" />
8690 </ItemGroup>
8791 <ItemGroup>
92+ <ClCompile Include="src\framework\bdlist.c" />
93+ <ClCompile Include="src\framework\listbox.c" />
94+ <ClCompile Include="src\framework\monitor.c" />
8895 <ClCompile Include="src\framework\screen.c" />
8996 <ClCompile Include="src\framework\winmain.c" />
9097 </ItemGroup>
--- a/DebugMonitor/DebugMonitor.vcxproj.filters
+++ b/DebugMonitor/DebugMonitor.vcxproj.filters
@@ -30,6 +30,18 @@
3030 <ClInclude Include="src\framework\header.h">
3131 <Filter>ヘッダー ファイル\framework</Filter>
3232 </ClInclude>
33+ <ClInclude Include="src\framework\console.h">
34+ <Filter>ヘッダー ファイル\framework</Filter>
35+ </ClInclude>
36+ <ClInclude Include="src\framework\listbox.h">
37+ <Filter>ヘッダー ファイル\framework</Filter>
38+ </ClInclude>
39+ <ClInclude Include="src\framework\monitor.h">
40+ <Filter>ヘッダー ファイル\framework</Filter>
41+ </ClInclude>
42+ <ClInclude Include="src\framework\bdlist.h">
43+ <Filter>ヘッダー ファイル\framework</Filter>
44+ </ClInclude>
3345 </ItemGroup>
3446 <ItemGroup>
3547 <ClCompile Include="src\framework\winmain.c">
@@ -38,5 +50,14 @@
3850 <ClCompile Include="src\framework\screen.c">
3951 <Filter>ソース ファイル\framework</Filter>
4052 </ClCompile>
53+ <ClCompile Include="src\framework\listbox.c">
54+ <Filter>ソース ファイル\framework</Filter>
55+ </ClCompile>
56+ <ClCompile Include="src\framework\monitor.c">
57+ <Filter>ソース ファイル\framework</Filter>
58+ </ClCompile>
59+ <ClCompile Include="src\framework\bdlist.c">
60+ <Filter>ソース ファイル\framework</Filter>
61+ </ClCompile>
4162 </ItemGroup>
4263 </Project>
\ No newline at end of file
--- /dev/null
+++ b/DebugMonitor/src/framework/bdlist.c
@@ -0,0 +1,96 @@
1+/*
2+ * Debug Monitor Framework
3+ * Author: Yasushi Tanaka
4+ *
5+ * [ 双方向リスト ]
6+ */
7+
8+#include "header.h"
9+#include "bdlist.h"
10+
11+/*
12+ * 双方向リスト
13+ * リストの終端を取得
14+ */
15+BDLIST_ENTRY* bdlist_get_tail(BDLIST_ENTRY *bdlist)
16+{
17+ BDLIST_ENTRY *tail;
18+
19+ assert(NULL != bdlist);
20+ tail = bdlist;
21+
22+ /* next方向に進む */
23+ while (tail->bdlist_next != NULL)
24+ {
25+ tail = tail->bdlist_next;
26+ }
27+
28+ return tail;
29+}
30+
31+/*
32+ * 双方向リスト
33+ * リストの終端に追加
34+ */
35+void bdlist_insert_tail(BDLIST_ENTRY *bdlist, BDLIST_ENTRY *entry)
36+{
37+ BDLIST_ENTRY *tail;
38+
39+ assert(NULL != bdlist);
40+ assert(NULL != entry);
41+
42+ /* リストの終端を取得 */
43+ tail = bdlist_get_tail(bdlist);
44+
45+ /* tailの次にentry */
46+ tail->bdlist_next = entry;
47+
48+ /* entryの前はtail */
49+ entry->bdlist_prev = tail;
50+
51+ /* entryの次はない */
52+ entry->bdlist_next = NULL;
53+}
54+
55+/*
56+ * 双方向リスト
57+ * リストから取り外す
58+ */
59+BDLIST_ENTRY* bdlist_remove(BDLIST_ENTRY *entry)
60+{
61+ BDLIST_ENTRY *prev;
62+ BDLIST_ENTRY *next;
63+
64+ assert(NULL != entry);
65+
66+ /* entryからprevとnextを取得 */
67+ prev = entry->bdlist_prev;
68+ next = entry->bdlist_next;
69+
70+ /* prevが存在すれば、prev->nextを設定 */
71+ if (NULL != prev)
72+ {
73+ prev->bdlist_next = next;
74+ }
75+
76+ /* nextが存在すれば、next->prevを設定 */
77+ if (NULL != next)
78+ {
79+ next->bdlist_prev = prev;
80+ }
81+
82+ /* エントリを初期化 */
83+ entry->bdlist_prev = NULL;
84+ entry->bdlist_next = NULL;
85+
86+ /* prevまたはnextで、NULLでないものを返す */
87+ if (NULL != prev)
88+ {
89+ /* prevが存在 */
90+ return prev;
91+ }
92+
93+ /* nextは存在するかもしれないし、NULLかもしれない */
94+ return next;
95+}
96+
--- /dev/null
+++ b/DebugMonitor/src/framework/bdlist.h
@@ -0,0 +1,33 @@
1+/*
2+ * Debug Monitor Framework
3+ * Author: Yasushi Tanaka
4+ *
5+ * [ 双方向リスト ]
6+ */
7+
8+#pragma once
9+
10+/*
11+ * 構造体定義
12+ */
13+typedef struct _BDLIST_ENTRY
14+{
15+ /* 前のエントリ */
16+ struct _BDLIST_ENTRY *bdlist_prev;
17+
18+ /* 次のエントリ */
19+ struct _BDLIST_ENTRY *bdlist_next;
20+} BDLIST_ENTRY;
21+
22+/*
23+ * グローバル関数
24+ */
25+
26+/* リストの終端を取得 */
27+BDLIST_ENTRY* bdlist_get_tail(BDLIST_ENTRY *bdlist);
28+
29+/* リストの終端に追加 */
30+void bdlist_insert_tail(BDLIST_ENTRY *bdlist, BDLIST_ENTRY *entry);
31+
32+/* リストから取り外す */
33+BDLIST_ENTRY* bdlist_remove(BDLIST_ENTRY *entry)
--- a/DebugMonitor/src/framework/header.h
+++ b/DebugMonitor/src/framework/header.h
@@ -26,5 +26,6 @@
2626 #include <assert.h>
2727 #include <stdio.h>
2828 #include <stdlib.h>
29+#include <crtdbg.h>
2930 #include <stdarg.h>
3031 #include <string.h>
--- a/DebugMonitor/src/framework/screen.c
+++ b/DebugMonitor/src/framework/screen.c
@@ -13,15 +13,6 @@
1313 * 定数
1414 */
1515
16-/* ウィンドウクラス名 */
17-#define SCREEN_CLASS_NAME L"ScreenWindow"
18-
19-/* スクリーンの最大幅(キャラクタ単位) */
20-#define SCREEN_WIDTH_MAX 0x400
21-
22-/* スクリーンの最大高さ(キャラクタ単位) */
23-#define SCREEN_HEIGHT_MAX 0x400
24-
2516 /* スクリーン色定義(白色) */
2617 #define SCREEN_COLOR_WHITE (RGB(255, 255, 255))
2718
@@ -29,613 +20,945 @@
2920 #define SCREEN_COLOR_BLACK (RGB(0, 0, 0))
3021
3122 /*
32- * 仮想キャラクタ構造体
23+ * static変数
3324 */
34-typedef struct _SCREEN_VIRT_CHR
35-{
36- /* 現在のキャラクタ */
37- SCREEN_CHR current;
3825
39- /* 描画したキャラクタ */
40- SCREEN_CHR draw;
41-} SCREEN_VIRT_CHR;
26+/* 最初のスクリーンオブジェクト */
27+static SCREEN_OBJECT *g_screen_object_head;
4228
4329 /*
44- * static変数
30+ * スクリーン
31+ * キャラクタの比較
4532 */
33+static BOOL screen_chr_is_equal(const SCREEN_CHR *chr1, const SCREEN_CHR *chr2)
34+{
35+ assert(NULL != chr1);
36+ assert(NULL != chr2);
4637
47-/* スクリーンのウィンドウハンドル */
48-static HWND g_hScreenWnd;
49-
50-/* スクリーンの表示幅(キャラクタ単位) */
51-static LONG g_lScreenWidth;
52-
53-/* スクリーンの表示高さ(キャラクタ単位) */
54-static LONG g_lScreenHeight;
55-
56-/* スクリーンの余り幅(ピクセル単位) */
57-static LONG g_lScreenExtWidth;
58-
59-/* スクリーンの余り高さ(ピクセル単位) */
60-static LONG g_lScreenExtHeight;
38+ /* キャラクタ本体 */
39+ if (chr1->chr != chr2->chr)
40+ {
41+ return FALSE;
42+ }
6143
62-/* 仮想画面 */
63-static SCREEN_VIRT_CHR g_ScreenAry[SCREEN_HEIGHT_MAX][SCREEN_WIDTH_MAX];
44+ /* 左右フラグ */
45+ if (chr1->right == chr2->right)
46+ {
47+ return FALSE;
48+ }
6449
65-/* 現在のフォアグラウンドカラー */
66-static COLORREF g_ForeTextColor;
50+ /* フォアグラウンドカラー */
51+ if (chr1->fore != chr2->fore)
52+ {
53+ return FALSE;
54+ }
6755
68-/* 現在のバックグラウンドカラー */
69-static COLORREF g_BackTextColor;
56+ /* バックグラウンドカラー */
57+ if (chr1->back != chr2->back)
58+ {
59+ return FALSE;
60+ }
7061
71-/* 描画要求フラグ */
72-static BOOL g_bRequestDraw;
62+ /* すべて一致 */
63+ return TRUE;
64+}
7365
7466 /*
7567 * スクリーン
76- * 描画比較
68+ * キャラクタを描画
7769 */
78-static BOOL screen_drawcompare(LONG x, LONG y)
70+static BOOL screen_chr_draw(HDC hDC, SCREEN_VIRT_CHR *chr, SCREEN_OBJECT *object)
7971 {
80- BOOL bCompare;
81-
82- assert(0 <= x);
83- assert(SCREEN_WIDTH_MAX > x);
84- assert(0 <= y);
85- assert(SCREEN_HEIGHT_MAX > y);
72+ COLORREF fore_prev;
73+ COLORREF back_prev;
74+ RECT *rect;
8675
87- /* 比較フラグをTRUEに */
88- bCompare = TRUE;
76+ assert(NULL != hDC);
77+ assert(chr != NULL);
78+ assert(object != NULL);
8979
90- /* キャラクタ */
91- if (g_ScreenAry[y][x].current.chr != g_ScreenAry[y][x].draw.chr)
80+ /* 現在のキャラクタと描画したキャラクタが一致すれば、何もしないのでFALSEを返す */
81+ if (TRUE == screen_chr_is_equal(&chr->current, &chr->draw))
9282 {
93- bCompare = FALSE;
83+ return FALSE;
84+ }
85+
86+ /* フォアグラウンドカラーの更新が必要か */
87+ if (chr->current.fore != object->fore)
88+ {
89+ /* フォアグラウンドカラーを更新する */
90+ fore_prev = SetTextColor(hDC, chr->current.fore);
91+ assert(CLR_INVALID != fore_prev);
92+ if (CLR_INVALID == fore_prev)
93+ {
94+ return FALSE;
95+ }
96+
97+ /* 更新成功 */
98+ object->fore = chr->current.fore;
9499 }
95100
96- /* 左右 */
97- if (g_ScreenAry[y][x].current.lr != g_ScreenAry[y][x].draw.lr)
101+ /* バックグラウンドカラーの更新が必要か */
102+ if (chr->current.back != object->back)
98103 {
99- bCompare = FALSE;
104+ /* バックグラウンドカラーを更新する */
105+ back_prev = SetBkColor(hDC, chr->current.back);
106+ assert(CLR_INVALID != back_prev);
107+ if (CLR_INVALID == back_prev)
108+ {
109+ return FALSE;
110+ }
111+
112+ /* 更新成功 */
113+ object->back = chr->current.back;
100114 }
101115
102- /* フォアグラウンドカラー */
103- if (g_ScreenAry[y][x].current.fore != g_ScreenAry[y][x].draw.fore)
116+ /* 右側であれば、化け防止のため半角スペースに強制変更する */
117+ if (TRUE == chr->current.right)
104118 {
105- bCompare = FALSE;
119+ /* currentを半角スペースに強制変更 */
120+ chr->current.chr = L' ';
121+
122+ /* 併せて左側にする */
123+ chr->current.right = FALSE;
106124 }
107125
108- /* バックグラウンドカラー */
109- if (g_ScreenAry[y][x].current.back != g_ScreenAry[y][x].draw.back)
126+ /* 半角または全角で、矩形を分ける */
127+ if (0x0100 > chr->current.chr)
110128 {
111- bCompare = FALSE;
129+ /* 半角 */
130+ rect = &chr->rect_ank;
112131 }
132+ else
133+ {
134+ /* 全角 */
135+ rect = &chr->rect_kanji;
136+ }
137+
138+ /* 描画 */
139+ ExtTextOut(hDC, rect->left, rect->top, ETO_OPAQUE, rect, (LPWSTR)&chr->current.chr, 1, NULL);
113140
114- /* 比較結果を返す */
115- return bCompare;
141+ /* 描画キャラクタを現在のキャラクタに更新 */
142+ chr->draw = chr->current;
143+
144+ /* TRUEを返し、描画したことを示す */
145+ return TRUE;
116146 }
117147
118148 /*
119149 * スクリーン
120- * 描画要求フラグ設定
150+ * ライン単位で比較
121151 */
122-static void screen_requestdraw(LONG x, LONG y)
152+static BOOL screen_line_is_equal(SCREEN_VIRT_LINE *line, SCREEN_OBJECT *object)
123153 {
124- BOOL bCompare;
154+ UINT loop;
155+ BOOL result;
125156
126- assert(0 <= x);
127- assert(x < SCREEN_WIDTH_MAX);
128- assert(0 <= y);
129- assert(y < SCREEN_HEIGHT_MAX);
157+ assert(NULL != line);
158+ assert(NULL != object);
130159
131- /* 比較 */
132- bCompare = screen_drawcompare(x, y);
160+ /* キャラクタ数が0であれば常にTRUE(一致) */
161+ if (0 == line->chrs)
162+ {
163+ return TRUE;
164+ }
133165
134- /* もしFALSEであれば、描画要求フラグを設定 */
135- if (FALSE == bCompare)
166+ /* 上下方向が描画範囲を超えていれば常にTRUE(一致) */
167+ if (0 > line->chr[0].rect_ank.bottom)
168+ {
169+ /* 描画範囲より上すぎる */
170+ return TRUE;
171+ }
172+ if (object->height < line->chr[0].rect_ank.top)
136173 {
137- /* 描画要求フラグを設定 */
138- g_bRequestDraw = TRUE;
174+ /* 描画範囲が下すぎる */
175+ return TRUE;
139176 }
177+
178+ /* キャラクタ単位でループ */
179+ for (loop = 0; loop < line->chrs; loop++)
180+ {
181+ /* 左右方向が描画範囲を超えていれば打ち切る */
182+ if (object->width < line->chr[loop].rect_ank.left)
183+ {
184+ break;
185+ }
186+
187+ /* 比較結果を得る */
188+ result = screen_chr_is_equal(&line->chr[loop].current, &line->chr[loop].draw);
189+ if (result == FALSE)
190+ {
191+ /* 不一致キャラクタを検出 */
192+ return FALSE;
193+ }
194+ }
195+
196+ /* 全ての描画範囲内キャラクタが一致 */
197+ return TRUE;
140198 }
141199
142200 /*
143201 * スクリーン
144- * 文字列セット
202+ * ライン単位で描画
145203 */
146-static void screen_settextw(UINT x, UINT y, COLORREF fore, COLORREF back, const wchar_t *format, ...)
204+static BOOL screen_line_draw(HDC hDC, SCREEN_VIRT_LINE *line, SCREEN_OBJECT *object)
147205 {
148- va_list ap;
149- wchar_t buf[SCREEN_WIDTH_MAX];
150- UINT offset;
206+ UINT loop;
207+ BOOL result;
151208
152- /* xチェック、yチェック */
153- assert(x < SCREEN_WIDTH_MAX);
154- if (x >= SCREEN_WIDTH_MAX)
209+ assert(NULL != hDC);
210+ assert(NULL != line);
211+ assert(NULL != object);
212+
213+ /* キャラクタ数が0であれば何もしない */
214+ if (0 == line->chrs)
155215 {
156- return;
216+ return FALSE;
157217 }
158- assert (y < SCREEN_HEIGHT_MAX);
159- if (y >= SCREEN_HEIGHT_MAX)
218+
219+ /* キャラクタ数は1以上 */
220+ assert(NULL != line->chr);
221+
222+ /* 上下方向が描画範囲を超えていればFALSEを返す */
223+ if (0 > line->chr[0].rect_ank.bottom)
160224 {
161- return;
225+ /* 描画範囲より上すぎる */
226+ return FALSE;
227+ }
228+ if (object->height < line->chr[0].rect_ank.top)
229+ {
230+ /* 描画範囲が下すぎる */
231+ return FALSE;
162232 }
163233
164- /* 可変長引数のフォーマット */
165- va_start(ap, format);
166- vswprintf_s(buf, _countof(buf), format, ap);
167- va_end(ap);
168-
169- /* ループ */
170- offset = 0;
171- while (x < SCREEN_WIDTH_MAX)
234+ /* キャラクタ単位でループ */
235+ for (loop = 0; loop < line->chrs; loop++)
172236 {
173- /* 制御文字が出てきたら打ち切る(\0を含む) */
174- if (L' ' > buf[offset])
237+ /* 左右方向が描画範囲を超えていれば打ち切る */
238+ if (object->width < line->chr[loop].rect_ank.left)
175239 {
176240 break;
177241 }
178242
179- /* 半角か、または全角か */
180- if (0x0100 > buf[offset])
181- {
182- /* 半角 */
183- g_ScreenAry[y][x].current.chr = buf[offset];
184- g_ScreenAry[y][x].current.lr = TRUE;
185- g_ScreenAry[y][x].current.fore = fore;
186- g_ScreenAry[y][x].current.back = back;
187-
188- /* 描画要求フラグ */
189- screen_requestdraw((LONG)x, (LONG)y);
243+ /* 1キャラクタ描画 */
244+ result = screen_chr_draw(hDC, &line->chr[loop], object);
190245
191- /* 半角は+1 */
192- x++;
193- }
194- else
246+ /* 実際に描画していて */
247+ if (result == TRUE)
195248 {
196- /* 全角は2文字一度にセットするため、SCREEN_WIDTH_MAXに対して、2文字の余裕が必要 */
197- if ((SCREEN_WIDTH_MAX - 1) > x)
198- {
199- /* Leftセット */
200- g_ScreenAry[y][x + 0].current.chr = buf[offset];
201- g_ScreenAry[y][x + 0].current.lr = TRUE;
202- g_ScreenAry[y][x + 0].current.fore = fore;
203- g_ScreenAry[y][x + 0].current.back = back;
204-
205- /* 描画要求フラグ(Left) */
206- screen_requestdraw((LONG)(x + 0), (LONG)y);
207-
208- /* Rightセット */
209- g_ScreenAry[y][x + 1].current.chr = buf[offset];
210- g_ScreenAry[y][x + 1].current.lr = FALSE;
211- g_ScreenAry[y][x + 1].current.fore = fore;
212- g_ScreenAry[y][x + 1].current.back = back;
213-
214- /* 描画要求フラグ(Right) */
215- screen_requestdraw((LONG)(x + 1), (LONG)y);
216-
217- /* 全角は+2 */
218- x += 2;
219- }
220- else
249+ /* 末尾以外か */
250+ if (loop < (line->chrs - 1))
221251 {
222- /* 打ち切る */
223- break;
252+ /* 全角か */
253+ if (0x0100 <= line->chr[loop].current.chr)
254+ {
255+ /* 左側か */
256+ if (FALSE == line->chr[loop].current.right)
257+ {
258+ /* 左側を描画しているので、右側も一致させる */
259+ line->chr[loop + 1].draw = line->chr[loop].draw;
260+
261+ /* ただし右側とする */
262+ line->chr[loop + 1].draw.right = TRUE;
263+ }
264+ }
224265 }
225266 }
226-
227- /* 次のオフセットに進む */
228- offset++;
229267 }
230268 }
231269
232270 /*
233271 * スクリーン
234- * 表示キャラクタ数と余りを算出
272+ * ライン矩形の再設定
235273 */
236-static void screen_calcwidthheight(HWND hWnd)
274+static void screen_line_rect(LONG top, SCREEN_VIRT_LINE *line)
237275 {
238- RECT rect;
239- LONG lWidth;
240- LONG lHeight;
241-
242- assert(NULL != hWnd);
276+ UINT loop;
277+ LONG bottom;
243278
244- /* クライアント領域を取得 */
245- GetClientRect(hWnd, &rect);
246-
247- /* 幅と高さを取得 */
248- lWidth = rect.right - rect.left;
249- lHeight = rect.bottom - rect.top;
250- assert(lWidth >= 0);
251- assert(lHeight >= 0);
279+ assert(NULL != line);
252280
253- /* スクリーンの表示幅・余り幅を記憶 */
254- g_lScreenExtWidth = 0;
255- assert(0 < g_tm.tmAveCharWidth);
256- g_lScreenWidth = lWidth / g_tm.tmAveCharWidth;
281+ /* topからbottomを算出 */
282+ bottom = top + g_tmAllHeight;
257283
258- /* ウィンドウ幅が広すぎないか */
259- if (SCREEN_WIDTH_MAX < g_lScreenWidth)
284+ /* 全てのキャラクタをループ */
285+ for (loop = 0; loop < line->chrs; loop++)
260286 {
261- /* ウィンドウ幅が広すぎるため、g_lScreenExtWidthが発生 */
262- g_lScreenWidth = SCREEN_WIDTH_MAX;
263- g_lScreenExtWidth = lWidth - (g_lScreenWidth * g_tm.tmAveCharWidth);
264- }
287+ /* 矩形(半角) */
288+ line->chr[loop].rect_ank.top = top;
289+ line->chr[loop].rect_ank.bottom = bottom;
265290
266- /* スクリーンの表示高さ・余り高さを記憶 */
267- g_lScreenExtHeight = 0;
268- assert(0 < g_tmAllHeight);
269- g_lScreenHeight = lHeight / g_tmAllHeight;
270-
271- /* ウィンドウ高さが高すぎないか */
272- if (SCREEN_HEIGHT_MAX < g_lScreenHeight)
273- {
274- /* ウィンドウ高さが高すぎるため、g_lScreenExtHeightが発生 */
275- g_lScreenHeight = SCREEN_HEIGHT_MAX;
276- g_lScreenExtHeight = lHeight - (g_lScreenHeight * g_tmAllHeight);
291+ /* 矩形(全角) */
292+ line->chr[loop].rect_kanji.top = top;
293+ line->chr[loop].rect_kanji.bottom = bottom;
277294 }
278295 }
279296
280297 /*
281298 * スクリーン
282- * WM_CREATEメッセージハンドラ
299+ * ラインのリサイズ
283300 */
284-static BOOL screen_oncreate(HWND hWnd)
301+static void screen_line_resize(LONG top, SCREEN_VIRT_LINE *line, SCREEN_OBJECT *object)
285302 {
286- LONG x;
287- LONG y;
303+ UINT loop;
304+ SCREEN_VIRT_CHR *array;
305+ RECT rect_ank;
306+ RECT rect_kanji;
288307
289- assert(NULL != hWnd);
308+ assert(line != NULL);
309+ assert(object != NULL);
290310
291- /* 仮想画面を初期化 */
292- for (y = 0; y < SCREEN_HEIGHT_MAX; y++)
311+ /* 現在のキャラクタ数と一致しているか、より大きければ */
312+ if (object->virt.width_chr <= line->chrs)
293313 {
294- for (x = 0; x < SCREEN_WIDTH_MAX; x++)
295- {
296- /* 現在のキャラクタは半角スペース、文字:黒色、背景:白色とする */
297- g_ScreenAry[y][x].current.chr = L' ';
298- g_ScreenAry[y][x].current.lr = TRUE;
299- g_ScreenAry[y][x].current.fore = SCREEN_COLOR_BLACK;
300- g_ScreenAry[y][x].current.back = SCREEN_COLOR_WHITE;
301-
302- /* 描画したキャラクタはヌル文字とする */
303- g_ScreenAry[y][x].draw.chr = L'\0';
304- g_ScreenAry[y][x].draw.lr = TRUE;
305- g_ScreenAry[y][x].draw.fore = SCREEN_COLOR_BLACK;
306- g_ScreenAry[y][x].draw.back = SCREEN_COLOR_WHITE;
307- }
314+ /* 矩形を再設定するのみ */
315+ screen_line_rect(top, line);
316+ return;
317+ }
318+
319+ /* 要求キャラクタ数が0なら何もしない */
320+ if (0 == object->virt.width_chr)
321+ {
322+ return;
308323 }
309324
310- /* 表示キャラクタ数と余りを算出 */
311- screen_calcwidthheight(hWnd);
325+ /* 新たな仮想キャラクタ配列を確保し、ゼロクリア */
326+ array = (SCREEN_VIRT_CHR*)malloc(sizeof(SCREEN_VIRT_CHR) * object->virt.width_chr);
327+ memset(array, 0, sizeof(SCREEN_VIRT_CHR) * object->virt.width_chr);
312328
313- return TRUE;
329+ /* 全ての最新キャラクタを半角スペースで初期化する */
330+ for (loop = 0; loop < object->virt.width_chr; loop++)
331+ {
332+ array[loop].current.chr = L' ';
333+ array[loop].current.right = FALSE;
334+ array[loop].current.fore = object->fore_def;
335+ array[loop].current.back = object->back_def;
336+ }
337+
338+ /* 現在のキャラクタ数が1以上ならコピー */
339+ if (0 < line->chrs)
340+ {
341+ assert(NULL != line->chr);
342+
343+ /* コピーして */
344+ memcpy(array, line->chr, sizeof(SCREEN_VIRT_CHR) * line->chrs);
345+
346+ /* 古い配列を解放 */
347+ free(line->chr);
348+ line->chr = NULL;
349+ line->chrs = 0;
350+ }
351+
352+ /* ポインタをセット */
353+ line->chr = array;
354+
355+ /* 新しいキャラクタ数をセット */
356+ line->chrs = object->virt.width_chr;
357+
358+ /* 半角矩形を初期化 */
359+ rect_ank.left = 0;
360+ rect_ank.top = top;
361+ rect_ank.right = g_tm.tmAveCharWidth;
362+ rect_ank.bottom = top + g_tmAllHeight;
363+
364+ /* 全角矩形を初期化 */
365+ rect_kanji.left = 0;
366+ rect_kanji.top = top;
367+ rect_kanji.right = g_tm.tmAveCharWidth * 2;
368+ rect_kanji.bottom = top + g_tmAllHeight;
369+
370+ /* 全てのキャラクタの矩形を更新 */
371+ for (loop = 0; loop < line->chrs; loop++)
372+ {
373+ /* 矩形を更新 */
374+ line->chr[loop].rect_ank = rect_ank;
375+ line->chr[loop].rect_kanji = rect_kanji;
376+
377+ /* コピー元矩形を、右側へ移動 */
378+ rect_ank.left += g_tm.tmAveCharWidth;
379+ rect_ank.right += g_tm.tmAveCharWidth;
380+ rect_kanji.left += g_tm.tmAveCharWidth;
381+ rect_kanji.right += g_tm.tmAveCharWidth;
382+ }
314383 }
315384
316385 /*
317386 * スクリーン
318- * WM_DESTROYメッセージハンドラ
387+ * ラインの破棄
319388 */
320-static void screen_ondestroy(HWND hWnd)
389+static void screen_line_destroy(SCREEN_VIRT_LINE *line)
321390 {
322- assert(NULL != hWnd);
323- assert(hWnd == g_hScreenWnd);
391+ assret(NULL != line);
324392
325- /* ウィンドウが無効であることを示す */
326- g_hScreenWnd = NULL;
327-
328- /* 描画要求は必要ない */
329- g_bRequestDraw = FALSE;
393+ /* 現在のキャラクタ数が0を超えていれば */
394+ if (0 < line->chrs)
395+ {
396+ /* キャラクタ配列を解放 */
397+ assert(NULL != line->chr);
398+ free(line->chr);
399+ line->chr = NULL;
400+ line->chrs = 0;
401+ }
330402 }
331403
332404 /*
333405 * スクリーン
334- * WM_SIZEメッセージハンドラ
406+ * ラインの無効化
335407 */
336-static void screen_onsize(HWND hWnd, LONG cx, LONG cy)
408+static void screen_line_invalidate(SCREEN_VIRT_LINE *line)
337409 {
338- assert(NULL != hWnd);
339- assert(0 <= cx);
340- assert(0 <= cy);
341-
342- /* 表示キャラクタ数と余りを算出 */
343- screen_calcwidthheight(hWnd);
410+ UINT loop;
344411
345- /* スクリーン全体を無効化 */
346- InvalidateRect(hWnd, NULL, TRUE);
412+ assert(NULL != line);
347413
348- /* テスト */
349- screen_settextw(90, 0, SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, L"幅=%d文字 高さ=%d文字", g_lScreenWidth, g_lScreenHeight);
414+ /* キャラクタループ */
415+ for (loop = 0; loop < line->chrs; loop++)
416+ {
417+ /* 描画済みキャラクタをヌル文字に変更 */
418+ line->chr[loop].draw.chr = L'\0';
419+ }
350420 }
351421
352422 /*
353423 * スクリーン
354- * WM_ERASEBKGNDメッセージハンドラ
424+ * 全てのラインのリサイズ
355425 */
356-static void screen_onerasebkgnd(HWND hWnd, HDC hDC)
426+static void screen_allline_resize(SCREEN_OBJECT *object)
357427 {
358- HBRUSH hBrush;
359- RECT rect;
428+ UINT add;
429+ UINT loop;
430+ LONG top;
431+ SCREEN_VIRT_LINE *line;
360432
361- assert(NULL != hWnd);
362- assert(NULL != hDC);
433+ assert(NULL != object);
363434
364- /* 余り領域がなければ何もしない */
365- if ((0 == g_lScreenExtWidth) && (0 == g_lScreenExtHeight))
435+ /* クライアント領域の幅から、キャラクタ数を決める(余りがあれば+1) */
436+ object->virt.width_chr = object->width / g_tm.tmAveCharWidth;
437+ if (0 < object->width % g_tm.tmAveCharWidth)
366438 {
367- return;
439+ object->virt.width_chr++;
368440 }
369441
370- /* 背景ブラシを取得 */
371- hBrush = GetSysColorBrush(COLOR_WINDOW);
442+ /* クライアント領域の高さから、キャラクタ数を決める(余りがあれば+1) */
443+ object->virt.height_chr = object->height / g_tmAllHeight;
444+ if (0 < object->height % g_tmAllHeight)
445+ {
446+ object->virt.height_chr++;
447+ }
372448
373- /* 右側の余り領域を描画 */
374- if (0 != g_lScreenExtWidth)
449+ /* 現在の行数 < 算出した行数の場合 */
450+ if (object->virt.lines < object->virt.height_chr)
375451 {
376- /* クライアント領域を取得 */
377- GetClientRect(hWnd, &rect);
452+ /* 現在存在する行数を考慮して、追加すべき行を算出する */
453+ add = object->virt.height_chr - object->virt.lines;
378454
379- /* rect.leftのみ修正 */
380- rect.left = SCREEN_WIDTH_MAX + g_tm.tmAveCharWidth;
455+ /* 行を追加 */
456+ for (loop = 0; loop < add; loop++)
457+ {
458+ /* 新たな行オブジェクトを作成 */
459+ line = (SCREEN_VIRT_LINE*)malloc(sizeof(SCREEN_VIRT_LINE));
460+ memset(line, 0, sizeof(SCREEN_VIRT_LINE));
381461
382- /* ブラシで塗りつぶす */
383- FillRect(hDC, &rect, hBrush);
462+ /* 最初の行か*/
463+ if (NULL == object->virt.head)
464+ {
465+ /* 最初の行なので、そのままセット */
466+ object->virt.head = line;
467+ }
468+ else
469+ {
470+ /* 終端に追加 */
471+ bdlist_insert_tail((BDLIST_ENTRY*)object->virt.head, (BDLIST_ENTRY*)line);
472+ }
473+ }
474+
475+ /* 行の数を更新 */
476+ object->virt.lines = object->virt.height_chr;
477+ }
478+
479+ /* dir_upを考慮して、topを決める */
480+ if (TRUE == object->virt.dir_up)
481+ {
482+ /* 下方向から上方向に延びる*/
483+ top = object->height - g_tmAllHeight;
484+ }
485+ else
486+ {
487+ /* 上方向から下方向に延びる*/
488+ top = 0;
384489 }
385490
386- /* 下側の余り領域を描画 */
387- if (0 != g_lScreenExtHeight)
491+ /* 全ての行をリサイズ */
492+ line = object->virt.head;
493+ for (loop = 0; loop < object->virt.lines; loop++)
388494 {
389- /* クライアント領域を取得 */
390- GetClientRect(hWnd, &rect);
495+ assert(NULL != line);
496+
497+ /* ラインのリサイズ */
498+ screen_line_resize(top, line, object);
391499
392- /* rect.topのみ修正 */
393- rect.top = SCREEN_HEIGHT_MAX + g_tmAllHeight;
500+ /* topを更新 */
501+ if (FALSE == object->virt.dir_up)
502+ {
503+ /* 上から下へ */
504+ top += g_tmAllHeight;
505+ }
506+ else
507+ {
508+ /* 下から上へ */
509+ top -= g_tmAllHeight;
510+ }
394511
395- /* ブラシで塗りつぶす */
396- FillRect(hDC, &rect, hBrush);
512+ /* 次のラインへ*/
513+ line = (SCREEN_VIRT_LINE*)line->bdlist.bdlist_next;
397514 }
398515 }
399516
400517 /*
401- * スクリーン
402- * キャラクタ描画
403- */
404-static void screen_drawone(HDC hDC, LONG x, LONG y)
518+* スクリーン
519+* 全てのラインの比較
520+*/
521+static BOOL screen_allline_is_equal(SCREEN_OBJECT *object)
405522 {
406- RECT rect;
407- COLORREF clrPrev;
408- BOOL bResult;
523+ SCREEN_VIRT_LINE *line;
524+ BOOL result;
409525
410- assert(NULL != hDC);
411- assert(0 <= x);
412- assert(SCREEN_WIDTH_MAX > x);
413- assert(0 <= y);
414- assert(SCREEN_HEIGHT_MAX > y);
526+ assert(NULL != object);
415527
416- /* 右側は描画しない */
417- if (FALSE == g_ScreenAry[y][x].current.lr)
418- {
419- return;
420- }
528+ /* 最初のラインを取得、戻り値をTRUEに初期化 */
529+ line = object->virt.head;
530+ result = TRUE;
421531
422- /* フォアグラウンドカラーを更新 */
423- if (g_ScreenAry[y][x].current.fore != g_ForeTextColor)
532+ /* ラインが存在する限りループ */
533+ while (NULL != line)
424534 {
425- clrPrev = SetTextColor(hDC, g_ScreenAry[y][x].current.fore);
426- assert(CLR_INVALID != clrPrev);
427- if (CLR_INVALID == clrPrev)
535+ /* このラインを比較 */
536+ result = screen_line_is_equal(line, object);
537+
538+ /* 結果がFALSEであれば直ちに抜ける */
539+ if (FALSE == result)
428540 {
429- return;
541+ break;
430542 }
431- g_ForeTextColor = g_ScreenAry[y][x].current.fore;
543+
544+ /* 次のラインを得る */
545+ line = (BDLIST_ENTRY*)line->bdlist.bdlist_next;
432546 }
433547
434- /* バックグラウンドカラーを更新 */
435- if (g_ScreenAry[y][x].current.back != g_BackTextColor)
548+ /* 結果を返す */
549+ return result;
550+}
551+
552+/*
553+* スクリーン
554+* 全てのラインの描画
555+*/
556+static void screen_allline_draw(HDC hDC, SCREEN_OBJECT *object)
557+{
558+ SCREEN_VIRT_LINE *line;
559+ BOOL result;
560+ COLORREF fore_prev;
561+ COLORREF back_prev;
562+
563+ assert(hDC != NULL);
564+ assert(object != NULL);
565+
566+ /* 最初のラインを得る */
567+ line = object->virt.head;
568+
569+ /* フォアグラウンドカラーをデフォルト色にセット */
570+ fore_prev = SetTextColor(hDC, object->fore_def);
571+ assert(CLR_INVALID != fore_prev);
572+ if (4)
573+
574+ /* ラインが存在する限りループ */
575+ while (NULL != line)
436576 {
437- clrPrev = SetBkColor(hDC, g_ScreenAry[y][x].current.back);
438- assert(CLR_INVALID != clrPrev);
439- if (CLR_INVALID == clrPrev)
577+ /* このラインを描画 */
578+ result = screen_line_draw(hDC, line, object);
579+
580+ /* 描画範囲を超えていればFALSEが返る */
581+ if (FALSE == result)
440582 {
441- return;
583+ break;
442584 }
443- g_BackTextColor = g_ScreenAry[y][x].current.back;
585+
586+ /* 次のラインを得る */
587+ line = (SCREEN_VIRT_LINE*)line->bdlist.bdlist_next;
588+ }
589+}
590+
591+/*
592+ * スクリーン
593+ * 全てのラインの破棄
594+ */
595+static void screen_allline_destroy(SCREEN_OBJECT *object)
596+{
597+ SCREEN_VIRT_LINE *line;
598+
599+ assert(NULL != object);
600+
601+ /* 最初のラインが有効であればループ */
602+ while (NULL != object->virt.head)
603+ {
604+ /* ラインを記憶しておく */
605+ line = object->virt.head;
606+
607+ /* このラインを削除 */
608+ screen_line_destroy(line);
609+
610+ /* リストから取り外す */
611+ object->virt.head = (SCREEN_VIRT_LINE*)bdlist_remove((BDLIST_ENTRY*)&line);
612+
613+ /* 行オブジェクトを解放 */
614+ free(line);
615+ }
616+}
617+
618+/*
619+ * スクリーン
620+ * 全てのラインの無効化
621+ */
622+static void screen_allline_invalidate(SCREEN_OBJECT *object)
623+{
624+ SCREEN_VIRT_LINE *line;
625+
626+ assert(NULL != object);
627+
628+ /* 最初のラインを得る */
629+ line = object->virt.head;
630+
631+ /* ラインが存在する限りループ */
632+ while (NULL != line)
633+ {
634+ /* このラインを無効化 */
635+ screen_line_invalidate(line);
636+
637+ /* 次のラインを得る */
638+ line = (SCREEN_VIRT_LINE*)line->bdlist.bdlist_next;
444639 }
640+}
641+
642+/*
643+ * スクリーン
644+ * ウィンドウハンドルからスクリーンオブジェクトを逆引きする
645+ */
646+static SCREEN_OBJECT* screen_get_object(HWND hwnd)
647+{
648+ SCREEN_OBJECT *object;
649+
650+ assert(NULL != hwnd);
445651
446- /* 担当矩形を選択 */
447- rect.left = x * g_tm.tmAveCharWidth;
448- rect.right = rect.left + g_tm.tmAveCharWidth;
449- rect.top = y * g_tmAllHeight;
450- rect.bottom = rect.top + g_tmAllHeight;
652+ /* 最初のスクリーンオブジェクトを得る */
653+ object = g_screen_object_head;
451654
452- /* 全角文字の場合は幅を2倍にする */
453- if (0x0100 <= g_ScreenAry[y][x].current.chr)
655+ /* 無ければエラー */
656+ assert(NULL != object);
657+ if (NULL == object)
454658 {
455- rect.right += g_tm.tmAveCharWidth;
659+ return NULL;
456660 }
457661
458- /* テキストを描画 */
459- bResult = ExtTextOut(hDC, rect.left, rect.top, ETO_OPAQUE, &rect, (LPWSTR)&g_ScreenAry[y][x].current.chr, 1, NULL);
460- assert(FALSE != bResult);
461- if (FALSE == bResult)
662+ /* 一致するか */
663+ while(object->hwnd != hwnd)
462664 {
463- return;
665+ /* 次がなければ存在しない */
666+ assert(NULL != object->bdlist.bdlist_next);
667+ if (NULL == object->bdlist.bdlist_next)
668+ {
669+ return NULL;
670+ }
671+
672+ /* 次へ移動 */
673+ object = object->bdlist.bdlist_next;
464674 }
465675
466- /* 正常終了 */
676+ /* 見つかった */
677+ return object;
467678 }
468679
469680 /*
470681 * スクリーン
471- * 描画更新
682+ * スクリーンオブジェクトの描画を禁止する
683+ * ※WM_DESTROYハンドラで呼び出すこと
472684 */
473-static void screen_drawupate(LONG x, LONG y)
685+static void screen_disable_object(SCREEN_OBJECT *object)
474686 {
475- assert(0 <= x);
476- assert(SCREEN_WIDTH_MAX > x);
477- assert(0 <= y);
478- assert(SCREEN_HEIGHT_MAX > y);
479- assert(0 < g_lScreenWidth);
480-
481- /* キャラクタ */
482- g_ScreenAry[y][x].draw.chr = g_ScreenAry[y][x].current.chr;
687+ assert(NULL != object);
483688
484- /* 左右 */
485- g_ScreenAry[y][x].draw.lr = g_ScreenAry[y][x].current.lr;
689+ /* 破棄フラグにTRUEをセットすることで、定期描画を無効化する */
690+ object->destroy = TRUE;
691+}
486692
487- /* フォアグラウンドカラー */
488- g_ScreenAry[y][x].draw.fore = g_ScreenAry[y][x].current.fore;
693+/*
694+ * スクリーン
695+ * オブジェクトを削除する
696+ * ※WM_NCDESTROYハンドラで呼び出すこと
697+ */
698+static void screen_destroy_object(SCREEN_OBJECT *object)
699+{
700+ assert(NULL != object);
701+ assert(TRUE == object->destroy);
489702
490- /* バックグラウンドカラー */
491- g_ScreenAry[y][x].draw.back = g_ScreenAry[y][x].current.back;
703+ /* 全てのラインを破棄 */
704+ screen_allline_destroy(object);
492705
493- /* 描画範囲のx終端以外でなく、かつキャラクタが0x0100以上(全角)で、Lの場合 */
494- if ((x < (g_lScreenWidth - 1)) && (0x0100 <= g_ScreenAry[y][x].current.chr) && (TRUE == g_ScreenAry[y][x].current.lr))
706+ /* 先頭かどうか */
707+ if (g_screen_object_head == object)
495708 {
496- /* 一つ右側も描画しているので、右のdrawを更新 */
497- g_ScreenAry[y][x + 1].draw.chr = g_ScreenAry[y][x].current.chr;
709+ /* 先頭なので、headを更新 */
710+ g_screen_object_head = (SCREEN_OBJECT*)bdlist_remove((BDLIST_ENTRY*)object);
711+ }
712+ else
713+ {
714+ /* 単純にリストから取り外せばよい */
715+ bdlist_remove((BDLIST_ENTRY*)object);
716+ }
498717
499- /* 左右は右にする */
500- g_ScreenAry[y][x + 1].draw.lr = FALSE;
718+ /* ウィンドウハンドルを無効化 */
719+ object->hwnd = NULL;
501720
502- /* フォアグラウンドカラー */
503- g_ScreenAry[y][x + 1].draw.fore = g_ScreenAry[y][x].current.fore;
721+ /* object本体は、呼び出し元ウィンドウで静的に持つことを前提としているので、解放しない */
722+}
723+
724+/*
725+* スクリーン
726+* 更新
727+*/
728+static void screen_update_object(SCREEN_OBJECT *object)
729+{
730+ BOOL result;
731+
732+ assert(NULL != object);
504733
505- /* バックグラウンドカラー */
506- g_ScreenAry[y][x + 1].draw.back = g_ScreenAry[y][x].current.back;
734+ /* 全てのラインを比較 */
735+ result = screen_allline_is_equal(object);
736+ if (FALSE == result)
737+ {
738+ /* 描画要求をセット */
739+ object->update = TRUE;
740+ }
741+ else
742+ {
743+ /* すべて一致しているので、描画要求は必要ない */
744+ object->update = FALSE;
507745 }
508746 }
509747
510748 /*
511749 * スクリーン
512- * 描画共通
750+ * 描画
513751 */
514-static void screen_drawmain(HWND hWnd, HDC hDC)
752+static void screen_draw_object(SCREEN_OBJECT *object)
515753 {
516- LONG x;
517- LONG y;
518- HFONT hDefFont;
519- COLORREF clrPrev;
520- BOOL bCompare;
754+ HDC hDC;
521755
522- assert(NULL != hWnd);
523- assert(NULL != hDC);
524- assert(NULL != g_hFont);
525- assert(0 <= g_lScreenHeight);
526- assert(0 <= g_lScreenWidth);
756+ assert(NULL != object);
527757
528- /* フォントを選択 */
529- hDefFont = SelectObject(hDC, g_hFont);
530- assert(NULL != hDefFont);
531- if (NULL == hDefFont)
758+ /* 破棄フラグがセットされていれば、何もしない */
759+ if (TRUE == object->destroy)
532760 {
533761 return;
534762 }
535763
536- /* 最初のフォアグラウンドカラーを選択(白色) */
537- clrPrev = SetTextColor(hDC, SCREEN_COLOR_WHITE);
538- assert(CLR_INVALID != clrPrev);
539- if (CLR_INVALID == clrPrev)
764+ /* 更新フラグがセットされていなければ、何もしない */
765+ if (FALSE == object->update)
540766 {
541- SelectObject(hDC, hDefFont);
542767 return;
543768 }
544- g_ForeTextColor = SCREEN_COLOR_WHITE;
545769
546- /* 最初のバックグラウンドカラーを選択(黒色) */
547- clrPrev = SetBkColor(hDC, SCREEN_COLOR_BLACK);
548- assert(CLR_INVALID != clrPrev);
549- if (CLR_INVALID == clrPrev)
770+ /* デバイスコンテキストを取得 */
771+ assert(NULL != object->hwnd);
772+ hDC = GetDC(object->hwnd);
773+ assert(NULL != hDC);
774+ if (NULL == hDC)
550775 {
551- SelectObject(hDC, hDefFont);
552776 return;
553777 }
554- g_BackTextColor = SCREEN_COLOR_BLACK;
555778
556- /* ループ */
557- for (y = 0; y < g_lScreenHeight; y++)
779+ /* 全てのラインを描画 */
780+ screen_allline_draw(hDC, object);
781+
782+ /* デバイスコンテキストを解放 */
783+ ReleaseDC(object->hwnd, hDC);
784+ hDC = NULL;
785+
786+ /* 更新フラグを降ろす */
787+ object->update = FALSE;
788+}
789+
790+/*
791+ * スクリーン
792+ * WM_CREATEハンドラ
793+ */
794+static BOOL screen_on_create(HWND hWnd, const LPCREATESTRUCT lpcs)
795+{
796+ SCREEN_OBJECT *object;
797+ BOOL result;
798+ RECT rect;
799+
800+ assert(NULL != hWnd);
801+ assert(NULL != lpcs);
802+
803+ /* スクリーンオブジェクトを取得 */
804+ object = (SCREEN_OBJECT*)lpcs->lpCreateParams;
805+ assert(NULL != object);
806+
807+ /* ウィドウハンドルを記憶 */
808+ object->hwnd = hWnd;
809+
810+ /* クライアント領域を取得 */
811+ result = GetClientRect(hWnd, &rect);
812+ assert(FALSE != result);
813+ if (FALSE == result)
558814 {
559- for (x = 0; x < g_lScreenWidth; x++)
560- {
561- /* 比較 */
562- bCompare = screen_drawcompare(x, y);
815+ return FALSE;
816+ }
563817
564- /* 一致していない場合、描画と更新 */
565- if (FALSE == bCompare)
566- {
567- /* このキャラクタは描画する必要がある */
568- screen_drawone(hDC, x, y);
569- screen_drawupate(x, y);
570- }
571- }
818+ /* クライアント領域の幅と高さを記憶 */
819+ object->width = rect.right - rect.left;
820+ assert(0 <= object->width);
821+ if (0 > object->width)
822+ {
823+ return FALSE;
824+ }
825+ object->height = rect.bottom - rect.top;
826+ assert(0 <= object->height);
827+ if (0 > object->height)
828+ {
829+ return FALSE;
572830 }
573831
574- /* フォントを戻す */
575- SelectObject(hDC, hDefFont);
832+ /* 垂直スクロールバーの有無で方向を設定 */
833+ object->virt.dir_up = object->vscroll;
834+
835+ /* リサイズによって仮想ラインを作成する */
836+ screen_allline_resize(object);
837+
838+ /* スクリーンの先頭によって分ける */
839+ if (NULL == g_screen_object_head)
840+ {
841+ /* 最初のオブジェクト */
842+ g_screen_object_head = object;
843+ }
844+ else
845+ {
846+ /* 既存のオブジェクトの末尾に追加 */
847+ bdlist_insert_tail((BDLIST_ENTRY*)g_screen_object_head, (BDLIST_ENTRY*)object);
848+ }
576849
577- /* 描画要求なし */
578- g_bRequestDraw = FALSE;
850+ /* 成功 */
851+ return FALSE;
579852 }
580853
581854 /*
582855 * スクリーン
583- * WM_PAINTメッセージハンドラ
856+ * WM_DESTROYハンドラ
584857 */
585-static void screen_onpaint(HWND hWnd)
858+static void screen_on_destroy(HWND hWnd)
586859 {
587- LONG x;
588- LONG y;
589- HDC hDC;
590- PAINTSTRUCT ps;
860+ SCREEN_OBJECT *object;
591861
592862 assert(NULL != hWnd);
593863
594- /* スクリーンの表示範囲について、描画キャラクタをヌル文字にする */
595- assert(0 <= g_lScreenHeight);
596- assert(0 <= g_lScreenWidth);
597- for (y = 0; y < g_lScreenHeight; y++)
864+ /* ウィンドウハンドルからオブジェクトを逆引きする */
865+ object = screen_get_object(hWnd);
866+ assert(NULL != object);
867+ if (NULL == object)
598868 {
599- for (x = 0; x < g_lScreenWidth; x++)
600- {
601- g_ScreenAry[y][x].draw.chr = L'\0';
602- }
869+ return;
603870 }
604871
605- /* 描画を開始(WM_ERASEBKGNDが送信される) */
606- hDC = BeginPaint(hWnd, &ps);
607- assert(NULL != hDC);
872+ /* スクリーンオブジェクトの描画を禁止する */
873+ screen_disable_object(object);
874+}
608875
609- /* 描画共通 */
610- screen_drawmain(hWnd, hDC);
876+/*
877+ * スクリーン
878+ * WM_NCDESTROYハンドラ
879+ */
880+static void screen_on_ncdestroy(HWND hWnd)
881+{
882+ SCREEN_OBJECT *object;
611883
612- /* 描画を終了 */
613- EndPaint(hWnd, &ps);
884+ assert(NULL != hWnd);
885+
886+ /* ウィンドウハンドルからオブジェクトを逆引きする */
887+ object = screen_get_object(hWnd);
888+ assert(NULL != object);
889+ if (NULL == object)
890+ {
891+ return;
892+ }
893+
894+ /* スクリーンオブジェクトを破棄する */
895+ screen_destroy_object(object);
614896 }
615897
616898 /*
617899 * スクリーン
618- * アイドル描画
900+ * WM_SIZEハンドラ
619901 */
620-static void screen_drawidle(void)
902+static void screen_on_size(HWND hWnd, int width, int height)
621903 {
904+ SCREEN_OBJECT *object;
905+
906+ assert(NULL != hWnd);
907+ assert(0 <= width);
908+ assert(0 <= height);
909+
910+ /* ウィンドウハンドルからオブジェクトを逆引きする */
911+ object = screen_get_object(hWnd);
912+ assert(NULL != object);
913+ if (NULL == object)
914+ {
915+ return;
916+ }
917+
918+ /* 幅と高さを更新 */
919+ object->width = width;
920+ object->height = height;
921+
922+ /* スクリーンのリサイズ */
923+ screen_allline_resize(object);
924+}
925+
926+/*
927+ * スクリーン
928+ * WM_PAINTハンドラ
929+ */
930+static void screen_on_paint(HWND hWnd)
931+{
932+ SCREEN_OBJECT *object;
622933 HDC hDC;
934+ PAINTSTRUCT ps;
935+
936+ assert(NULL != hWnd);
937+
938+ /* ウィンドウハンドルからオブジェクトを逆引きする */
939+ object = screen_get_object(hWnd);
940+ assert(NULL != object);
941+ if (NULL == object)
942+ {
943+ return;
944+ }
623945
624- assert(NULL != g_hScreenWnd);
946+ /* 全てのラインを無効化 */
947+ screen_allline_invalidate(object);
625948
626- /* デバイスコンテキストを取得 */
627- hDC = GetDC(g_hScreenWnd);
949+ /* 描画を開始(WM_ERASEBKGNDが送信される) */
950+ hDC = BeginPaint(hWnd, &ps);
628951 assert(NULL != hDC);
629952 if (NULL == hDC)
630953 {
631954 return;
632955 }
633956
634- /* 描画共通 */
635- screen_drawmain(g_hScreenWnd, hDC);
957+ /* 全てのラインを描画 */
958+ screen_allline_draw(hDC, object);
636959
637- /* デバイスコンテキストを解放 */
638- ReleaseDC(g_hScreenWnd, hDC);
960+ /* 描画を終了 */
961+ EndPaint(hWnd, &ps);
639962 }
640963
641964 /*
@@ -644,54 +967,52 @@ static void screen_drawidle(void)
644967 */
645968 static LRESULT CALLBACK screen_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
646969 {
647- BOOL bResult;
970+ LPCREATESTRUCT lpcs;
971+ BOOL result;
972+ int width;
973+ int height;
648974
649975 switch (uMsg)
650976 {
651977 /* ウィンドウが作成された */
652978 case WM_CREATE:
653- /* ハンドラを呼び出す */
654- bResult = screen_oncreate(hWnd);
655- assert(FALSE != bResult);
979+ lpcs = (LPCREATESTRUCT)lParam;
980+ result = screen_on_create(hWnd, lpcs);
656981
657982 /* ハンドラの結果によって、CreateWindowを失敗させる */
658- if (FALSE == bResult)
983+ if (FALSE == result)
659984 {
660- /* OnCreateに失敗 */
985+ /* 失敗 */
661986 return -1;
662987 }
663-
664- /* テスト */
665- screen_settextw(90, 1, RGB(255, 255, 0), RGB(128, 128, 128), L"文字平均幅 =%d", g_tm.tmAveCharWidth);
666- screen_settextw(90, 2, RGB(128, 128, 128), RGB(255, 255, 0), L"文字最大幅 =%d", g_tm.tmMaxCharWidth);
667- screen_settextw(90, 3, RGB(128, 128, 128), RGB(255, 255, 0), L"文字高さ =%d", g_tm.tmHeight + g_tm.tmExternalLeading);
668- screen_settextw(90, 4, RGB(128, 128, 128), RGB(255, 255, 0), L"文字最大高 =%d", g_tmAllHeight);
669-
670- /* 正常終了 */
988+ /* 成功 */
671989 return 0;
672990
673- /* ウィンドウが破棄された */
991+ /* ウィンドウが破棄された(子ウィンドウが破棄される前) */
674992 case WM_DESTROY:
675- /* ハンドラを呼び出す */
676- screen_ondestroy(hWnd);
993+ screen_on_destroy(hWnd);
994+ return 0;
995+
996+ /* ウィンドウが破棄された(子ウィンドウが破棄された後) */
997+ case WM_NCDESTROY:
998+ screen_on_ncdestroy(hWnd);
677999 return 0;
6781000
6791001 /* ウィンドウがリサイズされた*/
6801002 case WM_SIZE:
681- /* ハンドラを呼び出す */
682- screen_onsize(hWnd, (LONG)LOWORD(lParam), (LONG)HIWORD(lParam));
1003+ width = (int)LOWORD(lParam);
1004+ height = (int)HIWORD(lParam);
1005+ screen_on_size(hWnd, width, height);
6831006 return 0;
6841007
6851008 /* 背景を再描画する */
6861009 case WM_ERASEBKGND:
687- /* ハンドラを呼び出す */
688- screen_onerasebkgnd(hWnd, (HDC)wParam);
6891010 /* 自力でを背景を描画した場合は非ゼロを返す必要がある */
6901011 return 1;
6911012
6921013 /* ウィンドウを再描画する */
6931014 case WM_PAINT:
694- screen_onpaint(hWnd);
1015+ screen_on_paint(hWnd);
6951016 return 0;
6961017
6971018 /* その他 */
@@ -707,18 +1028,18 @@ static LRESULT CALLBACK screen_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
7071028 * スクリーン
7081029 * ウィンドウクラスの登録
7091030 */
710-static BOOL screen_register(void)
1031+static BOOL screen_register_class(void)
7111032 {
7121033 WNDCLASSEX wcex;
7131034
7141035 /* ゼロクリア */
715- ZeroMemory(&wcex, sizeof(wcex));
1036+ memset(&wcex, 0, sizeof(wcex));
7161037
7171038 /* 構造体サイズ */
7181039 wcex.cbSize = sizeof(wcex);
7191040
7201041 /* ウィンドウスタイル */
721- wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
1042+ wcex.style = CS_HREDRAW | CS_VREDRAW;
7221043
7231044 /* ウィンドウプロシージャ */
7241045 wcex.lpfnWndProc = screen_proc;
@@ -748,7 +1069,7 @@ static BOOL screen_register(void)
7481069 return FALSE;
7491070 }
7501071
751- /* 正常終了 */
1072+ /* 成功 */
7521073 return TRUE;
7531074 }
7541075
@@ -756,44 +1077,75 @@ static BOOL screen_register(void)
7561077 * スクリーン
7571078 * 初期化
7581079 */
759-BOOL screen_init(HWND hParentWnd, LONG lWidth, LONG lHeight)
1080+BOOL screen_init(void)
7601081 {
761- BOOL bResult;
762-
763- /* static変数を初期化 */
764- g_hScreenWnd = NULL;
765- g_lScreenWidth = 0;
766- g_lScreenHeight = 0;
767- g_lScreenExtWidth = 0;
768- g_lScreenExtHeight = 0;
769- ZeroMemory(g_ScreenAry, sizeof(g_ScreenAry));
770- g_bRequestDraw = TRUE;
1082+ BOOL result;
7711083
772- /* ウィンドウクラスの登録 */
773- bResult = screen_register();
774- assert(FALSE != bResult);
775- if (FALSE == bResult)
1084+ /* ウィンドウクラスを登録 */
1085+ result = screen_register();
1086+ assert(FALSE != result);
1087+ if (FALSE == result)
7761088 {
7771089 return FALSE;
7781090 }
7791091
1092+ /* スクリーン登録リストを初期化 */
1093+ g_screen_object_head = NULL;
1094+
1095+ /* 成功 */
1096+ return TRUE;
1097+}
1098+
1099+/*
1100+ * スクリーン
1101+ * 作成
1102+ */
1103+BOOL screen_create(SCREEN_OBJECT *screen)
1104+{
1105+ BOOL bResult;
1106+ DWORD dwStyle;
1107+
1108+ assert(NULL != screen);
1109+
1110+ /* 呼び出し元がセットする領域 */
1111+ assert(NULL != screen->name);
1112+ assert(NULL != screen->parent);
1113+ assert(0 <= screen->x);
1114+ assert(0 <= screen->y);
1115+ assert(0 <= screen->width);
1116+ assert(0 <= screen->height);
1117+
1118+ /* スクリーン側が管理する領域 */
1119+ memset(&screen->virt, 0, sizeof(screen->virt));
1120+ screen->update = FALSE;
1121+ screen->destroy = FALSE;
1122+ screen->hwnd = NULL;
1123+
1124+ /* ウィンドウスタイルの決定 */
1125+ dwStyle = WS_CHILD | WS_VISIBLE;
1126+ if (FALSE != screen->vscroll)
1127+ {
1128+ /* 垂直スクロールバーを追加する */
1129+ dwStyle |= WS_VSCROLL;
1130+ }
1131+
7801132 /* ウィンドウの作成 */
781- g_hScreenWnd = CreateWindow(
782- SCREEN_CLASS_NAME,
1133+ screen->hwnd = CreateWindow(
7831134 SCREEN_CLASS_NAME,
784- WS_CHILD | WS_VISIBLE,
785- 0,
786- 0,
787- lWidth,
788- lHeight,
789- hParentWnd,
1135+ screen->name,
1136+ dwStyle,
1137+ screen->x,
1138+ screen->y,
1139+ screen->width,
1140+ screen->height,
1141+ screen->parent,
7901142 NULL,
7911143 g_hAppInstance,
792- NULL);
1144+ (LPVOID)screen);
7931145
7941146 /* ウィンドウが作成できたかチェック */
795- assert(NULL != g_hScreenWnd);
796- if (NULL == g_hScreenWnd)
1147+ assert(NULL != screen->hwnd);
1148+ if (NULL == screen->hwnd)
7971149 {
7981150 return FALSE;
7991151 }
@@ -806,17 +1158,21 @@ BOOL screen_init(HWND hParentWnd, LONG lWidth, LONG lHeight)
8061158 * スクリーン
8071159 * リサイズ
8081160 */
809-void screen_resize(LONG lWidth, LONG lHeight)
1161+void screen_resize(SCREEN_OBJECT *screen)
8101162 {
8111163 BOOL bResult;
8121164
813- assert(NULL != g_hScreenWnd);
1165+ assert(NULL != screen);
8141166
815- bResult = MoveWindow(g_hScreenWnd, 0, 0, lWidth, lHeight, FALSE);
816- assert(bResult != FALSE);
817- if (bResult == FALSE)
1167+ /* 呼び出し元がセットする領域 */
1168+ assert(0 <= screen->x);
1169+ assert(0 <= screen->y);
1170+ assert(0 <= screen->width);
1171+ assert(0 <= screen->height);
1172+
1173+ if (NULL != screen->hwnd)
8181174 {
819- return;
1175+ MoveWindow(screen->hwnd, screen->x, screen->y, screen->width, screen->height, FALSE);
8201176 }
8211177 }
8221178
@@ -826,79 +1182,5 @@ void screen_resize(LONG lWidth, LONG lHeight)
8261182 */
8271183 void screen_idle(void)
8281184 {
829- SYSTEMTIME st;
830-
831- /* ウィンドウが有効で、描画要求が存在する場合 */
832- if ((NULL != g_hScreenWnd) && (FALSE != g_bRequestDraw))
833- {
834- /* アイドル描画 */
835- screen_drawidle();
836- }
837-
838- GetLocalTime(&st);
839- screen_settextw(90, 5, SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, L"%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
8401185 }
8411186
842-/*
843- * スクリーン
844- * 矩形コピー
845- */
846-void screen_copyregion(LONG left, LONG top, LONG width, LONG height, const SCREEN_CHR *ptr)
847-{
848- LONG x;
849- LONG y;
850- LONG width_cp;
851- LONG height_cp;
852-
853- assert(0 <= left);
854- assert(0 <= top);
855- assert(0 <= width);
856- assert(0 <= height);
857- assert(NULL != ptr);
858-
859- /* ウィンドウが有効の場合に限る */
860- if (NULL == g_hScreenWnd)
861- {
862- return;
863- }
864-
865- /* コピー幅を算出 */
866- width_cp = width;
867- if ((left + width_cp) > SCREEN_WIDTH_MAX)
868- {
869- width_cp = SCREEN_WIDTH_MAX - left;
870- }
871- if (0 >= width_cp)
872- {
873- /* コピーできる幅が0文字またはマイナス */
874- return;
875- }
876-
877- /* コピー高さを算出 */
878- height_cp = height;
879- if ((top + height_cp) > SCREEN_HEIGHT_MAX)
880- {
881- height_cp = SCREEN_HEIGHT_MAX - top;
882- }
883- if (0 >= height_cp)
884- {
885- /* コピーできる高さが0文字またはマイナス */
886- return;
887- }
888-
889- /* ループ */
890- for (y = 0; y < height_cp; y++)
891- {
892- for (x = 0; x < width_cp; x++)
893- {
894- /* コピー */
895- g_ScreenAry[y + top][x + left].current = ptr[x];
896-
897- /* 比較して描画要求 */
898- screen_requestdraw(x + left, y + top);
899- }
900-
901- /* ptrを進める */
902- ptr += width;
903- }
904-}
--- a/DebugMonitor/src/framework/screen.h
+++ b/DebugMonitor/src/framework/screen.h
@@ -7,6 +7,13 @@
77
88 #pragma once
99
10+#include "bdlist.h"
11+
12+/*
13+ * ウィンドウクラス
14+ */
15+#define SCREEN_CLASS_NAME L"ScreenWindow"
16+
1017 /*
1118 * キャラクタ構造体
1219 */
@@ -15,8 +22,8 @@ typedef struct _SCREEN_CHR
1522 /* キャラクタ(0x0100未満は半角、0x0100以上は全角 */
1623 wchar_t chr;
1724
18- /* 全角の左・右フラグ(TRUE:左、FALSE:右)。半角は常にTRUE */
19- BOOL lr;
25+ /* 全角の左・右フラグ(TRUE:右、FALSE:左)※半角は常にFALSE */
26+ BOOL right;
2027
2128 /* フォアグラウンドカラー(テキスト色) */
2229 COLORREF fore;
@@ -26,17 +33,133 @@ typedef struct _SCREEN_CHR
2633 } SCREEN_CHR;
2734
2835 /*
36+ * 仮想キャラクタ構造体
37+ */
38+typedef struct _SCREEN_VIRT_CHR
39+{
40+ /* 現在のキャラクタ */
41+ SCREEN_CHR current;
42+
43+ /* 描画したキャラクタ */
44+ SCREEN_CHR draw;
45+
46+ /* 描画座標(半角) */
47+ RECT rect_ank;
48+
49+ /* 描画座標(全角) */
50+ RECT rect_kanji;
51+} SCREEN_VIRT_CHR;
52+
53+/*
54+ * 仮想ライン構造体
55+ */
56+typedef struct _SCREEN_VIRT_LINE
57+{
58+ /* 仮想ライン単位で双方向リストを構成 */
59+ BDLIST_ENTRY bdlist;
60+
61+ /* このラインの文字数 */
62+ UINT chrs;
63+
64+ /* 仮想キャラクタ構造体の配列 */
65+ SCREEN_VIRT_CHR *chr;
66+} SCREEN_VIRT_LINE;
67+
68+/*
69+ * 仮想スクリーン構造体
70+ */
71+typedef struct _SCREEN_VIRT_SCREEN
72+{
73+ /* ラインの方向 */
74+ BOOL dir_up;
75+
76+ /* ウィンドウの幅(キャラクタ数) */
77+ UINT width_chr;
78+
79+ /* ウィンドウの高さ(キャラクタ数) */
80+ UINT height_chr;
81+
82+ /* ラインの数 */
83+ UINT lines;
84+
85+ /* 最初のライン */
86+ SCREEN_VIRT_LINE *head;
87+} SCREEN_VIRT_SCREEN;
88+
89+/*
90+ * スクリーンオブジェクト
91+ */
92+typedef struct _SCREEN_OBJECT
93+{
94+ /* スクリーン単位で双方向リストを構成 */
95+ BDLIST_ENTRY bdlist;
96+
97+ /*
98+ * 呼び出し元がセットする領域
99+ */
100+
101+ /* ウィンドウの名称 */
102+ LPWSTR name;
103+
104+ /* 親ウィンドウ */
105+ HWND parent;
106+
107+ /* 親ウィンドウクライアントのx座標 */
108+ int x;
109+
110+ /* 親ウィンドウクライアントのy座標 */
111+ int y;
112+
113+ /* ウィンドウの幅 */
114+ int width;
115+
116+ /* ウィンドウの高さ */
117+ int height;
118+
119+ /* 垂直スクロールバーの有無(表示方向を兼ねる) */
120+ BOOL vscroll;
121+
122+ /* デフォルトのフォアグラウンドカラー */
123+ COLORREF fore_def;
124+
125+ /* デフォルトのバックグラウンドカラー */
126+ COLORREF back_def;
127+
128+ /*
129+ * スクリーン側が管理する領域
130+ */
131+
132+ /* 仮想スクリーン */
133+ SCREEN_VIRT_SCREEN virt;
134+
135+ /* 描画中のフォアグラウンドカラー */
136+ COLORREF fore;
137+
138+ /* 描画中のバックグラウンドカラー */
139+ COLORREF back;
140+
141+ /* 更新要求フラグ */
142+ BOOL update;
143+
144+ /* 破棄フラグ */
145+ BOOL destroy;
146+
147+ /* ウィンドウハンドル */
148+ HWND hwnd;
149+} SCREEN_OBJECT;
150+
151+/*
29152 * グローバル関数
30153 */
31154
32155 /* 初期化 */
33-BOOL screen_init(HWND hParentWnd, LONG lWidth, LONG lHeight);
156+BOOL screen_init(void);
157+
158+/* 作成 */
159+BOOL screen_create(SCREEN_OBJECT *screen);
34160
35161 /* リサイズ */
36-void screen_resize(LONG lWidth, LONG lHeight);
162+void screen_resize(SCREEN_OBJECT *screen);
37163
38164 /* アイドル */
39-void screen_idle(void);
40-
41-/* 矩形コピー */
42-void screen_copyregion(LONG left, LONG top, LONG width, LONG height, const SCREEN_CHR *ptr);
165+void screen_idle(SCREEN_OBJECT *screen);
--- a/DebugMonitor/src/framework/winmain.c
+++ b/DebugMonitor/src/framework/winmain.c
@@ -7,6 +7,9 @@
77
88 #include "header.h"
99 #include "screen.h"
10+#include "console.h"
11+#include "monitor.h"
12+#include "listbox.h"
1013 #include "winmain.h"
1114
1215 /*
@@ -51,6 +54,12 @@ LONG g_tmAllHeight;
5154 /* フレームウィンドウのウインドウハンドル */
5255 static HWND g_hFrameWnd;
5356
57+/* コンソールウィンドウの幅 */
58+static LONG g_lConsoleWidth;
59+
60+/* コンソールウィンドウの高さ */
61+static LONG g_lConsoleHeight;
62+
5463 /* スクリーンウィンドウの幅 */
5564 static LONG g_lScreenWidth;
5665
@@ -65,9 +74,9 @@ static LONG g_lLogHeight;
6574
6675 /*
6776 * WinMain
68- * スクリーンウィンドウとログウィンドウのサイズを決定
77+ * サブウィンドウのサイズを決定
6978 */
70-static BOOL CalcSubWidthSize(HWND hWnd)
79+static void CalcSubWidthSize(HWND hWnd)
7180 {
7281 RECT rect;
7382 LONG lWidth;
@@ -77,7 +86,6 @@ static BOOL CalcSubWidthSize(HWND hWnd)
7786 LONG lChars;
7887 LONG lMod;
7988 BOOL bSuccess;
80- BOOL bCompare;
8189
8290 assert(NULL != hWnd);
8391 assert(0 < g_tmAllHeight);
@@ -129,61 +137,43 @@ static BOOL CalcSubWidthSize(HWND hWnd)
129137 }
130138 }
131139
132- /* lLogHeightに1キャラクタ分以上の高さがあれば、スクリーンを倍数に繰り上げる */
133140 if (FALSE == bSuccess)
134141 {
135- if (lLogHeight > g_tmAllHeight)
136- {
137- /* スクリーンの文字数と余りを得る */
138- lChars = (LONG)(lScreenHeight / g_tmAllHeight);
139- lMod = (LONG)(lScreenHeight % g_tmAllHeight);
142+ /* スクリーンの文字数と余りを得る */
143+ lChars = (LONG)(lScreenHeight / g_tmAllHeight);
144+ lMod = (LONG)(lScreenHeight % g_tmAllHeight);
140145
141- /* 余りがあるなら倍数に繰り上げ */
142- if (0 < lMod)
143- {
144- lChars++;
145- lScreenHeight = (LONG)(lChars * g_tmAllHeight);
146- lLogHeight = lHeight - lScreenHeight;
147- }
148-
149- /* 余りの有無にかかわらず確定 */
150- bSuccess = TRUE;
146+ /* 余りがあるなら繰り下げ */
147+ if (0 < lMod)
148+ {
149+ lScreenHeight = (LONG)(lChars * g_tmAllHeight);
150+ lLogHeight = lHeight - lScreenHeight;
151151 }
152- }
153152
154- /* すべてマッチした状態に初期化 */
155- bCompare = TRUE;
153+ /* 余りの有無にかかわらず確定 */
154+ bSuccess = TRUE;
155+ }
156156
157- /* 幅を比較 */
158- if ((lWidth != g_lScreenWidth) || (lWidth != g_lLogWidth))
157+ /* スクリーンの幅 */
158+ if (lWidth > g_lConsoleWidth)
159159 {
160- g_lScreenWidth = lWidth;
161- g_lLogWidth = lWidth;
162-
163- /* マッチ失敗 */
164- bCompare = FALSE;
160+ /* コンソールの余り領域を与える */
161+ g_lScreenWidth = lWidth - g_lConsoleWidth;
165162 }
166-
167- /* スクリーン高さを比較 */
168- if (lScreenHeight != g_lScreenHeight)
163+ else
169164 {
170- g_lScreenHeight = lScreenHeight;
171-
172- /* マッチ失敗 */
173- bCompare = FALSE;
165+ /* コンソールだけでも足りない */
166+ g_lScreenWidth = 0;
174167 }
175168
176- /* ログ高さを比較 */
177- if (lLogHeight != g_lLogHeight)
178- {
179- g_lLogHeight = lLogHeight;
169+ /* ログの幅 */
170+ g_lLogWidth = lWidth;
180171
181- /* マッチ失敗 */
182- bCompare = FALSE;
183- }
172+ /* スクリーンの高さ */
173+ g_lScreenHeight = lScreenHeight;
184174
185- /* マッチ結果を返す */
186- return bCompare;
175+ /* ログの高さ */
176+ g_lLogHeight = lLogHeight;
187177 }
188178
189179 /*
@@ -327,11 +317,22 @@ static BOOL OnCreate(HWND hWnd, const CREATESTRUCT *lpcs)
327317 return FALSE;
328318 }
329319
320+ /* コンソールの幅を算出 */
321+ g_lConsoleWidth = CONSOLE_WIDTH_MAX * g_tm.tmAveCharWidth + (LONG)GetSystemMetrics(SM_CXVSCROLL);
322+
330323 /* スクリーンとログのサイズを算出 */
331324 CalcSubWidthSize(hWnd);
332325
333- /* スクリーンを作成 */
334- bResult = screen_init(hWnd, g_lScreenWidth, g_lScreenHeight);
326+ /* モニタを作成 */
327+ bResult = monitor_init(hWnd, (int)g_lConsoleWidth, 0, (int)g_lScreenWidth, (int)g_lScreenHeight);
328+ assert(FALSE != bResult);
329+ if (FALSE == bResult)
330+ {
331+ return FALSE;
332+ }
333+
334+ /* リストボックスを作成 */
335+ bResult = listbox_init(hWnd, (int)0, (int)g_lScreenHeight, (int)g_lLogWidth, (int)g_lLogHeight);
335336 assert(FALSE != bResult);
336337 if (FALSE == bResult)
337338 {
@@ -373,8 +374,11 @@ static void OnSize(HWND hWnd)
373374 /* スクリーンとログのサイズを算出 */
374375 CalcSubWidthSize(hWnd);
375376
376- /* スクリーンのリサイズを要求 */
377- screen_resize(g_lScreenWidth, g_lScreenHeight);
377+ /* モニタのリサイズを要求 */
378+ monitor_resize((int)g_lConsoleWidth, 0, (int)g_lScreenWidth, (int)g_lScreenHeight);
379+
380+ /* リストボックスのリサイズを要求 */
381+ listbox_resize(0, (int)g_lScreenHeight,(int) g_lLogWidth, (int)g_lLogHeight);
378382 }
379383
380384 /*
@@ -486,6 +490,11 @@ static BOOL InitInstance(HINSTANCE hInstance)
486490 {
487491 BOOL bResult;
488492
493+#ifdef _DEBUG
494+ /* CRTデバッグフラグを設定 */
495+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
496+#endif /* _DEBUG */
497+
489498 /* インスタンスを記憶 */
490499 g_hAppInstance = hInstance;
491500
@@ -494,6 +503,8 @@ static BOOL InitInstance(HINSTANCE hInstance)
494503 ZeroMemory(&g_tm, sizeof(g_tm));
495504 g_tmAllHeight = 0;
496505 g_hFrameWnd = NULL;
506+ g_lConsoleWidth = 0;
507+ g_lConsoleHeight = 0;
497508 g_lScreenWidth = 0;
498509 g_lScreenHeight = 0;
499510 g_lLogWidth = 0;
@@ -583,7 +594,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine
583594 else
584595 {
585596 /* アイドル処理 */
586- screen_idle();
597+ monitor_idle();
587598
588599 /* 必ずSleepを入れる */
589600 Sleep(10);