]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - cgram/cgram.c
1 /* $NetBSD: cgram.c,v 1.11 2021/02/21 22:21:56 rillig Exp $ */
4 * Copyright (c) 2013, 2021 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by David A. Holland and Roland Illig.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #if defined(__RCSID) && !defined(lint)
34 __RCSID("$NetBSD: cgram.c,v 1.11 2021/02/21 22:21:56 rillig Exp $");
47 #include "pathnames.h"
49 ////////////////////////////////////////////////////////////
54 return (char)toupper((unsigned char)ch
);
60 return (char)tolower((unsigned char)ch
);
66 return isalpha((unsigned char)ch
) != 0;
72 return islower((unsigned char)ch
) != 0;
78 return isupper((unsigned char)ch
) != 0;
93 ////////////////////////////////////////////////////////////
107 string_init(struct string
*s
)
115 string_add(struct string
*s
, char ch
)
117 if (s
->len
>= s
->cap
) {
118 s
->cap
= 2 * s
->cap
+ 16;
119 s
->s
= realloc(s
->s
, s
->cap
);
121 errx(1, "Out of memory");
127 string_finish(struct string
*s
)
134 stringarray_init(struct stringarray
*a
)
141 stringarray_cleanup(struct stringarray
*a
)
143 for (size_t i
= 0; i
< a
->num
; i
++)
149 stringarray_add(struct stringarray
*a
, struct string
*s
)
151 size_t num
= a
->num
++;
152 a
->v
= realloc(a
->v
, a
->num
* sizeof a
->v
[0]);
154 errx(1, "Out of memory");
159 stringarray_dup(struct stringarray
*dst
, const struct stringarray
*src
)
161 assert(dst
->num
== 0);
162 for (size_t i
= 0; i
< src
->num
; i
++) {
165 for (const char *p
= src
->v
[i
].s
; *p
!= '\0'; p
++)
166 string_add(&str
, *p
);
168 stringarray_add(dst
, &str
);
172 ////////////////////////////////////////////////////////////
174 static struct stringarray lines
;
175 static struct stringarray sollines
;
187 return (int)lines
.v
[cursor_y
].len
;
199 FILE *f
= popen(_PATH_FORTUNE
, "r");
201 err(1, "%s", _PATH_FORTUNE
);
207 while ((ch
= fgetc(f
)) != EOF
) {
209 string_finish(&line
);
210 stringarray_add(&lines
, &line
);
212 } else if (ch
== '\t') {
213 string_add(&line
, ' ');
214 while (line
.len
% 8 != 0)
215 string_add(&line
, ' ');
216 } else if (ch
== '\b') {
220 string_add(&line
, (char)ch
);
224 stringarray_dup(&sollines
, &lines
);
226 extent_y
= (int)lines
.num
;
227 for (int i
= 0; i
< extent_y
; i
++)
228 extent_x
= imax(extent_x
, (int)lines
.v
[i
].len
);
238 for (int i
= 0; i
< 26; i
++)
241 for (int i
= 26; i
> 1; i
--) {
242 int c
= (int)(random() % i
);
248 for (int y
= 0; y
< extent_y
; y
++) {
249 for (char *p
= lines
.v
[y
].s
; *p
!= '\0'; p
++) {
251 *p
= (char)('a' + key
[*p
- 'a']);
253 *p
= (char)('A' + key
[*p
- 'A']);
261 assert(cursor_x
>= 0 && cursor_x
< extent_x
);
262 assert(cursor_y
>= 0 && cursor_y
< extent_y
);
263 if (cursor_x
>= cur_max_x()) {
268 char och
= lines
.v
[cursor_y
].s
[cursor_x
];
269 if (!ch_isalpha(och
)) {
274 char loch
= ch_tolower(och
);
275 char uoch
= ch_toupper(och
);
276 char lch
= ch_tolower(ch
);
277 char uch
= ch_toupper(ch
);
279 for (int y
= 0; y
< (int)lines
.num
; y
++) {
280 for (char *p
= lines
.v
[y
].s
; *p
!= '\0'; p
++) {
294 ////////////////////////////////////////////////////////////
299 for (size_t i
= 0; i
< lines
.num
; i
++)
300 if (strcmp(lines
.v
[i
].s
, sollines
.v
[i
].s
) != 0)
310 int max_y
= imin(LINES
- 1, extent_y
- offset_y
);
311 for (int y
= 0; y
< max_y
; y
++) {
314 int len
= (int)lines
.v
[offset_y
+ y
].len
;
315 int max_x
= imin(COLS
- 1, len
- offset_x
);
316 const char *line
= lines
.v
[offset_y
+ y
].s
;
317 const char *solline
= sollines
.v
[offset_y
+ y
].s
;
319 for (int x
= 0; x
< max_x
; x
++) {
320 char ch
= line
[offset_x
+ x
];
321 bool bold
= hinting
&&
322 ch
== solline
[offset_x
+ x
] &&
337 addstr("~ to quit, * to cheat, ^pnfb to move");
339 move(cursor_y
- offset_y
, cursor_x
- offset_x
);
350 keypad(stdscr
, true);
359 ////////////////////////////////////////////////////////////
362 saturate_cursor(void)
364 cursor_y
= imax(cursor_y
, 0);
365 cursor_y
= imin(cursor_y
, cur_max_y());
367 assert(cursor_x
>= 0);
368 cursor_x
= imin(cursor_x
, cur_max_x());
372 scroll_into_view(void)
374 if (cursor_x
< offset_x
)
376 if (cursor_x
> offset_x
+ COLS
- 1)
377 offset_x
= cursor_x
- (COLS
- 1);
379 if (cursor_y
< offset_y
)
381 if (cursor_y
> offset_y
+ LINES
- 2)
382 offset_y
= cursor_y
- (LINES
- 2);
386 handle_char_input(int ch
)
388 if (isascii(ch
) && ch_isalpha((char)ch
)) {
389 if (substitute((char)ch
)) {
390 if (cursor_x
< cur_max_x())
392 if (cursor_x
== cur_max_x() &&
393 cursor_y
< cur_max_y()) {
398 } else if (cursor_x
< cur_max_x() &&
399 ch
== lines
.v
[cursor_y
].s
[cursor_x
]) {
401 if (cursor_x
== cur_max_x() &&
402 cursor_y
< cur_max_y()) {
425 } else if (cursor_y
> 0) {
427 cursor_x
= cur_max_x();
432 cursor_x
= cur_max_x();
436 if (cursor_x
< cur_max_x()) {
438 } else if (cursor_y
< cur_max_y()) {
455 cursor_y
-= LINES
- 2;
458 cursor_y
+= LINES
- 2;
466 handle_char_input(ch
);
475 stringarray_init(&lines
);
476 stringarray_init(&sollines
);
477 srandom((unsigned int)time(NULL
));
499 stringarray_cleanup(&sollines
);
500 stringarray_cleanup(&lines
);
503 ////////////////////////////////////////////////////////////