/*
* Preferences for Euler
*
* Copyright (C) 2001 Eric Boucharé <bouchare.eric@wanadoo.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <glib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* for strchr */
#include "rc.h"
static short colors[3][MAX_COLORS] = {
{255,0,100,0 ,0 ,0 ,100,150,100,50,220 ,80 ,80 ,80 ,140,190},
{255,0,0 ,100,0 ,100,100,150,100,50,80 ,220 ,80 ,140 ,140,190},
{255,0,0 ,0 ,100,100, 0,150,100,50,80 ,80 ,220 ,140 , 80,190}
};
/* define enumeration values to be returned for specific symbols */
typedef enum {
E_TOKEN_FIRST = G_TOKEN_LAST,
E_TOKEN_SAVEATEXIT,
E_TOKEN_BROWSER,
E_TOKEN_TFONT,
E_TOKEN_PFONT,
E_TOKEN_TWIDTH,
E_TOKEN_THEIGHT,
E_TOKEN_GWIDTH,
E_TOKEN_GHEIGHT,
E_TOKEN_ESTACK,
E_TOKEN_GSTACK,
E_TOKEN_GLINES,
E_TOKEN_GCOLORS,
E_TOKEN_LAST
} EulerRcTokenType;
/* symbol array */
static const struct {
gchar *name;
guint token;
} symbols[] = {
{ "saveatexit", E_TOKEN_SAVEATEXIT },
{ "browser", E_TOKEN_BROWSER },
{ "tfont", E_TOKEN_TFONT },
{ "pfont", E_TOKEN_PFONT },
{ "twidth", E_TOKEN_TWIDTH },
{ "theight", E_TOKEN_THEIGHT },
{ "gwidth", E_TOKEN_GWIDTH },
{ "gheight", E_TOKEN_GHEIGHT },
{ "estack", E_TOKEN_ESTACK },
{ "gstack", E_TOKEN_GSTACK },
{ "glines", E_TOKEN_GLINES },
{ "colors", E_TOKEN_GCOLORS }
};
static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
static guint eulerrc_parse(GScanner *scanner, EulerPrefs *prefs)
{
guint token;
token = g_scanner_get_next_token(scanner);
switch (token) {
case E_TOKEN_SAVEATEXIT:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->saveatexit = scanner->value.v_int;
break;
case E_TOKEN_BROWSER:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_STRING) return G_TOKEN_STRING;
strcpy(prefs->browser, scanner->value.v_string);
break;
case E_TOKEN_TFONT:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_STRING) return G_TOKEN_STRING;
strcpy(prefs->tfont, scanner->value.v_string);
break;
case E_TOKEN_PFONT:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_STRING) return G_TOKEN_STRING;
strcpy(prefs->pfont, scanner->value.v_string);
break;
case E_TOKEN_TWIDTH:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->twidth = scanner->value.v_int;
break;
case E_TOKEN_THEIGHT:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->theight = scanner->value.v_int;
break;
case E_TOKEN_GWIDTH:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->gwidth = scanner->value.v_int;
break;
case E_TOKEN_GHEIGHT:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->gheight = scanner->value.v_int;
break;
case E_TOKEN_ESTACK:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->estack = scanner->value.v_int;
break;
case E_TOKEN_GSTACK:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->gstack = scanner->value.v_int;
break;
case E_TOKEN_GLINES:
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->glines = scanner->value.v_int;
break;
case E_TOKEN_GCOLORS:
{
int i, j;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN;
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_LEFT_CURLY) return G_TOKEN_LEFT_CURLY;
for (j=0 ; j<MAX_COLORS ;j++) {
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_LEFT_CURLY) return G_TOKEN_LEFT_CURLY;
for (i=0 ; i<3 ; i++) {
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT) return G_TOKEN_INT;
prefs->colors[i][j] = scanner->value.v_int;
if (i!=2) {
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_COMMA) return G_TOKEN_COMMA;
}
}
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_RIGHT_CURLY) return G_TOKEN_RIGHT_CURLY;
}
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_RIGHT_CURLY) return G_TOKEN_RIGHT_CURLY;
}
break;
default:
return token;
}
return G_TOKEN_NONE;
}
static gint eulerrc_load(EulerPrefs *prefs)
{
GScanner *scanner;
gint fd;
guint i, expected_token = G_TOKEN_NONE;
gchar *filename;
filename = g_strconcat(g_get_home_dir(),"/.euler/eulerrc",NULL);
fd = open(filename, O_RDONLY);
g_free(filename);
if (fd < 0) return 0;
scanner = g_scanner_new(NULL);
/* Don't return G_TOKEN_SYMBOL, but the symbol's value */
scanner->config->symbol_2_token = TRUE;
/* Don't return G_TOKEN_IDENTIFIER, but convert it to string */
scanner->config->identifier_2_string = TRUE;
g_scanner_freeze_symbol_table(scanner);
for (i = 0; i < n_symbols; i++)
g_scanner_add_symbol(scanner,symbols[i].name,GINT_TO_POINTER(symbols[i].token));
g_scanner_thaw_symbol_table(scanner);
g_scanner_input_file(scanner, fd);
scanner->input_name = ".eulerrc";
/*
* Scanning loop, we parse the input until it's end is reached,
* the scanner encountered a lexing error, or our sub routine came
* across invalid syntax
*/
while(1) {
expected_token = eulerrc_parse(scanner,prefs);
if (expected_token != G_TOKEN_NONE) {
switch (expected_token) {
case G_TOKEN_EQUAL_SIGN:
g_scanner_unexp_token(scanner,expected_token,NULL,"=",NULL,NULL,TRUE);
break;
case G_TOKEN_EOF:
break;
default:
g_scanner_unexp_token(scanner,expected_token,NULL,NULL,NULL,NULL,TRUE);
break;
}
break;
}
}
g_scanner_destroy(scanner);
close(fd);
return 1;
}
/*
* preference init
*/
EulerPrefs eulerrc_init()
{
EulerPrefs prefs;
int i,j;
prefs.saveatexit = E_SAVEATEXIT_DEFAULT;
prefs.twidth = E_TWIDTH_DEFAULT;
prefs.theight = E_THEIGHT_DEFAULT;
prefs.gwidth = E_GWIDTH_DEFAULT;
prefs.gheight = E_GHEIGHT_DEFAULT;
prefs.estack = E_ESTACK_DEFAULT;
prefs.gstack = E_GSTACK_DEFAULT;
prefs.glines = E_GLINES_DEFAULT;
for (i=0 ; i<3 ; i++)
for (j=0 ; j<MAX_COLORS ; j++)
prefs.colors[i][j] = colors[i][j];
strcpy(prefs.browser, E_BROWSER_DEFAULT);
strcpy(prefs.tfont, E_TFONT_DEFAULT);
strcpy(prefs.pfont, E_PFONT_DEFAULT);
eulerrc_load(&prefs);
return prefs;
}
static int is_dir(char *dirname)
{
struct stat buf;
if (stat(dirname,&buf)==0) {
if (S_ISDIR(buf.st_mode))
return 1;
}
return 0;
}
/*
* Preferences memory-deallocation
* (Call this one at exit time)
*/
void eulerrc_save(EulerPrefs *prefs)
{
FILE *file;
char *filename, *dirname;
dirname = g_strconcat(g_get_home_dir(),"/.euler",NULL);
if (!is_dir(dirname)) {
mkdir(dirname,0755);
}
g_free(dirname);
filename = g_strconcat(g_get_home_dir(),"/.euler/eulerrc",NULL);
file = fopen(filename, "w");
g_free(filename);
if (file) {
int i,j;
fprintf(file,"#\n# Euler ressouce file\n#\n");
fprintf(file,"#\n# flag to tell Euler if it must save the preferences when the program exits.\n#\n");
fprintf(file,"saveatexit = %d\n",prefs->saveatexit);
fprintf(file,"\n#\n# browser for documentation viewing\n#\n");
fprintf(file,"browser = \"%s\"\n",prefs->browser);
fprintf(file,"\n#\n# text window font\n#\n");
fprintf(file,"tfont = \"%s\"\n",prefs->tfont);
fprintf(file,"\n#\n# editor font\n#\n");
fprintf(file,"pfont = \"%s\"\n",prefs->pfont);
fprintf(file,"\n#\n# text window width and height (in chars)\n#\n");
fprintf(file,"twidth = %d\ntheight = %d\n",prefs->twidth,prefs->theight);
fprintf(file,"\n#\n# graphics window width and height (in pixels)\n#\n");
fprintf(file,"gwidth = %d\ngheight = %d\n",prefs->gwidth,prefs->gheight);
fprintf(file,"\n#\n# Euler stack size in kbyte\n#\n");
fprintf(file,"estack = %d\n",prefs->estack);
fprintf(file,"\n#\n# graphic stack in kbyte\n#\n");
fprintf(file,"gstack = %d\n",prefs->gstack);
fprintf(file,"\n#\n# glines fixes the font size for the graphics window\n# the font size is gheight / glines.\n#\n");
fprintf(file,"glines = %d\n",prefs->glines);
fprintf(file,"\n#\n# the 16 basic colors used for the graphics\n#\n");
fprintf(file,"colors = {\n");
for (j=0 ; j<MAX_COLORS ; j++) {
fprintf(file," { ");
for (i=0 ; i<3 ; i++) {
fprintf(file,"%3d ",prefs->colors[i][j]);
if (i!=2) fprintf(file,", ");
}
fprintf(file,"}\n");
}
fprintf(file,"}\n");
fclose(file);
}
}
syntax highlighted by Code2HTML, v. 0.9.1