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.
38 #include "pathnames.h"
40 ////////////////////////////////////////////////////////////
42 static char *xstrdup(const char *s) {
45 ret = malloc(strlen(s) + 1);
47 errx(1, "Out of memory");
53 ////////////////////////////////////////////////////////////
60 static void stringarray_init(struct stringarray *a) {
65 static void stringarray_cleanup(struct stringarray *a) {
69 static void stringarray_add(struct stringarray *a, const char *s) {
70 a->v = realloc(a->v, (a->num + 1) * sizeof(a->v[0]));
72 errx(1, "Out of memory");
74 a->v[a->num] = xstrdup(s);
78 ////////////////////////////////////////////////////////////
80 static struct stringarray lines;
81 static struct stringarray sollines;
83 static int scrolldown;
87 static void readquote(void) {
88 FILE *f = popen(_PATH_FORTUNE, "r");
90 err(1, "%s", _PATH_FORTUNE);
93 char buf[128], buf2[8*sizeof(buf)];
94 while (fgets(buf, sizeof(buf), f)) {
95 char *s = strrchr(buf, '\n');
101 for (i=j=0; buf[i]; i++) {
104 while (j%8) buf2[j++] = ' ';
106 else if (buf[i]=='\b') {
115 stringarray_add(&lines, buf2);
116 stringarray_add(&sollines, buf2);
122 static void encode(void) {
124 for (int i=0; i<26; i++) key[i] = i;
125 for (int i=26; i>1; i--) {
126 int c = random() % i;
132 for (int y=0; y<lines.num; y++) {
133 for (unsigned x=0; lines.v[y][x]; x++) {
134 if (islower((unsigned char)lines.v[y][x])) {
135 int q = lines.v[y][x]-'a';
136 lines.v[y][x] = 'a'+key[q];
138 if (isupper((unsigned char)lines.v[y][x])) {
139 int q = lines.v[y][x]-'A';
140 lines.v[y][x] = 'A'+key[q];
146 static int substitute(int ch) {
147 assert(cury>=0 && cury<lines.num);
148 if (curx >= strlen(lines.v[cury])) {
153 int och = lines.v[cury][curx];
154 if (!isalpha((unsigned char)och)) {
159 int loch = tolower((unsigned char)och);
160 int uoch = toupper((unsigned char)och);
161 int lch = tolower((unsigned char)ch);
162 int uch = toupper((unsigned char)ch);
164 for (int y=0; y<lines.num; y++) {
165 for (unsigned x=0; lines.v[y][x]; x++) {
166 if (lines.v[y][x]==loch) {
169 else if (lines.v[y][x]==uoch) {
172 else if (lines.v[y][x]==lch) {
173 lines.v[y][x] = loch;
175 else if (lines.v[y][x]==uch) {
176 lines.v[y][x] = uoch;
183 ////////////////////////////////////////////////////////////
185 static void redraw(void) {
188 for (int i=0; i<LINES-1; i++) {
190 int ln = i+scrolldown;
191 if (ln < lines.num) {
192 for (unsigned j=0; lines.v[i][j]; j++) {
193 int ch = lines.v[i][j];
194 if (ch != sollines.v[i][j] && isalpha((unsigned char)ch)) {
198 if (hinting && ch==sollines.v[i][j] &&
199 isalpha((unsigned char)ch)) {
203 addch(lines.v[i][j]);
216 addstr("~ to quit, * to cheat, ^pnfb to move");
220 move(cury-scrolldown, curx);
225 static void opencurses(void) {
231 static void closecurses(void) {
235 ////////////////////////////////////////////////////////////
237 static void loop(void) {
254 curx = strlen(lines.v[cury]);
259 curx = strlen(lines.v[cury]);
263 if (curx < strlen(lines.v[cury])) {
266 else if (cury < lines.num - 1) {
276 if (cury < lines.num-1) {
279 if (curx > strlen(lines.v[cury])) {
280 curx = strlen(lines.v[cury]);
282 if (scrolldown < cury - (LINES-2)) {
283 scrolldown = cury - (LINES-2);
291 if (curx > strlen(lines.v[cury])) {
292 curx = strlen(lines.v[cury]);
294 if (scrolldown > cury) {
306 if (!substitute(ch)) {
307 if (curx < strlen(lines.v[cury])) {
310 if (curx==strlen(lines.v[cury]) && cury < lines.num-1) {
316 else if (curx < strlen(lines.v[cury]) && ch==lines.v[cury][curx]) {
318 if (curx==strlen(lines.v[cury]) && cury < lines.num-1) {
331 ////////////////////////////////////////////////////////////
334 stringarray_init(&lines);
335 stringarray_init(&sollines);
341 keypad(stdscr, TRUE);
345 stringarray_cleanup(&sollines);
346 stringarray_cleanup(&lines);