2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 2 of the License, or (at your option)
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
17 // Suite 330, Boston, MA 02111-1307 USA
20 // gmcnutt@users.sourceforge.net
28 #include "dimensions.h"
38 #define CMDWIN_FRAG_MAX_LEN 64
39 #define CMDWIN_BUF_SZ 256
42 #define CMDWIN_FRAG_SEP (1<<0)
43 #define CMDWIN_FRAG_MARK (1<<1)
48 char buf[CMDWIN_FRAG_MAX_LEN];
52 SDL_Rect srect; /* screen rectangle (pixels) */
53 char *buf; /* string buffer */
54 char *ptr; /* next empty spot in buffer */
55 int blen; /* buffer length, this should be bigger than slen and
56 * is the max expected total size of any prompt (the
57 * longest prompts may be too big for the window) */
58 int room; /* empty space in buffer */
59 int slen; /* printable string length (blen >= slen), this is
60 * limited by the cmdwin UI size */
61 struct sprite *cursor_sprite;
66 static FILE *log = NULL;
69 struct dictionary *dictionary = NULL;
71 static inline void cmdwin_clear_no_repaint()
73 memset(cmdwin.buf, 0, cmdwin.blen);
74 cmdwin.ptr = cmdwin.buf;
75 cmdwin.room = cmdwin.blen;
78 static void cmdwin_cursor_sprite_init()
80 char *fname = cfg_get("cursor-image-filename");
81 struct images *ss_cursor = 0;
84 ss_cursor = images_new(0, 8, 16, 1, 4, 0, 0, fname);
86 cmdwin.cursor_sprite = sprite_new(0, 4, 0, 0, 0, ss_cursor);
87 assert(cmdwin.cursor_sprite);
90 static void cmdwin_clear_frag_stack(void)
94 entry = cmdwin.frags.next;
95 while (entry != &cmdwin.frags) {
96 struct cmdwin_frag *frag = (struct cmdwin_frag*)entry;
98 list_remove(&frag->list);
103 static struct cmdwin_frag *cmdwin_top()
105 if (list_empty(&cmdwin.frags))
107 return (struct cmdwin_frag*)cmdwin.frags.prev;
110 static void cmdwin_reprint_buffer(void)
114 /* Erase the buffer */
115 cmdwin_clear_no_repaint();
117 /* Loop over the fragments until out of room or out of fragments */
118 list_for_each(&cmdwin.frags, entry) {
119 struct cmdwin_frag *frag = (struct cmdwin_frag*)entry;
122 /* Append the fragment to the buffer. */
123 if ((frag->flags & CMDWIN_FRAG_SEP)
124 && (entry->next != &cmdwin.frags)) {
125 /* Print a '-' after this fragment. */
126 n = snprintf(cmdwin.ptr, cmdwin.room, "%s-", frag->buf);
128 /* No '-' afterwards. */
129 n = snprintf(cmdwin.ptr, cmdwin.room, "%s", frag->buf);
131 n = min(n, cmdwin.room);
135 /* If out of room then stop, and backup the ptr to the last
136 * entry in the buffer */
145 int cmdwin_init(void)
147 cmdwin_cursor_sprite_init();
149 list_init(&cmdwin.frags);
151 cmdwin.srect.x = CMD_X;
152 cmdwin.srect.y = CMD_Y;
153 cmdwin.srect.w = CMD_W;
154 cmdwin.srect.h = CMD_H;
155 cmdwin.slen = (CMD_W / ASCII_W) - 1; /* leave one space for the
157 cmdwin.blen = CMDWIN_BUF_SZ;
158 assert(cmdwin.blen >= cmdwin.slen);
160 cmdwin.buf = (char *) malloc(cmdwin.blen);
165 log = fopen(".cmdwin", "w+");
167 err(strerror(errno));
172 cmdwin_clear_no_repaint();
176 static void cmdwin_vpush(int flags, const char *fmt, va_list args)
178 /* Allocate a new fragment */
179 struct cmdwin_frag *frag = (struct cmdwin_frag*)malloc(sizeof(*frag));
181 warn("allocation failed");
187 /* default to empty string */
190 /* Store the string in the fragment */
192 vsnprintf(frag->buf, sizeof(frag->buf), fmt, args);
195 /* Push the fragment onto the stack */
196 list_add_tail(&cmdwin.frags, &frag->list);
198 /* Reprint the buffer with the new fragment */
199 cmdwin_reprint_buffer();
201 /* Update the display */
205 void cmdwin_spush(const char *fmt, ...)
210 cmdwin_vpush(CMDWIN_FRAG_SEP, fmt, args);
215 void cmdwin_push(const char *fmt, ...)
220 cmdwin_vpush(0, fmt, args);
224 void cmdwin_push_mark()
226 cmdwin_vpush(CMDWIN_FRAG_MARK, 0, 0);
229 void cmdwin_pop(void)
231 struct cmdwin_frag *frag;
233 /* Fragment stack should not be empty. */
234 assert(! list_empty(&cmdwin.frags));
236 /* Remove the last fragment and free it. */
237 frag = (struct cmdwin_frag*)cmdwin.frags.prev;
238 list_remove(&frag->list);
241 /* Reprint the buffer without the fragment */
242 cmdwin_reprint_buffer();
244 /* Update the display */
248 void cmdwin_pop_to_mark()
250 struct cmdwin_frag *frag = cmdwin_top();
251 while (frag && frag->flags != CMDWIN_FRAG_MARK) {
256 /* DON'T pop the mark itself */
259 void cmdwin_clear(void)
261 cmdwin_clear_frag_stack();
262 cmdwin_clear_no_repaint();
266 void cmdwin_repaint_cursor(void)
270 rect.x = cmdwin.srect.x;
271 rect.y = cmdwin.srect.y;
275 /* If the string is too big, show the last part of it (in other words,
276 * right-justify it) */
277 char *start = max(cmdwin.buf, cmdwin.ptr - cmdwin.slen);
278 rect.x += (cmdwin.ptr - start) * ASCII_W;
280 sprite_paint(cmdwin.cursor_sprite, 0, rect.x, rect.y);
284 void cmdwin_repaint(void)
286 /* If the string is too big, show the last part of it (in other words,
287 * right-justify it) */
288 char *start = max(cmdwin.buf, cmdwin.ptr - cmdwin.slen);
289 screenErase(&cmdwin.srect);
290 screenPrint(&cmdwin.srect, 0, start);
291 screenUpdate(&cmdwin.srect);
292 cmdwin_repaint_cursor();
295 void cmdwin_flush(void)
297 if (!strlen(cmdwin.buf))
300 log_msg("%s\n", cmdwin.buf);
304 int kana_to_english(char *kana, char *english, char *kanji)
308 for (i = 0; dictionary[i].kana != NULL; i++) {
309 if (!strcmp(kana, dictionary[i].kana)) {
311 strcpy(english, dictionary[i].english);
314 strcpy(kanji, dictionary[i].kanji);
321 strcpy(english, kana);
329 int alpha_to_kana(int key, char *buf)
331 const static struct {
617 static int roman = true;
618 static char roman_buf[] = { "\0\0\0\0\0" };
624 if (key == 0) { /* Clear roman buffer */
625 memset(roman_buf, 0, sizeof(roman_buf));
628 if (key == -1) { /* Roman mode off */
632 if (key == '\t') { /* Toggle roman mode */
634 memset(roman_buf, 0, sizeof(roman_buf));
638 if (!roman || (key & 0x80) || !isprint(key)) {
639 memset(roman_buf, 0, sizeof(roman_buf));
643 memmove(roman_buf + 1, roman_buf, sizeof (roman_buf) - 1);
646 for (i = 0; kana[i].alpha != NULL; i++) {
647 len = strlen(kana[i].alpha);
649 if (!strncasecmp(roman_buf, kana[i].alpha, len)) {
650 soku = (roman_buf[len - 1] == roman_buf[len]);
653 n = (roman_buf[len + 1] == 'n');
655 n = (roman_buf[len] == 'n');
657 sprintf (buf, "%.*s%s%s%s", len + n + soku, "\b\b\b\b\b", (n ? "¥ó": ""), (soku ? "¥Ã": ""), kana[i].kana);
659 memset(roman_buf, 0, sizeof (roman_buf));