1 /* -*- C++ -*-
2  *
3  *  ONScripter_rmenu.cpp - Right click menu handler of ONScripter
4  *
5  *  Copyright (c) 2001-2020 Ogapee. All rights reserved.
6  *
7  *  ogapee@aqua.dti2.ne.jp
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "ONScripter.h"
25 
26 #define DIALOG_W 241
27 #define DIALOG_H 167
28 #define DIALOG_HEADER 32
29 #define DIALOG_FOOTER 64
30 #define DIALOG_BUTTON_W 96
31 #define DIALOG_BUTTON_H 42
32 
33 #if defined(ENABLE_1BYTE_CHAR) && defined(FORCE_1BYTE_CHAR)
34 #define MESSAGE_SAVE_EXIST "`%s%s    Date %s/%s    Time %s:%s"
35 #define MESSAGE_SAVE_EMPTY "`%s%s    ------------------------"
36 #define MESSAGE_SAVE_CONFIRM "`Save in slot %s%s?"
37 #define MESSAGE_LOAD_CONFIRM "`Load from slot %s%s?"
38 #define MESSAGE_RESET_CONFIRM "`Return to Title Menu?"
39 #define MESSAGE_END_CONFIRM "`Quit?"
40 #define MESSAGE_YES "Yes"
41 #define MESSAGE_NO "No"
42 #define MESSAGE_OK "OK"
43 #define MESSAGE_CANCEL "Cancel"
44 #else
45 #define MESSAGE_SAVE_EXIST "%s%s�@%s��%s��%s��%s��"
46 #define MESSAGE_SAVE_EMPTY "%s%s�@�|�|�|�|�|�|�|�|�|�|�|�|"
47 #define MESSAGE_SAVE_CONFIRM "%s%s�ɃZ�[�u���܂��B��낵���ł����H"
48 #define MESSAGE_LOAD_CONFIRM "%s%s�����[�h���܂��B��낵���ł����H"
49 #define MESSAGE_RESET_CONFIRM "���Z�b�g���܂��B��낵���ł����H"
50 #define MESSAGE_END_CONFIRM "�I�����܂��B��낵���ł����H"
51 #define MESSAGE_YES "�͂�"
52 #define MESSAGE_NO "������"
53 #define MESSAGE_OK "�n�j"
54 #define MESSAGE_CANCEL "�L�����Z��"
55 #endif
56 
57 #ifdef ANDROID
58 #include <stdarg.h>
osprintf(char * str,const char * format,...)59 static int osprintf(char *str, const char *format, ...)
60 {
61     str[0] = 0;
62     va_list list;
63     va_start( list, format );
64     while(*format){
65         if (format[0] == '%' && format[1] == 's'){
66             strcat(str, va_arg(list, char*));
67             format += 2;
68         }
69         else{
70             strncat(str, format++, 1);
71         }
72     }
73     va_end( list );
74     return strlen(str);
75 }
76 #define sprintf osprintf
77 #endif
78 
enterSystemCall()79 void ONScripter::enterSystemCall()
80 {
81     shelter_button_link = root_button_link.next;
82     root_button_link.next = NULL;
83     shelter_select_link = root_select_link.next;
84     root_select_link.next = NULL;
85     shelter_event_mode = event_mode;
86     shelter_mouse_state.x = last_mouse_state.x;
87     shelter_mouse_state.y = last_mouse_state.y;
88     event_mode = IDLE_EVENT_MODE;
89     shelter_display_mode = display_mode;
90     display_mode = DISPLAY_MODE_TEXT;
91 
92     shelter_refresh_shadow_text_mode = refresh_shadow_text_mode;
93     refresh_shadow_text_mode &= ~REFRESH_CURSOR_MODE;
94     stopAnimation( clickstr_state );
95 }
96 
leaveSystemCall(bool restore_flag)97 void ONScripter::leaveSystemCall( bool restore_flag )
98 {
99     current_font = &sentence_font;
100     display_mode = shelter_display_mode;
101 
102     if ( restore_flag ){
103 
104         current_page = cached_page;
105         SDL_BlitSurface( backup_surface, NULL, text_info.image_surface, NULL );
106         root_button_link.next = shelter_button_link;
107         root_select_link.next = shelter_select_link;
108 
109         event_mode = shelter_event_mode;
110         refresh_shadow_text_mode = shelter_refresh_shadow_text_mode;
111         if ( event_mode & WAIT_BUTTON_MODE ){
112             int x = shelter_mouse_state.x * screen_device_width / screen_width;
113             int y = shelter_mouse_state.y * screen_device_width / screen_width;
114             SDL_WarpMouse(x, y);
115         }
116     }
117     dirty_rect.fill( screen_width, screen_height );
118     flush( refreshMode() );
119 
120     //printf("leaveSystemCall %d %d\n",event_mode, clickstr_state);
121 
122     refreshMouseOverButton();
123 
124     system_menu_mode = SYSTEM_NULL;
125 }
126 
executeSystemCall()127 int ONScripter::executeSystemCall()
128 {
129     SDL_BlitSurface( text_info.image_surface, NULL, backup_surface, NULL );
130 
131     enterSystemCall();
132 
133     while(system_menu_mode != SYSTEM_NULL){
134         dirty_rect.fill( screen_width, screen_height );
135         switch(system_menu_mode){
136           case SYSTEM_SKIP:
137             executeSystemSkip();
138             return 2; // continue parsing text
139             break;
140           case SYSTEM_RESET:
141             if (executeSystemReset()) return 1; // stop parsing text
142             break;
143           case SYSTEM_SAVE:
144             executeSystemSave();
145             break;
146           case SYSTEM_LOAD:
147             if (executeSystemLoad()) return 1; // stop parsing text
148             break;
149           case SYSTEM_LOOKBACK:
150             executeSystemLookback();
151             break;
152           case SYSTEM_WINDOWERASE:
153             executeWindowErase();
154             break;
155           case SYSTEM_MENU:
156             executeSystemMenu();
157             break;
158           case SYSTEM_AUTOMODE:
159             executeSystemAutomode();
160             return 2; // continue parsing text
161             break;
162           case SYSTEM_END:
163             executeSystemEnd();
164             break;
165           default:
166             leaveSystemCall();
167         }
168     }
169 
170     return 0;
171 }
172 
executeSystemMenu()173 void ONScripter::executeSystemMenu()
174 {
175     current_font = &menu_font;
176 
177     if ( menuselectvoice_file_name[MENUSELECTVOICE_OPEN] )
178         playSound(menuselectvoice_file_name[MENUSELECTVOICE_OPEN],
179                   SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
180 
181     text_info.fill( 0, 0, 0, 0 );
182     flush( refreshMode() );
183 
184     menu_font.num_xy[0] = rmenu_link_width;
185     menu_font.num_xy[1] = rmenu_link_num;
186     menu_font.top_xy[0] = (screen_width * screen_ratio2 / screen_ratio1 - menu_font.num_xy[0] * menu_font.pitch_xy[0]) / 2;
187     menu_font.top_xy[1] = (screen_height * screen_ratio2 / screen_ratio1  - menu_font.num_xy[1] * menu_font.pitch_xy[1]) / 2;
188     menu_font.setXY(0, 0);
189 
190     RMenuLink *link = root_rmenu_link.next;
191     int counter = 1;
192     while( link ){
193         ButtonLink *button = getSelectableSentence( link->label, &menu_font, false );
194         root_button_link.insert( button );
195         button->no = counter++;
196 
197         link = link->next;
198         flush( refreshMode() );
199     }
200 
201     flushEvent();
202     refreshMouseOverButton();
203 
204     event_mode = WAIT_BUTTON_MODE;
205     do waitEventSub(-1);
206     while (current_button_state.button == 0);
207 
208     deleteButtonLink();
209 
210     if ( current_button_state.button == -1 ){
211         if ( menuselectvoice_file_name[MENUSELECTVOICE_CANCEL] )
212             playSound(menuselectvoice_file_name[MENUSELECTVOICE_CANCEL],
213                       SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
214         leaveSystemCall();
215         return;
216     }
217 
218     if ( menuselectvoice_file_name[MENUSELECTVOICE_CLICK] )
219         playSound(menuselectvoice_file_name[MENUSELECTVOICE_CLICK],
220                   SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
221 
222     link = root_rmenu_link.next;
223     counter = 1;
224     while ( link ){
225         if ( current_button_state.button == counter++ ){
226             system_menu_mode = link->system_call_no;
227             break;
228         }
229         link = link->next;
230     }
231 }
232 
executeSystemSkip()233 void ONScripter::executeSystemSkip()
234 {
235     skip_mode |= SKIP_NORMAL;
236     leaveSystemCall();
237 }
238 
executeSystemAutomode()239 void ONScripter::executeSystemAutomode()
240 {
241     automode_flag = true;
242     skip_mode &= ~SKIP_NORMAL;
243     printf("systemcall_automode: change to automode\n");
244     leaveSystemCall();
245 }
246 
executeSystemReset()247 bool ONScripter::executeSystemReset()
248 {
249     if ( executeSystemYesNo( SYSTEM_RESET ) ){
250         resetCommand();
251         leaveSystemCall( false );
252 
253         return true;
254     }
255 
256     leaveSystemCall();
257 
258     return false;
259 }
260 
executeSystemEnd()261 void ONScripter::executeSystemEnd()
262 {
263     if ( executeSystemYesNo( SYSTEM_END ) )
264         endCommand();
265     else
266         leaveSystemCall();
267 }
268 
executeWindowErase()269 void ONScripter::executeWindowErase()
270 {
271     if (windowchip_sprite_no >= 0)
272         sprite_info[windowchip_sprite_no].visible = false;
273 
274     display_mode = DISPLAY_MODE_NORMAL;
275     flush(mode_saya_flag ? REFRESH_SAYA_MODE : REFRESH_NORMAL_MODE);
276 
277     event_mode = WAIT_TIMER_MODE | WAIT_BUTTON_MODE;
278     waitEventSub(-1);
279 
280     if (windowchip_sprite_no >= 0)
281         sprite_info[windowchip_sprite_no].visible = true;
282 
283     leaveSystemCall();
284 }
285 
executeSystemLoad()286 bool ONScripter::executeSystemLoad()
287 {
288     current_font = &menu_font;
289 
290     text_info.fill( 0, 0, 0, 0 );
291 
292     int n = script_h.enc.getNum((unsigned char*)save_item_name);
293     menu_font.num_xy[0] = (n+1)/2 + 2 + 13;
294     menu_font.num_xy[1] = num_save_file + 2;
295     menu_font.top_xy[0] = (screen_width * screen_ratio2 / screen_ratio1 - menu_font.num_xy[0] * menu_font.pitch_xy[0]) / 2;
296     menu_font.top_xy[1] = (screen_height * screen_ratio2 / screen_ratio1  - menu_font.num_xy[1] * menu_font.pitch_xy[1]) / 2;
297     int n2 = script_h.enc.getNum((unsigned char*)load_menu_name);
298     menu_font.setXY((menu_font.num_xy[0]*2 - n2)/4, 0);
299     uchar3 color = {0xff, 0xff, 0xff};
300     drawString( load_menu_name, color, &menu_font, true, accumulation_surface, NULL, &text_info );
301     menu_font.newLine();
302     menu_font.newLine();
303 
304     flush( refreshMode() );
305 
306     bool nofile_flag;
307     char *buffer = new char[menu_font.num_xy[0]*4 + 1];
308 
309     SaveFileInfo save_file_info;
310     for ( unsigned int i=1 ; i<=num_save_file ; i++ ){
311         searchSaveFile( save_file_info, i );
312         menu_font.setXY((menu_font.num_xy[0]*2 - (n + 15*2)) / 4);
313 
314         char *format_str = NULL;
315         if ( save_file_info.valid ){
316             setStr(&format_str, MESSAGE_SAVE_EXIST, -1, true);
317             sprintf(buffer, format_str,
318                     save_item_name,
319                     save_file_info.sjis_no,
320                     save_file_info.sjis_month,
321                     save_file_info.sjis_day,
322                     save_file_info.sjis_hour,
323                     save_file_info.sjis_minute);
324             nofile_flag = false;
325         }
326         else{
327             setStr(&format_str, MESSAGE_SAVE_EMPTY, -1, true);
328             sprintf(buffer, format_str,
329                     save_item_name,
330                     save_file_info.sjis_no);
331             nofile_flag = true;
332         }
333         if (format_str) delete[] format_str;
334         ButtonLink *button = getSelectableSentence( buffer, &menu_font, false, nofile_flag );
335         root_button_link.insert( button );
336         button->no = i;
337         flush( refreshMode() );
338     }
339     delete[] buffer;
340 
341     refreshMouseOverButton();
342 
343     event_mode = WAIT_BUTTON_MODE;
344     int file_no = 0;
345     while(1){
346         waitEventSub(-1);
347 
348         if ( current_button_state.button > 0 ){
349             file_no = current_button_state.button;
350             searchSaveFile( save_file_info, file_no );
351             if ( !save_file_info.valid ) continue;
352         }
353 
354         if (current_button_state.button != 0) break;
355     }
356 
357     if ( current_button_state.button > 0 ){
358         deleteButtonLink();
359 
360         if (executeSystemYesNo( SYSTEM_LOAD, file_no )){
361             current_font = &sentence_font;
362             system_menu_mode = 0; // for fadeout in mp3stopCommand()
363             if ( loadSaveFile( file_no ) )
364                 return false;
365 
366             leaveSystemCall( false );
367             saveon_flag = true;
368             internal_saveon_flag = true;
369             text_on_flag = false;
370             indent_offset = 0;
371             line_enter_status = 0;
372             page_enter_status = 0;
373             string_buffer_offset = 0;
374             break_flag = false;
375 
376             flushEvent();
377 
378 #ifdef USE_LUA
379             if (lua_handler.isCallbackEnabled(LUAHandler::LUA_LOAD)){
380                 if (lua_handler.callFunction(true, "load", &file_no))
381                     errorAndExit( lua_handler.error_str );
382             }
383 #endif
384 
385             if (loadgosub_label)
386                 gosubReal( loadgosub_label, script_h.getCurrent() );
387 
388             return true;
389         }
390 
391         return false;
392     }
393 
394     deleteButtonLink();
395     leaveSystemCall();
396 
397     return false;
398 }
399 
executeSystemSave()400 void ONScripter::executeSystemSave()
401 {
402     current_font = &menu_font;
403 
404     text_info.fill( 0, 0, 0, 0 );
405 
406     int n = script_h.enc.getNum((unsigned char*)save_item_name);
407     menu_font.num_xy[0] = (n+1)/2 + 2 + 13;
408     menu_font.num_xy[1] = num_save_file + 2;
409     menu_font.top_xy[0] = (screen_width * screen_ratio2 / screen_ratio1 - menu_font.num_xy[0] * menu_font.pitch_xy[0]) / 2;
410     menu_font.top_xy[1] = (screen_height * screen_ratio2 / screen_ratio1  - menu_font.num_xy[1] * menu_font.pitch_xy[1]) / 2;
411     int n2 = script_h.enc.getNum((unsigned char*)save_menu_name);
412     menu_font.setXY((menu_font.num_xy[0]*2 - n2)/4, 0);
413     uchar3 color = {0xff, 0xff, 0xff};
414     drawString( save_menu_name, color, &menu_font, true, accumulation_surface, NULL, &text_info );
415     menu_font.newLine();
416     menu_font.newLine();
417 
418     flush( refreshMode() );
419 
420     bool nofile_flag;
421     char *buffer = new char[menu_font.num_xy[0]*4 + 1];
422 
423     for ( unsigned int i=1 ; i<=num_save_file ; i++ ){
424         SaveFileInfo save_file_info;
425         searchSaveFile( save_file_info, i );
426         menu_font.setXY((menu_font.num_xy[0]*2 - (n + 15*2)) / 4);
427 
428         char *format_str = NULL;
429         if ( save_file_info.valid ){
430             setStr(&format_str, MESSAGE_SAVE_EXIST, -1, true);
431             sprintf(buffer, format_str,
432                     save_item_name,
433                     save_file_info.sjis_no,
434                     save_file_info.sjis_month,
435                     save_file_info.sjis_day,
436                     save_file_info.sjis_hour,
437                     save_file_info.sjis_minute);
438             nofile_flag = false;
439         }
440         else{
441             setStr(&format_str, MESSAGE_SAVE_EMPTY, -1, true);
442             sprintf(buffer, format_str,
443                     save_item_name,
444                     save_file_info.sjis_no);
445             nofile_flag = true;
446         }
447         if (format_str) delete[] format_str;
448         ButtonLink *button = getSelectableSentence( buffer, &menu_font, false, nofile_flag );
449         root_button_link.insert( button );
450         button->no = i;
451         flush( refreshMode() );
452     }
453     delete[] buffer;
454 
455     refreshMouseOverButton();
456 
457     event_mode = WAIT_BUTTON_MODE;
458     do waitEventSub(-1);
459     while (current_button_state.button == 0);
460 
461     deleteButtonLink();
462 
463     if ( current_button_state.button > 0 ){
464         int file_no = current_button_state.button;
465         if (executeSystemYesNo( SYSTEM_SAVE, file_no )){
466             if (saveon_flag && internal_saveon_flag) storeSaveFile();
467             writeSaveFile( file_no );
468             leaveSystemCall();
469         }
470         return;
471     }
472 
473     leaveSystemCall();
474 }
475 
executeSystemYesNo(int caller,int file_no)476 bool ONScripter::executeSystemYesNo( int caller, int file_no )
477 {
478     current_font = &menu_font;
479 
480     text_info.fill( 0, 0, 0, 0 );
481     dirty_rect.fill( screen_width, screen_height );
482 
483     char name[128] = {'\0'};
484     char *format_str = NULL;
485     if ( caller == SYSTEM_SAVE ){
486         SaveFileInfo save_file_info;
487         searchSaveFile( save_file_info, file_no );
488         setStr(&format_str, MESSAGE_SAVE_CONFIRM, -1, true);
489         sprintf(name, format_str,
490                 save_item_name,
491                 save_file_info.sjis_no);
492     }
493     else if ( caller == SYSTEM_LOAD ){
494         SaveFileInfo save_file_info;
495         searchSaveFile( save_file_info, file_no );
496         setStr(&format_str, MESSAGE_LOAD_CONFIRM, -1, true);
497         sprintf(name, format_str,
498                 save_item_name,
499                 save_file_info.sjis_no);
500     }
501     else if ( caller ==  SYSTEM_RESET ){
502         setStr(&format_str, MESSAGE_RESET_CONFIRM, -1, true);
503         strcpy(name, format_str);
504     }
505     else if ( caller ==  SYSTEM_END ){
506         setStr(&format_str, MESSAGE_END_CONFIRM, -1, true);
507         strcpy(name, format_str);
508     }
509 
510     int n = script_h.enc.getNum((unsigned char*)name);
511     menu_font.num_xy[0] = (n+1)/2;
512     menu_font.num_xy[1] = 3;
513     menu_font.top_xy[0] = (screen_width * screen_ratio2 / screen_ratio1 - menu_font.num_xy[0] * menu_font.pitch_xy[0]) / 2;
514     menu_font.top_xy[1] = (screen_height * screen_ratio2 / screen_ratio1  - menu_font.num_xy[1] * menu_font.pitch_xy[1]) / 2;
515     menu_font.setXY(0, 0);
516     uchar3 color = {0xff, 0xff, 0xff};
517     drawString( name, color, &menu_font, true, accumulation_surface, NULL, &text_info );
518 
519     flush( refreshMode() );
520 
521     int offset1 = n/5;
522     int offset2 = n/2 - offset1;
523     setStr(&format_str, MESSAGE_YES, -1, true);
524     strcpy(name, format_str);
525     menu_font.setXY(offset1-2, 2);
526     ButtonLink *button = getSelectableSentence( name, &menu_font, false );
527     root_button_link.insert( button );
528     button->no = 1;
529 
530     setStr(&format_str, MESSAGE_NO, -1, true);
531     strcpy(name, format_str);
532     menu_font.setXY(offset2, 2);
533     button = getSelectableSentence( name, &menu_font, false );
534     root_button_link.insert( button );
535     button->no = 2;
536 
537     if (format_str) delete[] format_str;
538 
539     flush( refreshMode() );
540 
541     refreshMouseOverButton();
542 
543     event_mode = WAIT_BUTTON_MODE;
544     do waitEventSub(-1);
545     while (current_button_state.button == 0);
546 
547     deleteButtonLink();
548 
549     if ( current_button_state.button == 1 ){ // yes is selected
550         if ( menuselectvoice_file_name[MENUSELECTVOICE_YES] )
551             playSound(menuselectvoice_file_name[MENUSELECTVOICE_YES],
552                       SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
553         return true;
554     }
555     else{
556         if ( menuselectvoice_file_name[MENUSELECTVOICE_NO] )
557             playSound(menuselectvoice_file_name[MENUSELECTVOICE_NO],
558                       SOUND_CHUNK, false, MIX_WAVE_CHANNEL);
559         return false;
560     }
561 }
562 
setupLookbackButton()563 void ONScripter::setupLookbackButton()
564 {
565     deleteButtonLink();
566 
567     /* ---------------------------------------- */
568     /* Previous button check */
569     if ( (current_page->previous->text_count > 0 ) &&
570          current_page != start_page ){
571         ButtonLink *button = new ButtonLink();
572         root_button_link.insert( button );
573 
574         button->no = 1;
575 
576         if ( lookback_sp[0] >= 0 ){
577             button->button_type = ButtonLink::SPRITE_BUTTON;
578             button->sprite_no = lookback_sp[0];
579             AnimationInfo &si = sprite_info[ button->sprite_no ];
580             si.visible = true;
581             button->select_rect = si.pos;
582             button->image_rect  = si.pos;
583         }
584         else{
585             button->button_type = ButtonLink::LOOKBACK_BUTTON;
586             button->select_rect = sentence_font_info.pos;
587             button->select_rect.h /= 3;
588             button->show_flag = 2;
589             button->anim[0] = &lookback_info[0];
590             button->anim[1] = &lookback_info[1];
591             button->image_rect.x = sentence_font_info.pos.x + sentence_font_info.pos.w - button->anim[0]->pos.w;
592             button->image_rect.y = sentence_font_info.pos.y;
593             button->image_rect.w = button->anim[0]->pos.w;
594             button->image_rect.h = button->anim[0]->pos.h;
595             button->anim[0]->pos.x = button->anim[1]->pos.x = button->image_rect.x;
596             button->anim[0]->pos.y = button->anim[1]->pos.y = button->image_rect.y;
597         }
598     }
599     else if (lookback_sp[0] >= 0){
600         sprite_info[ lookback_sp[0] ].visible = false;
601     }
602 
603     /* ---------------------------------------- */
604     /* Next button check */
605     if ( current_page->next != cached_page ){
606         ButtonLink *button = new ButtonLink();
607         root_button_link.insert( button );
608 
609         button->no = 2;
610 
611         if ( lookback_sp[1] >= 0 ){
612             button->button_type = ButtonLink::SPRITE_BUTTON;
613             button->sprite_no = lookback_sp[1];
614             AnimationInfo &si = sprite_info[ button->sprite_no ];
615             si.visible = true;
616             button->select_rect = si.pos;
617             button->image_rect  = si.pos;
618         }
619         else{
620             button->button_type = ButtonLink::LOOKBACK_BUTTON;
621             button->select_rect = sentence_font_info.pos;
622             button->select_rect.y += sentence_font_info.pos.h*2/3;
623             button->select_rect.h /= 3;
624             button->show_flag = 2;
625             button->anim[0] = &lookback_info[2];
626             button->anim[1] = &lookback_info[3];
627             button->image_rect.x = sentence_font_info.pos.x + sentence_font_info.pos.w - button->anim[0]->pos.w;
628             button->image_rect.y = sentence_font_info.pos.y + sentence_font_info.pos.h - button->anim[0]->pos.h;
629             button->image_rect.w = button->anim[0]->pos.w;
630             button->image_rect.h = button->anim[0]->pos.h;
631             button->anim[0]->pos.x = button->anim[1]->pos.x = button->image_rect.x;
632             button->anim[0]->pos.y = button->anim[1]->pos.y = button->image_rect.y;
633         }
634     }
635     else if (lookback_sp[1] >= 0){
636         sprite_info[ lookback_sp[1] ].visible = false;
637     }
638 }
639 
executeSystemLookback()640 void ONScripter::executeSystemLookback()
641 {
642     int i;
643     uchar3 color;
644 
645     current_font = &sentence_font;
646 
647     current_page = current_page->previous;
648     if ( current_page->text_count == 0 ){
649         if ( lookback_sp[0] >= 0 )
650             sprite_info[ lookback_sp[0] ].visible = false;
651         if ( lookback_sp[1] >= 0 )
652             sprite_info[ lookback_sp[1] ].visible = false;
653         leaveSystemCall();
654         return;
655     }
656 
657     while(1){
658         setupLookbackButton();
659         refreshMouseOverButton();
660 
661         dirty_rect.fill( screen_width, screen_height );
662         flush( refreshMode() & ~REFRESH_TEXT_MODE);
663 
664         for ( i=0 ; i<3 ; i++ ){
665             color[i] = sentence_font.color[i];
666             sentence_font.color[i] = lookback_color[i];
667         }
668         restoreTextBuffer(accumulation_surface);
669         for ( i=0 ; i<3 ; i++ ) sentence_font.color[i] = color[i];
670         flush( REFRESH_NONE_MODE );
671 
672         event_mode = WAIT_BUTTON_MODE;
673         waitEventSub(-1);
674 
675         if ( current_button_state.button == 0 ||
676              ( current_page == start_page &&
677                current_button_state.button == -2 ) ){
678             continue;
679         }
680         if ( current_button_state.button == -1 ||
681              ( current_button_state.button == -3 &&
682                current_page->next == cached_page ) ||
683              current_button_state.button <= -4 )
684         {
685             event_mode = IDLE_EVENT_MODE;
686             deleteButtonLink();
687             if ( lookback_sp[0] >= 0 )
688                 sprite_info[ lookback_sp[0] ].visible = false;
689             if ( lookback_sp[1] >= 0 )
690                 sprite_info[ lookback_sp[1] ].visible = false;
691             leaveSystemCall();
692             return;
693         }
694 
695         if ( current_button_state.button == 1 ||
696              current_button_state.button == -2 ){
697             current_page = current_page->previous;
698         }
699         else
700             current_page = current_page->next;
701     }
702 }
703 
buildDialog(bool yesno_flag,const char * mes1,const char * mes2)704 void ONScripter::buildDialog(bool yesno_flag, const char *mes1, const char *mes2)
705 {
706     SDL_PixelFormat *fmt = image_surface->format;
707     SDL_Surface *s = SDL_CreateRGBSurface( SDL_SWSURFACE, DIALOG_W, DIALOG_H,
708                                            fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask );
709 
710     SDL_Rect rect;
711     unsigned char col = 255;
712     SDL_FillRect(s, NULL, SDL_MapRGBA(s->format, col, col, col, 0xff));
713 
714     rect.x = 2; rect.y = DIALOG_HEADER;
715     rect.w = DIALOG_W-4; rect.h = DIALOG_H-rect.y-2;
716     col = 105;
717     SDL_FillRect(s, &rect, SDL_MapRGBA(s->format, col, col, col, 0xff));
718 
719     rect.x++; rect.y++; rect.w-=2; rect.h-=2;
720     col = 255;
721     SDL_FillRect(s, &rect, SDL_MapRGBA(s->format, col, col, col, 0xff));
722 
723     rect.h = DIALOG_FOOTER;
724     rect.y = DIALOG_H-3-rect.h;
725     col = 240;
726     SDL_FillRect(s, &rect, SDL_MapRGBA(s->format, col, col, col, 0xff));
727 
728     SDL_Surface *s2 = s;
729     if (screen_ratio2 != screen_ratio1){
730         s2 = SDL_CreateRGBSurface( SDL_SWSURFACE, DIALOG_W*screen_ratio1/screen_ratio2, DIALOG_H*screen_ratio1/screen_ratio2,
731                                    fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask );
732         resizeSurface(s, s2);
733         SDL_FreeSurface(s);
734     }
735 
736     uchar3 col3={0, 0, 0};
737     dialog_font.top_xy[0] = 7;
738     dialog_font.top_xy[1] = DIALOG_HEADER+5;
739     dialog_font.num_xy[0] = (DIALOG_W-7*2)/dialog_font.pitch_xy[0];
740     dialog_font.num_xy[1] = 3;
741     dialog_font.clear();
742     drawString( mes1, col3, &dialog_font, false, s2, NULL, NULL );
743 
744     dialog_font.top_xy[0] = 5;
745     dialog_font.top_xy[1] = (DIALOG_HEADER-dialog_font.font_size_xy[1])/2;
746     openFont(&dialog_font);
747     dialog_font.setLineArea(mes2);
748     dialog_font.clear();
749     drawString( mes2, col3, &dialog_font, false, s2, NULL, NULL );
750 
751     dialog_info.deleteSurface();
752     dialog_info.num_of_cells = 1;
753     dialog_info.setImage(s2, texture_format);
754 
755     dialog_info.pos.x = (screen_width  - dialog_info.pos.w)/2;
756     dialog_info.pos.y = (screen_height - dialog_info.pos.h)/2;
757 
758     // buttons
759     char* mes[2] = {NULL};
760     if (yesno_flag){
761         setStr(&mes[0], MESSAGE_YES, -1, true);
762         setStr(&mes[1], MESSAGE_NO, -1, true);
763     }
764     else{
765         setStr(&mes[0], MESSAGE_OK, -1, true);
766         setStr(&mes[1], MESSAGE_CANCEL, -1, true);
767     }
768 
769     for (int i=0 ; i<2 ; i++){
770         SDL_Surface *bs = SDL_CreateRGBSurface( SDL_SWSURFACE, DIALOG_BUTTON_W*2, DIALOG_BUTTON_H,
771                                                 fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask );
772 
773         for (int j=0 ; j<2 ; j++){
774             rect.x = DIALOG_BUTTON_W*j;
775             rect.y = 0;
776             rect.w = DIALOG_BUTTON_W; rect.h = DIALOG_BUTTON_H;
777 
778             col = 105;
779             SDL_FillRect(bs, &rect, SDL_MapRGBA(bs->format, col, col, col, 0xff));
780 
781             rect.w--; rect.h--;
782             col = 255;
783             SDL_FillRect(bs, &rect, SDL_MapRGBA(bs->format, col, col, col, 0xff));
784 
785             rect.x++; rect.y++; rect.w--; rect.h--;
786             col = 227;
787             SDL_FillRect(bs, &rect, SDL_MapRGBA(bs->format, col, col, col, 0xff));
788 
789             rect.x++; rect.y++; rect.w-=2; rect.h-=2;
790             col = 240;
791             if (j==1) col = 214;
792             SDL_FillRect(bs, &rect, SDL_MapRGBA(bs->format, col, col, col, 0xff));
793         }
794 
795         SDL_Surface *bs2 = bs;
796         if (screen_ratio2 != screen_ratio1){
797             bs2 = SDL_CreateRGBSurface( SDL_SWSURFACE, DIALOG_BUTTON_W*2*screen_ratio1/screen_ratio2, DIALOG_BUTTON_H*screen_ratio1/screen_ratio2,
798                                         fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask );
799             resizeSurface(bs, bs2);
800             SDL_FreeSurface(bs);
801         }
802 
803         for (int j=0 ; j<2 ; j++){
804             rect.x = DIALOG_BUTTON_W*j+2;
805             rect.y = 2;
806             rect.w = DIALOG_BUTTON_W-4; rect.h = DIALOG_BUTTON_H-4;
807 
808             dialog_font.top_xy[0] = rect.x+(rect.w-dialog_font.pitch_xy[0]*strlen(mes[i])/2)/2;
809             dialog_font.top_xy[1] = rect.y+(rect.h-dialog_font.font_size_xy[1])/2;
810             openFont(&dialog_font);
811             dialog_font.setLineArea(mes[i]);
812             dialog_font.clear();
813             drawString( mes[i], col3, &dialog_font, false, bs2, NULL, NULL );
814         }
815 
816         ButtonLink *btn = new ButtonLink();
817         btn->no = i+1;
818         btn->button_type = ButtonLink::TMP_SPRITE_BUTTON;
819         btn->anim[0] = new AnimationInfo();
820         btn->anim[0]->num_of_cells = 2;
821         btn->anim[0]->setImage(bs2, texture_format);
822         btn->show_flag = 1;
823 
824         btn->anim[0]->pos.x = dialog_info.pos.x + (DIALOG_W-3-(DIALOG_BUTTON_W+8)*(2-i))*screen_ratio1/screen_ratio2;
825         btn->anim[0]->pos.y = dialog_info.pos.y + (DIALOG_H-3-(DIALOG_FOOTER+DIALOG_BUTTON_H)/2)*screen_ratio1/screen_ratio2;
826 
827         btn->anim[0]->visible = true;
828         btn->select_rect = btn->image_rect = btn->anim[0]->pos;
829 
830         root_button_link.insert( btn );
831     }
832 
833     delete[] mes[0];
834     delete[] mes[1];
835 }
836