058f392c0f9b3c41c231f50c32ba2301bb5ef149
[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 - 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         p = (void *)*ip;
35
36         int i;
37         int num_record = 0;
38         int num_field = 0;
39         
40         int *field_index = 0;
41
42         char buffer [MAXBUFFER];
43         char line_buffer [MAXBUFFER];
44         const char ignore[] = " \t\n";
45         const char *delimiter_first, *delimiter_last;
46         char *token;
47
48 /* Previously allocated memory for the program names must be released
49    on subsequent reads of the config file. At program start the flag is 0 */
50
51         if (reread_config) {
52                 for (i = 0; i < num_list; i++, p++) {
53                         free(p->class_name);
54                 }
55                 p = (void *)*ip;
56         }
57         reread_config = 1;
58         num_list = 0;
59
60 /* Begin by making sure that the Config File Version number is present before
61    a record begins. We exit if it's lacking or the number doesn't match up */
62
63 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
64
65         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
66                 if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
67                         strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
68                         strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
69                         strcpy(line_buffer, buffer);
70                 }
71                 if ((delimiter_first = (strchr(line_buffer, '%'))) != NULL &&
72                 (delimiter_last = (strrchr(line_buffer, '%'))) != NULL &&
73                 (delimiter_last != delimiter_first)) {
74                         return 3;
75                 }
76                 if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
77                         strcpy(buffer, line_buffer);
78                         token = strtok(buffer, ":");
79                         token = strtok(NULL, ignore);
80                         strcpy(buffer, token);
81                         if (be_verbose) {
82                                 fprintf(stderr, "Config File Version on disk = %s Expected = %d\n", buffer, CONFIG_VERSION);
83                         }
84                         if ((atoi(buffer)) != CONFIG_VERSION) {
85                                 return 3;
86                         }
87                         break;
88                 }
89         }
90
91 /* Read the config file in one go from top to bottom. Parse out the info
92    between record start "%%" and record end "%%". Recognize field beginnings
93    by a colon ":". Each full record is written to a global memory structure,
94    while partial records are discarded and excessive fields are truncated.
95    No sanity check on program names or keycode functionality is performed
96    A global counter variable of full record instances is updated before the
97    function exits to reflect the new state. */
98
99 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
100
101         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
102                 if (num_record < MAXRECORDS) {
103                         if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
104                                 strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
105                                 strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
106                                 strcpy(line_buffer, buffer);
107                         }
108                         if ((delimiter_first = (strchr(line_buffer, '%'))) == NULL &&
109                         (delimiter_last = (strrchr(line_buffer, '%'))) == NULL &&
110                         (delimiter_last == delimiter_first)) {
111                                 if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
112                                         if ((delimiter_first = (strchr(line_buffer, '"'))) != NULL) {
113                                                 strcpy(buffer, line_buffer);
114                                                 token = strtok(buffer, "\t\n");
115                                                 while ((delimiter_first = (strchr(token, '"'))) == NULL) {
116                                                         token = strtok(NULL, "\t\n");
117                                                 }
118                                                 if (((delimiter_last = (strrchr(token, '"'))) != NULL) &&
119                                                 (delimiter_last != delimiter_first)) {
120                                                         strncpy(buffer, delimiter_first+1, ((delimiter_last) - (delimiter_first + 1)));
121                                                         strncpy(buffer + ((delimiter_last) - (delimiter_first + 1)), "\0", 1);
122                                                         if ((p->class_name = (char *)malloc(strlen(buffer)+1)) == NULL) {
123                                                                 return 2;
124                                                         }
125                                                         sprintf(p->class_name, "%s", buffer);
126                                                         if (be_verbose) {
127                                                                 fprintf(stderr, "PGR RECNAME = %s\n", buffer);
128                                                         }
129                                                         field_index = &p->handle_touch;
130
131 /* FIXME Unpredictable behaviour on lines longer than MAXBUFFER etc. See BUGS */
132
133                                                         while ((fgets(line_buffer, MAXBUFFER, fp)) != NULL) {
134                                                                 if ((delimiter_first = (strchr(line_buffer, '%'))) != NULL &&
135                                                                 (delimiter_last = (strrchr(line_buffer, '%'))) != NULL &&
136                                                                 (delimiter_last != delimiter_first)) {
137                                                                         break;
138                                                                 }
139                                                                 if (num_field < MAXFIELDS) {
140                                                                         if ((delimiter_first = (strchr(line_buffer, '#'))) != NULL) {
141                                                                                 strncpy(buffer, line_buffer, ((delimiter_first) - (line_buffer)));
142                                                                                 strncpy(buffer + ((delimiter_first) - (line_buffer)), "\0", 1);
143                                                                                 strcpy(line_buffer, buffer);
144                                                                         }
145                                                                         if ((delimiter_first = (strchr(line_buffer, ':'))) != NULL) {
146                                                                                 strcpy(buffer, line_buffer);
147                                                                                 token = strtok(buffer, ":");
148                                                                                 token = strtok(NULL, ignore);
149                                                                                 strcpy(buffer, token);
150                                                                                 *field_index = atoi(buffer);
151                                                                                 field_index++;
152                                                                                 num_field++;
153                                                                         }
154                                                                 }
155                                                         }
156                                                         if (num_field == MAXFIELDS) {
157                                                                 num_record++;
158                                                                 p++;
159                                                         } else {
160                                                                 if (be_verbose) {
161                                                                         fprintf(stderr, "%s skipped! (fields were too few)\n", p->class_name);
162                                                                 }
163                                                                 free(p->class_name);
164                                                         }
165                                                         num_field = 0;
166                                                 }
167                                         }
168                                 }
169                         }
170                 }
171         }
172         if (!num_record) {
173                 return 1;
174         }
175         num_list = num_record;
176
177         if (be_verbose) {
178                 fprintf(stderr, "PGR RECORDS = %d\n", num_list);
179         }
180
181         return 0;
182 }
183
184 /* End Code */
185