/*- * Copyright (c) 2013 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by David A. Holland. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include "pathnames.h" //////////////////////////////////////////////////////////// static char *xstrdup(const char *s) { char *ret; ret = malloc(strlen(s) + 1); if (ret == NULL) { errx(1, "Out of memory"); } strcpy(ret, s); return ret; } //////////////////////////////////////////////////////////// struct stringarray { char **v; int num; }; static void stringarray_init(struct stringarray *a) { a->v = NULL; a->num = 0; } static void stringarray_cleanup(struct stringarray *a) { free(a->v); } static void stringarray_add(struct stringarray *a, const char *s) { a->v = realloc(a->v, (a->num + 1) * sizeof(a->v[0])); if (a->v == NULL) { errx(1, "Out of memory"); } a->v[a->num] = xstrdup(s); a->num++; } //////////////////////////////////////////////////////////// static struct stringarray lines; static struct stringarray sollines; static bool hinting; static int scrolldown; static unsigned curx; static int cury; static void readquote(void) { FILE *f = popen(_PATH_FORTUNE, "r"); if (!f) { err(1, "%s", _PATH_FORTUNE); } char buf[128], buf2[8*sizeof(buf)]; while (fgets(buf, sizeof(buf), f)) { char *s = strrchr(buf, '\n'); assert(s); assert(strlen(s)==1); *s = 0; int i,j; for (i=j=0; buf[i]; i++) { if (buf[i]=='\t') { buf2[j++] = ' '; while (j%8) buf2[j++] = ' '; } else if (buf[i]=='\b') { if (j>0) j--; } else { buf2[j++] = buf[i]; } } buf2[j] = 0; stringarray_add(&lines, buf2); stringarray_add(&sollines, buf2); } pclose(f); } static void encode(void) { int used[26]; for (int i=0; i<26; i++) used[i] = 0; int key[26]; int keypos=0; while (keypos < 26) { int c = random()%26; if (used[c]) continue; key[keypos++] = c; used[c] = 1; } for (int y=0; y=0 && cury= strlen(lines.v[cury])) { beep(); return -1; } int och = lines.v[cury][curx]; if (!isalpha((unsigned char)och)) { beep(); return -1; } int loch = tolower((unsigned char)och); int uoch = toupper((unsigned char)och); int lch = tolower((unsigned char)ch); int uch = toupper((unsigned char)ch); for (int y=0; y 0) { curx--; } else if (cury > 0) { cury--; curx = strlen(lines.v[cury]); } break; case 5: /* ^E */ curx = strlen(lines.v[cury]); break; case 6: /* ^F */ if (curx < strlen(lines.v[cury])) { curx++; } else if (cury < lines.num - 1) { cury++; curx = 0; } break; case 12: /* ^L */ clear(); break; case 14: /* ^N */ if (cury < lines.num-1) { cury++; } if (curx > strlen(lines.v[cury])) { curx = strlen(lines.v[cury]); } if (scrolldown < cury - (LINES-2)) { scrolldown = cury - (LINES-2); } break; case 16: /* ^P */ if (cury > 0) { cury--; } if (curx > strlen(lines.v[cury])) { curx = strlen(lines.v[cury]); } if (scrolldown > cury) { scrolldown = cury; } break; case '*': hinting = !hinting; break; case '~': done = true; break; default: if (isalpha(ch)) { if (!substitute(ch)) { if (curx < strlen(lines.v[cury])) { curx++; } if (curx==strlen(lines.v[cury]) && cury < lines.num-1) { curx=0; cury++; } } } else if (curx < strlen(lines.v[cury]) && ch==lines.v[cury][curx]) { curx++; if (curx==strlen(lines.v[cury]) && cury < lines.num-1) { curx=0; cury++; } } else { beep(); } break; } } } //////////////////////////////////////////////////////////// int main(void) { stringarray_init(&lines); stringarray_init(&sollines); srandom(time(NULL)); readquote(); encode(); opencurses(); loop(); closecurses(); stringarray_cleanup(&sollines); stringarray_cleanup(&lines); return 0; }