diff --git a/src/android/i_system.c b/src/android/i_system.c index 150cbd50..58fca7c1 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -258,6 +258,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/console.c b/src/console.c index 11aa5cd5..02324ada 100644 --- a/src/console.c +++ b/src/console.c @@ -641,6 +641,12 @@ boolean CON_Responder(event_t *ev) key = ev->data1; + // Always eat ctrl/shift/alt, so the menu doesn't get ideas + if (key == KEY_LSHIFT || key == KEY_RSHIFT + || key == KEY_LCTRL || key == KEY_RCTRL + || key == KEY_LALT || key == KEY_RALT) + return true; + // check for console toggle key if (ev->type != ev_console) { @@ -677,67 +683,70 @@ boolean CON_Responder(event_t *ev) } - // command completion forward (tab) and backward (shift-tab) - if (key == KEY_TAB) + // ctrl modifier -- changes behavior, adds shortcuts + if (ctrldown) { // show all cvars/commands that match what we have inputted - if (ctrldown) + if (key == KEY_TAB) { - UINT32 i; - size_t stop = input_cx - 1; - char nameremainder[255]; + size_t i, len = strlen(inputlines[inputline]+1); - if (input_cx < 2 || strlen(inputlines[inputline]+1) >= 80) + if (input_cx < 2 || len >= 80 || strchr(inputlines[inputline]+1, ' ')) return true; strcpy(completion, inputlines[inputline]+1); - // trimming: stop at the first newline - for (i = 0; i < input_cx - 1; ++i) - { - if (completion[i] == ' ') - { - completion[i] = '\0'; - stop = i; - break; - } - } - - i = 0; - //first check commands CONS_Printf("\nCommands:\n"); - - for (cmd = COM_CompleteCommand(completion, i); cmd; cmd = COM_CompleteCommand(completion, i)) - { - strncpy(nameremainder, cmd+(stop), strlen(cmd)-(stop)); - nameremainder[strlen(cmd)-(stop)] = '\0'; - - CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, nameremainder); - ++i; - } - if (i == 0) - CONS_Printf(" (none)\n"); - - i = 0; + for (i = 0, cmd = COM_CompleteCommand(completion, i); cmd; cmd = COM_CompleteCommand(completion, ++i)) + CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len); + if (i == 0) CONS_Printf(" (none)\n"); //now we move on to CVARs CONS_Printf("Variables:\n"); - - for (cmd = CV_CompleteVar(completion, i); cmd; cmd = CV_CompleteVar(completion, i)) - { - strncpy(nameremainder, cmd+(stop), strlen(cmd)-(stop)); - nameremainder[strlen(cmd)-(stop)] = '\0'; - - CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, nameremainder); - ++i; - } - if (i == 0) - CONS_Printf(" (none)\n"); + for (i = 0, cmd = CV_CompleteVar(completion, i); cmd; cmd = CV_CompleteVar(completion, ++i)) + CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len); + if (i == 0) CONS_Printf(" (none)\n"); return true; } + // --- + if (key == KEY_HOME) // oldest text in buffer + { + con_scrollup = (con_totallines-((con_curlines-16)>>3)); + return true; + } + else if (key == KEY_END) // most recent text in buffer + { + con_scrollup = 0; + return true; + } + + if (key == 'x' || key == 'X') + { + CONS_Printf("Cut\n"); + return true; + } + else if (key == 'c' || key == 'C') + { + CONS_Printf("Copy\n"); + I_ClipboardCopy(inputlines[inputline]+1, strlen(inputlines[inputline]+1)); + return true; + } + else if (key == 'v' || key == 'V') + { + CONS_Printf("Paste: %s\n", I_ClipboardPaste()); + return true; + } + + // don't eat the key + return false; + } + + // command completion forward (tab) and backward (shift-tab) + if (key == KEY_TAB) + { // sequential command completion forward and backward // remember typing for several completions (a-la-4dos) @@ -815,16 +824,7 @@ boolean CON_Responder(event_t *ev) return true; } - if (key == KEY_HOME) // oldest text in buffer - { - con_scrollup = (con_totallines-((con_curlines-16)>>3)); - return true; - } - else if (key == KEY_END) // most recent text in buffer - { - con_scrollup = 0; - return true; - } + // command enter if (key == KEY_ENTER) diff --git a/src/djgppdos/i_system.c b/src/djgppdos/i_system.c index 854d68f4..dae9ed16 100644 --- a/src/djgppdos/i_system.c +++ b/src/djgppdos/i_system.c @@ -1721,6 +1721,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + const CPUInfoFlags *I_CPUInfo(void) { static CPUInfoFlags DOS_CPUInfo; diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index c1e48b60..a3fe3077 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -162,6 +162,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/i_system.h b/src/i_system.h index c161851e..d61f2d16 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -296,6 +296,14 @@ char *I_GetEnv(const char *name); INT32 I_PutEnv(char *variable); +/** \brief Put data in system clipboard +*/ +INT32 I_ClipboardCopy(const char *data, size_t size); + +/** \brief Retrieve data from system clipboard +*/ +const char *I_ClipboardPaste(void); + void I_RegisterSysCommands(void); #endif diff --git a/src/nds/i_system.c b/src/nds/i_system.c index 0ed58029..3e5c4b8c 100644 --- a/src/nds/i_system.c +++ b/src/nds/i_system.c @@ -269,6 +269,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ea8ade8c..8c4331aa 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -260,6 +260,18 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif +// FAKE_CLIPBOARD simulates system clipboard, but is just local to our app +#ifndef FAKE_CLIPBOARD +#include "SDL_syswm.h" + +#if defined (_WIN32) && !defined (_XBOX) +#include +#endif + +// TODO: clipboard support for other OSes + +#endif + /** \brief The JoyReset function \param JoySet Joystick info to reset @@ -2647,6 +2659,109 @@ INT32 I_PutEnv(char *variable) #endif } +#ifdef FAKE_CLIPBOARD +static char __clipboard[512] = ""; +#endif + +INT32 I_ClipboardCopy(const char *data, size_t size) +{ +#ifdef FAKE_CLIPBOARD + if (size >= 512) size = 511; + memcpy(__clipboard, data, size); + __clipboard[size] = 0; + return 0; +#else // !FAKE_CLIPBOARD + +#if defined(_WIN32) && !defined(_XBOX) + SDL_SysWMinfo syswm; + HGLOBAL *storage_ptr; + char *storage_raw; + + SDL_VERSION(&syswm.version); + + // Get window (HWND) information, use that to open the clipboard + if (!SDL_GetWindowWMInfo(window, &syswm) || !(OpenClipboard(syswm.info.win.window))) + return -1; + + // Erase clipboard contents -- if we have nothing to copy, just leave them blank + EmptyClipboard(); + if (size == 0) + goto clipboardend; + + // Allocate movable global memory to store our text. + if (!(storage_ptr = GlobalAlloc(GMEM_MOVEABLE, size+1)) + || !(storage_raw = (char *)GlobalLock(storage_ptr))) // Lock our pointer (gives us access to its data) + goto clipboardfail; + memcpy(storage_raw, data, size); + storage_raw[size] = 0; + GlobalUnlock(storage_ptr); // Unlock it before sending it off + if (!SetClipboardData(CF_TEXT, storage_ptr)) // NOTE: this removes our permissions from the pointer + goto clipboardfail; + +clipboardend: + CloseClipboard(); + return 0; //OpenClipboard(); +clipboardfail: + CloseClipboard(); // Don't leave me hanging + return -1; +#else + (void)data; + (void)size; + return -1; +#endif + +#endif // FAKE_CLIPBOARD +} + +const char *I_ClipboardPaste(void) +{ +#ifdef FAKE_CLIPBOARD + return (const char *)&__clipboard; +#else // !FAKE_CLIPBOARD + +#if defined(_WIN32) && !defined(_XBOX) + HGLOBAL *clipboard_ptr; + const char *clipboard_raw; + static char clipboard_contents[512]; + char *i = clipboard_contents; + + if (!IsClipboardFormatAvailable(CF_TEXT)) + return NULL; // Data either unavailable, or in wrong format + OpenClipboard(NULL); // NOTE: Don't need window pointer to get, only to set + if (!(clipboard_ptr = GetClipboardData(CF_TEXT))) // Get global pointer + return NULL; + if (!(clipboard_raw = (const char *)GlobalLock(clipboard_ptr))) // Lock access -- gives us direct ptr to data + { + CloseClipboard(); // Don't leave me hanging if we fail + return NULL; + } + memcpy(clipboard_contents, clipboard_raw, 511); + GlobalUnlock(clipboard_ptr); // Unlock for other apps + CloseClipboard(); // And make sure to close the clipboard for other apps too + clipboard_contents[511] = 0; // Done after unlock to cause as little interference as possible + + while (*i) + { + if (*i == '\n' || *i == '\r') + { // End on newline + *i = 0; + break; + } + else if (*i == '\t') + *i = ' '; // Tabs become spaces + else if (*i < 32 || (unsigned)*i > 127) + *i = '?'; // Nonprintable chars become question marks + ++i; + } + + return (const char *)&clipboard_contents; +#else + return NULL; +#endif + +#endif // FAKE_CLIPBOARD +} + /** \brief The isWadPathOk function \param path string path to check diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 7e144644..2d6209f2 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -24,7 +24,6 @@ boolean OglSdlSurface(INT32 w, INT32 h); void OglSdlFinishUpdate(boolean vidwait); -extern SDL_Window *window; extern SDL_Renderer *renderer; extern SDL_GLContext sdlglcontext; extern Uint16 realwidth; diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 7ac32f4b..fea1e164 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -71,4 +71,7 @@ void I_GetConsoleEvents(void); void SDLforceUngrabMouse(void); +// Needed for some WIN32 functions +extern SDL_Window *window; + #endif diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index 888a6a50..ed0db653 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -2666,6 +2666,18 @@ INT32 I_PutEnv(char *variable) #endif } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + /** \brief The isWadPathOk function \param path string path to check diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 0331080c..eec04380 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -3598,6 +3598,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + typedef BOOL (WINAPI *p_IsProcessorFeaturePresent) (DWORD); const CPUInfoFlags *I_CPUInfo(void) diff --git a/src/win32ce/win_sys.c b/src/win32ce/win_sys.c index 88764ef7..3b6a4725 100644 --- a/src/win32ce/win_sys.c +++ b/src/win32ce/win_sys.c @@ -3470,6 +3470,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + typedef BOOL (WINAPI *MyFunc3) (DWORD); const CPUInfoFlags *I_CPUInfo(void)