renaming file to PATCHES
[vimprobable2.git] / utilities.c
blob96ea52ba98413c8a65b46e5fe99f2de1fa1b446f
1 /*
2 (c) 2009 by Leon Winter
3 (c) 2009, 2010 by Hannes Schueller
4 (c) 2009, 2010 by Matto Fransen
5 (c) 2010 by Hans-Peter Deifel
6 (c) 2010 by Thomas Adam
7 see LICENSE file
8 */
10 #include "includes.h"
11 #include "vimprobable.h"
12 #include "main.h"
13 #include "utilities.h"
15 extern char commandhistory[COMMANDHISTSIZE][255];
16 extern Command *commands;
17 extern int lastcommand, maxcommands, commandpointer;
18 extern KeyList *keylistroot;
19 extern Key keys[];
20 extern char *error_msg;
21 extern gboolean complete_case_sensitive;
23 gboolean read_rcfile(const char *config)
25 int t;
26 char s[255];
27 FILE *fpin;
28 gboolean returnval = TRUE;
30 if ((fpin = fopen(config, "r")) == NULL)
31 return FALSE;
32 while (fgets(s, 254, fpin)) {
34 * ignore lines that begin with #, / and such
36 if (!isalpha(s[0]))
37 continue;
38 t = strlen(s);
39 s[t - 1] = '\0';
40 if (!process_line(s))
41 returnval = FALSE;
43 fclose(fpin);
44 return returnval;
47 void save_command_history(char *line)
49 char *c;
51 c = line;
52 while (isspace(*c) && *c)
53 c++;
54 if (!strlen(c))
55 return;
56 strncpy(commandhistory[lastcommand], c, 254);
57 lastcommand++;
58 if (maxcommands < COMMANDHISTSIZE - 1)
59 maxcommands++;
60 if (lastcommand == COMMANDHISTSIZE)
61 lastcommand = 0;
62 commandpointer = lastcommand;
65 gboolean
66 process_save_qmark(const char *bm, WebKitWebView *webview)
68 FILE *fp;
69 const char *filename;
70 const char *uri = webkit_web_view_get_uri(webview);
71 char qmarks[10][101];
72 char buf[100];
73 int i, mark, l=0;
74 Arg a;
75 mark = -1;
76 mark = atoi(bm);
77 if ( mark < 1 || mark > 9 )
79 a.i = Error;
80 a.s = g_strdup_printf("Invalid quickmark, only 1-9");
81 echo(&a);
82 return TRUE;
84 if ( uri == NULL ) return FALSE;
85 for( i=0; i < 9; ++i ) strcpy( qmarks[i], "");
87 filename = g_strdup_printf(QUICKMARK_FILE);
89 /* get current quickmarks */
91 fp = fopen(filename, "r");
92 if (fp != NULL){
93 for( i=0; i < 10; ++i ) {
94 if (feof(fp)) {
95 break;
97 fgets(buf, 100, fp);
98 l = 0;
99 while (buf[l] && l < 100 && buf[l] != '\n') {
100 qmarks[i][l]=buf[l];
101 l++;
103 qmarks[i][l]='\0';
105 fclose(fp);
108 /* save quickmarks */
109 strcpy( qmarks[mark-1], uri );
110 fp = fopen(filename, "w");
111 if (fp == NULL) return FALSE;
112 for( i=0; i < 10; ++i )
113 fprintf(fp, "%s\n", qmarks[i]);
114 fclose(fp);
115 a.i = Error;
116 a.s = g_strdup_printf("Saved as quickmark %d: %s", mark, uri);
117 echo(&a);
119 return TRUE;
122 void
123 make_keyslist(void)
125 int i;
126 KeyList *ptr, *current;
128 ptr = NULL;
129 current = NULL;
130 i = 0;
131 while ( keys[i].key != 0 )
133 current = malloc(sizeof(KeyList));
134 if (current == NULL) {
135 printf("Not enough memory\n");
136 exit(-1);
138 current->Element = keys[i];
139 current->next = NULL;
140 if (keylistroot == NULL) keylistroot = current;
141 if (ptr != NULL) ptr->next = current;
142 ptr = current;
143 i++;
147 gboolean
148 parse_colour(char *color) {
149 char goodcolor[8];
150 int colorlen;
152 colorlen = (int)strlen(color);
154 goodcolor[0] = '#';
155 goodcolor[7] = '\0';
157 /* help the user a bit by making string like
158 #a10 and strings like ffffff full 6digit
159 strings with # in front :)
162 if (color[0] == '#') {
163 switch (colorlen) {
164 case 7:
165 strncpy(goodcolor, color, 7);
166 break;
167 case 4:
168 goodcolor[1] = color[1];
169 goodcolor[2] = color[1];
170 goodcolor[3] = color[2];
171 goodcolor[4] = color[2];
172 goodcolor[5] = color[3];
173 goodcolor[6] = color[3];
174 break;
175 case 2:
176 goodcolor[1] = color[1];
177 goodcolor[2] = color[1];
178 goodcolor[3] = color[1];
179 goodcolor[4] = color[1];
180 goodcolor[5] = color[1];
181 goodcolor[6] = color[1];
182 break;
184 } else {
185 switch (colorlen) {
186 case 6:
187 strncpy(&goodcolor[1], color, 6);
188 break;
189 case 3:
190 goodcolor[1] = color[0];
191 goodcolor[2] = color[0];
192 goodcolor[3] = color[1];
193 goodcolor[4] = color[1];
194 goodcolor[5] = color[2];
195 goodcolor[6] = color[2];
196 break;
197 case 1:
198 goodcolor[1] = color[0];
199 goodcolor[2] = color[0];
200 goodcolor[3] = color[0];
201 goodcolor[4] = color[0];
202 goodcolor[5] = color[0];
203 goodcolor[6] = color[0];
204 break;
208 if (strlen (goodcolor) != 7) {
209 return FALSE;
210 } else {
211 strncpy(color, goodcolor, 8);
212 return TRUE;
216 gboolean
217 changemapping(Key * search_key, int maprecord) {
218 KeyList *current, *newkey;
220 current = keylistroot;
222 if (current)
223 while (current->next != NULL) {
224 if (
225 current->Element.mask == search_key->mask &&
226 current->Element.modkey == search_key->modkey &&
227 current->Element.key == search_key->key
229 current->Element.func = commands[maprecord].func;
230 current->Element.arg = commands[maprecord].arg;
231 return TRUE;
233 current = current->next;
235 newkey = malloc(sizeof(KeyList));
236 if (newkey == NULL) {
237 printf("Not enough memory\n");
238 exit (-1);
240 newkey->Element.mask = search_key->mask;
241 newkey->Element.modkey = search_key->modkey;
242 newkey->Element.key = search_key->key;
243 newkey->Element.func = commands[maprecord].func;
244 newkey->Element.arg = commands[maprecord].arg;
245 newkey->next = NULL;
247 if (keylistroot == NULL) keylistroot = newkey;
249 if (current != NULL) current->next = newkey;
251 return TRUE;
254 gboolean
255 mappings(const Arg *arg) {
256 char line[255];
258 if ( !arg->s ) {
259 set_error("Missing argument.");
260 return FALSE;
262 strncpy(line, arg->s, 254);
263 if (process_map_line(line))
264 return TRUE;
265 else {
266 set_error("Invalid mapping.");
267 return FALSE;
271 gboolean
272 process_mapping(char * keystring, int maprecord) {
273 Key search_key;
275 search_key.mask = 0;
276 search_key.modkey = 0;
277 search_key.key = 0;
279 if (strlen(keystring) == 1) {
280 search_key.key = keystring[0];
283 if (strlen(keystring) == 2) {
284 search_key.modkey= keystring[0];
285 search_key.key = keystring[1];
288 /* process stuff like <S-v> for Shift-v or <C-v> for Ctrl-v
289 or stuff like <S-v>a for Shift-v,a or <C-v>a for Ctrl-v,a
291 if ((strlen(keystring) == 5 || strlen(keystring) == 6) && keystring[0] == '<' && keystring[4] == '>') {
292 switch (toupper(keystring[1])) {
293 case 'S':
294 search_key.mask = GDK_SHIFT_MASK;
295 if (strlen(keystring) == 5) {
296 keystring[3] = toupper(keystring[3]);
297 } else {
298 keystring[3] = tolower(keystring[3]);
299 keystring[5] = toupper(keystring[5]);
301 break;
302 case 'C':
303 search_key.mask = GDK_CONTROL_MASK;
304 break;
306 if (!search_key.mask)
307 return FALSE;
308 if (strlen(keystring) == 5) {
309 search_key.key = keystring[3];
310 } else {
311 search_key.modkey= keystring[3];
312 search_key.key = keystring[5];
316 /* process stuff like <S-v> for Shift-v or <C-v> for Ctrl-v
317 or stuff like a<S-v> for a,Shift-v or a<C-v> for a,Ctrl-v
319 if (strlen(keystring) == 6 && keystring[1] == '<' && keystring[5] == '>') {
320 switch (toupper(keystring[2])) {
321 case 'S':
322 search_key.mask = GDK_SHIFT_MASK;
323 keystring[4] = toupper(keystring[4]);
324 break;
325 case 'C':
326 search_key.mask = GDK_CONTROL_MASK;
327 break;
329 if (!search_key.mask)
330 return FALSE;
331 search_key.modkey= keystring[0];
332 search_key.key = keystring[4];
334 return (changemapping(&search_key, maprecord));
337 gboolean
338 process_map_line(char *line) {
339 int listlen, i;
340 char *c;
341 my_pair.line = line;
342 c = search_word (0);
344 if (!strlen (my_pair.what))
345 return FALSE;
346 while (isspace (*c) && *c)
347 c++;
349 if (*c == ':' || *c == '=')
350 c++;
351 my_pair.line = c;
352 c = search_word (1);
353 if (!strlen (my_pair.value))
354 return FALSE;
355 listlen = LENGTH(commands);
356 for (i = 0; i < listlen; i++) {
357 if (strlen(commands[i].cmd) == strlen(my_pair.value) && strncmp(commands[i].cmd, my_pair.value, strlen(my_pair.value)) == 0)
358 return process_mapping(my_pair.what, i);
360 return FALSE;
363 gboolean
364 build_taglist(const Arg *arg, FILE *f) {
365 int k = 0, in_tag = 0;
366 int t = 0, marker = 0;
367 char foundtab[MAXTAGSIZE+1];
368 while (arg->s[k]) {
369 if (!isspace(arg->s[k]) && !in_tag) {
370 in_tag = 1;
371 marker = k;
373 if (isspace(arg->s[k]) && in_tag) {
374 /* found a tag */
375 t = 0;
376 while (marker < k && t < MAXTAGSIZE) foundtab[t++] = arg->s[marker++];
377 foundtab[t] = '\0';
378 fprintf(f, " [%s]", foundtab);
379 in_tag = 0;
381 k++;
383 if (in_tag) {
384 while (marker < strlen(arg->s) && t < MAXTAGSIZE) foundtab[t++] = arg->s[marker++];
385 foundtab[t] = '\0';
386 fprintf(f, " [%s]", foundtab );
388 return TRUE;
391 void
392 set_error(const char *error) {
393 /* it should never happen that set_error is called more than once,
394 * but to avoid any potential memory leaks, we ignore any subsequent
395 * error if the current one has not been shown */
396 if (error_msg == NULL) {
397 error_msg = g_strdup_printf("%s", error);
401 void
402 give_feedback(const char *feedback)
404 Arg a = { .i = Info };
406 a.s = g_strdup_printf(feedback);
407 echo(&a);
410 Listelement *
411 complete_list(const char *searchfor, const int mode, Listelement *elementlist)
413 FILE *f;
414 const char *filename;
415 Listelement *candidatelist = NULL, *candidatepointer = NULL;
416 char s[255] = "", readelement[MAXTAGSIZE + 1] = "";
417 int i, t, n = 0;
419 if (mode == 2) {
420 /* open in history file */
421 filename = g_strdup_printf(HISTORY_STORAGE_FILENAME);
422 } else {
423 /* open in bookmark file (for tags and bookmarks) */
424 filename = g_strdup_printf(BOOKMARKS_STORAGE_FILENAME);
426 f = fopen(filename, "r");
427 if (f == NULL) {
428 g_free((gpointer)filename);
429 return (NULL);
432 while (fgets(s, 254, f)) {
433 if (mode == 1) {
434 /* just tags (could be more than one per line) */
435 i = 0;
436 while (s[i] && i < 254) {
437 while (s[i] != '[' && s[i])
438 i++;
439 if (s[i] != '[')
440 continue;
441 i++;
442 t = 0;
443 while (s[i] != ']' && s[i] && t < MAXTAGSIZE)
444 readelement[t++] = s[i++];
445 readelement[t] = '\0';
446 candidatelist = add_list(readelement, candidatelist);
447 i++;
449 } else {
450 /* complete string (bookmarks & history) */
451 candidatelist = add_list(s, candidatelist);
453 candidatepointer = candidatelist;
454 while (candidatepointer != NULL) {
455 if (!complete_case_sensitive) {
456 g_strdown(candidatepointer->element);
458 if (!strlen(searchfor) || strstr(candidatepointer->element, searchfor) != NULL) {
459 /* only use string up to the first space */
460 memset(readelement, 0, MAXTAGSIZE + 1);
461 if (strchr(candidatepointer->element, ' ') != NULL) {
462 i = strcspn(candidatepointer->element, " ");
463 strncpy(readelement, candidatepointer->element, i);
464 } else {
465 strncpy(readelement, candidatepointer->element, MAXTAGSIZE);
467 elementlist = add_list(readelement, elementlist);
468 n = count_list(elementlist);
470 if (n >= MAX_LIST_SIZE)
471 break;
472 candidatepointer = candidatepointer->next;
474 free_list(candidatelist);
475 candidatelist = NULL;
476 if (n >= MAX_LIST_SIZE)
477 break;
479 g_free((gpointer)filename);
480 return (elementlist);
483 Listelement *
484 add_list(const char *element, Listelement *elementlist)
486 int n, i = 0;
487 Listelement *newelement, *elementpointer, *lastelement;
489 if (elementlist == NULL) { /* first element */
490 newelement = malloc(sizeof(Listelement));
491 if (newelement == NULL)
492 return (NULL);
493 strncpy(newelement->element, element, 254);
494 newelement->next = NULL;
495 return newelement;
497 elementpointer = elementlist;
498 n = strlen(element);
500 /* check if element is already in list */
501 while (elementpointer != NULL) {
502 if (strlen(elementpointer->element) == n &&
503 strncmp(elementpointer->element, element, n) == 0)
504 return (elementlist);
505 lastelement = elementpointer;
506 elementpointer = elementpointer->next;
507 i++;
509 /* add to list */
510 newelement = malloc(sizeof(Listelement));
511 if (newelement == NULL)
512 return (NULL);
513 lastelement->next = newelement;
514 strncpy(newelement->element, element, 254);
515 newelement->next = NULL;
516 return elementlist;
519 void
520 free_list(Listelement *elementlist)
522 Listelement *elementpointer;
524 while (elementlist != NULL) {
525 elementpointer = elementlist->next;
526 free(elementlist);
527 elementlist = elementpointer;
532 count_list(Listelement *elementlist)
534 Listelement *elementpointer = elementlist;
535 int n = 0;
537 while (elementpointer != NULL) {
538 n++;
539 elementpointer = elementpointer->next;
542 return n;