diff --git a/src/console.c b/src/console.c index 874fc2a4f288eb261a367efd68c488dcd770fb72..69160c24004ca45f1c561d6b205f3ffc1a5a71e5 100644 --- a/src/console.c +++ b/src/console.c @@ -922,8 +922,6 @@ static void CON_InputDelChar(void) // boolean CON_Responder(event_t *ev) { - static UINT8 consdown = false; // console is treated differently due to rare usage - // sequential completions a la 4dos static char completioncmd[80 + sizeof("find ")] = "find "; static char *completion = &completioncmd[sizeof("find ")-1]; @@ -943,32 +941,28 @@ boolean CON_Responder(event_t *ev) // let go keyup events, don't eat them if (ev->type != ev_keydown && ev->type != ev_text && ev->type != ev_console) { - if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1]) - consdown = false; return false; } key = ev->key; // check for console toggle key - if (ev->type != ev_console) + if (ev->type == ev_keydown) { if (modeattacking || metalrecording || marathonmode) return false; - if (ev->type == ev_keydown && ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown)) + if ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown) { - if (consdown) // ignore repeat - return true; + I_SetTextInputMode(con_destlines == 0); // inverse, since this is changed next tic. consoletoggle = true; - consdown = true; return true; } // check other keys only if console prompt is active if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!! { - if (ev->type == ev_keydown && !menuactive && bindtable[key]) + if (!menuactive && bindtable[key]) { COM_BufAddText(bindtable[key]); COM_BufAddText("\n"); @@ -980,14 +974,14 @@ boolean CON_Responder(event_t *ev) // escape key toggle off console if (key == KEY_ESCAPE) { + I_SetTextInputMode(false); consoletoggle = true; return true; } } - - if (ev->type == ev_text) + else if (ev->type == ev_text) { - if (!consoletoggle) + if (!consoletoggle && consoleready) CON_InputAddChar(key); return true; } @@ -1036,7 +1030,7 @@ boolean CON_Responder(event_t *ev) } else if (key == KEY_BACKSPACE) { - if (ctrldown) + if (ctrldown && input_cur != 0) { input_sel = M_JumpWordReverse(inputlines[inputline], input_cur); CON_InputDelSelection(); @@ -1094,7 +1088,9 @@ boolean CON_Responder(event_t *ev) if (key == 'x' || key == 'X') { - if (input_sel > input_cur) + if (input_sel == input_cur) // Don't replace the clipboard without a text selection + return true; + else 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); @@ -1104,7 +1100,9 @@ boolean CON_Responder(event_t *ev) } else if (key == 'c' || key == 'C') { - if (input_sel > input_cur) + if (input_sel == input_cur) // Don't replace the clipboard without a text selection + return true; + else 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); diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 858dfaf20234cb6898ffe008bce3c3f76e8b950b..413b366b865c035a08ece29008c30004ea58666e 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1585,5 +1585,15 @@ void I_GetCursorPosition(INT32 *x, INT32 *y) (void)y; } +void I_SetTextInputMode(boolean active) +{ + (void)active; +} + +boolean I_GetTextInputMode(void) +{ + return false; +} + #include "../sdl/dosstr.c" diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index ecabe3576d3f15b06513315a945562076587aff5..99bfa9f363ca04c9281b17b0cffeda5cc4314586 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -211,5 +211,15 @@ const char *I_GetSysName(void) return NULL; } +void I_SetTextInputMode(boolean active) +{ + (void)active; +} + +boolean I_GetTextInputMode(void) +{ + return false; +} + #include "../sdl/dosstr.c" diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 4e2f3d492974c0027c3b343a075018dc29682d33..16c59d9cf82bb9b92067f3c792a5f29292e7cdfd 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -999,6 +999,7 @@ static void HU_sendChatMessage(void) void HU_clearChatChars(void) { memset(w_chat, '\0', sizeof(w_chat)); + I_SetTextInputMode(false); chat_on = false; c_input = 0; @@ -1048,6 +1049,7 @@ boolean HU_Responder(event_t *ev) if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1]) && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. { + I_SetTextInputMode(true); chat_on = true; chat_on_first_event = false; w_chat[0] = 0; @@ -1059,6 +1061,7 @@ boolean HU_Responder(event_t *ev) if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1]) && netgame && !OLD_MUTE) { + I_SetTextInputMode(true); chat_on = true; chat_on_first_event = false; w_chat[0] = 0; @@ -1133,6 +1136,7 @@ boolean HU_Responder(event_t *ev) if (!CHAT_MUTE) HU_sendChatMessage(); + I_SetTextInputMode(false); chat_on = false; c_input = 0; // reset input cursor chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) @@ -1143,6 +1147,7 @@ boolean HU_Responder(event_t *ev) || c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1]) && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. { + I_SetTextInputMode(false); chat_on = false; c_input = 0; // reset input cursor I_UpdateMouseGrab(); diff --git a/src/i_system.h b/src/i_system.h index 3f0e05d127fa4ed5ce9aa8fbe89ff109773851f4..f4d169113c50b0ae5e2c1aca53b4d04f128658f4 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -339,4 +339,12 @@ void I_SetMouseGrab(boolean grab); */ const char *I_GetSysName(void); +/** \brief Sets text input mode. When enabled, keyboard inputs will respect dead keys. + */ +void I_SetTextInputMode(boolean active); + +/** \brief Retrieves current text input mode. + */ +boolean I_GetTextInputMode(void); + #endif diff --git a/src/m_menu.c b/src/m_menu.c index 50011347550c32622238ef02a6d538be62bbb31f..4d8ee17e8a50c582b910a1748d741997515d9457 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2102,6 +2102,12 @@ menu_t OP_PlaystyleDef = { 0, 0, 0, NULL }; +static void M_UpdateItemOn(void) +{ + I_SetTextInputMode((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || + (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER); +} + static void M_VideoOptions(INT32 choice) { (void)choice; @@ -2329,6 +2335,7 @@ void Nextmap_OnChange(void) { currentMenu->lastOn = itemOn; itemOn = nastart; + M_UpdateItemOn(); } } else if (currentMenu == &SP_TimeAttackDef) @@ -2378,6 +2385,7 @@ void Nextmap_OnChange(void) { currentMenu->lastOn = itemOn; itemOn = tastart; + M_UpdateItemOn(); } if (mapheaderinfo[cv_nextmap.value-1] && mapheaderinfo[cv_nextmap.value-1]->forcecharacter[0] != '\0') @@ -3128,6 +3136,7 @@ static void M_NextOpt(void) else itemOn++; } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); + M_UpdateItemOn(); } static void M_PrevOpt(void) @@ -3140,6 +3149,7 @@ static void M_PrevOpt(void) else itemOn--; } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); + M_UpdateItemOn(); } // lock out further input in a tic when important buttons are pressed @@ -3651,12 +3661,14 @@ void M_StartControlPanel(void) currentMenu = &MainDef; itemOn = singleplr; + M_UpdateItemOn(); } else if (modeattacking) { currentMenu = &MAPauseDef; MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); itemOn = mapause_continue; + M_UpdateItemOn(); } else if (!(netgame || multiplayer)) // Single Player { @@ -3703,6 +3715,7 @@ void M_StartControlPanel(void) currentMenu = &SPauseDef; itemOn = spause_continue; + M_UpdateItemOn(); } else // multiplayer { @@ -3744,6 +3757,7 @@ void M_StartControlPanel(void) currentMenu = &MPauseDef; itemOn = mpause_continue; + M_UpdateItemOn(); } CON_ToggleOff(); // move away console @@ -3837,6 +3851,7 @@ void M_SetupNextMenu(menu_t *menudef) } } } + M_UpdateItemOn(); hidetitlemap = false; } @@ -6109,6 +6124,7 @@ void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtyp currentMenu = &MessageDef; itemOn = 0; + M_UpdateItemOn(); } static void M_DrawMessageMenu(void) @@ -6183,6 +6199,7 @@ static void M_HandleImageDef(INT32 choice) if (itemOn >= (INT16)(currentMenu->numitems-1)) itemOn = 0; else itemOn++; + M_UpdateItemOn(); break; case KEY_LEFTARROW: @@ -6193,6 +6210,7 @@ static void M_HandleImageDef(INT32 choice) if (!itemOn) itemOn = currentMenu->numitems - 1; else itemOn--; + M_UpdateItemOn(); break; case KEY_ESCAPE: @@ -7389,6 +7407,7 @@ static void M_EmblemHints(INT32 choice) SR_EmblemHintDef.prevMenu = currentMenu; M_SetupNextMenu(&SR_EmblemHintDef); itemOn = 2; // always start on back. + M_UpdateItemOn(); } static void M_DrawEmblemHints(void) @@ -10050,6 +10069,7 @@ static void M_TimeAttack(INT32 choice) Nextmap_OnChange(); itemOn = tastart; // "Start" is selected. + M_UpdateItemOn(); } // Drawing function for Nights Attack @@ -10288,6 +10308,7 @@ static void M_NightsAttack(INT32 choice) Nextmap_OnChange(); itemOn = nastart; // "Start" is selected. + M_UpdateItemOn(); } // Player has selected the "START" from the nights attack screen @@ -10607,6 +10628,7 @@ static void M_ModeAttackEndGame(INT32 choice) break; } itemOn = currentMenu->lastOn; + M_UpdateItemOn(); G_SetGamestate(GS_TIMEATTACK); modeattacking = ATTACKING_NONE; M_ChangeMenuMusic("_title", true); @@ -10688,6 +10710,7 @@ static void M_Marathon(INT32 choice) titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_MarathonDef); itemOn = marathonstart; // "Start" is selected. + M_UpdateItemOn(); recatkdrawtimer = (50-8) * FRACUNIT; char_scroll = 0; } @@ -11401,6 +11424,7 @@ static void M_ConnectMenu(INT32 choice) else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; + M_UpdateItemOn(); M_Refresh(0); } @@ -11660,6 +11684,7 @@ static void M_StartServerMenu(INT32 choice) Newgametype_OnChange(); M_SetupNextMenu(&MP_ServerDef); itemOn = 1; + M_UpdateItemOn(); } // ============== @@ -11842,15 +11867,21 @@ static void M_HandleConnectIP(INT32 choice) case KEY_INS: case 'c': case 'C': // ctrl+c, ctrl+insert, copying - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + } break; case 'x': case 'X': // ctrl+x, cutting - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[0] = 0; + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; + } break; default: // otherwise do nothing @@ -11874,9 +11905,12 @@ static void M_HandleConnectIP(INT32 choice) break; } case KEY_DEL: // shift+delete, cutting - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[0] = 0; + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; + } break; default: // otherwise do nothing. break; @@ -13071,7 +13105,10 @@ static void M_SetupScreenshotMenu(void) { item->status = IT_GRAYEDOUT; if ((currentMenu == &OP_ScreenshotOptionsDef) && (itemOn == op_screenshot_colorprofile)) // Can't select that + { itemOn = op_screenshot_storagelocation; + M_UpdateItemOn(); + } } else #endif diff --git a/src/m_misc.c b/src/m_misc.c index 55c5485a149a2b2c43e48fab973c5ad898091036..a60bbea98d2e2b47cf3fea0dae652d26b6aa4763 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2208,6 +2208,8 @@ int M_JumpWordReverse(const char *line, int offset) { int (*is)(int); int c; + if (offset == 0) // Don't let "--offset" later result in a negative value + return 0; c = line[--offset]; if (isspace(c)) is = isspace; diff --git a/src/p_spec.c b/src/p_spec.c index 805817fb033c465b33059c24fbefb52432173444..78cf460632970ac108512f29f1fd2111aea5f462 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3684,7 +3684,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 466: // Set level failure state { - if (line->args[1]) + if (line->args[0]) { stagefailed = false; CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); diff --git a/src/r_textures.c b/src/r_textures.c index 59cc114139c5abb24df0f47fa0dddd0e70ec8d72..5d3fe24db2c942647d514a92ad42a759d0b3c9f4 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -821,8 +821,8 @@ Rloadflats (INT32 i, INT32 w) UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); if (Picture_PNGDimensions((UINT8 *)flatlump, &texw, &texh, NULL, NULL, lumplength)) { - width = (INT16)width; - height = (INT16)height; + width = (INT16)texw; + height = (INT16)texh; } else { @@ -1068,6 +1068,98 @@ void R_LoadTexturesPwad(UINT16 wadnum) R_FinishLoadingTextures(newtextures); } +static lumpnum_t W_GetTexPatchLumpNum(const char *name) +{ + // Flats as a texture patch crashes horribly, and flats + // can share the same name as textures. + + // But even if they worked, we want to prioritize: + // Patches -> Textures -> anything else + + enum + { + USE_PATCHES, + USE_TEXTURES, + USE__MAX, + }; + + lumpnum_t lump = LUMPERROR; + INT32 lump_type_it; + + + for (lump_type_it = 0; lump_type_it < USE__MAX; lump_type_it++) + { + INT32 i; + + for (i = numwadfiles - 1; i >= 0; i--) // Scan wad files backwards so patched lumps take precedent + { + lumpnum_t start = LUMPERROR; + lumpnum_t end = LUMPERROR; + + switch (wadfiles[i]->type) + { + case RET_WAD: + if (lump_type_it == USE_PATCHES) + { + if ((start = W_CheckNumForMarkerStartPwad("P_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("P_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + else if (lump_type_it == USE_TEXTURES) + { + if ((start = W_CheckNumForMarkerStartPwad("TX_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + break; + case RET_PK3: + case RET_FOLDER: + if (lump_type_it == USE_PATCHES) + { + if ((start = W_CheckNumForFolderStartPK3("Patches/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Patches/", i, start)) == INT16_MAX) + continue; + } + else if (lump_type_it == USE_TEXTURES) + { + if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) + continue; + } + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + + if (lump != LUMPERROR) + { + break; + } + } + + if (lump == LUMPERROR) + { + // Use whatever else you can find. + return W_GetNumForName(name); + } + + return lump; +} + static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { char *texturesToken; @@ -1240,13 +1332,13 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) if (actuallyLoadPatch == true) { // Check lump exists - patchLumpNum = W_GetNumForName(patchName); + patchLumpNum = W_GetTexPatchLumpNum(patchName); // If so, allocate memory for texpatch_t and fill 'er up resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL); resultPatch->originx = patchXPos; resultPatch->originy = patchYPos; - resultPatch->lump = patchLumpNum & 65535; - resultPatch->wad = patchLumpNum>>16; + resultPatch->lump = LUMPNUM(patchLumpNum); + resultPatch->wad = WADFILENUM(patchLumpNum); resultPatch->flip = flip; resultPatch->alpha = alpha; resultPatch->style = style; diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index f5fe9fb041b9f02057955afe072815e709b19dc3..b2177e563120fc76cf726353e5cad841e45b1762 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -186,6 +186,9 @@ int main(int argc, char **argv) #endif #endif + // disable text input right off the bat, since we don't need it at the start. + I_SetTextInputMode(false); + #ifdef LOGMESSAGES if (!M_CheckParm("-nolog")) InitLogging(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 2d051888dc1f26de5357b8689eced942ab38da59..115b900f5b575ce376a816dc9093c38202724e86 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -3275,4 +3275,18 @@ const char *I_GetSysName(void) return SDL_GetPlatform(); } + +void I_SetTextInputMode(boolean active) +{ + if (active) + SDL_StartTextInput(); + else + SDL_StopTextInput(); +} + +boolean I_GetTextInputMode(void) +{ + return SDL_IsTextInputActive(); +} + #endif