2 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
39 #include "pathnames.h"
41 ////////////////////////////////////////////////////////////
44 xstrdup(const char *s)
48 ret = malloc(strlen(s) + 1);
50 errx(1, "Out of memory");
56 ////////////////////////////////////////////////////////////
64 stringarray_init(struct stringarray *a)
71 stringarray_cleanup(struct stringarray *a)
77 stringarray_add(struct stringarray *a, const char *s)
79 a->v = realloc(a->v, (a->num + 1) * sizeof(a->v[0]));
81 errx(1, "Out of memory");
83 a->v[a->num] = xstrdup(s);
87 ////////////////////////////////////////////////////////////
89 static struct stringarray lines;
90 static struct stringarray sollines;
92 static int scrolldown;
99 FILE *f = popen(_PATH_FORTUNE, "r");
101 err(1, "%s", _PATH_FORTUNE);
103 char buf[128], buf2[8 * sizeof(buf)];
104 while (fgets(buf, sizeof(buf), f)) {
105 char *s = strrchr(buf, '\n');
106 assert(s && strlen(s) == 1);
110 for (i = j = 0; buf[i]; i++) {
111 if (buf[i] == '\t') {
115 } else if (buf[i] == '\b') {
124 stringarray_add(&lines, buf2);
125 stringarray_add(&sollines, buf2);
136 for (int i = 0; i < 26; i++)
138 for (int i = 26; i > 1; i--) {
139 int c = random() % i;
145 for (int y = 0; y < lines.num; y++) {
146 for (unsigned x = 0; lines.v[y][x]; x++) {
147 if (islower((unsigned char)lines.v[y][x])) {
148 int q = lines.v[y][x] - 'a';
149 lines.v[y][x] = 'a' + key[q];
151 if (isupper((unsigned char)lines.v[y][x])) {
152 int q = lines.v[y][x] - 'A';
153 lines.v[y][x] = 'A' + key[q];
162 assert(cury >= 0 && cury < lines.num);
163 if (curx >= strlen(lines.v[cury])) {
168 int och = lines.v[cury][curx];
169 if (!isalpha((unsigned char)och)) {
174 int loch = tolower((unsigned char)och);
175 int uoch = toupper((unsigned char)och);
176 int lch = tolower((unsigned char)ch);
177 int uch = toupper((unsigned char)ch);
179 for (int y = 0; y < lines.num; y++) {
180 for (unsigned x = 0; lines.v[y][x]; x++) {
181 if (lines.v[y][x] == loch)
183 else if (lines.v[y][x] == uoch)
185 else if (lines.v[y][x] == lch)
186 lines.v[y][x] = loch;
187 else if (lines.v[y][x] == uch)
188 lines.v[y][x] = uoch;
195 ////////////////////////////////////////////////////////////
203 for (int i = 0; i < LINES - 1; i++) {
205 int ln = i + scrolldown;
206 if (ln < lines.num) {
207 for (unsigned j = 0; lines.v[i][j]; j++) {
208 int ch = lines.v[i][j];
209 if (ch != sollines.v[i][j] &&
210 isalpha((unsigned char)ch)) {
214 if (hinting && ch == sollines.v[i][j] &&
215 isalpha((unsigned char)ch)) {
219 addch(lines.v[i][j]);
230 addstr("~ to quit, * to cheat, ^pnfb to move");
233 move(cury - scrolldown, curx);
252 ////////////////////////////////////////////////////////////
272 } else if (cury > 0) {
274 curx = strlen(lines.v[cury]);
279 curx = strlen(lines.v[cury]);
283 if (curx < strlen(lines.v[cury])) {
285 } else if (cury < lines.num - 1) {
295 if (cury < lines.num - 1)
297 if (curx > strlen(lines.v[cury]))
298 curx = strlen(lines.v[cury]);
299 if (scrolldown < cury - (LINES - 2))
300 scrolldown = cury - (LINES - 2);
306 if (curx > strlen(lines.v[cury]))
307 curx = strlen(lines.v[cury]);
308 if (scrolldown > cury)
319 if (!substitute(ch)) {
320 if (curx < strlen(lines.v[cury]))
322 if (curx == strlen(lines.v[cury]) &&
323 cury < lines.num - 1) {
328 } else if (curx < strlen(lines.v[cury]) &&
329 ch == lines.v[cury][curx]) {
331 if (curx == strlen(lines.v[cury]) &&
332 cury < lines.num - 1) {
344 ////////////////////////////////////////////////////////////
349 stringarray_init(&lines);
350 stringarray_init(&sollines);
356 keypad(stdscr, TRUE);
360 stringarray_cleanup(&sollines);
361 stringarray_cleanup(&lines);