From 9f87841936a957c4c7552089654cfdd2bd22cc15 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 8 Sep 2016 22:55:11 +0100 Subject: [PATCH 01/32] Fix bottom of FOF with a pusher special not accounting for slopes --- src/p_spec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 30b08ebb1..92f62af4d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7428,7 +7428,7 @@ void T_Pusher(pusher_t *p) } else { - if (top < thing->z || referrer->floorheight > (thing->z + (thing->height >> 1))) + if (top < thing->z || bottom > (thing->z + (thing->height >> 1))) continue; if (thing->z + thing->height > top) touching = true; From c977d174166142a47b5aa7a2d32f57a2a5412702 Mon Sep 17 00:00:00 2001 From: ilag11111 Date: Sun, 11 Sep 2016 09:41:18 -0700 Subject: [PATCH 02/32] Prevent truncation when resampling sounds with non-multiples of 11250. --- src/sdl/mixer_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 4a46813c1..88bbadd20 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -220,7 +220,7 @@ static Mix_Chunk *ds2chunk(void *stream) break; default: // convert arbitrary hz to 44100. step = 0; - frac = ((UINT32)freq << FRACBITS) / 44100; + frac = ((UINT32)freq << FRACBITS) / 44100 + 1; //Add 1 to counter truncation. while (i < samples) { o = (INT16)(*s+0x80)<<8; // changed signedness and shift up to 16 bits From b8345aaf27ab32dd7cee8960143fc63bd666f5c2 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 22 Sep 2016 00:13:34 +0100 Subject: [PATCH 03/32] Solid objects are now no longer selectively intangible on slopes. HOWEVER, since these changes to PIT_CheckThing do raise questions about whether there may be unintended side effects here. As a result, I may remake this for internal only if necessary. --- src/p_map.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index c4616db48..13496bef9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -985,7 +985,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - topz = thing->z - FixedMul(FRACUNIT, thing->scale); + topz = thing->z - thing->scale; // block only when jumping not high enough, // (dont climb max. 24units while already in air) @@ -996,7 +996,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->flags & MF_SPRING) ; - else if (topz < tmceilingz && tmthing->z+tmthing->height <= thing->z+thing->height) + else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; #ifdef ESLOPE @@ -1022,7 +1022,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - topz = thing->z + thing->height + FixedMul(FRACUNIT, thing->scale); + topz = thing->z + thing->height + thing->scale; // block only when jumping not high enough, // (dont climb max. 24units while already in air) @@ -1032,7 +1032,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->flags & MF_SPRING) ; - else if (topz > tmfloorz && tmthing->z >= thing->z) + else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; #ifdef ESLOPE From fa16abf7ae8cf0468bb3237047687eefca997e6e Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 22 Sep 2016 11:15:08 +0100 Subject: [PATCH 04/32] Fixed the thing where if you thok into a solid object you spin really fast in the air without moving OR losing your momentum. --- src/p_map.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 13496bef9..a3f34aa8a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -989,12 +989,18 @@ static boolean PIT_CheckThing(mobj_t *thing) // block only when jumping not high enough, // (dont climb max. 24units while already in air) - // if not in air, let P_TryMove() decide if it's not too high + // since return false doesn't handle momentum properly, + // we lie to P_TryMove() so it's always too high if (tmthing->player && tmthing->z + tmthing->height > topz && tmthing->z + tmthing->height < tmthing->ceilingz) - return false; // block while in air - - if (thing->flags & MF_SPRING) + { + tmceilingz = INT32_MIN; // block while in air +#ifdef ESLOPE + tmceilingslope = NULL; +#endif + tmfloorthing = thing; // needed for side collision + } + else if (thing->flags & MF_SPRING) ; else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { @@ -1026,11 +1032,18 @@ static boolean PIT_CheckThing(mobj_t *thing) // block only when jumping not high enough, // (dont climb max. 24units while already in air) - // if not in air, let P_TryMove() decide if it's not too high - if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) - return false; // block while in air - - if (thing->flags & MF_SPRING) + // since return false doesn't handle momentum properly, + // we lie to P_TryMove() so it's always too high + if (tmthing->player && tmthing->z < topz + && tmthing->z > tmthing->floorz) + { + tmfloorz = INT32_MAX; // block while in air +#ifdef ESLOPE + tmfloorslope = NULL; +#endif + tmfloorthing = thing; // needed for side collision + } + else if (thing->flags & MF_SPRING) ; else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { From 0568712a5e3bee3335e5e0f9256c1ad07f78d25a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 22 Sep 2016 12:01:13 +0100 Subject: [PATCH 05/32] Prevent overflow when attempting to calculate the space between floor and ceiling. (I didn't notice any bugs as a result of the previous behvaiour, but you never know.) --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index a3f34aa8a..8b8c6c07d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -994,7 +994,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player && tmthing->z + tmthing->height > topz && tmthing->z + tmthing->height < tmthing->ceilingz) { - tmceilingz = INT32_MIN; // block while in air + tmfloorz = tmceilingz = INT32_MIN; // block while in air #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1037,7 +1037,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) { - tmfloorz = INT32_MAX; // block while in air + tmfloorz = tmceilingz = INT32_MAX; // block while in air #ifdef ESLOPE tmfloorslope = NULL; #endif From 394ed30f4436dd3d9a2a8bd118a60175f350527b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 22 Sep 2016 21:08:36 +0100 Subject: [PATCH 06/32] Fixed the problem with the reverseplatform_clipping branch that caused springs to fall through platforms, as tested by Wolfs in TD. --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5e5961d41..82326f04c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2017,13 +2017,13 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); if (topheight > mo->floorz && abs(delta1) < abs(delta2) && !(rover->flags & FF_REVERSEPLATFORM) - && ((P_MobjFlip(mo)*mo->momz > 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) + && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) { mo->floorz = topheight; } if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) - && ((P_MobjFlip(mo)*mo->momz > 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below + && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below { mo->ceilingz = bottomheight; } From 8ad72232bea1b1b093fe9a36ca189e1c90db5127 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 22 Sep 2016 21:15:12 +0100 Subject: [PATCH 07/32] Helpful explanatory comments to assauge MI's fears. --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 8b8c6c07d..6a555953e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -985,7 +985,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - topz = thing->z - thing->scale; + topz = thing->z - thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways // block only when jumping not high enough, // (dont climb max. 24units while already in air) @@ -1028,7 +1028,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - topz = thing->z + thing->height + thing->scale; + topz = thing->z + thing->height + thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways // block only when jumping not high enough, // (dont climb max. 24units while already in air) From 8881a413f3c3a652675e4f451ebb849f17a8ac10 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 27 Sep 2016 17:17:23 +0100 Subject: [PATCH 08/32] Fixed that really annoying bug where you disappear when spindashing on top of a FOF whilst wearing a multi-layer shield. (the problem was that MT_OVERLAY's default radius and height were never getting changed from 1*FRACUNIT, and that meant that when you spindashed, the game considered it completely below the surface of the flat you were standing on. Since you're not usually clipped on flats that don't belong to FOFs, we didn't notice this issue sooner.) --- src/p_mobj.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 5e5961d41..b35b72867 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5930,6 +5930,8 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) P_UnsetThingPosition(thing); thing->x = thing->target->x; thing->y = thing->target->y; + thing->radius = thing->target->radius; + thing->height = thing->target->height; if (thing->eflags & MFE_VERTICALFLIP) thing->z = thing->target->z + thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) - FixedMul(2*FRACUNIT, thing->target->scale); else @@ -6048,6 +6050,8 @@ void P_RunOverlays(void) P_UnsetThingPosition(mo); mo->x = destx; mo->y = desty; + mo->radius = mo->target->radius; + mo->height = mo->target->height; if (mo->eflags & MFE_VERTICALFLIP) mo->z = (mo->target->z + mo->target->height - mo->height) - zoffs; else From e1baf02b7a3f2dd27ccf8bcf6089c5d765dfe756 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 18 Oct 2016 22:07:20 +0100 Subject: [PATCH 09/32] Lua now errors if negative scales are used with v.drawScaled --- src/lua_hudlib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 7aadd9c0e..60cbbe501 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -369,6 +369,8 @@ static int libd_drawScaled(lua_State *L) x = luaL_checkinteger(L, 1); y = luaL_checkinteger(L, 2); scale = luaL_checkinteger(L, 3); + if (scale < 0) + return luaL_error(L, "negative scale"); patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) From aa3e52f05e5b044e4f9a6f710027fae020b625c7 Mon Sep 17 00:00:00 2001 From: Yukita Mayako Date: Wed, 19 Oct 2016 03:17:36 -0400 Subject: [PATCH 10/32] Fix ANIMDEFS parsing to allow overwrite. ANIMATED and ANIMDEFS are now processed in reverse order, and duplicate definitions in ANIMDEFS are dropped. --- src/p_spec.c | 111 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 45 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index cb928eeef..b04c55881 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -221,8 +221,8 @@ static animdef_t harddefs[] = static animdef_t *animdefs = NULL; // A prototype; here instead of p_spec.h, so they're "private" -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i); -void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i); +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); +void P_ParseAnimationDefintion(SINT8 istexture); /** Sets up texture and flat animations. * @@ -232,24 +232,21 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i); * Issues an error if any animation cycles are invalid. * * \sa P_FindAnimatedFlat, P_SetupLevelFlatAnims - * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs) + * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_) */ void P_InitPicAnims(void) { // Init animation - INT32 i; // Position in the animdefs array INT32 w; // WAD - UINT8 *wadAnimdefs; // not to be confused with animdefs, the combined total of every ANIMATED lump in every WAD, or ANIMDEFS, the ZDoom lump I intend to implement later + UINT8 *animatedLump; UINT8 *currentPos; + size_t i; + + I_Assert(animdefs == NULL); if (W_CheckNumForName("ANIMATED") != LUMPERROR || W_CheckNumForName("ANIMDEFS") != LUMPERROR) { - if (animdefs) - { - Z_Free(animdefs); - animdefs = NULL; - } - for (w = 0, i = 0, maxanims = 0; w < numwadfiles; w++) + for (w = numwadfiles-1, maxanims = 0; w >= 0; w--) { UINT16 animatedLumpNum; UINT16 animdefsLumpNum; @@ -258,20 +255,20 @@ void P_InitPicAnims(void) animatedLumpNum = W_CheckNumForNamePwad("ANIMATED", w, 0); if (animatedLumpNum != INT16_MAX) { - wadAnimdefs = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC); + animatedLump = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC); // Get the number of animations in the file - for (currentPos = wadAnimdefs; *currentPos != UINT8_MAX; maxanims++, currentPos+=23); + i = maxanims; + for (currentPos = animatedLump; *currentPos != UINT8_MAX; maxanims++, currentPos+=23); // Resize animdefs (or if it hasn't been created, create it) animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); // Sanity check it - if (!animdefs) { + if (!animdefs) I_Error("Not enough free memory for ANIMATED data"); - } // Populate the new array - for (currentPos = wadAnimdefs; *currentPos != UINT8_MAX; i++, currentPos+=23) + for (currentPos = animatedLump; *currentPos != UINT8_MAX; i++, currentPos+=23) { M_Memcpy(&(animdefs[i].istexture), currentPos, 1); // istexture, 1 byte M_Memcpy(animdefs[i].endname, (currentPos + 1), 9); // endname, 9 bytes @@ -279,15 +276,13 @@ void P_InitPicAnims(void) M_Memcpy(&(animdefs[i].speed), (currentPos + 19), 4); // speed, 4 bytes } - Z_Free(wadAnimdefs); + Z_Free(animatedLump); } // Now find ANIMDEFS animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); if (animdefsLumpNum != INT16_MAX) - { - P_ParseANIMDEFSLump(w, animdefsLumpNum, &i); - } + P_ParseANIMDEFSLump(w, animdefsLumpNum); } // Define the last one animdefs[maxanims].istexture = -1; @@ -347,16 +342,20 @@ void P_InitPicAnims(void) lastanim->istexture = -1; R_ClearTextureNumCache(false); + // Clear animdefs now that we're done with it. + // We'll only be using anims from now on. if (animdefs != harddefs) - Z_ChangeTag(animdefs, PU_CACHE); + Z_Free(animdefs); + animdefs = NULL; } -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i) +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) { char *animdefsLump; size_t animdefsLumpLength; char *animdefsText; char *animdefsToken; + char *p; // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll // need to make a space of memory where I can ensure that it will terminate @@ -376,18 +375,19 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i) Z_Free(animdefsLump); // Now, let's start parsing this thing - animdefsToken = M_GetToken(animdefsText); + p = animdefsText; + animdefsToken = M_GetToken(p); while (animdefsToken != NULL) { if (stricmp(animdefsToken, "TEXTURE") == 0) { Z_Free(animdefsToken); - P_ParseAnimationDefintion(1, i); + P_ParseAnimationDefintion(1); } else if (stricmp(animdefsToken, "FLAT") == 0) { Z_Free(animdefsToken); - P_ParseAnimationDefintion(0, i); + P_ParseAnimationDefintion(0); } else if (stricmp(animdefsToken, "OSCILLATE") == 0) { @@ -398,23 +398,22 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, INT32 *i) { I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); } - animdefsToken = M_GetToken(NULL); + // parse next line + while (*p != '\0' && *p != '\n') ++p; + if (*p == '\n') ++p; + animdefsToken = M_GetToken(p); } Z_Free(animdefsToken); Z_Free((void *)animdefsText); } -void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) +void P_ParseAnimationDefintion(SINT8 istexture) { char *animdefsToken; size_t animdefsTokenLength; char *endPos; INT32 animSpeed; - - // Increase the size to make room for the new animation definition - maxanims++; - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); - animdefs[*i].istexture = istexture; + size_t i; // Startname animdefsToken = M_GetToken(NULL); @@ -448,14 +447,39 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) { I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); } - strncpy(animdefs[*i].startname, animdefsToken, 9); + + // Search for existing animdef + for (i = 0; i < maxanims; i++) + if (stricmp(animdefsToken, animdefs[i].startname) == 0) + { + //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); + + // If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found. + // Instead, we're just going to skip parsing the rest of this line entirely. + Z_Free(animdefsToken); + return; + } + + // Not found + if (i == maxanims) + { + // Increase the size to make room for the new animation definition + maxanims++; + animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); + strncpy(animdefs[i].startname, animdefsToken, 9); + } + + // animdefs[i].startname is now set to animdefsToken either way. Z_Free(animdefsToken); + // set texture type + animdefs[i].istexture = istexture; + // "RANGE" animdefsToken = M_GetToken(NULL); if (animdefsToken == NULL) { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[*i].startname); + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); } if (stricmp(animdefsToken, "ALLOWDECALS") == 0) { @@ -470,7 +494,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) } if (stricmp(animdefsToken, "RANGE") != 0) { - I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[*i].startname, animdefsToken); + I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); } Z_Free(animdefsToken); @@ -478,21 +502,21 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) animdefsToken = M_GetToken(NULL); if (animdefsToken == NULL) { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[*i].startname); + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); } animdefsTokenLength = strlen(animdefsToken); if (animdefsTokenLength>8) { I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); } - strncpy(animdefs[*i].endname, animdefsToken, 9); + strncpy(animdefs[i].endname, animdefsToken, 9); Z_Free(animdefsToken); // "TICS" animdefsToken = M_GetToken(NULL); if (animdefsToken == NULL) { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[*i].startname); + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); } if (stricmp(animdefsToken, "RAND") == 0) { @@ -501,7 +525,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) } if (stricmp(animdefsToken, "TICS") != 0) { - I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[*i].startname, animdefsToken); + I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); } Z_Free(animdefsToken); @@ -509,7 +533,7 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) animdefsToken = M_GetToken(NULL); if (animdefsToken == NULL) { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[*i].startname); + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); } endPos = NULL; #ifndef AVOID_ERRNO @@ -523,13 +547,10 @@ void P_ParseAnimationDefintion(SINT8 istexture, INT32 *i) #endif || animSpeed < 0) // Number is not positive { - I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[*i].startname, animdefsToken); + I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); } - animdefs[*i].speed = animSpeed; + animdefs[i].speed = animSpeed; Z_Free(animdefsToken); - - // Increment i before we go, so this doesn't cause issues later - (*i)++; } From cdb841ef544f479cc4f9548e067f98d548987456 Mon Sep 17 00:00:00 2001 From: Yukita Mayako Date: Wed, 19 Oct 2016 03:22:11 -0400 Subject: [PATCH 11/32] Only P_InitPicAnims when wads are loaded. Not in P_SetupLevel. That's just dumb. --- src/p_setup.c | 7 +++---- src/r_data.c | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e56c44c70..f1d3a68c8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2587,10 +2587,6 @@ boolean P_SetupLevel(boolean skipprecip) R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); CON_ReSetupBackColormap(mapheaderinfo[gamemap-1]->palette); - // now part of level loading since in future each level may have - // its own anim texture sequences, switches etc. - P_InitPicAnims(); - // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); @@ -3001,6 +2997,9 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname) else R_FlushTextureCache(); // just reload it from file + // Reload ANIMATED / ANIMDEFS + P_InitPicAnims(); + // Flush and reload HUD graphics ST_UnloadGraphics(); HU_LoadGraphics(); diff --git a/src/r_data.c b/src/r_data.c index cb5cf3591..87b6b1193 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -1499,6 +1499,9 @@ void R_InitData(void) CONS_Printf("R_LoadTextures()...\n"); R_LoadTextures(); + CONS_Printf("P_InitPicAnims()...\n"); + P_InitPicAnims(); + CONS_Printf("R_InitSprites()...\n"); R_InitSpriteLumps(); R_InitSprites(); From 8025ef2f79ec32e71053e7d9eaeb4e7f8c89972a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Oct 2016 16:08:06 +0100 Subject: [PATCH 12/32] At MI's suggestion (shields don't NEED to be tweaked, just overlays) --- src/p_mobj.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index b35b72867..b3842da15 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5930,8 +5930,6 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) P_UnsetThingPosition(thing); thing->x = thing->target->x; thing->y = thing->target->y; - thing->radius = thing->target->radius; - thing->height = thing->target->height; if (thing->eflags & MFE_VERTICALFLIP) thing->z = thing->target->z + thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) - FixedMul(2*FRACUNIT, thing->target->scale); else From ff443251b18e666c8618e61a6fa052ba5ac0abed Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 27 Oct 2016 23:14:22 +0100 Subject: [PATCH 13/32] P_IsPointInSubsector now works in both Software and GL, which means it can be used as the main driver behind support for Knuckles climbing on one-sided walls. Also, the "teleport" devmode command can now gracefully handle coordinates specified outside maps with no/few thok barriers, which previously prevented teleport via the thok barrier bleed's sector floor and ceiling being equal. --- src/m_cheat.c | 2 +- src/p_user.c | 7 +++---- src/r_main.c | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/m_cheat.c b/src/m_cheat.c index 89334596e..3bbaadc5b 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -452,7 +452,7 @@ void Command_RTeleport_f(void) else inty = 0; - ss = R_PointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); + ss = R_IsPointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); diff --git a/src/p_user.c b/src/p_user.c index 3867137ad..f8dc942c0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2280,14 +2280,13 @@ static void P_DoClimbing(player_t *player) fixed_t platy; subsector_t *glidesector; boolean climb = true; - boolean onesided = ((player->lastsidehit != -1 && player->lastlinehit != -1) && !(lines[player->lastlinehit].backsector)); platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy); + glidesector = R_IsPointInSubsector(player->mo->x + platx, player->mo->y + platy); - if (onesided || glidesector->sector != player->mo->subsector->sector) + if (!glidesector || glidesector->sector != player->mo->subsector->sector) { boolean floorclimb = false; boolean thrust = false; @@ -2295,7 +2294,7 @@ static void P_DoClimbing(player_t *player) boolean skyclimber = false; fixed_t floorheight, ceilingheight; // ESLOPE - if (onesided) + if (!glidesector) floorclimb = true; else { diff --git a/src/r_main.c b/src/r_main.c index 498f4dab8..1b4322b48 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -771,7 +771,7 @@ subsector_t *R_PointInSubsector(fixed_t x, fixed_t y) } // -// R_IsPointInSubsector, same as above but returns 0 if not in subsector - this does not work in opengl because of polyvertex_t +// R_IsPointInSubsector, same as above but returns 0 if not in subsector // subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) { @@ -795,7 +795,8 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) ret = &subsectors[nodenum & ~NF_SUBSECTOR]; for (i = 0; i < ret->numlines; i++) - if (R_PointOnSegSide(x, y, &segs[ret->firstline + i])) + //if (R_PointOnSegSide(x, y, &segs[ret->firstline + i])) -- breaks in ogl because polyvertex_t cast over vertex pointers + if (P_PointOnLineSide(x, y, segs[ret->firstline + i].linedef) != segs[ret->firstline + i].side) return 0; return ret; From ab6fd676b5d42b1446ba4a6961abce6093a8422a Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Thu, 27 Oct 2016 23:41:24 +0100 Subject: [PATCH 14/32] YUP, I just fixed OGL Precipitation with this branch too. What the fuck? Squashing ancient bugs, woo. --- src/hardware/hw_main.c | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5251e0b30..a107ecd35 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -45,7 +45,7 @@ #include "hw_md2.h" #define R_FAKEFLOORS -//#define HWPRECIP +#define HWPRECIP #define SORTING //#define POLYSKY @@ -4401,7 +4401,6 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) FOutVector *wv; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; - sector_t *sector; if (!spr->mobj) return; @@ -4455,19 +4454,38 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) //Hurdler: 25/04/2000: now support colormap in hardware mode HWR_GetMappedPatch(gpatch, spr->colormap); - sector = spr->mobj->subsector->sector; - - if (sector->ffloors) + // colormap test { - ffloor_t *caster = sector->lightlist[R_GetPlaneLight(sector, spr->mobj->z, false)].caster; - sector = caster ? §ors[caster->secnum] : sector; - } + sector_t *sector = spr->mobj->subsector->sector; + UINT8 lightlevel = 255; + extracolormap_t *colormap = sector->extra_colormap; - // sprite lighting by modulating the RGB components - if (sector->extra_colormap) - Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight,sector->extra_colormap->rgba,sector->extra_colormap->fadergba, false, false); + if (sector->numlights) + { + INT32 light; + + light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before + + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = *sector->lightlist[light].lightlevel; + + if (sector->lightlist[light].extra_colormap) + colormap = sector->lightlist[light].extra_colormap; + } else - Surf.FlatColor.rgba = HWR_Lighting(spr->sectorlight,NORMALFOG,FADEFOG, false, false); + { + if (!(spr->mobj->frame & FF_FULLBRIGHT)) + lightlevel = sector->lightlevel; + + if (sector->extra_colormap) + colormap = sector->extra_colormap; + } + + if (colormap) + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); + else + Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); + } if (spr->mobj->flags2 & MF2_SHADOW) { @@ -5289,6 +5307,11 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // vis = HWR_NewVisSprite(); vis->x1 = x1; +#if 0 + vis->x2 = x2; +#else + (void)x2; +#endif vis->x2 = tx; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST @@ -5301,7 +5324,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // set top/bottom coords vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset) - gr_viewz; - vis->sectorlight = 0xff; vis->precip = true; } #endif From 2d72b2fac6c2d227b11ea31826d6afd4d30337ac Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 2 Nov 2016 19:31:06 +0100 Subject: [PATCH 15/32] You can now move the cursor in command prompt and chat, using left/right, ctrl+left/right, home/end, and select text with shift --- src/console.c | 213 ++++++++++++++++++++++-- src/hu_stuff.c | 437 +++++++++++++++++++++++++++++++++---------------- src/hu_stuff.h | 1 - 3 files changed, 498 insertions(+), 153 deletions(-) diff --git a/src/console.c b/src/console.c index 025bc1c19..44819fb4f 100644 --- a/src/console.c +++ b/src/console.c @@ -91,11 +91,13 @@ 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 INT32 input_selection; // selection border in current input line, -1 if no selection // protos. static void CON_InputInit(void); static void CON_RecalcSize(void); +static void CON_DeleteSelectedText(void); static void CONS_hudlines_Change(void); static void CON_DrawBackpic(patch_t *pic, INT32 startx, INT32 destwidth); //static void CON_DrawBackpic2(pic_t *pic, INT32 startx, INT32 destwidth); @@ -394,6 +396,7 @@ static void CON_InputInit(void) inputlines[i][0] = CON_PROMPTCHAR; inputline = 0; input_cx = 1; + input_selection = -1; } //====================================================================== @@ -618,6 +621,25 @@ void CON_Ticker(void) } } +// Deletes selected text, assuming there is, and resets selection. +// Also sets the cursor to the correct position. +// +static void CON_DeleteSelectedText(void) +{ + UINT32 i, j; + char *line = inputlines[inputline]; + size_t selstart = min(input_cx, input_selection); + size_t selend = max(input_cx, input_selection); + + for (i = selstart, j = selend; line[j]; ++i, ++j) + line[i] = line[j]; + while (line[i]) + line[i++] = 0; + + input_cx = selstart; + input_selection = -1; +} + // Handles console key input // boolean CON_Responder(event_t *ev) @@ -704,6 +726,9 @@ boolean CON_Responder(event_t *ev) // command completion forward (tab) and backward (shift-tab) if (key == KEY_TAB) { + input_cx = strlen(inputlines[inputline]); // make sure the cursor is at the end of the string, in case we were inserting + input_selection = -1; // make sure there is no text selected, it would look odd + // show all cvars/commands that match what we have inputted if (ctrldown) { @@ -839,21 +864,51 @@ boolean CON_Responder(event_t *ev) return true; } - if (key == KEY_HOME) // oldest text in buffer + if (key == KEY_HOME) { - con_scrollup = (con_totallines-((con_curlines-16)>>3)); + if (shiftdown) + { + if (input_selection == -1) + input_selection = input_cx; + } + else + input_selection = -1; + + if (ctrldown) + con_scrollup = (con_totallines-((con_curlines-16)>>3)); // oldest text in buffer + else + input_cx = 1; + + if (input_cx == input_selection) + input_selection = -1; + return true; } - else if (key == KEY_END) // most recent text in buffer + else if (key == KEY_END) { - con_scrollup = 0; + if (shiftdown) + { + if (input_selection == -1) + input_selection = input_cx; + } + else + input_selection = -1; + + if (ctrldown) + con_scrollup = 0; // most recent text in buffer + else + input_cx = strlen(inputlines[inputline]); + + if (input_cx == input_selection) + input_selection = -1; + return true; } // command enter if (key == KEY_ENTER) { - if (input_cx < 2) + if (strlen(inputlines[inputline]) < 2) return true; // push the command @@ -868,18 +923,107 @@ boolean CON_Responder(event_t *ev) memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); inputlines[inputline][0] = CON_PROMPTCHAR; input_cx = 1; + input_selection = -1; return true; } - // backspace command prompt + // backspace command prompt or delete selected text if (key == KEY_BACKSPACE) { - if (input_cx > 1) + if (input_selection == -1) { - input_cx--; - inputlines[inputline][input_cx] = 0; + if (input_cx > 1) + { + UINT32 i, j; + char *line = inputlines[inputline]; + + for (i = input_cx - 1, j = input_cx; line[j]; ++i, ++j) + line[i] = line[j]; + line[i] = 0; + input_cx--; + } } + else + CON_DeleteSelectedText(); + return true; + } + + // delete character under cursor or selected text + if (key == KEY_DEL) + { + if (input_selection == -1) + { + UINT32 i, j; + char *line = inputlines[inputline]; + + for (i = input_cx, j = input_cx + 1; line[j]; ++i, ++j) + line[i] = line[j]; + line[i] = 0; + } + else + CON_DeleteSelectedText(); + + return true; + } + + if (key == KEY_LEFTARROW) + { + if (shiftdown) + { + if (input_selection == -1) + input_selection = input_cx; + } + else + input_selection = -1; + + // move cursor to previous word + if (ctrldown) + { + char *line = inputlines[inputline]; + + while (input_cx > 1 && line[input_cx - 1] == ' ') + input_cx--; + while (input_cx > 1 && line[input_cx - 1] != ' ') + input_cx--; + } + // move cursor left + else if (input_cx > 1) + input_cx--; + + if (input_cx == input_selection) + input_selection = -1; + + return true; + } + + if (key == KEY_RIGHTARROW) + { + if (shiftdown) + { + if (input_selection == -1) + input_selection = input_cx; + } + else + input_selection = -1; + + // move cursor to next word + if (ctrldown) + { + char *line = inputlines[inputline]; + + while (line[input_cx] && line[input_cx] != ' ') + input_cx++; + while (line[input_cx] && line[input_cx] == ' ') + input_cx++; + } + // move cursor right + else if (inputlines[inputline][input_cx]) + input_cx++; + + if (input_cx == input_selection) + input_selection = -1; + return true; } @@ -950,13 +1094,21 @@ boolean CON_Responder(event_t *ev) return false; // add key to cmd line here - if (input_cx < CON_MAXPROMPTCHARS) + if (strlen(inputlines[inputline]) < CON_MAXPROMPTCHARS - 1) { + INT32 i, j; + char *line = inputlines[inputline]; + 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; + if (input_selection != -1) + CON_DeleteSelectedText(); + + for (i = strlen(line), j = i + 1; j > (INT32)input_cx; --i, --j) + line[j] = line[i]; + + line[input_cx] = (char)key; input_cx++; } @@ -1246,6 +1398,7 @@ static void CON_DrawInput(void) size_t c; INT32 x, y; INT32 charwidth = (INT32)con_scalefactor << 3; + INT32 f = cv_constextsize.value | V_NOSCALESTART; // input line scrolls left if it gets too long p = inputlines[inputline]; @@ -1254,14 +1407,44 @@ static void CON_DrawInput(void) y = con_curlines - 12 * con_scalefactor; - 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); + if (input_selection == -1) + { + for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth) + V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); + } + else + { + size_t selstart = min(input_cx, input_selection); + size_t selend = max(input_cx, input_selection); + + for (c = 0, x = charwidth; c < selstart && c < con_width-11; c++, x += charwidth) + V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); + + f |= V_YELLOWMAP; + for (; c < selend && c < con_width-11; c++, x += charwidth) + V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); + f &= ~V_YELLOWMAP; + + for (; c < con_width-11; c++, x += charwidth) + V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); + } + //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); // 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 (inputlines[inputline][input_cx]) + //V_DrawCharacter(x - 2 * con_scalefactor, y, '|' | f, !cv_allcaps.value); + V_DrawCharacter(x, y + 2 * con_scalefactor, '_' | f, !cv_allcaps.value); + else + V_DrawCharacter(x, y, '_' | f, !cv_allcaps.value); + } + /*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);*/ } // draw the last lines of console text to the top of the screen diff --git a/src/hu_stuff.c b/src/hu_stuff.c index ec747305e..9f1cea13f 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -73,6 +73,9 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; +static size_t chat_pos; // position of the cursor in the chat +static INT32 chat_selection; // selection border in current input line, -1 if no selection +static boolean teamtalk = false; static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -106,6 +109,7 @@ static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics static void HU_DrawRankings(void); static void HU_DrawCoopOverlay(void); static void HU_DrawNetplayCoopOverlay(void); +static void HU_DeleteSelectedText(void); //====================================================================== // KEYBOARD LAYOUTS FOR ENTERING TEXT @@ -621,36 +625,183 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } #endif +// Deletes selected text, assuming there is, and resets selection. +// Also sets the cursor to the correct position. +// +static void HU_DeleteSelectedText(void) +{ + UINT32 i, j; + size_t selstart = min(chat_pos, chat_selection); + size_t selend = max(chat_pos, chat_selection); + + for (i = selstart, j = selend; w_chat[j]; ++i, ++j) + w_chat[i] = w_chat[j]; + while (w_chat[i]) + w_chat[i++] = 0; + + chat_pos = selstart; + chat_selection = -1; +} + // Handles key input and string input // -static inline boolean HU_keyInChatString(char *s, char ch) +static inline void HU_keyInChatString(char *s, UINT32 key, boolean shiftdown, boolean ctrldown) { - size_t l; - - if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART]) - || ch == ' ') // Allow spaces, of course + switch (key) { - l = strlen(s); - if (l < HU_MAXMSGLEN - 1) + case KEY_ESCAPE: + chat_on = false; + break; + case KEY_ENTER: + { + // send automatically the message (no more chat char) + char buf[2+256]; + size_t ci = 2; + char *cp = w_chat; + + while (*cp) { - s[l++] = ch; - s[l]=0; - return true; + if (*cp >= ' ' && !(*cp & 0x80)) + buf[ci++] = *cp; + cp++; } - return false; - } - else if (ch == KEY_BACKSPACE) - { - l = strlen(s); - if (l) - s[--l] = 0; - else - return false; - } - else if (ch != KEY_ENTER) - return false; // did not eat key + buf[ci] = 0; - return true; // ate the key + // last minute mute check + if (cv_mute.value && !(server || adminplayer == consoleplayer)) + { + CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); + return; + } + + if (ci > 2) // don't send target+flags+empty message. + { + if (teamtalk) + buf[0] = -1; // target + else + buf[0] = 0; // target + buf[1] = 0; // flags + SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); + } + + chat_on = false; + break; + } + // cursor moving + case KEY_LEFTARROW: + case KEY_RIGHTARROW: + case KEY_HOME: + case KEY_END: + if (shiftdown) + { + if (chat_selection == -1) + chat_selection = chat_pos; + } + else + chat_selection = -1; + + switch (key) + { + case KEY_LEFTARROW: + // move cursor to previous word + if (ctrldown) + { + while (chat_pos > 0 && w_chat[chat_pos - 1] == ' ') + chat_pos--; + while (chat_pos > 0 && w_chat[chat_pos - 1] != ' ') + chat_pos--; + } + // move cursor left + else if (chat_pos > 0) + chat_pos--; + break; + case KEY_RIGHTARROW: + // move cursor to next word + if (ctrldown) + { + while (w_chat[chat_pos] && w_chat[chat_pos] != ' ') + chat_pos++; + while (w_chat[chat_pos] && w_chat[chat_pos] == ' ') + chat_pos++; + } + // move cursor right + else if (w_chat[chat_pos]) + chat_pos++; + break; + case KEY_HOME: + chat_pos = 0; + break; + case KEY_END: + chat_pos = strlen(w_chat); + } + + if (chat_pos == chat_selection) + chat_selection = -1; + break; + // backspace or delete selected text + case KEY_BACKSPACE: + if (chat_selection == -1) + { + if (chat_pos > 0) + { + UINT32 i, j; + for (i = chat_pos - 1, j = chat_pos; w_chat[j]; ++i, ++j) + w_chat[i] = w_chat[j]; + w_chat[i] = 0; + chat_pos--; + } + } + else + HU_DeleteSelectedText(); + break; + // delete character under cursor + case KEY_DEL: + if (chat_selection == -1) + { + UINT32 i, j; + + for (i = chat_pos, j = chat_pos + 1; w_chat[j]; ++i, ++j) + w_chat[i] = w_chat[j]; + w_chat[i] = 0; + } + else + HU_DeleteSelectedText(); + break; + default: + // allow people to use keypad in chat + if (key >= KEY_KEYPAD7 && key <= KEY_KPADDEL) + { + XBOXSTATIC char keypad_translation[] = {'7','8','9','-', + '4','5','6','+', + '1','2','3', + '0','.'}; + + key = keypad_translation[key - KEY_KEYPAD7]; + } + else if (key == KEY_KPADSLASH) + key = '/'; + + // use console translations + if (shiftdown) + key = shiftxform[key]; + + if ((key >= HU_FONTSTART && key <= HU_FONTEND && hu_font[key-HU_FONTSTART]) + || key == ' ') // Allow spaces, of course + { + if (strlen(w_chat) < HU_MAXMSGLEN - 1) + { + UINT32 i, j; + + if (chat_selection != -1) + HU_DeleteSelectedText(); + + for (i = strlen(w_chat), j = i + 1; j > chat_pos; --i, --j) + w_chat[j] = w_chat[i]; + w_chat[chat_pos] = (char)key; + chat_pos++; + } + } + } } // @@ -669,86 +820,9 @@ void HU_Ticker(void) hu_showscores = false; } -#define QUEUESIZE 256 - -static boolean teamtalk = false; -static char chatchars[QUEUESIZE]; -static INT32 head = 0, tail = 0; - -// -// HU_dequeueChatChar -// -char HU_dequeueChatChar(void) -{ - char c; - - if (head != tail) - { - c = chatchars[tail]; - tail = (tail + 1) & (QUEUESIZE-1); - } - else - c = 0; - - return c; -} - -// -// -static void HU_queueChatChar(char c) -{ - // send automaticly the message (no more chat char) - if (c == KEY_ENTER) - { - char buf[2+256]; - size_t ci = 2; - - do { - c = HU_dequeueChatChar(); - if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. - buf[ci++]=c; - } while (c); - - // last minute mute check - if (cv_mute.value && !(server || adminplayer == consoleplayer)) - { - CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); - return; - } - - if (ci > 3) // don't send target+flags+empty message. - { - if (teamtalk) - buf[0] = -1; // target - else - buf[0] = 0; // target - buf[1] = 0; // flags - SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); - } - return; - } - - if (((head + 1) & (QUEUESIZE-1)) == tail) - CONS_Printf(M_GetText("[Message unsent]\n")); // message not sent - else - { - if (c == KEY_BACKSPACE) - { - if (tail != head) - head = (head - 1) & (QUEUESIZE-1); - } - else - { - chatchars[head] = c; - head = (head + 1) & (QUEUESIZE-1); - } - } -} - +// REMOVE? Now this has become pretty useless IMO void HU_clearChatChars(void) { - while (tail != head) - HU_queueChatChar(KEY_BACKSPACE); chat_on = false; } @@ -758,13 +832,19 @@ void HU_clearChatChars(void) boolean HU_Responder(event_t *ev) { static boolean shiftdown = false; - UINT8 c; + static boolean ctrldown = false; + INT32 key = ev->data1; // only valid if ev->type is a key event - if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) + if (key == KEY_LSHIFT || key == KEY_RSHIFT) { shiftdown = (ev->type == ev_keydown); return chat_on; } + else if (key == KEY_LCTRL || key == KEY_RCTRL) + { + ctrldown = (ev->type == ev_keydown); + return chat_on; + } if (ev->type != ev_keydown) return false; @@ -774,42 +854,36 @@ boolean HU_Responder(event_t *ev) if (!chat_on) { // enter chat mode - if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) + if ((key == gamecontrol[gc_talkkey][0] || key == gamecontrol[gc_talkkey][1]) && netgame && (!cv_mute.value || server || (adminplayer == consoleplayer))) { - if (cv_mute.value && !(server || adminplayer == consoleplayer)) - return false; + // we already checked for this two lines before... + //if (cv_mute.value && !(server || adminplayer == consoleplayer)) + //return false; chat_on = true; w_chat[0] = 0; + chat_pos = 0; + chat_selection = -1; teamtalk = false; return true; } - if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) + if ((key == gamecontrol[gc_teamkey][0] || key == gamecontrol[gc_teamkey][1]) && netgame && (!cv_mute.value || server || (adminplayer == consoleplayer))) { - if (cv_mute.value && !(server || adminplayer == consoleplayer)) - return false; + // we already checked for this two lines before... + //if (cv_mute.value && !(server || adminplayer == consoleplayer)) + //return false; chat_on = true; w_chat[0] = 0; + chat_pos = 0; + chat_selection = -1; teamtalk = true; return true; } } else // if chat_on { - c = (UINT8)ev->data1; - - // use console translations - if (shiftdown) - c = shiftxform[c]; - - if (HU_keyInChatString(w_chat,c)) - HU_queueChatChar(c); - if (c == KEY_ENTER) - chat_on = false; - else if (c == KEY_ESCAPE) - chat_on = false; - + HU_keyInChatString(w_chat, key, shiftdown, ctrldown); return true; } return false; @@ -826,7 +900,7 @@ boolean HU_Responder(event_t *ev) // static void HU_DrawChat(void) { - INT32 t = 0, c = 0, y = HU_INPUTY; + INT32 t = 0, f = 0, c = 0, y = HU_INPUTY; size_t i = 0; const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *talk = ntalk; @@ -844,6 +918,8 @@ static void HU_DrawChat(void) #endif } + f = cv_constextsize.value | V_NOSCALESTART; + while (talk[i]) { if (talk[i] < HU_FONTSTART) @@ -854,36 +930,123 @@ static void HU_DrawChat(void) else { //charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | f, !cv_allcaps.value); } c += charwidth; } + f |= t; i = 0; - while (w_chat[i]) + if (chat_selection == -1) { - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) + while (w_chat[i]) { - ++i; - //charwidth = 4 * con_scalefactor; + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + { + ++i; + //charwidth = 4 * con_scalefactor; + } + else + { + //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); + } + + c += charwidth; + if (c >= vid.width) + { + c = 0; + y += charheight; + } } - else + } + else + { + size_t selstart = min(chat_pos, chat_selection); + size_t selend = max(chat_pos, chat_selection); + + while (i < selstart) { - //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value); + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + { + ++i; + //charwidth = 4 * con_scalefactor; + } + else + { + //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); + } + + c += charwidth; + if (c >= vid.width) + { + c = 0; + y += charheight; + } } - c += charwidth; - if (c >= vid.width) + f &= ~t; + f |= V_YELLOWMAP; + while (i < selend) { - c = 0; - y += charheight; + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + { + ++i; + //charwidth = 4 * con_scalefactor; + } + else + { + //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); + } + + c += charwidth; + if (c >= vid.width) + { + c = 0; + y += charheight; + } + } + f &= ~V_YELLOWMAP; + f |= t; + + while (w_chat[i]) + { + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) + { + ++i; + //charwidth = 4 * con_scalefactor; + } + else + { + //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); + } + + c += charwidth; + if (c >= vid.width) + { + c = 0; + y += charheight; + } } } if (hu_tick < 4) - V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value); + { + if (w_chat[chat_pos]) + { + i = (strlen(talk) + chat_pos) * charwidth; + c = i % vid.width; + y = HU_INPUTY + i / vid.width * charheight + 2 * con_scalefactor; + } + V_DrawCharacter(HU_INPUTX + c, y, '_' | f, !cv_allcaps.value); + } } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 7b22f33f1..5dca10981 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -93,7 +93,6 @@ boolean HU_Responder(event_t *ev); void HU_Ticker(void); void HU_Drawer(void); -char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); From 8b72b553be7e28da023ee15298a40fa02755fbab Mon Sep 17 00:00:00 2001 From: Louis-Antoine Date: Wed, 2 Nov 2016 20:10:08 +0100 Subject: [PATCH 16/32] Fixed warnings --- src/console.c | 16 ++++++++-------- src/hu_stuff.c | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/console.c b/src/console.c index 44819fb4f..f4a1e4f82 100644 --- a/src/console.c +++ b/src/console.c @@ -628,8 +628,8 @@ static void CON_DeleteSelectedText(void) { UINT32 i, j; char *line = inputlines[inputline]; - size_t selstart = min(input_cx, input_selection); - size_t selend = max(input_cx, input_selection); + size_t selstart = min(input_cx, (size_t)input_selection); + size_t selend = max(input_cx, (size_t)input_selection); for (i = selstart, j = selend; line[j]; ++i, ++j) line[i] = line[j]; @@ -879,7 +879,7 @@ boolean CON_Responder(event_t *ev) else input_cx = 1; - if (input_cx == input_selection) + if ((INT32)input_cx == input_selection) input_selection = -1; return true; @@ -899,7 +899,7 @@ boolean CON_Responder(event_t *ev) else input_cx = strlen(inputlines[inputline]); - if (input_cx == input_selection) + if ((INT32)input_cx == input_selection) input_selection = -1; return true; @@ -991,7 +991,7 @@ boolean CON_Responder(event_t *ev) else if (input_cx > 1) input_cx--; - if (input_cx == input_selection) + if ((INT32)input_cx == input_selection) input_selection = -1; return true; @@ -1021,7 +1021,7 @@ boolean CON_Responder(event_t *ev) else if (inputlines[inputline][input_cx]) input_cx++; - if (input_cx == input_selection) + if ((INT32)input_cx == input_selection) input_selection = -1; return true; @@ -1414,8 +1414,8 @@ static void CON_DrawInput(void) } else { - size_t selstart = min(input_cx, input_selection); - size_t selend = max(input_cx, input_selection); + size_t selstart = min(input_cx, (size_t)input_selection); + size_t selend = max(input_cx, (size_t)input_selection); for (c = 0, x = charwidth; c < selstart && c < con_width-11; c++, x += charwidth) V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 9f1cea13f..80e7cf714 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -631,8 +631,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) static void HU_DeleteSelectedText(void) { UINT32 i, j; - size_t selstart = min(chat_pos, chat_selection); - size_t selend = max(chat_pos, chat_selection); + size_t selstart = min(chat_pos, (size_t)chat_selection); + size_t selend = max(chat_pos, (size_t)chat_selection); for (i = selstart, j = selend; w_chat[j]; ++i, ++j) w_chat[i] = w_chat[j]; @@ -645,7 +645,7 @@ static void HU_DeleteSelectedText(void) // Handles key input and string input // -static inline void HU_keyInChatString(char *s, UINT32 key, boolean shiftdown, boolean ctrldown) +static void HU_keyInChatString(UINT32 key, boolean shiftdown, boolean ctrldown) { switch (key) { @@ -735,7 +735,7 @@ static inline void HU_keyInChatString(char *s, UINT32 key, boolean shiftdown, bo chat_pos = strlen(w_chat); } - if (chat_pos == chat_selection) + if ((INT32)chat_pos == chat_selection) chat_selection = -1; break; // backspace or delete selected text @@ -883,7 +883,7 @@ boolean HU_Responder(event_t *ev) } else // if chat_on { - HU_keyInChatString(w_chat, key, shiftdown, ctrldown); + HU_keyInChatString(key, shiftdown, ctrldown); return true; } return false; @@ -963,8 +963,8 @@ static void HU_DrawChat(void) } else { - size_t selstart = min(chat_pos, chat_selection); - size_t selend = max(chat_pos, chat_selection); + size_t selstart = min(chat_pos, (size_t)chat_selection); + size_t selend = max(chat_pos, (size_t)chat_selection); while (i < selstart) { From 81077656772cbd91ceee32e919fa7fb68f2dbc83 Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Wed, 2 Nov 2016 14:26:35 -0700 Subject: [PATCH 17/32] 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 025bc1c19..3fa9b8a97 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 47af65e21..8cf6483ff 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 e56c44c70..111c717d3 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 3cc6d195f..43e3f0182 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 70255d0ef..353f84c1d 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 18/32] 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 3fa9b8a97..11aa5cd56 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 b61ec4143..2caf50087 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 fb8ab1ca2..4b2d8c737 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 ec747305e..e33a54305 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 78c381273..d7b4d9080 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 b2c71944f6bedcf47462d852ba4bb23c14f655f5 Mon Sep 17 00:00:00 2001 From: STJrInuyasha Date: Thu, 3 Nov 2016 00:34:15 -0700 Subject: [PATCH 19/32] Revert "Chat and console improvements" --- src/console.c | 211 ++---------------------- src/hu_stuff.c | 437 ++++++++++++++++--------------------------------- src/hu_stuff.h | 1 + 3 files changed, 152 insertions(+), 497 deletions(-) diff --git a/src/console.c b/src/console.c index f4a1e4f82..025bc1c19 100644 --- a/src/console.c +++ b/src/console.c @@ -91,13 +91,11 @@ 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 INT32 input_selection; // selection border in current input line, -1 if no selection // protos. static void CON_InputInit(void); static void CON_RecalcSize(void); -static void CON_DeleteSelectedText(void); static void CONS_hudlines_Change(void); static void CON_DrawBackpic(patch_t *pic, INT32 startx, INT32 destwidth); //static void CON_DrawBackpic2(pic_t *pic, INT32 startx, INT32 destwidth); @@ -396,7 +394,6 @@ static void CON_InputInit(void) inputlines[i][0] = CON_PROMPTCHAR; inputline = 0; input_cx = 1; - input_selection = -1; } //====================================================================== @@ -621,25 +618,6 @@ void CON_Ticker(void) } } -// Deletes selected text, assuming there is, and resets selection. -// Also sets the cursor to the correct position. -// -static void CON_DeleteSelectedText(void) -{ - UINT32 i, j; - char *line = inputlines[inputline]; - size_t selstart = min(input_cx, (size_t)input_selection); - size_t selend = max(input_cx, (size_t)input_selection); - - for (i = selstart, j = selend; line[j]; ++i, ++j) - line[i] = line[j]; - while (line[i]) - line[i++] = 0; - - input_cx = selstart; - input_selection = -1; -} - // Handles console key input // boolean CON_Responder(event_t *ev) @@ -726,9 +704,6 @@ boolean CON_Responder(event_t *ev) // command completion forward (tab) and backward (shift-tab) if (key == KEY_TAB) { - input_cx = strlen(inputlines[inputline]); // make sure the cursor is at the end of the string, in case we were inserting - input_selection = -1; // make sure there is no text selected, it would look odd - // show all cvars/commands that match what we have inputted if (ctrldown) { @@ -864,51 +839,21 @@ boolean CON_Responder(event_t *ev) return true; } - if (key == KEY_HOME) + if (key == KEY_HOME) // oldest text in buffer { - if (shiftdown) - { - if (input_selection == -1) - input_selection = input_cx; - } - else - input_selection = -1; - - if (ctrldown) - con_scrollup = (con_totallines-((con_curlines-16)>>3)); // oldest text in buffer - else - input_cx = 1; - - if ((INT32)input_cx == input_selection) - input_selection = -1; - + con_scrollup = (con_totallines-((con_curlines-16)>>3)); return true; } - else if (key == KEY_END) + else if (key == KEY_END) // most recent text in buffer { - if (shiftdown) - { - if (input_selection == -1) - input_selection = input_cx; - } - else - input_selection = -1; - - if (ctrldown) - con_scrollup = 0; // most recent text in buffer - else - input_cx = strlen(inputlines[inputline]); - - if ((INT32)input_cx == input_selection) - input_selection = -1; - + con_scrollup = 0; return true; } // command enter if (key == KEY_ENTER) { - if (strlen(inputlines[inputline]) < 2) + if (input_cx < 2) return true; // push the command @@ -923,107 +868,18 @@ boolean CON_Responder(event_t *ev) memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); inputlines[inputline][0] = CON_PROMPTCHAR; input_cx = 1; - input_selection = -1; return true; } - // backspace command prompt or delete selected text + // backspace command prompt if (key == KEY_BACKSPACE) { - if (input_selection == -1) + if (input_cx > 1) { - if (input_cx > 1) - { - UINT32 i, j; - char *line = inputlines[inputline]; - - for (i = input_cx - 1, j = input_cx; line[j]; ++i, ++j) - line[i] = line[j]; - line[i] = 0; - input_cx--; - } - } - else - CON_DeleteSelectedText(); - return true; - } - - // delete character under cursor or selected text - if (key == KEY_DEL) - { - if (input_selection == -1) - { - UINT32 i, j; - char *line = inputlines[inputline]; - - for (i = input_cx, j = input_cx + 1; line[j]; ++i, ++j) - line[i] = line[j]; - line[i] = 0; - } - else - CON_DeleteSelectedText(); - - return true; - } - - if (key == KEY_LEFTARROW) - { - if (shiftdown) - { - if (input_selection == -1) - input_selection = input_cx; - } - else - input_selection = -1; - - // move cursor to previous word - if (ctrldown) - { - char *line = inputlines[inputline]; - - while (input_cx > 1 && line[input_cx - 1] == ' ') - input_cx--; - while (input_cx > 1 && line[input_cx - 1] != ' ') - input_cx--; - } - // move cursor left - else if (input_cx > 1) input_cx--; - - if ((INT32)input_cx == input_selection) - input_selection = -1; - - return true; - } - - if (key == KEY_RIGHTARROW) - { - if (shiftdown) - { - if (input_selection == -1) - input_selection = input_cx; + inputlines[inputline][input_cx] = 0; } - else - input_selection = -1; - - // move cursor to next word - if (ctrldown) - { - char *line = inputlines[inputline]; - - while (line[input_cx] && line[input_cx] != ' ') - input_cx++; - while (line[input_cx] && line[input_cx] == ' ') - input_cx++; - } - // move cursor right - else if (inputlines[inputline][input_cx]) - input_cx++; - - if ((INT32)input_cx == input_selection) - input_selection = -1; - return true; } @@ -1094,21 +950,13 @@ boolean CON_Responder(event_t *ev) return false; // add key to cmd line here - if (strlen(inputlines[inputline]) < CON_MAXPROMPTCHARS - 1) + if (input_cx < CON_MAXPROMPTCHARS) { - INT32 i, j; - char *line = inputlines[inputline]; - if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers key = key + 'a' - 'A'; - if (input_selection != -1) - CON_DeleteSelectedText(); - - for (i = strlen(line), j = i + 1; j > (INT32)input_cx; --i, --j) - line[j] = line[i]; - - line[input_cx] = (char)key; + inputlines[inputline][input_cx] = (char)key; + inputlines[inputline][input_cx + 1] = 0; input_cx++; } @@ -1398,7 +1246,6 @@ static void CON_DrawInput(void) size_t c; INT32 x, y; INT32 charwidth = (INT32)con_scalefactor << 3; - INT32 f = cv_constextsize.value | V_NOSCALESTART; // input line scrolls left if it gets too long p = inputlines[inputline]; @@ -1407,44 +1254,14 @@ static void CON_DrawInput(void) y = con_curlines - 12 * con_scalefactor; - if (input_selection == -1) - { - for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); - } - else - { - size_t selstart = min(input_cx, (size_t)input_selection); - size_t selend = max(input_cx, (size_t)input_selection); - - for (c = 0, x = charwidth; c < selstart && c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); - - f |= V_YELLOWMAP; - for (; c < selend && c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); - f &= ~V_YELLOWMAP; - - for (; c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | f, !cv_allcaps.value); - } - //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); + 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); // draw the blinking cursor // x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth); if (con_tick < 4) - { - if (inputlines[inputline][input_cx]) - //V_DrawCharacter(x - 2 * con_scalefactor, y, '|' | f, !cv_allcaps.value); - V_DrawCharacter(x, y + 2 * con_scalefactor, '_' | f, !cv_allcaps.value); - else - V_DrawCharacter(x, y, '_' | f, !cv_allcaps.value); - } - /*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);*/ + V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); } // draw the last lines of console text to the top of the screen diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 80e7cf714..ec747305e 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -73,9 +73,6 @@ patch_t *cred_font[CRED_FONTSIZE]; static player_t *plr; boolean chat_on; // entering a chat message? static char w_chat[HU_MAXMSGLEN]; -static size_t chat_pos; // position of the cursor in the chat -static INT32 chat_selection; // selection border in current input line, -1 if no selection -static boolean teamtalk = false; static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; @@ -109,7 +106,6 @@ static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics static void HU_DrawRankings(void); static void HU_DrawCoopOverlay(void); static void HU_DrawNetplayCoopOverlay(void); -static void HU_DeleteSelectedText(void); //====================================================================== // KEYBOARD LAYOUTS FOR ENTERING TEXT @@ -625,183 +621,36 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } #endif -// Deletes selected text, assuming there is, and resets selection. -// Also sets the cursor to the correct position. -// -static void HU_DeleteSelectedText(void) -{ - UINT32 i, j; - size_t selstart = min(chat_pos, (size_t)chat_selection); - size_t selend = max(chat_pos, (size_t)chat_selection); - - for (i = selstart, j = selend; w_chat[j]; ++i, ++j) - w_chat[i] = w_chat[j]; - while (w_chat[i]) - w_chat[i++] = 0; - - chat_pos = selstart; - chat_selection = -1; -} - // Handles key input and string input // -static void HU_keyInChatString(UINT32 key, boolean shiftdown, boolean ctrldown) +static inline boolean HU_keyInChatString(char *s, char ch) { - switch (key) + size_t l; + + if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART]) + || ch == ' ') // Allow spaces, of course { - case KEY_ESCAPE: - chat_on = false; - break; - case KEY_ENTER: + l = strlen(s); + if (l < HU_MAXMSGLEN - 1) + { + s[l++] = ch; + s[l]=0; + return true; + } + return false; + } + else if (ch == KEY_BACKSPACE) { - // send automatically the message (no more chat char) - char buf[2+256]; - size_t ci = 2; - char *cp = w_chat; - - while (*cp) - { - if (*cp >= ' ' && !(*cp & 0x80)) - buf[ci++] = *cp; - cp++; - } - buf[ci] = 0; - - // last minute mute check - if (cv_mute.value && !(server || adminplayer == consoleplayer)) - { - CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); - return; - } - - if (ci > 2) // don't send target+flags+empty message. - { - if (teamtalk) - buf[0] = -1; // target - else - buf[0] = 0; // target - buf[1] = 0; // flags - SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); - } - - chat_on = false; - break; + l = strlen(s); + if (l) + s[--l] = 0; + else + return false; } - // cursor moving - case KEY_LEFTARROW: - case KEY_RIGHTARROW: - case KEY_HOME: - case KEY_END: - if (shiftdown) - { - if (chat_selection == -1) - chat_selection = chat_pos; - } - else - chat_selection = -1; + else if (ch != KEY_ENTER) + return false; // did not eat key - switch (key) - { - case KEY_LEFTARROW: - // move cursor to previous word - if (ctrldown) - { - while (chat_pos > 0 && w_chat[chat_pos - 1] == ' ') - chat_pos--; - while (chat_pos > 0 && w_chat[chat_pos - 1] != ' ') - chat_pos--; - } - // move cursor left - else if (chat_pos > 0) - chat_pos--; - break; - case KEY_RIGHTARROW: - // move cursor to next word - if (ctrldown) - { - while (w_chat[chat_pos] && w_chat[chat_pos] != ' ') - chat_pos++; - while (w_chat[chat_pos] && w_chat[chat_pos] == ' ') - chat_pos++; - } - // move cursor right - else if (w_chat[chat_pos]) - chat_pos++; - break; - case KEY_HOME: - chat_pos = 0; - break; - case KEY_END: - chat_pos = strlen(w_chat); - } - - if ((INT32)chat_pos == chat_selection) - chat_selection = -1; - break; - // backspace or delete selected text - case KEY_BACKSPACE: - if (chat_selection == -1) - { - if (chat_pos > 0) - { - UINT32 i, j; - for (i = chat_pos - 1, j = chat_pos; w_chat[j]; ++i, ++j) - w_chat[i] = w_chat[j]; - w_chat[i] = 0; - chat_pos--; - } - } - else - HU_DeleteSelectedText(); - break; - // delete character under cursor - case KEY_DEL: - if (chat_selection == -1) - { - UINT32 i, j; - - for (i = chat_pos, j = chat_pos + 1; w_chat[j]; ++i, ++j) - w_chat[i] = w_chat[j]; - w_chat[i] = 0; - } - else - HU_DeleteSelectedText(); - break; - default: - // allow people to use keypad in chat - if (key >= KEY_KEYPAD7 && key <= KEY_KPADDEL) - { - XBOXSTATIC char keypad_translation[] = {'7','8','9','-', - '4','5','6','+', - '1','2','3', - '0','.'}; - - key = keypad_translation[key - KEY_KEYPAD7]; - } - else if (key == KEY_KPADSLASH) - key = '/'; - - // use console translations - if (shiftdown) - key = shiftxform[key]; - - if ((key >= HU_FONTSTART && key <= HU_FONTEND && hu_font[key-HU_FONTSTART]) - || key == ' ') // Allow spaces, of course - { - if (strlen(w_chat) < HU_MAXMSGLEN - 1) - { - UINT32 i, j; - - if (chat_selection != -1) - HU_DeleteSelectedText(); - - for (i = strlen(w_chat), j = i + 1; j > chat_pos; --i, --j) - w_chat[j] = w_chat[i]; - w_chat[chat_pos] = (char)key; - chat_pos++; - } - } - } + return true; // ate the key } // @@ -820,9 +669,86 @@ void HU_Ticker(void) hu_showscores = false; } -// REMOVE? Now this has become pretty useless IMO +#define QUEUESIZE 256 + +static boolean teamtalk = false; +static char chatchars[QUEUESIZE]; +static INT32 head = 0, tail = 0; + +// +// HU_dequeueChatChar +// +char HU_dequeueChatChar(void) +{ + char c; + + if (head != tail) + { + c = chatchars[tail]; + tail = (tail + 1) & (QUEUESIZE-1); + } + else + c = 0; + + return c; +} + +// +// +static void HU_queueChatChar(char c) +{ + // send automaticly the message (no more chat char) + if (c == KEY_ENTER) + { + char buf[2+256]; + size_t ci = 2; + + do { + c = HU_dequeueChatChar(); + if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only. + buf[ci++]=c; + } while (c); + + // last minute mute check + if (cv_mute.value && !(server || adminplayer == consoleplayer)) + { + CONS_Alert(CONS_NOTICE, M_GetText("The chat is muted. You can't say anything at the moment.\n")); + return; + } + + if (ci > 3) // don't send target+flags+empty message. + { + if (teamtalk) + buf[0] = -1; // target + else + buf[0] = 0; // target + buf[1] = 0; // flags + SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1); + } + return; + } + + if (((head + 1) & (QUEUESIZE-1)) == tail) + CONS_Printf(M_GetText("[Message unsent]\n")); // message not sent + else + { + if (c == KEY_BACKSPACE) + { + if (tail != head) + head = (head - 1) & (QUEUESIZE-1); + } + else + { + chatchars[head] = c; + head = (head + 1) & (QUEUESIZE-1); + } + } +} + void HU_clearChatChars(void) { + while (tail != head) + HU_queueChatChar(KEY_BACKSPACE); chat_on = false; } @@ -832,19 +758,13 @@ void HU_clearChatChars(void) boolean HU_Responder(event_t *ev) { static boolean shiftdown = false; - static boolean ctrldown = false; - INT32 key = ev->data1; // only valid if ev->type is a key event + UINT8 c; - if (key == KEY_LSHIFT || key == KEY_RSHIFT) + if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) { shiftdown = (ev->type == ev_keydown); return chat_on; } - else if (key == KEY_LCTRL || key == KEY_RCTRL) - { - ctrldown = (ev->type == ev_keydown); - return chat_on; - } if (ev->type != ev_keydown) return false; @@ -854,36 +774,42 @@ boolean HU_Responder(event_t *ev) if (!chat_on) { // enter chat mode - if ((key == gamecontrol[gc_talkkey][0] || key == gamecontrol[gc_talkkey][1]) + if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) && netgame && (!cv_mute.value || server || (adminplayer == consoleplayer))) { - // we already checked for this two lines before... - //if (cv_mute.value && !(server || adminplayer == consoleplayer)) - //return false; + if (cv_mute.value && !(server || adminplayer == consoleplayer)) + return false; chat_on = true; w_chat[0] = 0; - chat_pos = 0; - chat_selection = -1; teamtalk = false; return true; } - if ((key == gamecontrol[gc_teamkey][0] || key == gamecontrol[gc_teamkey][1]) + if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) && netgame && (!cv_mute.value || server || (adminplayer == consoleplayer))) { - // we already checked for this two lines before... - //if (cv_mute.value && !(server || adminplayer == consoleplayer)) - //return false; + if (cv_mute.value && !(server || adminplayer == consoleplayer)) + return false; chat_on = true; w_chat[0] = 0; - chat_pos = 0; - chat_selection = -1; teamtalk = true; return true; } } else // if chat_on { - HU_keyInChatString(key, shiftdown, ctrldown); + c = (UINT8)ev->data1; + + // use console translations + if (shiftdown) + c = shiftxform[c]; + + if (HU_keyInChatString(w_chat,c)) + HU_queueChatChar(c); + if (c == KEY_ENTER) + chat_on = false; + else if (c == KEY_ESCAPE) + chat_on = false; + return true; } return false; @@ -900,7 +826,7 @@ boolean HU_Responder(event_t *ev) // static void HU_DrawChat(void) { - INT32 t = 0, f = 0, c = 0, y = HU_INPUTY; + INT32 t = 0, c = 0, y = HU_INPUTY; size_t i = 0; const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *talk = ntalk; @@ -918,8 +844,6 @@ static void HU_DrawChat(void) #endif } - f = cv_constextsize.value | V_NOSCALESTART; - while (talk[i]) { if (talk[i] < HU_FONTSTART) @@ -930,123 +854,36 @@ static void HU_DrawChat(void) else { //charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | f, !cv_allcaps.value); + V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); } c += charwidth; } - f |= t; i = 0; - if (chat_selection == -1) + while (w_chat[i]) { - while (w_chat[i]) + //Hurdler: isn't it better like that? + if (w_chat[i] < HU_FONTSTART) { - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); - } - - c += charwidth; - if (c >= vid.width) - { - c = 0; - y += charheight; - } + ++i; + //charwidth = 4 * con_scalefactor; } - } - else - { - size_t selstart = min(chat_pos, (size_t)chat_selection); - size_t selend = max(chat_pos, (size_t)chat_selection); - - while (i < selstart) + else { - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); - } - - c += charwidth; - if (c >= vid.width) - { - c = 0; - y += charheight; - } + //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value); } - f &= ~t; - f |= V_YELLOWMAP; - while (i < selend) + c += charwidth; + if (c >= vid.width) { - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); - } - - c += charwidth; - if (c >= vid.width) - { - c = 0; - y += charheight; - } - } - f &= ~V_YELLOWMAP; - f |= t; - - while (w_chat[i]) - { - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | f, !cv_allcaps.value); - } - - c += charwidth; - if (c >= vid.width) - { - c = 0; - y += charheight; - } + c = 0; + y += charheight; } } if (hu_tick < 4) - { - if (w_chat[chat_pos]) - { - i = (strlen(talk) + chat_pos) * charwidth; - c = i % vid.width; - y = HU_INPUTY + i / vid.width * charheight + 2 * con_scalefactor; - } - V_DrawCharacter(HU_INPUTX + c, y, '_' | f, !cv_allcaps.value); - } + V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value); } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 5dca10981..7b22f33f1 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -93,6 +93,7 @@ boolean HU_Responder(event_t *ev); void HU_Ticker(void); void HU_Drawer(void); +char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); From bb20cfd6beb341c0774c473150ebb9e1d889cbfe Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Thu, 3 Nov 2016 01:43:57 -0700 Subject: [PATCH 20/32] 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 150cbd505..58fca7c19 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 11aa5cd56..02324ada2 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 854d68f4d..dae9ed16e 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 c1e48b60b..a3fe3077c 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 c161851e0..d61f2d16e 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 0ed58029c..3e5c4b8c6 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 ea8ade8c1..8c4331aa0 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 7e144644c..2d6209f2b 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 7ac32f4b3..fea1e1648 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 888a6a507..ed0db653d 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 0331080c8..eec043803 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 88764ef73..3b6a47258 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 21/32] 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 8c4331aa0..97746b6bf 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 22/32] 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 eec043803..80b89a6e6 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 2ec972af54fe9c8c241e89387f3516ebd4b68c3b Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 3 Nov 2016 20:40:17 +0000 Subject: [PATCH 23/32] check numVertices, bail out and print error message if there are too many I added similar checks for the other num* but it seems some MD2s break the other limits without knowing anyway ...so I've commented these checks out for now, unless we have further discussion regarding them later on --- src/hardware/hw_md2.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 8e48ec110..8e2b9a5b5 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -308,6 +308,23 @@ static md2_model_t *md2_readModel(const char *filename) model->header.numSkins = 1; +#define MD2LIMITCHECK(field, max, msgname) \ + if (field >= max) \ + { \ + CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \ + md2_freeModel (model); \ + return 0; \ + } + + // Uncomment if these are actually needed +// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins") +// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates") +// MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles") +// MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames") + MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices") + +#undef MD2LIMITCHECK + // read skins fseek(file, model->header.offsetSkins, SEEK_SET); if (model->header.numSkins > 0) @@ -319,8 +336,6 @@ static md2_model_t *md2_readModel(const char *filename) md2_freeModel (model); return 0; } - - ; } // read texture coordinates @@ -334,8 +349,6 @@ static md2_model_t *md2_readModel(const char *filename) md2_freeModel (model); return 0; } - - } // read triangles From 561a0fe76880455a97079a4a171c1cefad7fc70c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 3 Nov 2016 21:06:23 +0000 Subject: [PATCH 24/32] Attempt loading of an MD2 only once; if we failed then don't bother again This keeps my new error messages from flooding the console and log.txt --- src/hardware/hw_md2.c | 5 +++++ src/hardware/hw_md2.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 8e2b9a5b5..2fcf252d2 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -782,6 +782,7 @@ void HWR_InitMD2(void) md2_playermodels[s].grpatch = NULL; md2_playermodels[s].skin = -1; md2_playermodels[s].notfound = true; + md2_playermodels[s].error = false; } for (i = 0; i < NUMSPRITES; i++) { @@ -790,6 +791,7 @@ void HWR_InitMD2(void) md2_models[i].grpatch = NULL; md2_models[i].skin = -1; md2_models[i].notfound = true; + md2_models[s].error = false; } // read the md2.dat file @@ -1282,6 +1284,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else md2 = &md2_models[spr->mobj->sprite]; + if (md2->error) + return; // we already failed loading this before :( if (!md2->model) { //CONS_Debug(DBG_RENDER, "Loading MD2... (%s)", sprnames[spr->mobj->sprite]); @@ -1295,6 +1299,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else { //CONS_Debug(DBG_RENDER, " FAILED\n"); + md2->error = true; // prevent endless fail return; } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 36078268b..5a7e6d2b3 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -123,6 +123,7 @@ typedef struct void *blendgrpatch; boolean notfound; INT32 skin; + boolean error; } md2_t; extern md2_t md2_models[NUMSPRITES]; From efe02e2a42b380003c07433d4a837e3011e732d7 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 3 Nov 2016 22:53:49 +0000 Subject: [PATCH 25/32] allow triangle/frame limits too --- src/hardware/hw_md2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 2fcf252d2..a578e6b75 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -319,8 +319,8 @@ static md2_model_t *md2_readModel(const char *filename) // Uncomment if these are actually needed // MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins") // MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates") -// MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles") -// MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames") + MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles") + MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames") MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices") #undef MD2LIMITCHECK From e245cdfcbf41fed6667565c4f4fd3568eed297cd Mon Sep 17 00:00:00 2001 From: Inuyasha Date: Thu, 3 Nov 2016 17:30:30 -0700 Subject: [PATCH 26/32] 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 02324ada2..ea5999c0d 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 8c4331aa0..71ee3f794 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 43e3f0182..f6a966e67 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 27/32] 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 ea5999c0d..e06190975 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 28/32] 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 e06190975..70f8ab6f8 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; From 8909b7c27b16b49bba54e74f3a90ea7e3ce08205 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 5 Nov 2016 17:38:36 +0000 Subject: [PATCH 29/32] Change >= to >, I THINK having exactly 4096 vertices is safe? --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index a578e6b75..ca24b76d2 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -309,7 +309,7 @@ static md2_model_t *md2_readModel(const char *filename) model->header.numSkins = 1; #define MD2LIMITCHECK(field, max, msgname) \ - if (field >= max) \ + if (field > max) \ { \ CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \ md2_freeModel (model); \ From 2dfb841c381ded5f5da6fcdc495fce4b16ae25e0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 6 Nov 2016 17:50:04 +0000 Subject: [PATCH 30/32] Correcting slight mistake I made --- src/hardware/hw_md2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index ca24b76d2..4ec2e346a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -791,7 +791,7 @@ void HWR_InitMD2(void) md2_models[i].grpatch = NULL; md2_models[i].skin = -1; md2_models[i].notfound = true; - md2_models[s].error = false; + md2_models[i].error = false; } // read the md2.dat file From 0726dbe0185e573335c7d4f280361093165021b7 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 15 Nov 2016 20:33:07 +0000 Subject: [PATCH 31/32] Started work on making HWR_DrawFill support V_NOSCALESTART properly ...so far I've got the console text select highlight in the right place outside of 320x200 (and 320x200 is still fine), but for whatever reason it's too large in width and height Oh well, we're part of the way there, anyway --- src/hardware/hw_draw.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 60183b58e..c2d8dfdb9 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -656,6 +656,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { FOutVector v[4]; FSurfaceInfo Surf; + float sdupx, sdupy, pdupx, pdupy; if (w < 0 || h < 0) return; // consistency w/ software @@ -664,10 +665,18 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) // | /| // |/ | // 0--1 - v[0].x = v[3].x = (x - 160.0f)/160.0f; - v[2].x = v[1].x = ((x+w) - 160.0f)/160.0f; - v[0].y = v[1].y = -(y - 100.0f)/100.0f; - v[2].y = v[3].y = -((y+h) - 100.0f)/100.0f; + sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; + sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; + pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; + pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; + + if (color & V_NOSCALESTART) + sdupx = sdupy = 2.0f; + + v[0].x = v[3].x = (x*sdupx)/vid.width - 1; + v[2].x = v[1].x = (x*sdupx + w*pdupx)/vid.width - 1; + v[0].y = v[1].y = 1-(y*sdupy)/vid.height; + v[2].y = v[3].y = 1-(y*sdupy + h*pdupy)/vid.height; //Hurdler: do we still use this argb color? if not, we should remove it v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; From 42f985cda537d769bbee6331aa2879daa3095e02 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 16 Nov 2016 12:10:56 +0000 Subject: [PATCH 32/32] Remove pdupx/y and just use sdupx/y for everything, thanks Inuyasha --- src/hardware/hw_draw.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index c2d8dfdb9..f23753ee5 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -656,7 +656,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { FOutVector v[4]; FSurfaceInfo Surf; - float sdupx, sdupy, pdupx, pdupy; + float sdupx, sdupy; if (w < 0 || h < 0) return; // consistency w/ software @@ -667,16 +667,14 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) // 0--1 sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; - pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; - pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; if (color & V_NOSCALESTART) sdupx = sdupy = 2.0f; v[0].x = v[3].x = (x*sdupx)/vid.width - 1; - v[2].x = v[1].x = (x*sdupx + w*pdupx)/vid.width - 1; + v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1; v[0].y = v[1].y = 1-(y*sdupy)/vid.height; - v[2].y = v[3].y = 1-(y*sdupy + h*pdupy)/vid.height; + v[2].y = v[3].y = 1-(y*sdupy + h*sdupy)/vid.height; //Hurdler: do we still use this argb color? if not, we should remove it v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;