joncampbell123 / dosbox-x

DOSBox-X fork of the DOSBox project
GNU General Public License v2.0
2.76k stars 381 forks source link

Clipboard revisions #481

Open emendelson opened 6 years ago

emendelson commented 6 years ago

DOSBox-X uses a PasteClipboard function that I lifted from an old dbDOS version and posted in Vogons. Since I posted it, Wengier Wu suggested changing two lines so that the clipboard-paste could feed in upper-ASCII characters: these are around line 4287 (I'm not being exact because I made some changes elsewhere):

if (!::IsClipboardFormatAvailable(CF_OEMTEXT)) return; // change CF_TEXT to CF_OEMTEXT

HANDLE hContents = ::GetClipboardData(CF_OEMTEXT);      // ditto

For use with Windows running in DOSBox-X, I've been trying to figure out how to paste ANSI (codepage 1252) text instead of OEM text, but I've got mostly nowhere, because it involves translating from Unicode text to ANSI text, and that's beyond my abilities. If you see an easy way, it would be a nice feature to have.

joncampbell123 commented 6 years ago

Here's what I think should be done:

The problem is how to feed to the guest.

If the DOSBox kernel is running, then feeding to the guest is as simple as pushing to the BIOS keyboard interface where the BIOS keyboard buffer can hold the final value (as long as it's not zero).

If a guest OS is running, but using BIOS INT 16h, then the BIOS keyboard buffer method can still be used, but it won't work with DOS programs that talk directly to the keyboard.

The biggest problem is when the guest OS talks directly to the keyboard. The only way I can think of to type arbitrary upper ASCII to the guest is to send ALT+nnn keyboard input that IBM PCs have supported since forever.

sikthehedgehog commented 6 years ago

The biggest problem is when the guest OS talks directly to the keyboard. The only way I can think of to type arbitrary upper ASCII to the guest is to send ALT+nnn keyboard input that IBM PCs have supported since forever.

That will only work if the guest OS is Windows. That won't work with other guest OSes (which may implement their own method), nor with games that take over the keyboard interrupt (as they usually won't bother kicking the input back to the BIOS nor using the BIOS to read ASCII input). Although the latter also tend to completely ignore the concept of codepage anyway.

You may need to resort to including clipboard mappings which are analogous to keyboard mappings. Or just use whatever DOSBox-X is using for the current keyboard mapping already. Ultimately this may need to be turned into a setting in the long term I guess.

joncampbell123 commented 6 years ago

The only situation I know of where you would want to paste arbitrary text with upper ASCII is if you were running Windows 3.1 or Windows 95 as a guest OS, or a DOS-based text editor.

emendelson commented 6 years ago

Yes, if you're pasting text with French/German/etc. accents and diacritics into a Windows guest OS (or a DOS-based text editor), then you want to use upper ASCII. The change from CF_TEXT to CF_OEMTEXT works in DOS-based editors, but not in Windows (In my Win311 project, I use an AutoIt script running in the background that can feed ANSI text into the keyboard, but that's not portable at all.)

At one point in my experiments, when I was trying to feed ANSI text into the keyboard buffer, Windows thought I was pressing Alt keys, and kept going to the menus instead of feeding text. Jos Schaars, the author of vDos, suggested adding the following to SDLmain.cpp, after the line //putchar(cKey; and the closing brace below that line (EDIT: I can't seem to make the first five lines go into the code block, but you'll get the idea...)

`
// Jos Schaars adds else { if (KEYBOARD_BufferSpaceAvail() < (10+kPasteMinBufExtra)) // For simplicity, we just mimic Alt+<3 digits> return false;

    const SDLMod sdlmModsOn = SDL_GetModState();
    const bool bModShiftOn = ((sdlmModsOn & (KMOD_LSHIFT|KMOD_RSHIFT)) > 0);
    const bool bModCntrlOn = ((sdlmModsOn & (KMOD_LCTRL|KMOD_RCTRL )) > 0);
    const bool bModAltOn = ((sdlmModsOn&(KMOD_LALT|KMOD_RALT)) > 0);
    const SDLMod sdlmMods = (SDLMod)((sdlmModsOn&~(KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL|KMOD_LALT|KMOD_RALT)) |
                                             (bModShiftOn ? KMOD_LSHIFT : 0) |
                                             (bModCntrlOn ? KMOD_LCTRL  : 0) |
                                             (bModAltOn   ? KMOD_LALT   : 0));

    if (!bModAltOn)                                                // Alt down if not already down
        GenKBStroke(uiScanCodeAlt, true, sdlmMods);

    int ansiVal = cKey;
    for (int i = 100; i; i /= 10)
        {
        int numKey = ansiVal/i;                                    // High digit of Alt+ASCII number combination
        ansiVal %= i;
        UINT uiScanCode = MapVirtualKey(numKey+VK_NUMPAD0, MAPVK_VK_TO_VSC);
        GenKBStroke(uiScanCode, true, sdlmMods);
        GenKBStroke(uiScanCode, false, sdlmMods);
        }
    GenKBStroke(uiScanCodeAlt, false, sdlmMods);                // Alt up
    if (bModAltOn)                                                // Alt down if is was already down
        GenKBStroke(uiScanCodeAlt, true, sdlmMods);
    }
// end Jos Schaars adds

` This fixed the false Alt-letter keys, but didn't enter any (non-ASCII) ANSI text. I'm far too ignorant to take this any further, unfortunately.

emendelson commented 6 years ago

Until it becomes possible to paste ANSI text into Win 3.x/9x guests, could we have this very minor fix for pasting OEM (upper-ASCII) text from the Windows clipboard? This has been working correctly in one of my projects for many years:

https://github.com/emendelson/dosbox-x/commit/58436b837211c1e67ae8eb6d8dc20a4380c65434