]> git.sur5r.net Git - c128-kasse/blob - src/general.c
kasse: move inputting nicknames w/ completion in its own function
[c128-kasse] / src / general.c
1 /*
2  * RGB2R-C128-Kassenprogramm
3  * © 2007-2009 phil_fry, sECuRE, sur5r
4  * See LICENSE for license information
5  *
6  */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <conio.h>
11 #include <stdint.h>
12
13 #include "general.h"
14 #include "config.h"
15 #include "vdc_patch_charset.h"
16
17 /*
18  * get_input_terminated_by() reads input (handling backspace correctly) until
19  * a terminator of |terminators| is encountered or |out| is full (outlen-1
20  * characters were read).
21  *
22  * get_input_terminated_by() returns the terminator it encountered.
23  *
24  */
25 input_terminator_t get_input_terminated_by(input_terminator_mask_t terminators,
26                                            char *out, BYTE outlen) {
27   BYTE i = strlen(out);
28   BYTE c, x, y;
29   x = wherex() - i;
30   y = wherey();
31   while (1) {
32     c = cgetc();
33     if (((terminators & INPUT_TERMINATOR_RETURN) == INPUT_TERMINATOR_RETURN) &&
34         (c == PETSCII_CR)) {
35       return INPUT_TERMINATOR_RETURN;
36     } else if (((terminators & INPUT_TERMINATOR_SPACE) ==
37                 INPUT_TERMINATOR_SPACE) &&
38                (c == PETSCII_SP)) {
39       return INPUT_TERMINATOR_SPACE;
40     } else if (c == PETSCII_DEL) {
41       /* If you are at the left-most position, do nothing */
42       if (i == 0)
43         continue;
44       out[--i] = '\0';
45       cputcxy(x + i, y, ' ');
46       gotoxy(x + i, y);
47       continue;
48     }
49     if (i == (outlen - 1)) {
50       continue;
51     }
52     cputc(c);
53     out[i++] = c;
54   }
55 }
56
57 /*
58  * Liest (maximal 31) Zeichen ein, bis Enter gedrückt wird.
59  * Vorsicht: Es wird ein statischer Buffer benutzt, sodass man
60  * das Ergebnis via strdup() retten muss, bevor man get_input()
61  * erneut aufruft
62  *
63  */
64 char *get_input(void) {
65   static char output[32];
66   memset(output, '\0', sizeof(output));
67   get_input_terminated_by(INPUT_TERMINATOR_RETURN, output, sizeof(output));
68   return output;
69 }
70
71 BYTE cgetn_input(char *s, BYTE len) {
72   memset(s, '\0', len);
73   get_input_terminated_by(INPUT_TERMINATOR_RETURN, s, len);
74   return strlen(s);
75 }
76
77 int16_t cget_number(int16_t default_val) {
78   char c;
79   int x, y;
80   uint8_t num_chars = 0;
81   char buf[6] = {0, 0, 0, 0, 0, 0};
82   int i = 0;
83   x = wherex();
84   y = wherey();
85   while (1) {
86     c = cgetc();
87
88     /* Enter */
89     if (c == PETSCII_CR)
90       break;
91
92     /* Backspace */
93     if (c == PETSCII_DEL) {
94       if (i == 0)
95         continue;
96       buf[--i] = '\0';
97       cputcxy(x + i, y, ' ');
98       gotoxy(x + i, y);
99       continue;
100     }
101
102     /* Abort */
103     if (c == PETSCII_ESC) {
104       return default_val;
105     }
106
107     /* end of buffer? wait for user to press RETURN */
108     if (i == (sizeof(buf) - 1))
109       continue;
110
111     /* match either numbers or iff it's the first entered char a minus sign */
112     if ((c >= PETSCII_0 && c <= PETSCII_9) || (c == '-' && i == 0)) {
113       buf[i] = c;
114       ++i;
115       ++num_chars;
116       cputc(c);
117     }
118   }
119
120   if (num_chars == 0) {
121     return default_val;
122   } else if ((num_chars == 1) && (c == '-')) {
123     return default_val;
124   }
125
126   return atoi(buf);
127 }
128
129 uint8_t cget_nickname(char *nickname, uint8_t length) {
130   uint8_t i, x, y, matches;
131   char *uniquematch;
132   input_terminator_t terminator;
133
134   memset(nickname, '\0', length);
135
136   while (1) {
137     terminator = get_input_terminated_by(
138         INPUT_TERMINATOR_RETURN | INPUT_TERMINATOR_SPACE, nickname, length);
139
140     /* Clear the screen from any previous completions */
141     x = wherex();
142     y = wherey();
143     for (i = 1; i < 7; i++) {
144       /* "Completion:" is longer than NICKNAME_MAX_LEN */
145       cclearxy(0, y + i, strlen("Completion:"));
146     }
147     gotoxy(x, y);
148
149     if (terminator != INPUT_TERMINATOR_SPACE) {
150       return strlen(nickname);
151     }
152
153     matches = 0;
154     uniquematch = NULL;
155     for (i = 0; i < credits.num_items; i++) {
156       if (strncmp(nickname, credits.credits[i].nickname, strlen(nickname)) !=
157           0) {
158         continue;
159       }
160       matches++;
161       if (matches > 1) {
162         break;
163       }
164       uniquematch = credits.credits[i].nickname;
165     }
166     if (matches == 1) {
167       /* Display the rest of the nickname */
168       textcolor(TC_LIGHT_GREEN);
169       cprintf("%s", uniquematch + strlen(nickname));
170       textcolor(TC_LIGHT_GRAY);
171       strcat(nickname, uniquematch + strlen(nickname));
172     } else {
173       /* Multiple nicknames match what was entered so far. Abort and
174        * display all matches, then prompt the user again. */
175       char completion[NICKNAME_MAX_LEN + 1];
176       BYTE len = strlen(nickname);
177       x = wherex();
178       y = wherey();
179       cprintf("\r\nCompletion:\r\n");
180       matches = 0;
181       for (i = 0; i < credits.num_items; i++) {
182         if (strncmp(nickname, credits.credits[i].nickname, len) != 0) {
183           continue;
184         }
185         if (++matches == 5) {
186           cprintf("...\r\n");
187           break;
188         }
189         strcpy(completion, credits.credits[i].nickname);
190         *(completion + len) = '\0';
191         cprintf("%s", completion);
192         textcolor(TC_LIGHT_GREEN);
193         cprintf("%c", *(credits.credits[i].nickname + len));
194         textcolor(TC_LIGHT_GRAY);
195         cprintf("%s\r\n", completion + len + 1);
196       }
197       gotoxy(x, y);
198     }
199   }
200 }
201
202 /* wait until user pressed RETURN, ignore all other input */
203 void cget_return() {
204   while (cgetc() != PETSCII_CR) {
205   }
206   return;
207 }
208
209 char retry_or_quit(void) {
210   char *c;
211   do {
212     cprintf("\r\nr)etry or q)uit?\r\n");
213     c = get_input();
214   } while ((*c != 'r') && (*c != 'q'));
215   return *c;
216 }
217
218 char *format_euro(char *s, int maxlen, int cent) {
219   if (snprintf(s, maxlen, EUR_FORMAT, cent / 100, cent % 100) > maxlen)
220     return NULL;
221   return s;
222 }
223
224 void c128_perror(BYTE c, char *msg) {
225   cprintf("\r\nError (Code %d) while: %s\r\nOS Error = %d\r\n", c, msg,
226           _oserror);
227 }