MF_API int MFString_AsciiToInteger(const char *pString, bool bDetectBase, int base, const char **ppNextChar) { pString = MFSkipWhite(pString); int number = 0; if(base == 16 || (bDetectBase && ((pString[0] == '0' && pString[1] == 'x') || pString[0] == '$'))) { // hex number if(pString[0] == '0' && pString[1] == 'x') pString += 2; else if(pString[0] == '$') pString += 1; while(*pString) { int digit = *pString++; if(!MFIsHex(digit)) return number; number <<= 4; number += MFIsNumeric(digit) ? digit - '0' : MFToLower(digit) - 'a' + 10; } } else if(base == 2 || (bDetectBase && pString[0] == 'b')) { if(pString[0] == 'b') ++pString; while(*pString == '0' || *pString == '1') { number <<= 1; number |= *pString - '0'; } } else if(base == 10) { // decimal number bool neg = false; if(*pString == '-' || *pString == '+') { neg = *pString == '-'; ++pString; } while(*pString) { if(!MFIsNumeric(*pString)) return neg ? -number : number; number = number*10 + (*pString++) - '0'; } if(neg) number = -number; } if(ppNextChar) *ppNextChar = pString; return number; }
char* GetFloat(char *pFilePtr, float *pFloat) { char *pEnd, *pToken; bool negative = false; int dotFound = 1; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr == '-') { negative = true; pFilePtr++; } pEnd = pFilePtr; while(MFIsNumeric(*pEnd) || (*pEnd == '.' && dotFound--)) pEnd++; pToken = (char*)MFStrN(pFilePtr, (int)(pEnd-pFilePtr)); if(*pEnd == 'f') pEnd++; if(!MFIsWhite(*pEnd) && !MFIsNewline(*pEnd) && *pEnd != 0) { MFDebug_Warn(3, "Error: GetFloat() found non numeric character."); *pFloat = 0.0f; return pFilePtr; } pFilePtr = pEnd; *pFloat = (float)atof(pToken); if(negative) *pFloat = -*pFloat; return pFilePtr; }
char* GetInt(char *pFilePtr, int *pInt) { char *pEnd, *pToken; bool negative = false; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr == '-') { negative = true; pFilePtr++; } pEnd = pFilePtr; while(MFIsNumeric(*pEnd)) pEnd++; if(!MFIsWhite(*pEnd) && !MFIsNewline(*pEnd) && *pEnd != 0) { MFDebug_Warn(3, "Error: GetInt() found non numeric character."); *pInt = 0; return pFilePtr; } pToken = (char*)MFStrN(pFilePtr, (int)(pEnd - pFilePtr)); pFilePtr = pEnd; *pInt = atoi(pToken); if(negative) *pInt = -*pInt; return pFilePtr; }
void GotoSection(int cancel, const char *pString) { if(cancel || !*pString) return; const char *pTest = pString; while(*pTest && (MFIsNumeric(*pTest) || *pTest == '.')) ++pTest; int res = gEditor.pSong->GetRes(); if(pTest > pString) { if(!*pTest) { OffsetToMeasureAndBeat((int)((float)atof(pString) * res), &gEditor.measure, &gEditor.beat); return; } if(!MFString_CaseCmp(pTest, "s")) { float time = (float)atof(pString); OffsetToMeasureAndBeat(gEditor.pSong->CalculateTickAtTime((int64)(time*1000000.0f)), &gEditor.measure, &gEditor.beat); return; } else if(!MFString_CaseCmp(pTest, "ms")) { float time = (float)atof(pString); OffsetToMeasureAndBeat(gEditor.pSong->CalculateTickAtTime((int64)(time*1000.0f)), &gEditor.measure, &gEditor.beat); return; } } // find section by name size_t len = MFString_Length(pString); GHEvent *pSE = gEditor.pSong->events.First(); while(pSE) { if(!MFString_CaseCmpN(pSE->GetString(), "section ", 8) && !MFString_CaseCmpN(&pSE->GetString()[8], pString, len)) { OffsetToMeasureAndBeat(pSE->tick, &gEditor.measure, &gEditor.beat); return; } pSE = pSE->Next(); } }
MF_API bool MFString_IsNumber(const char *pString, bool bAllowHex) { pString = MFSkipWhite(pString); int numDigits = 0; if(bAllowHex && pString[0] == '0' && pString[1] == 'x') { // hex number pString += 2; while(*pString) { if(!MFIsHex(*pString++)) return false; ++numDigits; } } else { // decimal number if(*pString == '-' || *pString == '+') ++pString; bool bHasDot = false; while(*pString) { if(!MFIsNumeric(*pString) && (bHasDot || *pString != '.')) return false; if(*pString++ == '.') { bHasDot = true; numDigits = 0; } else ++numDigits; } } return numDigits > 0 ? true : false; }
MF_API float MFString_AsciiToFloat(const char *pString, const char **ppNextChar) { pString = MFSkipWhite(pString); int64 number = 0; float frac = 1; // floating poiont number bool neg = false; if(*pString == '-' || *pString == '+') { neg = *pString == '-'; ++pString; } bool bHasDot = false; while(*pString) { int digit = *pString++; if(!MFIsNumeric(digit) && (bHasDot || digit != '.')) return (float)(neg ? -number : number) * frac; if(digit == '.') bHasDot = true; else { number = number*10 + digit - '0'; if(bHasDot) frac *= 0.1f; } } if(neg) number = -number; if(ppNextChar) *ppNextChar = pString; return (float)number * frac; }
int MFRenderer_CreateDisplay(MFDisplay *pDisplay) { #if MF_DISPLAY == MF_DRIVER_X11 Window window = (Window)MFWindow_GetSystemWindowHandle(pDisplay->settings.pWindow); glXWindow = glXCreateWindow(xdisplay, fbConfigs[0], window, NULL); if(!glXWindow) { MFDebug_Error("Unable to associate window with a GLXWindow"); MFRenderer_DestroyDisplay(pDisplay); return 1; } glXContext = glXCreateNewContext(xdisplay, fbConfigs[0], GLX_RGBA_TYPE, NULL, true); if(!glXContext) { MFDebug_Error("Unable to create GLXContext"); MFRenderer_DestroyDisplay(pDisplay); return 1; } XFree(fbConfigs); fbConfigs = NULL; if(!glXMakeContextCurrent(xdisplay, glXWindow, glXWindow, glXContext)) { MFDebug_Error("glXMakeContextCurrent failed"); MFRenderer_DestroyDisplay(pDisplay); return 1; } #elif MF_DISPLAY == MF_DRIVER_WIN32 HWND hWnd = (HWND)MFWindow_GetSystemWindowHandle(pDisplay->settings.pWindow); GLuint pixelFormat; PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 32, // colour depth 0, 0, 0, 0, 0, 0, 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 24, // 16Bit Z-Buffer (Depth Buffer) 8, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 0, 0 // Layer Masks Ignored }; pfd.dwFlags |= pDisplay->settings.numBuffers > 1 ? PFD_DOUBLEBUFFER : 0; hDC = GetDC(hWnd); if(!hDC) { MFRenderer_DestroyDisplay(pDisplay); MessageBoxA(NULL, "Can't Create A GL Device Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); return 1; } pixelFormat = ChoosePixelFormat(hDC, &pfd); if(!pixelFormat) { MFRenderer_DestroyDisplay(pDisplay); MessageBoxA(NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); return 2; } if(!SetPixelFormat(hDC, pixelFormat, &pfd)) { MFRenderer_DestroyDisplay(pDisplay); MessageBoxA(NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK|MB_ICONEXCLAMATION); return 3; } hRC = wglCreateContext(hDC); if(!hRC) { // *** driver bug *** // HACK: do it again... SetPixelFormat(hDC, pixelFormat, &pfd); hRC = wglCreateContext(hDC); } if(!hRC) { MessageBoxA(NULL, MFStr("Failed to create OpenGL context: %s", MFSystemPC_GetLastError()), "ERROR", MB_OK|MB_ICONEXCLAMATION); MFRenderer_DestroyDisplay(pDisplay); return 4; } if(!wglMakeCurrent(hDC, hRC)) { MFRenderer_DestroyDisplay(pDisplay); MessageBoxA(NULL, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK|MB_ICONEXCLAMATION); return 5; } #elif MF_DISPLAY == MF_DRIVER_SDL2 glContext = SDL_GL_CreateContext((SDL_Window*)MFWindow_GetSystemWindowHandle(pDisplay->settings.pWindow)); #elif MF_DISPLAY == MF_DRIVER_IPHONE MFRendererIPhone_MakeCurrent(); #elif MF_DISPLAY == MF_DRIVER_NACL // do we need to do anything? #endif // get the opengl version const char *pVersion = (const char *)glGetString(GL_VERSION); while(pVersion && *pVersion && !MFIsNumeric(*pVersion)) ++pVersion; float ver = MFString_AsciiToFloat(pVersion); gOpenGLVersion = (int)(ver * 100); #if !defined(MF_OPENGL_ES) // glew wrangles all the horrid extensions... GLenum r = glewInit(); MFDebug_Assert(r == GLEW_OK, "Error loading extensions!"); #endif #if !defined(MF_OPENGL_ES) glEnable(GL_LINE_SMOOTH); // glFrontFace(GL_CW); // glCullFace(GL_BACK); glDisable(GL_LIGHTING); #endif glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); #if defined(MF_OPENGL_ES) // we need the EGL display apparently... // eglSwapInterval(, 1); #else #if MF_DISPLAY == MF_DRIVER_X11 // GLXDrawable drawable = glXGetCurrentDrawable(); // glXSwapIntervalEXT(xdisplay, drawable, 1); #elif MF_DISPLAY == MF_DRIVER_WIN32 // wglSwapInterval(1); #endif #endif glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&gDefaultRenderTarget); MFTextureDesc texDesc = { MFTexType_2D, ImgFmt_A8R8G8B8, pDisplay->settings.width, pDisplay->settings.height, 0, 0, 1, MFTCF_RenderTarget }; gpDeviceColourTarget = MFTexture_InitTexture(&texDesc, MFRD_OpenGL, 0); gpDeviceColourTarget->pName = "Device Colour Target"; gpDeviceColourTarget->pSurfaces[0].platformData = (uint64)gDefaultRenderTarget; texDesc.format = ImgFmt_D24S8; gpDeviceZTarget = MFTexture_InitTexture(&texDesc, MFRD_OpenGL, 0); gpDeviceZTarget->pName = "Device Depth Stencil"; gpDeviceZTarget->pSurfaces[0].platformData = 0; MFRenderTargetDesc desc; desc.pName = "Device Render Target"; desc.width = pDisplay->settings.width; desc.height = pDisplay->settings.height; desc.colourTargets[0].pSurface = gpDeviceColourTarget; desc.depthStencil.pSurface = gpDeviceZTarget; gpDeviceRenderTarget = MFRenderTarget_Create(&desc); gCurrentViewport.x = 0.0f; gCurrentViewport.y = 0.0f; gCurrentViewport.width = (float)pDisplay->settings.width; gCurrentViewport.height = (float)pDisplay->settings.height; glViewport(0, 0, pDisplay->settings.width, pDisplay->settings.height); return 0; }
void HKStringEntryLogic::Update() { bool shiftL = !!MFInput_Read(Key_LShift, IDD_Keyboard); bool shiftR = !!MFInput_Read(Key_RShift, IDD_Keyboard); bool ctrlL = !!MFInput_Read(Key_LControl, IDD_Keyboard); bool ctrlR = !!MFInput_Read(Key_RControl, IDD_Keyboard); int keyPressed = 0; bool shift = shiftL || shiftR; bool ctrl = ctrlL || ctrlR; #if defined(MF_WINDOWS) if(ctrl && MFInput_WasPressed(Key_C, IDD_Keyboard) && selectionStart != selectionEnd) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, numChars + 1); char *pString = (char*)GlobalLock(hData); MFString_Copy(pString, GetRenderString().SubStr(selMin, numChars).CStr()); GlobalUnlock(hData); EmptyClipboard(); SetClipboardData(CF_TEXT, hData); CloseClipboard(); } } else if(ctrl && MFInput_WasPressed(Key_X, IDD_Keyboard) && selectionStart != selectionEnd) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, numChars + 1); char *pString = (char*)GlobalLock(hData); MFString_Copy(pString, GetRenderString().SubStr(selMin, numChars).CStr()); GlobalUnlock(hData); EmptyClipboard(); SetClipboardData(CF_TEXT, hData); CloseClipboard(); ClearSelection(); } } else if(ctrl && MFInput_WasPressed(Key_V, IDD_Keyboard)) { BOOL opened = OpenClipboard(apphWnd); if(opened) { int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int numChars = selMax-selMin; HANDLE hData = GetClipboardData(CF_TEXT); MFString paste((const char*)GlobalLock(hData), true); buffer.Replace(selMin, numChars, paste); GlobalUnlock(hData); cursorPos = selMin + paste.NumBytes(); selectionStart = selectionEnd = cursorPos; GlobalUnlock(hData); CloseClipboard(); if((numChars || cursorPos != selMin) && changeCallback) changeCallback(buffer.CStr()); } } else #endif { // check for new keypresses for(int a=0; a<255; a++) { if(MFInput_WasPressed(a, IDD_Keyboard)) { keyPressed = a; holdKey = a; repeatDelay = gRepeatDelay; break; } } // handle repeat keys if(holdKey && MFInput_Read(holdKey, IDD_Keyboard)) { repeatDelay -= MFSystem_TimeDelta(); if(repeatDelay <= 0.f) { keyPressed = holdKey; repeatDelay += gRepeatRate; } } else holdKey = 0; // if there was a new key press if(keyPressed) { switch(keyPressed) { case Key_Backspace: case Key_Delete: { if(selectionStart != selectionEnd) { ClearSelection(); } else { if(keyPressed == Key_Backspace && cursorPos > 0) { buffer.ClearRange(--cursorPos, 1); selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } else if(keyPressed == Key_Delete && cursorPos < buffer.NumBytes()) { buffer.ClearRange(cursorPos, 1); selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } } break; } case Key_Left: case Key_Right: case Key_Home: case Key_End: { if(ctrl) { if(keyPressed == Key_Left) { while(cursorPos && MFIsWhite(buffer[cursorPos-1])) --cursorPos; if(MFIsAlphaNumeric(buffer[cursorPos-1])) { while(cursorPos && MFIsAlphaNumeric(buffer[cursorPos-1])) --cursorPos; } else if(cursorPos) { --cursorPos; while(cursorPos && buffer[cursorPos-1] == buffer[cursorPos]) --cursorPos; } } else if(keyPressed == Key_Right) { while(cursorPos < buffer.NumBytes() && MFIsWhite(buffer[cursorPos])) ++cursorPos; if(MFIsAlphaNumeric(buffer[cursorPos])) { while(cursorPos < buffer.NumBytes() && MFIsAlphaNumeric(buffer[cursorPos])) ++cursorPos; } else if(cursorPos < buffer.NumBytes()) { ++cursorPos; while(cursorPos < buffer.NumBytes() && buffer[cursorPos] == buffer[cursorPos-1]) ++cursorPos; } } else if(keyPressed == Key_Home) cursorPos = 0; else if(keyPressed == Key_End) cursorPos = buffer.NumBytes(); } else { if(keyPressed == Key_Left) cursorPos = (!shift && selectionStart != selectionEnd ? MFMin(selectionStart, selectionEnd) : MFMax(cursorPos-1, 0)); else if(keyPressed == Key_Right) cursorPos = (!shift && selectionStart != selectionEnd ? MFMax(selectionStart, selectionEnd) : MFMin(cursorPos+1, buffer.NumBytes())); else if(keyPressed == Key_Home) cursorPos = 0; // TODO: if multiline, go to start of line.. else if(keyPressed == Key_End) cursorPos = buffer.NumBytes(); // TODO: if multiline, go to end of line... } if(shift) selectionEnd = cursorPos; else selectionStart = selectionEnd = cursorPos; break; } default: { bool caps = MFInput_GetKeyboardStatusState(KSS_CapsLock); int ascii = MFInput_KeyToAscii(keyPressed, shift, caps); if(ascii && (!maxLen || buffer.NumBytes() < maxLen-1)) { // check character exclusions if(MFIsNewline(ascii) && type != ST_MultiLine) break; if(ascii == '\t' && type != ST_MultiLine) break; if(type == ST_Numeric && !MFIsNumeric(ascii)) break; if(include) { if(include.FindChar(ascii) < 0) break; } if(exclude) { if(exclude.FindChar(ascii) >= 0) break; } int selMin = MFMin(selectionStart, selectionEnd); int selMax = MFMax(selectionStart, selectionEnd); int selRange = selMax - selMin; const uint16 wstr[] = { (uint16)ascii, 0 }; char insert[5]; MFString_CopyUTF16ToUTF8(insert, wstr); buffer.Replace(selMin, selRange, insert); cursorPos = selMin + 1; selectionStart = selectionEnd = cursorPos; if(changeCallback) changeCallback(buffer.CStr()); } break; } } } } }
int MFString::Parse(const char *pFormat, ...) { if(!pData || !pFormat) return 0; va_list arglist; va_start(arglist, pFormat); const char *pS = pData->pMemory; int numArgs = 0; MFString format = GetNextBit(pFormat); int numChars = Match(pS, format.CStr()); while(*pFormat && numChars >= 0) { pS += numChars; ++pFormat; int length = -1; // gather format options... while(*pFormat) { int c = MFToLower(*pFormat++); if(c == 's') { MFString *pStr = va_arg(arglist, MFString*); ++numArgs; format = GetNextBit(pFormat); if(length >= 0) { MFString s(pS, (size_t)length); *pStr = s; numChars = Match(pS, format.CStr()); } else if(format.NumBytes() == 0) { *pStr = pS; } else { const char *pEnd = pS; while(*pEnd && (numChars = Match(pEnd, format.CStr())) < 0) ++pEnd; MFString s(pS, (size_t)(pEnd - pS)); *pStr = s; } pS += pStr->NumBytes(); break; } else if(c == 'd' || c == 'i') { int *pInt = va_arg(arglist, int*); ++numArgs; bool bNeg = *pS == '-'; if(*pS == '-' || *pS == '+') ++pS; *pInt = 0; while(MFIsNumeric(*pS) && ((uint32&)length)-- > 0) *pInt = *pInt*10 + *pS++ - '0'; if(bNeg) *pInt = -*pInt; format = GetNextBit(pFormat); numChars = Match(pS, format.CStr()); break; }