version 0.2.5
[expresskeys.git] / src-expresskeys / config_read.c
1 /*
2  config_read.c -- Support ExpressKeys & Touch Strips on a Wacom Intuos3 tablet.
3  
4  Copyright (C) 2005-2006 - Mats Johannesson
5  
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15  
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21 #include "globals.h"
22
23 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24  Function reads a configuration file containing program names and
25  definitions of which keys that should be mapped to pad buttons and
26  touch strips. It takes a file pointer and a pointer to a global
27  structure as input. Returns nothing unless an error occured.
28  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
29
30 int read_file_config(int *ip, FILE *fp)
31 {
32
33         struct program *p;
34         
35         /* Convert to long for x86_64 systems */
36         p = (void *)(long)*ip;
37
38         int i;
39         int num_record = 0;
40         int num_field = 0;
41         
42         int *field_index = 0;
43
44         char buffer [MAXBUFFER];
45         char line_buffer [MAXBUFFER];
46         const char ignore[] = " \t\n";
47         const char *delimiter_first, *delimiter_last;
48         char *token;
49
50 /* Previously allocated memory for the program names must be released
51    on subsequent reads of the config file. At program start the flag is 0 */
52
53         if (reread_config) {
54                 for (i = 0; i < num_list; i++, p++) {
55                         free(p->class_name);
56                 }
57                 /* Convert to long for x86_64 systems */
58                 p = (void *)(long)*ip;
59         }
60         reread_config = 1;
61         num_list = 0;
62
63 /* Begin by making sure that the Config File Version number is present before
64    a record begins. We exit if it's lacking or the number doesn't match up */
65
66 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
67
68         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
69                 if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
70                         strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
71                         strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
72                         strcpy(line_buffer, buffer);
73                 }
74                 if ((delimiter_first = (strchr(line_buffer, '%'))) != NULL &&
75                 (delimiter_last = (strrchr(line_buffer, '%'))) != NULL &&
76                 (delimiter_last != delimiter_first)) {
77                         return 3;
78                 }
79                 if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
80                         strcpy(buffer, line_buffer);
81                         token = strtok(buffer, ":");
82                         token = strtok(NULL, ignore);
83                         strcpy(buffer, token);
84                         if (be_verbose) {
85                                 fprintf(stderr, "Config File Version on disk = %s Expected = %d\n", buffer, CONFIG_VERSION);
86                         }
87                         if ((atoi(buffer)) != CONFIG_VERSION) {
88                                 return 3;
89                         }
90                         break;
91                 }
92         }
93
94 /* Read the config file in one go from top to bottom. Parse out the info
95    between record start "%%" and record end "%%". Recognize field beginnings
96    by a colon ":". Each full record is written to a global memory structure,
97    while partial records are discarded and excessive fields are truncated.
98    No sanity check on program names is performed and only a basic control
99    of the keycodes is in place - it filters out anything below 9 [Esc]. 
100    A global counter variable of full record instances is updated before the
101    function exits to reflect the new state. */
102
103 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
104
105         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
106                 if (num_record < MAXRECORDS) {
107                         if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
108                                 strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
109                                 strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
110                                 strcpy(line_buffer, buffer);
111                         }
112                         if ((delimiter_first = (strchr(line_buffer, '%'))) == NULL &&
113                         (delimiter_last = (strrchr(line_buffer, '%'))) == NULL &&
114                         (delimiter_last == delimiter_first)) {
115                                 if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
116                                         if ((delimiter_first = (strchr(line_buffer, '"'))) != NULL) {
117                                                 strcpy(buffer, line_buffer);
118                                                 token = strtok(buffer, "\t\n");
119                                                 while ((delimiter_first = (strchr(token, '"'))) == NULL) {
120                                                         token = strtok(NULL, "\t\n");
121                                                 }
122                                                 if (((delimiter_last = (strrchr(token, '"'))) != NULL) &&
123                                                 (delimiter_last != delimiter_first)) {
124                                                         strncpy(buffer, delimiter_first+1, ((delimiter_last) - (delimiter_first + 1)));
125                                                         strncpy(buffer + ((delimiter_last) - (delimiter_first + 1)), "\0", 1);
126                                                         if ((p->class_name = (char *)malloc(strlen(buffer)+1)) == NULL) {
127                                                                 return 2;
128                                                         }
129                                                         sprintf(p->class_name, "%s", buffer);
130                                                         if (be_verbose) {
131                                                                 fprintf(stderr, "PGR RECNAME = %s\n", buffer);
132                                                         }
133                                                         field_index = &p->handle_touch;
134
135 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
136
137                                                         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
138                                                                 if ((delimiter_first = (strchr(line_buffer, '%'))) != NULL &&
139                                                                 (delimiter_last = (strrchr(line_buffer, '%'))) != NULL &&
140                                                                 (delimiter_last != delimiter_first)) {
141                                                                         break;
142                                                                 }
143                                                                 if (num_field < MAXFIELDS) {
144                                                                         if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
145                                                                                 strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
146                                                                                 strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
147                                                                                 strcpy(line_buffer, buffer);
148                                                                         }
149                                                                         if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
150                                                                                 strcpy(buffer, line_buffer);
151                                                                                 token = strtok(buffer, ":");
152                                                                                 token = strtok(NULL, ignore);
153                                                                                 strcpy(buffer, token);
154
155 /* FIXME Only a basic control of the keycodes is in place - it filters out anything below 9 [Esc] and above 0 */
156
157                                                                                 if (field_index == &p->handle_touch) {
158                                                                                         if ((atoi(buffer) == 1) || (atoi(buffer) == 0)) {
159                                                                                                 *field_index = atoi(buffer);
160                                                                                         } else {
161                                                                                                 *field_index = 0;
162                                                                                                 if (be_verbose) {
163                                                                                                         fprintf(stderr, "Illegal keycode (not 0 or 1) in Handle Touch Strips field <-- keycode IGNORED\n");
164                                                                                                 }
165                                                                                         }
166                                                                                 } else {
167                                                                                         if ((atoi(buffer) > 8) || (atoi(buffer) == 0)) {
168                                                                                                 *field_index = atoi(buffer);
169                                                                                         } else {
170                                                                                                 *field_index = 0;
171                                                                                                 if (be_verbose) {
172                                                                                                         fprintf(stderr, "Illegal keycode (not 0 or above 8) encountered in a field <-- keycode IGNORED\n");
173                                                                                                 }
174                                                                                         }
175                                                                                 }
176                                                                                 field_index++;
177                                                                                 num_field++;
178                                                                         }
179                                                                 }
180                                                         }
181                                                         if (num_field == MAXFIELDS) {
182                                                                 num_record++;
183                                                                 p++;
184                                                         } else {
185                                                                 if (be_verbose) {
186                                                                         fprintf(stderr, "%s skipped! (fields were too few)\n", p->class_name);
187                                                                 }
188                                                                 free(p->class_name);
189                                                         }
190                                                         num_field = 0;
191                                                 }
192                                         }
193                                 }
194                         }
195                 }
196         }
197         if (!num_record) {
198                 return 1;
199         }
200         num_list = num_record;
201
202         if (be_verbose) {
203                 fprintf(stderr, "PGR RECORDS = %d\n", num_list);
204         }
205
206         return 0;
207 }
208
209 /* End Code */
210