-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindlg_tx.c
245 lines (213 loc) · 7.26 KB
/
indlg_tx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#ifdef RCSID
static char RCSid[] =
"$Header$";
#endif
/*
* Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
indlg_tx.c - input dialog - formatted text-only version
Function
Implements the input dialog function using formatted text
Notes
Only one of indlg_tx or indlg_os should be included in a given
executable. The choice depends on whether a system-level dialog
is available or not. If no system-level dialog is available,
include indlg_tx, which provides an implementation using formatted
text. If a system-level dialog is available, use indlg_os, which
calls os_input_dialog().
This file exists in the portable layer, rather than in the OS layer,
so that we can provide an implementation using formatted text. An
OS-layer implementation could not provide formatted text.
Modified
09/27/99 MJRoberts - Creation
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "std.h"
#include "os.h"
#include "tio.h"
/* ------------------------------------------------------------------------ */
/*
* Text-mode os_input_dialog implementation
*/
int tio_input_dialog(int icon_id, const char *prompt,
int standard_button_set,
const char **buttons, int button_count,
int default_index, int cancel_index)
{
/* ignore the icon ID - we can't display an icon in text mode */
VARUSED(icon_id);
/* keep going until we get a valid response */
for (;;)
{
int i;
char buf[256];
const char *p;
const char *cur;
char *resp;
int match_cnt;
int last_found;
static const struct
{
const char *buttons[3];
int button_count;
} std_btns[] =
{
{ { "&OK" }, 1 },
{ { "&OK", "&Cancel" }, 2 },
{ { "&Yes", "&No" }, 2 },
{ { "&Yes", "&No", "&Cancel" }, 3 }
};
/*
* if we have a standard button set selected, get our button
* labels
*/
switch(standard_button_set)
{
case 0:
/* use the explicit buttons provided */
break;
case OS_INDLG_OK:
i = 0;
use_std_btns:
/* use the selected standard button set */
buttons = (const char **)std_btns[i].buttons;
button_count = std_btns[i].button_count;
break;
case OS_INDLG_OKCANCEL:
i = 1;
goto use_std_btns;
case OS_INDLG_YESNO:
i = 2;
goto use_std_btns;
case OS_INDLG_YESNOCANCEL:
i = 3;
goto use_std_btns;
default:
/*
* we don't recognize other standard button sets - return an
* error
*/
return 0;
}
/*
* if there are no buttons defined, they'll never be able to
* respond, so we'd just loop forever - rather than let that
* happen, return failure
*/
if (button_count == 0)
return 0;
/* display a newline and the prompt string */
outformat("\\n");
outformat((char *)prompt);
outformat(" ");
/* display the response */
for (i = 0 ; i < button_count ; ++i)
{
/*
* display a slash to separate responses, if this isn't the
* first one
*/
if (i != 0)
outformat("/");
/* get the current button */
cur = buttons[i];
/*
* Look for a "&" in the response string. If we find it,
* remove the "&" and enclose the shortcut key in parens.
*/
for (p = cur ; *p != '&' && *p != '\0' ; ++p) ;
/* if we found the "&", put the next character in parens */
if (*p == '&')
{
/* reformat the response string */
sprintf(buf, "%.*s(%c)%s", (int)(p - cur), cur, *(p+1), p+2);
/* display it */
outformat(buf);
}
else
{
/* no '&' - just display the response string as-is */
outformat((char *)cur);
}
}
/* if we're in HTML mode, switch to input font */
if (tio_is_html_mode())
outformat("<font face='TADS-Input'>");
/* read the response */
getstring(" >", buf, sizeof(buf));
/* if we're in HTML mode, close the input font tag */
if (tio_is_html_mode())
outformat("</font>");
/* skip any leading spaces in the reply */
for (resp = buf ; t_isspace(*resp) ; ++resp) ;
/* if it's one character, check it against the shortcut keys */
if (strlen(resp) == 1)
{
/* scan the responses */
for (i = 0 ; i < button_count ; ++i)
{
/* look for a '&' in this button */
for (p = buttons[i] ; *p != '&' && *p != '\0' ; ++p) ;
/* if we found the '&', check the shortcut */
if (*p == '&' && toupper(*(p+1)) == toupper(*resp))
{
/*
* this is the one - return the current index
* (bumping it by one to get a 1-based value)
*/
return i + 1;
}
}
}
/*
* Either it's not a one-character reply, or it didn't match a
* short-cut - check it against the leading substrings of the
* responses. If it matches exactly one of the responses in its
* leading substring, use that response.
*/
for (i = 0, match_cnt = 0 ; i < button_count ; ++i)
{
const char *p1;
const char *p2;
/*
* compare this response to the user's response; skip any
* '&' in the button label
*/
for (p1 = resp, p2 = buttons[i] ; *p1 != '\0' && *p2 != '\0' ;
++p1, ++p2)
{
/* if this is a '&' in the button label, skip it */
if (*p2 == '&')
++p2;
/* if these characters don't match, it's no match */
if (toupper(*p1) != toupper(*p2))
break;
}
/*
* if we reached the end of the user's response, we have a
* match in the leading substring - count it and remember
* this as the last one, but keep looking, since we need to
* make sure we don't have any other matches
*/
if (*p1 == '\0')
{
++match_cnt;
last_found = i;
}
}
/*
* if we found exactly one match, return it (adjusting to a
* 1-based index); if we found more or less than one match, it's
* not a valid response, so start over with a new prompt
*/
if (match_cnt == 1)
return last_found + 1;
}
}