root/climm/src/util_opts.c

Revision 2838, 14.9 kB (checked in by kuhlmann, 7 months ago)

* if ressource conflict happens, set a flag before reconnect to append random digits to the ressource * add savable flag for the same * change default ressource from "iks" to "climm"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Option handling within climm.
3  *
4  * climm Copyright (C) © 2003-2007 RÃŒdiger Kuhlmann
5  *
6  * climm is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 dated June, 1991.
9  *
10  * climm is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
13  * License for more details.
14  *
15  * In addition, as a special exception permission is granted to link the
16  * code of this release of climm with the OpenSSL project's "OpenSSL"
17  * library, and distribute the linked executables.  You must obey the GNU
18  * General Public License in all respects for all of the code used other
19  * than "OpenSSL".  If you modify this file, you may extend this exception
20  * to your version of the file, but you are not obligated to do so.  If you
21  * do not wish to do so, delete this exception statement from your version
22  * of this file.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this package; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  * 02111-1307, USA.
28  *
29  * $Id$
30  */
31                              
32 #include "climm.h"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include "util_opts.h"
36 #include "util_parse.h"
37 #include "conv.h"
38 #include "util_ui.h"
39 #include "preferences.h"
40
41 static char **strtable = NULL;
42 static int strmax = 0;
43 static int struse = 0;
44 static int strmin = 0;
45
46 typedef struct OptTable_s COT;
47
48 struct OptEntry_s OptList[] = {
49   { "intimate",      CO_INTIMATE      },
50   { "hidefrom",      CO_HIDEFROM      },
51   { "ignore",        CO_IGNORE        },
52   { "logonoff",      CO_LOGONOFF      },
53   { "logchange",     CO_LOGCHANGE     },
54   { "logmess",       CO_LOGMESS       },
55   { "showonoff",     CO_SHOWONOFF     },
56   { "showchange",    CO_SHOWCHANGE    },
57   { "autoauto",      CO_AUTOAUTO      },
58   { "logstream",     CO_LOGSTREAM     },
59   { "hideack",       CO_HIDEACK       },
60   { "wantsbl",       CO_WANTSBL       },
61   { "peekme",        CO_PEEKME        },
62   { "obeysbl",       CO_OBEYSBL       },
63   { "awaycount",     CO_AWAYCOUNT     },
64   { "shadow",        CO_SHADOW        },
65   { "local",         CO_LOCAL         },
66   { "webaware",      CO_WEBAWARE      },
67   { "hideip",        CO_HIDEIP        },
68   { "dcauth",        CO_DCAUTH        },
69   { "dccont",        CO_DCCONT        },
70   { "tagressource",  CO_TAGRESSOURCE  },
71   { "revealtime",    CO_REVEALTIME    },
72   { "autoaway",      CO_AUTOAWAY      },
73   { "autona",        CO_AUTONA        },
74   { "autoocc",       CO_AUTOOCC       },
75   { "autodnd",       CO_AUTODND       },
76   { "autoffc",       CO_AUTOFFC       },
77   { "colornone",     CO_COLORNONE     },
78   { "colorserver",   CO_COLORSERVER   },
79   { "colorclient",   CO_COLORCLIENT   },
80   { "colorerror",    CO_COLORERROR    },
81   { "colordebug",    CO_COLORDEBUG    },
82   { "colorquote",    CO_COLORQUOTE    },
83   { "colorinvchar",  CO_COLORINVCHAR  },
84   { "colormessage",  CO_COLORMESSAGE  },
85   { "colorincoming", CO_COLORINCOMING },
86   { "colorsent",     CO_COLORSENT     },
87   { "colorack",      CO_COLORACK      },
88   { "colorcontact",  CO_COLORCONTACT  },
89   { "encoding",      CO_ENCODINGSTR   }, /* not CO_ENCODING */
90   { "colorscheme",   CO_CSCHEME       },
91   { "tabspool",      CO_TABSPOOL      },
92   { "timeseen",      CO_TIMESEEN      },
93   { "timeonline",    CO_TIMEONLINE    },
94   { "timeclimm",     CO_TIMECLIMM     },
95   { "oscar_dc_mode", CO_OSCAR_DC_MODE },
96   { "oscar_dc_port", CO_OSCAR_DC_PORT },
97   { "scripting",     CO_SCRIPT        },
98   { "scriptingpath", CO_SCRIPT_PATH   },
99   { "s5_use",        CO_S5USE         },
100   { "s5_port",       CO_S5PORT        },
101   { "s5_host",       CO_S5HOST        },
102   { "s5_name",       CO_S5NAME        },
103   { "s5_pass",       CO_S5PASS        },
104 #ifdef ENABLE_OTR
105   { "otrpolicy",     CO_OTRPOLICY     },
106 #endif
107   { NULL, 0 }
108 };
109
110 /*
111  * Create new contact options
112  */
113 Opt *OptC (void)
114 {
115     return calloc (sizeof (Opt), 1);
116 }
117
118 /*
119  * Delete contact options
120  */
121 void OptD (Opt *opt)
122 {
123     Opt *cot;
124     UDWORD flag;
125     val_t val;
126     int i;
127
128     if (!opt)
129         return;
130     for (i = 0; OptList[i].name; i++)
131     {
132         if (~(flag = OptList[i].flag) & (COF_STRING | COF_COLOR))
133             continue;
134         if ((val = OptUndef (opt, flag)))
135         {
136             free (strtable[val]);
137             strtable[val] = NULL;
138             if (val + 1 == struse)
139                 while (!strtable[val])
140                     val--, struse--;
141             if (val < strmin)
142                 strmin = val;
143         }
144     }
145     while (opt)
146     {
147         cot = opt->next;
148         free (opt);
149         opt = cot;
150     }
151 }
152
153 /*
154  * Import options from a string.
155  */
156 int OptImport (Opt *opts, const char *args)
157 {
158     strc_t par;
159     char *argst;
160     const char *argstt;
161     UDWORD flag = 0;
162     int i, ret = 0;
163    
164     argst = strdup (args);
165     argstt = argst;
166    
167     while ((par = s_parse (&argstt)))
168     {
169         for (i = 0; OptList[i].name; i++)
170             if (!strcmp (par->txt, OptList[i].name))
171             {
172                 flag = OptList[i].flag;
173                 break;
174             }
175        
176         if (!OptList[i].name)
177         {
178             ret = 1;
179             break;
180         }
181        
182         if (!(par = s_parse (&argstt)))
183         {
184             ret = 1;
185             break;
186         }
187        
188         if (flag & COF_COLOR)
189         {
190             char *color = strdup (par->txt);
191             OptSetStr (opts, flag, OptC2S (color));
192             OptUndef  (opts, CO_CSCHEME);
193             free (color);
194         }
195         else if (flag == CO_ENCODINGSTR)
196         {
197             UWORD enc = ConvEnc (par->txt) & ~ENC_FLAGS;
198             OptSetVal (opts, CO_ENCODING, enc);
199             OptSetStr (opts, CO_ENCODINGSTR, ConvEncName (enc));
200         }
201         else if (flag & COF_NUMERIC)
202         {
203             val_t val = atoll (par->txt);
204            
205             if (flag == CO_CSCHEME)
206                 OptImport (opts, PrefSetColorScheme (val));
207            
208             OptSetVal (opts, flag, val);
209         }
210         else if (~flag & COF_BOOL)
211             OptSetStr (opts, flag, par->txt);
212         else if (!strcasecmp (par->txt, "on")  || !strcasecmp (par->txt, i18n (1085, "on")))
213             OptSetVal (opts, flag, 1);
214         else if (!strcasecmp (par->txt, "off") || !strcasecmp (par->txt, i18n (1086, "off")))
215             OptSetVal (opts, flag, 0);
216         else if (!strcasecmp (par->txt, "undef"))
217             OptUndef (opts, flag);
218         else
219         {
220             ret = 1;
221             break;
222         }
223     }
224     free (argst);
225     return ret;
226 }
227
228 /*
229  * Export options into a string.
230  */
231 const char *OptString (const Opt *opts)
232 {
233     static str_s str;
234     int i, flag;
235     val_t val = 0;
236    
237     s_init (&str, "", 100);
238    
239     for (i = 0; OptList[i].name; i++)
240         if (OptGetVal (opts, flag = OptList[i].flag, &val))
241         {
242             if (flag & COF_BOOL)
243             {
244                 if (!*str.txt)
245                     s_cat (&str, "options");
246                 s_catf (&str, " %s %s", OptList[i].name, val ? "on" : "off");
247             }
248             else
249             {
250                 if (*str.txt)
251                     s_catc (&str, '\n');
252                 if (flag & COF_NUMERIC)
253                     s_catf (&str, "options %s %lu", OptList[i].name, UD2UL (val));
254                 else if (flag & COF_COLOR)
255                     s_catf (&str, "options %s %s", OptList[i].name, s_quote (OptS2C (strtable[val])));
256                 else
257                     s_catf (&str, "options %s %s", OptList[i].name, s_quote (strtable[val]));
258             }
259         }
260     if (*str.txt)
261         s_catc (&str, '\n');
262
263     return str.txt;
264 }
265
266 /*
267  * Get a (string) contact option.
268  */
269 #undef OptGetStr
270 BOOL OptGetStr (const Opt *opt, UDWORD flag, const char **res DEBUGPARAM)
271 {
272     val_t val = 0;
273
274     assert (flag & (COF_STRING | COF_COLOR));
275
276     if (!OptGetVal (opt, flag, &val))
277         return FALSE;
278
279     if (val >= strmax)
280         return FALSE;
281
282     *res = strtable[val];
283     if (~flag & 0x80)
284         Debug (DEB_OPTS, "(%p,%lx) = %s", opt, UD2UL (flag), s_quote (*res));
285     return TRUE;
286 }
287
288 /*
289  * Set several contact options at once
290  */
291 Opt *OptSetVals (Opt *opt, UDWORD flag, ...)
292 {
293     const char *text;
294     va_list args;
295     val_t val;
296    
297     va_start (args, flag);
298     if (!opt)
299         opt = OptC ();
300     while (flag)
301     {
302         if (flag & COF_STRING)
303         {
304             text = va_arg (args, const char *);
305             OptSetStr (opt, flag, text);
306         }
307         else
308         {
309             val = va_arg (args, val_t);
310             OptSetVal (opt, flag, val);
311         }
312         flag = va_arg (args, UDWORD);
313     }
314     va_end (args);
315     return opt;
316 }
317
318 /*
319  * Set a (string) contact option.
320  */
321 #undef OptSetStr
322 BOOL OptSetStr (Opt *opt, UDWORD flag, const char *text DEBUGPARAM)
323 {
324     val_t val;
325
326     assert (flag & (COF_STRING | COF_COLOR));
327    
328     if ((val = OptUndef (opt, flag)))
329     {
330         free (strtable[val]);
331         strtable[val] = NULL;
332         if (val < strmin)
333             strmin = val;
334     }
335     if (!text)
336         return TRUE;
337
338     val = strmin;
339     while (val < strmax && strtable[val])
340        val++;
341     strmin = val + 1;
342    
343     if (val == strmax)
344     {
345         int j, news = (strmax ? strmax * 2 : 128);
346         char **new = realloc (strtable, sizeof (char *) * news);
347         if (!new)
348             return FALSE;
349         for (j = strmax; j < news; j++)
350             new[j] = NULL;
351         strtable = new;
352         strmax = news;
353     }
354     if (!(strtable[val] = strdup (text)))
355         return FALSE;
356    
357     Debug (DEB_OPTS, "(%p,%lx) := %ld / %s", opt, UD2UL (flag), UD2UL (val), s_quote (strtable [val]));
358
359     return OptSetVal (opt, flag, val);
360 }
361
362 /*
363  * Get a contact option.
364  */
365 #undef OptGetVal
366 BOOL OptGetVal (const Opt *opt, UDWORD flag, val_t *res DEBUGPARAM)
367 {
368     const Opt *cot;
369     UBYTE tag = flag & 0xff;
370     int k = 0;
371
372     for (cot = opt; cot; cot = cot->next)
373     {
374         for (k = 0; k < OPT_TABLESIZE; k++)
375             if (cot->tags[k] == tag)
376                 break;
377         if (k != OPT_TABLESIZE)
378             break;
379     }
380     if (!cot || ((flag & COF_BOOL) && (~cot->vals[k] & (flag & CO_BOOLMASK))))
381     {
382         Debug (DEB_OPTS, "(%p,%lx) undef", opt, UD2UL (flag));
383         return FALSE;
384     }
385     *res = (flag & COF_BOOL) ? (cot->vals[k] & (flag * 2) & CO_BOOLMASK) != 0 : cot->vals[k];
386     if (~tag & 0x80)
387         Debug (DEB_OPTS, "(%p,%lx) = %lx = %lu", opt, UD2UL (flag), UD2UL (*res), UD2UL (*res));
388     return TRUE;
389 }
390
391 /*
392  * Set a contact option.
393  */
394 #undef OptSetVal
395 BOOL OptSetVal (Opt *opt, UDWORD flag, val_t val DEBUGPARAM)
396 {
397     Opt *cot, *cotold;
398     int k = 0;
399     UBYTE tag = flag & 0xff;
400
401     cotold = NULL;
402     for (cot = opt; cot; cot = cot->next)
403     {
404         cotold = cot;
405         for (k = 0; k < OPT_TABLESIZE; k++)
406             if ((cot->tags[k] == tag) || !cot->tags[k])
407                 break;
408         if (k != OPT_TABLESIZE)
409             break;
410     }
411     if (!cot)
412     {
413         if (!(cot = calloc (sizeof (Opt), 1)))
414         {
415             Debug (DEB_OPTS, "(%p,%lx) != %lx = %lu <mem %p>", opt, UD2UL (flag), UD2UL (val), UD2UL (val), cot);
416             return FALSE;
417         }
418
419         Debug (DEB_OPTS, "(%p,%lx) := %lx = %lu <new %p>", opt, UD2UL (flag), UD2UL (val), UD2UL (val), cot);
420         cotold->next = cot;
421         k = 0;
422     }
423     else
424         Debug (DEB_OPTS, "(%p,%lx) := %lx = %lu <%p>", opt, UD2UL (flag), UD2UL (val), UD2UL (val), cot);
425
426     cot->tags[k] = tag;
427     if (flag & COF_BOOL)
428     {
429         cot->vals[k] |= flag & CO_BOOLMASK;
430         if (val)
431             cot->vals[k] |= (flag & CO_BOOLMASK) * 2;
432         else
433             cot->vals[k] &= ~((flag & CO_BOOLMASK) * 2);
434     }
435     else
436         cot->vals[k] = val;
437     return TRUE;
438 }
439
440 /*
441  * Undefine a contact option.
442  */
443 #undef OptUndef
444 val_t OptUndef (Opt *opt, UDWORD flag DEBUGPARAM)
445 {
446     Opt *cot, *cotold;
447     UBYTE tag = flag & 0xff;
448     val_t old = 0;
449     int k = 0, m;
450
451
452     for (cot = opt; cot; cot = cot->next)
453     {
454         for (k = 0; k < OPT_TABLESIZE; k++)
455             if (cot->tags[k] == tag)
456                 break;
457         if (k != OPT_TABLESIZE)
458             break;
459     }
460     if (!cot)
461     {
462         Debug (DEB_OPTS, "(%p,%lx) := undef <unset>", opt, UD2UL (flag));
463         return 0;
464     }
465     if (flag & COF_BOOL)
466     {
467         cot->vals[k] &= ~(flag & CO_BOOLMASK);
468         cot->vals[k] &= ~((flag & CO_BOOLMASK) * 2);
469         Debug (DEB_OPTS, "(%p,%lx) := undef <bit>", opt, UD2UL (flag));
470         if (cot->vals[k])
471             return 0;
472     }
473     for (cotold = cot; cotold->next; )
474         cotold = cotold->next;
475     for (m = OPT_TABLESIZE - 1; m > 0; m--)
476         if (cotold->tags[m])
477             break;
478     old = cot->vals[k];
479     cot->tags[k] = cotold->tags[m];
480     cot->vals[k] = cotold->vals[m];
481     cotold->tags[m] = 0;
482     cotold->vals[m] = 0;
483     Debug (DEB_OPTS, "(%p,%lx) := undef <%ld>", opt, UD2UL (flag), UD2UL (old));
484
485     return old;
486 }
487
488 /*
489  * Convert a string describing a color into an escape sequence.
490  */
491 const char *OptC2S (const char *color)
492 {
493     static str_s str;
494     strc_t par;
495     const char *cmd, *c;
496
497     s_init (&str, "", 10);
498
499     while ((par = s_parse (&color)))
500     {
501         cmd = par->txt;
502         if      (!strcasecmp (cmd, "black"))   c = BLACK;
503         else if (!strcasecmp (cmd, "red"))     c = RED;
504         else if (!strcasecmp (cmd, "green"))   c = GREEN;
505         else if (!strcasecmp (cmd, "yellow"))  c = YELLOW;
506         else if (!strcasecmp (cmd, "blue"))    c = BLUE;
507         else if (!strcasecmp (cmd, "magenta")) c = MAGENTA;
508         else if (!strcasecmp (cmd, "cyan"))    c = CYAN;
509         else if (!strcasecmp (cmd, "white"))   c = WHITE;
510         else if (!strcasecmp (cmd, "none"))    c = SGR0;
511         else if (!strcasecmp (cmd, "bold"))    c = BOLD;
512         else c = cmd;
513        
514         s_cat (&str, c);
515     }
516     return str.txt;
517 }
518
519 /*
520  * Convert an escape sequence into a description of the color it selects
521  */
522 const char *OptS2C (const char *text)
523 {
524     static str_s str;
525     const char *c;
526     int l;
527    
528     s_init (&str, "", 20);
529
530     for ( ; *text; text += l)
531     {
532         if      (!strncmp (BLACK,   text, l = strlen (BLACK)))   c = "black";
533         else if (!strncmp (RED,     text, l = strlen (RED)))     c = "red";
534         else if (!strncmp (BLUE,    text, l = strlen (BLUE)))    c = "blue";
535         else if (!strncmp (GREEN,   text, l = strlen (GREEN)))   c = "green";
536         else if (!strncmp (YELLOW,  text, l = strlen (YELLOW)))  c = "yellow";
537         else if (!strncmp (MAGENTA, text, l = strlen (MAGENTA))) c = "magenta";
538         else if (!strncmp (CYAN,    text, l = strlen (CYAN)))    c = "cyan";
539         else if (!strncmp (WHITE,   text, l = strlen (WHITE)))   c = "white";
540         else if (!strncmp (SGR0,    text, l = strlen (SGR0)))    c = "none";
541         else if (!strncmp (BOLD,    text, l = strlen (BOLD)))    c = "bold";
542         else (c = text), (l = strlen (text));
543
544         if (*str.txt)
545             s_catc (&str, ' ');
546         s_cat (&str, s_quote (c));
547     }
548     return str.txt;
549 }
550
Note: See TracBrowser for help on using the browser.