Update rcore.c

This commit is contained in:
Nickolas McDonald 2023-08-19 20:55:53 -04:00
parent 3001a4adb3
commit 1fed487137

View File

@ -6510,14 +6510,14 @@ static void InitEvdevInput(void)
} }
// Identifies a input device and configures it for use if appropriate // Identifies a input device and configures it for use if appropriate
static void ConfigureEvdevDevice(char* device) static void ConfigureEvdevDevice(char *device)
{ {
#define BITS_PER_LONG (8*sizeof(long)) #define BITS_PER_LONG (8*sizeof(long))
#define NBITS(x) ((((x) - 1)/BITS_PER_LONG) + 1) #define NBITS(x) ((((x) - 1)/BITS_PER_LONG) + 1)
#define OFF(x) ((x)%BITS_PER_LONG) #define OFF(x) ((x)%BITS_PER_LONG)
#define BIT(x) (1UL<<OFF(x)) #define BIT(x) (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG) #define LONG(x) ((x)/BITS_PER_LONG)
#define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1) #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
struct input_absinfo absinfo = { 0 }; struct input_absinfo absinfo = { 0 };
unsigned long evBits[NBITS(EV_MAX)] = { 0 }; unsigned long evBits[NBITS(EV_MAX)] = { 0 };
@ -6530,12 +6530,12 @@ static void ConfigureEvdevDevice(char* device)
int freeWorkerId = -1; int freeWorkerId = -1;
int fd = -1; int fd = -1;
InputEventWorker* worker = NULL; InputEventWorker *worker = NULL;
// Open the device and allocate worker // Open the device and allocate worker
//------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------
// Find a free spot in the workers array // Find a free spot in the workers array
for (int i = 0; i < sizeof(CORE.Input.eventWorker) / sizeof(InputEventWorker); ++i) for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{ {
if (CORE.Input.eventWorker[i].threadId == 0) if (CORE.Input.eventWorker[i].threadId == 0)
{ {
@ -6567,7 +6567,7 @@ static void ConfigureEvdevDevice(char* device)
// Grab number on the end of the devices name "event<N>" // Grab number on the end of the devices name "event<N>"
int devNum = 0; int devNum = 0;
char* ptrDevName = strrchr(device, 't'); char *ptrDevName = strrchr(device, 't');
worker->eventNum = -1; worker->eventNum = -1;
if (ptrDevName != NULL) if (ptrDevName != NULL)
@ -6670,13 +6670,13 @@ static void ConfigureEvdevDevice(char* device)
{ {
// Looks like an interesting device // Looks like an interesting device
TRACELOG(LOG_INFO, "RPI: Opening input device: %s (%s%s%s%s)", device, TRACELOG(LOG_INFO, "RPI: Opening input device: %s (%s%s%s%s)", device,
worker->isMouse ? "mouse " : "", worker->isMouse? "mouse " : "",
worker->isMultitouch ? "multitouch " : "", worker->isMultitouch? "multitouch " : "",
worker->isTouch ? "touchscreen " : "", worker->isTouch? "touchscreen " : "",
worker->isGamepad ? "gamepad " : ""); worker->isGamepad? "gamepad " : "");
// Create a thread for this device // Create a thread for this device
int error = pthread_create(&worker->threadId, NULL, &EventThread, (void*)worker); int error = pthread_create(&worker->threadId, NULL, &EventThread, (void *)worker);
if (error != 0) if (error != 0)
{ {
TRACELOG(LOG_WARNING, "RPI: Failed to create input device thread: %s (error: %d)", device, error); TRACELOG(LOG_WARNING, "RPI: Failed to create input device thread: %s (error: %d)", device, error);
@ -6688,13 +6688,13 @@ static void ConfigureEvdevDevice(char* device)
// Find touchscreen with the highest index // Find touchscreen with the highest index
int maxTouchNumber = -1; int maxTouchNumber = -1;
for (int i = 0; i < sizeof(CORE.Input.eventWorker) / sizeof(InputEventWorker); ++i) for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{ {
if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum > maxTouchNumber)) maxTouchNumber = CORE.Input.eventWorker[i].eventNum; if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum > maxTouchNumber)) maxTouchNumber = CORE.Input.eventWorker[i].eventNum;
} }
// Find touchscreens with lower indexes // Find touchscreens with lower indexes
for (int i = 0; i < sizeof(CORE.Input.eventWorker) / sizeof(InputEventWorker); ++i) for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{ {
if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum < maxTouchNumber)) if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum < maxTouchNumber))
{ {
@ -6762,25 +6762,25 @@ static void PollKeyboardEvents(void)
// WARNING: https://www.kernel.org/doc/Documentation/input/input.txt // WARNING: https://www.kernel.org/doc/Documentation/input/input.txt
// Event interface: 'value' is the value the event carries. Either a relative change for EV_REL, // Event interface: 'value' is the value the event carries. Either a relative change for EV_REL,
// absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat // absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat
CORE.Input.Keyboard.currentKeyState[keycode] = (event.value >= 1) ? 1 : 0; CORE.Input.Keyboard.currentKeyState[keycode] = (event.value >= 1)? 1 : 0;
if (event.value >= 1) if (event.value >= 1)
{ {
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed
CORE.Input.Keyboard.keyPressedQueueCount++; CORE.Input.Keyboard.keyPressedQueueCount++;
} }
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
// Check screen capture key (raylib key: KEY_F12) // Check screen capture key (raylib key: KEY_F12)
if (CORE.Input.Keyboard.currentKeyState[301] == 1) if (CORE.Input.Keyboard.currentKeyState[301] == 1)
{ {
TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter)); TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++; screenshotCounter++;
} }
#endif #endif
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true; if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true;
TRACELOGD("RPI: KEY_%s ScanCode: %4i KeyCode: %4i", event.value == 0 ? "UP" : "DOWN", event.code, keycode); TRACELOGD("RPI: KEY_%s ScanCode: %4i KeyCode: %4i", event.value == 0 ? "UP":"DOWN", event.code, keycode);
} }
} }
} }
@ -6788,10 +6788,10 @@ static void PollKeyboardEvents(void)
} }
// Input device events reading thread // Input device events reading thread
static void* EventThread(void* arg) static void *EventThread(void *arg)
{ {
struct input_event event = { 0 }; struct input_event event = { 0 };
InputEventWorker* worker = (InputEventWorker*)arg; InputEventWorker *worker = (InputEventWorker *)arg;
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool gestureUpdate = false; // Flag to note gestures require to update bool gestureUpdate = false; // Flag to note gestures require to update
@ -6831,8 +6831,8 @@ static void* EventThread(void* arg)
// Basic movement // Basic movement
if (event.code == ABS_X) if (event.code == ABS_X)
{ {
CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x) * CORE.Window.screen.width / worker->absRange.width; // Scale according to absRange CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x) * CORE.Window.screen.width / worker->absRange.width; // Scale according to absRange CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true; gestureUpdate = true;
@ -6840,8 +6840,8 @@ static void* EventThread(void* arg)
if (event.code == ABS_Y) if (event.code == ABS_Y)
{ {
CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y) * CORE.Window.screen.height / worker->absRange.height; // Scale according to absRange CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y) * CORE.Window.screen.height / worker->absRange.height; // Scale according to absRange CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true; gestureUpdate = true;
@ -6852,12 +6852,12 @@ static void* EventThread(void* arg)
if (event.code == ABS_MT_POSITION_X) if (event.code == ABS_MT_POSITION_X)
{ {
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x) * CORE.Window.screen.width / worker->absRange.width; // Scale according to absRange if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
} }
if (event.code == ABS_MT_POSITION_Y) if (event.code == ABS_MT_POSITION_Y)
{ {
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y) * CORE.Window.screen.height / worker->absRange.height; // Scale according to absRange if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
} }
if (event.code == ABS_MT_TRACKING_ID) if (event.code == ABS_MT_TRACKING_ID)
@ -6919,10 +6919,10 @@ static void* EventThread(void* arg)
if (!CORE.Input.Mouse.cursorHidden) if (!CORE.Input.Mouse.cursorHidden)
{ {
if (CORE.Input.Mouse.currentPosition.x < 0) CORE.Input.Mouse.currentPosition.x = 0; if (CORE.Input.Mouse.currentPosition.x < 0) CORE.Input.Mouse.currentPosition.x = 0;
if (CORE.Input.Mouse.currentPosition.x > CORE.Window.screen.width / CORE.Input.Mouse.scale.x) CORE.Input.Mouse.currentPosition.x = CORE.Window.screen.width / CORE.Input.Mouse.scale.x; if (CORE.Input.Mouse.currentPosition.x > CORE.Window.screen.width/CORE.Input.Mouse.scale.x) CORE.Input.Mouse.currentPosition.x = CORE.Window.screen.width/CORE.Input.Mouse.scale.x;
if (CORE.Input.Mouse.currentPosition.y < 0) CORE.Input.Mouse.currentPosition.y = 0; if (CORE.Input.Mouse.currentPosition.y < 0) CORE.Input.Mouse.currentPosition.y = 0;
if (CORE.Input.Mouse.currentPosition.y > CORE.Window.screen.height / CORE.Input.Mouse.scale.y) CORE.Input.Mouse.currentPosition.y = CORE.Window.screen.height / CORE.Input.Mouse.scale.y; if (CORE.Input.Mouse.currentPosition.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.currentPosition.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y;
} }
// Update touch point count // Update touch point count
@ -6994,11 +6994,11 @@ static void InitGamepad(void)
} }
// Process Gamepad (/dev/input/js0) // Process Gamepad (/dev/input/js0)
static void* GamepadThread(void* arg) static void *GamepadThread(void *arg)
{ {
#define JS_EVENT_BUTTON 0x01 // Button pressed/released #define JS_EVENT_BUTTON 0x01 // Button pressed/released
#define JS_EVENT_AXIS 0x02 // Joystick axis moved #define JS_EVENT_AXIS 0x02 // Joystick axis moved
#define JS_EVENT_INIT 0x80 // Initial state of device #define JS_EVENT_INIT 0x80 // Initial state of device
struct js_event { struct js_event {
unsigned int time; // event timestamp in milliseconds unsigned int time; // event timestamp in milliseconds
@ -7039,7 +7039,7 @@ static void* GamepadThread(void* arg)
if (gamepadEvent.number < MAX_GAMEPAD_AXIS) if (gamepadEvent.number < MAX_GAMEPAD_AXIS)
{ {
// NOTE: Scaling of gamepadEvent.value to get values between -1..1 // NOTE: Scaling of gamepadEvent.value to get values between -1..1
CORE.Input.Gamepad.axisState[i][gamepadEvent.number] = (float)gamepadEvent.value / 32768; CORE.Input.Gamepad.axisState[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
} }
} }
} }
@ -7053,13 +7053,13 @@ static void* GamepadThread(void* arg)
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM)
// Search matching DRM mode in connector's mode list // Search matching DRM mode in connector's mode list
static int FindMatchingConnectorMode(const drmModeConnector* connector, const drmModeModeInfo* mode) static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)
{ {
if (NULL == connector) return -1; if (NULL == connector) return -1;
if (NULL == mode) return -1; if (NULL == mode) return -1;
// safe bitwise comparison of two modes // safe bitwise comparison of two modes
#define BINCMP(a, b) memcmp((a), (b), (sizeof(a) < sizeof(b)) ? sizeof(a) : sizeof(b)) #define BINCMP(a, b) memcmp((a), (b), (sizeof(a) < sizeof(b)) ? sizeof(a) : sizeof(b))
for (size_t i = 0; i < connector->count_modes; i++) for (size_t i = 0; i < connector->count_modes; i++)
{ {
@ -7071,11 +7071,11 @@ static int FindMatchingConnectorMode(const drmModeConnector* connector, const dr
return -1; return -1;
#undef BINCMP #undef BINCMP
} }
// Search exactly matching DRM connector mode in connector's list // Search exactly matching DRM connector mode in connector's list
static int FindExactConnectorMode(const drmModeConnector* connector, uint width, uint height, uint fps, bool allowInterlaced) static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced)
{ {
TRACELOG(LOG_TRACE, "DISPLAY: Searching exact connector mode for %ux%u@%u, selecting an interlaced mode is allowed: %s", width, height, fps, allowInterlaced ? "yes" : "no"); TRACELOG(LOG_TRACE, "DISPLAY: Searching exact connector mode for %ux%u@%u, selecting an interlaced mode is allowed: %s", width, height, fps, allowInterlaced ? "yes" : "no");
@ -7083,7 +7083,7 @@ static int FindExactConnectorMode(const drmModeConnector* connector, uint width,
for (int i = 0; i < CORE.Window.connector->count_modes; i++) for (int i = 0; i < CORE.Window.connector->count_modes; i++)
{ {
const drmModeModeInfo* const mode = &CORE.Window.connector->modes[i]; const drmModeModeInfo *const mode = &CORE.Window.connector->modes[i];
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive"); TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive");
@ -7097,7 +7097,7 @@ static int FindExactConnectorMode(const drmModeConnector* connector, uint width,
} }
// Search the nearest matching DRM connector mode in connector's list // Search the nearest matching DRM connector mode in connector's list
static int FindNearestConnectorMode(const drmModeConnector* connector, uint width, uint height, uint fps, bool allowInterlaced) static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced)
{ {
TRACELOG(LOG_TRACE, "DISPLAY: Searching nearest connector mode for %ux%u@%u, selecting an interlaced mode is allowed: %s", width, height, fps, allowInterlaced ? "yes" : "no"); TRACELOG(LOG_TRACE, "DISPLAY: Searching nearest connector mode for %ux%u@%u, selecting an interlaced mode is allowed: %s", width, height, fps, allowInterlaced ? "yes" : "no");
@ -7106,7 +7106,7 @@ static int FindNearestConnectorMode(const drmModeConnector* connector, uint widt
int nearestIndex = -1; int nearestIndex = -1;
for (int i = 0; i < CORE.Window.connector->count_modes; i++) for (int i = 0; i < CORE.Window.connector->count_modes; i++)
{ {
const drmModeModeInfo* const mode = &CORE.Window.connector->modes[i]; const drmModeModeInfo *const mode = &CORE.Window.connector->modes[i];
TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, TRACELOG(LOG_TRACE, "DISPLAY: DRM mode: %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh,
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive"); (mode->flags & DRM_MODE_FLAG_INTERLACE) ? "interlaced" : "progressive");
@ -7149,7 +7149,7 @@ static int FindNearestConnectorMode(const drmModeConnector* connector, uint widt
#if defined(SUPPORT_EVENTS_AUTOMATION) #if defined(SUPPORT_EVENTS_AUTOMATION)
// NOTE: Loading happens over AutomationEvent *events // NOTE: Loading happens over AutomationEvent *events
// TODO: This system should probably be redesigned // TODO: This system should probably be redesigned
static void LoadAutomationEvents(const char* fileName) static void LoadAutomationEvents(const char *fileName)
{ {
// Load events file (binary) // Load events file (binary)
/* /*
@ -7169,7 +7169,7 @@ static void LoadAutomationEvents(const char* fileName)
*/ */
// Load events file (text) // Load events file (text)
FILE* repFile = fopen(fileName, "rt"); FILE *repFile = fopen(fileName, "rt");
if (repFile != NULL) if (repFile != NULL)
{ {
@ -7201,7 +7201,7 @@ static void LoadAutomationEvents(const char* fileName)
} }
// Export recorded events into a file // Export recorded events into a file
static void ExportAutomationEvents(const char* fileName) static void ExportAutomationEvents(const char *fileName)
{ {
unsigned char fileId[4] = "rEP "; unsigned char fileId[4] = "rEP ";
@ -7215,7 +7215,7 @@ static void ExportAutomationEvents(const char* fileName)
*/ */
// Export events as text // Export events as text
FILE* repFile = fopen(fileName, "wt"); FILE *repFile = fopen(fileName, "wt");
if (repFile != NULL) if (repFile != NULL)
{ {
@ -7428,7 +7428,7 @@ static void RecordAutomationEvent(unsigned int frame)
events[eventCount].type = INPUT_GAMEPAD_AXIS_MOTION; events[eventCount].type = INPUT_GAMEPAD_AXIS_MOTION;
events[eventCount].params[0] = gamepad; events[eventCount].params[0] = gamepad;
events[eventCount].params[1] = axis; events[eventCount].params[1] = axis;
events[eventCount].params[2] = (int)(CORE.Input.Gamepad.axisState[gamepad][axis] * 32768.0f); events[eventCount].params[2] = (int)(CORE.Input.Gamepad.axisState[gamepad][axis]*32768.0f);
TRACELOG(LOG_INFO, "[%i] INPUT_GAMEPAD_AXIS_MOTION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]); TRACELOG(LOG_INFO, "[%i] INPUT_GAMEPAD_AXIS_MOTION: %i, %i, %i", events[eventCount].frame, events[eventCount].params[0], events[eventCount].params[1], events[eventCount].params[2]);
eventCount++; eventCount++;
@ -7487,7 +7487,7 @@ static void PlayAutomationEvent(unsigned int frame)
case INPUT_GAMEPAD_BUTTON_DOWN: CORE.Input.Gamepad.currentButtonState[events[i].params[0]][events[i].params[1]] = true; break; // param[0]: gamepad, param[1]: button case INPUT_GAMEPAD_BUTTON_DOWN: CORE.Input.Gamepad.currentButtonState[events[i].params[0]][events[i].params[1]] = true; break; // param[0]: gamepad, param[1]: button
case INPUT_GAMEPAD_AXIS_MOTION: // param[0]: gamepad, param[1]: axis, param[2]: delta case INPUT_GAMEPAD_AXIS_MOTION: // param[0]: gamepad, param[1]: axis, param[2]: delta
{ {
CORE.Input.Gamepad.axisState[events[i].params[0]][events[i].params[1]] = ((float)events[i].params[2] / 32768.0f); CORE.Input.Gamepad.axisState[events[i].params[0]][events[i].params[1]] = ((float)events[i].params[2]/32768.0f);
} break; } break;
case INPUT_GESTURE: GESTURES.current = events[i].params[0]; break; // param[0]: gesture (enum Gesture) -> rgestures.h: GESTURES.current case INPUT_GESTURE: GESTURES.current = events[i].params[0]; break; // param[0]: gesture (enum Gesture) -> rgestures.h: GESTURES.current
@ -7514,20 +7514,20 @@ static void PlayAutomationEvent(unsigned int frame)
#if !defined(SUPPORT_MODULE_RTEXT) #if !defined(SUPPORT_MODULE_RTEXT)
// Formatting of text with variables to 'embed' // Formatting of text with variables to 'embed'
// WARNING: String returned will expire after this function is called MAX_TEXTFORMAT_BUFFERS times // WARNING: String returned will expire after this function is called MAX_TEXTFORMAT_BUFFERS times
const char* TextFormat(const char* text, ...) const char *TextFormat(const char *text, ...)
{ {
#ifndef MAX_TEXTFORMAT_BUFFERS #ifndef MAX_TEXTFORMAT_BUFFERS
#define MAX_TEXTFORMAT_BUFFERS 4 // Maximum number of static buffers for text formatting #define MAX_TEXTFORMAT_BUFFERS 4 // Maximum number of static buffers for text formatting
#endif #endif
#ifndef MAX_TEXT_BUFFER_LENGTH #ifndef MAX_TEXT_BUFFER_LENGTH
#define MAX_TEXT_BUFFER_LENGTH 1024 // Maximum size of static text buffer #define MAX_TEXT_BUFFER_LENGTH 1024 // Maximum size of static text buffer
#endif #endif
// We create an array of buffers so strings don't expire until MAX_TEXTFORMAT_BUFFERS invocations // We create an array of buffers so strings don't expire until MAX_TEXTFORMAT_BUFFERS invocations
static char buffers[MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH] = { 0 }; static char buffers[MAX_TEXTFORMAT_BUFFERS][MAX_TEXT_BUFFER_LENGTH] = { 0 };
static int index = 0; static int index = 0;
char* currentBuffer = buffers[index]; char *currentBuffer = buffers[index];
memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using
va_list args; va_list args;