Esempio n. 1
0
z_ucs *z_ucs_cat(z_ucs *dst, z_ucs *src)
{
  dst += z_ucs_len(dst);

  while (*src != 0)
    *(dst++) = *(src++);
  *dst = 0;

  return dst;
}
Esempio n. 2
0
z_ucs *z_ucs_dup(z_ucs *src)
{
  z_ucs *result;

  if ((result = malloc(sizeof(z_ucs) * (z_ucs_len(src) + 1))) == NULL)
    return NULL;

  z_ucs_cpy(result, src);

  return result;
}
Esempio n. 3
0
void wordwrap_wrap_z_ucs(WORDWRAP *wrapper, z_ucs *input)
{
  size_t len, chars_to_copy, space_in_buffer;

  len = z_ucs_len(input);

  while (len > 0)
  {
    space_in_buffer = wrapper->input_buffer_size - 1 - wrapper->input_index;

    chars_to_copy
      = len > space_in_buffer
      ? space_in_buffer
      : len;

    TRACE_LOG("chars_to_copy: %d, len:%d, space_in_buffer:%d.\n",
        chars_to_copy, len, space_in_buffer);

    z_ucs_ncpy(
        wrapper->input_buffer + wrapper->input_index,
        input,
        chars_to_copy);

    wrapper->input_index += chars_to_copy;
    wrapper->input_buffer[wrapper->input_index] = 0;
    input += chars_to_copy;
    len -= chars_to_copy;

    TRACE_LOG("chars copied: %d, chars left: %ld.\n",chars_to_copy,(long)len);

    if (
        (wrapper->input_index == wrapper->input_buffer_size - 1)
        ||
        (
         (wrapper->flush_after_newline == true)
         &&
         (
          (wrapper->input_index + wrapper->chars_already_on_line
           > wrapper->line_length)
          ||
          (z_ucs_chr(wrapper->input_buffer, Z_UCS_NEWLINE) != NULL)
         )
        )
       )
    {
      flush_input_buffer(wrapper, false);

      //FIXME: Increase buffer size in case flush not possible.
    }
  }
}
Esempio n. 4
0
z_ucs *z_ucs_rchrs(z_ucs *s1, z_ucs *chars)
{
  z_ucs *ptr = s1 + z_ucs_len(s1), *ptr2;

  while (ptr >= s1)
  {
    if ((ptr2 = z_ucs_chr(chars, *ptr)) != NULL)
      return ptr;

    ptr--;
  }

  return NULL;
}
Esempio n. 5
0
z_ucs *z_ucs_rchr(z_ucs *s1, z_ucs chr)
{
  z_ucs *ptr = s1 + z_ucs_len(s1);

  while (ptr >= s1)
  {
    if (*ptr == chr)
      return ptr;

    ptr--;
  }

  return NULL;
}
Esempio n. 6
0
static int i18n_send_output(z_ucs *z_ucs_data, int output_mode,
                            z_ucs **string_target)
{
    char *output;

    if (z_ucs_data == NULL)
    {
        return 0;
    }
    else if (output_mode == i18n_OUTPUT_MODE_STREAMS)
    {
        if (stream_output_function == NULL)
        {
            if ((output = dup_zucs_string_to_utf8_string(z_ucs_data)) == NULL)
                return -1;
            fputs(output, stdout);
            free(output);
            return 0;
        }
        else
            return stream_output_function(z_ucs_data);
    }
    else if (output_mode == i18n_OUTPUT_MODE_STRING)
    {
        (void)z_ucs_cpy(*string_target, z_ucs_data);
        *string_target += z_ucs_len(z_ucs_data);
        return 0;
    }
    else if (output_mode == i18n_OUTPUT_MODE_DEV_NULL)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}
void freetype_wrap_z_ucs(true_type_wordwrapper *wrapper, z_ucs *input,
    bool end_line_after_end_of_input) {
  z_ucs *hyphenated_word, *input_index = input;
  z_ucs current_char, last_char, buf;
  long wrap_width_position, end_index, hyph_index;
  long buf_index, last_valid_hyph_index, output_metadata_index;
  long last_valid_hyph_position, hyph_position;
  int hyph_font_dash_bitmap_width, hyph_font_dash_advance;
  int metadata_index = 0, advance, bitmap_width;
  true_type_font *hyph_font;
  bool process_line_end = end_line_after_end_of_input;

  // In order to build an algorithm most suitable to both enabled and
  // disabled hyphenation, we'll collect input until we'll find the first
  // space or newline behind the right margin and then initiate a buffer
  // flush, which will then break according to the given situation.

  // Invoking a separate flush method makes sense since it also allows
  // a simple external triggering of the flush.

  // To minimize calculations, we keeping track of the last complete word's
  // rightmost char in last_word_end_index and the "word's last advance
  // position" in last_word_end_advance_position.

  // An "advance position" sums up all the "horiAdvance" distances for all
  // glyphs in the current word.

  // last_word_end_advance_position contains the advance position of
  // the last complete word/char which still fits into the current line.
  // This is updated every time we hit a space (so we can easily find the last
  // valid position to break).


  // We'll start by fetching the last char from the buffer (if possible) for
  // purposes of kerning.
  last_char
    = (wrapper->current_buffer_index > 0)
    ? wrapper->input_buffer[wrapper->current_buffer_index - 1]
    : 0;

  while ( ((input != NULL) && (*input_index != 0))
      || (process_line_end == true) ) {

    if ((input != NULL) && (*input_index != 0)) {
      current_char = *input_index;

      ensure_additional_buffer_capacity(wrapper, 1);
      wrapper->input_buffer[wrapper->current_buffer_index] = current_char;

      TRACE_LOG("buffer-add: %c / %ld / %p / cap:%ld / lweap:%ld \n",
          (char)current_char,
          wrapper->current_buffer_index,
          wrapper->input_buffer + wrapper->current_buffer_index,
          wrapper->current_advance_position,
          wrapper->last_word_end_advance_position);

      wrapper->current_buffer_index++;

      tt_get_glyph_size(wrapper->current_font, current_char,
          &advance, &bitmap_width);
      wrapper->current_width_position
        = wrapper->current_advance_position + bitmap_width;
      //printf("current_width_position: %ld for '%c'\n",
      //    wrapper->current_width_position, current_char);
      wrapper->current_advance_position += advance;

      /*
      printf("check:'%c',font:%p,advpos,ll,lweim,cwwp,bmw: %ld/%d/%ld/%ld/%d\n",
          current_char,
          wrapper->current_font,
          wrapper->current_advance_position,
          wrapper->line_length,
          wrapper->last_word_end_index,
          wrapper->current_width_position,
          bitmap_width);

      printf("bmw, lwp, ll: %d, %ld, %d.\n",
          bitmap_width,
          wrapper->last_width_position,
          wrapper->line_length);
      */
    }
    else {
      current_char = 0;
      bitmap_width = 0;
      advance = 0;
    }

    if ( (
          (bitmap_width == 0)
          && (wrapper->last_width_position >= wrapper->line_length)
         )
        || (wrapper->current_width_position >= wrapper->line_length) ) {

      wrapper->last_width_position
        = wrapper->current_width_position;
      wrapper->last_chars_font
        = wrapper->current_font;

      /*
      printf("linebehind: %ld, %d.\n",
          wrapper->current_width_position, wrapper->line_length);
      */

      TRACE_LOG("Behind past line, match on space|newline, breaking.\n");
      // In case we're past the right margin, we'll take a look how
      // to best break the line.

      if ((current_char == Z_UCS_SPACE) || (current_char == Z_UCS_NEWLINE)
          || (((input == NULL) || (*input_index == 0))
            && (process_line_end == true)) ) {
        // Here we've found a completed word past the lind end. At this
        // point we'll break the line without exception.
        /*
        printf("last_word_end_width_position: %ld, line_length: %d.\n",
            wrapper->last_word_end_width_position, wrapper->line_length);
        */

        if (wrapper->enable_hyphenation == true) {
          end_index = wrapper->current_buffer_index - 2;
          TRACE_LOG("end_index: %d / %c, lwei: %d\n",
              end_index, wrapper->input_buffer[end_index],
              wrapper->last_word_end_index);
          while ( (end_index >= 0)
              && (end_index > wrapper->last_word_end_index)
              && ( (wrapper->input_buffer[end_index] == Z_UCS_COMMA)
                || (wrapper->input_buffer[end_index] == Z_UCS_DOT) ) ) {
            end_index--;
          }
          TRACE_LOG("end end_index: %d / %c, lwei: %d\n",
              end_index, wrapper->input_buffer[end_index],
              wrapper->last_word_end_index);
          if (end_index > wrapper->last_word_end_index) {
            end_index++;
            buf = wrapper->input_buffer[end_index];
            wrapper->input_buffer[end_index] = 0;
            if ((hyphenated_word = hyphenate(wrapper->input_buffer
                    + wrapper->last_word_end_index + 1)) == NULL) {
              TRACE_LOG("Error hyphenating.\n");
            }
            else {
              TRACE_LOG("hyphenated word: \"");
              TRACE_LOG_Z_UCS(hyphenated_word);
              TRACE_LOG("\".\n");

              wrap_width_position
                = wrapper->last_word_end_advance_position
                + wrapper->space_bitmap_width;
              hyph_index = wrapper->last_word_end_index + 1;
              buf_index = 0;
              last_valid_hyph_index = -1;

              // We'll now have to find the correct font for the start
              // of our hyphenated word. For that we'll remember the current
              // font at buffer start and iterate though all the metadata
              // until we're at the hyphenated word's beginning.
              hyph_font = wrapper->font_at_buffer_start;
              tt_get_glyph_size(hyph_font, Z_UCS_MINUS,
                  &hyph_font_dash_bitmap_width, &hyph_font_dash_advance);
              metadata_index = 0;

              while ( (buf_index < z_ucs_len(hyphenated_word))
                  && (wrap_width_position + hyph_font_dash_bitmap_width
                    <= wrapper->line_length) ) {
                /*
                   printf("Checking buf char %ld / %c, hi:%ld\n",
                   buf_index, hyphenated_word[buf_index],
                   hyph_index);
                   */
                TRACE_LOG("Checking buf char %ld / %c, hi:%ld\n",
                    buf_index, hyphenated_word[buf_index],
                    hyph_index);

                while (metadata_index < wrapper->metadata_index) {
                  //printf("metadata: %d of %d.\n",
                  //    metadata_index, wrapper->metadata_index);

                  output_metadata_index =
                    wrapper->metadata[metadata_index].output_index;

                  //printf("output_metadata_index: %ld, hyph_index: %ld\n",
                  //    output_metadata_index, hyph_index);
                  //printf("hyph_font: %p.\n", hyph_font);

                  if (output_metadata_index <= hyph_index) {
                    if (wrapper->metadata[metadata_index].font != NULL) {
                      hyph_font = wrapper->metadata[metadata_index].font;
                      tt_get_glyph_size(hyph_font, Z_UCS_MINUS,
                          &hyph_font_dash_bitmap_width,
                          &hyph_font_dash_advance);
                    }
                    metadata_index++;
                  }
                  else {
                    break;
                  }
                }

                if (hyphenated_word[buf_index] == Z_UCS_SOFT_HYPEN) {
                  last_valid_hyph_index = hyph_index + 1;
                }
                else if (hyphenated_word[buf_index] == Z_UCS_MINUS) {
                  last_valid_hyph_index = hyph_index;
                }

                if (hyphenated_word[buf_index] != Z_UCS_SOFT_HYPEN) {
                  //printf("hyph_font: %p.\n", hyph_font);
                  tt_get_glyph_size(hyph_font,
                      hyphenated_word[buf_index],
                      &advance, &bitmap_width);
                  //wrap_width_position += bitmap_width;
                  wrap_width_position += advance;
                  hyph_index++;
                }

                if ( (hyphenated_word[buf_index] == Z_UCS_SOFT_HYPEN)
                    || (hyphenated_word[buf_index] == Z_UCS_MINUS) ) {
                  last_valid_hyph_position = wrap_width_position;
                }

                buf_index++;

                /*
                   printf("(%ld + %d) = %ld <= %d\n",
                   wrap_width_position, hyph_font_dash_bitmap_width,
                   wrap_width_position + hyph_font_dash_bitmap_width,
                   wrapper->line_length);
                   */
              }

              free(hyphenated_word);

              if (last_valid_hyph_index != -1) {
                /*
                   printf("Found valid hyph pos at %ld / %c.\n",
                   last_valid_hyph_index,
                   wrapper->input_buffer[last_valid_hyph_index]);
                   */
                TRACE_LOG("Found valid hyph pos at %ld / %c.\n",
                    last_valid_hyph_index,
                    wrapper->input_buffer[last_valid_hyph_index]);
                hyph_index = last_valid_hyph_index;
                hyph_position = last_valid_hyph_position;
              }
              else {
                hyph_index = wrapper->last_word_end_index;
                hyph_position = wrapper->last_word_end_advance_position;
                //printf("no valid hyph, hyph_index: %ld.\n", hyph_index);
              }
            }
            wrapper->input_buffer[end_index] = buf;
          } // endif (end_index > wrapper->last_work_end_index)
          else {
            hyph_index = end_index;
            //printf("Hyph at %ld.\n", hyph_index);
          }
        } // endif (wrapper->enable_hyphentation == true)
        else {
          // 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".
          wrap_width_position = wrapper->current_width_position;
          hyph_index = wrapper->current_buffer_index - 2;
          while ( (hyph_index >= 0)
              && (hyph_index > wrapper->last_word_end_index)) {
            /*
            printf("hyph_index: %ld / '%c'.\n",
                hyph_index, wrapper->input_buffer[hyph_index]);
            */

            if ( (wrapper->input_buffer[hyph_index] == Z_UCS_MINUS)
                && (wrap_width_position <= wrapper->line_length) ) {
              // Found a dash to break on
              break;
            }
            tt_get_glyph_size(wrapper->current_font,
                wrapper->input_buffer[hyph_index],
                &advance, &bitmap_width);
            wrap_width_position -= bitmap_width;
            hyph_index--;
          }
          hyph_position = wrap_width_position;
        }

        //printf("breaking on char %ld / %c.\n",
        //    hyph_index, wrapper->input_buffer[hyph_index]);
        TRACE_LOG("breaking on char %ld / %c.\n",
            hyph_index, wrapper->input_buffer[hyph_index]);

        if (wrapper->input_buffer[hyph_index] == Z_UCS_MINUS) {
          // We're wrappring on a in-word-dash.
          flush_line(wrapper, hyph_index, false, true);
        }
        else if (wrapper->input_buffer[hyph_index] == Z_UCS_SPACE) {
          flush_line(wrapper, hyph_index - 1, false, true);
          // In case we're wrapping between words without hyphenation or
          // in-word-dashes we'll have to get rid of the remaining leading
          // space-char in the input buffer.
          forget_first_char_in_buffer(wrapper);
        }
        else {
          if (wrapper->input_buffer[hyph_index - 2] == Z_UCS_MINUS) {
            flush_line(wrapper, hyph_index - 3, true, true);
            forget_first_char_in_buffer(wrapper);
          }
          else {
            flush_line(wrapper, hyph_index - 2, true, true);
          }
        }

        wrapper->current_advance_position
          -= hyph_position - wrapper->dash_bitmap_width;

        /*
        wrapper->last_width_position
          = wrapper->current_width_position
          - wrapper->last_word_end_advance_position;
          */

        wrapper->current_width_position
          = wrapper->current_advance_position;

        wrapper->last_word_end_advance_position
          = wrapper->current_advance_position;

        wrapper->last_word_end_width_position
          = wrapper->current_width_position;

        wrapper->last_word_end_index = -1;
      }
      else if (wrapper->current_advance_position > wrapper->line_length * 2) {
        // In case we haven't found a word end we'll only force a line
        // break in case we've filled two full lines of text.

        /*
        printf("flush on: %c\n", wrapper->input_buffer[
            wrapper->current_buffer_index - 2]);
        */
        flush_line(wrapper, wrapper->current_buffer_index - 2, false, true);

        wrapper->current_advance_position
          = advance;

        wrapper->current_width_position
          = wrapper->current_advance_position + bitmap_width;

        wrapper->last_word_end_index = -1;
        wrapper->last_word_end_advance_position = 0;
        wrapper->last_word_end_width_position = 0;

        //printf("first buf: %c\n", wrapper->input_buffer[0]);

        /*
        printf("current_buffer_index: %ld\n", wrapper->current_buffer_index);
        printf("current_advance_position: %ld\n",
            wrapper->current_advance_position);
        printf("break at %ld, 1\n", wrapper->last_char_in_line_index);
        old_index = wrapper->current_buffer_index;
        flush_line(wrapper, wrapper->last_char_in_line_index, false, true);
        chars_sent_count = old_index - wrapper->current_buffer_index;

        printf("chars_sent_count: %ld\n", chars_sent_count);
        printf("current_buffer_index: %ld\n", wrapper->current_buffer_index);

        tt_get_glyph_size(wrapper->last_chars_in_line_font,
            wrapper->input_buffer[wrapper->current_buffer_index],
            &advance, &bitmap_width);

        wrapper->current_advance_position
          -= wrapper->last_chars_in_line_advance_position;

        wrapper->last_width_position
          = wrapper->current_advance_position
          + bitmap_width;

        wrapper->last_char_in_line_index
          = 0;

        wrapper->last_word_end_advance_position
          -= wrapper->last_chars_in_line_advance_position;

        wrapper->last_word_end_width_position
          -= wrapper->last_chars_in_line_advance_position;

        wrapper->last_word_end_index
          -= chars_sent_count;

        printf("current_advance_position: %ld\n",
            wrapper->current_advance_position);
        */
      }
      else {
        // Otherwise, we'll do nothing and keep collecting chars until
        // we later find a word and or exceed the double line length.
      }
    }
    else {
      wrapper->last_width_position
        = wrapper->current_width_position;
    }

    if (current_char == Z_UCS_NEWLINE) {
      TRACE_LOG("Flushing on newline at current position.\n");
      // In case everything fits into the current line and the current
      // char is a newline, we can simply flush at the current position.
      flush_line(wrapper, wrapper->current_buffer_index - 1, false, false);

      wrapper->last_word_end_advance_position = 0;
      wrapper->last_word_end_width_position = 0;
      wrapper->current_advance_position = 0;
      wrapper->current_width_position = 0;
      wrapper->last_width_position = 0;
      wrapper->last_word_end_index = -1;
    }

    if ( (current_char == Z_UCS_SPACE) && (last_char != Z_UCS_SPACE) ) {
      TRACE_LOG("lweap-at-space: %ld\n",
          wrapper->last_word_end_advance_position);
      wrapper->last_word_end_advance_position
        = wrapper->current_advance_position;
      wrapper->last_word_end_width_position
        = wrapper->current_width_position;
      wrapper->last_word_end_index
        = wrapper->current_buffer_index - 1;
    }

    if ( (input != NULL) && (*input_index != 0) ) {
      input_index++;
      last_char = current_char;
    }
    else if (process_line_end == true) {
      process_line_end = false;
    }
  }
}
void flush_line(true_type_wordwrapper *wrapper, long flush_index,
    bool append_minus, bool append_newline) {
  z_ucs buf_1; //, buf_2;
  size_t chars_sent;
  int chars_to_move;
  int metadata_index = 0;
  long output_metadata_index, output_index;
  struct freetype_wordwrap_metadata *metadata_entry;
  int i;

  if (flush_index == -1) {
    flush_index = wrapper->current_buffer_index - 1;
  }
  else
  {
    TRACE_LOG("flush on: %c %d \n",
      (char)wrapper->input_buffer[flush_index],
      wrapper->input_buffer[flush_index]);
  }
  // Ensure there's enough space to place a terminating 0.
  ensure_additional_buffer_capacity(wrapper, 1);

  output_index = 0;
  while (metadata_index < wrapper->metadata_index) {
    TRACE_LOG("Found some metadata, starting at metadata index %d of %d.\n",
        metadata_index, wrapper->metadata_index);

    // Look which buffer position is affected by the next metadata entry.
    output_metadata_index =
      wrapper->metadata[metadata_index].output_index;

    TRACE_LOG("mdoutput: mdindex: %d, flushindex: %d, output_index:%d\n",
        output_metadata_index, flush_index, output_index);

    // In case we're not flushing everything and the next buffer position is
    // behind the current flush position, there's nothing more to do.
    if ( (flush_index >= 0) && (output_metadata_index > flush_index) ) {
     break;
    }

    // In case current output position is before the metadata entry's
    // output position, we'll flush everything until this position.
    if (output_index < output_metadata_index) {
      TRACE_LOG("Flusing up to next metadata entry at %ld\n",
          output_metadata_index);

      buf_1 = wrapper->input_buffer[output_metadata_index];
      wrapper->input_buffer[output_metadata_index] = 0;
      wrapper->wrapped_text_output_destination(
          wrapper->input_buffer + output_index,
          wrapper->destination_parameter);
      wrapper->input_buffer[output_metadata_index] = buf_1;
      output_index = output_metadata_index;
    }

    TRACE_LOG("metadata_index: %d,output_index: %d,output_metadata_index:%d\n",
        metadata_index, output_index, output_metadata_index);
    TRACE_LOG("wrapper->metadata[%d].output_index: %d\n",
        metadata_index,
        wrapper->metadata[metadata_index].output_index);
    TRACE_LOG("wrapper->metadata_index: %d\n",
        wrapper->metadata_index);
    // We can now flush all the metadata entries at the current position.
    TRACE_LOG("%d / %d\n",
        wrapper->metadata[metadata_index].output_index + 1,
        output_metadata_index + 1);

    while ( (metadata_index < wrapper->metadata_index)
        && (wrapper->metadata[metadata_index].output_index
          == output_metadata_index) ) {

      metadata_entry = &wrapper->metadata[metadata_index];

      TRACE_LOG("Output metadata prm %d at buffer position %ld.\n",
          metadata_entry->int_parameter,
          output_metadata_index);

      metadata_entry->metadata_output_function(
          metadata_entry->ptr_parameter,
          metadata_entry->int_parameter);

      if (metadata_entry->font != NULL) {
        wrapper->font_at_buffer_start = metadata_entry->font;
      }

      metadata_index++;
    }
  }

  if (metadata_index > 0) {
    TRACE_LOG("Removing %d metadata entries.\n", metadata_index);
    memmove(
        wrapper->metadata,
        &wrapper->metadata[metadata_index],
        (wrapper->metadata_index - metadata_index) * sizeof(
          struct freetype_wordwrap_metadata));
    wrapper->metadata_index -= metadata_index;
  }

  /*
  if (append_newline == true) {
    buf_1 = wrapper->input_buffer[flush_index + 1];
    buf_2 = wrapper->input_buffer[flush_index + 2];
    wrapper->input_buffer[flush_index + 1] = Z_UCS_NEWLINE;
    wrapper->input_buffer[flush_index + 2] = 0;
    TRACE_LOG("flush-index: %d\n", flush_index);
    TRACE_LOG("flush-line (%d / %p): \"", z_ucs_len(wrapper->input_buffer),
        wrapper->input_buffer);
    TRACE_LOG_Z_UCS(wrapper->input_buffer);
    TRACE_LOG("\"\n");
    wrapper->wrapped_text_output_destination(
        wrapper->input_buffer + output_index,
        wrapper->destination_parameter);
    wrapper->input_buffer[flush_index + 1] = buf_1;
    wrapper->input_buffer[flush_index + 2] = buf_2;
  }
  else {
    buf_1 = wrapper->input_buffer[flush_index + 1];
    wrapper->input_buffer[flush_index + 1] = 0;
    TRACE_LOG("flush-index: %d\n", flush_index);
    TRACE_LOG("flush-line (%d / %p): \"", z_ucs_len(wrapper->input_buffer),
        wrapper->input_buffer);
    TRACE_LOG_Z_UCS(wrapper->input_buffer);
    TRACE_LOG("\"\n");
    wrapper->wrapped_text_output_destination(
        wrapper->input_buffer + output_index,
        wrapper->destination_parameter);
    wrapper->input_buffer[flush_index + 1] = buf_1;
  }
  */

  buf_1 = wrapper->input_buffer[flush_index + 1];
  wrapper->input_buffer[flush_index + 1] = 0;
  TRACE_LOG("flush-index: %d\n", flush_index);
  TRACE_LOG("flush-line (%d / %p): \"", z_ucs_len(wrapper->input_buffer),
      wrapper->input_buffer);
  TRACE_LOG_Z_UCS(wrapper->input_buffer);
  TRACE_LOG("\"\n");
  wrapper->wrapped_text_output_destination(
      wrapper->input_buffer + output_index,
      wrapper->destination_parameter);
  wrapper->input_buffer[flush_index + 1] = buf_1;

  if (append_minus == true) {
    wrapper->wrapped_text_output_destination(
        minus_string,
        wrapper->destination_parameter);
  }

  if (append_newline == true) {
    wrapper->wrapped_text_output_destination(
        newline_string,
        wrapper->destination_parameter);
  }

  chars_sent = flush_index + 1;
  TRACE_LOG("chars_sent: %ld, dst: %p, src: %p, bufindex: %ld\n",
      chars_sent,
      wrapper->input_buffer,
      wrapper->input_buffer + flush_index,
      wrapper->current_buffer_index);
  if ((chars_to_move = wrapper->current_buffer_index - chars_sent) > 0) {
    memmove(
        wrapper->input_buffer,
        wrapper->input_buffer + flush_index + 1,
        chars_to_move * sizeof(z_ucs));
  }
  for (i=0; i<wrapper->metadata_index; i++)
    wrapper->metadata[i].output_index -= chars_sent;

  wrapper->current_buffer_index -= chars_sent;
}
Esempio n. 9
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;
}
Esempio n. 10
0
static void output_buffer(WORDWRAP *wrapper, z_ucs *buffer_start,
    int *metadata_offset)
{
  long index, end_index, next_index;
  struct wordwrap_metadata *metadata_entry;
  z_ucs buf;

  TRACE_LOG("Output buffer: \"");
  TRACE_LOG_Z_UCS(buffer_start);
  TRACE_LOG("\"");

  if (*metadata_offset == wrapper->metadata_index)
  {
    wrapper->wrapped_text_output_destination(
        buffer_start,
        wrapper->destination_parameter);
  }
  else
  {
    index = buffer_start - wrapper->input_buffer;
    end_index = index + z_ucs_len(buffer_start);

    while (index < end_index)
    {
      TRACE_LOG("index: %ld, end_index: %ld.\n", index, end_index);
      TRACE_LOG("metadata-offset: %d.\n", *metadata_offset);

      if (*metadata_offset < wrapper->metadata_index)
      {
        TRACE_LOG("next metadata-index: %ld.\n",
            wrapper->metadata[*metadata_offset].output_index);

        while (
            (*metadata_offset < wrapper->metadata_index)
            &&
            (wrapper->metadata[*metadata_offset].output_index == index)
            )
        {
          metadata_entry = &wrapper->metadata[*metadata_offset];

          TRACE_LOG("Output metadata prm %d at %ld.\n",
              metadata_entry->int_parameter,
              index);

          metadata_entry->metadata_output_function(
              metadata_entry->ptr_parameter,
              metadata_entry->int_parameter);

          (*metadata_offset)++;
        }
      }

      next_index
        = (
            (*metadata_offset < wrapper->metadata_index)
            &&
            (wrapper->metadata[*metadata_offset].output_index < end_index)
          )
        ? wrapper->metadata[*metadata_offset].output_index
        : end_index;

      TRACE_LOG("next-index: %ld.\n", next_index);


      buf = wrapper->input_buffer[next_index];
      wrapper->input_buffer[next_index] = 0;

      wrapper->wrapped_text_output_destination(
          wrapper->input_buffer + index,
          wrapper->destination_parameter);

      wrapper->input_buffer[next_index] = buf;

      index = next_index;
    }
  }
}
Esempio n. 11
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;
}
Esempio n. 12
0
// "string_code" is one of the codes defined in "utf8.h".
// "ap" is the va_list initialized in the various i18n-methods.
// "output_mode" is either "i18n_OUTPUT_MODE_DEV_NULL" for no output
//  at all (useful for string length measuring), "i18n_OUTPUT_MODE_STREAMS"
//  for sending output to "streams_utf8_output" and "i18n_OUTPUT_MODE_STRING"
//  to write the output to a string.
static long i18n_translate_from_va_list(z_ucs *module_name, int string_code,
                                        va_list ap, int output_mode, z_ucs *string_target)
{
    z_ucs *locale_name;
    locale_module *module;
    z_ucs *index;
    char parameter_types[11]; // May each contain 's', 'z' or 'd'. Using 11
    // instead of ten so that a null byte may be
    // placed after a char to print the error
    // message as string.
    char *string_parameters[10]; // pointers to the parameters.
    z_ucs *z_ucs_string_parameters[10];
    char formatted_parameters[10][MAXIMUM_FORMATTED_PARAMTER_LENGTH + 1];
    z_ucs *start;
    uint8_t match_stage;
    int i,k;
    int n;
    z_ucs buf;
    size_t length;
    z_ucs *start_index;
    char index_char;
    z_ucs z_ucs_buffer[LATIN1_TO_Z_UCS_BUFFER_SIZE];
    char *ptr;

    locale_name
        = current_locale_name != NULL
          ? current_locale_name
          : default_locale_name;

    TRACE_LOG("Trying to get module '");
    TRACE_LOG_Z_UCS(module_name);
    TRACE_LOG("' for locale '");
    TRACE_LOG_Z_UCS(locale_name);
    TRACE_LOG("'.\n");

    if ((module = get_locale_module(locale_name, module_name)) == NULL)
    {
        TRACE_LOG("Module not found.\n");
        i18n_exit(-1, NULL);
    }

    TRACE_LOG("Got module at %p with %d messages at %p.\n",
              module, module->nof_messages, module->messages);

    if (string_code >= module->nof_messages)
    {
        TRACE_LOG("String %d code too large, exiting.\n", string_code);
        i18n_exit(-1, NULL);
    }

    index = module->messages[string_code];

    if (index == NULL)
        return -1;

    TRACE_LOG("Translating string code %d at %p.\n", string_code, index);

    n = 0;
    while ((index = z_ucs_chr(index, (z_ucs)'\\')) != NULL)
    {
        index++;
        start_index = index;
        index_char = zucs_char_to_latin1_char(*index);

        if (index_char == '{')
        {
            TRACE_LOG("'{' found.\n");
            index++;
            index_char = zucs_char_to_latin1_char(*index);
        }
        else
        {
            index = start_index;
            continue;
        }

        if ((index_char >= '0') && (index_char <= '9'))
        {
            TRACE_LOG("'[0-9]' found.\n");
            index++;
            index_char = zucs_char_to_latin1_char(*index);
        }
        else
        {
            index = start_index;
            continue;
        }

        if (
            (index_char == 's')
            ||
            (index_char == 'z')
            ||
            (index_char == 'd')
            ||
            (index_char == 'x')
        )
        {
            TRACE_LOG("'[szdx]' found.\n");
            parameter_types[n] = index_char;
            index++;
            index_char = zucs_char_to_latin1_char(*index);
        }
        else
        {
            index = start_index;
            continue;
        }

        if (index_char == '}')
        {
            TRACE_LOG("'}' found.\n");
            index++;
            index_char = zucs_char_to_latin1_char(*index);
            n++;
        }
        else
        {
            index = start_index;
            continue;
        }
    }

    TRACE_LOG("Found %d parameter codes.\n", n);

    if (n == 0)
    {
        TRACE_LOG("No parameter.\n");
        // In case we don't have a single parameter, we can just print
        // everything right away and quit.

        if (i18n_send_output(
                    module->messages[string_code],
                    output_mode,
                    (string_target != NULL ? &string_target : NULL)) != 0)
            return -1;
        else
            return z_ucs_len(module->messages[string_code]);
    }

    length = 0;

    for (i=0; i<n; i++)
    {
        // parameter_types[0-n] are always defined, thus using "usedef" is okay.

        if (parameter_types[i] == 's')
        {
            string_parameters[i] = va_arg(ap, char*);
            TRACE_LOG("p#%d: %s\n", i, string_parameters[i]);
            length += strlen(string_parameters[i]);
        }
        else if (parameter_types[i] == 'z')
Esempio n. 13
0
// Returns malloc()ed string which needs to be free()d later.
static char *get_path_for_locale(z_ucs *locale_name)
{
    z_dir *dir;
    char *search_path;
    z_ucs *search_path_zucs, *path_ptr, *colon_index, *zucs_ptr;
    z_ucs *zucs_buf = NULL;
    size_t bufsize = 0, len, dirname_len;
    struct z_dir_ent z_dir_entry;
    char *dirname;
    char *locale_name_utf8, *locale_dir_name = NULL;

    search_path
        = locale_search_path == NULL
          ? default_search_path
          : locale_search_path;

    search_path_zucs = dup_utf8_string_to_zucs_string(search_path);
    path_ptr = search_path_zucs;

    TRACE_LOG("Search path: \"");
    TRACE_LOG_Z_UCS(search_path_zucs);
    TRACE_LOG("'.\n");

    // open-resource:
    locale_name_utf8 = dup_zucs_string_to_utf8_string(locale_name);

    while (*path_ptr != 0)
    {
        colon_index = z_ucs_chr(path_ptr, Z_UCS_COLON);

        len
            = colon_index == NULL
              ? z_ucs_len(path_ptr)
              : (size_t)(colon_index - path_ptr);

        TRACE_LOG("len: %ld\n", (long)len);

        if (len > 0)
        {
            if (bufsize < len + 1)
            {
                TRACE_LOG("realloc buf for %ld chars / %ld bytes.\n",
                          (long)len + 1, (long)sizeof(z_ucs) * (len + 1));

                // open-resource:
                if ((zucs_ptr = realloc(zucs_buf, sizeof(z_ucs) * (len + 1))) == NULL)
                {
                    // exit-point:
                    TRACE_LOG("realloc() returned NULL.\n");
                    free(zucs_buf);
                    free(locale_name_utf8);
                    free(path_ptr);
                    return NULL;
                }

                bufsize = len + 1;
                zucs_buf = zucs_ptr;
            }

            z_ucs_ncpy(zucs_buf, path_ptr, len);
            zucs_buf[len] = 0;

            // open-resource:
            if ((dirname = dup_zucs_string_to_utf8_string(zucs_buf)) == NULL)
            {
                // exit-point:
                TRACE_LOG("dup_zucs_string_to_utf8_string() returned NULL.\n");
                free(zucs_buf);
                free(locale_name_utf8);
                free(path_ptr);
                return NULL;
            }

            TRACE_LOG("Path: '%s'\n", dirname);

            // open-resource:
            if ((dir = fsi->open_dir(dirname)) != NULL)
            {
                while (fsi->read_dir(&z_dir_entry, dir) == 0)
                {
                    TRACE_LOG("Processing \"%s\".\n", z_dir_entry.d_name);
                    if (strcasecmp(locale_name_utf8, z_dir_entry.d_name) == 0)
                    {
                        dirname_len = strlen(dirname) + strlen(z_dir_entry.d_name);
                        TRACE_LOG("dirname_len: %ld.\n", (long)dirname_len);
                        // open-resource:
                        if ((locale_dir_name = malloc(dirname_len + 2)) == NULL)
                        {
                            // exit-point:
                            TRACE_LOG("malloc() returned NULL.\n");
                            fsi->close_dir(dir);
                            free(dirname);
                            free(zucs_buf);
                            free(locale_name_utf8);
                            free(path_ptr);
                            return NULL;
                        }

                        strcpy(locale_dir_name, dirname);
                        strcat(locale_dir_name, "/");
                        strcat(locale_dir_name, z_dir_entry.d_name);
                        break;
                    }
                }

                // close-resource:
                fsi->close_dir(dir);
            }

            // close-resource:
            free(dirname);
        }

        if (locale_dir_name != NULL)
            break;

        path_ptr += len + (colon_index != NULL ? 1 : 0);
    }

    free(search_path_zucs);

    // close-resource:
    free(locale_name_utf8);

    // close-resource:
    free(zucs_buf);

    //TRACE_LOG("res:'");
    //TRACE_LOG_Z_UCS(locale_dir_name);
    //TRACE_LOG("\n");

    return locale_dir_name;
}
Esempio n. 14
0
static locale_module *parse_locale_file(z_ucs *module_name,
                                        char* locale_dir_name, char* module_name_utf8)
{
    char *filename;
    z_file *in;
    z_ucs *locale_data;
    locale_module *result;
    char in_char;
    long nof_zucs_chars;
    z_ucs input;
    z_ucs *linestart;
    list *lines;

    TRACE_LOG("locale_dir_name: \"%s\".\n", locale_dir_name);
    TRACE_LOG("module_name_utf8: \"%s\".\n", module_name_utf8);

    // open-resource:
    if ((filename
            = malloc(strlen(locale_dir_name) + strlen(module_name_utf8) + 2))
            == NULL)
    {
        // exit-point:
        TRACE_LOG("malloc() returned NULL.\n");
        return NULL;
    }

    TRACE_LOG("locale_dir_name: \"%s\".\n", locale_dir_name);
    TRACE_LOG("module_name_utf8: \"%s\".\n", module_name_utf8);

    strcpy(filename, locale_dir_name);
    strcat(filename, "/");
    strcat(filename, module_name_utf8);

    TRACE_LOG("Parsing locale file \"%s\".\n", filename);

    // open-resource:
    if ((in = fsi->openfile(filename, FILETYPE_DATA, FILEACCESS_READ))
            == NULL)
    {
        // exit-point:
        TRACE_LOG("openfile(\"%s\") returned NULL.\n", filename);
        free(filename);
        return NULL;
    }

    nof_zucs_chars = 0;
    while ((parse_utf8_char_from_file(in)) != UEOF)
        nof_zucs_chars++;
    nof_zucs_chars++; // Add space for terminating zero (yes, really required).

    if (fsi->setfilepos(in, 0, SEEK_SET) == -1)
    {
        // exit-point:
        TRACE_LOG("setfilepos() returned -1.\n");
        fsi->closefile(in);
        free(filename);
        return NULL;
    }

    TRACE_LOG("Allocating space for %ld z_ucs chars.\n", nof_zucs_chars);

    // open-resource:
    if ((locale_data = malloc(nof_zucs_chars * sizeof(z_ucs))) == NULL)
    {
        // exit-point:
        TRACE_LOG("malloc(%ld) returned NULL.\n", nof_zucs_chars * sizeof(z_ucs));
        fsi->closefile(in);
        free(filename);
        return NULL;
    }

    TRACE_LOG("Locale data at %p, ends at %p.\n",
              locale_data, locale_data+nof_zucs_chars);

    // open-resource:
    if ((result = malloc(sizeof(locale_module))) == NULL)
    {
        // exit-point:
        free(locale_data);
        fsi->closefile(in);
        free(filename);
        return NULL;
    }

    TRACE_LOG("New module at %p.\n", result);

    result->locale_data = locale_data;
    TRACE_LOG("Locale data starts at %p.\n", locale_data);

    /* --- */

    // open-resource:
    lines = create_list();
    //printf("new list created: %p\n", lines);

    in_char = fsi->getchar(in);
    while (in_char != EOF)
    {
        linestart = locale_data;

        // Found a new line.
        fsi->ungetchar(in_char, in);

        for (;;)
        {
            input = input_char(in);

            if (input == Z_UCS_BACKSLASH)
            {
                //*locale_data++ = input;

                input = input_char(in);

                if (input == Z_UCS_BACKSLASH)
                {
                    *locale_data++ = Z_UCS_BACKSLASH;
                }
                else if (input == 'n')
                {
                    *locale_data++ = Z_UCS_NEWLINE;
                }
                else if (input == '{')
                {
                    *locale_data++ = Z_UCS_BACKSLASH;
                    *locale_data++ = (z_ucs)'{';

                    input = input_char(in);

                    if ((input < 0x30) && (input > 0x39))
                    {
                        fprintf(stderr, "Variable number expected.\n");
                        exit(EXIT_FAILURE);
                    }

                    *locale_data++ = input;

                    input = input_char(in);

                    if (
                        (input != (z_ucs)'s')
                        &&
                        (input != (z_ucs)'d')
                        &&
                        (input != (z_ucs)'x')
                        &&
                        (input != (z_ucs)'z')
                    )
                    {
                        fprintf(stderr, "Invalid parameter type.\n");
                        exit(EXIT_FAILURE);
                    }

                    *locale_data++ = input;

                    input = input_char(in);

                    if (input != (z_ucs)'}')
                    {
                        fprintf(stderr, "Expected '}'.\n");
                        exit(EXIT_FAILURE);
                    }

                    *locale_data++ = (z_ucs)'}';
                }
                else
                {
                    fprintf(stderr, "Undefined control sequence \\%c.\n",(char)input);
                    exit(EXIT_FAILURE);
                }
            }
            else if (input == Z_UCS_NEWLINE)
            {
                *locale_data++ = 0;
                TRACE_LOG("New line at %p.\n", linestart);
                add_list_element(lines, (void*)linestart);

                //TRACE_LOG_Z_UCS(linestart);

                break;
            }
            else
            {
                // Here we've found some "normal" output.
                *locale_data++ = (z_ucs)input;
            }
        }

        //messages_processed++;
        in_char = fsi->getchar(in);
    }

    *locale_data = 0;
    TRACE_LOG("Wirte last byte at %p.\n", locale_data);

    /* --- */

    TRACE_LOG("Read %d lines.\n", get_list_size(lines));

    // close-resource(l), open-resource(result->messages):
    result->nof_messages = get_list_size(lines);
    result->messages = (z_ucs**)delete_list_and_get_ptrs(lines);

    TRACE_LOG("Messages at %p.\n", result->messages);

    TRACE_LOG("First msg at %p.\n", result->messages[0]);

    if ((result->module_name = malloc(sizeof(z_ucs) * (z_ucs_len(module_name)+1)))
            == NULL)
    {
        // exit-point:
        free(result->messages);
        free(result);
        free(locale_data);
        fsi->closefile(in);
        free(filename);
        return NULL;
    }

    z_ucs_cpy(result->module_name, module_name);

    // close-resource:
    fsi->closefile(in);

    // close-resource:
    free(filename);

    TRACE_LOG("Returning new module at %p.\n", result);

    return result;
}