1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #include "NstIoScreen.hpp" 26 #include "NstResourceString.hpp" 27 #include "NstResourceClipboard.hpp" 28 #include "NstSystemKeyboard.hpp" 29 #include "NstManager.hpp" 30 #include "NstManagerInput.hpp" 31 32 namespace Nestopia 33 { 34 namespace Managers 35 { Clipboard(Emulator & e,Window::Menu & m)36 Input::Clipboard::Clipboard(Emulator& e,Window::Menu& m) 37 : 38 Manager (e,m), 39 paste (false) 40 { 41 static const Window::Menu::CmdHandler::Entry<Clipboard> commands[] = 42 { 43 { IDM_MACHINE_EXT_KEYBOARD_PASTE, &Clipboard::OnCmdMachineKeyboardPaste } 44 }; 45 46 menu.Commands().Add( this, commands ); 47 48 static const Window::Menu::PopupHandler::Entry<Clipboard> popups[] = 49 { 50 { Window::Menu::PopupHandler::Pos<IDM_POS_MACHINE,IDM_POS_MACHINE_EXT,IDM_POS_MACHINE_EXT_KEYBOARD>::ID, &Clipboard::OnMenuKeyboard } 51 }; 52 53 menu.Popups().Add( this, popups ); 54 55 HeapString name; 56 menu[IDM_MACHINE_EXT_KEYBOARD_PASTE].Text() >> name; 57 menu[IDM_MACHINE_EXT_KEYBOARD_PASTE].Text() << (name << '\t' << System::Keyboard::GetName( VK_F12 )); 58 } 59 Clear()60 void Input::Clipboard::Clear() 61 { 62 paste = false; 63 buffer.Destroy(); 64 } 65 CanPaste() const66 bool Input::Clipboard::CanPaste() const 67 { 68 return emulator.IsGameOn() && buffer.Empty() && Resource::Clipboard::Available() && 69 ( 70 Nes::Input(emulator).IsControllerConnected( Nes::Input::FAMILYKEYBOARD ) || 71 Nes::Input(emulator).IsControllerConnected( Nes::Input::SUBORKEYBOARD ) 72 ); 73 } 74 Query(const uchar * const NST_RESTRICT keyboard,const Type type)75 uint Input::Clipboard::Query(const uchar* const NST_RESTRICT keyboard,const Type type) 76 { 77 const bool prev = paste; 78 paste = false; 79 80 if (buffer.Empty()) 81 { 82 if (prev || (keyboard[DIK_F12] & 0x80U)) 83 { 84 Resource::Clipboard resource; 85 86 if (wcstring string = resource) 87 { 88 pos = 0; 89 releasing = 0; 90 hold = 0; 91 shifted = false; 92 93 bool kana = false; 94 95 for (wchar_t p; '\0' != (p = *string); ++string) 96 { 97 bool mode = false; 98 99 if (p < 32) 100 { 101 if (p != '\r') 102 continue; 103 } 104 else if (p >= 'A' && p <= 'Z') 105 { 106 p = p - 'A' + 'a'; 107 } 108 else if (p > 122) 109 { 110 if (p == 165) // '' 111 { 112 p = '\\'; 113 } 114 else if (type == SUBOR) 115 { 116 if (p > 125) 117 continue; 118 } 119 else if (p > 0xFF00) 120 { 121 switch (p) 122 { 123 case 0xFF71: p = '1'; break; 124 case 0xFF72: p = '2'; break; 125 case 0xFF73: p = '3'; break; 126 case 0xFF74: p = '4'; break; 127 case 0xFF75: p = '5'; break; 128 129 case 0xFF67: p = '!'; break; 130 case 0xFF68: p = '\"'; break; 131 case 0xFF69: p = '#'; break; 132 case 0xFF6A: p = '$'; break; 133 case 0xFF6B: p = '%'; break; 134 135 case 0xFF6F: p = 'c' | 0x80; break; 136 137 case 0xFF76: p = 'q'; break; 138 case 0xFF77: p = 'w'; break; 139 case 0xFF78: p = 'e'; break; 140 case 0xFF79: p = 'r'; break; 141 case 0xFF7A: p = 't'; break; 142 143 case 0xFF9E: 144 145 if (buffer.Length()) 146 buffer.Back() |= 0x100; 147 148 continue; 149 150 case 0xFF9F: 151 152 if (buffer.Length()) 153 buffer.Back() |= 0x80; 154 155 continue; 156 157 case 0xFF7B: p = 'a'; break; 158 case 0xFF7C: p = 's'; break; 159 case 0xFF7D: p = 'd'; break; 160 case 0xFF7E: p = 'f'; break; 161 case 0xFF7F: p = 'g'; break; 162 163 case 0xFF80: p = 'z'; break; 164 case 0xFF81: p = 'x'; break; 165 case 0xFF82: p = 'c'; break; 166 case 0xFF83: p = 'v'; break; 167 case 0xFF84: p = 'b'; break; 168 169 case 0xFF85: p = '6'; break; 170 case 0xFF86: p = '7'; break; 171 case 0xFF87: p = '8'; break; 172 case 0xFF88: p = '9'; break; 173 case 0xFF89: p = '0'; break; 174 175 case 0xFF8A: p = 'y'; break; 176 case 0xFF8B: p = 'u'; break; 177 case 0xFF8C: p = 'i'; break; 178 case 0xFF8D: p = 'o'; break; 179 case 0xFF8E: p = 'p'; break; 180 181 case 0xFF8F: p = 'h'; break; 182 case 0xFF90: p = 'j'; break; 183 case 0xFF91: p = 'k'; break; 184 case 0xFF92: p = 'l'; break; 185 case 0xFF93: p = ';'; break; 186 187 case 0xFF94: p = 'n'; break; 188 case 0xFF95: p = 'm'; break; 189 case 0xFF96: p = ','; break; 190 191 case 0xFF6C: p = 'n' | 0x80; break; 192 case 0xFF6D: p = 'm' | 0x80; break; 193 case 0xFF6E: p = '<'; break; 194 195 case 0xFF97: p = '-'; break; 196 case 0xFF98: p = '^'; break; 197 case 0xFF99: p = '\\'; break; 198 case 0xFF9A: p = '@'; break; 199 case 0xFF9B: p = '['; break; 200 201 case 0xFF9C: p = '.'; break; 202 case 0xFF66: p = '-'; break; 203 case 0xFF9D: p = '\t'; break; 204 205 case 0xFF61: p = ']'; break; 206 case 0xFF62: p = '[' | 0x80; break; 207 case 0xFF63: p = ']' | 0x80; break; 208 209 default: continue; 210 } 211 212 mode = true; 213 } 214 else 215 { 216 continue; 217 } 218 } 219 220 if (kana != mode) 221 { 222 kana = mode; 223 buffer << char(0xFF); 224 } 225 226 buffer << (p); 227 } 228 229 if (kana) 230 buffer << char(0xFF); 231 232 if (buffer.Length()) 233 Io::Screen() << Resource::String( IDS_SCREEN_TEXT_PASTE ).Invoke( buffer.Length() ); 234 } 235 } 236 } 237 else 238 { 239 if (keyboard[DIK_ESCAPE] & 0x80U) 240 Clear(); 241 } 242 243 return buffer.Length(); 244 } 245 OnCmdMachineKeyboardPaste(uint)246 void Input::Clipboard::OnCmdMachineKeyboardPaste(uint) 247 { 248 paste = CanPaste(); 249 Resume(); 250 } 251 OnMenuKeyboard(const Window::Menu::PopupHandler::Param & param)252 void Input::Clipboard::OnMenuKeyboard(const Window::Menu::PopupHandler::Param& param) 253 { 254 param.menu[IDM_MACHINE_EXT_KEYBOARD_PASTE].Enable( !param.show || CanPaste() ); 255 } 256 257 #ifdef NST_MSVC_OPTIMIZE 258 #pragma optimize("t", on) 259 #endif 260 operator ++()261 void Input::Clipboard::operator ++ () 262 { 263 hold = (hold + 1) & 7; 264 265 if (!hold) 266 { 267 shifted = false; 268 releasing = 32; 269 270 if (++pos == buffer.Length()) 271 Clear(); 272 } 273 } 274 275 #ifdef NST_MSVC_OPTIMIZE 276 #pragma optimize("", on) 277 #endif 278 } 279 } 280