comparison scn2k/scn2k_text.cc @ 56:c7bcc0ec2267

* replaced Grp and Text classes by the TextImpl and GrpImpl ones * splitted scn2k.h into smaller header files * moved some definitions from scn2k_*.cc to the header files * moved opcode implementation to scn2k_*impl.cc
author thib
date Thu, 30 Apr 2009 19:05:09 +0000
parents f1a27ee7e03c
children 6d9146f56ccf
comparison
equal deleted inserted replaced
55:f1a27ee7e03c 56:c7bcc0ec2267
7 ・ウェイト終了後、クリアなしに新たなテキストを追加、新たにstart-waitする 7 ・ウェイト終了後、クリアなしに新たなテキストを追加、新たにstart-waitする
8 ・文字の描画 (Start) と Wait(カーソル表示待ち)の分離。 8 ・文字の描画 (Start) と Wait(カーソル表示待ち)の分離。
9 Start すると文字を描画開始する。クリックで全描画。 9 Start すると文字を描画開始する。クリックで全描画。
10 Flush するとバッファ内の文字をすべて描画する 10 Flush するとバッファ内の文字をすべて描画する
11 Wait すると全描画後、クリックされるまでカーソルを表示するまで待つ 11 Wait すると全描画後、クリックされるまでカーソルを表示するまで待つ
12 TextImpl 側の状態としては Wait のみを持つ (PREPAREに戻るのを待つ) 12 Text 側の状態としては Wait のみを持つ (PREPAREに戻るのを待つ)
13 ただし、Skip の権利はどっちがもつ?(現状は?) 13 ただし、Skip の権利はどっちがもつ?(現状は?)
14 14
15 GrpObj: NextObj と GrpObj を分離。CreateObj は現状通り、Visible=1 時に行う。 15 GrpObj: NextObj と GrpObj を分離。CreateObj は現状通り、Visible=1 時に行う。
16 それぞれ num=0 (screen) の枝leaf として実装。delete時は親のdeleteのみを 16 それぞれ num=0 (screen) の枝leaf として実装。delete時は親のdeleteのみを
17 行い、子はGrpObjの実体だけを削除する 17 行い、子はGrpObjの実体だけを削除する
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */ 56 */
57 57
58 #include "window/event.h" 58 #include "scn2k_text.h"
59 #include "window/picture.h" 59
60 #include "window/widget.h"
61 #include "system/file.h" 60 #include "system/file.h"
62 #include "system/system_config.h"
63 #include "scn2k.h" 61 #include "scn2k.h"
64 62
65 #include <string> 63 #include <string>
66 using namespace std; 64 using namespace std;
67 65
68 // kanji conv : デバッグ表示用 66 #include "window/render.h"
69 void kconv(const unsigned char* src, unsigned char* dest);
70 void kconv_rev(const unsigned char* src, unsigned char* dest);
71 string kconv(const string& s);
72 string kconv_rev(const string& s);
73 // render.cc
74 void DSurfaceFillA(Surface* src, const Rect& rect, int r, int g, int b, int a); // テキストウィンドウ背景の設定
75 void DSurfaceMove(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect); // コピー
76 67
77 /**************************************************************:: 68 /**************************************************************::
78 ** 69 **
79 ** TextImpl(interface) 70 ** Text(implementation)
80 */ 71 */
81 struct TimerAtom { 72 Text::Text(Event::Container& _event, PicContainer& _parent) :
82 int from; 73 text(0),status(Text::NORMAL), status_saved(Text::NORMAL), status_mask(Text::NORMAL), ruby_text_flag(false),
83 int to;
84 unsigned int start_time;
85 unsigned int total_time;
86 };
87
88 struct TextWindow {
89 /* @@@ : SetWindowColor での surface 再設定に注意 */
90 WidText* wid;
91 bool name_visible;
92 WidLabel* name;
93 PicContainer* name_container;
94 PicBase* face;
95 PicBase* face_pics[8];
96 TextWindow(PicContainer& parent, Event::Container& event, int window_no, void* callback);
97 ~TextWindow() {
98 if (name_container != NULL) {
99 delete name_container;
100 name_container = NULL;
101 }
102 int i;
103 for (i=0; i<8; i++) {
104 if (face_pics[i] != NULL) {
105 delete face_pics[i];
106 face_pics[i] = NULL;
107 }
108 }
109 if (wid != NULL) {
110 delete wid;
111 wid = NULL;
112 }
113 }
114 Rect WakuSize(PicContainer& pic, int waku_no);
115 void MakeWaku(PicContainer& pic, Event::Container& event, int waku_no,int window_no, bool* use_btn, void* callback);
116 void show(void) {
117 wid->show();
118 if (name_container && name_visible) name_container->show();
119 if (face) face->show();
120 }
121 void hide(void) {
122 wid->hide();
123 if (name_container) name_container->hide();
124 if (face) face->hide();
125 }
126 void ShowFace(const char* path) {
127 if (!face) return;
128 face->SetSurface( path, 0,0);
129 }
130 void ResetFace(void) {
131 if (!face) return;
132 face->SetSurface( (Surface*)0, 0,0);
133 }
134 void StartText(const TextStream& _stream) {
135 wid->Clear();
136 wid->stream = _stream;
137 if (name_container) {
138 char namestr[1024];
139 namestr[0] = 0;
140 wid->stream.RemoveName(namestr, 1024);
141 if (namestr[0] == 0) {
142 name_container->hide();
143 } else {
144 if (name) {
145 name_container->show_all();
146 name->SetText(namestr);
147 }
148 }
149 }
150 wid->Start();
151 }
152 void SetName(const char* n) {
153 if (name_container && name) {
154 if (n[0]) {
155 name_container->show();
156 name->SetText(n);
157 name_visible = true;
158 } else {
159 name_container->hide();
160 name_visible = false;
161 }
162 }
163 }
164 };
165
166 class TextImpl : public CommandHandler {
167 public:
168 TextImpl(Event::Container& _event, PicContainer& _parent, vector<BacklogItem>& parent_backlog, BacklogItem& parent_backlog_item);
169 ~TextImpl();
170 void InitWindow(void);
171 void SetWindowColor(int r, int g, int b, int a, bool is_transparent);
172 void SetTextSpeed(int new_speed);
173 void SetTextWait(int new_wait);
174 void CreateSelect(Cmd& cmd);
175 void Exec(Cmd& cmd);
176 bool Wait(unsigned int current_time, Cmd& cmd);
177 void hide(void);
178 void show(void) { show(text_window_number); }
179 void show(int num);
180 void DrawBacklog(BacklogItem& item, Cmd& cmd);
181 void Save(std::string& str, bool select_save);
182 void Load(const char* str);
183 void SetSkipMode(SkipMode _mode);
184 void CreateSelBG(void);
185
186 void AddText(const char* str);
187
188 static void PressFuncSkip(void* pointer, WidButton* from);
189 static void PressFuncLoad(void* pointer, WidButton* from);
190 static void PressFuncSave(void* pointer, WidButton* from);
191 static void PressFuncBacklog(void* pointer, WidButton* from);
192 static void PressFuncBacklogFwd(void* pointer, WidButton* from);
193
194 private:
195 static void PressFuncButton(void* pointer, WidButton* from);
196 static bool PressFunc(int x, int y, void* pointer);
197 void SetCursor(int num);
198
199 public:
200 TextWindow* text;
201 typedef enum {NORMAL=0, WAIT_TEXT=1, WAIT=2,
202 WAIT_CLICK=3, WAIT_ABORT=4, WAIT_CLICK_MOUSEPOS = 5,
203 WAIT_CLICK_MOUSEPOSEND_L = 6, WAIT_CLICK_MOUSEPOSEND_R = 7,
204 WAIT_SELECT_INBOX = 10, WAIT_SELECT_OUTBOX=11, WAIT_SELECT_VALUE = 12,
205 WAIT_EXTRN_MASK = 64, SAVEMASK = 128, LOADMASK = 256, SKIPMASK = 512,
206 CLEARSCR_MASK = 1024, STATSAVE_MASK = 2048, CLEARSCR_WAIT_MASK=(1<<12),
207 SKIPEND_MASK = (1<<13), BACKLOG_MASK=(1<<14), BACKLOG_MASK_FWD=(1<<15),
208 BACKLOG_MASK_KOE=(1<<16), BACKLOG_WAIT_MASK=(1<<17),
209 ALLMASK = (CLEARSCR_MASK | WAIT_EXTRN_MASK | SAVEMASK |
210 LOADMASK | SKIPMASK | BACKLOG_MASK | BACKLOG_MASK_FWD |
211 BACKLOG_MASK_KOE | BACKLOG_WAIT_MASK | STATSAVE_MASK |
212 CLEARSCR_WAIT_MASK | SKIPEND_MASK)
213 } Status;
214 Status status, status_saved, status_mask;
215
216 private:
217 std::string ruby_text;
218 bool ruby_text_flag;
219 unsigned int wait_time;
220 unsigned int old_time;
221 unsigned int base_time;
222 int text_window_number;
223 bool text_parsing;
224 TextStream text_stream;
225 SkipMode skip_mode;
226 int save_selectcount;
227
228 std::map<int, TimerAtom> timer_var;
229 std::vector<WidTextButton*> selects;
230 std::vector<int> sel_backlog_pos;
231 string replace_name[26];
232 string replace_name2[26];
233 PicContainer* sel_widget;
234 PicWidget* backlog_widget;
235
236 vector<BacklogItem>& backlog;
237 BacklogItem& backlog_item;
238 BacklogItem cur_backlog_item;
239 BacklogItem drawn_backlog_item;
240
241 TextWindow* widgets[32];
242 WidTimeCursor* kcursor;
243 Surface* sel_bg1;
244 Surface* sel_bg2;
245 Rect sel_bg_rect;
246
247 VarInfo wait_savedvar[2];
248
249 AyuSysConfig *config;
250
251 Event::Container& event;
252 PicContainer& parent;
253
254 //Opcode handling
255 void impl_txtClear(Cmd& cmd);
256 void impl_logKoe(Cmd& cmd);
257 void impl_pause(Cmd& cmd);
258 void impl_br(Cmd& cmd);
259 void impl_FaceOpen(Cmd& cmd);
260 void impl_FaceClear(Cmd& cmd);
261 };
262
263 /**************************************************************::
264 **
265 ** TextImpl(implementation)
266 */
267 TextImpl::TextImpl(Event::Container& _event, PicContainer& _parent, vector<BacklogItem>& parent_backlog, BacklogItem& parent_backlog_item) :
268 text(0),status(TextImpl::NORMAL), status_saved(TextImpl::NORMAL), status_mask(TextImpl::NORMAL), ruby_text_flag(false),
269 old_time(0), base_time(0), text_window_number(0), text_parsing(false), skip_mode(SKIP_NO), save_selectcount(0), sel_widget(0), 74 old_time(0), base_time(0), text_window_number(0), text_parsing(false), skip_mode(SKIP_NO), save_selectcount(0), sel_widget(0),
270 backlog_widget(0), backlog(parent_backlog), backlog_item(parent_backlog_item), parent(_parent), event(_event), 75 backlog_widget(0), parent(_parent), event(_event),
271 kcursor(0), sel_bg1(0), sel_bg2(0), sel_bg_rect(0,0,0,0) { 76 kcursor(0), sel_bg1(0), sel_bg2(0), sel_bg_rect(0,0,0,0) {
272 config = AyuSysConfig::GetInstance(); 77 config = AyuSysConfig::GetInstance();
273 int i; 78 int i;
274 for (i=0; i<32; i++) { 79 for (i=0; i<32; i++) {
275 widgets[i] = 0; 80 widgets[i] = 0;
276 } 81 }
277 text_stream.kanji_type = TextStream::sjis; 82 text_stream.kanji_type = TextStream::sjis;
278 event.RegisterGlobalPressFunc(&PressFunc, (void*)this); 83 event.RegisterGlobalPressFunc(&PressFunc, (void*)this);
279 84
280 RegisterCommand(1, 33, 73, "grpOpenBg", (CmdImpl) &TextImpl::impl_txtClear); 85 RegisterCommand(1, 33, 73, "grpOpenBg", (CmdImpl) &Text::impl_txtClear);
281 RegisterCommand(1, 33, 75, "grpMulti", (CmdImpl) &TextImpl::impl_txtClear); 86 RegisterCommand(1, 33, 75, "grpMulti", (CmdImpl) &Text::impl_txtClear);
282 RegisterCommand(1, 33, 76, "grpOpen", (CmdImpl) &TextImpl::impl_txtClear); 87 RegisterCommand(1, 33, 76, "grpOpen", (CmdImpl) &Text::impl_txtClear);
283 88
284 RegisterCommand(1, 23, 0, "koePlay", (CmdImpl) &TextImpl::impl_logKoe); 89 RegisterCommand(1, 23, 0, "koePlay", (CmdImpl) &Text::impl_logKoe);
285 RegisterCommand(1, 23, 8, "koeDoPlay", (CmdImpl) &TextImpl::impl_logKoe); 90 RegisterCommand(1, 23, 8, "koeDoPlay", (CmdImpl) &Text::impl_logKoe);
286 91
287 RegisterCommand(0, 3, 151, "msgHide", (CmdImpl) &TextImpl::impl_txtClear); 92 RegisterCommand(0, 3, 151, "msgHide", (CmdImpl) &Text::impl_txtClear);
288 RegisterCommand(0, 3, 17, "pause", (CmdImpl) &TextImpl::impl_pause); 93 RegisterCommand(0, 3, 17, "pause", (CmdImpl) &Text::impl_pause);
289 RegisterCommand(0, 3, 3, "par", (CmdImpl) &TextImpl::impl_br); //FIXME 94 RegisterCommand(0, 3, 3, "par", (CmdImpl) &Text::impl_br); //FIXME
290 RegisterCommand(0, 3, 201, "br", (CmdImpl) &TextImpl::impl_br); 95 RegisterCommand(0, 3, 201, "br", (CmdImpl) &Text::impl_br);
291 RegisterCommand(0, 3, 1000, "FaceOpen", (CmdImpl) &TextImpl::impl_FaceOpen); 96 RegisterCommand(0, 3, 1000, "FaceOpen", (CmdImpl) &Text::impl_FaceOpen);
292 RegisterCommand(0, 3, 1001, "FaceClear", (CmdImpl) &TextImpl::impl_FaceClear); 97 RegisterCommand(0, 3, 1001, "FaceClear", (CmdImpl) &Text::impl_FaceClear);
293 } 98 RegisterCommand(0, 3, 120, "__doruby", (CmdImpl) &Text::impl_doRuby); //FIXME: I don't know how it works
294 99 RegisterCommand(0, 3, 102, "TextWindow", (CmdImpl) &Text::impl_TextWindow);
295 TextImpl::~TextImpl() { 100 RegisterCommand(0, 3, 103, "FastText", NULL);//FIXME: (CmdImpl) &Text::impl_FastText);
296 if (sel_widget) delete sel_widget; 101 RegisterCommand(0, 3, 104, "NormalText", NULL);
102 RegisterCommand(0, 3, 152, "msgClear", (CmdImpl) &Text::impl_msgClear);
103
104 RegisterCommand(0, 2, 1, "select", (CmdImpl) &Text::impl_createSelect);
105 RegisterCommand(0, 2, 3, "select2?", (CmdImpl) &Text::impl_createSelect); //What difference with select?
106
107 RegisterCommand(0, 4, 1000, "ShowBackground", (CmdImpl) &Text::impl_ShowBackground);
108 RegisterCommand(0, 4, 1100, "SetSkipMode", (CmdImpl) &Text::impl_SetSkipMode);
109 RegisterCommand(1, 4, 100, "wait", (CmdImpl) &Text::impl_Wait);
110 RegisterCommand(1, 4, 111, "time", (CmdImpl) &Text::impl_Wait);
111 RegisterCommand(1, 4, 121, "timeEx", (CmdImpl) &Text::impl_Wait);
112 }
113
114 Text::~Text() {
115 if (sel_widget != NULL)
116 delete sel_widget;
297 int i; 117 int i;
298 for (i=0; i<32; i++) { 118 for (i=0; i<32; i++) {
299 if (widgets[i]) delete widgets[i]; 119 if (widgets[i] != NULL)
300 } 120 delete widgets[i];
301 if (backlog_widget) delete backlog_widget; 121 }
302 if (sel_bg1) parent.Root().DeleteSurface(sel_bg1); 122 if (backlog_widget != NULL)
303 if (sel_bg2) parent.Root().DeleteSurface(sel_bg2); 123 delete backlog_widget;
124 if (sel_bg1 != NULL)
125 parent.Root().DeleteSurface(sel_bg1);
126 if (sel_bg2 != NULL)
127 parent.Root().DeleteSurface(sel_bg2);
304 event.DeleteGlobalPressFunc(&PressFunc, (void*)this); 128 event.DeleteGlobalPressFunc(&PressFunc, (void*)this);
305 } 129 }
306 130
307 bool TextImpl::PressFunc(int x, int y, void* pointer) { 131 bool Text::PressFunc(int x, int y, void* pointer) {
308 TextImpl* t = (TextImpl*)pointer; 132 Text* t = (Text*)pointer;
309 if (t->status == WAIT_CLICK) { 133 if (t->status == WAIT_CLICK) {
310 t->status = WAIT_ABORT; 134 t->status = WAIT_ABORT;
311 } else if (t->status == WAIT_CLICK_MOUSEPOS) { 135 } else if (t->status == WAIT_CLICK_MOUSEPOS) {
312 t->status = WAIT_CLICK_MOUSEPOSEND_L; 136 t->status = WAIT_CLICK_MOUSEPOSEND_L;
313 } else if (t->status_mask & CLEARSCR_WAIT_MASK) { 137 } else if (t->status_mask & CLEARSCR_WAIT_MASK) {
326 else if (t->status == WAIT_SELECT_VALUE) ; 150 else if (t->status == WAIT_SELECT_VALUE) ;
327 else t->status_mask = Status(t->status_mask | SKIPEND_MASK); 151 else t->status_mask = Status(t->status_mask | SKIPEND_MASK);
328 } 152 }
329 return true; // event not deleted 153 return true; // event not deleted
330 } 154 }
331 void TextImpl::PressFuncButton(void* pointer, WidButton* from) { 155
332 TextImpl* t = (TextImpl*)pointer; 156 void Text::PressFuncButton(void* pointer, WidButton* from) {
157 Text* t = (Text*)pointer;
333 if (t->status != WAIT_SELECT_INBOX && t->status != WAIT_SELECT_OUTBOX) return; 158 if (t->status != WAIT_SELECT_INBOX && t->status != WAIT_SELECT_OUTBOX) return;
334 vector<WidTextButton*>::iterator it; 159 vector<WidTextButton*>::iterator it;
335 int sel = 0; 160 int sel = 0;
336 for (it=t->selects.begin(); it != t->selects.end(); it++, sel++) { 161 for (it=t->selects.begin(); it != t->selects.end(); it++, sel++) {
337 if (from == *it) break; 162 if (from == *it) break;
338 } 163 }
339 if (it == t->selects.end()) { 164 if (it == t->selects.end()) {
340 fprintf(stderr,"TextImpl::PressFuncButton: Cannot find select widget\n"); 165 fprintf(stderr,"Text::PressFuncButton: Cannot find select widget\n");
341 return; 166 return;
342 } 167 }
343 t->status = Status(WAIT_SELECT_VALUE + sel); 168 t->status = Status(WAIT_SELECT_VALUE + sel);
344 return; 169 }
345 } 170
346 171 void Text::SetSkipMode(SkipMode _mode) {
347 void TextImpl::SetSkipMode(SkipMode _mode) {
348 if ( (skip_mode & SKIP_IN_MENU) && (_mode & SKIP_IN_MENU) == 0) { 172 if ( (skip_mode & SKIP_IN_MENU) && (_mode & SKIP_IN_MENU) == 0) {
349 if (status_mask & BACKLOG_WAIT_MASK) { // backlog mode から復帰 173 if (status_mask & BACKLOG_WAIT_MASK) { // backlog mode から復帰
350 status_mask = Status(status_mask & (~(BACKLOG_MASK|BACKLOG_MASK_FWD|BACKLOG_MASK_KOE|BACKLOG_WAIT_MASK))); 174 status_mask = Status(status_mask & (~(BACKLOG_MASK|BACKLOG_MASK_FWD|BACKLOG_MASK_KOE|BACKLOG_WAIT_MASK)));
351 text->wid->Clear(); 175 text->wid->Clear();
352 if (status == WAIT_TEXT && text != NULL) { 176 if (status == WAIT_TEXT && text != NULL) {
373 if (backlog_widget) backlog_widget->hide(); 197 if (backlog_widget) backlog_widget->hide();
374 } 198 }
375 skip_mode = _mode; 199 skip_mode = _mode;
376 } 200 }
377 201
378 /* hash_map が欲しい……*/ 202 void Text::InitWindow(void) {
379 #include <map> 203 int i;
380 #include <list> 204 int w;
381 struct SaveFaceHash { // バックログセーブ時の顔画像管理を行う 205 std::string str;
382 map<string, int> facetonum; 206
383 typedef pair<string,int> Node; 207 for (w=0; w<32; w++) {
384 typedef list<Node> List; 208 widgets[w] = new TextWindow(parent, event, w, (void*)this);
385 List container; 209 if (widgets[w]->wid == 0) {
386 int id_max; 210 delete widgets[w];
387 static int size_max; 211 widgets[w] = NULL;
388 SaveFaceHash() : id_max(0) { 212 }
389 } 213 }
390 void NewNode(string face, int face_id) { 214 SetCursor(0);
391 facetonum[face] = face_id; 215 for (i=0; i<26; i++) {
392 container.push_front(Node(face, face_id)); 216 char buf[1024];
393 if (container.size() > size_max) { 217 sprintf(buf, "#NAME.%c", i+'A');
394 Node remove = container.back(); 218 const char* s = config->GetParaStr(buf);
395 container.pop_back(); 219 if (s != NULL) replace_name[i] = s;
396 facetonum.erase(remove.first); 220 }
397 } 221 // replace_name2 : 初期設定
398 } 222 // 渚、秋生、渚 (CLANNAD)
399 int Add(string face) { 223 char name_nagisa[3] = {'\x8f', '\x8d', '\0'};
400 int id; int ret = -1; 224 char name_akio[5] = {'\x8f', '\x48', '\x90', '\xb6', '\0'};
401 int i; List::iterator it; 225 replace_name2[0] = name_nagisa;
402 if (face.empty()) return -1; 226 replace_name2[1] = name_akio;
403 if (facetonum.find(face) == facetonum.end()) { 227 replace_name2[2] = name_nagisa;
404 id = ++id_max; 228 text = NULL;
405 NewNode(face, id); 229 /* テキスト速度の設定 */
406 ret = -1; 230 int speed, mod, wait, auto_mod;
407 } else { 231 config->GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
408 id = facetonum[face]; 232 config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &mod);
409 for (i=0, it=container.begin(); it != container.end(); i++, it++) { 233 config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &auto_mod);
410 if (it->second == id) { 234 config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
411 ret = i; 235 if (mod) speed = -1;
412 Node n = *it; 236 if (!auto_mod) wait = -1;
413 container.erase(it); 237 SetTextSpeed(speed);
414 container.push_front(n); 238 SetTextWait(wait);
415 break; 239 }
416 } 240
417 } 241 void Text::Save(string& str, bool rollback_save) {
418 }
419 return ret;
420 }
421 string Get(int num) {
422 if (num < 0) return "";
423 List::iterator it = container.begin();
424 for (; it != container.end(); it++) {
425 if (num == 0) return it->first;
426 num--;
427 }
428 return "";
429 }
430 };
431
432 int SaveFaceHash::size_max = 20;
433
434 void TextImpl::Save(string& str, bool rollback_save) {
435 char buf[1024]; 242 char buf[1024];
436 str = "\n"; 243 str = "\n";
437 str += "[TextImpl Window]\n"; 244 str += "[Text Window]\n";
438 sprintf(buf, "TextImplWindow=%d\n",text_window_number); 245 sprintf(buf, "TextWindow=%d\n",text_window_number);
439 str += buf; 246 str += buf;
440 if (rollback_save) { 247 if (rollback_save) {
441 ++save_selectcount; 248 ++save_selectcount;
442 BacklogItem save_item; 249 BacklogItem save_item;
443 save_item.SetSavepos(save_selectcount); 250 save_item.SetSavepos(save_selectcount);
456 vector<BacklogItem>::iterator it; 263 vector<BacklogItem>::iterator it;
457 it = backlog.begin(); 264 it = backlog.begin();
458 if (!rollback_save) { 265 if (!rollback_save) {
459 SaveFaceHash face_log; 266 SaveFaceHash face_log;
460 do { 267 do {
461 int cur_scn = -1; int cur_pos = -1; 268 int cur_scn = -1; int cur_pos = -1;
462 sprintf(buf, "Backlog.%d=",++cnt); 269 sprintf(buf, "Backlog.%d=",++cnt);
463 str += buf; 270 str += buf;
464 for (; it != backlog.end(); it++) { 271 for (; it != backlog.end(); it++) {
465 buf[0] = 0; int buflen = 0; 272 buf[0] = 0;
466 if (it->scn == -1) continue; 273 int buflen = 0;
467 if (it->pos == -1 && it->scn != 0) continue; 274 if (it->scn == -1)
468 275 continue;
469 buf[buflen++] = ';'; 276 if (it->pos == -1 && it->scn != 0)
470 if (it->scn == 0 && it->pos == -1) { 277 continue;
471 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\".", it->text.Save().c_str()); 278
472 } else { 279 buf[buflen++] = ';';
473 if (cur_scn != -1 && cur_scn != it->scn) break; // scn change 280 if (it->scn == 0 && it->pos == -1)
474 if (cur_pos != -1 && cur_pos/5000 != it->pos/5000) break; // pos exceeded 281 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\".", it->text.Save().c_str());
475 if (!it->text.container.empty()) { 282 else {
476 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\"", it->text.Save().c_str()); 283 if (cur_scn != -1 && cur_scn != it->scn) break; // scn change
284 if (cur_pos != -1 && cur_pos/5000 != it->pos/5000) break; // pos exceeded
285 if (!it->text.container.empty()) {
286 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\"", it->text.Save().c_str());
287 }
288 if (cur_scn == -1) { // scene change
289 buflen += snprintf(buf+buflen, 1000-buflen, ":%d:%d",it->scn,it->pos);
290 cur_scn = it->scn;
291 }
292 else
293 buflen += snprintf(buf+buflen, 1000-buflen, "%d",it->pos);
294 cur_pos = it->pos;
477 } 295 }
478 if (cur_scn == -1) { // scene change 296 if (it->koe != -1)
479 buflen += snprintf(buf+buflen, 1000-buflen, ":%d:%d",it->scn,it->pos); 297 buflen += snprintf(buf+buflen, 1000-buflen, ",%d",it->koe);
480 cur_scn = it->scn; 298 if (!it->face.empty()) {
481 } else { 299 if (it->koe == -1) buf[buflen++] = ',';
482 buflen += snprintf(buf+buflen, 1000-buflen, "%d",it->pos); 300 int face_num = face_log.Add(it->face);
301 if (face_num >= 0 && face_num < 20)
302 buflen += snprintf(buf+buflen, 1000-buflen, ",%c", 'A'+face_num);
303 else
304 buflen += snprintf(buf+buflen, 1000-buflen, ",\"%s\"", it->face.c_str());
483 } 305 }
484 cur_pos = it->pos; 306 buf[buflen++] = '\0';
485 } 307 if (buflen >= 1000) { // 万が一、バックログ1アイテムの大きさが 1000byte を越えるとき
486 if (it->koe != -1) 308 fprintf(stderr,"Fatal : Cannot save backlog crrectly; Please send bug report to the author.\n");
487 buflen += snprintf(buf+buflen, 1000-buflen, ",%d",it->koe); 309 } else str += buf;
488 if (!it->face.empty()) { 310 }
489 if (it->koe == -1) buf[buflen++] = ','; 311 str += "\n";
490 int face_num = face_log.Add(it->face); 312 } while(it != backlog.end());
491 if (face_num >= 0 && face_num < 20) 313 }
492 buflen += snprintf(buf+buflen, 1000-buflen, ",%c", 'A'+face_num); 314 }
493 else 315
494 buflen += snprintf(buf+buflen, 1000-buflen, ",\"%s\"", it->face.c_str()); 316 void Text::Load(const char* str) {
495 }
496 buf[buflen++] = '\0';
497 if (buflen >= 1000) { // 万が一、バックログ1アイテムの大きさが 1000byte を越えるとき
498 fprintf(stderr,"Fatal : Cannot save backlog crrectly; Please send bug report to the author.\n");
499 } else str += buf;
500 }
501 str += "\n";
502 } while(it != backlog.end());
503 }
504 return;
505 }
506
507 void TextImpl::Load(const char* str) {
508 if (text) text->wid->Clear(); 317 if (text) text->wid->Clear();
509 hide(); 318 hide();
510 text_window_number = 0; 319 text_window_number = 0;
511 save_selectcount = 0; 320 save_selectcount = 0;
512 if (sel_widget != NULL) { 321 if (sel_widget != NULL) {
528 vector<BacklogItem> new_backlog; 337 vector<BacklogItem> new_backlog;
529 backlog_item.Clear(); 338 backlog_item.Clear();
530 cur_backlog_item.Clear(); 339 cur_backlog_item.Clear();
531 drawn_backlog_item.Clear(); 340 drawn_backlog_item.Clear();
532 341
533 str = strstr(str, "\n[TextImpl Window]\n"); 342 str = strstr(str, "\n[Text Window]\n");
534 343
535 if (str) { 344 if (str) {
536 SaveFaceHash face_log; 345 SaveFaceHash face_log;
537 str += strlen("\n[TextImpl Window]\n"); 346 str += strlen("\n[Text Window]\n");
538 const char* strend = str; 347 const char* strend = str;
539 do { 348 do {
540 str = strend; 349 str = strend;
541 350
542 strend = strchr(str, '\n'); 351 strend = strchr(str, '\n');
543 if (strend == NULL) strend = str + strlen(str); 352 if (strend == NULL) strend = str + strlen(str);
544 else strend++; 353 else strend++;
545 354
546 if (str[0] == '[') break; // next section 355 if (str[0] == '[') break; // next section
547 if (strncmp(str, "TextImplWindow=",15) == 0) { 356 if (strncmp(str, "TextWindow=",15) == 0) {
548 str += 15; 357 str += 15;
549 sscanf(str, "%d", &text_window_number); 358 sscanf(str, "%d", &text_window_number);
550 } else if (strncmp(str, "SaveSelectCount=",16) == 0) { 359 } else if (strncmp(str, "SaveSelectCount=",16) == 0) {
551 str += 16; 360 str += 16;
552 sscanf(str, "%d", &save_selectcount); 361 sscanf(str, "%d", &save_selectcount);
630 backlog.swap(new_backlog); 439 backlog.swap(new_backlog);
631 } 440 }
632 // backlog.clear(); 441 // backlog.clear();
633 } 442 }
634 443
635 void TextImpl::hide(void) { 444 void Text::hide(void) {
636 if (text) text->hide(); 445 if (text) text->hide();
637 if (kcursor) kcursor->hide(); 446 if (kcursor) kcursor->hide();
638 text = NULL; 447 text = NULL;
639 } 448 }
640 void TextImpl::show(int num) { 449 void Text::show(int num) {
641 if (num != text_window_number) { 450 if (num != text_window_number) {
642 hide(); 451 hide();
643 if (num >= 0 && num < 32 && widgets[num] != 0) { 452 if (num >= 0 && num < 32 && widgets[num] != 0) {
644 text_window_number = num; 453 text_window_number = num;
645 } 454 }
658 ky += 8; 467 ky += 8;
659 kcursor->Pic()->Move(kx, ky); 468 kcursor->Pic()->Move(kx, ky);
660 } 469 }
661 } 470 }
662 471
663 void TextImpl::DrawBacklog(BacklogItem& item, Cmd& cmd) { 472 void Text::DrawBacklog(BacklogItem& item, Cmd& cmd) {
664 show(); 473 show();
665 text->wid->deactivate(); 474 text->wid->deactivate();
666 status_mask = Status(status_mask | BACKLOG_WAIT_MASK); 475 status_mask = Status(status_mask | BACKLOG_WAIT_MASK);
667 drawn_backlog_item = item; 476 drawn_backlog_item = item;
668 if (item.text.container.empty()) { 477 if (item.text.container.empty()) {
679 if (item.face.empty()) text->ResetFace(); 488 if (item.face.empty()) text->ResetFace();
680 else text->ShowFace(item.face.c_str()); 489 else text->ShowFace(item.face.c_str());
681 if (kcursor) kcursor->hide(); 490 if (kcursor) kcursor->hide();
682 } 491 }
683 492
684 void TextImpl::CreateSelBG(void) { 493 void Text::CreateSelBG(void) {
685 if (sel_bg1 != NULL || sel_bg2 != NULL) return; 494 if (sel_bg1 != NULL || sel_bg2 != NULL) return;
686 495
687 const char* btnfile1 = config->GetParaStr("#SELBTN.000.NAME"); 496 const char* btnfile1 = config->GetParaStr("#SELBTN.000.NAME");
688 const char* btnfile2 = config->GetParaStr("#SELBTN.000.BACK"); 497 const char* btnfile2 = config->GetParaStr("#SELBTN.000.BACK");
689 char path[1024]; 498 char path[1024];
702 sel_bg_rect = Rect(0,0,0,0); 511 sel_bg_rect = Rect(0,0,0,0);
703 if (sel_bg1) sel_bg_rect.join(Rect(*sel_bg1)); 512 if (sel_bg1) sel_bg_rect.join(Rect(*sel_bg1));
704 if (sel_bg2) sel_bg_rect.join(Rect(*sel_bg2)); 513 if (sel_bg2) sel_bg_rect.join(Rect(*sel_bg2));
705 } 514 }
706 515
707 void TextImpl::CreateSelect(Cmd& cmd) { 516 void Text::CreateSelect(Cmd& cmd) {
708 char key[1024]; 517 char key[23];
709 sprintf(key, "#WINDOW.%03d.SELCOM_USE",text_window_number); 518 sprintf(key, "#WINDOW.%03d.SELCOM_USE",text_window_number);
710 int sel_type = 0; 519 int sel_type = 0;
711 if (cmd.cmd3 == 1) config->GetParam(key, 1, &sel_type); 520 if (cmd.cmd3 == 1) config->GetParam(key, 1, &sel_type);
712 else if (cmd.cmd3 == 3) sel_type = 0; 521 else if (cmd.cmd3 == 3) sel_type = 0;
713 522
823 sel_widget->show_all(); 632 sel_widget->show_all();
824 status = WAIT_SELECT_INBOX; 633 status = WAIT_SELECT_INBOX;
825 } 634 }
826 } 635 }
827 636
828 void TextImpl::AddText(const char* str_o) { 637 void Text::AddText(const char* str_o) {
829 char str[10001]; 638 char str[10001];
830 if (text == NULL) return; 639 if (text == NULL) return;
831 /* まず、replace string を変換 */ 640 /* まず、replace string を変換 */
832 int i; 641 int i;
833 int cnt = 0; 642 int cnt = 0;
888 } else if (*s < 0 && s[1] != 0) s++; 697 } else if (*s < 0 && s[1] != 0) s++;
889 } 698 }
890 text_stream.Add(str_top); 699 text_stream.Add(str_top);
891 } 700 }
892 701
893 void TextImpl::impl_txtClear(Cmd& cmd) { 702 void Text::Exec(Cmd& cmd) {
894 if (text != NULL) {
895 text->ResetFace();
896 if (cmd.cmd2 == 3 && cmd.cmd3 == 151)
897 text->wid->Clear();
898 }
899 cur_backlog_item.face = "";
900 if (cmd.cmd2 == 3 && cmd.cmd3 == 151)
901 text_stream.Clear();
902 hide();
903 }
904
905 void TextImpl::impl_logKoe(Cmd& cmd) {
906 // PlayKoe ; 声出力コマンドをチェックする */
907 cur_backlog_item.koe = cmd.args[0].value;
908 }
909
910 void TextImpl::impl_pause(Cmd& cmd) {
911 if (text != NULL) {
912 eprintf("start\n");
913 text->StartText(text_stream);
914 if (skip_mode & SKIP_TEXT) text->wid->Flush();
915 else if (kcursor) kcursor->show();
916 status = WAIT_TEXT;
917 text_parsing = false;
918 }
919 backlog_item = cur_backlog_item;
920 if (cur_backlog_item.scn == 0 && cur_backlog_item.pos == -1) backlog_item.text = text_stream;
921 cur_backlog_item.Clear();
922
923 cmd.clear();
924 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
925 }
926
927 void TextImpl::impl_br(Cmd& cmd) {
928 text_stream.AddReturn();
929 cur_backlog_item.DeleteTextPos();
930 cmd.clear();
931 }
932
933 void TextImpl::impl_FaceOpen(Cmd& cmd) {
934 if (text == NULL)
935 show();
936 string s = cmd.Str(cmd.args[0]);
937 s += ".g00";
938 if (text != NULL)
939 text->ShowFace(s.c_str());
940 cur_backlog_item.face = s;
941 cmd.cmd_type = CMD_SAVECMD_ONCE;
942 }
943
944 void TextImpl::impl_FaceClear(Cmd& cmd) {
945 if (text == NULL)
946 show();
947 if (text)
948 text->ResetFace();
949 cur_backlog_item.face = "";
950 cmd.cmd_type = CMD_SAVECMD_ONCE;
951 }
952
953 void TextImpl::Exec(Cmd& cmd) {
954 if (cmd.cmd_type == CMD_TEXT) { 703 if (cmd.cmd_type == CMD_TEXT) {
955 if (text == NULL) { 704 if (text == NULL) {
956 show(); 705 show();
957 } 706 }
958 if (cmd.args.size() != 1) return; 707 if (cmd.args.size() != 1) return;
977 726
978 if (cmd.cmd_type != CMD_OTHER) return; 727 if (cmd.cmd_type != CMD_OTHER) return;
979 728
980 CommandHandler::Exec(cmd); 729 CommandHandler::Exec(cmd);
981 730
982 if (cmd.cmd1 == 0 && cmd.cmd2 == 3) { 731 if (cmd.cmd1 == 1 && cmd.cmd2 == 4) {
983 if (cmd.cmd3 == 0x78) { // ルビ関連
984 if (text == NULL) {
985 show();
986 }
987 if (cmd.cmd4 == 1) {
988 ruby_text_flag = true;
989 eprintf("SetRubyTextImpl.");
990 cmd.clear();
991 } else if (cmd.cmd4 == 0) {
992 if (ruby_text.length() == 0) { // ルビを振るテキストがない
993 eprintf("Cannot find ruby text.\n");
994 return;
995 }
996 if (cmd.args.size() != 1) return;
997 char debug1[1024], debug2[1024];
998 kconv( (unsigned char*)ruby_text.c_str(), (unsigned char*)debug1);
999 kconv( (unsigned char*)cmd.Str(cmd.args[0]), (unsigned char*)debug2);
1000 eprintf("SetRuby. %s, %s",debug1, debug2);
1001 text_stream.AddRuby(ruby_text.c_str(), cmd.Str(cmd.args[0]));
1002 cur_backlog_item.DeleteTextPos();
1003 cmd.clear();
1004 }
1005 } else if (cmd.cmd3 == 0x66) { // テキストウィンドウの形
1006 if (cmd.cmd4 == 0) {
1007 eprintf("set text window <- %d\n",cmd.args[0].value);
1008 if (text) show(cmd.args[0].value);
1009 else text_window_number = cmd.args[0].value;
1010 } else if (cmd.cmd4 == 1) { // default value
1011 eprintf("set text window <- default\n");
1012 if (text) show(0);
1013 else text_window_number = 0;
1014 }
1015 cmd.clear();
1016 } else if (cmd.cmd3 == 0x67) { // テキストウィンドウ表示?
1017 show();
1018 // 表示の際はテキストをクリアしない?
1019 // if (text) text->wid->Clear();
1020 // text_stream.Clear();
1021 cmd.clear();
1022 } else if (cmd.cmd3 == 0x68) { // テキスト表示?
1023 // 全テキスト表示
1024 if (text) {
1025 text->StartText(text_stream);
1026 text->wid->Flush();
1027 }
1028 cmd.clear();
1029 } else if (cmd.cmd3 == 0x98) { // テキストウィンドウクリア?
1030 show();
1031 if (text) text->wid->Clear();
1032 text_stream.Clear();
1033 cmd.clear();
1034 }
1035 } else if (cmd.cmd1 == 0 && cmd.cmd2 == 2 && (cmd.cmd3 == 1 || cmd.cmd3 == 3) && cmd.cmd4 == 0) {
1036 // 選択肢
1037 CreateSelect(cmd);
1038 //FIXME: Check if it's really clean
1039 if (text_parsing) {
1040 show();
1041 text->StartText(text_stream);
1042 if (skip_mode & SKIP_TEXT) text->wid->Flush();
1043 else if (kcursor) kcursor->hide();
1044 text_parsing = false;
1045 text_stream.Clear();
1046 }
1047 cmd.cmd_type = CMD_ROLLBACKPOINT; /* 選択肢はセーブ位置 / シナリオ巻き戻し位置 */
1048 // cmd.clear();
1049 } else if (cmd.cmd1 == 0 && cmd.cmd2 == 4) {
1050 if (cmd.cmd3 == 0x44c) { // テキストスキップ開始
1051 status_mask = Status(SKIPMASK | status_mask);
1052 cmd.clear();
1053 } else if (cmd.cmd3 == 0x3e8) { // ウィンドウ消去
1054 status_mask = Status(CLEARSCR_MASK | status_mask);
1055 cmd.clear();
1056 }
1057 } else if (cmd.cmd1 == 1 && cmd.cmd2 == 0x04) {
1058 /* ウェイト関連命令 */ 732 /* ウェイト関連命令 */
1059 if (cmd.cmd3 == 0x64 || cmd.cmd3 == 0x6f || cmd.cmd3 == 0x79) { 733 if (cmd.cmd3 == 0x65 || cmd.cmd3 == 0x70) {
1060 eprintf("wait %dmsec\n",cmd.args[0].value);
1061 if (cmd.cmd3 == 0x64 && text) {
1062 /* 0x64 だと文字描画中の待ちに使うことがある */
1063 text->StartText(text_stream);
1064 text->wid->Flush();
1065 }
1066 if (cmd.cmd3 == 0x6f || cmd.cmd3 == 0x79) wait_time = base_time + cmd.args[0].value;
1067 else wait_time = old_time + cmd.args[0].value;
1068 status = WAIT;
1069 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
1070 } else if (cmd.cmd3 == 0x65 || cmd.cmd3 == 0x70) {
1071 eprintf("wait %dmsec(click stop)\n",cmd.args[0].value); 734 eprintf("wait %dmsec(click stop)\n",cmd.args[0].value);
1072 if (cmd.cmd3 == 0x70) wait_time = base_time + cmd.args[0].value; 735 if (cmd.cmd3 == 0x70) wait_time = base_time + cmd.args[0].value;
1073 else wait_time = old_time + cmd.args[0].value; 736 else wait_time = old_time + cmd.args[0].value;
1074 status = WAIT_CLICK; 737 status = WAIT_CLICK;
1075 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため) 738 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
1372 } 1035 }
1373 } 1036 }
1374 } 1037 }
1375 1038
1376 extern int print_blit; 1039 extern int print_blit;
1377 bool TextImpl::Wait(unsigned int current_time, Cmd& cmd) { 1040 bool Text::Wait(unsigned int current_time, Cmd& cmd) {
1378 if (current_time != Event::Time::NEVER_WAKE) old_time = current_time; 1041 if (current_time != Event::Time::NEVER_WAKE) old_time = current_time;
1379 /* 1042 /*
1380 if (event.presscount(MOUSE_UP)) { 1043 if (event.presscount(MOUSE_UP)) {
1381 if (text) text->Pic()->ReBlit(); 1044 if (text) text->Pic()->ReBlit();
1382 } 1045 }
1558 return false; 1221 return false;
1559 } 1222 }
1560 1223
1561 void clearbtn_press(void* pointer, WidButton* button) { 1224 void clearbtn_press(void* pointer, WidButton* button) {
1562 if (pointer == NULL) return; 1225 if (pointer == NULL) return;
1563 TextImpl* t = (TextImpl*)pointer; 1226 Text* t = (Text*)pointer;
1564 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::CLEARSCR_MASK); 1227 t->status_mask = Text::Status(t->status_mask | Text::CLEARSCR_MASK);
1228 }
1229
1230 void Text::PressFuncSkip(void* pointer, WidButton* from) {
1231 if (pointer == NULL) return;
1232 Text* t = (Text*)pointer;
1233 t->status_mask = Text::Status(t->status_mask | Text::SKIPMASK);
1565 return; 1234 return;
1566 } 1235 }
1567 void TextImpl::PressFuncSkip(void* pointer, WidButton* from) { 1236 void Text::PressFuncLoad(void* pointer, WidButton* from) {
1568 if (pointer == NULL) return; 1237 if (pointer == NULL) return;
1569 TextImpl* t = (TextImpl*)pointer; 1238 Text* t = (Text*)pointer;
1570 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::SKIPMASK); 1239 t->status_mask = Text::Status(t->status_mask | Text::LOADMASK);
1571 return; 1240 }
1572 } 1241
1573 void TextImpl::PressFuncLoad(void* pointer, WidButton* from) { 1242 void Text::PressFuncSave(void* pointer, WidButton* from) {
1574 if (pointer == NULL) return; 1243 if (pointer == NULL) return;
1575 TextImpl* t = (TextImpl*)pointer; 1244 Text* t = (Text*)pointer;
1576 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::LOADMASK); 1245 t->status_mask = Text::Status(t->status_mask | Text::SAVEMASK);
1577 return; 1246 }
1578 } 1247
1579 void TextImpl::PressFuncSave(void* pointer, WidButton* from) { 1248 void Text::PressFuncBacklog(void* pointer, WidButton* from) {
1580 if (pointer == NULL) return; 1249 if (pointer == NULL) return;
1581 TextImpl* t = (TextImpl*)pointer; 1250 Text* t = (Text*)pointer;
1582 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::SAVEMASK); 1251 t->status_mask = Text::Status(t->status_mask | Text::BACKLOG_MASK);
1583 return; 1252 }
1584 } 1253
1585 void TextImpl::PressFuncBacklog(void* pointer, WidButton* from) { 1254 void Text::PressFuncBacklogFwd(void* pointer, WidButton* from) {
1586 if (pointer == NULL) return; 1255 if (pointer == NULL) return;
1587 TextImpl* t = (TextImpl*)pointer; 1256 Text* t = (Text*)pointer;
1588 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::BACKLOG_MASK); 1257 t->status_mask = Text::Status(t->status_mask | Text::BACKLOG_MASK_FWD);
1589 return; 1258 }
1590 } 1259
1591 void TextImpl::PressFuncBacklogFwd(void* pointer, WidButton* from) {
1592 if (pointer == NULL) return;
1593 TextImpl* t = (TextImpl*)pointer;
1594 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::BACKLOG_MASK_FWD);
1595 return;
1596 }
1597 void movebtn_drag(int from_x, int from_y, int x, int y, void* pointer, WidButton* button) { 1260 void movebtn_drag(int from_x, int from_y, int x, int y, void* pointer, WidButton* button) {
1598 if (pointer == NULL) return; 1261 if (pointer == NULL) return;
1599 fprintf(stderr,"drag.\n"); 1262 fprintf(stderr,"drag.\n");
1600 } 1263 }
1601 1264
1617 // 0, 1, 13, 12, 2, 3, 4, 5, 6, 7 // princess bride? 1280 // 0, 1, 13, 12, 2, 3, 4, 5, 6, 7 // princess bride?
1618 0, 1, 13, 14, 2, 3, 4, 5, 6, 7 // tomoyo after? 1281 0, 1, 13, 14, 2, 3, 4, 5, 6, 7 // tomoyo after?
1619 }; 1282 };
1620 1283
1621 static WidButton::PressFunc btnpress[BTNCNT] = { 1284 static WidButton::PressFunc btnpress[BTNCNT] = {
1622 0, clearbtn_press, &TextImpl::PressFuncSkip,0,&TextImpl::PressFuncBacklogFwd,&TextImpl::PressFuncBacklog,&TextImpl::PressFuncBacklogFwd,&TextImpl::PressFuncSave,&TextImpl::PressFuncLoad,0 1285 0, clearbtn_press, &Text::PressFuncSkip,0,&Text::PressFuncBacklogFwd,&Text::PressFuncBacklog,&Text::PressFuncBacklogFwd,&Text::PressFuncSave,&Text::PressFuncLoad,0
1623 }; 1286 };
1624 1287
1625 static WidButton::DragFunc btndrag[BTNCNT] = { 1288 static WidButton::DragFunc btndrag[BTNCNT] = {
1626 movebtn_drag, 0,0,0,0, 0,0,0,0, 0 1289 movebtn_drag, 0,0,0,0, 0,0,0,0, 0
1627 }; 1290 };
1628 1291
1629 void TextImpl::SetTextSpeed(int speed) { 1292 void Text::SetTextSpeed(int speed) {
1630 // 100 : 10char / sec 1293 // 100 : 10char / sec
1631 // 10 : 100char / sec 1294 // 10 : 100char / sec
1632 // text widget: 1295 // text widget:
1633 if (speed <= 0) speed = -1; 1296 if (speed <= 0) speed = -1;
1634 else if (speed > 1000) speed = 1; 1297 else if (speed > 1000) speed = 1;
1636 int i; 1299 int i;
1637 for (i=0; i<32; i++) 1300 for (i=0; i<32; i++)
1638 if (widgets[i]) widgets[i]->wid->SetSpeed(speed); 1301 if (widgets[i]) widgets[i]->wid->SetSpeed(speed);
1639 } 1302 }
1640 1303
1641 void TextImpl::SetTextWait(int wait) { 1304 void Text::SetTextWait(int wait) {
1642 int i; 1305 int i;
1643 for (i=0; i<32; i++) 1306 for (i=0; i<32; i++)
1644 if (widgets[i]) widgets[i]->wid->SetWait(wait); 1307 if (widgets[i]) widgets[i]->wid->SetWait(wait);
1645 } 1308 }
1646 1309
1647 void TextImpl::SetWindowColor(int r, int g, int b, int a, bool is_transparent) { 1310 void Text::SetWindowColor(int r, int g, int b, int a, bool is_transparent) {
1648 char key[1024]; 1311 char key[1024];
1649 int w; 1312 int w;
1650 1313
1651 for (w=0; w<32; w++) { 1314 for (w=0; w<32; w++) {
1652 if (widgets[w] == NULL) continue; 1315 if (widgets[w] == NULL) continue;
1666 widgets[w]->wid->Pic()->SetSurfaceAttribute(PicBase::BLIT_MULTIPLY); 1329 widgets[w]->wid->Pic()->SetSurfaceAttribute(PicBase::BLIT_MULTIPLY);
1667 parent.Root().DeleteSurface(back_s); 1330 parent.Root().DeleteSurface(back_s);
1668 } 1331 }
1669 } 1332 }
1670 1333
1671 void TextImpl::SetCursor(int cursor_no) { 1334 void Text::SetCursor(int cursor_no) {
1672 char key[1024]; 1335 char key[1024];
1673 sprintf(key, "#CURSOR.%03d.NAME", cursor_no); 1336 sprintf(key, "#CURSOR.%03d.NAME", cursor_no);
1674 string path = config->GetParaStr(key); 1337 string path = config->GetParaStr(key);
1675 if (path.length() == 0) return; // 名前なし 1338 if (path.length() == 0) return; // 名前なし
1676 path += ".pdt"; 1339 path += ".pdt";
1771 return ret; 1434 return ret;
1772 } 1435 }
1773 1436
1774 /**************************************************************:: 1437 /**************************************************************::
1775 ** 1438 **
1776 ** Text
1777 */
1778 Text::Text(Event::Container& _event, PicContainer& _parent) {
1779 pimpl = new TextImpl(_event, _parent, backlog, backlog_item);
1780 }
1781
1782 Text::~Text() {
1783 delete pimpl;
1784 pimpl = NULL;
1785 }
1786
1787 void Text::InitWindow(void) {
1788 pimpl->InitWindow();
1789 }
1790
1791 void Text::Exec(Cmd& cmd) {
1792 pimpl->Exec(cmd);
1793 }
1794
1795 bool Text::Wait(unsigned int current_time, Cmd& cmd) {
1796 return pimpl->Wait(current_time, cmd);
1797 }
1798
1799 void Text::SetSkipMode(SkipMode mode) {
1800 pimpl->SetSkipMode(mode);
1801 }
1802
1803 void Text::Save(std::string& str, bool select_save) {
1804 pimpl->Save(str, select_save);
1805 }
1806
1807 void Text::Load(const char* str) {
1808 pimpl->Load(str);
1809 }
1810
1811 void Text::hide(void) {
1812 pimpl->hide();
1813 }
1814
1815 void Text::show(void) {
1816 pimpl->show();
1817 }
1818
1819 void Text::show(int num) {
1820 pimpl->show(num);
1821 }
1822
1823 void Text::DrawBacklog(BacklogItem& item, Cmd& cmd) {
1824 pimpl->DrawBacklog(item, cmd);
1825 }
1826
1827 /**************************************************************::
1828 **
1829 ** BacklogItem 1439 ** BacklogItem
1830 */ 1440 */
1831 1441
1832 BacklogItem::BacklogItem(void) { 1442 BacklogItem::BacklogItem(void) {
1833 scn = -1; 1443 scn = -1;
1869 void BacklogItem::SetSavepos(int p) { 1479 void BacklogItem::SetSavepos(int p) {
1870 Clear(); 1480 Clear();
1871 scn = SaveSelect; 1481 scn = SaveSelect;
1872 pos = p; 1482 pos = p;
1873 } 1483 }
1484
1485
1486 /**************************************************************::
1487 **
1488 ** TextWindow
1489 */
1874 1490
1875 Rect TextWindow::WakuSize(PicContainer& pic, int waku_no) { 1491 Rect TextWindow::WakuSize(PicContainer& pic, int waku_no) {
1876 char key[1024]; 1492 char key[1024];
1877 sprintf(key, "#WAKU.%03d.000.NAME", waku_no); 1493 sprintf(key, "#WAKU.%03d.000.NAME", waku_no);
1878 const char* name = AyuSysConfig::GetInstance()->GetParaStr(key); 1494 const char* name = AyuSysConfig::GetInstance()->GetParaStr(key);
2073 } 1689 }
2074 } 1690 }
2075 MakeWaku(*wid->PicNode(), event,waku_no, win_no, use_btn, callback); 1691 MakeWaku(*wid->PicNode(), event,waku_no, win_no, use_btn, callback);
2076 } 1692 }
2077 1693
2078 void TextImpl::InitWindow(void) { 1694 TextWindow::~TextWindow()
1695 {
1696 if (name_container != NULL) {
1697 delete name_container;
1698 name_container = NULL;
1699 }
2079 int i; 1700 int i;
2080 int w; 1701 for (i=0; i<8; i++) {
2081 std::string str; 1702 if (face_pics[i] != NULL) {
2082 1703 delete face_pics[i];
2083 for (w=0; w<32; w++) { 1704 face_pics[i] = NULL;
2084 widgets[w] = new TextWindow(parent, event, w, (void*)this); 1705 }
2085 if (widgets[w]->wid == 0) { 1706 }
2086 delete widgets[w]; 1707 if (wid != NULL) {
2087 widgets[w] = NULL; 1708 delete wid;
2088 } 1709 wid = NULL;
2089 } 1710 }
2090 SetCursor(0); 1711 }
2091 for (i=0; i<26; i++) { 1712
2092 char buf[1024]; 1713 void TextWindow::show(void)
2093 sprintf(buf, "#NAME.%c", i+'A'); 1714 {
2094 const char* s = config->GetParaStr(buf); 1715 wid->show();
2095 if (s != NULL) replace_name[i] = s; 1716 if (name_container != NULL && name_visible)
2096 } 1717 name_container->show();
2097 // replace_name2 : 初期設定 1718 if (face != NULL)
2098 // 渚、秋生、渚 (CLANNAD) 1719 face->show();
2099 char name_nagisa[3] = {'\x8f', '\x8d', '\0'}; 1720 }
2100 char name_akio[5] = {'\x8f', '\x48', '\x90', '\xb6', '\0'}; 1721
2101 replace_name2[0] = name_nagisa; 1722 void TextWindow::hide(void)
2102 replace_name2[1] = name_akio; 1723 {
2103 replace_name2[2] = name_nagisa; 1724 wid->hide();
2104 text = NULL; 1725 if (name_container != NULL)
2105 /* テキスト速度の設定 */ 1726 name_container->hide();
2106 int speed, mod, wait, auto_mod; 1727 if (face != NULL)
2107 config->GetParam("#INIT_MESSAGE_SPEED", 1, &speed); 1728 face->hide();
2108 config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &mod); 1729 }
2109 config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &auto_mod); 1730
2110 config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait); 1731 void TextWindow::ShowFace(const char* path)
2111 if (mod) speed = -1; 1732 {
2112 if (!auto_mod) wait = -1; 1733 if (face == NULL)
2113 SetTextSpeed(speed); 1734 return;
2114 SetTextWait(wait); 1735 face->SetSurface(path, 0, 0);
2115 return; 1736 }
2116 } 1737
1738 void TextWindow::ResetFace(void) {
1739 if (face == NULL)
1740 return;
1741 face->SetSurface((Surface*) NULL, 0, 0);
1742 }
1743
1744 void TextWindow::StartText(const TextStream& _stream)
1745 {
1746 wid->Clear();
1747 wid->stream = _stream;
1748 if (name_container != NULL) {
1749 char namestr[1024];
1750 namestr[0] = 0;
1751 wid->stream.RemoveName(namestr, 1024);
1752 if (namestr[0] == 0) {
1753 name_container->hide();
1754 }
1755 else {
1756 if (name != NULL) {
1757 name_container->show_all();
1758 name->SetText(namestr);
1759 }
1760 }
1761 }
1762 wid->Start();
1763 }
1764
1765 void TextWindow::SetName(const char* n)
1766 {
1767 if (name_container != NULL && name != NULL) {
1768 if (n[0]) {
1769 name_container->show();
1770 name->SetText(n);
1771 name_visible = true;
1772 }
1773 else {
1774 name_container->hide();
1775 name_visible = false;
1776 }
1777 }
1778 }
1779
1780 /**************************************************************::
1781 **
1782 ** SaveFaceHash
1783 */
1784
1785 void SaveFaceHash::NewNode(string face, int face_id)
1786 {
1787 facetonum[face] = face_id;
1788 container.push_front(Node(face, face_id));
1789 if (container.size() > size_max) {
1790 Node remove = container.back();
1791 container.pop_back();
1792 facetonum.erase(remove.first);
1793 }
1794 }
1795
1796 int SaveFaceHash::Add(string face)
1797 {
1798 int id;
1799 int ret = -1;
1800 int i;
1801 List::iterator it;
1802 if (face.empty()) return -1;
1803 if (facetonum.find(face) == facetonum.end()) {
1804 id = ++id_max;
1805 NewNode(face, id);
1806 ret = -1;
1807 }
1808 else {
1809 id = facetonum[face];
1810 for (i=0, it=container.begin(); it != container.end(); i++, it++) {
1811 if (it->second == id) {
1812 ret = i;
1813 Node n = *it;
1814 container.erase(it);
1815 container.push_front(n);
1816 break;
1817 }
1818 }
1819 }
1820 return ret;
1821 }
1822
1823 string SaveFaceHash::Get(int num) {
1824 if (num < 0) return "";
1825 List::iterator it = container.begin();
1826 for (; it != container.end(); it++) {
1827 if (num == 0) return it->first;
1828 num--;
1829 }
1830 return "";
1831 }
1832
1833 int SaveFaceHash::size_max = 20;
1834