332 lines
6.5 KiB
C
332 lines
6.5 KiB
C
/*
|
|
* rcfuncs - routines to parse generic RC files
|
|
* tengel@sonic.net
|
|
*
|
|
* This is taken from the LiteStep Shell Source code
|
|
* (http://www.litestep.net) and modified a bunch to meet
|
|
* our RC needs along with using gdk.
|
|
*
|
|
* This code is distributed under the terms of the GNU
|
|
* General Public License, etc etc. Use it, don't abuse it.
|
|
* See the file "Copying" for the entire GNU Public
|
|
* License policy.
|
|
*/
|
|
|
|
#include <gdk/gdk.h>
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "rcfuncs.h"
|
|
|
|
#ifndef MAX_BUFF
|
|
#define MAX_BUFF 1024
|
|
#endif
|
|
|
|
static gchar **RCBuffer = NULL;
|
|
static gint RCLen = 0;
|
|
|
|
FILE* RCOpen(const gchar *szFile)
|
|
{
|
|
FILE *f = NULL;
|
|
|
|
if (!szFile)
|
|
return f;
|
|
|
|
/* make sure to open in text mode; in MS ANSI C,
|
|
* this will map our \n and \r\n for us. Valid
|
|
* in unix? */
|
|
f = fopen(szFile, "rt");
|
|
if (f)
|
|
fseek(f, 0, SEEK_SET);
|
|
|
|
return f;
|
|
}
|
|
|
|
BOOL RCClose(FILE *f)
|
|
{
|
|
if (f)
|
|
fclose (f);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Parses szString, splitting it up into tokens. Pays
|
|
* attention to single and double quotes. */
|
|
gint RCTokenize(const gchar *szString, gchar **lpszBuffers, DWORD dwNumBuffers, gchar *szExtraParameters)
|
|
{
|
|
gint index = 0;
|
|
gchar quoteChar = 0;
|
|
gchar buffer[MAX_BUFF];
|
|
gchar output[MAX_BUFF];
|
|
gchar *pOutput = NULL;
|
|
DWORD dwBufferCount = 0;
|
|
|
|
strcpy(buffer, szString);
|
|
pOutput = output;
|
|
|
|
while (buffer[index] && dwBufferCount < dwNumBuffers) {
|
|
BOOL skipWhitespace = FALSE;
|
|
|
|
switch (buffer[index]) {
|
|
case '"':
|
|
case '\'':
|
|
{
|
|
if (!quoteChar) {
|
|
quoteChar = buffer[index];
|
|
break;
|
|
} else {
|
|
if (quoteChar == buffer[index]) {
|
|
quoteChar = 0;
|
|
strcpy (*lpszBuffers, output);
|
|
lpszBuffers++;
|
|
dwBufferCount++;
|
|
|
|
if (dwBufferCount < dwNumBuffers)
|
|
(*lpszBuffers)[0] = '\0';
|
|
|
|
pOutput = output;
|
|
*pOutput = '\0';
|
|
skipWhitespace = TRUE;
|
|
break;
|
|
} else {
|
|
*pOutput++ = buffer[index];
|
|
*pOutput = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
case ' ':
|
|
case '\t':
|
|
{
|
|
if (!quoteChar) {
|
|
if (strlen (output)) {
|
|
strcpy (*lpszBuffers, output);
|
|
lpszBuffers++;
|
|
dwBufferCount++;
|
|
|
|
if (dwBufferCount < dwNumBuffers)
|
|
(*lpszBuffers)[0] = '\0';
|
|
|
|
pOutput = output;
|
|
*pOutput = '\0';
|
|
skipWhitespace = TRUE;
|
|
}
|
|
} else {
|
|
*pOutput++ = buffer[index];
|
|
*pOutput = '\0';
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
*pOutput++ = buffer[index];
|
|
*pOutput = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
index++;
|
|
if (skipWhitespace) {
|
|
while(isspace(buffer[index])) {
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strlen (output)) {
|
|
if (dwBufferCount < dwNumBuffers) {
|
|
dwBufferCount++;
|
|
strcat(*lpszBuffers, output);
|
|
}
|
|
}
|
|
|
|
if (szExtraParameters && dwBufferCount == dwNumBuffers)
|
|
strcpy (szExtraParameters, buffer + index);
|
|
|
|
return dwBufferCount;
|
|
}
|
|
|
|
gchar* RCFindLine(const gchar *lpKeyName)
|
|
{
|
|
gint i;
|
|
gint l = strlen(lpKeyName);
|
|
|
|
for (i = 0; i < RCLen; i++) {
|
|
if (!strnicmp(RCBuffer[i], lpKeyName, l))
|
|
return RCBuffer[i];
|
|
}
|
|
|
|
return (gchar *) 0;
|
|
}
|
|
|
|
gint RCGetInt(const gchar *lpKeyName, gint nDefault)
|
|
{
|
|
gint val = nDefault;
|
|
gchar *line = NULL;
|
|
gchar token1[MAX_BUFF], token2[MAX_BUFF];
|
|
gchar *tokens[2];
|
|
|
|
tokens[0] = token1;
|
|
tokens[1] = token2;
|
|
line = RCFindLine(lpKeyName);
|
|
if (line) {
|
|
gint count = 0;
|
|
token1[0] = token2[0] = '\0';
|
|
count = RCTokenize(line, tokens, 2, NULL);
|
|
if (count < 2)
|
|
return val;
|
|
val = atoi(token2);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
BOOL RCGetBool(const gchar *lpKeyName, BOOL ifFound)
|
|
{
|
|
gchar token1[MAX_BUFF], token2[MAX_BUFF];
|
|
gchar *tokens[2];
|
|
gchar *line = NULL;
|
|
|
|
tokens[0] = token1;
|
|
tokens[1] = token2;
|
|
line = RCFindLine(lpKeyName);
|
|
if (line) {
|
|
gint count = 0;
|
|
token1[0] = token2[0] = '\0';
|
|
count = RCTokenize (line, tokens, 2, NULL);
|
|
if (count < 2)
|
|
return ifFound;
|
|
if (strnicmp (token2, "OFF", 3) == 0)
|
|
return FALSE;
|
|
else
|
|
return TRUE; /* ON */
|
|
}
|
|
return (ifFound);
|
|
}
|
|
|
|
BOOL RCGetString(const gchar *lpKeyName, gchar *value, const gchar *defStr, gint maxLen)
|
|
{
|
|
gchar token1[MAX_BUFF], token2[MAX_BUFF];
|
|
gchar *tokens[2];
|
|
gchar *line = NULL;
|
|
|
|
tokens[0] = token1;
|
|
tokens[1] = token2;
|
|
strncpy(value, defStr, maxLen);
|
|
line = RCFindLine(lpKeyName);
|
|
if (line) {
|
|
gint count = 0;
|
|
token1[0] = token2[0] = '\0';
|
|
count = RCTokenize (line, tokens, 2, NULL);
|
|
if (count < 2)
|
|
return FALSE;
|
|
RCVarExpansion(value, token2);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void RCVarExpansion(gchar *buffer, const gchar *value)
|
|
{
|
|
gint i=0, j=0;
|
|
gchar *startDollar, *endDollar;
|
|
gchar *string1;
|
|
gchar buf[255];
|
|
gchar buf2[255];
|
|
|
|
strcpy(buffer, value);
|
|
if (startDollar = strchr(value, '$')) {
|
|
if (endDollar = strchr(&startDollar[1], '$')) {
|
|
i = strlen(startDollar) - strlen(endDollar) - 1;
|
|
j = strlen(value) - strlen(startDollar);
|
|
string1 = startDollar;
|
|
string1++;
|
|
strncpy(buf, string1, i);
|
|
buf[i]='\0';
|
|
|
|
RCGetString(buf, buf2, buf, 255);
|
|
if (value != startDollar) {
|
|
strncpy(buffer, value, j);
|
|
buffer[j] = '\0';
|
|
} else {
|
|
strcpy(buffer, "");
|
|
}
|
|
strcat(buffer, buf2);
|
|
strcat(buffer, ++endDollar);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL RCReadNextLine (FILE *f, gchar *szBuffer, DWORD dwLength)
|
|
{
|
|
while (f && !feof (f)) {
|
|
gint length;
|
|
|
|
if (!fgets(szBuffer, dwLength, f))
|
|
break;
|
|
|
|
length = strlen(szBuffer);
|
|
|
|
// Skip any leading and trailing whitespace
|
|
while (length && isspace(szBuffer[0])) {
|
|
length--;
|
|
strcpy(szBuffer, szBuffer + 1);
|
|
}
|
|
|
|
while (length && isspace(szBuffer[length-1]))
|
|
szBuffer[--length] = '\0';
|
|
|
|
if (length && szBuffer[0] != '#')
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL RCInit(const gchar *szPath)
|
|
{
|
|
FILE* rc;
|
|
gchar buffer[MAX_BUFF];
|
|
|
|
if (RCLen)
|
|
return FALSE;
|
|
|
|
rc = RCOpen(szPath);
|
|
if (!(rc))
|
|
return FALSE;
|
|
|
|
while (RCReadNextLine(rc, buffer, sizeof (buffer))) {
|
|
gchar *temp;
|
|
|
|
if (buffer[0] == '*')
|
|
continue;
|
|
|
|
temp = g_malloc(strlen(buffer) + 1);
|
|
strcpy(temp, buffer);
|
|
|
|
if (!RCBuffer)
|
|
RCBuffer = g_malloc((RCLen + 1) * sizeof(gchar *));
|
|
else
|
|
RCBuffer = g_realloc(RCBuffer, (RCLen + 1) * sizeof(gchar *));
|
|
|
|
RCBuffer[RCLen++] = temp;
|
|
}
|
|
|
|
return RCClose(rc);
|
|
}
|
|
|
|
void RCShutDown(void)
|
|
{
|
|
gint loop;
|
|
|
|
for (loop = 0; loop < RCLen; ++loop)
|
|
g_free(RCBuffer[loop]);
|
|
|
|
if (RCBuffer) {
|
|
g_free(RCBuffer);
|
|
RCBuffer = NULL;
|
|
}
|
|
|
|
RCLen = 0;
|
|
}
|