OSDN Git Service

Nazghul-0.7.1
[nazghul-jp/nazghul-jp.git] / src / ascii.c
1 //
2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
4 //
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)
8 // any later version.
9 //
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
13 // more details.
14 //
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
18 //
19 // Gordon McNutt
20 // gmcnutt@users.sourceforge.net
21 //
22 #include "ascii.h"
23 #include "images.h"
24 #include "screen.h"
25 #include "common.h"
26 #include "cfg.h"
27 #include "dimensions.h"
28
29 #include <SDL_image.h>
30
31 #include <assert.h>
32
33
34 #define DEBUG 0
35 #if DEBUG
36 /* To see the function names in backtraces, you need to ask gcc to
37  * add them to the binary with the -rdynamic linker (LDFLAGS) option
38  * and disable the static keyword for objects which static functions
39  * you'd like to see, either with -Dstatic= compiler option or just
40  * using in those sources following: */
41 #define static
42
43 #include <execinfo.h>
44 #define MAX_STACK_DEPTH 16
45 static void backtrace2stderr(void)
46 {
47         int depth;
48         void *bt[MAX_STACK_DEPTH];
49         depth = backtrace(bt, MAX_STACK_DEPTH);
50         if (depth > 1) {
51                 /* skip this fuction and C++ main, show rest */
52                 backtrace_symbols_fd(bt+1, depth-2, 2);
53         }
54 }
55 #endif /* DEBUG */
56
57
58 #define ASCII_DEF_CLR White /* default printing color is white */
59 #define ASCII_CLR_STK_SZ 32
60
61 /* State machine states for embedded control sequences. */
62 enum ascii_ctrl_states {
63         ASCII_STATE_DEF = 0,
64         ASCII_STATE_ESC,
65         ASCII_STATE_CLR,
66         ASCII_STATE_CLRPUSH
67 };
68
69 /* This is a default character image set in XPM format. For emergency use
70  * only. */
71 static const char * charset_xpm[] = {
72 "128 144 44 1",
73 "       c None",
74 ".      c #000000",
75 "+      c #004040",
76 "@      c #20FCFC",
77 "#      c #E0FCFC",
78 "$      c #000060",
79 "%      c #000080",
80 "&      c #0000A0",
81 "*      c #0000C0",
82 "=      c #E8E8E8",
83 "-      c #C0C0C0",
84 ";      c #808080",
85 ">      c #FCFCFC",
86 ",      c #B0B0B0",
87 "'      c #D4D4D4",
88 ")      c #008080",
89 "!      c #006060",
90 "~      c #800000",
91 "{      c #FC1000",
92 "]      c #404040",
93 "^      c #505050",
94 "/      c #4040FC",
95 "(      c #600000",
96 "_      c #400000",
97 ":      c #A0A0A0",
98 "<      c #C0C0FC",
99 "[      c #C00000",
100 "}      c #303030",
101 "|      c #909090",
102 "1      c #8080FC",
103 "2      c #000040",
104 "3      c #0000FC",
105 "4      c #6060FC",
106 "5      c #0000E0",
107 "6      c #A00000",
108 "7      c #202020",
109 "8      c #101010",
110 "9      c #606060",
111 "0      c #FCFC80",
112 "a      c #FCFCE0",
113 "b      c #FCFCA0",
114 "c      c #A0A0FC",
115 "d      c #FCFC40",
116 "e      c #FCFCC0",
117 ".+@##@+.$%%&*&%$=-;-=-;-=-;-=-;-...;>......;-......;>....+@##@+............->>.....->>.............->>..........,-''''-,........",
118 ".+@##@+.$%%&*&%$=-;-=-;-=-;-=-;-...;>......;-......;>....+@##@+............->>.....->>.............->>..........,-''''-,........",
119 ".@#)!#@.%~{{{{~%;.;;;;.;;;;;;;;;..;;->.....;-.....;;->...@#)!#@...];;]....-^^^>...-^^^>......->>..->^->.////////-......-..$&&$..",
120 ".@#)!#@.%~{{{{~%;.;;;;.;;;;;;;;;..;;->.....;-.....;;->...@#)!#@...];;]....-^^^>...-^^^>......->>..->^->.////////-......-..$&&$..",
121 ".@#.+#@.&~(__(~&;-=-;-=-;-=-;-=-.;;-->>....;-....;;-->>..........^:'=:^..-.->>^>.-.-->^>....^^->.^->^->.<<<<<<<<'......'.%*//*%.",
122 ".@#.+#@.&~(__(~&;-=-;-=-;-=-;-=-.;;-->>....;-....;;-->>..........^:'=:^..-.->>^>.-.-->^>....^^->.^->^->.<<<<<<<<'......'.%*//*%.",
123 ".+@##@+.*~[__[~*;;;;;;;;;;;;;;;;...;;......;-......;;....+@##@+.}|'>>'|}^-^-^.^>^-^->^^>..->>-^>.^^->>..11111111'......'2&341/&2",
124 ".+@##@+.*~[__[~*;;;;;;;;;;;;;;;;...;;......;-......;;....+@##@+.}|'>>'|}^-^-^.^>^-^->^^>..->>-^>.^^->>..11111111'......'2&341/&2",
125 "+@####@+&~(__(~&=-;-=-;-=-;-=-;=...;-......;-......;-...........}|--''|}^-^->>^>^-^-^>^>.->^->^...^^>...////////'......'2&55/3&2",
126 "+@####@+&~(__(~&=-;-=-;-=-;-=-;=...;-......;-......;-...........}|--''|}^-^->>^>^-^-^>^>.->^->^...^^>...////////'......'2&55/3&2",
127 "..+@#+..%~6__6~%;;;;;;;;;;;;;;;;.;;-->>..;;-->>....;-.....+@#+...^:--:^.^^-^^.>.^^-^^.>.^->^->.....->>..********'......'.%*55*%.",
128 "..+@#+..%~6__6~%;;;;;;;;;;;;;;;;.;;-->>..;;-->>....;-.....+@#+...^:--:^.^^-^^.>.^^-^^.>.^->^->.....->>..********'......'.%*55*%.",
129 "..+@#+..2%~66~%2;.=-;-.-;-=-;-=-..;;->....;;->.....;-.....+@#+....];;]...^^-->...^^-->..^^->>.....^^-...%%%%%%%%-......-..$&&$..",
130 "..+@#+..2%~66~%2;.=-;-.-;-=-;-=-..;;->....;;->.....;-.....+@#+....];;]...^^-->...^^-->..^^->>.....^^-...%%%%%%%%-......-..$&&$..",
131 "..+@#+...2%~~%2.;;;;;;;;;;;;;;;;...;>......;>......;-.....+@#+............^^^.....^^^....^^^.......^............,-''''-,........",
132 "..+@#+...2%~~%2.;;;;;;;;;;;;;;;;...;>......;>......;-.....+@#+............^^^.....^^^....^^^.......^............,-''''-,........",
133 "..................................;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888....2%%&&$..%*55*$..%5/5$2..222$$2.",
134 "..................................;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888....2%%&&$..%*55*$..%5/5$2..222$$2.",
135 "/*%..........%*/.................,9778...,>978...,>0,7...,>a>,...7,>b,...879>,...8779,...87778..2$2$$%*%$*%%%*5%$5*&*5%22%**%2$2",
136 "/*%..........%*/.................,9778...,>978...,>0,7...,>a>,...7,>b,...879>,...8779,...87778..2$2$$%*%$*%%%*5%$5*&*5%22%**%2$2",
137 "<5*$........$*5c................;'77778.;>b^778.;>>>b97.|>00a0|.79b>b>;.877^b>;.87777';.8777778.$2&53&%*&%&3/**5***/%/*2$5//5&2%",
138 "<5*$........$*5c................;'77778.;>b^778.;>>>b97.|>00a0|.79b>b>;.877^b>;.87777';.8777778.$2&53&%*&%&3/**5***/%/*2$5//5&2%",
139 "135%........%531................,=77778.,>a9778.,>bbd;7.,>>>0b,.7;eded-.8779a>,.87777=,.8777778.$%5**3%5&$3**/&/5%/*%/*25*%%*5$%",
140 "135%........%531................,=77778.,>a9778.,>bbd;7.,>>>0b,.7;eded-.8779a>,.87777=,.8777778.$%5**3%5&$3**/&/5%/*%/*25*%%*5$%",
141 "//5%........%5//................;'77778.;>e^778.;>d>097.|>b>ad|.79b>>>;.877^b>;.87777';.8777778.2*/%*/%5%$5*%%*55%3**5%$/&/**3$&",
142 "//5%........%5//................;'77778.;>e^778.;>d>097.|>b>ad|.79b>>>;.877^b>;.87777';.8777778.2*/%*/%5%$5*%%*55%3**5%$/&/**3$&",
143 "**%$........$%**........->.->.->.,9778...,>978...,>b,7...,>>0,...7,b>,...879>,...8779,...87778..2*/%/***%2&5//5$*%&35&2$5**/3&%&",
144 "**%$........$%**........->.->.->.,9778...,>978...,>b,7...,>>0,...7,b>,...879>,...8779,...87778..2*/%/***%2&5//5$*%&35&2$5**/3&%&",
145 "%%$..........$%%........->^->^->..;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888...2%5*&*5$2$2%**%2%*%$$2$2%5*%%%*$",
146 "%%$..........$%%........->^->^->..;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888...2%5*&*5$2$2%**%2%*%$$2$2%5*%%%*$",
147 "........................^.^^.^^..................................................................2$5/5%..2$$222..$&&%%2..$*55*%.",
148 "........................^.^^.^^..................................................................2$5/5%..2$$222..$&&%%2..$*55*%.",
149 "...........->.....->.->.............>..............->>....->........->....->..................................................->",
150 "...........->.....->.->.............>..............->>....->........->....->..................................................->",
151 "..........^->....^->^->...->.->...->>>>..->...->..->^->..^->.......->....^^->.....->.->....->................................->.",
152 "..........^->....^->^->...->.->...->>>>..->...->..->^->..^->.......->....^^->.....->.->....->................................->.",
153 "..........^->....^->^->..->>>>>>.->^>^..^->..->..^^->>...->.......->......^^->...^^->>....^->...............................->..",
154 "..........^->....^->^->..->>>>>>.->^>^..^->..->..^^->>...->.......->......^^->...^^->>....^->...............................->..",
155 "..........^->....^^.^^..^^->^->.^^->>>>.^^..->....->>...^^.......^->.......^->...->>>>>>.->>>>>..........->>>>.............->...",
156 "..........^->....^^.^^..^^->^->.^^->>>>.^^..->....->>...^^.......^->.......^->...->>>>>>.->>>>>..........->>>>.............->...",
157 "..........^->............->>>>>>.^^^>^->...->....->^->->.........^->.......^->..^^^->>^.^^^->...........^^^^^.............->....",
158 "..........^->............->>>>>>.^^^>^->...->....->^->->.........^->.......^->..^^^->>^.^^^->...........^^^^^.............->....",
159 "..........^^............^^->^->...->>>>...->..->^->.^->..........^^->......->.....->^->...^->......->..............->....->.....",
160 "..........^^............^^->^->...->>>>...->..->^->.^->..........^^->......->.....->^->...^->......->..............->....->.....",
161 "...........->............^^.^^...^^^>....->..^->^^->>>............^^->....->.....^^.^^....^^......^->.............^->...->......",
162 "...........->............^^.^^...^^^>....->..^->^^->>>............^^->....->.....^^.^^....^^......^->.............^->...->......",
163 "..........^^.......................^....^^...^^..^^^^..............^^....^^.......................->..............^^....^.......",
164 "..........^^.......................^....^^...^^..^^^^..............^^....^^.......................->..............^^....^.......",
165 "...->>.....->.....->>>....->>>...->.^->..->>>>>....->>...->>>>>...->>>....->>>......................->............->......->>>..",
166 "...->>.....->.....->>>....->>>...->.^->..->>>>>....->>...->>>>>...->>>....->>>......................->............->......->>>..",
167 "..->^->...->>....->^^->..->^^->.^->.^->.^->^^^....->^...^^^^^->..->^^->..->^^->....................->............^^->....->^^->.",
168 "..->^->...->>....->^^->..->^^->.^->.^->.^->^^^....->^...^^^^^->..->^^->..->^^->....................->............^^->....->^^->.",
169 ".->.^->..^^->...^^..^->.^^..^->.^->.^->.^->>>>...->.........->..^->.^->.^->.^->....->......->.....->.....->>>>....^^->..^^..^->.",
170 ".->.^->..^^->...^^..^->.^^..^->.^->.^->.^->>>>...->.........->..^->.^->.^->.^->....->......->.....->.....->>>>....^^->..^^..^->.",
171 "^->.^->...^->......->>.....->>..^->>>>>.^^^^^->.^->>>>.....^->..^^->>>..^^->>>>...^->.....^->....->.....^^^^^......^^->.....->..",
172 "^->.^->...^->......->>.....->>..^->>>>>.^^^^^->.^->>>>.....^->..^^->>>..^^->>>>...^->.....^->....->.....^^^^^......^^->.....->..",
173 "^->.^->...^->.....->^.....^^^->.^^^^^->.....^->.^->^^->....->....->^^->..^^^^->...^^......^^....^^->................->.....->...",
174 "^->.^->...^->.....->^.....^^^->.^^^^^->.....^->.^->^^->....->....->^^->..^^^^->...^^......^^....^^->................->.....->...",
175 "^->.^->...^->....->......->.^->.....^->..->.^->.^->.^->...^->...^->.^->.....->.....->......->....^^->....->>>>.....->.....^^....",
176 "^->.^->...^->....->......->.^->.....^->..->.^->.^->.^->...^->...^->.^->.....->.....->......->....^^->....->>>>.....->.....^^....",
177 "^^->>>....->>>..^->>>>>.^^->>>......^->.^^->>>..^^->>>....^->...^^->>>....->>.....^->.....^->.....^^->..^^^^^.....->.......->...",
178 "^^->>>....->>>..^->>>>>.^^->>>......^->.^^->>>..^^->>>....^->...^^->>>....->>.....^->.....^->.....^^->..^^^^^.....->.......->...",
179 ".^^^^....^^^^...^^^^^^...^^^^.......^^...^^^^....^^^^.....^^.....^^^^....^^^......^^......->.......^^............^^.......^^....",
180 ".^^^^....^^^^...^^^^^^...^^^^.......^^...^^^^....^^^^.....^^.....^^^^....^^^......^^......->.......^^............^^.......^^....",
181 "..->>>.....->....->>>>....->>>...->>>>...->>>>>..->>>>>...->>>...->..->...->>>.....->>>..->..->..->......->...->.->..->...->>>..",
182 "..->>>.....->....->>>>....->>>...->>>>...->>>>>..->>>>>...->>>...->..->...->>>.....->>>..->..->..->......->...->.->..->...->>>..",
183 ".->^^->...->>>..^->^^->..->^^->.^->^^->.^->^^^..^->^^^...->^^->.^->.^->..^^->.....^^^->.^->.^->.^->.....^->>.->>^->>^->..->^^->.",
184 ".->^^->...->>>..^->^^->..->^^->.^->^^->.^->^^^..^->^^^...->^^->.^->.^->..^^->.....^^^->.^->.^->.^->.....^->>.->>^->>^->..->^^->.",
185 "^->.->>..->^^->.^->.^->.^->.^^..^->.^->.^->.....^->.....^->.^^..^->.^->...^->.......^->.^->.->..^->.....^->>>>>>^->->->.^->.^->.",
186 "^->.->>..->^^->.^->.^->.^->.^^..^->.^->.^->.....^->.....^->.^^..^->.^->...^->.......^->.^->.->..^->.....^->>>>>>^->->->.^->.^->.",
187 "^->^-^>.^->.^->.^->>>>..^->.....^->.^->.^->>>...^->>>...^->.->>.^->>>>>...^->.......^->.^->>>...^->.....^->^>^->^->^->>.^->.^->.",
188 "^->^-^>.^->.^->.^->>>>..^->.....^->.^->.^->>>...^->>>...^->.->>.^->>>>>...^->.......^->.^->>>...^->.....^->^>^->^->^->>.^->.^->.",
189 "^->^->>.^->>>>>.^->^^->.^->.....^->.^->.^->^....^->^....^->^^->.^->^^->...^->....->.^->.^->^->..^->.....^->^.^->^->^^->.^->.^->.",
190 "^->^->>.^->>>>>.^->^^->.^->.....^->.^->.^->^....^->^....^->^^->.^->^^->...^->....->.^->.^->^->..^->.....^->^.^->^->^^->.^->.^->.",
191 "^->^^^..^->.^->.^->.^->.^->..->.^->.^->.^->.....^->.....^->..->.^->.^->...^->...^->.^->.^->^^->.^->.....^->..^->^->.^->.^->.^->.",
192 "^->^^^..^->.^->.^->.^->.^->..->.^->.^->.^->.....^->.....^->..->.^->.^->...^->...^->.^->.^->^^->.^->.....^->..^->^->.^->.^->.^->.",
193 "^^->>>..^->.^->.^->>>>..^^->>>..^->>>>..^->>>>>.^->.....^^->>>..^->.^->...->>>..^^->>>..^->.^->.^->>>>>.^->..^->^->.^->.^^->>>..",
194 "^^->>>..^->.^->.^->>>>..^^->>>..^->>>>..^->>>>>.^->.....^^->>>..^->.^->...->>>..^^->>>..^->.^->.^->>>>>.^->..^->^->.^->.^^->>>..",
195 ".^^^^...^^..^^..^^^^^....^^^^...^^^^^...^^^^^^..^^.......^^^^...^^..^^...^^^^....^^^^...^^..^^..^^^^^^..^^...^^.^^..^^...^^^^...",
196 ".^^^^...^^..^^..^^^^^....^^^^...^^^^^...^^^^^^..^^.......^^^^...^^..^^...^^^^....^^^^...^^..^^..^^^^^^..^^...^^.^^..^^...^^^^...",
197 ".->>>>....->>>...->>>>....->>>...->>>>>..->..->..->..->..->...->.->..->..->..->..->>>>>..^>-....^>.......^->.......^............",
198 ".->>>>....->>>...->>>>....->>>...->>>>>..->..->..->..->..->...->.->..->..->..->..->>>>>..^>-....^>.......^->.......^............",
199 "^->^^->..->^^->.^->^^->..->^^->.^^^->...^->.^->.^->.^->.^->..^->^->.^->.^->.^->.^^^^^->..^>......^>........>......^->...........",
200 "^->^^->..->^^->.^->^^->..->^^->.^^^->...^->.^->.^->.^->.^->..^->^->.^->.^->.^->.^^^^^->..^>......^>........>......^->...........",
201 "^->.^->.^->.^->.^->.^->.^->.^^....^->...^->.^->.^->.^->.^->..^->^^->->..^->.^->.....->...^>.......^>.......>.....^-.^>..........",
202 "^->.^->.^->.^->.^->.^->.^->.^^....^->...^->.^->.^->.^->.^->..^->^^->->..^->.^->.....->...^>.......^>.......>.....^-.^>..........",
203 "^->>>>..^->.^->.^->>>>..^^->>>....^->...^->.^->.^->.^->.^->.>^->.^^->...^^->>>.....->....^>........^>......>....^-...^>.........",
204 "^->>>>..^->.^->.^->>>>..^^->>>....^->...^->.^->.^->.^->.^->.>^->.^^->...^^->>>.....->....^>........^>......>....^-...^>.........",
205 "^->^^...^->.^->.^->.^->..^^^^->...^->...^->.^->.^->.^->.^->>>>->..->->...^^->.....->.....^>.........^-.....>....................",
206 "^->^^...^->.^->.^->.^->..^^^^->...^->...^->.^->.^->.^->.^->>>>->..->->...^^->.....->.....^>.........^-.....>....................",
207 "^->.....^->.>>>.^->.^->..->.^->...^->...^->.^->.^^->>>..^->>^->>.->^^->...^->....->......^>..........^-....>....................",
208 "^->.....^->.>>>.^->.^->..->.^->...^->...^->.^->.^^->>>..^->>^->>.->^^->...^->....->......^>..........^-....>....................",
209 "^->.....^^->->..^->.^->.^^->>>....^->...^^->>>...^^->...^->.^^->^->.^->...^->...^->>>>>..^>-..........^..^->....................",
210 "^->.....^^->->..^->.^->.^^->>>....^->...^^->>>...^^->...^->.^^->^->.^->...^->...^->>>>>..^>-..........^..^->....................",
211 "^^.......^^^^->.^^..^^...^^^^.....^^.....^^^^.....^^....^^...^^.^^..^^....^^....^^^^^^..................................>>>>>>>>",
212 "^^.......^^^^->.^^..^^...^^^^.....^^.....^^^^.....^^....^^...^^.^^..^^....^^....^^^^^^..................................>>>>>>>>",
213 ".^>..............->..................->............->>...........->........->........->..->.......->>...........................",
214 ".^>..............->..................->............->>...........->........->........->..->.......->>...........................",
215 ".^>^............^->.................^->...........->^->.........^->.......^^........^^..^->......^^->...........................",
216 ".^>^............^->.................^->...........->^->.........^->.......^^........^^..^->......^^->...........................",
217 "..^-......->>>..^->.......->>>......^->...->>>...^->^^....->>>>.^->.......->>.......->>.^->..->...^->....->>.>>..->>>>....->>>..",
218 "..^-......->>>..^->.......->>>......^->...->>>...^->^^....->>>>.^->.......->>.......->>.^->..->...^->....->>.>>..->>>>....->>>..",
219 ".........^^^^->.^->>>>...->^^->...->>>>..->^^->..->>>....->^^->.^->>>>...^^->......^^->.^->.->....^->...^->>>>>>^->^^->..->^^->.",
220 ".........^^^^->.^->>>>...->^^->...->>>>..->^^->..->>>....->^^->.^->>>>...^^->......^^->.^->.->....^->...^->>>>>>^->^^->..->^^->.",
221 "..........->>>>.^->^^->.^->.^^...->^^->.^->>>>>.^^->....^->.^->.^->^^->...^->.......^->.^->>>.....^->...^->^>^->^->.^->.^->.^->.",
222 "..........->>>>.^->^^->.^->.^^...->^^->.^->>>>>.^^->....^->.^->.^->^^->...^->.......^->.^->>>.....^->...^->^>^->^->.^->.^->.^->.",
223 ".........->^^->.^->.^->.^->..->.^->.^->.^->^^^...^->....^^->>>>.^->.^->...^->....->.^->.^->^->....^->...^->^.^->^->.^->.^->.^->.",
224 ".........->^^->.^->.^->.^->..->.^->.^->.^->^^^...^->....^^->>>>.^->.^->...^->....->.^->.^->^->....^->...^->^.^->^->.^->.^->.^->.",
225 "........^^->>>>.^->>>>..^^->>>..^^->>>>.^^->>>...^->.....^^^^->.^->.^->...->>>..^->.^->.^->^^->...->>>..^->..^->^->.^->.^^->>>..",
226 "........^^->>>>.^->>>>..^^->>>..^^->>>>.^^->>>...^->.....^^^^->.^->.^->...->>>..^->.^->.^->^^->...->>>..^->..^->^->.^->.^^->>>..",
227 ".........^^^^^..^^^^^....^^^^....^^^^^...^^^^....^^.......->>>..^^..^^...^^^^...^^->>>..^^..^^...^^^^...^^...^^.^^..^^...^^^^...",
228 ".........^^^^^..^^^^^....^^^^....^^^^^...^^^^....^^.......->>>..^^..^^...^^^^...^^->>>..^^..^^...^^^^...^^...^^.^^..^^...^^^^...",
229 "..................................->........................................................->.....->.....->......->>.->........",
230 "..................................->........................................................->.....->.....->......->>.->........",
231 ".................................^->.......................................................->.....^->....^^->....->^->>....^>...",
232 ".................................^->.......................................................->.....^->....^^->....->^->>....^>...",
233 ".->>>>....->>>>..->>>>....->>>...->>>....->..->..->..->..->...->.->..->..->..->..->>>>>....->.....^->.....^->...^^.^^^....^-->..",
234 ".->>>>....->>>>..->>>>....->>>...->>>....->..->..->..->..->...->.->..->..->..->..->>>>>....->.....^->.....^->...^^.^^^....^-->..",
235 "^->^^->..->^^->.^->^^->..->^^...^^->....^->.^->.^->.^->.^->.>^->^^->->..^->.^->.^^^^->....->......^^......^^->...........^->^->.",
236 "^->^^->..->^^->.^->^^->..->^^...^^->....^->.^->.^->.^->.^->.>^->^^->->..^->.^->.^^^^->....->......^^......^^->...........^->^->.",
237 "^->.^->.^->.^->.^->.^^..^^->>>...^->....^->.^->.^->.^->.^->>>>->.^^->...^->.^->....->....^^->......->......->...........^->..^->",
238 "^->.^->.^->.^->.^->.^^..^^->>>...^->....^->.^->.^->.^->.^->>>>->.^^->...^->.^->....->....^^->......->......->...........^->..^->",
239 "^->>>>..^^->>>>.^->......^^^^->..^->.->.^->.^->.^^->>>..^->>^->>..->->..^^->>>>...->......^->.....^->.....^->...........^->..^->",
240 "^->>>>..^^->>>>.^->......^^^^->..^->.->.^->.^->.^^->>>..^->>^->>..->->..^^->>>>...->......^->.....^->.....^->...........^->..^->",
241 "^->^^....^^^^->.^->.......->>>...^^->>..^^->>>>..^^->...^->.^^->.->^^->..^^^^->..->>>>>...^^->....^->.....->............^------>",
242 "^->^^....^^^^->.^->.......->>>...^^->>..^^->>>>..^^->...^->.^^->.->^^->..^^^^->..->>>>>...^^->....^->.....->............^------>",
243 "^->.........^->.^^.......^^^^.....^^^....^^^^^....^^....^^...^^.^^..^^....->>>..^^^^^^.....^^.....^^.....^^.....................",
244 "^->.........^->.^^.......^^^^.....^^^....^^^^^....^^....^^...^^.^^..^^....->>>..^^^^^^.....^^.....^^.....^^.....................",
245 "................                                                                                                                ",
246 "....>>..........                                                                                                                ",
247 "..>>>>..........                                                                                                                ",
248 ">>---->>>>>>>>>>                                                                                                                ",
249 ";;;;--;;;;;;;;;;                                                                                                                ",
250 "..;;;;..........                                                                                                                ",
251 "....;;..........                                                                                                                ",
252 "................                                                                                                                ",
253 "................                                                                                                                ",
254 "..........>>....                                                                                                                ",
255 "..........>>>>..                                                                                                                ",
256 ">>>>>>>>------>>                                                                                                                ",
257 ";;;;;;;;;;--;;;;                                                                                                                ",
258 "..........;;;;..                                                                                                                ",
259 "..........;;....                                                                                                                ",
260 "................                                                                                                                "};
261
262 static struct ascii {
263         struct images *images;
264         int offset;
265         ascii_ctrl_states state;
266         Uint32 color_stack[ASCII_CLR_STK_SZ];
267         int i_color;  /* index onto stack */
268         Uint32 color; /* active color */
269 } Ascii;
270
271 static Uint32  asciiDecodeColor(char clr)
272 {
273         switch (clr) {
274         case 'w': return White;
275         case 'B': return Black;
276         case 'r': return TextRed;
277         case 'g': return TextGreen;
278         case 'b': return TextBlue;
279         case 'y': return TextYellow;
280         case 'c': return TextCyan;
281         case 'm': return TextMagenta;
282         case 'G': return Gray;
283         default:
284                 warn("Color '%c' unknown\n", clr);
285                 return ASCII_DEF_CLR;
286         }
287 }
288
289 static void asciiPushColor()
290 {
291         /* Check for overrun. */
292         if (array_sz(Ascii.color_stack) == Ascii.i_color) {
293                 warn("Ascii color stack overrun\n");
294                 return;
295         }
296
297         /* Push the new color. */
298         Ascii.color_stack[Ascii.i_color] = Ascii.color;
299         Ascii.i_color++;
300 }
301
302 static void asciiPopColor()
303 {
304         /* Check for underrun. */
305         if (0 == Ascii.i_color) {
306                 warn("Ascii color stack already at bottom\n");
307                 return;
308         }
309         
310         Ascii.i_color--;
311         Ascii.color = Ascii.color_stack[Ascii.i_color];
312         return;
313 }
314
315 static void asciiSetColor(char clr)
316 {
317         /* Check for a pop. */
318         switch (clr) {
319         case '+': 
320                 asciiPushColor();
321                 break;
322         case '-':
323                 asciiPopColor();
324                 break;
325         case '=':
326                 /* current color, nop */
327                 break;
328         default:
329                 Ascii.color = asciiDecodeColor(clr);
330                 break;
331         }
332 }
333
334 static void asciiBlitColored16(SDL_Surface *src, SDL_Rect *srcrect,
335                                SDL_Surface *dst, SDL_Rect *dstrect,
336                                Uint32 color)
337 {
338         Uint16 mask = color;
339         Uint16 *srcpix, *dstpix;
340         int x=0, y=0;
341
342         assert(dst->format->BitsPerPixel==16);
343
344         for (y=0; y<dstrect->h; y++) {
345
346                 srcpix = (Uint16*)src->pixels 
347                         + (srcrect->y+y)*src->w 
348                         + srcrect->x;
349                 dstpix = (Uint16*)dst->pixels 
350                         + (dstrect->y+y)*dst->w 
351                         + dstrect->x;
352
353                 for (x=0; x<dstrect->w; x++) {
354                         *dstpix = *srcpix&mask;
355                         srcpix++;
356                         dstpix++;
357                 }
358         }
359 }
360
361 static void asciiBlitColored32(SDL_Surface *src, SDL_Rect *srcrect,
362                                SDL_Surface *dst, SDL_Rect *dstrect,
363                                Uint32 color)
364 {
365         Uint32 mask = color;
366         Uint32 *srcpix, *dstpix;
367         int x=0, y=0;
368
369         assert(dst->format->BitsPerPixel==32);
370
371         for (y=0; y<dstrect->h; y++) {
372
373                 srcpix = (Uint32*)src->pixels 
374                         + (srcrect->y+y)*src->w 
375                         + srcrect->x;
376                 dstpix = (Uint32*)dst->pixels 
377                         + (dstrect->y+y)*dst->w 
378                         + dstrect->x;
379
380                 for (x=0; x<dstrect->w; x++) {
381                         *dstpix = *srcpix&mask;
382                         srcpix++;
383                         dstpix++;
384                 }
385         }
386 }
387
388 static void asciiBlitColored(SDL_Surface *src, SDL_Rect *srcrect,
389                              SDL_Surface *dst, SDL_Rect *dstrect,
390                              Uint32 color)
391 {
392 #if DEBUG
393         if (src->format->BitsPerPixel!=dst->format->BitsPerPixel) {
394                 fprintf(stderr,
395                         "ERROR: %dx%d@%d surface not in destination format!\n",
396                         src->w, src->h, src->format->BytesPerPixel);
397                 backtrace2stderr();
398                 exit(-1);
399         }
400 #else
401         assert(src->format->BitsPerPixel==dst->format->BitsPerPixel);
402 #endif
403         assert(dstrect->w==srcrect->w);
404         assert(dstrect->h==srcrect->h);
405
406         switch (dst->format->BitsPerPixel) {
407         case 16:
408                 asciiBlitColored16(src, srcrect, dst, dstrect, color);
409                 break;
410         case 32:
411                 asciiBlitColored32(src, srcrect, dst, dstrect, color);
412                 break;
413         default:
414                 err("asciiBlitColored: unsupported BitsPerPixel: %d\n",
415                     dst->format->BitsPerPixel);
416                 break;
417         }
418 }
419
420 static void asciiPaintColored(unsigned char c, int x, int y, 
421                               SDL_Surface *surf, Uint32 color)
422 {
423         SDL_Rect dest;
424         SDL_Rect src;
425         int row;
426         int col;
427
428         assert(Ascii.images);
429
430         if (c == '\t')
431                 c = ' ';
432
433         assert(c >= ' ');
434
435         if (c<' ') {
436                 warn("c==%d\n", c);
437                 c='?';
438         }
439
440         /* fixme -- put these calcs in a table or something. Don't need to do
441          * it every time. */
442         col = c % Ascii.images->cols;
443         row = c / Ascii.images->cols;
444
445         src.x = (col * ASCII_W) + Ascii.images->offx;
446         src.y = (row * ASCII_H) + Ascii.images->offy;
447         src.w = ASCII_W;
448         src.h = ASCII_H;
449
450         dest.x = x;
451         dest.y = y;
452         dest.w = ASCII_W;
453         dest.h = ASCII_H;
454
455         asciiBlitColored(Ascii.images->images, &src, 
456                          surf, &dest, 
457                          color);
458 }
459
460 static void asciiPaintDefault(unsigned char c, int x, int y, 
461                               SDL_Surface * surf)
462 {
463         SDL_Rect dest;
464         SDL_Rect src;
465         int row;
466         int col;
467
468         assert(Ascii.images);
469
470         if (c == '\t')
471                 c = ' ';
472
473         /* fixme -- put these calcs in a table or something. Don't need to do
474          * it every time. */
475         col = c % Ascii.images->cols;
476         row = c / Ascii.images->cols;
477
478         src.x = (col * ASCII_W) + Ascii.images->offx;
479         src.y = (row * ASCII_H) + Ascii.images->offy;
480         src.w = ASCII_W;
481         src.h = ASCII_H;
482
483         dest.x = x;
484         dest.y = y;
485         dest.w = ASCII_W;
486         dest.h = ASCII_H;
487
488         SDL_BlitSurface(Ascii.images->images, &src, surf, &dest);
489 }
490
491 /**
492  * Load the emergency ASCII image set from XPM.
493  *
494  * @returns The images struct ready for use, our 0 if there was some kind of
495  * error in loading it.
496  */
497 static struct images *ascii_load_fixed_charset(void)
498 {
499         struct images *images;
500
501         images = new struct images;
502         assert(images);
503         memset(images, 0, sizeof(*images));
504
505         images->w       = 8;
506         images->h       = 16;
507         images->offx    = 0;
508         images->offy    = 0;
509         images->rows    = 9;
510         images->cols    = 16;
511
512         images->images = IMG_ReadXPMFromArray((char**)charset_xpm);
513         if (!images->images) {
514                 err("IMG_ReadXPMFromArray() failed: '%s'\n", SDL_GetError() );
515                 images_del(images);
516                 return NULL;
517         }
518         if (!images_convert2display(images)) {
519                 images_del(images);
520                 return NULL;
521         }
522         return images;
523 }
524
525 int asciiInit(void)
526 {
527         char *fname = cfg_get("ascii-image-filename");
528         
529         /* This lib might be unitialized twice: once early in startup so that
530          * error messages can be displayed, and again later after the
531          * configuration file has been found and parsed. */
532         if (Ascii.images) {
533                 images_del(Ascii.images);
534                 Ascii.images = 0;
535         }
536
537         if (fname) {
538                 Ascii.images = images_new(0, 8, 16, 9, 16, 0, 0, fname);
539         } else {
540                 Ascii.images = ascii_load_fixed_charset();
541         }
542         assert(Ascii.images);
543         Ascii.offset = 0;
544         Ascii.state = ASCII_STATE_DEF;
545         Ascii.i_color = 0;
546         Ascii.color = ASCII_DEF_CLR;
547         return 0;
548 }
549
550 int asciiPaint(char c, int x, int y, SDL_Surface * surf)
551 {
552         int ret = 0;
553
554         switch (Ascii.state) {
555                         
556         case ASCII_STATE_CLR:
557                 asciiSetColor(c);
558                 Ascii.state = ('+'==c?ASCII_STATE_CLRPUSH:ASCII_STATE_DEF);
559                 break;
560                 
561         case ASCII_STATE_CLRPUSH:
562                 asciiSetColor(c);
563                 Ascii.state = ASCII_STATE_DEF;
564                 break;
565
566         case ASCII_STATE_ESC:
567                 if (c == 'c') {
568                         Ascii.state = ASCII_STATE_CLR;
569                 }
570                 break;
571                 
572         case ASCII_STATE_DEF:
573         default:
574                 if (c == '^') {
575                         Ascii.state = ASCII_STATE_ESC;
576                 } else {
577                         if (ASCII_DEF_CLR==Ascii.color) {
578                                 asciiPaintDefault(c, x, y, surf);
579                         } else {
580                                 asciiPaintColored(c, x, y, surf, Ascii.color);
581                         }
582                         ret = 1;
583                 }
584         }
585
586         return ret;
587 }
588
589 int asciiStrlen(char *s)
590 {
591         /* Start with the current state. */
592         enum ascii_ctrl_states state = Ascii.state;
593         char c = 0;
594         int len = 0;
595
596         while ((c = *s++)) {
597                 switch (state) {
598                 case ASCII_STATE_CLR:
599                         state = ('+'==c?ASCII_STATE_CLRPUSH:ASCII_STATE_DEF);
600                         break;
601                         
602                 case ASCII_STATE_CLRPUSH:
603                         state = ASCII_STATE_DEF;
604                         break;
605                         
606                 case ASCII_STATE_ESC:
607                         if (c == 'c') {
608                                 state = ASCII_STATE_CLR;
609                         }
610                         break;
611                         
612                 case ASCII_STATE_DEF:
613                 default:
614                         if ('^' == c) {
615                                 state = ASCII_STATE_ESC;
616                         } else {
617                                 len++;
618                         }
619                 }
620         }
621         
622         return len;
623 }