small highlighting correction...
[midnight-commander.git] / src / popthelp.c
blobc1f0f43af86df6d89dbeb68e446e857ef0c3fc28
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 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
16 #include "popt.h"
17 #include "poptint.h"
19 static void displayArgs(poptContext con, enum poptCallbackReason foo,
20 struct poptOption * key,
21 const char * arg, void * data) {
22 if (key->shortName== '?')
23 poptPrintHelp(con, stdout, 0);
24 else
25 poptPrintUsage(con, stdout, 0);
26 exit(0);
29 struct poptOption poptHelpOptions[] = {
30 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL },
31 { "help", '?', 0, NULL, '?', N_("Show this help message") },
32 { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message") },
33 { NULL, '\0', 0, NULL, 0 }
34 } ;
37 static const char *
38 getTableTranslationDomain(const struct poptOption *table)
40 const struct poptOption *opt;
42 for(opt = table;
43 opt->longName || opt->shortName || opt->arg;
44 opt++) {
45 if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
46 return opt->arg;
49 return NULL;
52 static const char * getArgDescrip(const struct poptOption * opt,
53 const char *translation_domain) {
54 if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
56 if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
57 if (opt->argDescrip) return POPT_(opt->argDescrip);
59 if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
60 return POPT_("ARG");
63 static void singleOptionHelp(FILE * f, int maxLeftCol,
64 const struct poptOption * opt,
65 const char *translation_domain) {
66 int indentLength = maxLeftCol + 5;
67 int lineLength = 79 - indentLength;
68 const char * help = D_(translation_domain, opt->descrip);
69 int helpLength;
70 const char * ch;
71 char format[10];
72 char * left;
73 const char * argDescrip = getArgDescrip(opt, translation_domain);
75 left = malloc(maxLeftCol + 1);
76 *left = '\0';
78 if (opt->longName && opt->shortName)
79 sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
80 else if (opt->shortName)
81 sprintf(left, "-%c", opt->shortName);
82 else if (opt->longName)
83 sprintf(left, "--%s", opt->longName);
84 if (!*left) return ;
85 if (argDescrip) {
86 strcat(left, "=");
87 strcat(left, argDescrip);
90 if (help)
91 fprintf(f," %-*s ", maxLeftCol, left);
92 else {
93 fprintf(f," %s\n", left);
94 goto out;
97 helpLength = strlen(help);
98 while (helpLength > lineLength) {
99 ch = help + lineLength - 1;
100 while (ch > help && !isspace(*ch)) ch--;
101 if (ch == help) break; /* give up */
102 while (ch > (help + 1) && isspace(*ch)) ch--;
103 ch++;
105 sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
106 fprintf(f, format, help, " ");
107 help = ch;
108 while (isspace(*help) && *help) help++;
109 helpLength = strlen(help);
112 if (helpLength) fprintf(f, "%s\n", help);
114 out:
115 free(left);
118 static int maxArgWidth(const struct poptOption * opt,
119 const char * translation_domain) {
120 int max = 0;
121 int this;
122 const char * s;
124 while (opt->longName || opt->shortName || opt->arg) {
125 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
126 this = maxArgWidth(opt->arg, translation_domain);
127 if (this > max) max = this;
128 } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
129 this = opt->shortName ? 2 : 0;
130 if (opt->longName) {
131 if (this) this += 2;
132 this += strlen(opt->longName) + 2;
135 s = getArgDescrip(opt, translation_domain);
136 if (s)
137 this += strlen(s) + 1;
138 if (this > max) max = this;
141 opt++;
144 return max;
147 static void singleTableHelp(FILE * f, const struct poptOption * table,
148 int left,
149 const char *translation_domain) {
150 const struct poptOption * opt;
151 const char *sub_transdom;
153 opt = table;
154 while (opt->longName || opt->shortName || opt->arg) {
155 if ((opt->longName || opt->shortName) &&
156 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
157 singleOptionHelp(f, left, opt, translation_domain);
158 opt++;
161 opt = table;
162 while (opt->longName || opt->shortName || opt->arg) {
163 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
164 sub_transdom = getTableTranslationDomain(opt->arg);
165 if(!sub_transdom)
166 sub_transdom = translation_domain;
168 if (opt->descrip)
169 fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
171 singleTableHelp(f, opt->arg, left, sub_transdom);
173 opt++;
177 static int showHelpIntro(poptContext con, FILE * f) {
178 int len = 6;
179 char * fn;
181 fprintf(f, POPT_("Usage:"));
182 if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
183 fn = con->optionStack->argv[0];
184 if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
185 fprintf(f, " %s", fn);
186 len += strlen(fn) + 1;
189 return len;
192 void poptPrintHelp(poptContext con, FILE * f, int flags) {
193 int leftColWidth;
195 showHelpIntro(con, f);
196 if (con->otherHelp)
197 fprintf(f, " %s\n", con->otherHelp);
198 else
199 fprintf(f, " %s\n", POPT_("[OPTION...]"));
201 leftColWidth = maxArgWidth(con->options, NULL);
202 singleTableHelp(f, con->options, leftColWidth, NULL);
205 static int singleOptionUsage(FILE * f, int cursor,
206 const struct poptOption * opt,
207 const char *translation_domain) {
208 int len = 3;
209 char shortStr[2];
210 const char * item = shortStr;
211 const char * argDescrip = getArgDescrip(opt, translation_domain);
213 if (opt->shortName) {
214 if (!(opt->argInfo & POPT_ARG_MASK))
215 return cursor; /* we did these already */
216 len++;
217 *shortStr = opt->shortName;
218 shortStr[1] = '\0';
219 } else if (opt->longName) {
220 len += 1 + strlen(opt->longName);
221 item = opt->longName;
224 if (len == 3) return cursor;
226 if (argDescrip)
227 len += strlen(argDescrip) + 1;
229 if ((cursor + len) > 79) {
230 fprintf(f, "\n ");
231 cursor = 7;
234 fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
235 argDescrip ? (opt->shortName ? " " : "=") : "",
236 argDescrip ? argDescrip : "");
238 return cursor + len + 1;
241 static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
242 const char *translation_domain) {
243 const struct poptOption * opt;
245 opt = table;
246 while (opt->longName || opt->shortName || opt->arg) {
247 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
248 translation_domain = (const char *)opt->arg;
249 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
250 cursor = singleTableUsage(f, cursor, opt->arg,
251 translation_domain);
252 else if ((opt->longName || opt->shortName) &&
253 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
254 cursor = singleOptionUsage(f, cursor, opt, translation_domain);
256 opt++;
259 return cursor;
262 static int showShortOptions(const struct poptOption * opt, FILE * f,
263 char * str) {
264 char s[300]; /* this is larger then the ascii set, so
265 it should do just fine */
267 if (!str) {
268 str = s;
269 memset(str, 0, sizeof(s));
272 while (opt->longName || opt->shortName || opt->arg) {
273 if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
274 str[strlen(str)] = opt->shortName;
275 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
276 showShortOptions(opt->arg, f, str);
278 opt++;
281 if (s != str || !*s)
282 return 0;
284 fprintf(f, " [-%s]", s);
285 return strlen(s) + 4;
288 void poptPrintUsage(poptContext con, FILE * f, int flags) {
289 int cursor;
291 cursor = showHelpIntro(con, f);
292 cursor += showShortOptions(con->options, f, NULL);
293 singleTableUsage(f, cursor, con->options, NULL);
295 if (con->otherHelp) {
296 cursor += strlen(con->otherHelp) + 1;
297 if (cursor > 79) fprintf(f, "\n ");
298 fprintf(f, " %s", con->otherHelp);
301 fprintf(f, "\n");
304 void poptSetOtherOptionHelp(poptContext con, const char * text) {
305 if (con->otherHelp) free(con->otherHelp);
306 con->otherHelp = strdup(text);