Added SILC Thread Queue API
[crypto.git] / apps / irssi / src / lib-popt / popthelp.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
3 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
4    file accompanying popt source distributions, available from 
5    ftp://ftp.redhat.com/pub/code/popt */
6
7 #include "common.h"
8
9 #include "popt.h"
10 #include "poptint.h"
11
12 static void displayArgs(poptContext con, enum poptCallbackReason foo, 
13                         struct poptOption * key, 
14                         const char * arg, void * data) {
15     if (key->shortName== '?')
16         poptPrintHelp(con, stdout, 0);
17     else
18         poptPrintUsage(con, stdout, 0);
19     exit(0);
20 }
21
22 struct poptOption poptHelpOptions[] = {
23     { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL },
24     { "help", '?', 0, NULL, '?', "Show this help message" },
25     { "usage", '\0', 0, NULL, 'u', "Display brief usage message" },
26     { NULL, '\0', 0, NULL, 0 }
27 } ;
28
29
30 static const char *
31 getTableTranslationDomain(const struct poptOption *table)
32 {
33   const struct poptOption *opt;
34
35   for(opt = table;
36       opt->longName || opt->shortName || opt->arg;
37       opt++) {
38     if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
39       return opt->arg;
40   }
41
42   return NULL;
43 }
44
45 static const char * getArgDescrip(const struct poptOption * opt,
46                                   const char *translation_domain) {
47     if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
48
49     if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
50         if (opt->argDescrip) return POPT_(opt->argDescrip);
51
52     if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
53     return POPT_("ARG");
54 }
55
56 static void singleOptionHelp(FILE * f, int maxLeftCol, 
57                              const struct poptOption * opt,
58                              const char *translation_domain) {
59     int indentLength = maxLeftCol + 5;
60     int lineLength = 79 - indentLength;
61     const char * help = D_(translation_domain, opt->descrip);
62     int helpLength;
63     const char * ch;
64     char format[10];
65     char * left = malloc(maxLeftCol + 1);
66     const char * argDescrip = getArgDescrip(opt, translation_domain);
67
68     *left = '\0';
69     if (opt->longName && opt->shortName)
70         sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
71     else if (opt->shortName) 
72         sprintf(left, "-%c", opt->shortName);
73     else if (opt->longName)
74         sprintf(left, "--%s", opt->longName);
75     if (!*left) {
76         free(left);
77         return;
78     }
79     if (argDescrip) {
80         strcat(left, "=");
81         strcat(left, argDescrip);
82     }
83
84     if (help)
85         fprintf(f,"  %-*s   ", maxLeftCol, left);
86     else {
87         fprintf(f,"  %s\n", left); 
88         free(left);
89         return;
90     }
91
92     free(left);
93
94     helpLength = strlen(help);
95     while (helpLength > lineLength) {
96         ch = help + lineLength - 1;
97         while (ch > help && !i_isspace(*ch)) ch--;
98         if (ch == help) break;          /* give up */
99         while (ch > (help + 1) && i_isspace(*ch)) ch--;
100         ch++;
101
102         sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
103         fprintf(f, format, help, " ");
104         help = ch;
105         while (i_isspace(*help) && *help) help++;
106         helpLength = strlen(help);
107     }
108
109     if (helpLength) fprintf(f, "%s\n", help);
110 }
111
112 static int maxArgWidth(const struct poptOption * opt,
113                        const char * translation_domain) {
114     int max = 0;
115     int this;
116     const char * s;
117     
118     while (opt->longName || opt->shortName || opt->arg) {
119         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
120             this = maxArgWidth(opt->arg, translation_domain);
121             if (this > max) max = this;
122         } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
123             this = opt->shortName ? 2 : 0;
124             if (opt->longName) {
125                 if (this) this += 2;
126                 this += strlen(opt->longName) + 2;
127             }
128
129             s = getArgDescrip(opt, translation_domain);
130             if (s)
131                 this += strlen(s) + 1;
132             if (this > max) max = this;
133         }
134
135         opt++;
136     }
137     
138     return max;
139 }
140
141 static void singleTableHelp(FILE * f, const struct poptOption * table, 
142                             int left,
143                             const char *translation_domain) {
144     const struct poptOption * opt;
145     const char *sub_transdom;
146
147     opt = table;
148     while (opt->longName || opt->shortName || opt->arg) {
149         if ((opt->longName || opt->shortName) && 
150             !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
151             singleOptionHelp(f, left, opt, translation_domain);
152         opt++;
153     }
154
155     opt = table;
156     while (opt->longName || opt->shortName || opt->arg) {
157         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
158             sub_transdom = getTableTranslationDomain(opt->arg);
159             if(!sub_transdom)
160                 sub_transdom = translation_domain;
161             
162             if (opt->descrip)
163                 fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
164
165             singleTableHelp(f, opt->arg, left, sub_transdom);
166         }
167         opt++;
168     }
169 }
170
171 static int showHelpIntro(poptContext con, FILE * f) {
172     int len = 6;
173     char * fn;
174
175     fprintf(f, POPT_("Usage:"));
176     if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
177         fn = con->optionStack->argv[0];
178         if (strrchr(fn, '/')) fn = strrchr(fn, '/') + 1;
179         fprintf(f, " %s", fn);
180         len += strlen(fn) + 1;
181     }
182
183     return len;
184 }
185
186 void poptPrintHelp(poptContext con, FILE * f, int flags) {
187     int leftColWidth;
188
189     showHelpIntro(con, f);
190     if (con->otherHelp)
191         fprintf(f, " %s\n", con->otherHelp);
192     else
193         fprintf(f, " %s\n", POPT_("[OPTION...]"));
194
195     leftColWidth = maxArgWidth(con->options, NULL);
196     singleTableHelp(f, con->options, leftColWidth, NULL);
197 }
198
199 static int singleOptionUsage(FILE * f, int cursor, 
200                              const struct poptOption * opt,
201                              const char *translation_domain) {
202     int len = 3;
203     char shortStr[2];
204     const char * item = shortStr;
205     const char * argDescrip = getArgDescrip(opt, translation_domain);
206
207     if (opt->shortName) {
208         if (!(opt->argInfo & POPT_ARG_MASK)) 
209             return cursor;      /* we did these already */
210         len++;
211         *shortStr = opt->shortName;
212         shortStr[1] = '\0';
213     } else if (opt->longName) {
214         len += 1 + strlen(opt->longName);
215         item = opt->longName;
216     }
217
218     if (len == 3) return cursor;
219
220     if (argDescrip) 
221         len += strlen(argDescrip) + 1;
222
223     if ((cursor + len) > 79) {
224         fprintf(f, "\n       ");
225         cursor = 7;
226     } 
227
228     fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
229             argDescrip ? (opt->shortName ? " " : "=") : "",
230             argDescrip ? argDescrip : "");
231
232     return cursor + len + 1;
233 }
234
235 static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
236                      const char *translation_domain) {
237     const struct poptOption * opt;
238     
239     opt = table;
240     while (opt->longName || opt->shortName || opt->arg) {
241         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
242             translation_domain = (const char *)opt->arg;
243         else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) 
244             cursor = singleTableUsage(f, cursor, opt->arg,
245                                       translation_domain);
246         else if ((opt->longName || opt->shortName) && 
247                  !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
248           cursor = singleOptionUsage(f, cursor, opt, translation_domain);
249
250         opt++;
251     }
252
253     return cursor;
254 }
255
256 static int showShortOptions(const struct poptOption * opt, FILE * f, 
257                             char * str) {
258     char s[300];                /* this is larger then the ascii set, so
259                                    it should do just fine */
260
261     if (!str) {
262         str = s;
263         memset(str, 0, sizeof(s));
264     }
265
266     while (opt->longName || opt->shortName || opt->arg) {
267         if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
268             str[strlen(str)] = opt->shortName;
269         else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
270             showShortOptions(opt->arg, f, str);
271
272         opt++;
273     } 
274
275     if (s != str || !*s)
276         return 0;
277
278     fprintf(f, " [-%s]", s);
279     return strlen(s) + 4;
280 }
281
282 void poptPrintUsage(poptContext con, FILE * f, int flags) {
283     int cursor;
284
285     cursor = showHelpIntro(con, f);
286     cursor += showShortOptions(con->options, f, NULL);
287     singleTableUsage(f, cursor, con->options, NULL);
288
289     if (con->otherHelp) {
290         cursor += strlen(con->otherHelp) + 1;
291         if (cursor > 79) fprintf(f, "\n       ");
292         fprintf(f, " %s", con->otherHelp);
293     }
294
295     fprintf(f, "\n");
296 }
297
298 void poptSetOtherOptionHelp(poptContext con, const char * text) {
299     if (con->otherHelp) free(con->otherHelp);
300     con->otherHelp = g_strdup(text);
301 }