source: mainline/uspace/lib/clui/nchoice.c@ 4547f11

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4547f11 was 68b5dd11, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Provide some default options.

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*
2 * Copyright (c) 2015 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup libclui
29 * @{
30 */
31/**
32 * @file Numerical choice
33 */
34
35#include <errno.h>
36#include <nchoice.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <str.h>
40#include <tinput.h>
41
42/** Create numerical choice
43 *
44 */
45int nchoice_create(nchoice_t **rchoice)
46{
47 nchoice_t *choice = NULL;
48 int rc;
49
50 choice = calloc(1, sizeof(nchoice_t));
51 if (choice == NULL)
52 goto error;
53
54 list_initialize(&choice->opts);
55
56 choice->tinput = tinput_new();
57 if (choice->tinput == NULL)
58 goto error;
59
60 rc = tinput_set_prompt(choice->tinput, "Choice> ");
61 if (rc != EOK) {
62 assert(rc == ENOMEM);
63 goto error;
64 }
65
66 *rchoice = choice;
67 return EOK;
68error:
69 nchoice_destroy(choice);
70 return ENOMEM;
71}
72
73/** Destroy numerical choice */
74void nchoice_destroy(nchoice_t *choice)
75{
76 if (choice == NULL)
77 return;
78
79 tinput_destroy(choice->tinput);
80 free(choice);
81}
82
83/** Set numerica choice prompt text */
84int nchoice_set_prompt(nchoice_t *choice, const char *prompt)
85{
86 char *pstr;
87
88 pstr = str_dup(prompt);
89 if (pstr == NULL)
90 return ENOMEM;
91
92 free(choice->prompt);
93 choice->prompt = pstr;
94 return EOK;
95}
96
97/** Add option to numerical choice */
98int nchoice_add(nchoice_t *choice, const char *opttext, void *arg,
99 nchoice_flag_t flags)
100{
101 nchoice_opt_t *opt;
102 char *ptext;
103
104 opt = calloc(1, sizeof(nchoice_opt_t));
105 if (opt == NULL)
106 return ENOMEM;
107
108 ptext = str_dup(opttext);
109 if (ptext == NULL) {
110 free(opt);
111 return ENOMEM;
112 }
113
114 opt->text = ptext;
115 opt->arg = arg;
116 list_append(&opt->lchoice, &choice->opts);
117
118 if ((flags & ncf_default) != 0) {
119 /* Set this option as the default */
120 assert(choice->def_opt == NULL);
121
122 choice->def_opt = opt;
123 }
124
125 return EOK;
126}
127
128/** Get numerical choice from user */
129int nchoice_get(nchoice_t *choice, void **rarg)
130{
131 int i;
132 int rc;
133 char *str;
134 unsigned long c;
135 char *eptr;
136 char *istr;
137 int def_i;
138
139again:
140 printf("%s\n", choice->prompt);
141
142 def_i = 0;
143 i = 1;
144 list_foreach(choice->opts, lchoice, nchoice_opt_t, opt) {
145 printf("%d: %s%s\n", i, opt->text, opt == choice->def_opt ?
146 " [default]" : "");
147 if (opt == choice->def_opt)
148 def_i = i;
149 ++i;
150 }
151
152 if (def_i > 0) {
153 rc = asprintf(&istr, "%d", def_i);
154 if (rc < 0)
155 return ENOMEM;
156 } else {
157 istr = str_dup("");
158 if (istr == NULL)
159 return ENOMEM;
160 }
161
162 rc = tinput_read_i(choice->tinput, istr, &str);
163 free(istr);
164
165 if (rc != EOK) {
166 assert(rc == EIO || rc == ENOENT);
167
168 if (rc == ENOENT) {
169 return ENOENT;
170 } else {
171 /* rc == EIO */
172 return EIO;
173 }
174 }
175
176 c = strtoul(str, &eptr, 10);
177 if (*eptr != '\0' || c < 1 || c > (unsigned long)i - 1) {
178 printf("Invalid choice. Try again.\n");
179 free(str);
180 goto again;
181 }
182
183 free(str);
184
185 i = 1;
186 list_foreach(choice->opts, lchoice, nchoice_opt_t, opt) {
187 if ((unsigned long)i == c) {
188 *rarg = opt->arg;
189 return EOK;
190 }
191 ++i;
192 }
193
194 assert(false);
195 return ENOENT;
196}
197
198/** @}
199 */
Note: See TracBrowser for help on using the repository browser.