void ScriptHandler::readConfiguration()
{
    variable_range = 4096;
    global_variable_border = 200;

    char *buf = script_buffer;
    while ( buf < script_buffer + script_buffer_length ){
        if (*buf == ';') break;
        if (IS_TWO_BYTE(*buf)) buf++;
        buf++;
    }
    
    while ( ++buf >= script_buffer + script_buffer_length ) return;
    
    SKIP_SPACE(buf);
    bool config_flag = false;
    if (buf[0] == '$'){
        config_flag = true;
        buf++;
    }

    while (*buf && *buf != 0x0a){
        SKIP_SPACE(buf);
        if (!strncmp( buf, "mode", 4 )){
            buf += 4;
            if      (!strncmp( buf, "800", 3 )){
                screen_width  = 800;
                screen_height = 600;
                buf += 3;
            }
            else if (!strncmp( buf, "400", 3 )){
                screen_width  = 400;
                screen_height = 300;
                buf += 3;
            }
            else if (!strncmp( buf, "320", 3 )){
                screen_width  = 320;
                screen_height = 240;
                buf += 3;
            }
            else
                break;
        }
        else if (!strncmp( buf, "value", 5 ) ||
                 *buf == 'g' || *buf == 'G'){
            if (*buf == 'g' || *buf == 'G') buf++;
            else                            buf += 5;
            SKIP_SPACE(buf);
            global_variable_border = 0;
            while ( *buf >= '0' && *buf <= '9' )
                global_variable_border = global_variable_border*10 + *buf++ - '0';
        }
        else if (*buf == 'v' || *buf == 'V'){
            buf++;
            SKIP_SPACE(buf);
            variable_range = 0;
            while (*buf >= '0' && *buf <= '9')
                variable_range = variable_range*10 + *buf++ - '0';
        }
        else if (*buf == 's' || *buf == 'S'){
            buf++;
            if (!(*buf >= '0' && *buf <= '9')) break;
            screen_width = 0;
            while (*buf >= '0' && *buf <= '9')
                screen_width = screen_width*10 + *buf++ - '0';
            while (*buf == ',' || *buf == ' ' || *buf == '\t') buf++;
            screen_height = 0;
            while (*buf >= '0' && *buf <= '9')
                screen_height = screen_height*10 + *buf++ - '0';
        }
        else if (*buf == 'l' || *buf == 'L'){
            buf++;
            SKIP_SPACE(buf);
            while (*buf >= '0' && *buf <= '9') buf++;
        }
        else if (*buf != ',')
            break;

        SKIP_SPACE(buf);
        if (!config_flag && *buf != ',') break;
        if (*buf == ',') buf++;
    }
}
Exemple #2
0
// basic parser function
const char *ScriptHandler::readToken()
{
    current_script = next_script;
    wait_script = NULL;
    char *buf = current_script;
    end_status = END_NONE;
    current_variable.type = VAR_NONE;

    text_flag = false;

    SKIP_SPACE( buf );
    markAsKidoku( buf );

  readTokenTop:
    string_counter = 0;
    char ch = *buf;
    if (ch == ';'){ // comment
        addStringBuffer( ch );
        do{
            ch = *++buf;
            addStringBuffer( ch );
        } while ( ch != 0x0a && ch != '\0' );
    }
    else if (ch & 0x80 ||
             (ch >= '0' && ch <= '9') ||
             ch == '@' || ch == '\\' || ch == '/' ||
             ch == '%' || ch == '?' || ch == '$' ||
             ch == '[' || ch == '(' || ch == '<' ||
#ifndef ENABLE_1BYTE_CHAR
             ch == '`' ||
#endif             
             (!english_mode && ch == '>') ||
             ch == '!' || ch == '#' || ch == ',' || ch == '"'){ // text
        bool ignore_clickstr_flag = false;
        while(1){
            if ( IS_TWO_BYTE(ch) ){
                addStringBuffer( ch );
                ch = *++buf;
                if (ch == 0x0a || ch == '\0') break;
                addStringBuffer( ch );
                buf++;
                if (!wait_script && !ignore_clickstr_flag &&
                    checkClickstr(buf-2) > 0)
                    wait_script = buf;
                ignore_clickstr_flag = false;
            }
            else{
                ignore_clickstr_flag = false;
                if (ch == '%' || ch == '?'){
                    addIntVariable(&buf);
                    SKIP_SPACE(buf);
                }
                else if (ch == '$'){
                    addStrVariable(&buf);
                    SKIP_SPACE(buf);
                }
                else{
                    if (ch == 0x0a || ch == '\0') break;
                    addStringBuffer( ch );
                    buf++;
                    if (ch == '_') ignore_clickstr_flag = true;
                    if (!wait_script && ch == '@') wait_script = buf;
                }
            }
            ch = *buf;
        }

        text_flag = true;
    }
#ifdef ENABLE_1BYTE_CHAR
    else if (ch == '`'){
        ch = *++buf;
        while (ch != '`' && ch != 0x0a && ch !='\0'){
            if ( IS_TWO_BYTE(ch) ){
                addStringBuffer( ch );
                ch = *++buf;
            }
            addStringBuffer( ch );
            ch = *++buf;
        }
        if (ch == '`') buf++;
        
        text_flag = true;
        end_status |= END_1BYTE_CHAR;
    }
#endif
    else if (english_mode && ch == '>'){
        ch = *++buf;
        while (1){
            if (ch == 0x0a || ch =='\0') break;

            if (ch != '\t') 
                addStringBuffer( ch );
            ch = *++buf;
        }
        
        text_flag = true;
        end_status |= END_1BYTE_CHAR;
    }
    else if ((ch >= 'a' && ch <= 'z') || 
             (ch >= 'A' && ch <= 'Z') ||
             ch == '_'){ // command
        do{
            if (ch >= 'A' && ch <= 'Z') ch += 'a' - 'A';
            addStringBuffer( ch );
            ch = *++buf;
        }
        while((ch >= 'a' && ch <= 'z') || 
              (ch >= 'A' && ch <= 'Z') ||
              (ch >= '0' && ch <= '9') ||
              ch == '_');
    }
    else if (ch == '*'){ // label
        return readLabel();
    }
    else if (ch == '~' || ch == 0x0a || ch == ':'){
        addStringBuffer( ch );
        markAsKidoku( buf++ );
    }
    else if (ch != '\0'){
        fprintf(stderr, "readToken: skip unknown heading character %c (%x)\n", ch, ch);
        buf++;
        goto readTokenTop;
    }

    next_script = checkComma(buf);

    //printf("readToken [%s] len=%d [%c(%x)] %p\n", string_buffer, strlen(string_buffer), ch, ch, next_script);

    return string_buffer;
}
int ONScripterLabel::processText()
{
    //printf("textCommand %c %d %d %d\n", script_h.getStringBuffer()[ string_buffer_offset ], string_buffer_offset, event_mode, line_enter_status);
    char out_text[3]= {'\0', '\0', '\0'};

    if ( event_mode & (WAIT_INPUT_MODE | WAIT_SLEEP_MODE) ){
        draw_cursor_flag = false;
        if ( clickstr_state == CLICK_WAIT ){
            if (script_h.checkClickstr(script_h.getStringBuffer() + string_buffer_offset) != 1) string_buffer_offset++;
            string_buffer_offset++;
            clickstr_state = CLICK_NONE;
        }
        else if ( clickstr_state == CLICK_NEWPAGE ){
            event_mode = IDLE_EVENT_MODE;
            if (script_h.checkClickstr(script_h.getStringBuffer() + string_buffer_offset) != 1) string_buffer_offset++;
            string_buffer_offset++;
            newPage( true );
            clickstr_state = CLICK_NONE;
            return RET_CONTINUE | RET_NOREAD;
        }
        else if ( IS_TWO_BYTE(script_h.getStringBuffer()[ string_buffer_offset ]) ){
            string_buffer_offset += 2;
        }
        else if ( script_h.getStringBuffer()[ string_buffer_offset ] == '!' ){
            string_buffer_offset++;
            if ( script_h.getStringBuffer()[ string_buffer_offset ] == 'w' || script_h.getStringBuffer()[ string_buffer_offset ] == 'd' ){
                string_buffer_offset++;
                while ( script_h.getStringBuffer()[ string_buffer_offset ] >= '0' &&
                        script_h.getStringBuffer()[ string_buffer_offset ] <= '9' )
                    string_buffer_offset++;
                while (script_h.getStringBuffer()[ string_buffer_offset ] == ' ' ||
                       script_h.getStringBuffer()[ string_buffer_offset ] == '\t') string_buffer_offset++;
            }
        }
        else if ( script_h.getStringBuffer()[ string_buffer_offset + 1 ] &&
                  !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) ){
            string_buffer_offset += 2;
        }
        else
            string_buffer_offset++;

        event_mode = IDLE_EVENT_MODE;
    }

    
    if (script_h.getStringBuffer()[string_buffer_offset] == 0x0a ||
        script_h.getStringBuffer()[string_buffer_offset] == 0x00){
        indent_offset = 0; // redundant
        return RET_CONTINUE;
    }

    new_line_skip_flag = false;
    
    //printf("*** textCommand %d (%d,%d)\n", string_buffer_offset, sentence_font.xy[0], sentence_font.xy[1]);

    while( (!(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) &&
            script_h.getStringBuffer()[ string_buffer_offset ] == ' ') ||
           script_h.getStringBuffer()[ string_buffer_offset ] == '\t' ) string_buffer_offset ++;

    char ch = script_h.getStringBuffer()[string_buffer_offset];
    if ( IS_TWO_BYTE(ch) ){ // Shift jis
        /* ---------------------------------------- */
        /* Kinsoku process */
        if (IS_KINSOKU( script_h.getStringBuffer() + string_buffer_offset + 2)){
            int i = 2;
            while (!sentence_font.isEndOfLine(i) &&
                   IS_KINSOKU( script_h.getStringBuffer() + string_buffer_offset + i + 2)){
                i += 2;
            }

            if (sentence_font.isEndOfLine(i)){
                sentence_font.newLine();
                for (int i=0 ; i<indent_offset ; i++){
                    current_page->add(LOC_TWOBYTE_SYMBOL(' ')[0]);
                    current_page->add(LOC_TWOBYTE_SYMBOL(' ')[1]);
                    sentence_font.advanceCharInHankaku(2);
                }
            }
        }
        
        out_text[0] = script_h.getStringBuffer()[string_buffer_offset];
        out_text[1] = script_h.getStringBuffer()[string_buffer_offset+1];
        if ( clickstr_state == CLICK_IGNORE ){
            clickstr_state = CLICK_NONE;
        }
        else{
            if (script_h.checkClickstr(&script_h.getStringBuffer()[string_buffer_offset]) > 0){
                if (sentence_font.getRemainingLine() <= clickstr_line)
                    return clickNewPage( out_text );
                else
                    return clickWait( out_text );
            }
            else{
                clickstr_state = CLICK_NONE;
            }
        }
        
        if ( skip_flag || draw_one_page_flag || ctrl_pressed_status ){
            drawChar( out_text, &sentence_font, false, true, accumulation_surface, &text_info );
            num_chars_in_sentence++;
                
            string_buffer_offset += 2;
            return RET_CONTINUE | RET_NOREAD;
        }
        else{
            drawChar( out_text, &sentence_font, true, true, accumulation_surface, &text_info );
            num_chars_in_sentence++;
            event_mode = WAIT_SLEEP_MODE;
            if ( sentence_font.wait_time == -1 )
                advancePhase( default_text_speed[text_speed_no] );
            else
                advancePhase( sentence_font.wait_time );
            return RET_WAIT | RET_NOREAD;
        }
    }
    else if ( ch == '@' ){ // wait for click
        return clickWait( NULL );
    }
    else if ( ch == '\\' ){ // new page
        return clickNewPage( NULL );
    }
    else if ( ch == '_' ){ // Ignore following forced return
        clickstr_state = CLICK_IGNORE;
        string_buffer_offset++;
        return RET_CONTINUE | RET_NOREAD;
    }
    else if ( ch == '!' && !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) ){
        string_buffer_offset++;
        if ( script_h.getStringBuffer()[ string_buffer_offset ] == 's' ){
            string_buffer_offset++;
            if ( script_h.getStringBuffer()[ string_buffer_offset ] == 'd' ){
                sentence_font.wait_time = -1;
                string_buffer_offset++;
            }
            else{
                int t = 0;
                while( script_h.getStringBuffer()[ string_buffer_offset ] >= '0' &&
                       script_h.getStringBuffer()[ string_buffer_offset ] <= '9' ){
                    t = t*10 + script_h.getStringBuffer()[ string_buffer_offset ] - '0';
                    string_buffer_offset++;
                }
                sentence_font.wait_time = t;
                while (script_h.getStringBuffer()[ string_buffer_offset ] == ' ' ||
                       script_h.getStringBuffer()[ string_buffer_offset ] == '\t') string_buffer_offset++;
            }
        }
        else if ( script_h.getStringBuffer()[ string_buffer_offset ] == 'w' ||
                  script_h.getStringBuffer()[ string_buffer_offset ] == 'd' ){
            bool flag = false;
            if ( script_h.getStringBuffer()[ string_buffer_offset ] == 'd' ) flag = true;
            string_buffer_offset++;
            int tmp_string_buffer_offset = string_buffer_offset;
            int t = 0;
            while( script_h.getStringBuffer()[ string_buffer_offset ] >= '0' &&
                   script_h.getStringBuffer()[ string_buffer_offset ] <= '9' ){
                t = t*10 + script_h.getStringBuffer()[ string_buffer_offset ] - '0';
                string_buffer_offset++;
            }
            while (script_h.getStringBuffer()[ string_buffer_offset ] == ' ' ||
                   script_h.getStringBuffer()[ string_buffer_offset ] == '\t') string_buffer_offset++;
            if ( skip_flag || draw_one_page_flag || ctrl_pressed_status ){
                return RET_CONTINUE | RET_NOREAD;
            }
            else{
                event_mode = WAIT_SLEEP_MODE;
                if ( flag ) event_mode |= WAIT_INPUT_MODE;
                key_pressed_flag = false;
                startTimer( t );
                string_buffer_offset = tmp_string_buffer_offset - 2;
                return RET_WAIT | RET_NOREAD;
            }
        }
        return RET_CONTINUE | RET_NOREAD;
    }
    else if ( ch == '#' && !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) ){
        readColor( &sentence_font.color, script_h.getStringBuffer() + string_buffer_offset );
        readColor( &ruby_font.color, script_h.getStringBuffer() + string_buffer_offset );
        string_buffer_offset += 7;
        return RET_CONTINUE | RET_NOREAD;
    }
    else if ( ch == '(' && !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR)){
        current_page->add('(');
        startRuby( script_h.getStringBuffer() + string_buffer_offset + 1, sentence_font );
        
        string_buffer_offset++;
        return RET_CONTINUE | RET_NOREAD;
    }
    else if ( ch == '/' && !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) ){
        if ( ruby_struct.stage == RubyStruct::BODY ){
            current_page->add('/');
            sentence_font.addLineOffset(ruby_struct.margin);
            string_buffer_offset = ruby_struct.ruby_end - script_h.getStringBuffer();
            if (*ruby_struct.ruby_end == ')'){
                if ( skip_flag || draw_one_page_flag || ctrl_pressed_status )
                    endRuby(false, true, accumulation_surface, &text_info);
                else
                    endRuby(true, true, accumulation_surface, &text_info);
                current_page->add(')');
                string_buffer_offset++;
            }

            return RET_CONTINUE | RET_NOREAD;
        }
        else{ // skip new line
            new_line_skip_flag = true;
            string_buffer_offset++;
            if (script_h.getStringBuffer()[string_buffer_offset] != 0x0a)
                errorAndExit( "'new line' must follow '/'." );
            return RET_CONTINUE; // skip the following eol
        }
    }
    else if ( ch == ')' && !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR) &&
              ruby_struct.stage == RubyStruct::BODY ){
        current_page->add(')');
        string_buffer_offset++;
        ruby_struct.stage = RubyStruct::NONE;
        return RET_CONTINUE | RET_NOREAD;
    }
    else{
        out_text[0] = ch;
        
        if ( clickstr_state == CLICK_IGNORE ){
            clickstr_state = CLICK_NONE;
        }
        else{
            int matched_len = script_h.checkClickstr(script_h.getStringBuffer() + string_buffer_offset);

            if (matched_len > 0){
                if (matched_len == 2) out_text[1] = script_h.getStringBuffer()[ string_buffer_offset + 1 ];
                if (sentence_font.getRemainingLine() <= clickstr_line)
                    return clickNewPage( out_text );
                else
                    return clickWait( out_text );
            }
            else if (script_h.getStringBuffer()[ string_buffer_offset + 1 ] &&
                     script_h.checkClickstr(&script_h.getStringBuffer()[string_buffer_offset+1]) == 1 &&
                     script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR){
                if ( script_h.getStringBuffer()[ string_buffer_offset + 2 ] &&
                     script_h.checkClickstr(&script_h.getStringBuffer()[string_buffer_offset+2]) > 0){
                    clickstr_state = CLICK_NONE;
                }
                else if (script_h.getStringBuffer()[ string_buffer_offset + 1 ] == '@'){
                    return clickWait( out_text );
                }
                else if (script_h.getStringBuffer()[ string_buffer_offset + 1 ] == '\\'){
                    return clickNewPage( out_text );
                }
                else{
                    out_text[1] = script_h.getStringBuffer()[ string_buffer_offset + 1 ];
                    if (sentence_font.getRemainingLine() <= clickstr_line)
                        return clickNewPage( out_text );
                    else
                        return clickWait( out_text );
                }
            }
            else{
                clickstr_state = CLICK_NONE;
            }
        }
        
        bool flush_flag = true;
        if ( skip_flag || draw_one_page_flag || ctrl_pressed_status )
            flush_flag = false;
        if ( script_h.getStringBuffer()[ string_buffer_offset + 1 ] &&
             script_h.getStringBuffer()[ string_buffer_offset + 1 ] != 0x0a &&
             !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR)){
            out_text[1] = script_h.getStringBuffer()[ string_buffer_offset + 1 ];
            drawDoubleChars( out_text, &sentence_font, flush_flag, true, accumulation_surface, &text_info );
            num_chars_in_sentence++;
        }
        else if (script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR){
            drawDoubleChars( out_text, &sentence_font, flush_flag, true, accumulation_surface, &text_info );
            num_chars_in_sentence++;
        }
        
        if ( skip_flag || draw_one_page_flag || ctrl_pressed_status ){
            if ( script_h.getStringBuffer()[ string_buffer_offset + 1 ] &&
                 !(script_h.getEndStatus() & ScriptHandler::END_1BYTE_CHAR))
                string_buffer_offset++;
            string_buffer_offset++;
            return RET_CONTINUE | RET_NOREAD;
        }
        else{
            event_mode = WAIT_SLEEP_MODE;
            if ( sentence_font.wait_time == -1 )
                advancePhase( default_text_speed[text_speed_no] );
            else
                advancePhase( sentence_font.wait_time );
            return RET_WAIT | RET_NOREAD;
        }
    }

    return RET_NOMATCH;
}
int ONScripterLabel::textCommand()
{
    char *start_buf = script_h.getCurrent();

    if (pretextgosub_label && 
        (!pagetag_flag || page_enter_status == 0) &&
        (line_enter_status == 0 ||
         (line_enter_status == 1 &&
          (start_buf[0] == '[' ||
           zenkakko_flag && start_buf[0] == LOC_TWOBYTE_SYMBOL('[')[0] && start_buf[1] == LOC_TWOBYTE_SYMBOL('[')[1]))) ){
        if (start_buf[0] == '[')
            start_buf++;
        else if (zenkakko_flag && start_buf[0] == LOC_TWOBYTE_SYMBOL('[')[0] && start_buf[1] == LOC_TWOBYTE_SYMBOL('[')[1])
            start_buf += 2;
        else
            start_buf = NULL;
        
        char *end_buf = start_buf;
        while (end_buf && *end_buf){
            if (zenkakko_flag && end_buf[0] == LOC_TWOBYTE_SYMBOL(']')[0] && end_buf[1] == LOC_TWOBYTE_SYMBOL(']')[1]){
                script_h.setCurrent(end_buf+2);
                break;
            }
            else if (*end_buf == ']'){
                script_h.setCurrent(end_buf+1);
                break;
            }
            else if (IS_TWO_BYTE(end_buf[0]))
                end_buf+=2;
            else
                end_buf++;
        }

        if (current_page->tag) delete[] current_page->tag;
        if (current_tag.tag) delete[] current_tag.tag;
        if (start_buf){
            int len = end_buf - start_buf;
            current_page->tag = new char[len+1];
            memcpy(current_page->tag, start_buf, len);
            current_page->tag[len] = 0;

            current_tag.tag = new char[len+1];
            memcpy(current_tag.tag, current_page->tag, len+1);
        }
        else{
            current_page->tag = NULL;
            current_tag.tag = NULL;
        }

        gosubReal( pretextgosub_label, script_h.getCurrent() );
        line_enter_status = 1;

        return RET_CONTINUE;
    }

    int ret = enterTextDisplayMode();
    if ( ret != RET_NOMATCH ) return ret;

    line_enter_status = 2;
    if (pagetag_flag) page_enter_status = 1;

    ret = processText();
    if (ret == RET_CONTINUE){
        indent_offset = 0;
    }
    
    return ret;
}
void ONScripterLabel::drawString( const char *str, uchar3 color, FontInfo *info, bool flush_flag, SDL_Surface *surface, SDL_Rect *rect, AnimationInfo *cache_info )
{
    int i;

    int start_xy[2];
    start_xy[0] = info->xy[0];
    start_xy[1] = info->xy[1];

    /* ---------------------------------------- */
    /* Draw selected characters */
    uchar3 org_color;
    for ( i=0 ; i<3 ; i++ ) org_color[i] = info->color[i];
    for ( i=0 ; i<3 ; i++ ) info->color[i] = color[i];

    bool skip_whitespace_flag = true;
    char text[3] = { '\0', '\0', '\0' };
    while( *str ){
        while (*str == ' ' && skip_whitespace_flag) str++;

#ifdef ENABLE_1BYTE_CHAR
        if ( *str == '`' ){
            str++;
            skip_whitespace_flag = false;
            continue;
        }
#endif            

#ifndef FORCE_1BYTE_CHAR            
        if (cache_info && !cache_info->is_tight_region){
            if (*str == '('){
                startRuby(str+1, *info);
                str++;
                continue;
            }
            else if (*str == '/' && ruby_struct.stage == RubyStruct::BODY ){
                info->addLineOffset(ruby_struct.margin);
                str = ruby_struct.ruby_end;
                if (*ruby_struct.ruby_end == ')'){
                    endRuby(false, false, NULL, cache_info);
                    str++;
                }
                continue;
            }
            else if (*str == ')' && ruby_struct.stage == RubyStruct::BODY ){
                ruby_struct.stage = RubyStruct::NONE;
                str++;
                continue;
            }
        }
#endif

        if ( IS_TWO_BYTE(*str) ){
            /* Kinsoku process */
            if (info->isEndOfLine(2) && IS_KINSOKU( str+2 )){
                info->newLine();
                for (int i=0 ; i<indent_offset ; i++){
                    sentence_font.advanceCharInHankaku(2);
                }
            }
            text[0] = *str++;
            text[1] = *str++;
            drawChar( text, info, false, false, surface, cache_info );
        }
        else if (*str == 0x0a || *str == '\\' && info->is_newline_accepted){
            info->newLine();
            str++;
        }
        else{
            text[0] = *str++;
            text[1] = '\0';
            drawChar( text, info, false, false, surface, cache_info );
            if (*str && *str != 0x0a){
                text[0] = *str++;
                drawChar( text, info, false, false, surface, cache_info );
            }
        }
    }
    for ( i=0 ; i<3 ; i++ ) info->color[i] = org_color[i];

    /* ---------------------------------------- */
    /* Calculate the area of selection */
    SDL_Rect clipped_rect = info->calcUpdatedArea(start_xy, screen_ratio1, screen_ratio2);
    info->addShadeArea(clipped_rect, shade_distance);
    
    if ( flush_flag )
        flush( refresh_shadow_text_mode, &clipped_rect );
    
    if ( rect ) *rect = clipped_rect;
}
void ONScripterLabel::drawChar( char* text, FontInfo *info, bool flush_flag, bool lookback_flag, SDL_Surface *surface, AnimationInfo *cache_info, SDL_Rect *clip )
{
    //printf("draw %x-%x[%s] %d, %d\n", text[0], text[1], text, info->xy[0], info->xy[1] );
    
    if ( info->ttf_font == NULL ){
        if ( info->openFont( font_file, screen_ratio1, screen_ratio2 ) == NULL ){
            fprintf( stderr, "can't open font file: %s\n", font_file );
            quit();
            exit(-1);
        }
    }
#if defined(PSP)
    else
        info->openFont( font_file, screen_ratio1, screen_ratio2 );
#endif

    if ( info->isEndOfLine() ){
        info->newLine();
        for (int i=0 ; i<indent_offset ; i++)
            sentence_font.advanceCharInHankaku(2);

        if ( lookback_flag ){
            for (int i=0 ; i<indent_offset ; i++){
                current_page->add(LOC_TWOBYTE_SYMBOL(' ')[0]);
                current_page->add(LOC_TWOBYTE_SYMBOL(' ')[1]);
            }
        }
    }

    int xy[2];
    xy[0] = info->x() * screen_ratio1 / screen_ratio2;
    xy[1] = info->y() * screen_ratio1 / screen_ratio2;
    
    SDL_Color color;
    SDL_Rect dst_rect;
    if ( info->is_shadow ){
        color.r = color.g = color.b = 0;
        drawGlyph(surface, info, color, text, xy, true, cache_info, clip, dst_rect);
    }
    color.r = info->color[0];
    color.g = info->color[1];
    color.b = info->color[2];
    drawGlyph( surface, info, color, text, xy, false, cache_info, clip, dst_rect );

    if ( surface == accumulation_surface &&
         !flush_flag &&
         (!clip || AnimationInfo::doClipping( &dst_rect, clip ) == 0) ){
        dirty_rect.add( dst_rect );
    }
    else if ( flush_flag ){
        info->addShadeArea(dst_rect, shade_distance);
        flushDirect( dst_rect, REFRESH_NONE_MODE );
    }

    /* ---------------------------------------- */
    /* Update text buffer */
    if (IS_TWO_BYTE(text[0]))
        info->advanceCharInHankaku(2);
    else
        info->advanceCharInHankaku(1);
    
    if ( lookback_flag ){
        current_page->add( text[0] );
        if (IS_TWO_BYTE(text[0]) && text[1])
            current_page->add( text[1] );
    }
}