]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - cgram/cgram.c
93ebddd9b936de234f09373184cee5162be1f6c0
1 /* $NetBSD: cgram.c,v 1.13 2021/02/22 17:36:42 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.13 2021/02/22 17:36:42 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 isspace((unsigned char)ch
) != 0;
84 return isupper((unsigned char)ch
) != 0;
99 ////////////////////////////////////////////////////////////
113 string_init(struct string
*s
)
121 string_add(struct string
*s
, char ch
)
123 if (s
->len
>= s
->cap
) {
124 s
->cap
= 2 * s
->cap
+ 16;
125 s
->s
= realloc(s
->s
, s
->cap
);
127 errx(1, "Out of memory");
133 string_finish(struct string
*s
)
140 stringarray_init(struct stringarray
*a
)
147 stringarray_cleanup(struct stringarray
*a
)
149 for (size_t i
= 0; i
< a
->num
; i
++)
155 stringarray_add(struct stringarray
*a
, struct string
*s
)
157 size_t num
= a
->num
++;
158 a
->v
= realloc(a
->v
, a
->num
* sizeof a
->v
[0]);
160 errx(1, "Out of memory");
165 stringarray_dup(struct stringarray
*dst
, const struct stringarray
*src
)
167 assert(dst
->num
== 0);
168 for (size_t i
= 0; i
< src
->num
; i
++) {
171 for (const char *p
= src
->v
[i
].s
; *p
!= '\0'; p
++)
172 string_add(&str
, *p
);
174 stringarray_add(dst
, &str
);
178 ////////////////////////////////////////////////////////////
180 static struct stringarray lines
;
181 static struct stringarray sollines
;
193 return (int)lines
.v
[cursor_y
].len
;
203 char_left_of_cursor(void)
206 return lines
.v
[cursor_y
].s
[cursor_x
- 1];
207 assert(cursor_y
> 0);
208 return '\n'; /* eol of previous line */
214 if (cursor_x
== cur_max_x())
216 return lines
.v
[cursor_y
].s
[cursor_x
];
222 FILE *f
= popen(_PATH_FORTUNE
, "r");
224 err(1, "%s", _PATH_FORTUNE
);
230 while ((ch
= fgetc(f
)) != EOF
) {
232 string_finish(&line
);
233 stringarray_add(&lines
, &line
);
235 } else if (ch
== '\t') {
236 string_add(&line
, ' ');
237 while (line
.len
% 8 != 0)
238 string_add(&line
, ' ');
239 } else if (ch
== '\b') {
243 string_add(&line
, (char)ch
);
247 stringarray_dup(&sollines
, &lines
);
249 extent_y
= (int)lines
.num
;
250 for (int i
= 0; i
< extent_y
; i
++)
251 extent_x
= imax(extent_x
, (int)lines
.v
[i
].len
);
254 exit(1); /* error message must come from child process */
262 for (int i
= 0; i
< 26; i
++)
265 for (int i
= 26; i
> 1; i
--) {
266 int c
= (int)(random() % i
);
272 for (int y
= 0; y
< extent_y
; y
++) {
273 for (char *p
= lines
.v
[y
].s
; *p
!= '\0'; p
++) {
275 *p
= (char)('a' + key
[*p
- 'a']);
277 *p
= (char)('A' + key
[*p
- 'A']);
285 assert(cursor_x
>= 0 && cursor_x
< extent_x
);
286 assert(cursor_y
>= 0 && cursor_y
< extent_y
);
287 if (cursor_x
>= cur_max_x()) {
292 char och
= char_at_cursor();
293 if (!ch_isalpha(och
)) {
298 char loch
= ch_tolower(och
);
299 char uoch
= ch_toupper(och
);
300 char lch
= ch_tolower(ch
);
301 char uch
= ch_toupper(ch
);
303 for (int y
= 0; y
< (int)lines
.num
; y
++) {
304 for (char *p
= lines
.v
[y
].s
; *p
!= '\0'; p
++) {
321 for (size_t i
= 0; i
< lines
.num
; i
++)
322 if (strcmp(lines
.v
[i
].s
, sollines
.v
[i
].s
) != 0)
327 ////////////////////////////////////////////////////////////
334 int max_y
= imin(LINES
- 1, extent_y
- offset_y
);
335 for (int y
= 0; y
< max_y
; y
++) {
338 int len
= (int)lines
.v
[offset_y
+ y
].len
;
339 int max_x
= imin(COLS
- 1, len
- offset_x
);
340 const char *line
= lines
.v
[offset_y
+ y
].s
;
341 const char *solline
= sollines
.v
[offset_y
+ y
].s
;
343 for (int x
= 0; x
< max_x
; x
++) {
344 char ch
= line
[offset_x
+ x
];
345 bool bold
= hinting
&&
346 ch
== solline
[offset_x
+ x
] &&
361 addstr("~ to quit, * to cheat, ^pnfb to move");
363 move(cursor_y
- offset_y
, cursor_x
- offset_x
);
368 ////////////////////////////////////////////////////////////
371 saturate_cursor(void)
373 cursor_y
= imax(cursor_y
, 0);
374 cursor_y
= imin(cursor_y
, cur_max_y());
376 assert(cursor_x
>= 0);
377 cursor_x
= imin(cursor_x
, cur_max_x());
381 scroll_into_view(void)
383 if (cursor_x
< offset_x
)
385 if (cursor_x
> offset_x
+ COLS
- 1)
386 offset_x
= cursor_x
- (COLS
- 1);
388 if (cursor_y
< offset_y
)
390 if (cursor_y
> offset_y
+ LINES
- 2)
391 offset_y
= cursor_y
- (LINES
- 2);
397 return cursor_y
> 0 ||
398 (cursor_y
== 0 && cursor_x
> 0);
404 return cursor_y
< cur_max_y() ||
405 (cursor_y
== cur_max_y() && cursor_x
< cur_max_x());
409 go_to_prev_line(void)
412 cursor_x
= cur_max_x();
416 go_to_next_line(void)
427 else if (cursor_y
> 0)
434 if (cursor_x
< cur_max_x())
436 else if (cursor_y
< cur_max_y())
441 go_to_prev_word(void)
443 while (can_go_left() && ch_isspace(char_left_of_cursor()))
446 while (can_go_left() && !ch_isspace(char_left_of_cursor()))
451 go_to_next_word(void)
453 while (can_go_right() && !ch_isspace(char_at_cursor()))
456 while (can_go_right() && ch_isspace(char_at_cursor()))
461 handle_char_input(int ch
)
463 if (isascii(ch
) && ch_isalpha((char)ch
)) {
464 if (substitute((char)ch
)) {
465 if (cursor_x
< cur_max_x())
467 if (cursor_x
== cur_max_x())
470 } else if (ch
== char_at_cursor())
492 cursor_x
= cur_max_x();
519 cursor_y
-= LINES
- 2;
522 cursor_y
+= LINES
- 2;
530 handle_char_input(ch
);
539 stringarray_init(&lines
);
540 stringarray_init(&sollines
);
541 srandom((unsigned int)time(NULL
));
548 keypad(stdscr
, true);
568 stringarray_cleanup(&sollines
);
569 stringarray_cleanup(&lines
);
572 ////////////////////////////////////////////////////////////