uint16_t get_variable(uint8_t variable_number, bool keep_stack_index) { uint16_t result; if (variable_number == 0) { if (stack_words_from_active_routine == 0) { if (bool_equal(skip_active_routines_stack_check_warning, false)) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_NOT_ENOUGH_STACK_WORDS_FROM_LOCAL_ROUTINE_ON_STACK, -1); else return 0; } if (bool_equal(keep_stack_index, true)) result = z_stack_peek_word(); else { result = z_stack_pull_word(); stack_words_from_active_routine--; } return result; } else if (variable_number < 0x10) { if (variable_number > number_of_locals_active) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_TRYING_TO_STORE_VARIABLE_L_P0D_BUT_ONLY_P1D_VARIABLES_ACTIVE, -1, (long int)variable_number-1, (long int)number_of_locals_active); variable_number--; result = local_variable_storage_index[variable_number]; TRACE_LOG("Reading %x from L0%x.\n", result, variable_number); return result; } else { variable_number -= 0x10; result = load_word(active_z_story->global_variables+(variable_number*2)); TRACE_LOG("Reading %x from global variable G%02x.\n", result, variable_number); return result; } }
void set_variable(uint8_t variable_number, uint16_t data, bool keep_stack_index) { if (variable_number == 0) { if (stack_words_from_active_routine == MAXIMUM_STACK_ENTRIES_PER_ROUTINE) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_MAXIMUM_NUMBER_OF_STACK_ENTRIES_PER_ROUTINE_P0D_EXCEEDED, -1, (long int)MAXIMUM_STACK_ENTRIES_PER_ROUTINE); if (bool_equal(keep_stack_index, true)) { z_stack_pull_word(); z_stack_push_word(data); } else { z_stack_push_word(data); stack_words_from_active_routine++; } } else if (variable_number < 0x10) { if (variable_number > number_of_locals_active) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_TRYING_TO_STORE_VARIABLE_L_P0D_BUT_ONLY_P1D_VARIABLES_ACTIVE, -1, (long int)variable_number-1, (long int)number_of_locals_active); variable_number--; TRACE_LOG("Storing %x in L0%x.\n", data, variable_number); local_variable_storage_index[variable_number] = data; } else { variable_number -= 0x10; TRACE_LOG("Setting global variable G%02x to %x.\n", variable_number, data); store_word( /*@-nullderef@*/ active_z_story->global_variables /*@-nullderef@*/ +(variable_number*2), data); } }
true_type_factory *create_true_type_factory(char *font_search_path) { true_type_factory *result; int ft_error; result = (true_type_factory*)fizmo_malloc(sizeof(true_type_factory)); if ((ft_error = FT_Init_FreeType(&result->ftlibrary))) { i18n_translate_and_exit( libpixelif_module_name, i18n_libpixelif_FUNCTION_CALL_P0S_ABORTED_DUE_TO_ERROR, -1, "FT_Init_FreeType"); } if ((ft_error = FT_Library_SetLcdFilter( result->ftlibrary, FT_LCD_FILTER_DEFAULT))) { result->render_mode = FT_RENDER_MODE_NORMAL; } else { result->render_mode = FT_RENDER_MODE_LCD; } result->font_search_path = strdup(font_search_path); TRACE_LOG("factory path: %s\n", result->font_search_path); return result; }
FILE* glkint_get_stdio_stream(z_file *fileref) { if (fileref->implementation == FILE_IMPLEMENTATION_STDIO) return z_filesys_interface_c.get_stdio_stream(fileref); else { i18n_translate_and_exit( libglkif_module_name, i18n_libglkif_NOT_YET_IMPLEMENTED_IN_LIBGLKIF, -0x010d); return NULL; } }
time_t glkint_get_last_file_mod_timestamp(z_file *fileref) { if (fileref->implementation == FILE_IMPLEMENTATION_STDIO) return z_filesys_interface_c.get_last_file_mod_timestamp(fileref); else { i18n_translate_and_exit( libglkif_module_name, i18n_libglkif_NOT_YET_IMPLEMENTED_IN_LIBGLKIF, -0x010d); return -1; } }
int glkint_unreadchar(int c, z_file *fileref) { if (fileref->implementation == FILE_IMPLEMENTATION_STDIO) return z_filesys_interface_c.unreadchar(c, fileref); else { i18n_translate_and_exit( libglkif_module_name, i18n_libglkif_NOT_YET_IMPLEMENTED_IN_LIBGLKIF, -0x010d); return -1; } }
int glkint_vfilescanf(z_file *fileref, char *format, va_list ap) { if (fileref->implementation == FILE_IMPLEMENTATION_STDIO) return z_filesys_interface_c.vfilescanf(fileref, format, ap); else { i18n_translate_and_exit( libglkif_module_name, i18n_libglkif_NOT_YET_IMPLEMENTED_IN_LIBGLKIF, -0x010d); return -1; } }
void opcode_pop(void) { TRACE_LOG("Opcode: POP.\n"); if (stack_words_from_active_routine == 0) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_NOT_ENOUGH_STACK_WORDS_FROM_LOCAL_ROUTINE_ON_STACK, -1); (void)z_stack_pull_word(); stack_words_from_active_routine--; }
void opcode_push(void) { TRACE_LOG("Opcode: PUSH.\n"); TRACE_LOG("Pushing %x to stack.\n", op[0]); if (stack_words_from_active_routine == MAXIMUM_STACK_ENTRIES_PER_ROUTINE) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_MAXIMUM_NUMBER_OF_STACK_ENTRIES_PER_ROUTINE_P0D_EXCEEDED, -1, (long int)MAXIMUM_STACK_ENTRIES_PER_ROUTINE); z_stack_push_word(op[0]); stack_words_from_active_routine++; }
void opcode_pull(void) { uint16_t value = 0; uint16_t spare_slots; uint8_t *user_stack; TRACE_LOG("Opcode: PULL.\n"); if (ver == 6) (void)read_z_result_variable(); if ( (ver != 6) || (number_of_operands < 1) ) { if ( (stack_words_from_active_routine == 0) && (bool_equal(skip_active_routines_stack_check_warning, false)) ) { i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_NOT_ENOUGH_STACK_WORDS_FROM_LOCAL_ROUTINE_ON_STACK, -1); } else { TRACE_LOG("Pulling to variable %x.\n", op[0]); value = z_stack_pull_word(); stack_words_from_active_routine--; } } else { user_stack = z_mem + (uint16_t)op[0]; spare_slots = load_word(user_stack); spare_slots++; value = load_word(user_stack + spare_slots); store_word(user_stack, spare_slots); } if (ver == 6) set_variable(z_res_var, value, true); else set_variable(op[0], value, true); }
void turn_on_trace(void) { if (stream_t != NULL) { TRACE_LOG("Tracelog already active.\n"); return; } stream_t = fsi->openfile( DEFAULT_TRACE_FILE_NAME, FILETYPE_TEXT, FILEACCESS_WRITE); if (stream_t == NULL) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_COULD_NOT_OPEN_TRACE_FILE_P0S, -1, DEFAULT_TRACE_FILE_NAME); }
static void flush_input_buffer(WORDWRAP *wrapper, bool force_flush) { z_ucs *index = NULL, *ptr, *hyphenated_word, *last_hyphen, *word_start; z_ucs *word_end, *input = wrapper->input_buffer, *first_space_or_newline; z_ucs buf=0, buf2; // buf initialized to avoid compiler warning z_ucs buf3 = '-'; // buf3 initialized to avoid compiler warning long len, chars_sent = 0; int metadata_offset = 0, i, chars_left_on_line; struct wordwrap_metadata *metadata_entry; int current_line_length = wrapper->line_length - wrapper->chars_already_on_line; input[wrapper->input_index] = 0; TRACE_LOG("input-index: %ld\n", wrapper->input_index); TRACE_LOG("metadata stored: %d.\n", wrapper->metadata_index); for (;;) { TRACE_LOG("Processing flush for line-length %d, already in line: %d.\n", current_line_length, wrapper->chars_already_on_line); if (*input != 0) { TRACE_LOG("flush wordwrap-buffer at %p: \"", input); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); } if ((index = z_ucs_chr(input, Z_UCS_NEWLINE)) != NULL) { len = index - input; } else { len = z_ucs_len(input); TRACE_LOG("len:%ld, force:%d.\n", len, force_flush); if (len == 0) { if (force_flush == true) { // Force flush metadata behind end of output. while (metadata_offset < wrapper->metadata_index) { TRACE_LOG("flush post-output metadata at: %ld.\n", wrapper->metadata[metadata_offset].output_index); metadata_entry = &wrapper->metadata[metadata_offset]; TRACE_LOG("Output metadata prm %d.\n", metadata_entry->int_parameter); metadata_entry->metadata_output_function( metadata_entry->ptr_parameter, metadata_entry->int_parameter); metadata_offset++; } } wrapper->chars_already_on_line = 0; break; } if (len <= current_line_length) { if (force_flush == false) { // We're quitting on len == current_line_length since we can only // determine wether we can break cleanly is if a space follows // immediately after the last char. wrapper->chars_already_on_line = 0; break; } wrapper->chars_already_on_line = len; } // FIXME: Add break in case hyph is enabled and a word longer than // the line is not terminated with a space. } TRACE_LOG("wordwrap-flush-len: %ld.\n", len); if (len <= current_line_length) { // Line fits on screen. TRACE_LOG("Line fits on screen.\n"); if (index != NULL) { index++; len++; buf = *index; *index = 0; } chars_sent += len; output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); if (index != NULL) *index = buf; else { //wrapper->input_index = 0; break; } } else if (wrapper->enable_hyphenation == true) { // Line does not fit on screen and hyphenation is enabled, so we'll // try to hyphenate. // In this section we'll set "index" to the point where the line // should be split and "last_hyphen" to the word position where // hyphenation should take place -- if possible, otherwise NULL. // In case hyphenation is active we're looking at the word overruning // the line end. It has to be completed in order to make hyphenation // work. TRACE_LOG("to wrap/hyphenate (force:%d) to length %d : \"", force_flush, current_line_length); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); // Get the char at the current line end. if (input[current_line_length] == Z_UCS_SPACE) { // Fine, we can wrap right here at this space. index = input + current_line_length; last_hyphen = NULL; } else { if ( ((first_space_or_newline = z_ucs_chrs( input + current_line_length, word_split_chars)) == NULL) && (force_flush == false) ) { // In case we can't find any space the word may not have been // completely written to the buffer. Wait until we've got more // input. TRACE_LOG("No word end found.\n"); break; } else { if (first_space_or_newline == NULL) { word_end = input + current_line_length; while (*(word_end + 1) != 0) { word_end++; } } else { // We've found a space behind the overrunning word so we're // able to correctly split the current line. word_end = first_space_or_newline - 1; } // Before hyphentation, check for dashes inside the last word. // Example: "first-class car", where the word end we've now // found is between "first-class" and "car". word_start = word_end - 1; while (word_start > input) { TRACE_LOG("examining word end: \"%c\".\n", *word_start); if (*word_start == Z_UCS_MINUS) { if (input + current_line_length > word_start) { // Found a dash to break on word_start++; break; } } else if (*word_start == Z_UCS_SPACE) { // We just passed the word-start. word_start++; break; } word_start--; } // FIXME: Do we need a space left from here? TRACE_LOG("word-start: %c\n", *word_start); TRACE_LOG("word-end: %c\n", *word_end); last_hyphen = NULL; if (word_end >= input + current_line_length) { // We only have to hyphenate in case the line is still too long. buf = *(word_end+ 1); *(word_end+ 1) = 0; TRACE_LOG("buffer terminated at word end: \""); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); index = word_start; if ((hyphenated_word = hyphenate(index)) == NULL) { TRACE_LOG("Error hyphenating.\n"); i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_UNKNOWN_ERROR_CASE, -1); } TRACE_LOG("hyphenated word: \""); TRACE_LOG_Z_UCS(hyphenated_word); TRACE_LOG("\".\n"); *(word_end + 1) = buf; chars_left_on_line = current_line_length - (index - input); TRACE_LOG("chars left on line: %d\n", chars_left_on_line); ptr = hyphenated_word; while ((chars_left_on_line > 0) && (*ptr != 0)) { TRACE_LOG("Testing %c for soft-hyphen.\n", *ptr); if (*ptr == Z_UCS_SOFT_HYPEN) { last_hyphen = input + (current_line_length - chars_left_on_line); } else { chars_left_on_line--; } ptr++; } free(hyphenated_word); if (last_hyphen != NULL) { TRACE_LOG("Last hyphen at %ld.\n", last_hyphen - input); buf3 = *last_hyphen; *last_hyphen = '-'; index = last_hyphen + 1; } else { // We couldn't find a possibility to hyphenate the last // word in the line. TRACE_LOG("No hyphen found.\n"); if (index > input) { if (*(index-1) != Z_UCS_MINUS) { // In case the char before the last word is not a dash, // we'll skip the space before this word by moving back // the index by one. index--; } } else { // In case the current word is so long that it doesn't fit // on the line -- this may be the case if we're supposed // to display ASCII art and the linesize is to short -- we // have to advance the index to the line end. TRACE_LOG("This is the first word in the line, hard break.\n"); index = input + current_line_length; } } } else { index = word_end; last_hyphen = NULL; } } } // Output everything before *index and a newline after. TRACE_LOG("Input (%p, %p): \"", input, index); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); buf2 = *index; *index = Z_UCS_NEWLINE; buf = *(index + 1); *(index + 1) = 0; output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); *(index + 1) = buf; *index = buf2; if (last_hyphen != NULL) { *last_hyphen = buf3; index--; } // if (*index == Z_UCS_SPACE) { while (*index == Z_UCS_SPACE) { index++; } len = index - input; chars_sent += len; TRACE_LOG("Processed %ld chars in hyphenated wordwrap.\n", len); } else { // Line won't fit completely and hyphenation is disabled. // Find the end of the last word or dash in it before the end of line // (opposed to looking at the word overring the line end in case of // hyphentation). TRACE_LOG("linelength: %d.\n", current_line_length); ptr = input + current_line_length - 1; while (ptr > input) { if (*ptr == Z_UCS_SPACE) { index = ptr; break; } else if (*ptr == Z_UCS_MINUS) { index = ptr + 1; break; } ptr--; } if (ptr == input) { // We couldn't find any space or dash in the whole line, so we're // forced to flush everything. index = input + current_line_length; } buf = *index; *index = Z_UCS_NEWLINE; buf2 = *(index+1); *(index+1) = 0; TRACE_LOG("Output from %p.\n", input); output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); *(index+1) = buf2; *index = buf; //if (*index == Z_UCS_SPACE) { while (*index == Z_UCS_SPACE) { index++; } len = index - input; chars_sent += len; } TRACE_LOG("len-after: %ld.\n", len); if (index != NULL) { TRACE_LOG("index: \""); TRACE_LOG_Z_UCS(index); TRACE_LOG("\".\n"); } input += len; current_line_length = wrapper->line_length; } TRACE_LOG("chars sent: %ld, moving: %ld.\n", chars_sent, wrapper->input_index - chars_sent + 1); TRACE_LOG("chars_already_on_line: %d\n", wrapper->chars_already_on_line); index = z_ucs_rchr(wrapper->input_buffer, Z_UCS_NEWLINE); memmove( wrapper->input_buffer, input, sizeof(z_ucs) * (wrapper->input_index - chars_sent + 1)); wrapper->input_index -= chars_sent; if (metadata_offset > 0) { memmove( wrapper->metadata, wrapper->metadata + metadata_offset, sizeof(struct wordwrap_metadata) * (wrapper->metadata_index - metadata_offset)); wrapper->metadata_index -= metadata_offset; TRACE_LOG("metadata stored: %d.\n", wrapper->metadata_index); } for (i=0; i<wrapper->metadata_index; i++) wrapper->metadata[i].output_index -= chars_sent; }
static void flush_input_buffer(WORDWRAP *wrapper, bool force_flush) { z_ucs *index = NULL, *ptr, *hyphenated_word, *last_hyphen, *word_start; z_ucs *word_end_without_split_chars, *word_end_with_split_chars; z_ucs buf=0, buf2; // buf initialized to avoid compiler warning z_ucs buf3 = '-'; // buf3 initialized to avoid compiler warning long len, chars_sent = 0; z_ucs *input = wrapper->input_buffer; bool minus_found; int metadata_offset = 0; int i, chars_left_on_line; //int hyphen_offset; struct wordwrap_metadata *metadata_entry; input[wrapper->input_index] = 0; TRACE_LOG("input-index: %ld\n", wrapper->input_index); TRACE_LOG("metadata stored: %d.\n", wrapper->metadata_index); for (;;) { TRACE_LOG("Processing flush.\n"); if (*input != 0) { TRACE_LOG("flush wordwrap-buffer: \""); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); } if ((index = z_ucs_chr(input, Z_UCS_NEWLINE)) != NULL) len = index - input; else { len = z_ucs_len(input); TRACE_LOG("len:%ld, force:%d.\n", len, force_flush); if (len == 0) { if (force_flush == true) { // Force flush metadata behind end of output. while (metadata_offset < wrapper->metadata_index) { TRACE_LOG("flush post-output metadata at: %ld.\n", wrapper->metadata[metadata_offset].output_index); metadata_entry = &wrapper->metadata[metadata_offset]; TRACE_LOG("Output metadata prm %d.\n", metadata_entry->int_parameter); metadata_entry->metadata_output_function( metadata_entry->ptr_parameter, metadata_entry->int_parameter); metadata_offset++; } } break; } if ( (len <= wrapper->line_length) && (force_flush == false) ) // We're quitting on len == wrapper->line_length since we can only // determine wether we can break cleanly is if a space follows // immediately after the last char. break; // FIXME: Add break in case hyph is enabled and a word longer than // the line is not terminated with a space. } TRACE_LOG("wordwrap-flush-len: %ld.\n", len); if (len <= wrapper->line_length) { // Line fits on screen. TRACE_LOG("Line fits on screen.\n"); if (index != NULL) { index++; len++; buf = *index; *index = 0; } chars_sent += len; output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); if (index != NULL) *index = buf; else { //wrapper->input_index = 0; break; } } else if (wrapper->enable_hyphenation == true) { TRACE_LOG("to wrap/hyphenate (force:%d): \"", force_flush); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); if ((word_end_without_split_chars = z_ucs_chrs( input + wrapper->line_length, word_split_chars)) == NULL) { if (force_flush == true) word_end_without_split_chars = input + len; else { TRACE_LOG("No word end found.\n"); break; } } // We'll remeber the current position of the word-split-char we've // just found in "word_end_without_split_chars" and advance this pointer // until we won't find any more word-split-chars. Thus, if we've just // found the start dot of an ellipsis "..." we'll end up with the // position of the last dot. word_end_with_split_chars = word_end_without_split_chars; while ((ptr = z_ucs_chr( word_split_chars, *word_end_with_split_chars)) != NULL) word_end_with_split_chars++; // Now we've stored the end of the word in "word_end_without_split_chars". // We've now found a word boundary. This char may however not be part // of the actual last word (we might have hit a minus representing // a n- or m-dash--like this--or an elipsis like "..."). So we'll // rewind further if necessary. TRACE_LOG("examining split end:\"%c\".\n", *word_end_without_split_chars); //while (word_end_without_split_chars - 1 > input + wrapper->line_length) while (word_end_without_split_chars > input) { TRACE_LOG("Checking for split-char: %c/%d.\n", *word_end_without_split_chars, *word_end_without_split_chars); if (z_ucs_chr( word_split_chars, *(word_end_without_split_chars - 1)) == NULL) break; word_end_without_split_chars--; } if ( (word_end_without_split_chars != word_end_with_split_chars) && (*word_end_without_split_chars == Z_UCS_SPACE) && (word_end_without_split_chars < input + wrapper->line_length) ) { // In this case we have skipped a number of stand-alone word-split- // chars (like the elipsis in "Powers -- these") and are now so far // back that we can split right at the space before these chars. index = word_end_without_split_chars; last_hyphen = NULL; } else { word_start = NULL; // In case we've now found a word end, check for dashes before it. // Example: "first-class car", where the word end we've now found is // between "first-class" and "car". word_start = word_end_without_split_chars - 1; while (word_start > input) { TRACE_LOG("examining word end: \"%c\".\n", *word_start); if (*word_start == Z_UCS_MINUS) { if (input + wrapper->line_length > word_start) { // Found a dash to break on word_start++; break; } } else if ((ptr = z_ucs_chr(word_split_chars, *word_start)) != NULL) { // In case we've found a non-dash separator, we've found the // start of the word. word_start++; break; } word_start--; } // FIXME: Do we need a space left from here? TRACE_LOG("word-start: %c\n", *word_start); TRACE_LOG("%p / %p\n", word_end_without_split_chars, word_end_with_split_chars); TRACE_LOG("%c / %c\n", *word_end_without_split_chars, *word_end_with_split_chars); TRACE_LOG("%p / %p\n", word_end_without_split_chars, input + wrapper->line_length); last_hyphen = NULL; if (word_end_with_split_chars > input + wrapper->line_length) { // We only have to hyphenate in case the line is still too long. buf = *word_end_without_split_chars; *word_end_without_split_chars = 0; TRACE_LOG("buffer terminated at word end: \""); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); index = word_start; if ((hyphenated_word = hyphenate(index)) == NULL) { TRACE_LOG("Error hyphenating.\n"); i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_UNKNOWN_ERROR_CASE, -1); } *word_end_without_split_chars = buf; chars_left_on_line = wrapper->line_length - (index - input); TRACE_LOG("chars left on line: %d\n", chars_left_on_line); //hyphen_offset = index - input; ptr = hyphenated_word; while (chars_left_on_line > 0) { TRACE_LOG("Testing %c for hyphen.\n", *ptr); if (*ptr == Z_UCS_SOFT_HYPEN) last_hyphen = input + (wrapper->line_length - chars_left_on_line); else chars_left_on_line--; ptr++; } free(hyphenated_word); if (last_hyphen != NULL) { TRACE_LOG("Last hyphen at %ld.\n", last_hyphen - input); buf3 = *last_hyphen; *last_hyphen = '-'; index = last_hyphen + 1; } else if ( (word_start != input) && (*(word_start-1) != Z_UCS_MINUS) ) { TRACE_LOG("No hyphen found.\n"); index--; } } else { index = word_end_with_split_chars; } } // Output everything before *index and a newline after. buf2 = *index; *index = Z_UCS_NEWLINE; buf = *(index + 1); *(index + 1) = 0; output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); *(index + 1) = buf; *index = buf2; if (last_hyphen != NULL) { *last_hyphen = buf3; index--; } if (*index == Z_UCS_SPACE) index++; len = index - input; chars_sent += len; TRACE_LOG("Processed %ld chars in hyphenated wordwrap.\n", len); } else { // Line won't fit completely. Find the end of the last word. TRACE_LOG("linelength: %d.\n", wrapper->line_length); //word_end_with_split_chars = NULL; ptr = input + wrapper->line_length; if (*ptr == Z_UCS_SPACE) ptr++; TRACE_LOG("%p/%p/%c\n", input, ptr, *ptr); buf = *ptr; *ptr = 0; TRACE_LOG("examine buffer: \""); TRACE_LOG_Z_UCS(input); TRACE_LOG("\".\n"); index = z_ucs_rchrs(input, word_split_chars); if (*index == Z_UCS_MINUS) { minus_found = true; index++; } else minus_found = false; TRACE_LOG("Found word-split at %p from %p.\n", index, input); *ptr = buf; if (index == NULL) index = input + wrapper->line_length; buf = *index; *index = Z_UCS_NEWLINE; buf2 = *(index+1); *(index+1) = 0; TRACE_LOG("Output from %p.\n", input); output_buffer(wrapper, input, &metadata_offset); if (wrapper->left_side_padding != 0) wrapper->wrapped_text_output_destination( wrapper->padding_buffer, wrapper->destination_parameter); *(index+1) = buf2; *index = buf; if (minus_found == false) index++; len = index - input; chars_sent += len; } TRACE_LOG("len-after: %ld.\n", len); if (index != NULL) { TRACE_LOG("index: \""); TRACE_LOG_Z_UCS(index); TRACE_LOG("\".\n"); } input += len; } TRACE_LOG("chars sent: %ld, moving: %ld.\n", chars_sent, wrapper->input_index - chars_sent + 1); memmove( wrapper->input_buffer, input, sizeof(z_ucs) * (wrapper->input_index - chars_sent + 1)); wrapper->input_index -= chars_sent; if (metadata_offset > 0) { memmove( wrapper->metadata, wrapper->metadata + metadata_offset, sizeof(struct wordwrap_metadata) * (wrapper->metadata_index - metadata_offset)); wrapper->metadata_index -= metadata_offset; TRACE_LOG("metadata stored: %d.\n", wrapper->metadata_index); } for (i=0; i<wrapper->metadata_index; i++) wrapper->metadata[i].output_index -= chars_sent; }
static z_blorb_map *fizmo_blorb_init(z_file *blorb_file) { z_blorb_map *result_wrapper; fizmo_blorb_map *result; fizmo_blorb *blorb; int resource_chunk_size; char buf[5]; int nof_resources, nof_loops, blorb_index, resource_number; if (find_chunk("RIdx", blorb_file) == -1) { fsi->closefile(blorb_file); return NULL; } if (read_chunk_length(blorb_file) == -1) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D, -0x0101, "read_chunk_length", errno); result = fizmo_malloc(sizeof(fizmo_blorb_map)); result->blorb_file = blorb_file; result_wrapper = fizmo_malloc(sizeof(z_blorb_map)); result_wrapper->blorb_map_implementation = result; resource_chunk_size = get_last_chunk_length(); nof_resources = (resource_chunk_size - 4) / 12; // Skip next number of resources. if ((fsi->setfilepos(result->blorb_file, 4, SEEK_CUR)) != 0) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D, -0x0101, "setfilepos", errno); TRACE_LOG("Number of resources in blorb file: %d.\n", nof_resources); // Count number of images and sounds. result->blorbs = fizmo_malloc(sizeof(fizmo_blorb*) * (nof_resources+1)); buf[4] = '\0'; blorb_index = 0; while (nof_resources > 0) { blorb = fizmo_malloc(sizeof(fizmo_blorb)); if (fsi->readchars(buf, 4, result->blorb_file) != 4) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_FUNCTION_CALL_P0S_ABORTED_DUE_TO_ERROR, -0x0106, "readchars"); TRACE_LOG("Type descriptor: %s\n", buf); if (strcmp(buf, "Pict") == 0) blorb->type = Z_BLORB_TYPE_PICT; else if (strcmp(buf, "Snd ") == 0) blorb->type = Z_BLORB_TYPE_SOUND; else if (strcmp(buf, "Exec") == 0) blorb->type = Z_BLORB_TYPE_EXEC; else // Unknown resource. i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_UNKNOWN_ERROR_CASE, -1); blorb->resource_number = read_four_byte_number(result->blorb_file); blorb->offset = read_four_byte_number(result->blorb_file) + 8; blorb->v3_number_of_loops = -1; result->blorbs[blorb_index++] = blorb; nof_resources--; } result->blorbs[blorb_index] = NULL; if (find_chunk("Fspc", result->blorb_file) == 0) { if ((fsi->setfilepos(result->blorb_file, 4, SEEK_CUR)) != 0) i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_FUNCTION_CALL_P0S_RETURNED_ERROR_CODE_P1D, -0x0101, "setfilepos", errno); result->frontispiece_image_no = read_four_byte_number(result->blorb_file); } else result->frontispiece_image_no = -1; if (ver < 5) { if (find_chunk("Loop", result->blorb_file) == 0) { nof_resources = read_four_byte_number(result->blorb_file) / 8; TRACE_LOG("Number of loop entries: %d.\n", nof_resources); while (nof_resources > 0) { resource_number = read_four_byte_number(result->blorb_file); nof_loops = read_four_byte_number(result->blorb_file); TRACE_LOG("Trying to find resource #%d.\n", resource_number); if ((blorb = fizmo_get_blorb( result_wrapper, Z_BLORB_TYPE_SOUND, resource_number)) != NULL) { TRACE_LOG("Resource found, setting nof_loops to %d.\n", nof_loops); blorb->v3_number_of_loops = nof_loops; } nof_resources--; } } } return result_wrapper; }
int set_configuration_value(char *key, char* new_unexpanded_value) { int i, return_code, result; char *new_value = NULL; char buf[BUFSIZE]; short color_code; char *endptr; if (key == NULL) return -1; if (new_unexpanded_value != NULL) if ((new_value = expand_configuration_value(new_unexpanded_value)) == NULL) return -1; #ifdef ENABLE_TRACING TRACE_LOG("Setting configuration key \"%s\".\n", key); if (new_value != NULL) { TRACE_LOG("New value: %s at %p.\n", new_value, new_value); } #endif //ENABLE_TRACING i = 0; while (configuration_options[i].name != NULL) { TRACE_LOG("i:%d, name:%s.\n", i, configuration_options[i].name); if (strcmp(configuration_options[i].name, key) == 0) { // Parse option values which cannot be simply copied: if (strcmp(key, "locale") == 0) { TRACE_LOG("Trying to set locale to \"%s\".\n", new_value); return_code = (strcmp(get_configuration_value( "dont-set-locale-from-config"), "true") == 0) ? 0 : set_current_locale_name(new_value); free(new_value); return return_code; } else if (strcmp(key, "random-mode") == 0) { if (new_value == NULL) return -1; else if (strcmp(new_value, "random") == 0) { if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = new_value; seed_random_generator(); return 0; } else if (strcmp(new_value, "predictable") == 0) { if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = new_value; TRACE_LOG("stored value: %p.\n", configuration_options[i].value); seed_random_generator(); return 0; } else return -1; } else if (strcmp(key, "i18n-search-path") == 0) { // Forward to i18n, since this is in tools and cannot access the // "config.c" file. return_code = set_i18n_search_path(new_value); free(new_value); return return_code; } // Options for values which can simply be copied. else if ( (strcmp(key, "z-code-path") == 0) || (strcmp(key, "z-code-root-path") == 0) || (strcmp(key, "autosave-filename") == 0) || (strcmp(key, "savegame-path") == 0) || (strcmp(key, "savegame-default-filename") == 0) || (strcmp(key, "transcript-filename") == 0) || (strcmp(key, "save-text-history-paragraphs") == 0) || (strcmp(key, "input-command-filename") == 0) || (strcmp(key, "record-command-filename") == 0) ) { if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = new_value; return 0; } // Integer values else if ( (strcmp(key, "stream-2-line-width") == 0) || (strcmp(key, "stream-2-left-margin") == 0) || (strcmp(key, "max-undo-steps") == 0) ) { if (new_value == NULL) return -1; if (strlen(new_value) == 0) { free(new_value); return -1; } strtol(new_value, &endptr, 10); if (*endptr != 0) { free(new_value); return -1; } if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = new_value; return 0; } // Color options else if (strcmp(key, "foreground-color") == 0) { if (new_value == NULL) return -1; color_code = color_name_to_z_colour(new_value); free(new_value); if (color_code == -1) return -1; if (snprintf(buf, BUFSIZE, "%d", color_code) >= BUFSIZE) return -1; if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = fizmo_strdup(buf); default_foreground_colour = color_code; return 0; } else if (strcmp(key, "background-color") == 0) { if (new_value == NULL) return -1; color_code = color_name_to_z_colour(new_value); free(new_value); if (color_code == -1) return -1; if (snprintf(buf, BUFSIZE, "%d", color_code) >= BUFSIZE) return -1; if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = fizmo_strdup(buf); default_background_colour = color_code; return 0; } // Boolean options else if ( (strcmp(key, "disable-external-streams") == 0) || (strcmp(key, "disable-restore") == 0) || (strcmp(key, "disable-save") == 0) || (strcmp(key, "disable-sound") == 0) || (strcmp(key, "enable-font3-conversion") == 0) || (strcmp(key, "quetzal-umem") == 0) || (strcmp(key, "random-mode") == 0) || (strcmp(key, "restore-after-save-and-quit-file-before-read") == 0) || (strcmp(key, "save-and-quit-file-before-read") == 0) || (strcmp(key, "set-tandy-flag") == 0) || (strcmp(key, "start-command-recording-when-story-starts") == 0) || (strcmp(key, "start-script-when-story-starts") == 0) || (strcmp(key, "start-file-input-when-story-starts") == 0) || (strcmp(key, "disable-stream-2-hyphenation") == 0) || (strcmp(key, "disable-stream-2-wrap") == 0) || (strcmp(key, "sync-transcript") == 0) || (strcmp(key, "dont-set-locale-from-config") == 0) ) { if ( (new_value == NULL) || (*new_value == 0) || (strcmp(new_value, config_true_value) == 0) ) { if (new_value != NULL) free(new_value); if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = fizmo_strdup(config_true_value); return 0; } else if ((new_value != NULL) && (strcmp(new_value, config_false_value)==0)) { free(new_value); if (configuration_options[i].value != NULL) free(configuration_options[i].value); configuration_options[i].value = fizmo_strdup(config_false_value); return -1; } else { free(new_value); return -1; } } else { i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_UNKNOWN_CONFIGURATION_OPTION_P0S, -0x0101, key); } } i++; } if (active_interface != NULL) { result = active_interface->parse_config_parameter(key, new_value); if (result == -1) { i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_INVALID_VALUE_P0S_FOR_PARAMETER_P1S, -0x0101, key, new_value); } } if (active_sound_interface == NULL) return -2; else { result = active_sound_interface->parse_config_parameter(key, new_value); if (result == -1) { i18n_translate_and_exit( libfizmo_module_name, i18n_libfizmo_INVALID_VALUE_P0S_FOR_PARAMETER_P1S, -0x0101, key, new_value); } } return result; }