Пример #1
0
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;
  }
}
Пример #2
0
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);
  }
}
Пример #3
0
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;
}
Пример #4
0
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;
  }
}
Пример #5
0
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;
  }
}
Пример #6
0
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;
  }
}
Пример #7
0
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;
  }
}
Пример #8
0
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--;
}
Пример #9
0
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++;
}
Пример #10
0
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);

}
Пример #11
0
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);
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
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;
}
Пример #15
0
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;
}