Merge branch 'master' into pr_cmake

This commit is contained in:
oy 2019-01-02 19:31:36 +01:00 committed by GitHub
commit 02e716f509
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 223 additions and 62 deletions

2
.gitignore vendored
View file

@ -16,6 +16,8 @@ scripts/work/
/SDL.dll
/freetype.dll
/autoexec.cfg
other/freetype
other/sdl
_test.exe
Info.plist

15
bam.lua
View file

@ -268,6 +268,12 @@ function GenerateWindowsSettings(settings, conf, target_arch, compiler)
-- Content
BuildContent(settings)
-- dependencies
AddJob("other/sdl/include/SDL.h", "Downloading SDL2 headers and DLL...", dl .. " sdl SDL2.dll") -- TODO: split up dll and headers!
AddJob("other/freetype/include/ft2build.h", "Downloading freetype headers and DLL...", dl .. " freetype freetype.dll")
AddDependency(cur_builddir .. "/objs/engine/client/backend_sdl" .. settings.cc.extension, "other/sdl/include/SDL.h")
AddDependency(cur_builddir .. "/objs/engine/client/text" .. settings.cc.extension, "other/freetype/include/ft2build.h")
end
function SharedCommonFiles()
@ -433,7 +439,7 @@ function GenerateSettings(conf, arch, builddir, compiler)
return settings
end
-- String formatting wth named parameters, by RiciLake http://lua-users.org/wiki/StringInterpolation
-- String formatting with named parameters, by RiciLake http://lua-users.org/wiki/StringInterpolation
function interp(s, tab)
return (s:gsub('%%%((%a%w*)%)([-0-9%.]*[cdeEfgGiouxXsq])',
function(k, fmt)
@ -495,12 +501,19 @@ end
for a, cur_arch in ipairs(archs) do
for c, cur_conf in ipairs(confs) do
cur_builddir = interp(builddir, {platform=family, arch=cur_arch, target=cur_target, conf=cur_conf, compiler=compiler})
if family == "windows" then
dl = Python("scripts/download.py")
dl = dl .. " --arch " .. cur_arch .. " --conf " .. cur_conf
AddJob(cur_builddir .. "/SDL2.dll", "Downloading SDL.dll for " .. cur_arch .. "/" .. cur_conf, dl .. " SDL2.dll") -- TODO: Make me working!
AddJob(cur_builddir .. "/freetype.dll", "Downloading freetype.dll for " .. cur_arch .. "/" .. cur_conf, dl .. " freetype.dll")
end
local settings = GenerateSettings(cur_conf, cur_arch, cur_builddir, compiler)
for t, cur_target in pairs(targets) do
table.insert(subtargets[cur_target], PathJoin(cur_builddir, cur_target .. settings.link.extension))
end
end
end
for cur_name, cur_target in pairs(targets) do
-- Supertarget for all configurations and architectures of that target
PseudoTarget(cur_name, subtargets[cur_target])

61
scripts/download.py Normal file
View file

@ -0,0 +1,61 @@
import shutil, os, re, sys, zipfile
from distutils.dir_util import copy_tree
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])) + "/..")
import twlib
def unzip(filename, where):
try:
z = zipfile.ZipFile(filename, "r")
except:
return False
for name in z.namelist():
z.extract(name, where)
z.close()
return z.namelist()[0]
def downloadAll(arch, conf, targets):
url = "https://github.com/teeworlds/teeworlds-libs/archive/master.zip"
if arch == "x86_64":
_arch = "x64"
else:
_arch = arch
builddir = "build/" + arch + "/" + conf + "/"
# download and unzip
src_package_libs = twlib.fetch_file(url)
if not src_package_libs:
print("couldn't download libs")
sys.exit(-1)
libs_dir = unzip(src_package_libs, ".")
if not libs_dir:
print("couldn't unzip libs")
sys.exit(-1)
libs_dir = "teeworlds-libs-master"
if "SDL2.dll" in targets:
shutil.copy(libs_dir + "/sdl/windows/lib/" + _arch + "/SDL2.dll", builddir)
if "freetype.dll" in targets:
shutil.copy(libs_dir + "/freetype/windows/lib/" + _arch + "/freetype.dll", builddir)
if "sdl" in targets:
copy_tree(libs_dir + "/sdl/windows/", "other/sdl/")
if "freetype" in targets:
copy_tree(libs_dir + "/freetype/windows/", "other/freetype/")
# cleanup
try:
shutil.rmtree(libs_dir)
os.remove(src_package_libs)
except: pass
def main():
import argparse
p = argparse.ArgumentParser(description="Download freetype and SDL library and header files for Windows.")
p.add_argument("--arch", default="x86", choices=["x86", "x86_64"], help="Architecture for the downloaded libraries (Default: x86)")
p.add_argument("--conf", default="debug", choices=["debug", "release"], help="Build type (Default: debug)")
p.add_argument("targets", metavar="TARGET", nargs='+', choices=["SDL2.dll", "freetype.dll", "sdl", "freetype"], help='Target to download. Valid choices are "SDL.dll", "freetype.dll", "sdl" and "freetype"')
args = p.parse_args()
downloadAll(args.arch, args.conf, args.targets)
if __name__ == '__main__':
main()

View file

@ -1798,6 +1798,22 @@ void str_sanitize(char *str_in)
}
}
/* removes all forbidden windows/unix characters in filenames*/
char* str_sanitize_filename(char* aName)
{
char *str = (char *)aName;
while(*str)
{
// replace forbidden characters with a whispace
if(*str == '/' || *str == '<' || *str == '>' || *str == ':' || *str == '"'
|| *str == '/' || *str == '\\' || *str == '|' || *str == '?' || *str == '*')
*str = ' ';
str++;
}
str_clean_whitespaces(aName);
return aName;
}
/* removes leading and trailing spaces and limits the use of multiple spaces */
void str_clean_whitespaces(char *str_in)
{

View file

@ -841,6 +841,19 @@ void str_sanitize_cc(char *str);
*/
void str_sanitize(char *str);
/*
Function: str_sanitize_filename
Replaces all forbidden Windows/Unix characters with whitespace
or nothing if leading or trailing.
Parameters:
str - String to sanitize.
Remarks:
- The strings are treated as zero-terminated strings.
*/
char* str_sanitize_filename(char* aName);
/*
Function: str_check_pathname
Check if the string contains '..' (parent directory) paths.

View file

@ -12,11 +12,10 @@
#include "graphics_threaded.h"
#include "backend_sdl.h"
#if defined(CONF_FAMILY_WINDOWS)
PFNGLTEXIMAGE3DPROC glTexImage3DInternal;
void GLAPIENTRY glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
GLAPI void APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
glTexImage3DInternal(target, level, internalFormat, width, height, depth, border, format, type, pixels);
}
@ -160,7 +159,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
}
else
glDisable(GL_SCISSOR_TEST);
// texture
int SrcBlendMode = GL_ONE;
@ -335,7 +334,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
}
}
m_aTextures[pCommand->m_Slot].m_Format = pCommand->m_Format;
//
int Oglformat = TexFormatToOpenGLFormat(pCommand->m_Format);
int StoreOglformat = TexFormatToOpenGLFormat(pCommand->m_StoreFormat);
@ -384,7 +383,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
m_aTextures[pCommand->m_Slot].m_MemSize += TexWidth*TexHeight*pCommand->m_PixelSize;
}
}
// 3D texture
if((pCommand->m_Flags&CCommandBuffer::TEXFLAG_TEXTURE3D) && m_Max3DTexSize >= CTexture::MIN_GL_MAX_3D_TEXTURE_SIZE)
{
@ -410,12 +409,12 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
}
mem_free(pTexData);
//
glGenTextures(m_TextureArraySize, m_aTextures[pCommand->m_Slot].m_Tex3D);
m_aTextures[pCommand->m_Slot].m_State |= CTexture::STATE_TEX3D;
for(int i = 0; i < m_TextureArraySize; ++i)
{
{
glBindTexture(GL_TEXTURE_3D, m_aTextures[pCommand->m_Slot].m_Tex3D[i]);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -425,7 +424,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::
m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
}
pTexData = pTmpData;
}
}
*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
@ -441,7 +440,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_
void CCommandProcessorFragment_OpenGL::Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand)
{
SetState(pCommand->m_State);
glVertexPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices);
glTexCoordPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*3);
glColorPointer(4, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*6);
@ -472,7 +471,7 @@ void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCom
int h = pCommand->m_H == -1 ? aViewport[3] : pCommand->m_H;
int x = pCommand->m_X;
int y = aViewport[3] - pCommand->m_Y - 1 - (h - 1);
// we allocate one more row to use when we are flipping the texture
unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1);
unsigned char *pTempRow = pPixelData+w*h*3;
@ -626,16 +625,16 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer)
const CCommandBuffer::SCommand *pBaseCommand = pBuffer->GetCommand(&CmdIndex);
if(pBaseCommand == 0x0)
break;
if(m_OpenGL.RunCommand(pBaseCommand))
continue;
if(m_SDL.RunCommand(pBaseCommand))
continue;
if(m_General.RunCommand(pBaseCommand))
continue;
dbg_msg("graphics", "unknown command %d", pBaseCommand->m_Cmd);
}
}
@ -703,7 +702,7 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Screen, int *pWidt
#else
SdlFlags |= SDL_WINDOW_FULLSCREEN;
#endif
// set gl attributes
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if(FsaaSamples)
@ -786,7 +785,7 @@ int CGraphicsBackend_SDL_OpenGL::Shutdown()
CmdBuffer.AddCommand(Cmd);
RunBuffer(&CmdBuffer);
WaitForIdle();
// stop and delete the processor
StopProcessor();
delete m_pProcessor;

View file

@ -125,21 +125,23 @@ static void Mix(short *pFinalOut, unsigned Frames)
float Dist = sqrtf((float)dx*dx+dy*dy);
if(Dist >= 0.0f && Dist < m_MaxDistance)
{
// constant panning (-3dB center)
float a = 0.5f;
if(dx < 0)
a -= (Dist/m_MaxDistance)/2.0f;
else
a += (Dist/m_MaxDistance)/2.0f;
float Lgain = sinf((1-a)*pi/2.0f);
float Rgain = sinf(a*pi/2.0f);
// linear falloff
float Falloff = 1.0f - Dist/m_MaxDistance;
Lvol = Lvol*Lgain*Falloff;
Rvol = Rvol*Rgain*Falloff;
// amplitude after falloff
float FalloffAmp = v->m_pChannel->m_Vol * Falloff;
// distribute volume to the channels depending on x difference
float Lpan = 0.5f - dx/m_MaxDistance/2.0f;
float Rpan = 1.0f - Lpan;
// apply square root to preserve sound power after panning
float LampFactor = sqrt(Lpan);
float RampFactor = sqrt(Rpan);
// volume of the channels
Lvol = FalloffAmp*LampFactor;
Rvol = FalloffAmp*RampFactor;
}
else
{

View file

@ -760,15 +760,16 @@ void CServer::SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int Cli
void CServer::UpdateClientRconCommands()
{
int ClientID = Tick() % MAX_CLIENTS;
if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed)
for(int ClientID = Tick() % MAX_RCONCMD_RATIO; ClientID < MaxClients(); ClientID += MAX_RCONCMD_RATIO)
{
int ConsoleAccessLevel = m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD;
for(int i = 0; i < MAX_RCONCMD_SEND && m_aClients[ClientID].m_pRconCmdToSend; ++i)
if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed)
{
SendRconCmdAdd(m_aClients[ClientID].m_pRconCmdToSend, ClientID);
m_aClients[ClientID].m_pRconCmdToSend = m_aClients[ClientID].m_pRconCmdToSend->NextCommandInfo(ConsoleAccessLevel, CFGFLAG_SERVER);
int ConsoleAccessLevel = m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD;
for(int i = 0; i < MAX_RCONCMD_SEND && m_aClients[ClientID].m_pRconCmdToSend; ++i)
{
SendRconCmdAdd(m_aClients[ClientID].m_pRconCmdToSend, ClientID);
m_aClients[ClientID].m_pRconCmdToSend = m_aClients[ClientID].m_pRconCmdToSend->NextCommandInfo(ConsoleAccessLevel, CFGFLAG_SERVER);
}
}
}
}

View file

@ -76,6 +76,7 @@ public:
AUTHED_ADMIN,
MAX_RCONCMD_SEND=16,
MAX_RCONCMD_RATIO=8,
};
class CClient

View file

@ -139,6 +139,11 @@ void CChat::ConShowChat(IConsole::IResult *pResult, void *pUserData)
((CChat *)pUserData)->m_Show = pResult->GetInteger(0) != 0;
}
void CChat::OnInit()
{
m_Input.Init(Input());
}
void CChat::OnConsoleInit()
{
Console()->Register("say", "r", CFGFLAG_CLIENT, ConSay, this, "Say in chat");

View file

@ -81,6 +81,7 @@ public:
void Say(int Team, const char *pLine);
virtual void OnInit();
virtual void OnReset();
virtual void OnConsoleInit();
virtual void OnStateChange(int NewState, int OldState);

View file

@ -57,6 +57,7 @@ CGameConsole::CInstance::CInstance(int Type)
void CGameConsole::CInstance::Init(CGameConsole *pGameConsole)
{
m_pGameConsole = pGameConsole;
m_Input.Init(m_pGameConsole->Input());
};
void CGameConsole::CInstance::ClearBacklog()

View file

@ -448,11 +448,10 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
s_DoScroll = true;
s_ScrollStart = UI()->MouseX();
int MxRel = (int)(UI()->MouseX() - pRect->x);
float Offset = pRect->w/2.0f-TextRender()->TextWidth(0, FontSize, pStr, -1)/2.0f;
for(int i = 1; i <= Len; i++)
{
if(Offset + TextRender()->TextWidth(0, FontSize, pStr, i) - *pOffset > MxRel)
if(TextRender()->TextWidth(0, FontSize, pStr, i) - *pOffset > MxRel)
{
s_AtIndex = i - 1;
break;
@ -487,7 +486,7 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
{
Len = str_length(pStr);
int NumChars = Len;
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars, Input());
}
}
}
@ -562,15 +561,14 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
UI()->ClipEnable(pRect);
Textbox.x -= *pOffset;
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, CUI::ALIGN_CENTER);
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, CUI::ALIGN_LEFT);
// render the cursor
if(UI()->LastActiveItem() == pID && !JustGotActive)
{
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1);
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
Textbox = *pRect;
Textbox.x += Textbox.w/2.0f-w/2.0f;
w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex);
Textbox.VSplitLeft(2.0f, 0, &Textbox);
Textbox.x += (w-*pOffset-TextRender()->TextWidth(0, FontSize, "|", -1)/2);
if((2*time_get()/time_freq()) % 2) // make it blink

View file

@ -531,7 +531,7 @@ private:
void HandleCallvote(int Page, bool Force);
void RenderServerControl(CUIRect MainView);
void RenderServerControlKick(CUIRect MainView, bool FilterSpectators);
void RenderServerControlServer(CUIRect MainView);
bool RenderServerControlServer(CUIRect MainView);
// found in menus_browser.cpp
// int m_ScrollOffset;

View file

@ -2132,11 +2132,15 @@ void CMenus::RenderServerbrowserBottomBox(CUIRect MainView)
}
void CMenus::DoGameIcon(const char *pName, const CUIRect *pRect, int Type)
{
char aNameBuf[128];
str_copy(aNameBuf, pName, sizeof(aNameBuf));
str_sanitize_filename(aNameBuf);
// get texture
IGraphics::CTextureHandle Tex = m_GameIconDefault;
for(int i = 0; i < m_lGameIcons.size(); ++i)
{
if(!str_comp_nocase(pName, m_lGameIcons[i].m_Name))
if(!str_comp_nocase(aNameBuf, m_lGameIcons[i].m_Name))
{
Tex = m_lGameIcons[i].m_IconTexture;
break;

View file

@ -469,8 +469,9 @@ void CMenus::RenderServerInfo(CUIRect MainView)
TextRender()->Text(0, Motd.x, Motd.y, ButtonHeight*ms_FontmodHeight*0.8f, m_pClient->m_pMotd->GetMotd(), (int)Motd.w);
}
void CMenus::RenderServerControlServer(CUIRect MainView)
bool CMenus::RenderServerControlServer(CUIRect MainView)
{
bool doCallVote = false;
static int s_VoteList = 0;
static CListBoxState s_ListBoxState;
CUIRect List = MainView;
@ -482,14 +483,15 @@ void CMenus::RenderServerControlServer(CUIRect MainView)
CListboxItem Item = UiDoListboxNextItem(&s_ListBoxState, pOption);
if(Item.m_Visible)
{
{
Item.m_Rect.VMargin(5.0f, &Item.m_Rect);
Item.m_Rect.y += 2.0f;
UI()->DoLabel(&Item.m_Rect, pOption->m_aDescription, Item.m_Rect.h*ms_FontmodHeight*0.8f, CUI::ALIGN_LEFT);
}
}
m_CallvoteSelectedOption = UiDoListboxEnd(&s_ListBoxState, 0);
m_CallvoteSelectedOption = UiDoListboxEnd(&s_ListBoxState, &doCallVote);
return doCallVote;
}
void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
@ -676,9 +678,10 @@ void CMenus::RenderServerControl(CUIRect MainView)
MainView.HSplitBottom(90.0f+2*20.0f, &MainView, &Extended);
RenderTools()->DrawUIRect(&Extended, vec4(0.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
bool doCallVote = false;
// render page
if(s_ControlPage == 0)
RenderServerControlServer(MainView);
doCallVote = RenderServerControlServer(MainView); // double click triggers vote
else if(s_ControlPage == 1)
RenderServerControlKick(MainView, false);
else if(s_ControlPage == 2)
@ -720,7 +723,7 @@ void CMenus::RenderServerControl(CUIRect MainView)
{
// call vote
static CButtonContainer s_CallVoteButton;
if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button))
if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button) || doCallVote)
HandleCallvote(s_ControlPage, false);
}
else

View file

@ -1,11 +1,13 @@
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include <engine/keys.h>
#include <engine/input.h>
#include "lineinput.h"
CLineInput::CLineInput()
{
Clear();
m_pInput = 0;
}
void CLineInput::Clear()
@ -16,6 +18,11 @@ void CLineInput::Clear()
m_NumChars = 0;
}
void CLineInput::Init(IInput *pInput)
{
m_pInput = pInput;
}
void CLineInput::Set(const char *pString)
{
str_copy(m_Str, pString, sizeof(m_Str));
@ -30,7 +37,15 @@ void CLineInput::Set(const char *pString)
}
}
bool CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr)
bool CLineInput::CtrlStop(char c)
{
// jump to spaces and special ASCII characters
return ((32 <= c && c <= 47) || // !"#$%&'()*+,-./
(58 <= c && c <= 64) || // :;<=>?@
(91 <= c && c <= 96)); // [\]^_`
}
bool CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr, IInput *pInput)
{
int NumChars = *pNumCharsPtr;
int CursorPos = *pCursorPosPtr;
@ -74,31 +89,54 @@ bool CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize, in
if(Event.m_Flags&IInput::FLAG_PRESS)
{
int Key = Event.m_Key;
bool Ctrl = false;
#ifdef CONF_PLATFORM_MACOSX
if(pInput && (pInput->KeyIsPressed(KEY_LALT) || pInput->KeyIsPressed(KEY_RALT)))
#else
if(pInput && (pInput->KeyIsPressed(KEY_LCTRL) || pInput->KeyIsPressed(KEY_RCTRL)))
#endif
Ctrl = true;
if(Key == KEY_BACKSPACE && CursorPos > 0)
{
int NewCursorPos = str_utf8_rewind(pStr, CursorPos);
int NewCursorPos = CursorPos;
do
{
NewCursorPos = str_utf8_rewind(pStr, NewCursorPos);
NumChars -= 1;
} while(Ctrl && NewCursorPos > 0 && !CtrlStop(pStr[NewCursorPos - 1]));
int CharSize = CursorPos-NewCursorPos;
mem_move(pStr+NewCursorPos, pStr+CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term
CursorPos = NewCursorPos;
Len -= CharSize;
if(CharSize > 0)
--NumChars;
Changes = true;
}
else if(Key == KEY_DELETE && CursorPos < Len)
{
int p = str_utf8_forward(pStr, CursorPos);
int CharSize = p-CursorPos;
int EndCursorPos = CursorPos;
do
{
EndCursorPos = str_utf8_forward(pStr, EndCursorPos);
NumChars -= 1;
} while(Ctrl && EndCursorPos < Len && !CtrlStop(pStr[EndCursorPos - 1]));
int CharSize = EndCursorPos - CursorPos;
mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term
Len -= CharSize;
if(CharSize > 0)
--NumChars;
Changes = true;
}
else if(Key == KEY_LEFT && CursorPos > 0)
CursorPos = str_utf8_rewind(pStr, CursorPos);
{
do
{
CursorPos = str_utf8_rewind(pStr, CursorPos);
} while(Ctrl && CursorPos > 0 && !CtrlStop(pStr[CursorPos - 1]));
}
else if(Key == KEY_RIGHT && CursorPos < Len)
CursorPos = str_utf8_forward(pStr, CursorPos);
{
do
{
CursorPos = str_utf8_forward(pStr, CursorPos);
} while(Ctrl && CursorPos < Len && !CtrlStop(pStr[CursorPos - 1]));
}
else if(Key == KEY_HOME)
CursorPos = 0;
else if(Key == KEY_END)
@ -114,5 +152,5 @@ bool CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize, in
bool CLineInput::ProcessInput(IInput::CEvent e)
{
return Manipulate(e, m_Str, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars);
return Manipulate(e, m_Str, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars, m_pInput);
}

View file

@ -17,8 +17,10 @@ class CLineInput
int m_Len;
int m_CursorPos;
int m_NumChars;
IInput *m_pInput;
public:
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr);
static bool CtrlStop(char c);
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr, IInput *pInput);
class CCallback
{
@ -28,6 +30,7 @@ public:
};
CLineInput();
void Init(IInput *pInput);
void Clear();
bool ProcessInput(IInput::CEvent e);
void Set(const char *pString);

View file

@ -340,7 +340,7 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str
{
Len = str_length(pStr);
int NumChars = Len;
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars, Input());
}
}