From 81077656772cbd91ceee32e919fa7fb68f2dbc83 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 2 Nov 2016 14:26:35 -0700 Subject: [PATCH 1/8] make console back color use just one section of memory let's be honest, it's pretty dumb to have every single possible back colormap in memory when only one is being used at a time --- src/console.c | 99 +++++++++++++++++++++++++-------------------------- src/console.h | 7 ++-- src/p_setup.c | 2 +- src/v_video.c | 37 ++++++++----------- src/v_video.h | 2 +- 5 files changed, 68 insertions(+), 79 deletions(-) diff --git a/src/console.c b/src/console.c index 025bc1c1..3fa9b8a9 100644 --- a/src/console.c +++ b/src/console.c @@ -97,6 +97,7 @@ static void CON_InputInit(void); static void CON_RecalcSize(void); static void CONS_hudlines_Change(void); +static void CONS_backcolor_Change(void); static void CON_DrawBackpic(patch_t *pic, INT32 startx, INT32 destwidth); //static void CON_DrawBackpic2(pic_t *pic, INT32 startx, INT32 destwidth); @@ -129,10 +130,11 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"} // whether to use console background picture, or translucent mode static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Orange"}, - {2, "Blue"}, {3, "Green"}, {4, "Gray"}, - {5, "Red"}, {0, NULL}}; -consvar_t cons_backcolor = {"con_backcolor", "3", CV_SAVE, backcolor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"}, + {3, "Red"}, {4, "Orange"}, {5, "Yellow"}, + {6, "Green"}, {7, "Blue"}, {8, "Cyan"}, + {0, NULL}}; +consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; static void CON_Print(char *msg); @@ -219,8 +221,9 @@ static void CONS_Bind_f(void) // CONSOLE SETUP //====================================================================== -// Prepare a colormap for GREEN ONLY translucency over background -// +// Font colormap colors +// TODO: This could probably be improved somehow... +// These colormaps are 99% identical, with just a few changed bytes UINT8 *yellowmap; UINT8 *purplemap; UINT8 *lgreenmap; @@ -229,44 +232,49 @@ UINT8 *graymap; UINT8 *redmap; UINT8 *orangemap; -// Console BG colors -UINT8 *cwhitemap; -UINT8 *corangemap; -UINT8 *cbluemap; -UINT8 *cgreenmap; -UINT8 *cgraymap; -UINT8 *credmap; +// Console BG color +UINT8 *consolebgmap = NULL; -void CON_ReSetupBackColormap(UINT16 num) +void CON_SetupBackColormap(void) { - UINT16 i, j; - UINT8 k; - UINT8 *pal = W_CacheLumpName(R_GetPalname(num), PU_CACHE); + UINT16 i, palsum; + UINT8 j, palindex; + UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE); - // setup the green translucent background colormaps - for (i = 0, k = 0; i < 768; i += 3, k++) + if (!consolebgmap) + consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); + + switch (cons_backcolor.value) { - j = pal[i] + pal[i+1] + pal[i+2]; - cwhitemap[k] = (UINT8)(15 - (j>>6)); - corangemap[k] = (UINT8)(95 - (j>>6)); - cbluemap[k] = (UINT8)(239 - (j>>6)); - cgreenmap[k] = (UINT8)(175 - (j>>6)); - cgraymap[k] = (UINT8)(31 - (j>>6)); - credmap[k] = (UINT8)(143 - (j>>6)); + case 0: palindex = 15; break; // White + case 1: palindex = 31; break; // Gray + case 2: palindex = 63; break; // Brown + case 3: palindex = 143; break; // Red + case 4: palindex = 95; break; // Orange + case 5: palindex = 111; break; // Yellow + case 6: palindex = 175; break; // Green + case 7: palindex = 239; break; // Blue + case 8: palindex = 219; break; // Cyan + // Default green + default: palindex = 175; break; +} + + // setup background colormap + for (i = 0, j = 0; i < 768; i += 3, j++) + { + palsum = (pal[i] + pal[i+1] + pal[i+2]) >> 6; + consolebgmap[j] = (UINT8)(palindex - palsum); } } -static void CON_SetupBackColormap(void) +static void CONS_backcolor_Change(void) { - INT32 i, j, k; - UINT8 *pal; + CON_SetupBackColormap(); +} - cwhitemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - corangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cbluemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cgreenmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cgraymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - credmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); +static void CON_SetupColormaps(void) +{ + INT32 i; yellowmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); graymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); @@ -276,20 +284,6 @@ static void CON_SetupBackColormap(void) redmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); orangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - pal = W_CacheLumpName("PLAYPAL", PU_CACHE); - - // setup the green translucent background colormaps - for (i = 0, k = 0; i < 768; i += 3, k++) - { - j = pal[i] + pal[i+1] + pal[i+2]; - cwhitemap[k] = (UINT8)(15 - (j>>6)); - corangemap[k] = (UINT8)(95 - (j>>6)); - cbluemap[k] = (UINT8)(239 - (j>>6)); - cgreenmap[k] = (UINT8)(175 - (j>>6)); - cgraymap[k] = (UINT8)(31 - (j>>6)); - credmap[k] = (UINT8)(143 - (j>>6)); - } - // setup the other colormaps, for console text // these don't need to be aligned, unless you convert the @@ -320,6 +314,9 @@ static void CON_SetupBackColormap(void) redmap[9] = (UINT8)127; orangemap[3] = (UINT8)85; orangemap[9] = (UINT8)90; + + // Init back colormap + CON_SetupBackColormap(); } // Setup the console text buffer @@ -343,7 +340,7 @@ void CON_Init(void) con_width = 0; CON_RecalcSize(); - CON_SetupBackColormap(); + CON_SetupColormaps(); //note: CON_Ticker should always execute at least once before D_Display() con_clipviewtop = -1; // -1 does not clip @@ -1417,7 +1414,7 @@ static void CON_DrawConsole(void) { // inu: no more width (was always 0 and vid.width) if (rendermode != render_none) - V_DrawFadeConsBack(con_curlines, cons_backcolor.value); // translucent background + V_DrawFadeConsBack(con_curlines); // translucent background } // draw console text lines from top to bottom diff --git a/src/console.h b/src/console.h index 47af65e2..8cf6483f 100644 --- a/src/console.h +++ b/src/console.h @@ -40,11 +40,10 @@ extern consvar_t cons_backcolor; extern UINT8 *yellowmap, *purplemap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap; -// Console bg colors: -extern UINT8 *cwhitemap, *corangemap, *cbluemap, *cgreenmap, *cgraymap, - *credmap; +// Console bg color (auto updated to match) +extern UINT8 *consolebgmap; -void CON_ReSetupBackColormap(UINT16 num); +void CON_SetupBackColormap(void); void CON_ClearHUD(void); // clear heads up messages void CON_Ticker(void); diff --git a/src/p_setup.c b/src/p_setup.c index e56c44c7..111c717d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2585,7 +2585,7 @@ boolean P_SetupLevel(boolean skipprecip) lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap)); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); - CON_ReSetupBackColormap(mapheaderinfo[gamemap-1]->palette); + CON_SetupBackColormap(); // now part of level loading since in future each level may have // its own anim texture sequences, switches etc. diff --git a/src/v_video.c b/src/v_video.c index 3cc6d195..43e3f018 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -968,45 +968,38 @@ void V_DrawFadeScreen(void) } // Simple translucency with one color, over a set number of lines starting from the top. -void V_DrawFadeConsBack(INT32 plines, INT32 pcolor) +void V_DrawFadeConsBack(INT32 plines) { - UINT8 *deststop, *colormap, *buf; + UINT8 *deststop, *buf; #ifdef HWRENDER // not win32 only 19990829 by Kin if (rendermode != render_soft && rendermode != render_none) { UINT32 hwcolor; - switch (pcolor) + switch (cons_backcolor.value) { - case 0: hwcolor = 0xffffff00; break; //white - case 1: hwcolor = 0xff800000; break; //orange - case 2: hwcolor = 0x0000ff00; break; //blue - case 3: hwcolor = 0x00800000; break; //green - case 4: hwcolor = 0x80808000; break; //gray - case 5: hwcolor = 0xff000000; break; //red - default: hwcolor = 0x00800000; break; //green + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x80808000; break; // Gray + case 2: hwcolor = 0x40201000; break; // Brown + case 3: hwcolor = 0xff000000; break; // Red + case 4: hwcolor = 0xff800000; break; // Orange + case 5: hwcolor = 0x80800000; break; // Yellow + case 6: hwcolor = 0x00800000; break; // Green + case 7: hwcolor = 0x0000ff00; break; // Blue + case 8: hwcolor = 0x4080ff00; break; // Cyan + // Default green + default: hwcolor = 0x00800000; break; } HWR_DrawConsoleBack(hwcolor, plines); return; } #endif - switch (pcolor) - { - case 0: colormap = cwhitemap; break; - case 1: colormap = corangemap; break; - case 2: colormap = cbluemap; break; - case 3: colormap = cgreenmap; break; - case 4: colormap = cgraymap; break; - case 5: colormap = credmap; break; - default: colormap = cgreenmap; break; - } - // heavily simplified -- we don't need to know x or y position, // just the stop position deststop = screens[0] + vid.rowbytes * min(plines, vid.height); for (buf = screens[0]; buf < deststop; ++buf) - *buf = colormap[*buf]; + *buf = consolebgmap[*buf]; } // Gets string colormap, used for 0x80 color codes diff --git a/src/v_video.h b/src/v_video.h index 70255d0e..353f84c1 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -145,7 +145,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); // fade down the screen buffer before drawing the menu over void V_DrawFadeScreen(void); -void V_DrawFadeConsBack(INT32 plines, INT32 pcolor); +void V_DrawFadeConsBack(INT32 plines); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); From c277125fe7bbf18639ae830b5b1b695179ac7f3b Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 2 Nov 2016 15:23:22 -0700 Subject: [PATCH 2/8] modifier key status made globally accessible now also properly handles L/R simultaneous presses --- src/console.c | 25 ++----------------------- src/d_main.c | 36 ++++++++++++++++++++++++++++++++++++ src/doomdef.h | 3 +++ src/hu_stuff.c | 7 ------- src/m_menu.c | 12 ------------ 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/console.c b/src/console.c index 3fa9b8a9..11aa5cd5 100644 --- a/src/console.c +++ b/src/console.c @@ -619,9 +619,7 @@ void CON_Ticker(void) // boolean CON_Responder(event_t *ev) { - static boolean consdown; - static boolean shiftdown; - static boolean ctrldown; + static UINT8 consdown = false; // console is treated differently due to rare usage // sequential completions a la 4dos static char completion[80]; @@ -636,13 +634,8 @@ boolean CON_Responder(event_t *ev) // let go keyup events, don't eat them if (ev->type != ev_keydown && ev->type != ev_console) { - if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) - shiftdown = false; - else if (ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL) - ctrldown = false; - else if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1]) + if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1]) consdown = false; - return false; } @@ -684,20 +677,6 @@ boolean CON_Responder(event_t *ev) } - // eat shift only if console active - if (key == KEY_LSHIFT || key == KEY_RSHIFT) - { - shiftdown = true; - return true; - } - - // same for ctrl - if (key == KEY_LCTRL || key == KEY_RCTRL) - { - ctrldown = true; - return true; - } - // command completion forward (tab) and backward (shift-tab) if (key == KEY_TAB) { diff --git a/src/d_main.c b/src/d_main.c index b61ec414..2caf5008 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -73,6 +73,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "dehacked.h" // Dehacked list test #include "m_cond.h" // condition initialization #include "fastcmp.h" +#include "keys.h" #ifdef CMAKECONFIG #include "config.h" @@ -176,6 +177,38 @@ void D_PostEvent(const event_t *ev) void D_PostEvent_end(void) {}; #endif +// modifier keys +UINT8 shiftdown = 0; // 0x1 left, 0x2 right +UINT8 ctrldown = 0; // 0x1 left, 0x2 right +UINT8 altdown = 0; // 0x1 left, 0x2 right +// +// D_ModifierKeyResponder +// Sets global shift/ctrl/alt variables, never actually eats events +// +static inline void D_ModifierKeyResponder(event_t *ev) +{ + if (ev->type == ev_keydown) switch (ev->data1) + { + case KEY_LSHIFT: shiftdown |= 0x1; return; + case KEY_RSHIFT: shiftdown |= 0x2; return; + case KEY_LCTRL: ctrldown |= 0x1; return; + case KEY_RCTRL: ctrldown |= 0x2; return; + case KEY_LALT: altdown |= 0x1; return; + case KEY_RALT: altdown |= 0x2; return; + default: return; + } + else if (ev->type == ev_keyup) switch (ev->data1) + { + case KEY_LSHIFT: shiftdown &= ~0x1; return; + case KEY_RSHIFT: shiftdown &= ~0x2; return; + case KEY_LCTRL: ctrldown &= ~0x1; return; + case KEY_RCTRL: ctrldown &= ~0x2; return; + case KEY_LALT: altdown &= ~0x1; return; + case KEY_RALT: altdown &= ~0x2; return; + default: return; + } +} + // // D_ProcessEvents // Send all the events of the given timestamp down the responder chain @@ -188,6 +221,9 @@ void D_ProcessEvents(void) { ev = &events[eventtail]; + // Set global shift/ctrl/alt down variables + D_ModifierKeyResponder(ev); // never eats events + // Screenshots over everything so that they can be taken anywhere. if (M_ScreenshotResponder(ev)) continue; // ate the event diff --git a/src/doomdef.h b/src/doomdef.h index fb8ab1ca..4b2d8c73 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -394,6 +394,9 @@ extern INT32 cv_debug; // Misc stuff for later... // ======================= +// Modifier key variables, accessible anywhere +extern UINT8 shiftdown, ctrldown, altdown; + // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index ec747305..e33a5430 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -757,15 +757,8 @@ void HU_clearChatChars(void) // boolean HU_Responder(event_t *ev) { - static boolean shiftdown = false; UINT8 c; - if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) - { - shiftdown = (ev->type == ev_keydown); - return chat_on; - } - if (ev->type != ev_keydown) return false; diff --git a/src/m_menu.c b/src/m_menu.c index 78c38127..d7b4d908 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -182,9 +182,6 @@ static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; -// what a headache. -static boolean shiftdown = false; - // // PROTOTYPES // @@ -2080,11 +2077,6 @@ boolean M_Responder(event_t *ev) || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) return false; - if (ev->type == ev_keyup && (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT)) - { - shiftdown = false; - return false; - } if (noFurtherInput) { // Ignore input after enter/escape/other buttons @@ -2098,10 +2090,6 @@ boolean M_Responder(event_t *ev) // added 5-2-98 remap virtual keys (mouse & joystick buttons) switch (ch) { - case KEY_LSHIFT: - case KEY_RSHIFT: - shiftdown = true; - break; //return false; case KEY_MOUSE1: case KEY_JOY1: case KEY_JOY1 + 2: From bb20cfd6beb341c0774c473150ebb9e1d889cbfe Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Thu, 3 Nov 2016 01:43:57 -0700 Subject: [PATCH 3/8] Clipboard copy/paste testing (unfinished, but basics work) --- src/android/i_system.c | 12 +++++ src/console.c | 108 ++++++++++++++++++------------------- src/djgppdos/i_system.c | 12 +++++ src/dummy/i_system.c | 12 +++++ src/i_system.h | 8 +++ src/nds/i_system.c | 12 +++++ src/sdl/i_system.c | 115 ++++++++++++++++++++++++++++++++++++++++ src/sdl/ogl_sdl.h | 1 - src/sdl/sdlmain.h | 3 ++ src/sdl12/i_system.c | 12 +++++ src/win32/win_sys.c | 12 +++++ src/win32ce/win_sys.c | 12 +++++ 12 files changed, 264 insertions(+), 55 deletions(-) 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) From 8040a68fa087f4c09f60c5663fd08077830b8707 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 3 Nov 2016 14:29:51 -0400 Subject: [PATCH 4/8] Clipboard: remove Win32 code for SDL Clipboard API --- src/sdl/i_system.c | 107 ++------------------------------------------- 1 file changed, 4 insertions(+), 103 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 8c4331aa..97746b6b 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -260,18 +260,6 @@ 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 @@ -2659,107 +2647,20 @@ 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; + if (SDL_SetClipboardText(data) == 0) + return 0; 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 + if (SDL_HasClipboardText()) + return SDL_GetClipboardText(); return NULL; -#endif - -#endif // FAKE_CLIPBOARD } /** \brief The isWadPathOk function From 1f6388a2e0089c6004825fa7ef66c54c0800de73 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Thu, 3 Nov 2016 14:35:32 -0400 Subject: [PATCH 5/8] Fix up Win32 interface code misdeclaration of I_ClipboardPaste() --- src/win32/win_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index eec04380..80b89a6e 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -3605,7 +3605,7 @@ INT32 I_ClipboardCopy(const char *data, size_t size) return -1; } -char *I_ClipboardPaste(void) +const char *I_ClipboardPaste(void) { return NULL; } From e245cdfcbf41fed6667565c4f4fd3568eed297cd Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Thu, 3 Nov 2016 17:30:30 -0700 Subject: [PATCH 6/8] Console with moving cursor, selections, etc --- src/console.c | 355 +++++++++++++++++++++++++++++++++------------ src/sdl/i_system.c | 104 ++----------- src/v_video.c | 76 +++++----- 3 files changed, 322 insertions(+), 213 deletions(-) diff --git a/src/console.c b/src/console.c index 02324ada..ea5999c0 100644 --- a/src/console.c +++ b/src/console.c @@ -84,13 +84,16 @@ UINT32 con_scalefactor; // text size scale factor // hold 32 last lines of input for history #define CON_MAXPROMPTCHARS 256 -#define CON_PROMPTCHAR '>' +#define CON_PROMPTCHAR '$' static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines static INT32 inputline; // current input line number static INT32 inputhist; // line number of history input line to restore -static size_t input_cx; // position in current input line +static size_t input_cur; // position of cursor in line +static size_t input_sel; // position of selection marker (I.E.: anything between this and input_cur is "selected") +static size_t input_len; // length of current line, used to bound cursor and such +// notice: input does NOT include the "$" at the start of the line. - 11/3/16 // protos. static void CON_InputInit(void); @@ -383,14 +386,10 @@ void CON_Init(void) // static void CON_InputInit(void) { - INT32 i; - // prepare the first prompt line memset(inputlines, 0, sizeof (inputlines)); - for (i = 0; i < 32; i++) - inputlines[i][0] = CON_PROMPTCHAR; inputline = 0; - input_cx = 1; + input_cur = input_sel = input_len = 0; } //====================================================================== @@ -615,6 +614,86 @@ void CON_Ticker(void) } } +// +// ---- +// +// Shortcuts for adding and deleting characters, strings, and sections +// Necessary due to moving cursor +// + +static inline void CON_InputClear(void) +{ + memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + input_cur = input_sel = input_len = 0; +} + +static inline void CON_InputSetString(const char *c) +{ + memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + strcpy(inputlines[inputline], c); + input_cur = input_sel = input_len = strlen(c); +} + +static inline void CON_InputAddString(const char *c) +{ + size_t csize = strlen(c); + if (input_len + csize > CON_MAXPROMPTCHARS-1) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur+csize], &inputlines[inputline][input_cur], input_len-input_cur); + memcpy(&inputlines[inputline][input_cur], c, csize); + input_len += csize; + input_sel = (input_cur += csize); +} + +static inline void CON_InputDelSelection(void) +{ + size_t start, end, len; + if (input_cur > input_sel) + { + start = input_sel; + end = input_cur; + } + else + { + start = input_cur; + end = input_sel; + } + len = (end - start); + + if (end != input_len) + memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-input_cur); + memset(&inputlines[inputline][input_len - len], 0, len); + + input_len -= len; + input_sel = input_cur = start; +} + +static inline void CON_InputAddChar(char c) +{ + if (input_len >= CON_MAXPROMPTCHARS-1) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur+1], &inputlines[inputline][input_cur], input_len-input_cur); + inputlines[inputline][input_cur++] = c; + inputlines[inputline][++input_len] = 0; + input_sel = input_cur; +} + +static inline void CON_InputDelChar(void) +{ + if (!input_cur) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur-1], &inputlines[inputline][input_cur], input_len-input_cur); + inputlines[inputline][--input_len] = 0; + input_sel = --input_cur; +} + +// +// ---- +// + // Handles console key input // boolean CON_Responder(event_t *ev) @@ -689,12 +768,16 @@ boolean CON_Responder(event_t *ev) // show all cvars/commands that match what we have inputted if (key == KEY_TAB) { - size_t i, len = strlen(inputlines[inputline]+1); + size_t i, len; - if (input_cx < 2 || len >= 80 || strchr(inputlines[inputline]+1, ' ')) - return true; - - strcpy(completion, inputlines[inputline]+1); + if (!completion[0]) + { + if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' ')) + return true; + strcpy(completion, inputlines[inputline]); + comskips = varskips = 0; + } + len = strlen(completion); //first check commands CONS_Printf("\nCommands:\n"); @@ -725,18 +808,38 @@ boolean CON_Responder(event_t *ev) if (key == 'x' || key == 'X') { - CONS_Printf("Cut\n"); + if (input_sel > input_cur) + I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); + else + I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); + CON_InputDelSelection(); + completion[0] = 0; return true; } else if (key == 'c' || key == 'C') { - CONS_Printf("Copy\n"); - I_ClipboardCopy(inputlines[inputline]+1, strlen(inputlines[inputline]+1)); + if (input_sel > input_cur) + I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); + else + I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); return true; } else if (key == 'v' || key == 'V') { - CONS_Printf("Paste: %s\n", I_ClipboardPaste()); + const char *paste = I_ClipboardPaste(); + if (input_sel != input_cur) + CON_InputDelSelection(); + if (paste != NULL) + CON_InputAddString(paste); + completion[0] = 0; + return true; + } + + // Select all + if (key == 'a' || key == 'A') + { + input_sel = 0; + input_cur = input_len; return true; } @@ -750,13 +853,11 @@ boolean CON_Responder(event_t *ev) // sequential command completion forward and backward // remember typing for several completions (a-la-4dos) - if (inputlines[inputline][input_cx-1] != ' ') + if (!completion[0]) { - if (strlen(inputlines[inputline]+1) < 80) - strcpy(completion, inputlines[inputline]+1); - else - completion[0] = 0; - + if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' ')) + return true; + strcpy(completion, inputlines[inputline]); comskips = varskips = 0; } else @@ -768,37 +869,26 @@ boolean CON_Responder(event_t *ev) if (--varskips < 0) comskips = -comskips - 2; } - else if (comskips > 0) - comskips--; + else if (comskips > 0) comskips--; } else { - if (comskips < 0) - varskips++; - else - comskips++; + if (comskips < 0) varskips++; + else comskips++; } } if (comskips >= 0) { cmd = COM_CompleteCommand(completion, comskips); - if (!cmd) - // dirty: make sure if comskips is zero, to have a neg value + if (!cmd) // dirty: make sure if comskips is zero, to have a neg value comskips = -comskips - 1; } if (comskips < 0) cmd = CV_CompleteVar(completion, varskips); if (cmd) - { - memset(inputlines[inputline]+1, 0, CON_MAXPROMPTCHARS-1); - strcpy(inputlines[inputline]+1, cmd); - input_cx = strlen(cmd) + 1; - inputlines[inputline][input_cx] = ' '; - input_cx++; - inputlines[inputline][input_cx] = 0; - } + CON_InputSetString(va("%s ", cmd)); else { if (comskips > 0) @@ -824,38 +914,80 @@ boolean CON_Responder(event_t *ev) return true; } + if (key == KEY_LEFTARROW) + { + if (input_cur != 0) + --input_cur; + if (!shiftdown) + input_sel = input_cur; + return true; + } + else if (key == KEY_RIGHTARROW) + { + if (input_cur < input_len) + ++input_cur; + if (!shiftdown) + input_sel = input_cur; + return true; + } + else if (key == KEY_HOME) + { + input_cur = 0; + if (!shiftdown) + input_sel = input_cur; + return true; + } + else if (key == KEY_END) + { + input_cur = input_len; + if (!shiftdown) + input_sel = input_cur; + return true; + } + // At this point we're messing with input + // Clear completion + completion[0] = 0; // command enter if (key == KEY_ENTER) { - if (input_cx < 2) + if (!input_len) return true; // push the command - COM_BufAddText(inputlines[inputline]+1); + COM_BufAddText(inputlines[inputline]); COM_BufAddText("\n"); - CONS_Printf("%s\n", inputlines[inputline]); + CONS_Printf("\x86""%c""\x80""%s\n", CON_PROMPTCHAR, inputlines[inputline]); inputline = (inputline+1) & 31; inputhist = inputline; - - memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); - inputlines[inputline][0] = CON_PROMPTCHAR; - input_cx = 1; + CON_InputClear(); return true; } - // backspace command prompt - if (key == KEY_BACKSPACE) + // backspace and delete command prompt + if (input_sel != input_cur) { - if (input_cx > 1) + if (key == KEY_BACKSPACE || key == KEY_DEL) { - input_cx--; - inputlines[inputline][input_cx] = 0; + CON_InputDelSelection(); + return true; } + } + else if (key == KEY_BACKSPACE) + { + CON_InputDelChar(); + return true; + } + else if (key == KEY_DEL) + { + if (input_cur == input_len) + return true; + ++input_cur; + CON_InputDelChar(); return true; } @@ -864,18 +996,15 @@ boolean CON_Responder(event_t *ev) { // copy one of the previous inputlines to the current do - { inputhist = (inputhist - 1) & 31; // cycle back - } while (inputhist != inputline && !inputlines[inputhist][1]); + while (inputhist != inputline && !inputlines[inputhist][0]); // stop at the last history input line, which is the // current line + 1 because we cycle through the 32 input lines if (inputhist == inputline) inputhist = (inputline + 1) & 31; - M_Memcpy(inputlines[inputline], inputlines[inputhist], CON_MAXPROMPTCHARS); - input_cx = strlen(inputlines[inputline]); - + CON_InputSetString(inputlines[inputhist]); return true; } @@ -885,23 +1014,14 @@ boolean CON_Responder(event_t *ev) if (inputhist == inputline) return true; do - { inputhist = (inputhist + 1) & 31; - } while (inputhist != inputline && !inputlines[inputhist][1]); - - memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + while (inputhist != inputline && !inputlines[inputhist][0]); // back to currentline if (inputhist == inputline) - { - inputlines[inputline][0] = CON_PROMPTCHAR; - input_cx = 1; - } + CON_InputClear(); else - { - strcpy(inputlines[inputline], inputlines[inputhist]); - input_cx = strlen(inputlines[inputline]); - } + CON_InputSetString(inputlines[inputhist]); return true; } @@ -926,15 +1046,12 @@ boolean CON_Responder(event_t *ev) return false; // add key to cmd line here - if (input_cx < CON_MAXPROMPTCHARS) - { - if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers - key = key + 'a' - 'A'; + if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers + key = key + 'a' - 'A'; - inputlines[inputline][input_cx] = (char)key; - inputlines[inputline][input_cx + 1] = 0; - input_cx++; - } + if (input_sel != input_cur) + CON_InputDelSelection(); + CON_InputAddChar(key); return true; } @@ -1218,26 +1335,84 @@ void CONS_Error(const char *msg) // static void CON_DrawInput(void) { - char *p; - size_t c; - INT32 x, y; INT32 charwidth = (INT32)con_scalefactor << 3; - - // input line scrolls left if it gets too long - p = inputlines[inputline]; - if (input_cx >= con_width-11) - p += input_cx - (con_width-11) + 1; + const char *p = inputlines[inputline]; + size_t c, clen, cend; + UINT8 lellip = 0, rellip = 0; + INT32 x, y, i; y = con_curlines - 12 * con_scalefactor; + x = charwidth*2; - for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + clen = con_width-12; - // draw the blinking cursor - // - x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth); - if (con_tick < 4) - V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + if (input_len <= clen) + { + c = 0; + clen = input_len; + } + else // input line scrolls left if it gets too long + { + clen -= 2; // There will always be some extra truncation -- but where is what we'll find out + + if (input_cur <= clen/2) + { + // Close enough to right edge to show all + c = 0; + // Always will truncate right side from this position, so always draw right ellipsis + rellip = 1; + } + else + { + // Cursor in the middle (or right side) of input + // Move over for the ellipsis + c = input_cur - (clen/2) + 2; + x += charwidth*2; + lellip = 1; + + if (c + clen >= input_len) + { + // Cursor in the right side of input + // We were too far over, so move back + c = input_len - clen; + } + else + { + // Cursor in the middle -- ellipses on both sides + clen -= 2; + rellip = 1; + } + } + } + + if (lellip) + { + for (i = 0, x -= charwidth*3; i < 3; ++i, x += charwidth) + V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); + } + else + V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); + + for (cend = c + clen; c < cend; ++c, x += charwidth) + { + if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c)) + { + V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 107 | V_NOSCALESTART); + V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value); + } + else + V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + + if (c == input_cur && con_tick >= 4) + V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + } + if (cend == input_cur && con_tick >= 4) + V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + if (rellip) + { + for (i = 0; i < 3; ++i, x += charwidth) + V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); + } } // draw the last lines of console text to the top of the screen diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 8c4331aa..71ee3f79 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -260,18 +260,6 @@ 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 @@ -2659,86 +2647,30 @@ 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 + char storage[256]; + if (size > 255) + size = 255; + memcpy(storage, data, size); + storage[size] = 0; -#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 + if (SDL_SetClipboardText(storage)) + return 0; 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 + static char clipboard_modified[256]; + char *clipboard_contents, *i = clipboard_modified; -#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 + if (!SDL_HasClipboardText()) 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 + clipboard_contents = SDL_GetClipboardText(); + memcpy(clipboard_modified, clipboard_contents, 255); + SDL_free(clipboard_contents); + clipboard_modified[255] = 0; while (*i) { @@ -2753,13 +2685,7 @@ const char *I_ClipboardPaste(void) *i = '?'; // Nonprintable chars become question marks ++i; } - - return (const char *)&clipboard_contents; -#else - return NULL; -#endif - -#endif // FAKE_CLIPBOARD + return (const char *)&clipboard_modified; } /** \brief The isWadPathOk function diff --git a/src/v_video.c b/src/v_video.c index 43e3f018..f6a966e6 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -774,43 +774,51 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (!screens[0]) return; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); - return; - } - - dest = screens[0] + y*dupy*vid.width + x*dupx; - deststop = screens[0] + vid.rowbytes * vid.height; - - if (w == BASEVIDWIDTH) - w = vid.width; - else - w *= dupx; - if (h == BASEVIDHEIGHT) - h = vid.height; - else - h *= dupy; - - if (x && y && x + w < vid.width && y + h < vid.height) + if (c & V_NOSCALESTART) { - // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (c & V_SNAPTORIGHT) - dest += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(c & V_SNAPTOLEFT)) - dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + dest = screens[0] + y*vid.width + x; + deststop = screens[0] + vid.rowbytes * vid.height; + } + else + { + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { // Clear the entire screen, from dest to deststop. Yes, this really works. + memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + return; } - if (vid.height != BASEVIDHEIGHT * dupy) + + dest = screens[0] + y*dupy*vid.width + x*dupx; + deststop = screens[0] + vid.rowbytes * vid.height; + + if (w == BASEVIDWIDTH) + w = vid.width; + else + w *= dupx; + if (h == BASEVIDHEIGHT) + h = vid.height; + else + h *= dupy; + + if (x && y && x + w < vid.width && y + h < vid.height) { - // same thing here - if (c & V_SNAPTOBOTTOM) - dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(c & V_SNAPTOTOP)) - dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + dest += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; + else if (!(c & V_SNAPTOTOP)) + dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; + } } } From 010c52aed2ad0e4ee0f38a1fcfa42b6a6bf671f0 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Thu, 3 Nov 2016 19:36:43 -0700 Subject: [PATCH 7/8] show highlight BG over ellipses if highlight extends offscreen + bug fixes --- src/console.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/console.c b/src/console.c index ea5999c0..e0619097 100644 --- a/src/console.c +++ b/src/console.c @@ -662,7 +662,7 @@ static inline void CON_InputDelSelection(void) len = (end - start); if (end != input_len) - memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-input_cur); + memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-end); memset(&inputlines[inputline][input_len - len], 0, len); input_len -= len; @@ -720,12 +720,6 @@ 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) { @@ -759,9 +753,14 @@ boolean CON_Responder(event_t *ev) consoletoggle = true; return true; } - } + // Always eat ctrl/shift/alt if console open, 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; + // ctrl modifier -- changes behavior, adds shortcuts if (ctrldown) { @@ -1344,7 +1343,7 @@ static void CON_DrawInput(void) y = con_curlines - 12 * con_scalefactor; x = charwidth*2; - clen = con_width-12; + clen = con_width-13; if (input_len <= clen) { @@ -1387,7 +1386,10 @@ static void CON_DrawInput(void) if (lellip) { - for (i = 0, x -= charwidth*3; i < 3; ++i, x += charwidth) + x -= charwidth*3; + if (input_sel < c) + V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART); + for (i = 0; i < 3; ++i, x += charwidth) V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); } else @@ -1410,6 +1412,8 @@ static void CON_DrawInput(void) V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); if (rellip) { + if (input_sel > cend) + V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 107 | V_NOSCALESTART); for (i = 0; i < 3; ++i, x += charwidth) V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); } From 55400a262d3cb0f29cdb51d1c4d2a7da93a91da8 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Fri, 4 Nov 2016 02:02:26 -0700 Subject: [PATCH 8/8] go fuck yourself stupid compiler ...your guesses should not be treated as errors. --- src/console.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/console.c b/src/console.c index e0619097..70f8ab6f 100644 --- a/src/console.c +++ b/src/console.c @@ -621,20 +621,20 @@ void CON_Ticker(void) // Necessary due to moving cursor // -static inline void CON_InputClear(void) +static void CON_InputClear(void) { memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); input_cur = input_sel = input_len = 0; } -static inline void CON_InputSetString(const char *c) +static void CON_InputSetString(const char *c) { memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); strcpy(inputlines[inputline], c); input_cur = input_sel = input_len = strlen(c); } -static inline void CON_InputAddString(const char *c) +static void CON_InputAddString(const char *c) { size_t csize = strlen(c); if (input_len + csize > CON_MAXPROMPTCHARS-1) @@ -646,7 +646,7 @@ static inline void CON_InputAddString(const char *c) input_sel = (input_cur += csize); } -static inline void CON_InputDelSelection(void) +static void CON_InputDelSelection(void) { size_t start, end, len; if (input_cur > input_sel) @@ -669,7 +669,7 @@ static inline void CON_InputDelSelection(void) input_sel = input_cur = start; } -static inline void CON_InputAddChar(char c) +static void CON_InputAddChar(char c) { if (input_len >= CON_MAXPROMPTCHARS-1) return; @@ -680,7 +680,7 @@ static inline void CON_InputAddChar(char c) input_sel = input_cur; } -static inline void CON_InputDelChar(void) +static void CON_InputDelChar(void) { if (!input_cur) return;