mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-20 22:16:49 +01:00
24c86b5501
since the window system doesn't do it for us like other platforms. This prevents sticky keys and missed keys when going in and out of focus, for example Alt would appear to stick if switching away from an SDL app with Alt-Tab and had to be pressed again. CR: Sam
396 lines
9.9 KiB
C
396 lines
9.9 KiB
C
/* See COPYING.txt for the full license governing this code. */
|
|
/**
|
|
* \file action_configparser.c
|
|
*
|
|
* Source file for the parser for action config files.
|
|
*/
|
|
|
|
#include <SDL_stdinc.h>
|
|
#include <SDL_test.h>
|
|
#include <string.h>
|
|
#include "SDL_visualtest_action_configparser.h"
|
|
#include "SDL_visualtest_rwhelper.h"
|
|
#include "SDL_visualtest_parsehelper.h"
|
|
|
|
static void
|
|
FreeAction(SDLVisualTest_Action* action)
|
|
{
|
|
if(!action)
|
|
return;
|
|
switch(action->type)
|
|
{
|
|
case SDL_ACTION_LAUNCH:
|
|
{
|
|
char* path;
|
|
char* args;
|
|
|
|
path = action->extra.process.path;
|
|
args = action->extra.process.args;
|
|
|
|
if(path)
|
|
SDL_free(path);
|
|
if(args)
|
|
SDL_free(args);
|
|
|
|
action->extra.process.path = NULL;
|
|
action->extra.process.args = NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
int
|
|
SDLVisualTest_EnqueueAction(SDLVisualTest_ActionQueue* queue,
|
|
SDLVisualTest_Action action)
|
|
{
|
|
SDLVisualTest_ActionNode* node;
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return 0;
|
|
}
|
|
|
|
node = (SDLVisualTest_ActionNode*)SDL_malloc(
|
|
sizeof(SDLVisualTest_ActionNode));
|
|
if(!node)
|
|
{
|
|
SDLTest_LogError("malloc() failed");
|
|
return 0;
|
|
}
|
|
node->action = action;
|
|
node->next = NULL;
|
|
queue->size++;
|
|
if(!queue->rear)
|
|
queue->rear = queue->front = node;
|
|
else
|
|
{
|
|
queue->rear->next = node;
|
|
queue->rear = node;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
SDLVisualTest_DequeueAction(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
SDLVisualTest_ActionNode* node;
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return 0;
|
|
}
|
|
if(SDLVisualTest_IsActionQueueEmpty(queue))
|
|
{
|
|
SDLTest_LogError("cannot dequeue from empty queue");
|
|
return 0;
|
|
}
|
|
if(queue->front == queue->rear)
|
|
{
|
|
FreeAction(&queue->front->action);
|
|
SDL_free(queue->front);
|
|
queue->front = queue->rear = NULL;
|
|
}
|
|
else
|
|
{
|
|
node = queue->front;
|
|
queue->front = queue->front->next;
|
|
FreeAction(&node->action);
|
|
SDL_free(node);
|
|
}
|
|
queue->size--;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
SDLVisualTest_InitActionQueue(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return;
|
|
}
|
|
queue->front = NULL;
|
|
queue->rear = NULL;
|
|
queue->size = 0;
|
|
}
|
|
|
|
SDLVisualTest_Action*
|
|
SDLVisualTest_GetQueueFront(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return NULL;
|
|
}
|
|
if(!queue->front)
|
|
{
|
|
SDLTest_LogError("cannot get front of empty queue");
|
|
return NULL;
|
|
}
|
|
|
|
return &queue->front->action;
|
|
}
|
|
|
|
int
|
|
SDLVisualTest_IsActionQueueEmpty(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return 1;
|
|
}
|
|
|
|
if(queue->size > 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
SDLVisualTest_EmptyActionQueue(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
if(queue)
|
|
{
|
|
while(!SDLVisualTest_IsActionQueueEmpty(queue))
|
|
SDLVisualTest_DequeueAction(queue);
|
|
}
|
|
}
|
|
|
|
/* Since the size of the queue is not likely to be larger than 100 elements
|
|
we can get away with using insertion sort. */
|
|
static void
|
|
SortQueue(SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
SDLVisualTest_ActionNode* head;
|
|
SDLVisualTest_ActionNode* tail;
|
|
|
|
if(!queue || SDLVisualTest_IsActionQueueEmpty(queue))
|
|
return;
|
|
|
|
head = queue->front;
|
|
for(tail = head; tail && tail->next;)
|
|
{
|
|
SDLVisualTest_ActionNode* pos;
|
|
SDLVisualTest_ActionNode* element = tail->next;
|
|
|
|
if(element->action.time < head->action.time)
|
|
{
|
|
tail->next = tail->next->next;
|
|
element->next = head;
|
|
head = element;
|
|
}
|
|
else if(element->action.time >= tail->action.time)
|
|
{
|
|
tail = tail->next;
|
|
}
|
|
else
|
|
{
|
|
for(pos = head;
|
|
(pos->next->action.time < element->action.time);
|
|
pos = pos->next);
|
|
tail->next = tail->next->next;
|
|
element->next = pos->next;
|
|
pos->next = element;
|
|
}
|
|
}
|
|
|
|
queue->front = head;
|
|
queue->rear = tail;
|
|
}
|
|
|
|
int
|
|
SDLVisualTest_InsertIntoActionQueue(SDLVisualTest_ActionQueue* queue,
|
|
SDLVisualTest_Action action)
|
|
{
|
|
SDLVisualTest_ActionNode* n;
|
|
SDLVisualTest_ActionNode* prev;
|
|
SDLVisualTest_ActionNode* newnode;
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return 0;
|
|
}
|
|
|
|
if(SDLVisualTest_IsActionQueueEmpty(queue))
|
|
{
|
|
if(!SDLVisualTest_EnqueueAction(queue, action))
|
|
{
|
|
SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
newnode = (SDLVisualTest_ActionNode*)malloc(sizeof(SDLVisualTest_ActionNode));
|
|
if(!newnode)
|
|
{
|
|
SDLTest_LogError("malloc() failed");
|
|
return 0;
|
|
}
|
|
newnode->action = action;
|
|
|
|
queue->size++;
|
|
for(n = queue->front, prev = NULL; n; n = n->next)
|
|
{
|
|
if(action.time < n->action.time)
|
|
{
|
|
if(prev)
|
|
{
|
|
prev->next = newnode;
|
|
newnode->next = n;
|
|
}
|
|
else
|
|
{
|
|
newnode->next = queue->front;
|
|
queue->front = newnode;
|
|
}
|
|
return 1;
|
|
}
|
|
prev = n;
|
|
}
|
|
|
|
queue->rear->next = newnode;
|
|
newnode->next = NULL;
|
|
queue->rear = newnode;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
SDLVisualTest_ParseActionConfig(char* file, SDLVisualTest_ActionQueue* queue)
|
|
{
|
|
char line[MAX_ACTION_LINE_LENGTH];
|
|
SDLVisualTest_RWHelperBuffer buffer;
|
|
char* token_ptr;
|
|
int linenum;
|
|
SDL_RWops* rw;
|
|
|
|
if(!file)
|
|
{
|
|
SDLTest_LogError("file argument cannot be NULL");
|
|
return 0;
|
|
}
|
|
if(!queue)
|
|
{
|
|
SDLTest_LogError("queue argument cannot be NULL");
|
|
return 0;
|
|
}
|
|
|
|
rw = SDL_RWFromFile(file, "r");
|
|
if(!rw)
|
|
{
|
|
SDLTest_LogError("SDL_RWFromFile() failed");
|
|
return 0;
|
|
}
|
|
|
|
SDLVisualTest_RWHelperResetBuffer(&buffer);
|
|
SDLVisualTest_InitActionQueue(queue);
|
|
linenum = 0;
|
|
while(SDLVisualTest_RWHelperReadLine(rw, line, MAX_ACTION_LINE_LENGTH,
|
|
&buffer, '#'))
|
|
{
|
|
SDLVisualTest_Action action;
|
|
int hr, min, sec;
|
|
|
|
/* parse time */
|
|
token_ptr = strtok(line, " ");
|
|
if(!token_ptr ||
|
|
(SDL_sscanf(token_ptr, "%d:%d:%d", &hr, &min, &sec) != 3))
|
|
{
|
|
SDLTest_LogError("Could not parse time token at line: %d",
|
|
linenum);
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
action.time = (((hr * 60 + min) * 60) + sec) * 1000;
|
|
|
|
/* parse type */
|
|
token_ptr = strtok(NULL, " ");
|
|
if(SDL_strcasecmp(token_ptr, "launch") == 0)
|
|
action.type = SDL_ACTION_LAUNCH;
|
|
else if(SDL_strcasecmp(token_ptr, "kill") == 0)
|
|
action.type = SDL_ACTION_KILL;
|
|
else if(SDL_strcasecmp(token_ptr, "quit") == 0)
|
|
action.type = SDL_ACTION_QUIT;
|
|
else if(SDL_strcasecmp(token_ptr, "screenshot") == 0)
|
|
action.type = SDL_ACTION_SCREENSHOT;
|
|
else if(SDL_strcasecmp(token_ptr, "verify") == 0)
|
|
action.type = SDL_ACTION_VERIFY;
|
|
else
|
|
{
|
|
SDLTest_LogError("Could not parse type token at line: %d",
|
|
linenum);
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
|
|
/* parse the extra field */
|
|
if(action.type == SDL_ACTION_LAUNCH)
|
|
{
|
|
int len;
|
|
char* args;
|
|
char* path;
|
|
token_ptr = strtok(NULL, " ");
|
|
len = token_ptr ? SDL_strlen(token_ptr) : 0;
|
|
if(len <= 0)
|
|
{
|
|
SDLTest_LogError("Please specify the process to launch at line: %d",
|
|
linenum);
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
path = (char*)SDL_malloc(sizeof(char) * (len + 1));
|
|
if(!path)
|
|
{
|
|
SDLTest_LogError("malloc() failed");
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
SDL_strlcpy(path, token_ptr, len + 1);
|
|
|
|
token_ptr = strtok(NULL, "");
|
|
len = token_ptr ? SDL_strlen(token_ptr) : 0;
|
|
if(len > 0)
|
|
{
|
|
args = (char*)SDL_malloc(sizeof(char) * (len + 1));
|
|
if(!args)
|
|
{
|
|
SDLTest_LogError("malloc() failed");
|
|
SDL_free(path);
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
SDL_strlcpy(args, token_ptr, len + 1);
|
|
}
|
|
else
|
|
args = NULL;
|
|
|
|
action.extra.process.path = path;
|
|
action.extra.process.args = args;
|
|
}
|
|
|
|
/* add the action to the queue */
|
|
if(!SDLVisualTest_EnqueueAction(queue, action))
|
|
{
|
|
SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
|
|
if(action.type == SDL_ACTION_LAUNCH)
|
|
{
|
|
SDL_free(action.extra.process.path);
|
|
if(action.extra.process.args)
|
|
SDL_free(action.extra.process.args);
|
|
}
|
|
SDLVisualTest_EmptyActionQueue(queue);
|
|
SDL_RWclose(rw);
|
|
return 0;
|
|
}
|
|
}
|
|
/* sort the queue of actions */
|
|
SortQueue(queue);
|
|
|
|
SDL_RWclose(rw);
|
|
return 1;
|
|
} |