|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "wxsoftkey.h"
1.1.1.4 root 8: #include "wxcolor.h"
1.1 root 9: #include "wxtextscreen.h"
1.1.1.4 root 10: #include "sram.h"
1.1 root 11:
12: //
1.1.1.4 root 13: // ソフトウェアキーボード (パネル) 共通部分
1.1 root 14: //
15:
1.1.1.4 root 16: // エンター記号。
17: // 描画の際にキー刻印文字列の半角文字数から描画幅を決定しており、
18: // エンター記号は半角2文字幅で描いているので実際の文字列も2文字にしておく。
19: // そうすると "\\n" が意味的にもちょうどいい。
20: // これは幅を算出するのに使うだけで表示はされない。
21: #define EnterMark "\\n"
22:
1.1 root 23: // イベントテーブル
1.1.1.4 root 24: wxBEGIN_EVENT_TABLE(WXSoftKeyPanel, inherited)
25: EVT_LEFT_DOWN(WXSoftKeyPanel::OnLeftDown)
26: EVT_LEFT_UP(WXSoftKeyPanel::OnLeftUp)
27: EVT_LEFT_DCLICK(WXSoftKeyPanel::OnLeftDClick)
28: EVT_RIGHT_DOWN(WXSoftKeyPanel::OnRightDown)
29: EVT_PAINT(WXSoftKeyPanel::OnPaint)
30: EVT_SIZE(WXSoftKeyPanel::OnSize)
1.1 root 31: wxEND_EVENT_TABLE()
32:
33: // コンストラクタ
1.1.1.4 root 34: WXSoftKeyPanel::WXSoftKeyPanel(wxWindow *parent,
35: int u_width_, int u_height_)
1.1 root 36: : inherited(parent)
37: {
1.1.1.4 root 38: u_width = u_width_;
39: u_height = u_height_;
1.1 root 40: }
41:
42: // デストラクタ
1.1.1.4 root 43: WXSoftKeyPanel::~WXSoftKeyPanel()
1.1 root 44: {
1.1.1.4 root 45: bitmap.reset();
46: image.reset();
47: bmpbuf.reset();
1.1 root 48: }
49:
50: // フォントサイズ変更 (外部インタフェース)
51: void
1.1.1.5 ! root 52: WXSoftKeyPanel::SetFontSize(FontId new_fontid)
1.1 root 53: {
54: // 同じなら何もしない
1.1.1.5 ! root 55: if (fontid == new_fontid) {
1.1 root 56: return;
57: }
58:
59: // フォントを更新
1.1.1.5 ! root 60: UpdateFont(new_fontid);
1.1 root 61:
62: // サイズ変更処理
63: DoSize();
64: }
65:
66: // サイズ変更処理
67: // サイズを変更したい時に呼ぶ (サイズが変更されたらではない)。
68: // ここではサイズは fontsize にのみ依存しているので、フォントサイズが
69: // 変化/確定した時に呼び出すこと。
70: void
1.1.1.4 root 71: WXSoftKeyPanel::DoSize()
1.1 root 72: {
1.1.1.5 ! root 73: assert(fontid != FontId::None);
1.1 root 74:
75: // このパネル内の描画の基本単位
76: unit = font_height / 4;
77:
78: // エンターキーだけ矩形でないのでここでリージョンを計算。
79: // unit が確定したところで一回行う。
80: //
81: // | ^ | \ | BS |
82: // | | | |
83: // +---+---+--(A)--+------(B)
84: // | | |
85: // | [ | |
86: // | | Enter |
87: // +---+---+--(F)-(E) |
88: // | | | |
89: // | : | ] | |
90: // | | | |
91: // +---+---+------(D)-----(C)
92: // | |
93: // | SHIFT |
94: const keydata_t& keybs = FindKeydata(KC_BS);
95: const keydata_t& keyleft = FindKeydata(KC_bracketleft);
96: const keydata_t& keyright = FindKeydata(KC_bracketright);
97: const keydata_t& keyshift = FindKeydata(KC_SHIFT_R);
98: // 各点のピクセル座標
99: enter_points = {
100: { keyleft.right() * unit, keyleft.y * unit }, // A
101: { keybs.right() * unit, keyleft.y * unit }, // B
102: { keyshift.right() * unit, keyshift.y * unit }, // C
103: { keyright.right() * unit, keyshift.y * unit }, // D
104: { keyright.right() * unit, keyright.y * unit }, // E
105: { keyleft.right() * unit, keyright.y * unit }, // F
106: };
107: // 当たり判定用のリージョン
108: enter_region = wxRegion(enter_points.size(), enter_points.data());
109:
110: // コントロールの大きさを変更
1.1.1.4 root 111: wxSize size(u_width * unit, u_height * unit);
1.1 root 112: SetClientSize(size);
113: SetMinSize(size);
114: }
115:
116: // サイズ変更イベント
117: void
1.1.1.4 root 118: WXSoftKeyPanel::OnSize(wxSizeEvent& event)
1.1 root 119: {
120: // Mac ではウィンドウ作成時に 0 以下の値が来ることがある
121: // GTK では 1 で来ることがある
1.1.1.5 ! root 122: const wxSize& size = event.GetSize();
1.1 root 123: if (size.x <= 1 || size.y <= 1) {
124: return;
125: }
126:
127: view_width = size.x;
128: view_height = size.y;
129:
130: // ビットマップを持っていれば一旦解放
1.1.1.4 root 131: bitmap.reset();
132: image.reset();
133: bmpbuf.reset();
1.1 root 134:
135: // ビットマップ作成
136: // 正しく描かれなかった時に分かりやすいよう初期値は濃いグレーにしておく
1.1.1.4 root 137: bmpbuf.reset(new uint8 [view_width * view_height * 3]);
138: memset(&bmpbuf[0], 0x70, view_width * view_height * 3);
139: image.reset(new wxImage(view_width, view_height, bmpbuf.get(), true));
140: bitmap.reset(new wxBitmap(*image));
1.1 root 141:
142: // 再描画を指示
143: Refresh();
144: }
145:
146: // 描画イベント (UI スレッドから呼ばれる)
147: void
1.1.1.4 root 148: WXSoftKeyPanel::OnPaint(wxPaintEvent& event)
1.1 root 149: {
150: // メモリ DC に描画
151: wxMemoryDC memDC;
152: memDC.SelectObject(*bitmap);
153: Draw(memDC);
154:
155: // 実画面 DC にコピー
156: wxPaintDC dstDC(this);
157: dstDC.Blit(0, 0, view_width, view_height, &memDC, 0, 0);
158: }
159:
160: // 描画本体
161: void
1.1.1.4 root 162: WXSoftKeyPanel::Draw(wxDC& dc)
1.1 root 163: {
1.1.1.4 root 164: dc.SetPen(wxPen(color.Background));
165: dc.SetBrush(wxBrush(color.Background));
1.1 root 166: dc.DrawRectangle(wxPoint(0, 0), GetSize());
167:
1.1.1.4 root 168: dc.SetPen(color.Text);
169: SetTextForeColor(color.Text);
170: for (const auto& key : GetKeydata()) {
1.1 root 171: if (hit[key.keycode]) {
172: // 押されている
1.1.1.4 root 173: SetTextBackColor(color.KeyPressed);
174: dc.SetBrush(color.KeyPressed);
1.1 root 175: } else {
176: // 押されていない
1.1.1.4 root 177: SetTextBackColor(color.Keytop[key.coltype]);
178: dc.SetBrush(wxBrush(color.Keytop[key.coltype]));
1.1 root 179: }
180:
181: // エンターキーだけ枠の描き方が違うので別処理
182: if (__predict_false(key.x < 0)) {
183: DrawEnterKey(dc);
184: } else {
185: DrawKey(dc, key);
186: }
187: }
188:
1.1.1.4 root 189: #if 0
190: // X68k キーボードだとどこに表示するか
191: SetTextBackColor(color.Background);
1.1.1.2 root 192: wxString utfstr(wxT("右クリックで長押し"));
1.1 root 193: const char *sjis = (const char *)utfstr.mb_str(conv);
194: DrawStringSJIS(dc, 190 * unit, 2 * unit, sjis, TA::Disable);
1.1.1.4 root 195: #endif
1.1 root 196: }
197:
198: // 指定のキーを一つ (枠から刻印まで) 描画する。
199: void
1.1.1.4 root 200: WXSoftKeyPanel::DrawKey(wxDC& dc, const keydata_t& key)
1.1 root 201: {
202: // 枠
203: wxPoint pt(key.x * unit, key.y * unit);
204: wxSize sz(key.w * unit + 1, key.h * unit + 1);
205: dc.DrawRectangle(pt, sz);
206:
207: // 刻印を選択
208: const char *disp = key.disp[modifier];
209: if (disp == NULL) {
210: disp = key.disp[0];
211: }
212:
213: // Shift_JIS に変換
214: wxString utfstr(disp, wxConvUTF8);
215: const char *sjis = (const char *)utfstr.mb_str(conv);
1.1.1.4 root 216: // 改行があれば2行に分割
217: char sjis1[8] {};
218: char sjis2[8] {};
219: int sjislen;
220: int row;
221: const char *lf = strchr(sjis, '\n');
222: if (lf == NULL) {
223: // 1行なら、Shift_JIS での文字数は半角換算の文字数と一致する。
224: sjislen = strlen(sjis);
225: row = 1;
226: } else {
227: // 2行に分割。センタリングは1行目の長さだけで調べる。
228: strncpy(sjis1, sjis, lf - sjis);
229: strcpy(sjis2, lf + 1);
230: sjislen = strlen(sjis1);
231: row = 2;
232: }
1.1 root 233:
234: // センタリング
235: int x = key.x + (key.w - sjislen * 2) / 2;
1.1.1.4 root 236: int y = key.y + (key.h - row * 4) / 2;
1.1 root 237:
1.1.1.4 root 238: // LED を描画 (機種によって色々違うので個別クラス側で処理)
239: if (key.led >= 0) {
1.1 root 240: const wxPen oldpen = dc.GetPen();
241: const wxBrush oldbrush = dc.GetBrush();
1.1.1.4 root 242:
243: y += DrawLED(dc, key);
244:
1.1 root 245: dc.SetPen(oldpen);
246: dc.SetBrush(oldbrush);
247: }
248:
249: // 文字を描画
250: pt = wxPoint(x * unit + 1, y * unit + 1);
1.1.1.4 root 251: if (strcmp(disp, EnterMark) == 0) {
1.1 root 252: DrawEnterMark(dc, pt);
253: } else {
1.1.1.4 root 254: if (lf == NULL) {
255: // 1行の場合
256: DrawStringSJIS(dc, pt.x, pt.y, sjis);
257: } else {
258: // 2行の場合
259: DrawStringSJIS(dc, pt.x, pt.y, sjis1);
260: pt.y += 4 * unit;
261: DrawStringSJIS(dc, pt.x, pt.y, sjis2);
262: }
1.1 root 263: }
264: }
265:
266: // エンターキー
267: void
1.1.1.4 root 268: WXSoftKeyPanel::DrawEnterKey(wxDC& dc)
1.1 root 269: {
270: // エンターキーを描画
271: dc.DrawPolygon(enter_points.size(), enter_points.data());
272:
273: // エンター記号を描画
274: DrawEnterMark(dc, wxPoint(
275: (enter_points[0].x + enter_points[1].x) / 2 - (4 / 2),
276: (enter_points[1].y + enter_points[2].y) / 2 - (4 / 2)));
277: }
278:
279: // 指定の位置にエンター記号を描画する (エンターキー全体の描画ではない)。
280: // メインキーとテンキーの両方で同じ図柄を使う。
281: // 大きさは (3unit, 4unit) なので実質全角1文字分くらい。
282: void
1.1.1.4 root 283: WXSoftKeyPanel::DrawEnterMark(wxDC& dc, const wxPoint& basep)
1.1 root 284: {
285: // エンター記号は幅 3 unit、高さ 4 unit。
286: // +0 +1 +2 +3
287: // +0 .. .. .. 1.
288: // .. .. .. 1.
289: // +1 .. .. .. 1.
290: // .. .. .. 1.
291: // +2 .. 1. .. 1.
292: // .1 .. .. 1.
293: // +3 11 11 11 1.
294: // .1 .. .. ..
295: // +4 .. 1. .. ..
296: // .. .. .. ..
297: static const std::vector<std::pair<int,int>> entermark {
298: { 3, 0 },
299: { 3, 3 }, // │
300: { 0, 3 }, // ─
301: { 1, 2 }, // /
302: { 0, 3 }, // (一筆書きなので戻る)
303: { 1, 4 }, // \
304: };
305: for (int i = 1; i < entermark.size(); i++) {
306: auto start = entermark[i - 1];
307: auto end = entermark[i];
308: wxPoint startp(start.first * unit, start.second * unit);
309: wxPoint endp(end.first * unit, end.second * unit);
310: dc.DrawLine(basep + startp, basep + endp);
311: }
312: }
313:
314: // keycode に対応する keydata を返す
315: const keydata_t&
1.1.1.4 root 316: WXSoftKeyPanel::FindKeydata(uint keycode) const
1.1 root 317: {
1.1.1.4 root 318: for (const auto& key : GetKeydata()) {
1.1 root 319: if (key.keycode == keycode) {
320: return key;
321: }
322: }
323: // 見付からないはずはない
1.1.1.3 root 324: assertmsg(0, "keycode %d not found", keycode);
1.1 root 325: }
326:
327: // マウス左クリック (Down) イベント
328: void
1.1.1.4 root 329: WXSoftKeyPanel::OnLeftDown(wxMouseEvent& event)
1.1 root 330: {
1.1.1.5 ! root 331: const wxPoint& pt = event.GetPosition();
1.1.1.4 root 332: const keydata_t *key = GetKeydataFromPoint(pt);
1.1 root 333:
1.1.1.4 root 334: DoLeftDown(key);
1.1 root 335: }
336:
337: // マウス左クリック (Down) 処理
338: void
1.1.1.4 root 339: WXSoftKeyPanel::DoLeftDown(const keydata_t *key)
1.1 root 340: {
1.1.1.4 root 341: if (key != NULL) {
342: uint code = key->keycode;
1.1 root 343: if (hit[code]) {
344: // 押下(長押し)中のキーならここで開放
1.1.1.4 root 345: KeyUp(*key);
1.1 root 346: } else {
347: // 押下して、LeftUp のために覚えておく
1.1.1.4 root 348: KeyDown(*key);
349: leftdown_key = key;
1.1 root 350: }
351: }
352: }
353:
354: // マウス左クリック (Up) イベント
355: void
1.1.1.4 root 356: WXSoftKeyPanel::OnLeftUp(wxMouseEvent& event)
1.1 root 357: {
358: // Up 時は、これが起きた地点のキーコードではなく
359: // 直近に LeftDown したキーコードをターゲットにする。
1.1.1.4 root 360: const keydata_t *key = leftdown_key;
1.1 root 361:
1.1.1.4 root 362: DoLeftUp(key);
1.1 root 363: }
364:
365: // マウス左クリック (Up) 処理
366: void
1.1.1.4 root 367: WXSoftKeyPanel::DoLeftUp(const keydata_t *key)
1.1 root 368: {
1.1.1.4 root 369: if (key != NULL) {
1.1 root 370: // 押されていたら開放
1.1.1.4 root 371: uint code = key->keycode;
1.1 root 372: if (hit[code]) {
1.1.1.4 root 373: KeyUp(*key);
1.1 root 374: }
375: }
1.1.1.4 root 376: leftdown_key = NULL;
1.1 root 377: }
378:
379: // マウス左ダブルクリックイベント
380: // ダブルクリックという操作に特別何かを割り当ててはいないが、
381: // キーを連打するとその間隔によってはダブルクリックと扱われるため、
382: // 受け取ってここで処理する。
383: //
384: // DClick イベントは LeftDown、LeftUp、LeftDClick、LeftUp の順で
385: // 飛んでくるので、ここでは2回目の押下だけ処理すればよい。というか
386: // 処理自体は LeftDown とまったく同じになるので、イベントテーブルで
387: // 直接 EVT_LEFT_DCLICK => OnLeftDown に割り付けることも出来そうだが
388: // デバッグが紛らわしくなりそうなので独立したイベントとしておく。
389: void
1.1.1.4 root 390: WXSoftKeyPanel::OnLeftDClick(wxMouseEvent& event)
1.1 root 391: {
1.1.1.5 ! root 392: const wxPoint& pt = event.GetPosition();
1.1.1.4 root 393: const keydata_t *key = GetKeydataFromPoint(pt);
1.1 root 394:
1.1.1.4 root 395: DoLeftDown(key);
1.1 root 396: }
397:
398: // マウス右クリック (Down) イベント
399: // 長押し開始/解除。
400: // 右クリックのほうは Down だけで Up は使わない。
401: void
1.1.1.4 root 402: WXSoftKeyPanel::OnRightDown(wxMouseEvent& event)
1.1 root 403: {
1.1.1.5 ! root 404: const wxPoint& pt = event.GetPosition();
1.1.1.4 root 405: const keydata_t *key = GetKeydataFromPoint(pt);
1.1 root 406:
1.1.1.4 root 407: if (key != NULL) {
408: uint code = key->keycode;
1.1 root 409: if (hit[code]) {
410: // 押されていたら開放
1.1.1.4 root 411: KeyUp(*key);
1.1 root 412: } else {
413: // 押されてなければ長押し開始
1.1.1.4 root 414: KeyDown(*key);
1.1 root 415: }
416: }
417: }
418:
1.1.1.4 root 419: // 座標からキーデータを返す。
420: // キーに当たっていなければ NULL を返す。
421: const keydata_t *
422: WXSoftKeyPanel::GetKeydataFromPoint(const wxPoint& pt) const
1.1 root 423: {
1.1.1.4 root 424: // エンターキーだけ先に別判定
425: if (enter_region.Contains(pt) == wxInRegion) {
426: return &FindKeydata(KC_enter);
427: }
1.1 root 428:
1.1.1.4 root 429: for (const auto& key : GetKeydata()) {
430: if (key.x < 0) {
431: continue;
1.1 root 432: }
1.1.1.4 root 433: // 始点と幅の +1/-1 は罫線の分
434: wxRect rect(
435: (key.x * unit) + 1,
436: (key.y * unit) + 1,
437: (key.w * unit) - 1,
438: (key.h * unit) - 1);
439: if (rect.Contains(pt)) {
440: return &key;
1.1 root 441: }
1.1.1.4 root 442: }
443: return NULL;
444: }
445:
446: //
447: // LUNA ソフトウェアキーボード (パネル)
448: //
449:
450: // コンストラクタ
451: WXLunaSoftKeyPanel::WXLunaSoftKeyPanel(wxWindow *parent)
452: : inherited(parent, 226, 54)
453: {
454: // LUNA では
455: // BS キーの左隣 (0x5c) は円記号ではなくバックスラッシュ。
456: // それを SHIFT したやつ(0x7c) は破線でないパイプ。
457: // そのもう一つ左隣 (0x7e) はオーバーラインではなくチルダ。
458: SetGlyph5C(true);
459: SetGlyph7E(true);
460:
461: // キートップの濃淡はユニバーサルデザインの推奨色ではないけど
462: // ここは見分けを付けるためではなくただのデザインなので。
463: if (1) {
464: // 白モデル
465: color = {
466: .Background = UD_LIGHT_GREY, // 現物新品は何色だったんだろう
467: .Text = *wxBLACK,
468: .Keytop = { *wxWHITE, wxColour(200, 200, 203) },
469: // 白黒共通
470: .KeyPressed = UD_BLUE,
471: .Border = *wxBLACK,
472: .LED = { UD_RED },
473: };
474: } else {
475: // 黒モデル
476: color = {
477: .Background = *wxBLACK,
478: .Text = *wxWHITE,
479: .Keytop = { wxColour(50, 50, 53), *wxBLACK },
480: // 白黒共通
481: .KeyPressed = UD_BLUE,
482: .Border = *wxBLACK,
483: .LED = { UD_RED },
484: };
485: }
486:
487: DoSize();
488: }
489:
490: // デストラクタ
491: WXLunaSoftKeyPanel::~WXLunaSoftKeyPanel()
492: {
493: }
494:
495: // LED を描画して刻印描画のための y offset を返す。
496: int
497: WXLunaSoftKeyPanel::DrawLED(wxDC& dc, const keydata_t& key)
498: {
499: const std::vector<bool>& led = gKeyboard->GetLED();
500:
501: if (led[key.led]) {
502: // 点灯時は赤、枠は黒
503: dc.SetPen(color.Border);
504: dc.SetBrush(color.LED[0]);
1.1 root 505: } else {
1.1.1.4 root 506: // 消灯時は元のキートップの色で、枠は薄めにしたい
507: dc.SetPen(GetTextDisableColor());
508: dc.SetBrush(color.Keytop[key.coltype]);
1.1 root 509: }
510:
1.1.1.4 root 511: // LED を左肩に描く
512: wxPoint pt = wxPoint(key.x * unit + 2, key.y * unit + 2);
513: wxSize sz = wxSize(4 * unit - 2, 3 * unit - 2);
514: dc.DrawRectangle(pt, sz);
515:
516: // そのため文字は少し下げる
517: return +1;
518: }
519:
520: // このキーが押された処理
521: void
522: WXLunaSoftKeyPanel::KeyDown(const keydata_t& key)
523: {
524: uint code = key.keycode;
525:
526: // 押された
527: hit[code] = true;
528:
529: // VM に通知 (Keyboard がそれをホストに通知するかはまた別)
530: gKeyboard->MakeKey(code);
531:
1.1 root 532: // 修飾キー
533: if (code == KC_SHIFT_L || code == KC_SHIFT_R) {
534: modifier = ModShift;
535: }
536:
537: // キー状態が変わった(かも知れない)ので再描画
538: Refresh();
539: }
540:
541: // このキーが放された処理
542: void
1.1.1.4 root 543: WXLunaSoftKeyPanel::KeyUp(const keydata_t& key)
1.1 root 544: {
1.1.1.4 root 545: uint code = key.keycode;
546:
547: // 放された
1.1 root 548: hit[code] = false;
1.1.1.4 root 549:
550: // VM に通知 (Keyboard がそれをホストに通知するかはまた別)
551: gKeyboard->BreakKey(code);
1.1 root 552:
553: // 修飾キー
554: if (code == KC_SHIFT_L || code == KC_SHIFT_R) {
555: modifier = ModNormal;
556: }
557:
558: // キー状態が変わった(かも知れない)ので再描画
559: Refresh();
560: }
561:
562: // キーデータ
563: #define H (8) // キーの高さ
564: #define L0 (2) // ファンクションキーの行
565: #define L1 (12) // ESC の行
566: #define L2 (20) // TAB の行
567: #define L3 (28) // CTRL の行
568: #define L4 (36) // SHIFT の行
569: #define L5 (44) // space の行
570: /*static*/ std::vector<keydata_t>
571: WXLunaSoftKeyPanel::keydata {
1.1.1.4 root 572: // +---- キートップの色(1:濃)
573: // | +- 0 以上なら LED 番号
574: // X Y W H C L KeyCode 通常 SHIFT
575: { 2, L0, 15, H, 1,-1, KC_F1, { "PF1" } },
576: { 17, L0, 15, H, 1,-1, KC_F2, { "PF2" } },
577: { 32, L0, 15, H, 1,-1, KC_F3, { "PF3" } },
578: { 47, L0, 15, H, 1,-1, KC_F4, { "PF4" } },
579: { 62, L0, 15, H, 1,-1, KC_F5, { "PF5" } },
580: { 81, L0, 15, H, 1,-1, KC_F6, { "PF6" } },
581: { 96, L0, 15, H, 1,-1, KC_F7, { "PF7" } },
582: { 111, L0, 15, H, 1,-1, KC_F8, { "PF8" } },
583: { 126, L0, 15, H, 1,-1, KC_F9, { "PF9" } },
584: { 141, L0, 15, H, 1,-1, KC_F10, { "PF10" } },
585:
586: { 2, L1, 12, H, 1,-1, KC_ESC, { "ESC" } },
587: { 14, L1, 10, H, 0,-1, KC_1, { "1", "!" } },
588: { 24, L1, 10, H, 0,-1, KC_2, { "2", "\"" } },
589: { 34, L1, 10, H, 0,-1, KC_3, { "3", "#" } },
590: { 44, L1, 10, H, 0,-1, KC_4, { "4", "$" } },
591: { 54, L1, 10, H, 0,-1, KC_5, { "5", "%" } },
592: { 64, L1, 10, H, 0,-1, KC_6, { "6", "&" } },
593: { 74, L1, 10, H, 0,-1, KC_7, { "7", "'" } },
594: { 84, L1, 10, H, 0,-1, KC_8, { "8", "(" } },
595: { 94, L1, 10, H, 0,-1, KC_9, { "9", ")" } },
596: { 104, L1, 10, H, 0,-1, KC_0, { "0", " " } },
597: { 114, L1, 10, H, 0,-1, KC_minus, { "-", "=" } },
598: { 124, L1, 10, H, 0,-1, KC_circum, { "^", "~" } },
599: { 134, L1, 10, H, 0,-1, KC_backslash, { "\\", "|" } },
600: { 144, L1, 12, H, 1,-1, KC_BS, { "BS" } },
601:
602: { 2, L2, 17, H, 1,-1, KC_TAB, { "TAB" } },
603: { 19, L2, 10, H, 0,-1, KC_Q, { "q", "Q" } },
604: { 29, L2, 10, H, 0,-1, KC_W, { "w", "W" } },
605: { 39, L2, 10, H, 0,-1, KC_E, { "e", "E" } },
606: { 49, L2, 10, H, 0,-1, KC_R, { "r", "R" } },
607: { 59, L2, 10, H, 0,-1, KC_T, { "t", "T" } },
608: { 69, L2, 10, H, 0,-1, KC_Y, { "y", "Y" } },
609: { 79, L2, 10, H, 0,-1, KC_U, { "u", "U" } },
610: { 89, L2, 10, H, 0,-1, KC_I, { "i", "I" } },
611: { 99, L2, 10, H, 0,-1, KC_O, { "o", "O" } },
612: { 109, L2, 10, H, 0,-1, KC_P, { "p", "P" } },
613: { 119, L2, 10, H, 0,-1, KC_at, { "@", "`" } },
614: { 129, L2, 10, H, 0,-1, KC_bracketleft, { "[", "{" } },
615:
616: { 2, L3, 20, H, 1,-1, KC_CTRL, { "CTRL" } },
617: { 22, L3, 10, H, 0,-1, KC_A, { "a", "A" } },
618: { 32, L3, 10, H, 0,-1, KC_S, { "s", "S" } },
619: { 42, L3, 10, H, 0,-1, KC_D, { "d", "D" } },
620: { 52, L3, 10, H, 0,-1, KC_F, { "f", "F" } },
621: { 62, L3, 10, H, 0,-1, KC_G, { "g", "G" } },
622: { 72, L3, 10, H, 0,-1, KC_H, { "h", "H" } },
623: { 82, L3, 10, H, 0,-1, KC_J, { "j", "J" } },
624: { 92, L3, 10, H, 0,-1, KC_K, { "k", "K" } },
625: { 102, L3, 10, H, 0,-1, KC_L, { "l", "L" } },
626: { 112, L3, 10, H, 0,-1, KC_semicolon, { ";", "+" } },
627: { 122, L3, 10, H, 0,-1, KC_colon, { ":", "*" } },
628: { 132, L3, 10, H, 0,-1, KC_bracketright, { "]", "}" } },
629:
630: { 2, L4, 25, H, 1,-1, KC_SHIFT_L, { "SHIFT" } },
631: { 27, L4, 10, H, 0,-1, KC_Z, { "z", "Z" } },
632: { 37, L4, 10, H, 0,-1, KC_X, { "x", "X" } },
633: { 47, L4, 10, H, 0,-1, KC_C, { "c", "C" } },
634: { 57, L4, 10, H, 0,-1, KC_V, { "v", "V" } },
635: { 67, L4, 10, H, 0,-1, KC_B, { "b", "B" } },
636: { 77, L4, 10, H, 0,-1, KC_N, { "n", "N" } },
637: { 87, L4, 10, H, 0,-1, KC_M, { "m", "M" } },
638: { 97, L4, 10, H, 0,-1, KC_comma, { ",", "<" } },
639: { 107, L4, 10, H, 0,-1, KC_period, { ".", ">" } },
640: { 117, L4, 10, H, 0,-1, KC_slash, { "/", "?" } },
641: { 127, L4, 10, H, 0,-1, KC_underscore, { " ", "_" } },
642: { 137, L4, 19, H, 1,-1, KC_SHIFT_R, { "SHIFT" } },
643:
644: { 2, L5, 20, H, 1,-1, KC_VALID, { "確定" } },
645: { 22, L5, 10, H, 1,-1, KC_SF, { "前面" } },
646: { 32, L5, 10, H, 1, 1, KC_CAPS, { "CAP" } },
647: { 42, L5, 80, H, 0,-1, KC_space, { " " } },
648: { 122, L5, 10, H, 1, 0, KC_kana, { "かな" } },
649: { 132, L5, 24, H, 1,-1, KC_XFER, { "変換" } },
1.1 root 650:
651: // カーソルキー島
1.1.1.4 root 652: { 160, L1, 10, H, 1,-1, KC_PF11, { "消去" } },
653: { 170, L1, 10, H, 1,-1, KC_PF12, { "呼出" } },
654: { 160, L2, 10, H, 1,-1, KC_PF13, { "文節\n←" } },
655: { 170, L2, 10, H, 1,-1, KC_PF14, { "文節\n→" } },
656: { 160, L3, 20, H, 1,-1, KC_up, { "↑" } },
657: { 160, L4, 10, H, 1,-1, KC_left, { "←" } },
658: { 170, L4, 10, H, 1,-1, KC_right, { "→" } },
659: { 160, L5, 20, H, 1,-1, KC_down, { "↓" } },
1.1 root 660:
661: // テンキー島
1.1.1.4 root 662: { 184, L1, 10, H, 1,-1, KC_DEL, { "DEL" } },
663: { 194, L1, 10, H, 1,-1, KC_PAD_plus, { "+" } },
664: { 204, L1, 10, H, 1,-1, KC_PAD_minus, { "-" } },
665: { 214, L1, 10, H, 1,-1, KC_PAD_multiply, { "*" } },
666:
667: { 184, L2, 10, H, 0,-1, KC_PAD_7, { "7" } },
668: { 194, L2, 10, H, 0,-1, KC_PAD_8, { "8" } },
669: { 204, L2, 10, H, 0,-1, KC_PAD_9, { "9" } },
670: { 214, L2, 10, H, 1,-1, KC_PAD_divide, { "/" } },
671:
672: { 184, L3, 10, H, 0,-1, KC_PAD_4, { "4" } },
673: { 194, L3, 10, H, 0,-1, KC_PAD_5, { "5" } },
674: { 204, L3, 10, H, 0,-1, KC_PAD_6, { "6" } },
675: { 214, L3, 10, H, 1,-1, KC_PAD_equal, { "=" } },
676:
677: { 184, L4, 10, H, 0,-1, KC_PAD_1, { "1" } },
678: { 194, L4, 10, H, 0,-1, KC_PAD_2, { "2" } },
679: { 204, L4, 10, H, 0,-1, KC_PAD_3, { "3" } },
680: { 214, L4, 10, H, 1,-1, KC_PAD_comma, { "," } },
681:
682: { 184, L5, 10, H, 0,-1, KC_PAD_0, { "0" } },
683: { 194, L5, 10, H, 0,-1, KC_PAD_decimal, { "." } },
684: { 204, L5, 20, H, 1,-1, KC_PAD_enter, { EnterMark } },
1.1 root 685:
686: // Enter だけ矩形でないので別処理するが
687: // この構造体には全部のキー情報が統一的に並んでいるほうがよかろう。
1.1.1.4 root 688: { -1, -1, -1, -1, 1,-1, KC_enter, { EnterMark } },
1.1 root 689: };
690:
691:
692: //
1.1.1.4 root 693: // X68k ソフトウェアキーボード (パネル)
694: //
695:
696: // コンストラクタ
697: WXX68kSoftKeyPanel::WXX68kSoftKeyPanel(wxWindow *parent)
698: : inherited(parent, 235, 54)
699: {
700: // X68k では SRAM 設定に同期させる。
701: uint8 sw = gSRAM->Peek8(0xed0059);
702: SetGlyph5C((sw & 0x01));
703: SetGlyph7E((sw & 0x02));
704: SetGlyph7C((sw & 0x04));
705:
706: // とりあえず黒のみ
707: color = {
708: .Background = wxColour(50, 50, 53),
709: .Text = *wxWHITE,
710: .Keytop = { *wxBLACK },
711: .KeyPressed = UD_BLUE,
712: .Border = *wxBLACK,
713: .LED = { UD_RED, UD_YELLOW_GREEN },
714: };
715:
716: DoSize();
717: }
718:
719: // デストラクタ
720: WXX68kSoftKeyPanel::~WXX68kSoftKeyPanel()
721: {
722: }
723:
724: // LED を描画して刻印描画のための y offset を返す。
725: int
726: WXX68kSoftKeyPanel::DrawLED(wxDC& dc, const keydata_t& key)
727: {
728: const std::vector<bool>& led = gKeyboard->GetLED();
729:
730: // 色を選択
731: // idx 刻印 色
732: // ----------------
733: // 0 かな 赤
734: // 1 ローマ 赤
735: // 2 コード 赤
736: // 3 CAPS 赤
737: // 4 INS 赤
738: // 5 ひら 緑
739: // 6 全角 緑
740: if (led[key.led]) {
741: int n = (key.led < 5) ? 0 : 1;
742: dc.SetPen(color.LED[n]);
743: dc.SetBrush(color.LED[n]);
744: } else {
745: // 消灯時は元のキートップの色で、枠は薄めにしたい
746: dc.SetPen(GetTextDisableColor());
747: dc.SetBrush(color.Keytop[key.coltype]);
748: }
749:
750: // LED は中央前方(画面でいうと下)
751: wxPoint pt = wxPoint((key.x + 3) * unit, (key.y + key.h - 2) * unit);
752: wxSize sz = wxSize(4 * unit, 2 * unit);
753: dc.DrawRectangle(pt, sz);
754:
755: // そのため文字は少し上げる
756: return -1;
757: }
758:
759: // このキーが押された処理
760: void
761: WXX68kSoftKeyPanel::KeyDown(const keydata_t& key)
762: {
763: uint code = key.keycode;
764:
765: // 押された
766: hit[code] = true;
767:
768: // VM に通知 (Keyboard がそれをホストに通知するかはまた別)
769: gKeyboard->MakeKey(code);
770:
771: // 修飾キー
772: if (code == KC_SHIFT_L || code == KC_SHIFT_R) {
773: modifier = ModShift;
774: }
775:
776: // キー状態が変わった(かも知れない)ので再描画
777: Refresh();
778: }
779:
780: // このキーが放された処理
781: void
782: WXX68kSoftKeyPanel::KeyUp(const keydata_t& key)
783: {
784: uint code = key.keycode;
785:
786: hit[code] = false;
787:
788: // VM に通知 (Keyboard がそれをホストに通知するかはまた別)
789: gKeyboard->BreakKey(code);
790:
791: // 修飾キー
792: if (code == KC_SHIFT_L || code == KC_SHIFT_R) {
793: modifier = ModNormal;
794: }
795:
796: // キー状態が変わった(かも知れない)ので再描画
797: Refresh();
798: }
799:
800: #define LF (L0 + 2) // ファンクションキーは少し低い(横長い)
801: #define HT (H * 2) // 縦2倍角のキー
802: /*static*/ std::vector<keydata_t>
803: WXX68kSoftKeyPanel::keydata {
804: // +- 0以上なら LED 番号
805: // X Y W H C L KeyCode 通常 SHIFT
806: { 2, L0, 10, H, 0,-1, KC_BREAK, { "BRK" } },
807: { 15, L0, 10, H, 0,-1, KC_COPY, { "COPY" } },
808: { 29, LF, 12, 6, 0,-1, KC_F1, { "F1" } },
809: { 41, LF, 12, 6, 0,-1, KC_F2, { "F2" } },
810: { 53, LF, 12, 6, 0,-1, KC_F3, { "F3" } },
811: { 65, LF, 12, 6, 0,-1, KC_F4, { "F4" } },
812: { 77, LF, 13, 6, 0,-1, KC_F5, { "F5" } },
813: { 94, LF, 13, 6, 0,-1, KC_F6, { "F6" } },
814: { 106, LF, 12, 6, 0,-1, KC_F7, { "F7" } },
815: { 118, LF, 12, 6, 0,-1, KC_F8, { "F8" } },
816: { 130, LF, 12, 6, 0,-1, KC_F9, { "F9" } },
817: { 142, LF, 13, 6, 0,-1, KC_F10, { "F10" } },
818:
819: { 2, L1, 10, H, 0,-1, KC_ESC, { "ESC" } },
820: { 12, L1, 10, H, 0,-1, KC_1, { "1", "!" } },
821: { 22, L1, 10, H, 0,-1, KC_2, { "2", "\"" } },
822: { 32, L1, 10, H, 0,-1, KC_3, { "3", "#" } },
823: { 42, L1, 10, H, 0,-1, KC_4, { "4", "$" } },
824: { 52, L1, 10, H, 0,-1, KC_5, { "5", "%" } },
825: { 62, L1, 10, H, 0,-1, KC_6, { "6", "&" } },
826: { 72, L1, 10, H, 0,-1, KC_7, { "7", "'" } },
827: { 82, L1, 10, H, 0,-1, KC_8, { "8", "(" } },
828: { 92, L1, 10, H, 0,-1, KC_9, { "9", ")" } },
829: { 102, L1, 10, H, 0,-1, KC_0, { "0", " " } },
830: { 112, L1, 10, H, 0,-1, KC_minus, { "-", "=" } },
831: { 122, L1, 10, H, 0,-1, KC_circum, { "^", "~" } },
832: { 132, L1, 10, H, 0,-1, KC_backslash, { "\\", "|" } },
833: { 142, L1, 13, H, 0,-1, KC_BS, { "BS" } },
834:
835: { 2, L2, 16, H, 0,-1, KC_TAB, { "TAB" } },
836: { 18, L2, 10, H, 0,-1, KC_Q, { "q", "Q" } },
837: { 28, L2, 10, H, 0,-1, KC_W, { "w", "W" } },
838: { 38, L2, 10, H, 0,-1, KC_E, { "e", "E" } },
839: { 48, L2, 10, H, 0,-1, KC_R, { "r", "R" } },
840: { 58, L2, 10, H, 0,-1, KC_T, { "t", "T" } },
841: { 68, L2, 10, H, 0,-1, KC_Y, { "y", "Y" } },
842: { 78, L2, 10, H, 0,-1, KC_U, { "u", "U" } },
843: { 88, L2, 10, H, 0,-1, KC_I, { "i", "I" } },
844: { 98, L2, 10, H, 0,-1, KC_O, { "o", "O" } },
845: { 108, L2, 10, H, 0,-1, KC_P, { "p", "P" } },
846: { 118, L2, 10, H, 0,-1, KC_at, { "@", "`" } },
847: { 128, L2, 10, H, 0,-1, KC_bracketleft, { "[", "{" } },
848:
849: { 2, L3, 19, H, 0,-1, KC_CTRL, { "CTRL" } },
850: { 21, L3, 10, H, 0,-1, KC_A, { "a", "A" } },
851: { 31, L3, 10, H, 0,-1, KC_S, { "s", "S" } },
852: { 41, L3, 10, H, 0,-1, KC_D, { "d", "D" } },
853: { 51, L3, 10, H, 0,-1, KC_F, { "f", "F" } },
854: { 61, L3, 10, H, 0,-1, KC_G, { "g", "G" } },
855: { 71, L3, 10, H, 0,-1, KC_H, { "h", "H" } },
856: { 81, L3, 10, H, 0,-1, KC_J, { "j", "J" } },
857: { 91, L3, 10, H, 0,-1, KC_K, { "k", "K" } },
858: { 101, L3, 10, H, 0,-1, KC_L, { "l", "L" } },
859: { 111, L3, 10, H, 0,-1, KC_semicolon, { ";", "+" } },
860: { 121, L3, 10, H, 0,-1, KC_colon, { ":", "*" } },
861: { 131, L3, 10, H, 0,-1, KC_bracketright, { "]", "}" } },
862:
863: { 2, L4, 24, H, 0,-1, KC_SHIFT_L, { "SHIFT" } },
864: { 26, L4, 10, H, 0,-1, KC_Z, { "z", "Z" } },
865: { 36, L4, 10, H, 0,-1, KC_X, { "x", "X" } },
866: { 46, L4, 10, H, 0,-1, KC_C, { "c", "C" } },
867: { 56, L4, 10, H, 0,-1, KC_V, { "v", "V" } },
868: { 66, L4, 10, H, 0,-1, KC_B, { "b", "B" } },
869: { 76, L4, 10, H, 0,-1, KC_N, { "n", "N" } },
870: { 86, L4, 10, H, 0,-1, KC_M, { "m", "M" } },
871: { 96, L4, 10, H, 0,-1, KC_comma, { ",", "<" } },
872: { 106, L4, 10, H, 0,-1, KC_period, { ".", ">" } },
873: { 116, L4, 10, H, 0,-1, KC_slash, { "/", "?" } },
874: { 126, L4, 10, H, 0,-1, KC_underscore, { " ", "_" } },
875: { 136, L4, 19, H, 0,-1, KC_SHIFT_R, { "SHIFT" } },
876:
877: { 21, L5, 10, H, 0, 5, KC_hira, { "ひら" } },
878: { 31, L5, 12, H, 0,-1, KC_XF1, { "XF1" } },
879: { 43, L5, 13, H, 0,-1, KC_XF2, { "XF2" } },
880: { 56, L5, 36, H, 0,-1, KC_space, { " " } },
881: { 92, L5, 12, H, 0,-1, KC_XF3, { "XF3" } },
882: { 104, L5, 12, H, 0,-1, KC_XF4, { "XF4" } },
883: { 116, L5, 12, H, 0,-1, KC_XF5, { "XF5" } },
884: { 128, L5, 10, H, 0, 6, KC_zenkaku, { "全角" } },
885:
886: // カーソルキー島
887: { 159, L0, 10, H, 0, 0, KC_kana, { "かな" } },
888: { 169, L0, 10, H, 0, 1, KC_romaji, { "ローマ" } },
889: { 179, L0, 10, H, 0, 2, KC_code, { "コード" } },
890: { 159, L1, 10, H, 0,-1, KC_HOME, { "HOME" } },
891: { 169, L1, 10, H, 0, 4, KC_INS, { "INS" } },
892: { 179, L1, 10, H, 0,-1, KC_DEL, { "DEL" } },
893: { 159, L2, 10, H, 0,-1, KC_ROLLUP, { "ROLL\n UP" } },
894: { 169, L2, 10, H, 0,-1, KC_ROLLDOWN, { "ROLL\nDOWN" } },
895: { 179, L2, 10, H, 0,-1, KC_UNDO, { "UNDO" } },
896: { 169, L3, 10, H, 0,-1, KC_up, { "↑" } },
897: { 159, L3, 10, HT,0,-1, KC_left, { "←" } },
898: { 179, L3, 10, HT,0,-1, KC_right, { "→" } },
899: { 169, L4, 10, H, 0,-1, KC_down, { "↓" } },
900: { 159, L5, 15, H, 0,-1, KC_OPT1, { "OPT.1" } },
901: { 174, L5, 15, H, 0,-1, KC_OPT2, { "OPT.2" } },
902:
903: // テンキー島
904: { 193, L0, 10, H, 0, 3, KC_CAPS, { "CAPS" } },
905: { 203, L0, 10, H, 0,-1, KC_kigou, { "記号" } },
906: { 213, L0, 10, H, 0,-1, KC_touroku, { "登録" } },
907: { 223, L0, 10, H, 0,-1, KC_HELP, { "HELP" } },
908: { 193, L1, 10, H, 0,-1, KC_PAD_CLR, { "CLR" } },
909: { 203, L1, 10, H, 0,-1, KC_PAD_divide, { "/" } },
910: { 213, L1, 10, H, 0,-1, KC_PAD_multiply, { "*" } },
911: { 223, L1, 10, H, 0,-1, KC_PAD_minus, { "-" } },
912: { 193, L2, 10, H, 0,-1, KC_PAD_7, { "7" } },
913: { 203, L2, 10, H, 0,-1, KC_PAD_8, { "8" } },
914: { 213, L2, 10, H, 0,-1, KC_PAD_9, { "9" } },
915: { 223, L2, 10, H, 0,-1, KC_PAD_plus, { "+" } },
916: { 193, L3, 10, H, 0,-1, KC_PAD_4, { "4" } },
917: { 203, L3, 10, H, 0,-1, KC_PAD_5, { "5" } },
918: { 213, L3, 10, H, 0,-1, KC_PAD_6, { "6" } },
919: { 223, L3, 10, H, 0,-1, KC_PAD_equal, { "=" } },
920: { 193, L4, 10, H, 0,-1, KC_PAD_1, { "1" } },
921: { 203, L4, 10, H, 0,-1, KC_PAD_2, { "2" } },
922: { 213, L4, 10, H, 0,-1, KC_PAD_3, { "3" } },
923: { 223, L4, 10, HT,0,-1, KC_PAD_enter, { "ENT" } },
924: { 193, L5, 10, H, 0,-1, KC_PAD_0, { "0" } },
925: { 203, L5, 10, H, 0,-1, KC_PAD_comma, { "," } },
926: { 213, L5, 10, H, 0,-1, KC_PAD_decimal, { "." } },
927:
928: // Enter だけ矩形でないので別処理するが
929: // この構造体には全部のキー情報が統一的に並んでいるほうがよかろう。
930: { -1, -1, -1, -1, 0,-1, KC_enter, { EnterMark } },
931: };
932:
933: //
1.1 root 934: // LUNA ソフトウェアキーボード (ウィンドウ)
935: //
936:
937: // コンストラクタ
938: WXLunaSoftKeyWindow::WXLunaSoftKeyWindow(wxWindow *parent, wxWindowID id)
1.1.1.4 root 939: : inherited(parent, id, _("Software Keyboard"))
1.1 root 940: {
941: panel = new WXLunaSoftKeyPanel(this);
942:
943: // 大きさをそれに固定
944: Layout();
945: Fit();
946: }
947:
948: // デストラクタ
949: WXLunaSoftKeyWindow::~WXLunaSoftKeyWindow()
950: {
951: }
952:
1.1.1.4 root 953: //
954: // X680x0 ソフトウェアキーボード (ウィンドウ)
955: //
956:
957: // コンストラクタ
958: WXX68kSoftKeyWindow::WXX68kSoftKeyWindow(wxWindow *parent, wxWindowID id)
959: : inherited(parent, id, _("Software Keyboard"))
960: {
961: panel = new WXX68kSoftKeyPanel(this);
962:
963: // 大きさをそれに固定
964: Layout();
965: Fit();
966: }
967:
968: // デストラクタ
969: WXX68kSoftKeyWindow::~WXX68kSoftKeyWindow()
970: {
971: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.