Removed draw_double_box() function.
[midnight-commander.git] / src / popthelp.c
blobe4988366fccf92c3241df2c588ee510ff99c4eb5
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
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 */
7 /** \file popthelp.c
8 * \brief Source: popt helper module
9 */
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
15 #include <ctype.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
20 #include "global.h"
21 #include "popt.h"
22 #include "poptint.h"
24 static void displayArgs(poptContext con, enum poptCallbackReason foo,
25 struct poptOption * key,
26 const char * arg, void * data)
28 (void) foo;
29 (void) arg;
30 (void) data;
32 if (key->shortName== '?')
33 poptPrintHelp(con, stdout, 0);
34 else
35 poptPrintUsage(con, stdout, 0);
36 exit(0);
41 static const char *
42 getTableTranslationDomain(const struct poptOption *table)
44 const struct poptOption *opt;
46 for(opt = table;
47 opt->longName || opt->shortName || opt->arg.p;
48 opt++) {
49 if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
50 return opt->arg.p;
53 return NULL;
56 static const char * getArgDescrip(const struct poptOption * opt,
57 const char *translation_domain) {
58 struct poptOption *poptHelpOptions;
60 (void) translation_domain;
62 poptHelpOptions = g_malloc(sizeof(struct poptOption)*4);
64 poptHelpOptions[0].longName = NULL;
65 poptHelpOptions[0].shortName = '\0';
66 poptHelpOptions[0].argInfo = POPT_ARG_CALLBACK;
67 poptHelpOptions[0].arg.f1 = &displayArgs;
68 poptHelpOptions[0].val = '\0';
69 poptHelpOptions[0].descrip = NULL;
70 poptHelpOptions[0].argDescrip = NULL;
72 poptHelpOptions[1].longName = "help";
73 poptHelpOptions[1].shortName = '?';
74 poptHelpOptions[1].argInfo = 0;
75 poptHelpOptions[1].arg.p = NULL;
76 poptHelpOptions[1].val = '?';
77 poptHelpOptions[1].descrip = _("Show this help message");
78 poptHelpOptions[1].argDescrip = NULL;
80 poptHelpOptions[2].longName = "usage";
81 poptHelpOptions[2].shortName = '\0';
82 poptHelpOptions[2].argInfo = 0;
83 poptHelpOptions[2].arg.p = NULL;
84 poptHelpOptions[2].val = 'u';
85 poptHelpOptions[2].descrip = _("Display brief usage message");
86 poptHelpOptions[2].argDescrip = NULL;
88 poptHelpOptions[3].longName = NULL;
89 poptHelpOptions[3].shortName = '\0';
90 poptHelpOptions[3].argInfo = 0;
91 poptHelpOptions[3].arg.p = NULL;
92 poptHelpOptions[3].val = 0;
93 poptHelpOptions[3].descrip = NULL;
94 poptHelpOptions[3].argDescrip = NULL;
96 if (!(opt->argInfo & POPT_ARG_MASK)){
97 g_free(poptHelpOptions);
98 return NULL;
101 if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
102 if (opt->argDescrip)
104 g_free(poptHelpOptions);
105 return POPT_(opt->argDescrip);
108 if (opt->argDescrip)
110 g_free(poptHelpOptions);
111 return D_(translation_domain, opt->argDescrip);
113 g_free(poptHelpOptions);
114 return _("ARG");
117 static void singleOptionHelp(FILE * f, int maxLeftCol,
118 const struct poptOption * opt,
119 const char *translation_domain) {
120 int indentLength = maxLeftCol + 5;
121 int lineLength = 79 - indentLength;
122 const char * help = D_(translation_domain, opt->descrip);
123 int helpLength;
124 const char * ch;
125 char * left;
126 const char * argDescrip = getArgDescrip(opt, translation_domain);
128 left = malloc(maxLeftCol + 1);
129 *left = '\0';
131 if (opt->longName && opt->shortName)
132 sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
133 else if (opt->shortName)
134 sprintf(left, "-%c", opt->shortName);
135 else if (opt->longName)
136 sprintf(left, "--%s", opt->longName);
137 if (!*left) return ;
138 if (argDescrip) {
139 strcat(left, "=");
140 strcat(left, argDescrip);
143 if (help)
144 fprintf(f," %-*s ", maxLeftCol, left);
145 else {
146 fprintf(f," %s\n", left);
147 goto out;
150 helpLength = strlen(help);
151 while (helpLength > lineLength) {
152 ch = help + lineLength - 1;
153 while (ch > help && !isspace((unsigned char) *ch)) ch--;
154 if (ch == help) break; /* give up */
155 while (ch > (help + 1) && isspace((unsigned char) *ch)) ch--;
156 ch++;
158 fprintf(f, "%.*s\n%*s", (int) (ch - help), help, indentLength, " ");
159 help = ch;
160 while (isspace((unsigned char) *help) && *help) help++;
161 helpLength = strlen(help);
164 if (helpLength) fprintf(f, "%s\n", help);
166 out:
167 free(left);
170 static int maxArgWidth(const struct poptOption * opt,
171 const char * translation_domain) {
172 int max = 0;
173 int this;
174 const char * s;
176 while (opt->longName || opt->shortName || opt->arg.p) {
177 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
178 this = maxArgWidth(opt->arg.p, translation_domain);
179 if (this > max) max = this;
180 } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
181 this = opt->shortName ? 2 : 0;
182 if (opt->longName) {
183 if (this) this += 2;
184 this += strlen(opt->longName) + 2;
187 s = getArgDescrip(opt, translation_domain);
188 if (s)
189 this += strlen(s) + 1;
190 if (this > max) max = this;
193 opt++;
196 return max;
199 static void singleTableHelp(FILE * f, const struct poptOption * table,
200 int left,
201 const char *translation_domain) {
202 const struct poptOption * opt;
203 const char *sub_transdom;
205 opt = table;
206 while (opt->longName || opt->shortName || opt->arg.p) {
207 if ((opt->longName || opt->shortName) &&
208 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
209 singleOptionHelp(f, left, opt, translation_domain);
210 opt++;
213 opt = table;
214 while (opt->longName || opt->shortName || opt->arg.p) {
215 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
216 sub_transdom = getTableTranslationDomain(opt->arg.p);
217 if(!sub_transdom)
218 sub_transdom = translation_domain;
220 if (opt->descrip)
221 fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
223 singleTableHelp(f, opt->arg.p, left, sub_transdom);
225 opt++;
229 static int showHelpIntro(poptContext con, FILE * f) {
230 int len = 6;
231 const char * fn;
233 fprintf(f, _("Usage:"));
234 if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
235 fn = con->optionStack->argv[0];
236 if (strrchr(fn, '/')) fn = strrchr(fn, '/') + 1;
237 fprintf(f, " %s", fn);
238 len += strlen(fn) + 1;
241 return len;
244 int poptPrintHelp(poptContext con, FILE * f, int flags) {
245 int leftColWidth;
247 (void) flags;
249 showHelpIntro(con, f);
250 if (con->otherHelp)
251 fprintf(f, " %s\n", con->otherHelp);
252 else
253 fprintf(f, " %s\n", POPT_("[OPTION...]"));
255 leftColWidth = maxArgWidth(con->options, NULL);
256 singleTableHelp(f, con->options, leftColWidth, NULL);
257 return leftColWidth;
260 static int singleOptionUsage(FILE * f, int cursor,
261 const struct poptOption * opt,
262 const char *translation_domain) {
263 int len = 3;
264 char shortStr[2];
265 const char * item = shortStr;
266 const char * argDescrip = getArgDescrip(opt, translation_domain);
268 if (opt->shortName) {
269 if (!(opt->argInfo & POPT_ARG_MASK))
270 return cursor; /* we did these already */
271 len++;
272 *shortStr = opt->shortName;
273 shortStr[1] = '\0';
274 } else if (opt->longName) {
275 len += 1 + strlen(opt->longName);
276 item = opt->longName;
279 if (len == 3) return cursor;
281 if (argDescrip)
282 len += strlen(argDescrip) + 1;
284 if ((cursor + len) > 79) {
285 fprintf(f, "\n ");
286 cursor = 7;
289 fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
290 argDescrip ? (opt->shortName ? " " : "=") : "",
291 argDescrip ? argDescrip : "");
293 return cursor + len + 1;
296 static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
297 const char *translation_domain) {
298 const struct poptOption * opt;
300 opt = table;
301 while (opt->longName || opt->shortName || opt->arg.p) {
302 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
303 translation_domain = (const char *)opt->arg.p;
304 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
305 cursor = singleTableUsage(f, cursor, opt->arg.p,
306 translation_domain);
307 else if ((opt->longName || opt->shortName) &&
308 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
309 cursor = singleOptionUsage(f, cursor, opt, translation_domain);
311 opt++;
314 return cursor;
317 static int showShortOptions(const struct poptOption * opt, FILE * f,
318 char * str) {
319 char s[300]; /* this is larger then the ascii set, so
320 it should do just fine */
322 if (!str) {
323 str = s;
324 memset(str, 0, sizeof(s));
327 while (opt->longName || opt->shortName || opt->arg.p) {
328 if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
329 str[strlen(str)] = opt->shortName;
330 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
331 showShortOptions(opt->arg.p, f, str);
333 opt++;
336 if (s != str || !*s)
337 return 0;
339 fprintf(f, " [-%s]", s);
340 return strlen(s) + 4;
343 void poptPrintUsage(poptContext con, FILE * f, int flags) {
344 int cursor;
346 (void) flags;
348 cursor = showHelpIntro(con, f);
349 cursor += showShortOptions(con->options, f, NULL);
350 singleTableUsage(f, cursor, con->options, NULL);
352 if (con->otherHelp) {
353 cursor += strlen(con->otherHelp) + 1;
354 if (cursor > 79) fprintf(f, "\n ");
355 fprintf(f, " %s", con->otherHelp);
358 fprintf(f, "\n");
361 void poptSetOtherOptionHelp(poptContext con, const char * text) {
362 if (con->otherHelp) free(con->otherHelp);
363 con->otherHelp = strdup(text);