Annotation of nono/wx/wxmainview.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2018 [email protected]
                      4: //
                      5: 
                      6: #include "wxheader.h"
                      7: #include "keyboard.h"
                      8: #include "renderer.h"
                      9: #include "scheduler.h"
                     10: #include "wxmainview.h"
                     11: #include <wx/region.h>
                     12: #include <wx/event.h>
                     13: #if defined(__NetBSD__)
                     14: #include <sys/param.h> // __NetBSD_Version__
                     15: #endif
                     16: 
                     17: //#define KEYDEBUG 1
                     18: 
                     19: #if defined(KEYDEBUG)
                     20: #define DPRINTF(...)   printf(__VA_ARGS__)
                     21: #else
                     22: #define DPRINTF(...) /**/
                     23: #endif
                     24: 
                     25: // 再描画矩形の指定方法について。
                     26: // DoRefresh() にて、VM スレッドが自発的に画面を更新する際は、
                     27: // パフォーマンスの観点からも更新矩形だけを再描画すべき。
                     28: // これを wxWidgets に指示するのが wxWindow::Refresh{,Rect}() であるが
                     29: // 一部のプラットフォームではこれを呼び出すと、アプリケーションウィンドウ
                     30: // 全体がささってしまい、MainView だけでなくメニューバーも含めたすべてが
                     31: // 再描画できなくなってしまう。仕方がないので、これらのプラットフォームでは
                     32: // Refresh{,Rect}() を呼ばず、再描画矩形を画面全体として運用する。
                     33: // ちょっと無駄なだけなので (動かないことに比べれば) 気にしない。
                     34: //
                     35: // 今のところ NetBSD 5.0 以上(と Linux (CentOS 6.3/x86_64)) が該当する。
                     36: #if defined(__NetBSD__) && __NetBSD_Version__ >= 500000000
                     37: #define DONT_USE_REFRESH 1
                     38: #endif
                     39: 
                     40: #define TIMERID_PAINTTIMER 1
                     41: 
                     42: static void wxmainview_refresh();
                     43: 
                     44: WXMainView *gMainView;
                     45: 
                     46: wxBEGIN_EVENT_TABLE(WXMainView, inherited)
                     47:        EVT_PAINT(WXMainView::OnPaint)
                     48:        EVT_KEY_DOWN(WXMainView::OnKeyDown)
                     49:        EVT_KEY_UP(WXMainView::OnKeyUp)
                     50:        EVT_TIMER(TIMERID_PAINTTIMER, WXMainView::OnTimer)
                     51: wxEND_EVENT_TABLE()
                     52: 
                     53: WXMainView::WXMainView(wxWindow *parent)
                     54:        : inherited(parent)
                     55: {
                     56:        // 仮想画面(VM が描画する画面)
                     57:        rendwidth  = gRenderer->GetWidth();
                     58:        rendheight = gRenderer->GetHeight();
                     59: 
                     60:        // レンダラバッファは常に仮想画面サイズ
                     61:        int buflen = rendwidth * rendheight * 3;
                     62:        ImageBuf = new uint8_t[buflen];
                     63:        memset(ImageBuf, 0x70, buflen);
                     64:        // レンダラに通知
                     65:        gRenderer->SetBuf(ImageBuf, wxmainview_refresh);
                     66: 
                     67:        // 実画面 (ウィンドウの大きさ)
                     68:        DoResize(screen_scale);
                     69: 
                     70:        paintTimer.SetOwner(this, TIMERID_PAINTTIMER);
                     71:        paintTimer.Start(16);
                     72:        paintRequested = true;          // first paint request
                     73: }
                     74: 
                     75: WXMainView::~WXMainView()
                     76: {
                     77:        delete[] ImageBuf;
                     78: }
                     79: 
                     80: // リフレッシュ要求コールバック。
                     81: // VM から呼ばれるので一旦グローバル関数を経由する。
                     82: void
                     83: wxmainview_refresh(void)
                     84: {
                     85:        gMainView->DoRefresh();
                     86: }
                     87: 
                     88: // リフレッシュ要求コールバック。こっちが実体。
                     89: void
                     90: WXMainView::DoRefresh()
                     91: {
                     92: #if defined(DONT_USE_REFRESH)
                     93:        // Refresh{,Rect}() が使えないので、再描画範囲は常に全体とする
                     94: #else
                     95:        // 再描画範囲を更新矩形に限定
                     96:        // XXX のはずだが、今の所全体
                     97:        RefreshRect(wxRect(0, 0, viewwidth, viewheight), false);
                     98: #endif
                     99: 
                    100:        // PAINT イベントを投げる
                    101:        // XXX んだけど mac だと投げすぎるとシステムイベントを拾えなくなってしまう
                    102:        paintRequested = true;
                    103: }
                    104: 
                    105: void
                    106: WXMainView::OnTimer(wxTimerEvent& event)
                    107: {
                    108:        bool req = paintRequested.exchange(false);
                    109:        if (req) {
                    110:                // PAINT イベントを投げる
                    111:                wxPaintEvent *ev = new wxPaintEvent();
                    112:                QueueEvent(ev);
                    113:        }
                    114: }
                    115: 
                    116: // 描画イベント
                    117: void
                    118: WXMainView::OnPaint(wxPaintEvent& event)
                    119: {
                    120:        wxClientDC dc(this);
                    121: 
                    122:        DoPaint(dc);
                    123: }
                    124: 
                    125: // 描画実行
                    126: void
                    127: WXMainView::DoPaint(wxDC& dc)
                    128: {
                    129:        if (viewwidth == 0 || viewheight == 0)
                    130:                return;
                    131: 
                    132:        wxImage image(rendwidth, rendheight, ImageBuf, true);
                    133: 
                    134:        if (viewwidth != rendwidth || viewheight != rendheight) {
                    135:                // wxIMAGE_QUALITY_NORMAL だと速いが、品質優先。
                    136:                image.Rescale(viewwidth, viewheight, wxIMAGE_QUALITY_HIGH);
                    137:        }
                    138: 
                    139:        wxBitmap bitmap(image);
                    140:        wxMemoryDC memDC;
                    141:        memDC.SelectObject(bitmap);
                    142: 
                    143:        wxRegion region(0, 0, viewwidth, viewheight);
                    144:        wxRegionIterator ri(region);
                    145:        for (; ri; ri++) {
                    146:                int dx, dy, dw, dh;
                    147:                dx = ri.GetX();
                    148:                dy = ri.GetY();
                    149:                dw = ri.GetWidth();
                    150:                dh = ri.GetHeight();
                    151:                int sx = dx;
                    152:                int sy = dy;
                    153:                dc.Blit(dx, dy, dw, dh, &memDC, sx, sy, wxCOPY);
                    154:        }
                    155: }
                    156: 
                    157: // リサイズ (UI スレッドから呼ぶこと)
                    158: void
                    159: WXMainView::DoResize(double scale)
                    160: {
                    161:        screen_scale = scale;
                    162:        int width  = (double)rendwidth  * scale;
                    163:        int height = (double)rendheight * scale;
                    164:        if (viewwidth != width || viewheight != height) {
                    165:                // ウィンドウサイズ変更
                    166:                viewwidth  = width;
                    167:                viewheight = height;
                    168:                SetClientSize(viewwidth, viewheight);
                    169:                SetMinSize(wxSize(viewwidth, viewheight));
                    170:        }
                    171: }
                    172: 
                    173: // 現在のスケールを返す。
                    174: // screen_scale は public static なので見えるんだけど一応お行儀で。
                    175: double
                    176: WXMainView::GetScale() const
                    177: {
                    178:        return screen_scale;
                    179: }
                    180: 
                    181: // 現在のスケール
                    182: /*static*/ double WXMainView::screen_scale;
                    183: 
                    184: 
                    185: //
                    186: // キー入力
                    187: //
                    188: 
                    189: // wxKeyEvent でキーコードを得るためのメソッドは
                    190: // GetKeyCode()、GetRawKeyCode()、GetRawKeyFlags() の3つが用意されていて
                    191: // wxWigets の port (wxGTK、wxOSX とか) によってそれぞれ内容の定義が違う。
                    192: //
                    193: // wxGTK の場合
                    194: //  GetKeyCode() は wxWidgets の WXK_* (/usr/pkg/include/wx-3.0/wx/defs.h)。
                    195: //   これは左右の SHIFT が区別できないが、
                    196: //   それ以外はだいたい使えそうではある。
                    197: //
                    198: //  GetRawKeyCode() は GDK の keycode っぽい?
                    199: //   (/usr/pkg/include/gtk-2.0/gdk/gdkkeysyms.h)。
                    200: //   X11 の keysym から来てる? (/usr/X11R7/include/X11/keysymdef.h)。
                    201: //   ただし [A] と [SHIFT]+[A] が違うコードを返すというか、文字コードで
                    202: //   表現出来る時は文字コード、みたいな感じになっているので、ここでは
                    203: //   使いづらい。
                    204: //   左右の SHIFT は区別可能。
                    205: //   [^] と [SHIFT]+[^] もそもそも文字コードになるので '^' と '~' になる。
                    206: //
                    207: //  GetRawKeyFlags() は GDK の hardware keycode らしいけど、それが何か不明。
                    208: //   左右の SHIFT は違うコードを返す。
                    209: //   SHIFT を押しながらでもコードは変わらないっぽい。
                    210: //   [^] と [SHIFT]+[^] は同じコードを返す。
                    211: //
                    212: // wxOSX の場合
                    213: //  GetKeyCode()
                    214: //   これは左右の SHIFT が区別できないが、
                    215: //   それ以外はだいたい使えそうではある。
                    216: //
                    217: //  GetRawKeyCode()
                    218: //   [A] と [SHIFT]+[A] などは同じコードを返す。
                    219: //   左右の SHIFT は区別可能。
                    220: //
                    221: //  GetRawKeyFlags() は状態フラグか何かのようだ。
                    222: //
                    223: 
                    224: // キーを押した
                    225: void
                    226: WXMainView::OnKeyDown(wxKeyEvent& event)
                    227: {
                    228:        DPRINTF("KeyDown ");
                    229:        int keycode = GetKeyCode(event);
                    230:        gKeyboard->MakeKey(keycode);
                    231: }
                    232: 
                    233: // キーを離した
                    234: void
                    235: WXMainView::OnKeyUp(wxKeyEvent& event)
                    236: {
                    237:        DPRINTF("KeyUp   ");
                    238:        int keycode = GetKeyCode(event);
                    239:        gKeyboard->BreakKey(keycode);
                    240: }
                    241: 
                    242: // 共通キーコードを取得する。
                    243: // 対応するキーがない場合は -1 を返す。
                    244: int
                    245: WXMainView::GetKeyCode(wxKeyEvent& event)
                    246: {
                    247:        uint32 wxcode   __unused = event.GetKeyCode();
                    248:        uint32 rawcode  __unused = event.GetRawKeyCode();
                    249:        uint32 rawflags __unused = event.GetRawKeyFlags();
                    250:        uint32 inp;
                    251:        int keycode;
                    252: 
                    253: #if defined(__WXGTK__)
                    254:        // wxGTK では RawKeyFlags を使う
                    255:        DPRINTF("key=0x%03x raw=0x%04x <flags=0x%02x> ", wxcode, rawcode, rawflags);
                    256:        inp = rawflags;
                    257: #elif defined(__WXOSX__)
                    258:        // wxOSX では RawKeyCode を使う
                    259:        DPRINTF("key=0x%03x <raw=0x%02x> flags=0x%06x ", wxcode, rawcode, rawflags);
                    260:        inp = rawcode;
                    261: #endif
                    262: 
                    263:        // どちらにしてもテーブルを引く
                    264:        if (inp < countof(keycode_table)) {
                    265:                keycode = keycode_table[inp];
                    266:        } else {
                    267:                keycode = KC_none;
                    268:        }
                    269:        DPRINTF("keycode=%d %s\n", keycode, Keyboard::keyname[keycode]);
                    270:        return keycode;
                    271: }
                    272: 
                    273: #if defined(__WXGTK__)
                    274: // wxGTK の RawKeyFlags を共通キーコードに変換するテーブル。
                    275: /*static*/ const int
                    276: WXMainView::keycode_table[0xd4] = {
                    277:        KC_none,                // 0x00
                    278:        KC_none,                // 0x01
                    279:        KC_none,                // 0x02
                    280:        KC_none,                // 0x03
                    281:        KC_none,                // 0x04
                    282:        KC_none,                // 0x05
                    283:        KC_none,                // 0x06
                    284:        KC_none,                // 0x07
                    285:        KC_none,                // 0x08
                    286:        KC_none,                // 0x09
                    287:        KC_1,                   // 0x0a
                    288:        KC_2,                   // 0x0b
                    289:        KC_3,                   // 0x0c
                    290:        KC_4,                   // 0x0d
                    291:        KC_5,                   // 0x0e
                    292:        KC_6,                   // 0x0f
                    293: 
                    294:        KC_7,                   // 0x10
                    295:        KC_8,                   // 0x11
                    296:        KC_9,                   // 0x12
                    297:        KC_0,                   // 0x13
                    298:        KC_minus,               // 0x14
                    299:        KC_circum,              // 0x15
                    300:        KC_BS,                  // 0x16
                    301:        KC_TAB,                 // 0x17
                    302:        KC_Q,                   // 0x18
                    303:        KC_W,                   // 0x19
                    304:        KC_E,                   // 0x1a
                    305:        KC_R,                   // 0x1b
                    306:        KC_T,                   // 0x1c
                    307:        KC_Y,                   // 0x1d
                    308:        KC_U,                   // 0x1e
                    309:        KC_I,                   // 0x1f
                    310: 
                    311:        KC_O,                   // 0x20
                    312:        KC_P,                   // 0x21
                    313:        KC_at,                  // 0x22
                    314:        KC_bracketleft, // 0x23
                    315:        KC_enter,               // 0x24
                    316:        KC_CTRL,                // 0x25 (CTRL_L)
                    317:        KC_A,                   // 0x26
                    318:        KC_S,                   // 0x27
                    319:        KC_D,                   // 0x28
                    320:        KC_F,                   // 0x29
                    321:        KC_G,                   // 0x2a
                    322:        KC_H,                   // 0x2b
                    323:        KC_J,                   // 0x2c
                    324:        KC_K,                   // 0x2d
                    325:        KC_L,                   // 0x2e
                    326:        KC_semicolon,   // 0x2f
                    327: 
                    328:        KC_colon,               // 0x30
                    329:        KC_ESC,                 // 0x31
                    330:        KC_SHIFT_L,             // 0x32 (SHIFT_L)
                    331:        KC_bracketright,// 0x33
                    332:        KC_Z,                   // 0x34
                    333:        KC_X,                   // 0x35
                    334:        KC_C,                   // 0x36
                    335:        KC_V,                   // 0x37
                    336:        KC_B,                   // 0x38
                    337:        KC_N,                   // 0x39
                    338:        KC_M,                   // 0x3a
                    339:        KC_comma,               // 0x3b
                    340:        KC_period,              // 0x3c
                    341:        KC_slash,               // 0x3d
                    342:        KC_SHIFT_R,             // 0x3e (SHIFT_R)
                    343:        KC_PAD_multiply,// 0x3f
                    344: 
                    345:        KC_none,                // 0x40
                    346:        KC_space,               // 0x41
                    347:        KC_none,                // 0x42
                    348:        KC_F1,                  // 0x43
                    349:        KC_F2,                  // 0x44
                    350:        KC_F3,                  // 0x45
                    351:        KC_F4,                  // 0x46
                    352:        KC_F5,                  // 0x47
                    353:        KC_F6,                  // 0x48
                    354:        KC_F7,                  // 0x49
                    355:        KC_F8,                  // 0x4a
                    356:        KC_F9,                  // 0x4b
                    357:        KC_F10,                 // 0x4c
                    358:        KC_none,                // 0x4d
                    359:        KC_none,                // 0x4e
                    360:        KC_PAD_7,               // 0x4f
                    361: 
                    362:        KC_PAD_8,               // 0x50
                    363:        KC_PAD_9,               // 0x51
                    364:        KC_PAD_minus,   // 0x52
                    365:        KC_PAD_4,               // 0x53
                    366:        KC_PAD_5,               // 0x54
                    367:        KC_PAD_6,               // 0x55
                    368:        KC_PAD_plus,    // 0x56
                    369:        KC_PAD_1,               // 0x57
                    370:        KC_PAD_2,               // 0x58
                    371:        KC_PAD_3,               // 0x59
                    372:        KC_PAD_0,               // 0x5a
                    373:        KC_PAD_decimal, // 0x5b
                    374:        KC_none,                // 0x5c
                    375:        KC_none,                // 0x5d
                    376:        KC_none,                // 0x5e
                    377:        KC_none,                // 0x5f
                    378: 
                    379:        KC_none,                // 0x60
                    380:        KC_none,                // 0x61
                    381:        KC_up,                  // 0x62
                    382:        KC_none,                // 0x63
                    383:        KC_left,                // 0x64
                    384:        KC_none,                // 0x65
                    385:        KC_right,               // 0x66
                    386:        KC_none,                // 0x67
                    387:        KC_down,                // 0x68
                    388:        KC_none,                // 0x69
                    389:        KC_INS,                 // 0x6a
                    390:        KC_DEL,                 // 0x6b
                    391:        KC_PAD_enter,   // 0x6c
                    392:        KC_CTRL,                // 0x6d (CTRL_R)
                    393:        KC_none,                // 0x6e
                    394:        KC_none,                // 0x6f
                    395: 
                    396:        KC_PAD_divide,  // 0x70
                    397:        KC_none,                // 0x71
                    398:        KC_none,                // 0x72
                    399:        KC_none,                // 0x73
                    400:        KC_none,                // 0x74
                    401:        KC_none,                // 0x75
                    402:        KC_none,                // 0x76
                    403:        KC_none,                // 0x77
                    404:        KC_none,                // 0x78
                    405:        KC_none,                // 0x79
                    406:        KC_none,                // 0x7a
                    407:        KC_none,                // 0x7b
                    408:        KC_none,                // 0x7c
                    409:        KC_none,                // 0x7d
                    410:        KC_none,                // 0x7e
                    411:        KC_none,                // 0x7f
                    412: 
                    413:        KC_none,                // 0x80
                    414:        KC_none,                // 0x81
                    415:        KC_none,                // 0x82
                    416:        KC_none,                // 0x83
                    417:        KC_none,                // 0x84
                    418:        KC_backslash,   // 0x85
                    419:        KC_none,                // 0x86
                    420:        KC_none,                // 0x87
                    421:        KC_none,                // 0x88
                    422:        KC_none,                // 0x89
                    423:        KC_none,                // 0x8a
                    424:        KC_none,                // 0x8b
                    425:        KC_none,                // 0x8c
                    426:        KC_none,                // 0x8d
                    427:        KC_none,                // 0x8e
                    428:        KC_none,                // 0x8f
                    429: 
                    430:        KC_none, KC_none, KC_none, KC_none, // 0x90
                    431:        KC_none, KC_none, KC_none, KC_none,
                    432:        KC_none, KC_none, KC_none, KC_none,
                    433:        KC_none, KC_none, KC_none, KC_none,
                    434: 
                    435:        KC_none, KC_none, KC_none, KC_none, // 0xa0
                    436:        KC_none, KC_none, KC_none, KC_none,
                    437:        KC_none, KC_none, KC_none, KC_none,
                    438:        KC_none, KC_none, KC_none, KC_none,
                    439: 
                    440:        KC_none, KC_none, KC_none, KC_none, // 0xb0
                    441:        KC_none, KC_none, KC_none, KC_none,
                    442:        KC_none, KC_none, KC_none, KC_none,
                    443:        KC_none, KC_none, KC_none, KC_none,
                    444: 
                    445:        KC_none, KC_none, KC_none, KC_none, // 0xc0
                    446:        KC_none, KC_none, KC_none, KC_none,
                    447:        KC_none, KC_none, KC_none, KC_none,
                    448:        KC_none, KC_none, KC_none, KC_none,
                    449: 
                    450:        KC_none,                // 0xd0
                    451:        KC_none,                // 0xd1
                    452:        KC_none,                // 0xd2
                    453:        KC_underscore,  // 0xd3
                    454: };
                    455: #endif // __WXGTK__
                    456: 
                    457: #if defined(__WXOSX__)
                    458: // wxOSX の RawKeyCode を共通キーコードに変換するテーブル。
                    459: // Mac の CAPS は押す離すで一回分の KeyDown しか来ないのでちょっと放置。
                    460: // [英数] と [かな] もちょっと放置。
                    461: /*static*/ const int
                    462: WXMainView::keycode_table[0x80] = {
                    463:        KC_A,                   // 0x00
                    464:        KC_S,                   // 0x01
                    465:        KC_D,                   // 0x02
                    466:        KC_F,                   // 0x03
                    467:        KC_H,                   // 0x04
                    468:        KC_G,                   // 0x05
                    469:        KC_Z,                   // 0x06
                    470:        KC_X,                   // 0x07
                    471:        KC_C,                   // 0x08
                    472:        KC_V,                   // 0x09
                    473:        KC_none,                // 0x0a
                    474:        KC_B,                   // 0x0b
                    475:        KC_Q,                   // 0x0c
                    476:        KC_W,                   // 0x0d
                    477:        KC_E,                   // 0x0e
                    478:        KC_R,                   // 0x0f
                    479: 
                    480:        KC_Y,                   // 0x10
                    481:        KC_T,                   // 0x11
                    482:        KC_1,                   // 0x12
                    483:        KC_2,                   // 0x13
                    484:        KC_3,                   // 0x14
                    485:        KC_4,                   // 0x15
                    486:        KC_6,                   // 0x16
                    487:        KC_5,                   // 0x17
                    488:        KC_circum,              // 0x18
                    489:        KC_9,                   // 0x19
                    490:        KC_7,                   // 0x1a
                    491:        KC_minus,               // 0x1b
                    492:        KC_8,                   // 0x1c
                    493:        KC_0,                   // 0x1d
                    494:        KC_bracketleft, // 0x1e
                    495:        KC_O,                   // 0x1f
                    496: 
                    497:        KC_U,                   // 0x20
                    498:        KC_at,                  // 0x21
                    499:        KC_I,                   // 0x22
                    500:        KC_P,                   // 0x23
                    501:        KC_enter,               // 0x24
                    502:        KC_L,                   // 0x25
                    503:        KC_J,                   // 0x26
                    504:        KC_colon,               // 0x27
                    505:        KC_K,                   // 0x28
                    506:        KC_semicolon,   // 0x29
                    507:        KC_bracketright,// 0x2a
                    508:        KC_comma,               // 0x2b
                    509:        KC_slash,               // 0x2c
                    510:        KC_N,                   // 0x2d
                    511:        KC_M,                   // 0x2e
                    512:        KC_period,              // 0x2f
                    513: 
                    514:        KC_TAB,                 // 0x30
                    515:        KC_space,               // 0x31
                    516:        KC_none,                // 0x32
                    517:        KC_BS,                  // 0x33
                    518:        KC_none,                // 0x34
                    519:        KC_ESC,                 // 0x35
                    520:        KC_none,                // 0x36
                    521:        KC_none,                // 0x37
                    522:        KC_SHIFT_L,             // 0x38
                    523:        KC_none,                // 0x39
                    524:        KC_none,                // 0x3a
                    525:        KC_CTRL,                // 0x3b
                    526:        KC_SHIFT_R,             // 0x3c
                    527:        KC_none,                // 0x3d
                    528:        KC_none,                // 0x3e
                    529:        KC_none,                // 0x3f
                    530: 
                    531:        KC_none,                // 0x40
                    532:        KC_none,                // 0x41
                    533:        KC_none,                // 0x42
                    534:        KC_none,                // 0x43
                    535:        KC_none,                // 0x44
                    536:        KC_none,                // 0x45
                    537:        KC_none,                // 0x46
                    538:        KC_none,                // 0x47
                    539:        KC_none,                // 0x48
                    540:        KC_none,                // 0x49
                    541:        KC_none,                // 0x4a
                    542:        KC_none,                // 0x4b
                    543:        KC_none,                // 0x4c
                    544:        KC_none,                // 0x4d
                    545:        KC_none,                // 0x4e
                    546:        KC_none,                // 0x4f
                    547: 
                    548:        KC_none,                // 0x50
                    549:        KC_none,                // 0x51
                    550:        KC_none,                // 0x52
                    551:        KC_none,                // 0x53
                    552:        KC_none,                // 0x54
                    553:        KC_none,                // 0x55
                    554:        KC_none,                // 0x56
                    555:        KC_none,                // 0x57
                    556:        KC_none,                // 0x58
                    557:        KC_none,                // 0x59
                    558:        KC_none,                // 0x5a
                    559:        KC_none,                // 0x5b
                    560:        KC_none,                // 0x5c
                    561:        KC_backslash,   // 0x5d
                    562:        KC_underscore,  // 0x5e
                    563:        KC_none,                // 0x5f
                    564: 
                    565:        KC_F5,                  // 0x60
                    566:        KC_F6,                  // 0x61
                    567:        KC_F7,                  // 0x62
                    568:        KC_F3,                  // 0x63
                    569:        KC_F8,                  // 0x64
                    570:        KC_F9,                  // 0x65
                    571:        KC_none,                // 0x66
                    572:        KC_none,                // 0x67 F11
                    573:        KC_none,                // 0x68
                    574:        KC_none,                // 0x69
                    575:        KC_none,                // 0x6a
                    576:        KC_none,                // 0x6b
                    577:        KC_none,                // 0x6c
                    578:        KC_F10,                 // 0x6d
                    579:        KC_none,                // 0x6e
                    580:        KC_none,                // 0x6f F12
                    581: 
                    582:        KC_none,                // 0x70
                    583:        KC_none,                // 0x71
                    584:        KC_none,                // 0x72
                    585:        KC_none,                // 0x73
                    586:        KC_none,                // 0x74
                    587:        KC_none,                // 0x75
                    588:        KC_F4,                  // 0x76
                    589:        KC_none,                // 0x77
                    590:        KC_F2,                  // 0x78
                    591:        KC_none,                // 0x79
                    592:        KC_F1,                  // 0x7a
                    593:        KC_left,                // 0x7b
                    594:        KC_right,               // 0x7c
                    595:        KC_down,                // 0x7d
                    596:        KC_up,                  // 0x7e
                    597:        KC_none,                // 0x7f
                    598: };
                    599: #endif // __WXOSX__

unix.superglobalmegacorp.com

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