Annotation of nono/wx/wxsoftkey.cpp, revision 1.1.1.12

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: 
1.1.1.11  root        7: //
                      8: // ソフトウェアキーボード
                      9: //
                     10: 
1.1       root       11: #include "wxsoftkey.h"
1.1.1.11  root       12: #include "fontmanager.h"
1.1.1.4   root       13: #include "wxcolor.h"
1.1.1.6   root       14: #include "wxmainview.h"
1.1.1.8   root       15: #include "wxuimessage.h"
1.1.1.4   root       16: #include "sram.h"
1.1       root       17: 
                     18: //
1.1.1.4   root       19: // ソフトウェアキーボード (パネル) 共通部分
1.1       root       20: //
                     21: 
1.1.1.4   root       22: // エンター記号。
                     23: // 描画の際にキー刻印文字列の半角文字数から描画幅を決定しており、
                     24: // エンター記号は半角2文字幅で描いているので実際の文字列も2文字にしておく。
                     25: // そうすると "\\n" が意味的にもちょうどいい。
                     26: // これは幅を算出するのに使うだけで表示はされない。
                     27: #define EnterMark      "\\n"
                     28: 
1.1       root       29: // イベントテーブル
1.1.1.4   root       30: wxBEGIN_EVENT_TABLE(WXSoftKeyPanel, inherited)
                     31:        EVT_LEFT_DOWN(WXSoftKeyPanel::OnLeftDown)
                     32:        EVT_LEFT_UP(WXSoftKeyPanel::OnLeftUp)
                     33:        EVT_LEFT_DCLICK(WXSoftKeyPanel::OnLeftDClick)
                     34:        EVT_RIGHT_DOWN(WXSoftKeyPanel::OnRightDown)
1.1.1.9   root       35:        EVT_TIMER(wxID_ANY, WXSoftKeyPanel::OnTimer)
1.1       root       36: wxEND_EVENT_TABLE()
                     37: 
                     38: // コンストラクタ
1.1.1.4   root       39: WXSoftKeyPanel::WXSoftKeyPanel(wxWindow *parent,
1.1.1.6   root       40:        const std::vector<keydata_t>& keydata_, int u_width_, int u_height_)
1.1       root       41:        : inherited(parent)
1.1.1.6   root       42:        , keydata(keydata_)
1.1       root       43: {
1.1.1.9   root       44:        timer.SetOwner(this);
                     45: 
1.1.1.4   root       46:        u_width  = u_width_;
                     47:        u_height = u_height_;
1.1.1.6   root       48: 
1.1.1.11  root       49:        FontChanged();
1.1.1.7   root       50: 
1.1.1.10  root       51:        // トグル動作にするキー
                     52:        toggle.emplace(KC_SHIFT, 0);
                     53:        toggle.emplace(KC_SHIFT_L, 0);
                     54:        toggle.emplace(KC_SHIFT_R, 0);
                     55:        toggle.emplace(KC_CTRL, 0);
                     56: 
1.1.1.9   root       57:        // 残光の初期化。
                     58:        // persistence は keydata 分の配列ではなく共通キーコード分の配列。
                     59:        persistence.resize(KC_max);
                     60:        std::fill(persistence.begin(), persistence.end(), 0);
                     61: 
1.1.1.6   root       62:        // このパネルへのキー入力はメインビューへのキー入力と同じ。
1.1.1.9   root       63:        Connect(wxEVT_CHAR, wxCharEventHandler(WXMainView::OnChar), NULL,
                     64:                gMainView);
1.1.1.6   root       65:        Connect(wxEVT_KEY_UP, wxKeyEventHandler(WXMainView::OnKeyUp), NULL,
                     66:                gMainView);
                     67:        Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(WXMainView::OnKeyDown), NULL,
                     68:                gMainView);
                     69: 
1.1.1.8   root       70:        // VM からの通知を受け取る
                     71:        WXUIMessage::Connect(UIMessage::KEYBOARD, this,
                     72:                wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged));
1.1.1.11  root       73: 
                     74:        // 初期タイトルを保存しといて..
                     75:        title = dynamic_cast<wxFrame*>(parent)->GetTitle();
                     76:        // キーボードの接続状況でタイトルを更新する
                     77:        UpdateTitle();
1.1       root       78: }
                     79: 
                     80: // デストラクタ
1.1.1.4   root       81: WXSoftKeyPanel::~WXSoftKeyPanel()
1.1       root       82: {
1.1.1.10  root       83:        // ウィンドウクローズでトグルキーのワンショットは開放する
1.1.1.9   root       84:        // (長押しは開放しない)
1.1.1.10  root       85:        for (const auto& k : toggle) {
                     86:                auto code = k.second;
                     87:                if (code) {
                     88:                        KeyUp(code);
                     89:                }
                     90:        }
1.1.1.9   root       91: 
                     92:        timer.Stop();
                     93: 
1.1.1.8   root       94:        WXUIMessage::Disconnect(UIMessage::KEYBOARD,
                     95:                wxCommandEventHandler(WXSoftKeyPanel::OnKeyChanged));
1.1       root       96: }
                     97: 
1.1.1.11  root       98: // キーボードの接続状況によって親フレームのタイトルを更新する。
                     99: // ついでにメンバ変数を更新する。
                    100: void
                    101: WXSoftKeyPanel::UpdateTitle()
                    102: {
                    103:        auto parent = dynamic_cast<WXSoftKeyWindow *>(GetParent());
                    104:        assert(parent);
                    105: 
                    106:        // 次回比較用にメンバ変数に覚えておく
                    107:        connected = gKeyboard->IsConnected();
                    108: 
                    109:        if (connected) {
                    110:                parent->SetTitle(title);
                    111:        } else {
                    112:                parent->SetTitle(title + _(" (disconnected)"));
                    113:        }
                    114: }
                    115: 
1.1.1.9   root      116: // color.Keytop の初期化(補間)。
                    117: // num はキートップの種類の数。1 か 2
                    118: void
                    119: WXSoftKeyPanel::InitColorKeytop(int num)
                    120: {
1.1.1.11  root      121:        Color pressed = UD_BLUE;
1.1.1.9   root      122: 
                    123:        auto f = [](int a, int b, int x) {
                    124:                return a * x / 100 + b * (100 - x) / 100;
                    125:        };
                    126: 
                    127:        // Keytop[i][9] は押されたときの色
                    128:        // Keytop[i][0] は押されていないときの色
                    129:        for (int i = 0; i < num; i++) {
                    130:                for (int j = 1; j < 10; j++) {
                    131:                        int n = j * 100 / 9;
1.1.1.11  root      132:                        color.Keytop[i][j] = Color(
                    133:                                f(pressed.r, color.Keytop[i][0].r, n),
                    134:                                f(pressed.g, color.Keytop[i][0].g, n),
                    135:                                f(pressed.b, color.Keytop[i][0].b, n));
1.1.1.9   root      136:                }
                    137:        }
                    138: }
                    139: 
1.1.1.11  root      140: // フォントサイズ変更
1.1       root      141: void
1.1.1.11  root      142: WXSoftKeyPanel::FontChanged()
1.1       root      143: {
1.1.1.11  root      144:        inherited::FontChanged();
1.1       root      145: 
                    146:        // このパネル内の描画の基本単位
                    147:        unit = font_height / 4;
                    148: 
                    149:        // エンターキーだけ矩形でないのでここでリージョンを計算。
                    150:        // unit が確定したところで一回行う。
1.1.1.6   root      151:        // ただし SHIFT_R のキーコードはちょっと使いづらいので、ここでは SHIFT_R
                    152:        // を使わず [_] キーで代用する。
                    153:        //
                    154:        //   |   ^   |   \   |   BS  |
                    155:        //   |       |       |       |
                    156:        // --+---+---+--(A)--+------(B)
                    157:        //       |       |           |
1.1.1.11  root      158:        //       |   [   |   Enter   |
                    159:        //       |       |           |
                    160:        // --+---+---+--(F)-(E) - - (G)
1.1.1.6   root      161:        //   |       |       |       |
                    162:        //   |   :   |   ]   |       |
                    163:        //   |       |       |       |
                    164:        // --+---+---+------(D)-----(C)
                    165:        //       |                   |
                    166:        //   _   |      SHIFT        |
1.1       root      167:        //
1.1.1.11  root      168:        // Enter キーの上半分 A-B-G-F を enter_top。F-G の線分を含む。
                    169:        // Enter キーの下半分 E-G-C-D を enter_btm。E-G の線分を含む。
1.1       root      170:        const keydata_t& keybs = FindKeydata(KC_BS);
                    171:        const keydata_t& keyleft = FindKeydata(KC_bracketleft);
                    172:        const keydata_t& keyright = FindKeydata(KC_bracketright);
1.1.1.6   root      173:        const keydata_t& keyscore = FindKeydata(KC_underscore);
1.1.1.11  root      174:        enter_top.SetLTRB(
                    175:                keyleft.right() * unit, keyleft.y * unit,
                    176:                keybs.right() * unit, keyright.y * unit);
                    177:        enter_btm.SetLTRB(
                    178:                keyright.right() * unit, keyright.y * unit,
                    179:                keybs.right() * unit, keyscore.y * unit);
1.1       root      180: 
                    181:        // コントロールの大きさを変更
1.1.1.4   root      182:        wxSize size(u_width * unit, u_height * unit);
1.1       root      183:        SetClientSize(size);
1.1.1.6   root      184:        SetMinClientSize(size);
1.1       root      185: }
                    186: 
1.1.1.9   root      187: void
                    188: WXSoftKeyPanel::OnTimer(wxTimerEvent& event)
                    189: {
                    190:        Refresh();
                    191: }
                    192: 
1.1.1.8   root      193: // キー状態変更イベント (UIMessage)
1.1.1.9   root      194: //
                    195: // キー状態変更イベントは、キーの状態が変わるたびに都度通知される。
                    196: // ソフトウェアキーボード入力とパススルーモードの入力では、どのキーに変化
                    197: // (押下 or 開放)があったかの情報は付属しない。各キーの押下状態は全キーを
                    198: // 逐一調査することで判定する。人間時間で起きる事象なのでこの計算量は許容。
                    199: // Char 入力モードの場合は、イベントのパラメータ引数 (GetInt() で取得可) に
                    200: // 入力のあったキーの共通キーコードが入っている (複数のキーが同時に押される
                    201: // 場合はキーの回数分のイベントが飛んでくる)。Char 入力モードにはキー開放
                    202: // という概念はない。
1.1.1.6   root      203: void
1.1.1.8   root      204: WXSoftKeyPanel::OnKeyChanged(wxCommandEvent& event)
1.1.1.6   root      205: {
1.1.1.9   root      206:        // Char 入力モードでキーが押された場合は、共通キーコードが送られてくるので、
                    207:        // persistence[] をここでセットする。
                    208:        // Char 入力モードでは、キーの Make/Break が一瞬で終わるため、このイベント
                    209:        // を受け取って Refresh() を発行 -> OnPaint() -> Draw() 内で IsPressed()
                    210:        // を調べた頃にはタイミング問題でもうキーが離されている可能性があるので、
                    211:        // 描画時に全キーを調べる方法は使えない。
                    212:        uint keycode = event.GetInt();
                    213:        if (keycode != 0) {
                    214:                assert(keycode < persistence.size());
                    215:                // 9 が減光時の初期値 (10 は減光しない点灯)
                    216:                persistence[keycode] = 9;
1.1.1.6   root      217:        }
1.1.1.9   root      218: 
1.1.1.10  root      219:        // トグルキーが開放されていたらトグル情報をクリアする。
                    220:        // ハードウェアキーボードを含む VM 側で開放された場合と、
                    221:        // ソフトウェアキーボードの KeyUp() で開放された場合のどちらも
                    222:        // ここでクリア。
                    223:        for (auto& k : toggle) {
                    224:                if (gKeyboard->IsPressed(k.first) == false) {
                    225:                        k.second = 0;
                    226:                }
                    227:        }
                    228: 
1.1.1.11  root      229:        // 接続状況が変わっていたらタイトルを更新。
                    230:        if (gKeyboard->IsConnected() != connected) {
                    231:                UpdateTitle();
                    232:        }
1.1.1.6   root      233: 
1.1.1.11  root      234:        Refresh();
1.1       root      235: }
                    236: 
                    237: // 描画本体
                    238: void
1.1.1.11  root      239: WXSoftKeyPanel::Draw()
1.1       root      240: {
1.1.1.9   root      241:        bool timer_start = false;
                    242: 
                    243:        // キー刻印の表示更新用に修飾キーの状態を更新。
                    244:        // 本来は IsShift() だけで判定すべきだが、Char 入力モードでいずれかの
                    245:        // SHIFT キーが減光中は SHIFT 刻印を継続してみるのはどうか。
                    246:        // 0 まで待つとうちの環境だと消灯した少し後に刻印が戻るように見えるため、
                    247:        // ある程度暗くなったところでもう切り替えてみる。閾値は適当。
                    248:        if ((2 < persistence[KC_SHIFT_L] && persistence[KC_SHIFT_L] < 10) ||
                    249:            (2 < persistence[KC_SHIFT_R] && persistence[KC_SHIFT_R] < 10) ||
                    250:                (2 < persistence[KC_SHIFT]   && persistence[KC_SHIFT]   < 10) ||
                    251:                gKeyboard->IsShift())
                    252:        {
                    253:                modifier = ModShift;
                    254:        } else {
                    255:                modifier = ModNormal;
                    256:        }
                    257: 
1.1.1.11  root      258:        auto text_color = color.Text;
                    259: 
                    260:        // キーボードが接続されていないときは刻印をグレーにしておく
                    261:        if (gKeyboard->IsConnected() == false) {
                    262:                text_color = UD_GREY;
                    263:        }
                    264:        SetTextForeColor(text_color);
1.1       root      265: 
1.1.1.6   root      266:        for (const auto& key : keydata) {
1.1.1.9   root      267:                int c = persistence[key.keycode];
                    268:                if (0 < c && c < 10) {
                    269:                        // Char 入力モードで減光中
                    270:                        c--;
                    271:                        timer_start = true;
1.1       root      272:                } else {
1.1.1.9   root      273:                        // そうでない場合に限り、現在の状態を問い合わせる
                    274:                        bool is_pressed = gKeyboard->IsPressed(key.keycode);
                    275:                        if (is_pressed) {
                    276:                                // 押されている
                    277:                                c = 10;
                    278:                        } else {
                    279:                                // 押されていない
                    280:                                c = 0;
                    281:                        }
                    282:                }
                    283:                // persistence[] は 10 が(減光しない)点灯、9..1 が減光中を示す。
                    284:                persistence[key.keycode] = c;
                    285:                // ただし色配列は 0..9 で 9 が最大点灯色
                    286:                if (c > 9) {
                    287:                        c = 9;
1.1       root      288:                }
                    289: 
1.1.1.9   root      290:                SetTextBackColor(color.Keytop[key.coltype][c]);
                    291: 
1.1       root      292:                // エンターキーだけ枠の描き方が違うので別処理
                    293:                if (__predict_false(key.x < 0)) {
1.1.1.11  root      294:                        DrawEnterKey();
1.1       root      295:                } else {
1.1.1.11  root      296:                        DrawKey(key);
1.1       root      297:                }
                    298:        }
                    299: 
1.1.1.9   root      300:        if (timer_start) {
                    301:                timer.Start(25);
                    302:        } else {
                    303:                timer.Stop();
                    304:        }
1.1       root      305: }
                    306: 
                    307: // 指定のキーを一つ (枠から刻印まで) 描画する。
                    308: void
1.1.1.11  root      309: WXSoftKeyPanel::DrawKey(const keydata_t& key)
1.1       root      310: {
1.1.1.10  root      311:        uint attr = TA::Normal;
                    312: 
1.1       root      313:        // 枠
1.1.1.11  root      314:        Rect rect(
                    315:                key.x * unit,     key.y * unit,
                    316:                key.w * unit + 1, key.h * unit + 1);
                    317:        bitmap.FillRect(palette[0], rect);
                    318:        bitmap.DrawRect(color.Text, rect);
1.1       root      319: 
                    320:        // 刻印を選択
                    321:        const char *disp = key.disp[modifier];
                    322:        if (disp == NULL) {
                    323:                disp = key.disp[0];
                    324:        }
                    325: 
1.1.1.10  root      326:        // トグルキーのワンショット押しは太字で表示を区別したい
                    327:        const auto it = toggle.find(key.keycode);
                    328:        if (it != toggle.end()) {
                    329:                if (it->second) {
                    330:                        attr = TA::Em;
                    331:                }
                    332:        }
                    333: 
1.1       root      334:        // Shift_JIS に変換
                    335:        wxString utfstr(disp, wxConvUTF8);
1.1.1.11  root      336:        // mb_str() をキャストせずに一度保持しておく必要がある (scan-build 対策)
                    337:        auto mbstr = utfstr.mb_str(conv);
                    338:        const char *sjis = (const char *)mbstr;
1.1.1.4   root      339:        // 改行があれば2行に分割
                    340:        char sjis1[8] {};
                    341:        char sjis2[8] {};
                    342:        int sjislen;
                    343:        int row;
                    344:        const char *lf = strchr(sjis, '\n');
                    345:        if (lf == NULL) {
                    346:                // 1行なら、Shift_JIS での文字数は半角換算の文字数と一致する。
                    347:                sjislen = strlen(sjis);
                    348:                row = 1;
                    349:        } else {
                    350:                // 2行に分割。センタリングは1行目の長さだけで調べる。
                    351:                strncpy(sjis1, sjis, lf - sjis);
                    352:                strcpy(sjis2, lf + 1);
                    353:                sjislen = strlen(sjis1);
                    354:                row = 2;
                    355:        }
1.1       root      356: 
                    357:        // センタリング
                    358:        int x = key.x + (key.w - sjislen * 2) / 2;
1.1.1.4   root      359:        int y = key.y + (key.h - row * 4) / 2;
1.1       root      360: 
1.1.1.4   root      361:        // LED を描画 (機種によって色々違うので個別クラス側で処理)
                    362:        if (key.led >= 0) {
1.1.1.11  root      363:                y += DrawLED(key);
1.1       root      364:        }
                    365: 
                    366:        // 文字を描画
1.1.1.11  root      367:        x = x * unit + 1;
                    368:        y = y * unit + 1;
1.1.1.4   root      369:        if (strcmp(disp, EnterMark) == 0) {
1.1.1.11  root      370:                DrawEnterMark(x, y);
1.1       root      371:        } else {
1.1.1.4   root      372:                if (lf == NULL) {
                    373:                        // 1行の場合
1.1.1.11  root      374:                        DrawStringSJIS(x, y, sjis, attr);
1.1.1.4   root      375:                } else {
                    376:                        // 2行の場合
1.1.1.11  root      377:                        DrawStringSJIS(x, y, sjis1);
                    378:                        y += 4 * unit;
                    379:                        DrawStringSJIS(x, y, sjis2);
1.1.1.4   root      380:                }
1.1       root      381:        }
                    382: }
                    383: 
                    384: // エンターキー
                    385: void
1.1.1.11  root      386: WXSoftKeyPanel::DrawEnterKey()
1.1       root      387: {
1.1.1.11  root      388:        // 矩形の内側を背景色で塗りつぶす。
                    389:        bitmap.FillRect(palette[0], enter_top);
                    390:        bitmap.FillRect(palette[0], enter_btm);
                    391: 
                    392:        // 周囲の線分
                    393:        // (A)-(B)
                    394:        bitmap.DrawLineH(color.Text,
                    395:                enter_top.x, enter_top.y, enter_top.GetRight());
                    396:        // (B)-(C)
                    397:        bitmap.DrawLineV(color.Text,
                    398:                enter_top.GetRight(), enter_top.y, enter_btm.GetBottom());
                    399:        // (C)-(D)
                    400:        bitmap.DrawLineH(color.Text,
                    401:                enter_btm.GetRight(), enter_btm.GetBottom(), enter_btm.x);
                    402:        // (D)-(E)
                    403:        bitmap.DrawLineV(color.Text,
                    404:                enter_btm.x, enter_btm.GetBottom(), enter_btm.y);
                    405:        // (E)-(F)
                    406:        bitmap.DrawLineH(color.Text,
                    407:                enter_btm.x, enter_top.GetBottom(), enter_top.x);
                    408:        // (F)-(A)
                    409:        bitmap.DrawLineV(color.Text,
                    410:                enter_top.x, enter_top.GetBottom(), enter_top.y);
1.1       root      411: 
                    412:        // エンター記号を描画
1.1.1.11  root      413:        DrawEnterMark(
                    414:                (enter_top.x + enter_top.GetRight())  / 2 - (4 / 2),
                    415:                (enter_top.y + enter_btm.GetBottom()) / 2 - (4 / 2));
                    416: }
                    417: 
                    418: #define B(x)   (0b##x >> 8), (0b##x & 0xff)
                    419: 
                    420: static constexpr uint8 EnterMark12[] = {
                    421:        B(000000000000'0000),   // 0
                    422:        B(000000001110'0000),   // 1
                    423:        B(000000001010'0000),   // 2
                    424:        B(000000001010'0000),   // 3
                    425:        B(000000001010'0000),   // 4
                    426:        B(001100001010'0000),   // 5
                    427:        B(010111110010'0000),   // 6
                    428:        B(100000000010'0000),   // 7
                    429:        B(010111111100'0000),   // 8
                    430:        B(001100000000'0000),   // 9
                    431:        B(000000000000'0000),   // a
                    432:        B(000000000000'0000),   // b
                    433: };
                    434: static constexpr uint8 EnterMark16[] = {
                    435:        B(0000000000111110),    // 0
                    436:        B(0000000000100010),    // 1
                    437:        B(0000000000100010),    // 2
                    438:        B(0000000000100010),    // 3
                    439:        B(0000000000100010),    // 4
                    440:        B(0000000000100010),    // 5
                    441:        B(0000000000100010),    // 6
                    442:        B(0000110000100010),    // 7
                    443:        B(0001010000100010),    // 8
                    444:        B(0010011111000010),    // 9
                    445:        B(0100000000000010),    // a
                    446:        B(1000000000000010),    // b
                    447:        B(0100000000000010),    // c
                    448:        B(0010011111111100),    // d
                    449:        B(0001010000000000),    // e
                    450:        B(0000110000000000),    // f
                    451: };
1.1       root      452: 
                    453: // 指定の位置にエンター記号を描画する (エンターキー全体の描画ではない)。
                    454: // メインキーとテンキーの両方で同じ図柄を使う。
                    455: // 大きさは (3unit, 4unit) なので実質全角1文字分くらい。
                    456: void
1.1.1.11  root      457: WXSoftKeyPanel::DrawEnterMark(int px, int py)
1.1       root      458: {
1.1.1.11  root      459:        const uint8 *mark;
                    460: 
                    461:        switch (font_height) {
                    462:         case 12:
                    463:                mark = EnterMark12;
                    464:                break;
                    465:         case 16:
                    466:                mark = EnterMark16;
                    467:                break;
                    468:         default:
                    469:                PANIC("Unexpected font_height=%d", font_height);
1.1       root      470:        }
1.1.1.11  root      471:        BitmapI1 src(mark, font_height, font_height);
                    472:        bitmap.DrawBitmap(px, py, src, palette);
1.1       root      473: }
                    474: 
                    475: // keycode に対応する keydata を返す
                    476: const keydata_t&
1.1.1.4   root      477: WXSoftKeyPanel::FindKeydata(uint keycode) const
1.1       root      478: {
1.1.1.6   root      479:        for (const auto& key : keydata) {
1.1       root      480:                if (key.keycode == keycode) {
                    481:                        return key;
                    482:                }
                    483:        }
                    484:        // 見付からないはずはない
1.1.1.11  root      485:        PANIC("keycode %d not found", keycode);
1.1       root      486: }
                    487: 
                    488: // マウス左クリック (Down) イベント
                    489: void
1.1.1.4   root      490: WXSoftKeyPanel::OnLeftDown(wxMouseEvent& event)
1.1       root      491: {
1.1.1.5   root      492:        const wxPoint& pt = event.GetPosition();
1.1.1.4   root      493:        const keydata_t *key = GetKeydataFromPoint(pt);
1.1       root      494: 
1.1.1.9   root      495:        if (key != NULL) {
1.1.1.10  root      496:                DoLeftDown(key->keycode);
1.1.1.9   root      497:        }
1.1       root      498: }
                    499: 
                    500: // マウス左クリック (Down) 処理
                    501: void
1.1.1.10  root      502: WXSoftKeyPanel::DoLeftDown(uint code)
1.1       root      503: {
1.1.1.10  root      504:        auto it = toggle.find(code);
                    505:        if (it != toggle.end()) {
                    506:                // トグルキーはここで完結。LeftUp では何もしない。
                    507:                // second のクリアは KeyUp() からコールバックされる OnKeyChanged()
                    508:                // で行っている。
                    509:                if (gKeyboard->IsPressed(code)) {
                    510:                        KeyUp(code);
1.1.1.9   root      511:                } else {
1.1.1.10  root      512:                        KeyDown(code);
                    513:                        it->second = code;
1.1.1.9   root      514:                }
1.1.1.10  root      515:                leftdown_key = KC_none;
1.1.1.9   root      516:        } else {
1.1.1.10  root      517:                // トグルでない通常キーはここで押下して LeftUp のために覚えておく
                    518:                KeyDown(code);
                    519:                leftdown_key = code;
1.1       root      520:        }
                    521: }
                    522: 
                    523: // マウス左クリック (Up) イベント
                    524: void
1.1.1.4   root      525: WXSoftKeyPanel::OnLeftUp(wxMouseEvent& event)
1.1       root      526: {
                    527:        // Up 時は、これが起きた地点のキーコードではなく
                    528:        // 直近に LeftDown したキーコードをターゲットにする。
1.1.1.10  root      529:        uint code = leftdown_key;
1.1       root      530: 
1.1.1.10  root      531:        if (code != KC_none) {
                    532:                KeyUp(code);
1.1.1.9   root      533: 
1.1.1.10  root      534:                // 通常キーが離されたら、トグルキーはすべて開放
                    535:                for (const auto& k : toggle) {
                    536:                        auto tcode = k.second;
                    537:                        if (tcode) {
                    538:                                KeyUp(tcode);
1.1.1.9   root      539:                        }
                    540:                }
1.1       root      541:        }
1.1.1.9   root      542: 
1.1.1.10  root      543:        leftdown_key = KC_none;
1.1       root      544: }
                    545: 
                    546: // マウス左ダブルクリックイベント
                    547: // ダブルクリックという操作に特別何かを割り当ててはいないが、
                    548: // キーを連打するとその間隔によってはダブルクリックと扱われるため、
                    549: // 受け取ってここで処理する。
                    550: //
                    551: // DClick イベントは LeftDown、LeftUp、LeftDClick、LeftUp の順で
                    552: // 飛んでくるので、ここでは2回目の押下だけ処理すればよい。というか
                    553: // 処理自体は LeftDown とまったく同じになるので、イベントテーブルで
                    554: // 直接 EVT_LEFT_DCLICK => OnLeftDown に割り付けることも出来そうだが
                    555: // デバッグが紛らわしくなりそうなので独立したイベントとしておく。
                    556: void
1.1.1.4   root      557: WXSoftKeyPanel::OnLeftDClick(wxMouseEvent& event)
1.1       root      558: {
1.1.1.5   root      559:        const wxPoint& pt = event.GetPosition();
1.1.1.4   root      560:        const keydata_t *key = GetKeydataFromPoint(pt);
1.1       root      561: 
1.1.1.9   root      562:        if (key != NULL) {
1.1.1.10  root      563:                DoLeftDown(key->keycode);
1.1.1.9   root      564:        }
1.1       root      565: }
                    566: 
                    567: // マウス右クリック (Down) イベント
                    568: // 長押し開始/解除。
                    569: // 右クリックのほうは Down だけで Up は使わない。
                    570: void
1.1.1.4   root      571: WXSoftKeyPanel::OnRightDown(wxMouseEvent& event)
1.1       root      572: {
1.1.1.5   root      573:        const wxPoint& pt = event.GetPosition();
1.1.1.4   root      574:        const keydata_t *key = GetKeydataFromPoint(pt);
1.1       root      575: 
1.1.1.4   root      576:        if (key != NULL) {
                    577:                uint code = key->keycode;
1.1.1.6   root      578:                if (gKeyboard->IsPressed(code)) {
1.1       root      579:                        // 押されていたら開放
1.1.1.10  root      580:                        KeyUp(code);
1.1       root      581:                } else {
                    582:                        // 押されてなければ長押し開始
1.1.1.10  root      583:                        KeyDown(code);
1.1       root      584:                }
                    585:        }
                    586: }
                    587: 
1.1.1.4   root      588: // 座標からキーデータを返す。
                    589: // キーに当たっていなければ NULL を返す。
                    590: const keydata_t *
                    591: WXSoftKeyPanel::GetKeydataFromPoint(const wxPoint& pt) const
1.1       root      592: {
1.1.1.4   root      593:        // エンターキーだけ先に別判定
1.1.1.11  root      594:        if (enter_top.Contains(pt.x, pt.y) || enter_btm.Contains(pt.x, pt.y)) {
1.1.1.4   root      595:                return &FindKeydata(KC_enter);
                    596:        }
1.1       root      597: 
1.1.1.6   root      598:        for (const auto& key : keydata) {
1.1.1.4   root      599:                if (key.x < 0) {
                    600:                        continue;
1.1       root      601:                }
1.1.1.4   root      602:                // 始点と幅の +1/-1 は罫線の分
                    603:                wxRect rect(
                    604:                        (key.x * unit) + 1,
                    605:                        (key.y * unit) + 1,
                    606:                        (key.w * unit) - 1,
                    607:                        (key.h * unit) - 1);
                    608:                if (rect.Contains(pt)) {
                    609:                        return &key;
1.1       root      610:                }
1.1.1.4   root      611:        }
                    612:        return NULL;
                    613: }
                    614: 
1.1.1.6   root      615: // このキーが押された処理
                    616: void
1.1.1.10  root      617: WXSoftKeyPanel::KeyDown(uint code)
1.1.1.6   root      618: {
1.1.1.9   root      619:        // VM に通知 (Keyboard がホストに通知する)
1.1.1.6   root      620:        gKeyboard->MakeKey(code);
                    621: }
                    622: 
                    623: // このキーが放された処理
                    624: void
1.1.1.10  root      625: WXSoftKeyPanel::KeyUp(uint code)
1.1.1.6   root      626: {
1.1.1.9   root      627:        // VM に通知 (Keyboard がホストに通知する)
1.1.1.6   root      628:        gKeyboard->BreakKey(code);
                    629: }
                    630: 
                    631: 
1.1.1.4   root      632: //
                    633: // LUNA ソフトウェアキーボード (パネル)
                    634: //
                    635: 
                    636: // コンストラクタ
                    637: WXLunaSoftKeyPanel::WXLunaSoftKeyPanel(wxWindow *parent)
1.1.1.6   root      638:        : inherited(parent, keydata, 226, 54)
1.1.1.4   root      639: {
                    640:        // LUNA では
                    641:        // BS キーの左隣 (0x5c) は円記号ではなくバックスラッシュ。
                    642:        // それを SHIFT したやつ(0x7c) は破線でないパイプ。
                    643:        // そのもう一つ左隣 (0x7e) はオーバーラインではなくチルダ。
1.1.1.11  root      644:        gFontManager->SetGlyph5C(true);
                    645:        gFontManager->SetGlyph7E(true);
1.1.1.4   root      646: 
1.1.1.9   root      647:        // 白黒モデル共通
1.1.1.11  root      648:        color.Border = UD_BLACK;
1.1.1.9   root      649:        color.LED[0] = UD_RED;
                    650: 
1.1.1.4   root      651:        // キートップの濃淡はユニバーサルデザインの推奨色ではないけど
                    652:        // ここは見分けを付けるためではなくただのデザインなので。
                    653:        if (1) {
                    654:                // 白モデル
1.1.1.9   root      655:                color.Background        = UD_LIGHT_GREY;        // 現物新品は何色だったんだろう
1.1.1.11  root      656:                color.Text                      = UD_BLACK;
                    657:                color.Keytop[0][0]      = UD_WHITE;
                    658:                color.Keytop[1][0]      = Color(200, 200, 203);
1.1.1.4   root      659:        } else {
                    660:                // 黒モデル
1.1.1.11  root      661:                color.Background        = UD_BLACK;
                    662:                color.Text                      = UD_WHITE;
                    663:                color.Keytop[0][0]      = Color(50, 50, 53);
                    664:                color.Keytop[1][0]      = UD_BLACK;
1.1.1.4   root      665:        }
1.1.1.9   root      666:        InitColorKeytop(2);
1.1.1.11  root      667: 
                    668:        SetBitmapBGColor(color.Background);
1.1.1.4   root      669: }
                    670: 
                    671: // デストラクタ
                    672: WXLunaSoftKeyPanel::~WXLunaSoftKeyPanel()
                    673: {
                    674: }
                    675: 
                    676: // LED を描画して刻印描画のための y offset を返す。
                    677: int
1.1.1.11  root      678: WXLunaSoftKeyPanel::DrawLED(const keydata_t& key)
1.1.1.4   root      679: {
                    680:        const std::vector<bool>& led = gKeyboard->GetLED();
1.1.1.11  root      681:        Color fg;
                    682:        Color bg;
1.1.1.4   root      683: 
                    684:        if (led[key.led]) {
                    685:                // 点灯時は赤、枠は黒
1.1.1.11  root      686:                fg = color.Border;
                    687:                bg = color.LED[0];
1.1       root      688:        } else {
1.1.1.4   root      689:                // 消灯時は元のキートップの色で、枠は薄めにしたい
1.1.1.6   root      690:                // (枠の色は今の所全モデル共通なので ColorPalette に含めていない)
1.1.1.11  root      691:                fg = UD_GREY;
                    692:                bg = color.Keytop[key.coltype][0];
1.1       root      693:        }
                    694: 
1.1.1.4   root      695:        // LED を左肩に描く
1.1.1.11  root      696:        Rect rect(key.x * unit + 2, key.y * unit + 2, 4 * unit - 2, 3 * unit - 2);
                    697:        bitmap.FillRect(bg, rect);
                    698:        bitmap.DrawRect(fg, rect);
1.1.1.4   root      699: 
                    700:        // そのため文字は少し下げる
                    701:        return +1;
                    702: }
                    703: 
1.1       root      704: // キーデータ
                    705: #define H       (8)    // キーの高さ
                    706: #define L0      (2)    // ファンクションキーの行
                    707: #define L1     (12)    // ESC の行
                    708: #define L2     (20)    // TAB の行
                    709: #define L3     (28)    // CTRL の行
                    710: #define L4     (36)    // SHIFT の行
                    711: #define L5     (44)    // space の行
                    712: /*static*/ std::vector<keydata_t>
                    713: WXLunaSoftKeyPanel::keydata {
1.1.1.4   root      714:        //                +---- キートップの色(1:濃)
                    715:        //                |  +- 0 以上なら LED 番号
                    716:        //  X   Y   W  H  C  L  KeyCode                         通常  SHIFT
                    717:        {   2, L0, 15, H, 1,-1, KC_F1,                          { "PF1" } },
                    718:        {  17, L0, 15, H, 1,-1, KC_F2,                          { "PF2" } },
                    719:        {  32, L0, 15, H, 1,-1, KC_F3,                          { "PF3" } },
                    720:        {  47, L0, 15, H, 1,-1, KC_F4,                          { "PF4" } },
                    721:        {  62, L0, 15, H, 1,-1, KC_F5,                          { "PF5" } },
                    722:        {  81, L0, 15, H, 1,-1, KC_F6,                          { "PF6" } },
                    723:        {  96, L0, 15, H, 1,-1, KC_F7,                          { "PF7" } },
                    724:        { 111, L0, 15, H, 1,-1, KC_F8,                          { "PF8" } },
                    725:        { 126, L0, 15, H, 1,-1, KC_F9,                          { "PF9" } },
                    726:        { 141, L0, 15, H, 1,-1, KC_F10,                         { "PF10" } },
                    727: 
                    728:        {   2, L1, 12, H, 1,-1, KC_ESC,                         { "ESC" } },
                    729:        {  14, L1, 10, H, 0,-1, KC_1,                           { "1",  "!" } },
                    730:        {  24, L1, 10, H, 0,-1, KC_2,                           { "2",  "\"" } },
                    731:        {  34, L1, 10, H, 0,-1, KC_3,                           { "3",  "#" } },
                    732:        {  44, L1, 10, H, 0,-1, KC_4,                           { "4",  "$" } },
                    733:        {  54, L1, 10, H, 0,-1, KC_5,                           { "5",  "%" } },
                    734:        {  64, L1, 10, H, 0,-1, KC_6,                           { "6",  "&" } },
                    735:        {  74, L1, 10, H, 0,-1, KC_7,                           { "7",  "'" } },
                    736:        {  84, L1, 10, H, 0,-1, KC_8,                           { "8",  "(" } },
                    737:        {  94, L1, 10, H, 0,-1, KC_9,                           { "9",  ")" } },
                    738:        { 104, L1, 10, H, 0,-1, KC_0,                           { "0",  " " } },
                    739:        { 114, L1, 10, H, 0,-1, KC_minus,                       { "-",  "=" } },
                    740:        { 124, L1, 10, H, 0,-1, KC_circum,                      { "^",  "~" } },
                    741:        { 134, L1, 10, H, 0,-1, KC_backslash,           { "\\", "|" } },
                    742:        { 144, L1, 12, H, 1,-1, KC_BS,                          { "BS" } },
                    743: 
                    744:        {   2, L2, 17, H, 1,-1, KC_TAB,                         { "TAB" } },
                    745:        {  19, L2, 10, H, 0,-1, KC_Q,                           { "q",  "Q" } },
                    746:        {  29, L2, 10, H, 0,-1, KC_W,                           { "w",  "W" } },
                    747:        {  39, L2, 10, H, 0,-1, KC_E,                           { "e",  "E" } },
                    748:        {  49, L2, 10, H, 0,-1, KC_R,                           { "r",  "R" } },
                    749:        {  59, L2, 10, H, 0,-1, KC_T,                           { "t",  "T" } },
                    750:        {  69, L2, 10, H, 0,-1, KC_Y,                           { "y",  "Y" } },
                    751:        {  79, L2, 10, H, 0,-1, KC_U,                           { "u",  "U" } },
                    752:        {  89, L2, 10, H, 0,-1, KC_I,                           { "i",  "I" } },
                    753:        {  99, L2, 10, H, 0,-1, KC_O,                           { "o",  "O" } },
                    754:        { 109, L2, 10, H, 0,-1, KC_P,                           { "p",  "P" } },
                    755:        { 119, L2, 10, H, 0,-1, KC_at,                          { "@",  "`" } },
                    756:        { 129, L2, 10, H, 0,-1, KC_bracketleft,         { "[",  "{" } },
                    757: 
                    758:        {   2, L3, 20, H, 1,-1, KC_CTRL,                        { "CTRL" } },
                    759:        {  22, L3, 10, H, 0,-1, KC_A,                           { "a",  "A" } },
                    760:        {  32, L3, 10, H, 0,-1, KC_S,                           { "s",  "S" } },
                    761:        {  42, L3, 10, H, 0,-1, KC_D,                           { "d",  "D" } },
                    762:        {  52, L3, 10, H, 0,-1, KC_F,                           { "f",  "F" } },
                    763:        {  62, L3, 10, H, 0,-1, KC_G,                           { "g",  "G" } },
                    764:        {  72, L3, 10, H, 0,-1, KC_H,                           { "h",  "H" } },
                    765:        {  82, L3, 10, H, 0,-1, KC_J,                           { "j",  "J" } },
                    766:        {  92, L3, 10, H, 0,-1, KC_K,                           { "k",  "K" } },
                    767:        { 102, L3, 10, H, 0,-1, KC_L,                           { "l",  "L" } },
                    768:        { 112, L3, 10, H, 0,-1, KC_semicolon,           { ";",  "+" } },
                    769:        { 122, L3, 10, H, 0,-1, KC_colon,                       { ":",  "*" } },
                    770:        { 132, L3, 10, H, 0,-1, KC_bracketright,        { "]",  "}" } },
                    771: 
                    772:        {   2, L4, 25, H, 1,-1, KC_SHIFT_L,                     { "SHIFT" } },
                    773:        {  27, L4, 10, H, 0,-1, KC_Z,                           { "z",  "Z" } },
                    774:        {  37, L4, 10, H, 0,-1, KC_X,                           { "x",  "X" } },
                    775:        {  47, L4, 10, H, 0,-1, KC_C,                           { "c",  "C" } },
                    776:        {  57, L4, 10, H, 0,-1, KC_V,                           { "v",  "V" } },
                    777:        {  67, L4, 10, H, 0,-1, KC_B,                           { "b",  "B" } },
                    778:        {  77, L4, 10, H, 0,-1, KC_N,                           { "n",  "N" } },
                    779:        {  87, L4, 10, H, 0,-1, KC_M,                           { "m",  "M" } },
                    780:        {  97, L4, 10, H, 0,-1, KC_comma,                       { ",",  "<" } },
                    781:        { 107, L4, 10, H, 0,-1, KC_period,                      { ".",  ">" } },
                    782:        { 117, L4, 10, H, 0,-1, KC_slash,                       { "/",  "?" } },
                    783:        { 127, L4, 10, H, 0,-1, KC_underscore,          { " ",  "_" } },
                    784:        { 137, L4, 19, H, 1,-1, KC_SHIFT_R,                     { "SHIFT" } },
                    785: 
                    786:        {   2, L5, 20, H, 1,-1, KC_VALID,                       { "確定" } },
                    787:        {  22, L5, 10, H, 1,-1, KC_SF,                          { "前面" } },
                    788:        {  32, L5, 10, H, 1, 1, KC_CAPS,                        { "CAP" } },
                    789:        {  42, L5, 80, H, 0,-1, KC_space,                       { " " } },
                    790:        { 122, L5, 10, H, 1, 0, KC_kana,                        { "かな" } },
                    791:        { 132, L5, 24, H, 1,-1, KC_XFER,                        { "変換" } },
1.1       root      792: 
                    793:        // カーソルキー島
1.1.1.4   root      794:        { 160, L1, 10, H, 1,-1, KC_PF11,                        { "消去" } },
                    795:        { 170, L1, 10, H, 1,-1, KC_PF12,                        { "呼出" } },
                    796:        { 160, L2, 10, H, 1,-1, KC_PF13,                        { "文節\n←" } },
                    797:        { 170, L2, 10, H, 1,-1, KC_PF14,                        { "文節\n→" } },
                    798:        { 160, L3, 20, H, 1,-1, KC_up,                          { "↑" } },
                    799:        { 160, L4, 10, H, 1,-1, KC_left,                        { "←" } },
                    800:        { 170, L4, 10, H, 1,-1, KC_right,                       { "→" } },
                    801:        { 160, L5, 20, H, 1,-1, KC_down,                        { "↓" } },
1.1       root      802: 
                    803:        // テンキー島
1.1.1.4   root      804:        { 184, L1, 10, H, 1,-1, KC_DEL,                         { "DEL" } },
                    805:        { 194, L1, 10, H, 1,-1, KC_PAD_plus,            { "+" } },
                    806:        { 204, L1, 10, H, 1,-1, KC_PAD_minus,           { "-" } },
                    807:        { 214, L1, 10, H, 1,-1, KC_PAD_multiply,        { "*" } },
                    808: 
                    809:        { 184, L2, 10, H, 0,-1, KC_PAD_7,                       { "7" } },
                    810:        { 194, L2, 10, H, 0,-1, KC_PAD_8,                       { "8" } },
                    811:        { 204, L2, 10, H, 0,-1, KC_PAD_9,                       { "9" } },
                    812:        { 214, L2, 10, H, 1,-1, KC_PAD_divide,          { "/" } },
                    813: 
                    814:        { 184, L3, 10, H, 0,-1, KC_PAD_4,                       { "4" } },
                    815:        { 194, L3, 10, H, 0,-1, KC_PAD_5,                       { "5" } },
                    816:        { 204, L3, 10, H, 0,-1, KC_PAD_6,                       { "6" } },
                    817:        { 214, L3, 10, H, 1,-1, KC_PAD_equal,           { "=" } },
                    818: 
                    819:        { 184, L4, 10, H, 0,-1, KC_PAD_1,                       { "1" } },
                    820:        { 194, L4, 10, H, 0,-1, KC_PAD_2,                       { "2" } },
                    821:        { 204, L4, 10, H, 0,-1, KC_PAD_3,                       { "3" } },
                    822:        { 214, L4, 10, H, 1,-1, KC_PAD_comma,           { "," } },
                    823: 
                    824:        { 184, L5, 10, H, 0,-1, KC_PAD_0,                       { "0" } },
                    825:        { 194, L5, 10, H, 0,-1, KC_PAD_decimal,         { "." } },
                    826:        { 204, L5, 20, H, 1,-1, KC_PAD_enter,           { EnterMark } },
1.1       root      827: 
                    828:        // Enter だけ矩形でないので別処理するが
                    829:        // この構造体には全部のキー情報が統一的に並んでいるほうがよかろう。
1.1.1.4   root      830:        { -1, -1, -1, -1, 1,-1, KC_enter,                       { EnterMark } },
1.1       root      831: };
                    832: 
                    833: 
                    834: //
1.1.1.4   root      835: // X68k ソフトウェアキーボード (パネル)
                    836: //
                    837: 
                    838: // コンストラクタ
                    839: WXX68kSoftKeyPanel::WXX68kSoftKeyPanel(wxWindow *parent)
1.1.1.6   root      840:        : inherited(parent, keydata, 235, 54)
1.1.1.4   root      841: {
                    842:        // X68k では SRAM 設定に同期させる。
                    843:        uint8 sw = gSRAM->Peek8(0xed0059);
1.1.1.11  root      844:        gFontManager->SetGlyph5C((sw & 0x01));
                    845:        gFontManager->SetGlyph7E((sw & 0x02));
                    846:        gFontManager->SetGlyph7C((sw & 0x04));
1.1.1.4   root      847: 
                    848:        // とりあえず黒のみ
1.1.1.11  root      849:        color.Background        = Color(50, 50, 53);
                    850:        color.Text                      = UD_WHITE;
                    851:        color.Border            = UD_BLACK;
1.1.1.9   root      852:        color.LED[0]            = UD_RED;
                    853:        color.LED[1]            = UD_YELLOW_GREEN;
1.1.1.11  root      854:        color.Keytop[0][0]      = UD_BLACK;
1.1.1.9   root      855:        InitColorKeytop(1);
1.1.1.11  root      856: 
                    857:        SetBitmapBGColor(color.Background);
1.1.1.4   root      858: }
                    859: 
                    860: // デストラクタ
                    861: WXX68kSoftKeyPanel::~WXX68kSoftKeyPanel()
                    862: {
                    863: }
                    864: 
                    865: // LED を描画して刻印描画のための y offset を返す。
                    866: int
1.1.1.11  root      867: WXX68kSoftKeyPanel::DrawLED(const keydata_t& key)
1.1.1.4   root      868: {
                    869:        const std::vector<bool>& led = gKeyboard->GetLED();
1.1.1.11  root      870:        Color fg;
                    871:        Color bg;
1.1.1.4   root      872: 
                    873:        // 色を選択
                    874:        // idx  刻印  色
                    875:        // ----------------
                    876:        //  0   かな  赤
                    877:        //  1   ローマ       赤
                    878:        //  2   コード       赤
                    879:        //  3   CAPS    赤
                    880:        //  4   INS             赤
                    881:        //  5   ひら  緑
                    882:        //  6   全角  緑
                    883:        if (led[key.led]) {
                    884:                int n = (key.led < 5) ? 0 : 1;
1.1.1.11  root      885:                fg = color.LED[n];
                    886:                bg = color.LED[n];
1.1.1.4   root      887:        } else {
                    888:                // 消灯時は元のキートップの色で、枠は薄めにしたい
1.1.1.6   root      889:                // (枠の色は今の所全モデル共通なので ColorPalette に含めていない)
1.1.1.11  root      890:                fg = UD_GREY;
                    891:                bg = color.Keytop[key.coltype][0];
1.1.1.4   root      892:        }
                    893: 
                    894:        // LED は中央前方(画面でいうと下)
1.1.1.11  root      895:        Rect rect((key.x + 3) * unit, (key.y + key.h - 2) * unit,
                    896:                4 * unit, 2 * unit);
                    897:        bitmap.FillRect(bg, rect);
                    898:        bitmap.DrawRect(fg, rect);
1.1.1.4   root      899: 
                    900:        // そのため文字は少し上げる
                    901:        return -1;
                    902: }
                    903: 
                    904: #define LF (L0 + 2)            // ファンクションキーは少し低い(横長い)
                    905: #define HT (H * 2)             // 縦2倍角のキー
                    906: /*static*/ std::vector<keydata_t>
                    907: WXX68kSoftKeyPanel::keydata {
                    908:        //                   +- 0以上なら LED 番号
                    909:        //  X   Y   W  H  C  L  KeyCode                         通常  SHIFT
1.1.1.7   root      910:        {   2, L0, 10, H, 0,-1, KC_BREAK,                       { "\x4\x5\x6\x7" } },
1.1.1.4   root      911:        {  15, L0, 10, H, 0,-1, KC_COPY,                        { "COPY" } },
                    912:        {  29, LF, 12, 6, 0,-1, KC_F1,                          { "F1" } },
                    913:        {  41, LF, 12, 6, 0,-1, KC_F2,                          { "F2" } },
                    914:        {  53, LF, 12, 6, 0,-1, KC_F3,                          { "F3" } },
                    915:        {  65, LF, 12, 6, 0,-1, KC_F4,                          { "F4" } },
                    916:        {  77, LF, 13, 6, 0,-1, KC_F5,                          { "F5" } },
                    917:        {  94, LF, 13, 6, 0,-1, KC_F6,                          { "F6" } },
                    918:        { 106, LF, 12, 6, 0,-1, KC_F7,                          { "F7" } },
                    919:        { 118, LF, 12, 6, 0,-1, KC_F8,                          { "F8" } },
                    920:        { 130, LF, 12, 6, 0,-1, KC_F9,                          { "F9" } },
                    921:        { 142, LF, 13, 6, 0,-1, KC_F10,                         { "F10" } },
                    922: 
                    923:        {   2, L1, 10, H, 0,-1, KC_ESC,                         { "ESC" } },
                    924:        {  12, L1, 10, H, 0,-1, KC_1,                           { "1",  "!" } },
                    925:        {  22, L1, 10, H, 0,-1, KC_2,                           { "2",  "\"" } },
                    926:        {  32, L1, 10, H, 0,-1, KC_3,                           { "3",  "#" } },
                    927:        {  42, L1, 10, H, 0,-1, KC_4,                           { "4",  "$" } },
                    928:        {  52, L1, 10, H, 0,-1, KC_5,                           { "5",  "%" } },
                    929:        {  62, L1, 10, H, 0,-1, KC_6,                           { "6",  "&" } },
                    930:        {  72, L1, 10, H, 0,-1, KC_7,                           { "7",  "'" } },
                    931:        {  82, L1, 10, H, 0,-1, KC_8,                           { "8",  "(" } },
                    932:        {  92, L1, 10, H, 0,-1, KC_9,                           { "9",  ")" } },
                    933:        { 102, L1, 10, H, 0,-1, KC_0,                           { "0",  " " } },
                    934:        { 112, L1, 10, H, 0,-1, KC_minus,                       { "-",  "=" } },
                    935:        { 122, L1, 10, H, 0,-1, KC_circum,                      { "^",  "~" } },
                    936:        { 132, L1, 10, H, 0,-1, KC_backslash,           { "\\", "|" } },
                    937:        { 142, L1, 13, H, 0,-1, KC_BS,                          { "BS" } },
                    938: 
                    939:        {   2, L2, 16, H, 0,-1, KC_TAB,                         { "TAB" } },
                    940:        {  18, L2, 10, H, 0,-1, KC_Q,                           { "q",  "Q" } },
                    941:        {  28, L2, 10, H, 0,-1, KC_W,                           { "w",  "W" } },
                    942:        {  38, L2, 10, H, 0,-1, KC_E,                           { "e",  "E" } },
                    943:        {  48, L2, 10, H, 0,-1, KC_R,                           { "r",  "R" } },
                    944:        {  58, L2, 10, H, 0,-1, KC_T,                           { "t",  "T" } },
                    945:        {  68, L2, 10, H, 0,-1, KC_Y,                           { "y",  "Y" } },
                    946:        {  78, L2, 10, H, 0,-1, KC_U,                           { "u",  "U" } },
                    947:        {  88, L2, 10, H, 0,-1, KC_I,                           { "i",  "I" } },
                    948:        {  98, L2, 10, H, 0,-1, KC_O,                           { "o",  "O" } },
                    949:        { 108, L2, 10, H, 0,-1, KC_P,                           { "p",  "P" } },
                    950:        { 118, L2, 10, H, 0,-1, KC_at,                          { "@",  "`" } },
                    951:        { 128, L2, 10, H, 0,-1, KC_bracketleft,         { "[",  "{" } },
                    952: 
                    953:        {   2, L3, 19, H, 0,-1, KC_CTRL,                        { "CTRL" } },
                    954:        {  21, L3, 10, H, 0,-1, KC_A,                           { "a",  "A" } },
                    955:        {  31, L3, 10, H, 0,-1, KC_S,                           { "s",  "S" } },
                    956:        {  41, L3, 10, H, 0,-1, KC_D,                           { "d",  "D" } },
                    957:        {  51, L3, 10, H, 0,-1, KC_F,                           { "f",  "F" } },
                    958:        {  61, L3, 10, H, 0,-1, KC_G,                           { "g",  "G" } },
                    959:        {  71, L3, 10, H, 0,-1, KC_H,                           { "h",  "H" } },
                    960:        {  81, L3, 10, H, 0,-1, KC_J,                           { "j",  "J" } },
                    961:        {  91, L3, 10, H, 0,-1, KC_K,                           { "k",  "K" } },
                    962:        { 101, L3, 10, H, 0,-1, KC_L,                           { "l",  "L" } },
                    963:        { 111, L3, 10, H, 0,-1, KC_semicolon,           { ";",  "+" } },
                    964:        { 121, L3, 10, H, 0,-1, KC_colon,                       { ":",  "*" } },
                    965:        { 131, L3, 10, H, 0,-1, KC_bracketright,        { "]",  "}" } },
                    966: 
1.1.1.6   root      967:        {   2, L4, 24, H, 0,-1, KC_SHIFT,                       { "SHIFT" } },
1.1.1.4   root      968:        {  26, L4, 10, H, 0,-1, KC_Z,                           { "z",  "Z" } },
                    969:        {  36, L4, 10, H, 0,-1, KC_X,                           { "x",  "X" } },
                    970:        {  46, L4, 10, H, 0,-1, KC_C,                           { "c",  "C" } },
                    971:        {  56, L4, 10, H, 0,-1, KC_V,                           { "v",  "V" } },
                    972:        {  66, L4, 10, H, 0,-1, KC_B,                           { "b",  "B" } },
                    973:        {  76, L4, 10, H, 0,-1, KC_N,                           { "n",  "N" } },
                    974:        {  86, L4, 10, H, 0,-1, KC_M,                           { "m",  "M" } },
                    975:        {  96, L4, 10, H, 0,-1, KC_comma,                       { ",",  "<" } },
                    976:        { 106, L4, 10, H, 0,-1, KC_period,                      { ".",  ">" } },
                    977:        { 116, L4, 10, H, 0,-1, KC_slash,                       { "/",  "?" } },
                    978:        { 126, L4, 10, H, 0,-1, KC_underscore,          { " ",  "_" } },
1.1.1.6   root      979:        { 136, L4, 19, H, 0,-1, KC_SHIFT,                       { "SHIFT" } },
1.1.1.4   root      980: 
                    981:        {  21, L5, 10, H, 0, 5, KC_hira,                        { "ひら" } },
                    982:        {  31, L5, 12, H, 0,-1, KC_XF1,                         { "XF1" } },
                    983:        {  43, L5, 13, H, 0,-1, KC_XF2,                         { "XF2" } },
                    984:        {  56, L5, 36, H, 0,-1, KC_space,                       { " " } },
                    985:        {  92, L5, 12, H, 0,-1, KC_XF3,                         { "XF3" } },
                    986:        { 104, L5, 12, H, 0,-1, KC_XF4,                         { "XF4" } },
                    987:        { 116, L5, 12, H, 0,-1, KC_XF5,                         { "XF5" } },
                    988:        { 128, L5, 10, H, 0, 6, KC_zenkaku,                     { "全角" } },
                    989: 
                    990:        // カーソルキー島
                    991:        { 159, L0, 10, H, 0, 0, KC_kana,                        { "かな" } },
                    992:        { 169, L0, 10, H, 0, 1, KC_romaji,                      { "ローマ" } },
                    993:        { 179, L0, 10, H, 0, 2, KC_code,                        { "コード" } },
                    994:        { 159, L1, 10, H, 0,-1, KC_HOME,                        { "HOME" } },
                    995:        { 169, L1, 10, H, 0, 4, KC_INS,                         { "INS" } },
                    996:        { 179, L1, 10, H, 0,-1, KC_DEL,                         { "DEL" } },
                    997:        { 159, L2, 10, H, 0,-1, KC_ROLLUP,                      { "ROLL\n UP" } },
                    998:        { 169, L2, 10, H, 0,-1, KC_ROLLDOWN,            { "ROLL\nDOWN" } },
                    999:        { 179, L2, 10, H, 0,-1, KC_UNDO,                        { "UNDO" } },
                   1000:        { 169, L3, 10, H, 0,-1, KC_up,                          { "↑" } },
                   1001:        { 159, L3, 10, HT,0,-1, KC_left,                        { "←" } },
                   1002:        { 179, L3, 10, HT,0,-1, KC_right,                       { "→" } },
                   1003:        { 169, L4, 10, H, 0,-1, KC_down,                        { "↓" } },
                   1004:        { 159, L5, 15, H, 0,-1, KC_OPT1,                        { "OPT.1" } },
                   1005:        { 174, L5, 15, H, 0,-1, KC_OPT2,                        { "OPT.2" } },
                   1006: 
                   1007:        // テンキー島
                   1008:        { 193, L0, 10, H, 0, 3, KC_CAPS,                        { "CAPS" } },
                   1009:        { 203, L0, 10, H, 0,-1, KC_kigou,                       { "記号" } },
                   1010:        { 213, L0, 10, H, 0,-1, KC_touroku,                     { "登録" } },
                   1011:        { 223, L0, 10, H, 0,-1, KC_HELP,                        { "HELP" } },
                   1012:        { 193, L1, 10, H, 0,-1, KC_PAD_CLR,                     { "CLR" } },
                   1013:        { 203, L1, 10, H, 0,-1, KC_PAD_divide,          { "/" } },
                   1014:        { 213, L1, 10, H, 0,-1, KC_PAD_multiply,        { "*" } },
                   1015:        { 223, L1, 10, H, 0,-1, KC_PAD_minus,           { "-" } },
                   1016:        { 193, L2, 10, H, 0,-1, KC_PAD_7,                       { "7" } },
                   1017:        { 203, L2, 10, H, 0,-1, KC_PAD_8,                       { "8" } },
                   1018:        { 213, L2, 10, H, 0,-1, KC_PAD_9,                       { "9" } },
                   1019:        { 223, L2, 10, H, 0,-1, KC_PAD_plus,            { "+" } },
                   1020:        { 193, L3, 10, H, 0,-1, KC_PAD_4,                       { "4" } },
                   1021:        { 203, L3, 10, H, 0,-1, KC_PAD_5,                       { "5" } },
                   1022:        { 213, L3, 10, H, 0,-1, KC_PAD_6,                       { "6" } },
                   1023:        { 223, L3, 10, H, 0,-1, KC_PAD_equal,           { "=" } },
                   1024:        { 193, L4, 10, H, 0,-1, KC_PAD_1,                       { "1" } },
                   1025:        { 203, L4, 10, H, 0,-1, KC_PAD_2,                       { "2" } },
                   1026:        { 213, L4, 10, H, 0,-1, KC_PAD_3,                       { "3" } },
1.1.1.7   root     1027:        { 223, L4, 10, HT,0,-1, KC_PAD_enter,           { "\xb\xc\xd\xe" } },
1.1.1.4   root     1028:        { 193, L5, 10, H, 0,-1, KC_PAD_0,                       { "0" } },
                   1029:        { 203, L5, 10, H, 0,-1, KC_PAD_comma,           { "," } },
                   1030:        { 213, L5, 10, H, 0,-1, KC_PAD_decimal,         { "." } },
                   1031: 
                   1032:        // Enter だけ矩形でないので別処理するが
                   1033:        // この構造体には全部のキー情報が統一的に並んでいるほうがよかろう。
                   1034:        { -1, -1, -1, -1, 0,-1, KC_enter,                       { EnterMark } },
                   1035: };
                   1036: 
                   1037: //
1.1.1.6   root     1038: // ソフトウェアキーボード (ウィンドウ)
1.1.1.4   root     1039: //
                   1040: 
                   1041: // コンストラクタ
1.1.1.12! root     1042: WXSoftKeyWindow::WXSoftKeyWindow(wxWindow *parent, VMType vmtype)
1.1.1.7   root     1043:        : inherited(parent, wxID_ANY, _("Software Keyboard"))
1.1.1.4   root     1044: {
1.1.1.12! root     1045:        if (vmtype == VMType::X68030) {
1.1.1.6   root     1046:                panel = new WXX68kSoftKeyPanel(this);
                   1047:        } else {
                   1048:                panel = new WXLunaSoftKeyPanel(this);
                   1049:        }
1.1.1.4   root     1050: 
1.1.1.11  root     1051:        DoSize();
1.1.1.4   root     1052: }
                   1053: 
                   1054: // デストラクタ
1.1.1.6   root     1055: WXSoftKeyWindow::~WXSoftKeyWindow()
1.1.1.4   root     1056: {
                   1057: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.