示例#1
0
void
line_breaker_rep::break_string (line_item item, path pos, int i, space spc) {
  int j;
  string item_s= item->b->get_leaf_string ();
  array<int> hp= item->lan->get_hyphens (item_s);

  if ((item->b->w() > line_width) || (!is_atom (pos))) {
    j= get_position (item->b->get_leaf_font (), item_s, line_width- spc->def);
    for (j= min (j+2, N(hp)-1); j>=0; j--)
      if (hp[j] < HYPH_INVALID) {
	line_item item1, item2;
	hyphenate (item, j, item1, item2);
	path next= (i==pos->item)? pos * j: path (i, j);
	space spc_hyph= spc+ space (item1->b->w());
	if (spc_hyph->min <= line_width) {
	  propose_break (next, pos, hp[j], spc_hyph->min);
	  break;
	}
      }
  }
  else {
    for (j=0; j<N(hp); j++)
      if (hp[j] < HYPH_INVALID) {
	line_item item1, item2;
	hyphenate (item, j, item1, item2);
	path next= (i==pos->item)? pos * j: path (i, j);
	space spc_hyph= spc+ space (item1->b->w());
	(void) propose_break (next, pos, hp[j], spc_hyph);
      }
  }
}
示例#2
0
文件: isn.c 项目: DBInsight/postgres
static inline void
ean2ISMN(char *isn)
{
	/* the number should come in this format: 979-0-000-00000-0 */
	/* Just strip the first part and change the first digit ('0') to 'M' */
	hyphenate(isn, isn + 4, NULL, NULL);
	isn[0] = 'M';
}
示例#3
0
void paragraph::considerHyphenation(flags & flgs)
    {
    bool vowel = false;
    bool nonAlphaFound = false;
    int cnt = 0;
    int j = 0;
    int punkpos = -1;
    bool locAllLower = true;
    bool locAllUpper = true;
    for(j = 0;j != waited && isFlatSpace(circularBuffer[j]);++j)
        circularBuffer[j] = ' ';
    for(;j != waited;++j)
        {
        ++cnt;
        int k = circularBuffer[j];
        if(isAlpha(k))
            {
            if(!isLower(k))
                locAllLower = false;
            if(!isUpper(k))
                locAllUpper = false;
            }
        else if(k != '-')
            {
            if(punkpos < 0 && isPunct(k))
                punkpos = cnt;
            else if(!isSemiPunct(k))
                nonAlphaFound = true;
            break;
            }
        if(isVowel(k))
            vowel = true;
        }
    if(dropHyphen)
        { // Require agreement of case
        if(allLower)
            {
            if(!locAllLower)
                dropHyphen = false;
            }
        else
            {
            if(!locAllUpper)
                dropHyphen = false;
            }
        }
    if((!nonAlphaFound && cnt >= 2 && punkpos < 0) || punkpos == cnt)
        {
        if(!dropHyphen || !vowel)
            Segment.Put(file,'-',flgs);
        for(j = 0;j != waited;++j)
            Segment.Put(file,circularBuffer[j],flgs);
        }
    else
        hyphenate(flgs);
    }
示例#4
0
char * HfstHyphenator::hyphenate(const wchar_t * word,
								 size_t wlen) {
	if (wlen > LIBVOIKKO_MAX_WORD_CHARS) {
		return 0;
	}
	char * wordUtf8 = StringUtils::utf8FromUcs4(word, wlen);
	char * result = hyphenate(wordUtf8);
	delete[] wordUtf8;
	return result;
}
示例#5
0
void
line_breaker_rep::process (path pos) {
  int i;
  space spc;
  line_item first;

  first= a[pos->item];
  if (pos == path (start)) spc= space (first_spc+ first->b->w());
  else {
    path p= pos;
    while (!is_atom (p)) {
      line_item item1, item2;
      p= p->next;
      hyphenate (first, p->item, item1, item2);
      first= item2;
    }
    spc= space (first->b->w());
  }

  if ((pass>1) || (best[pos]->pen < HYPH_INVALID)) {
    // cout << "Process " << pos << ": " << first << "\n";
    for (i=pos->item; i<end; i++) {
      line_item item= a[i];
      if (i == pos->item) item= first;
      else spc= spc+ a[i-1]->spc+ space (item->b->w());
      if ((spc->max > line_width) &&
	  (item->type == STRING_ITEM) &&
	  (N(item->b->get_leaf_string ())>4))
	break_string (item, pos, i, spc+ space (-item->b->w()));
      if (item->penalty < HYPH_INVALID)
	if (propose_break (path (i+1), pos, item->penalty, spc))
	  break;
      if ((item->type == CONTROL_ITEM) &&
	  (item->t == LINE_BREAK) &&
	  (spc->min < line_width))
	if (propose_break (path (i+1), pos, 0, space (line_width)))
	  break;
    }
    if (i==end) {
      line_width -= last_spc;
      propose_break (path (i), pos, 0, spc);
      line_width += last_spc;
    }
  }

  if (first->type == STRING_ITEM) {
    string first_s= first->b->get_leaf_string ();
    int n= N(first_s);
    if (n>4)
      for (i=0; i<n-1; i++)
	if (best-> contains (pos * i))
	  process (pos * i);
  }
}
示例#6
0
文件: isn.c 项目: DBInsight/postgres
static inline void
ean2ISSN(char *isn)
{
	unsigned	check;

	/* the number should come in this format: 977-0000-000-00-0 */
	/* Strip the first part, crop, and calculate the new check digit */
	hyphenate(isn, isn + 4, NULL, NULL);
	check = weight_checkdig(isn, 8);
	if (check == 10)
		isn[8] = 'X';
	else
		isn[8] = check + '0';
	isn[9] = '\0';
}
示例#7
0
文件: isn.c 项目: DBInsight/postgres
/*
 * ean2UPC/ISxN --- Convert in-place a normalized EAN13 string to the corresponding
 *					UPC/ISxN string number. Assumes the input string is normalized.
 */
static inline void
ean2ISBN(char *isn)
{
	char	   *aux;
	unsigned	check;

	/* the number should come in this format: 978-0-000-00000-0 */
	/* Strip the first part and calculate the new check digit */
	hyphenate(isn, isn + 4, NULL, NULL);
	check = weight_checkdig(isn, 10);
	aux = strchr(isn, '\0');
	while (!isdigit((unsigned char) *--aux));
	if (check == 10)
		*aux = 'X';
	else
		*aux = check + '0';
}
示例#8
0
ZLTextHyphenationInfo ZLTextHyphenator::info(const ZLTextWord &word) const {
	ZLUnicodeUtil::Ucs4String ucs4Vector;
	ZLUnicodeUtil::utf8ToUcs4(ucs4Vector, word.Data, word.Size, word.Length);

	ZLUnicodeUtil::Ucs4String pattern;
	pattern.clear();
	pattern.reserve(word.Length + 2);

	static std::vector<unsigned char> isLetter;
	isLetter.clear();
	isLetter.reserve(word.Length);

	pattern.push_back(' ');
	for (unsigned int i = 0; i < ucs4Vector.size(); ++i) {
		ZLUnicodeUtil::Ucs4Char symbol = ucs4Vector[i];
		// TODO: get special symbols from pattern file
		bool letter = (symbol == '\'') || (symbol == '^') || ZLUnicodeUtil::isLetter(symbol);
		isLetter.push_back(letter);
		pattern.push_back(letter ? ZLUnicodeUtil::toLower(symbol) : ' ');
	}
	pattern.push_back(' ');

	ZLTextHyphenationInfo info(word.Length + 2);
	hyphenate(pattern, info.myMask, word.Length + 2);

	for (int i = 0; i < word.Length + 1; ++i) {
		if ((i < 2) || (i > word.Length - 2)) {
			info.myMask[i] = false;
		} else if (ucs4Vector[i - 1] == '-') {
			info.myMask[i] = (i >= 3) &&
				(isLetter[i - 3] || (ucs4Vector[i - 3] == '-')) &&
				(isLetter[i - 2] || (ucs4Vector[i - 2] == '-')) &&
				(isLetter[i] || (ucs4Vector[i] == '-')) &&
				(isLetter[i + 1] || (ucs4Vector[i + 1] == '-'));
		} else {
			info.myMask[i] = info.myMask[i] &&
				isLetter[i - 2] &&
				isLetter[i - 1] &&
				isLetter[i] &&
				isLetter[i + 1];
		}
	}

	return info;
}
示例#9
0
文件: isn.c 项目: adam8157/gpdb
/*
 * ean2UPC/ISxN --- Convert in-place a normalized EAN13 string to the corresponding
 *					UPC/ISxN string number. Assumes the input string is normalized.
 */
static inline void
ean2ISBN(char *isn)
{
	char	   *aux;
	unsigned	check;

	/*
	 * The number should come in this format: 978-0-000-00000-0
	 * or may be an ISBN-13 number, 979-..., which does not have a short
	 * representation. Do the short output version if possible.
	 */
	if (strncmp("978-", isn, 4) == 0)
	{
		/* Strip the first part and calculate the new check digit */
		hyphenate(isn, isn + 4, NULL, NULL);
		check = weight_checkdig(isn, 10);
		aux = strchr(isn, '\0');
		while (!isdigit((unsigned char) *--aux));
		if (check == 10)
			*aux = 'X';
		else
			*aux = check + '0';
	}
}
示例#10
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;
}
示例#11
0
void
try_hyph ()
{
	int	c, j;
	ptr	prev_p, p, q;
	
	prev_p = cur_p;
	p = link(cur_p);
	if (p != null) {
		loop {
			if (is_char_node(p)) {
				c = character(p);
				hf = font(p);
			} else if (type(p) == LIGATURE_NODE) {
				if (lig_ptr(p) == null)
					goto contin;
				q = lig_ptr(p);
				c = character(q);
				hf = font(q);
			} else if (type(p) == KERN_NODE
				&& subtype(p) == NORMAL) {
				goto contin;
			} else if (type(p) == WHATSIT_NODE) {
				try_hyph_whatsit(p);
				goto contin;
			} else {
				goto done1;
			}
			if (lc_code(c) != 0) {
				if (lc_code(c) == c || uc_hyph > 0) {
					goto done2;
				} else {
					goto done1;
				}
			}
		contin:
			prev_p = p;
			p = link(p);
		}
	done2:
		hyf_char = hyphen_char(hf);
		if (hyf_char < 0 || hyf_char > 255)
			goto done1;
		ha = prev_p;
		if (l_hyf + r_hyf > 63)
			goto done1;
		hn = 0;
		loop {
			if (is_char_node(p)) {
				if (font(p) != hf)
					goto done3;
				c = character(p);
				if (lc_code(c) == 0 || hn == 63)
					goto done3;
				hb = p;
				incr(hn);
				hu[hn] = c;
				hc[hn] = lc_code(c);
			} else if (type(p) == LIGATURE_NODE) {
				if (font(lig_char(p)) != hf)
					goto done3;
				j = hn;
				q = lig_ptr(p);
				while (q != null) {
					c = character(q);
					if (lc_code(c) == 0 || j == 63)
						goto done3;
					incr(j);
					hu[j] = c;
					hc[j] = lc_code(c);
					q = link(q);
				}
				hb = p;
				hn = j;
			} else if (type(p) != KERN_NODE
				|| subtype(p) != NORMAL) {
				goto done3;
			}
			p = link(p);
		}
	done3:
		if (hn < l_hyf + r_hyf)
			goto done1;
		loop {
			if (!is_char_node(p)) {
				switch (type(p))
				{
				case LIGATURE_NODE:
					break;

				case KERN_NODE:
					if (subtype(p) != NORMAL)
						goto done4;
					break;

				case WHATSIT_NODE:
				case GLUE_NODE:
				case PENALTY_NODE:
				case INS_NODE:
				case ADJUST_NODE:
				case MARK_NODE:
					goto done4;
				
				default: 
					goto done1;
				}
			}
			p = link(p);
		}

	done4:
		hyphenate();
	}
示例#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_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;
}
示例#13
0
path
line_breaker_rep::next_ragged_break (path pos) {
  int       cur_nr  = pos->item;
  line_item cur_item= a[cur_nr];
  SI        cur_spc;

  if (pos == path (start)) cur_spc= first_spc+ cur_item->b->w();
  else {
    path p= pos;
    while (!is_atom (p)) {
      line_item item1, item2;
      p= p->next;
      hyphenate (cur_item, p->item, item1, item2);
      cur_item= item2;
    }
    cur_spc= cur_item->b->w();
  }
  
  line_item first= cur_item;
  while (true) {
    cur_spc += cur_item->spc->def;
    if ((++cur_nr)==end) break;
    cur_item = a[cur_nr];
    cur_spc += cur_item->b->w();
    if (cur_spc > line_width) {
      // cout << "Overfull " << cur_spc << ", " << line_width << "\n";
      break;
    }
  }

  while (true) {
    if (cur_nr<end) {
      cur_spc -= cur_item->b->w();
      if ((cur_spc <= line_width) &&
	  (cur_item->type==STRING_ITEM)) {
	string s= cur_item->b->get_leaf_string ();
	if (N(s)>4) {
	  array<int> hp= cur_item->lan->get_hyphens (s);
	  int i= get_position (cur_item->b->get_leaf_font (),
			       s, line_width- cur_spc);
	  for (i= min (i+1, N(hp)-1); i>=0; i--)
	    if (hp[i] < HYPH_INVALID) {
	      line_item item1, item2;
	      hyphenate (cur_item, i, item1, item2);
	      if (cur_spc+item1->b->w() <= line_width)
		return (cur_nr>pos->item)?
		  path (cur_nr, i): pos * i;
	    }
	}
      }
    }
    if ((--cur_nr)<pos->item) {
      do cur_nr++;
      while ((cur_nr<end) && (a[cur_nr]->penalty >= HYPH_INVALID));
      if (cur_nr<end) cur_nr++;
      empty_line_fix (first, pos, cur_nr);
      return path (cur_nr);
    }
    cur_item = (cur_nr==pos->item? first: a[cur_nr]);
    cur_spc -= cur_item->spc->def;
    if ((cur_spc <= line_width) &&
	((cur_item->penalty < HYPH_INVALID) || (cur_nr==end-1))) {
      cur_nr++;
      empty_line_fix (first, pos, cur_nr);
      return path (cur_nr);
    }
  }
}
示例#14
0
文件: isn.c 项目: DBInsight/postgres
/*
 * ean2string --- Try to convert an ean13 number to a hyphenated string.
 *				  Assumes there's enough space in result to hold
 *				  the string (maximum MAXEAN13LEN+1 bytes)
 *				  This doesn't verify for a valid check digit.
 *
 * If shortType is true, the returned string is in the old ISxN short format.
 * If errorOK is false, ereport a useful error message if the string is bad.
 * If errorOK is true, just return "false" for bad input.
 */
static bool
ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
{
	const char *(*TABLE)[2];
	const unsigned (*TABLE_index)[2];
	enum isn_type type = INVALID;

	char	   *aux;
	unsigned	digval;
	unsigned	search;
	char		valid = '\0';	/* was the number initially written with a
								 * valid check digit? */

	TABLE_index = ISBN_index;

	if ((ean & 1) != 0)
		valid = '!';
	ean >>= 1;
	/* verify it's in the EAN13 range */
	if (ean > UINT64CONST(9999999999999))
		goto eantoobig;

	/* convert the number */
	search = 0;
	aux = result + MAXEAN13LEN;
	*aux = '\0';				/* terminate string; aux points to last digit */
	*--aux = valid;				/* append '!' for numbers with invalid but
								 * corrected check digit */
	do
	{
		digval = (unsigned) (ean % 10); /* get the decimal value */
		ean /= 10;				/* get next digit */
		*--aux = (char) (digval + '0'); /* convert to ascii and store */
		if (search == 0)
			*--aux = '-';		/* the check digit is always there */
	} while (ean && search++ < 13);
	while (search++ < 13)
		*--aux = '0';			/* fill the remaining EAN13 with '0' */

	/* The string should be in this form: ???DDDDDDDDDDDD-D" */
	search = hyphenate(result, result + 3, EAN13_range, EAN13_index);

	/* verify it's a logically valid EAN13 */
	if (search == 0)
	{
		search = hyphenate(result, result + 3, NULL, NULL);
		goto okay;
	}

	/* find out what type of hyphenation is needed: */
	if (strncmp("978-", result, search) == 0)
	{							/* ISBN -13 978-range */
		/* The string should be in this form: 978-??000000000-0" */
		type = ISBN;
		TABLE = ISBN_range;
		TABLE_index = ISBN_index;
	}
	else if (strncmp("977-", result, search) == 0)
	{							/* ISSN */
		/* The string should be in this form: 977-??000000000-0" */
		type = ISSN;
		TABLE = ISSN_range;
		TABLE_index = ISSN_index;
	}
	else if (strncmp("979-0", result, search + 1) == 0)
	{							/* ISMN */
		/* The string should be in this form: 979-0?000000000-0" */
		type = ISMN;
		TABLE = ISMN_range;
		TABLE_index = ISMN_index;
	}
	else if (strncmp("979-", result, search) == 0)
	{							/* ISBN-13 979-range */
		/* The string should be in this form: 979-??000000000-0" */
		type = ISBN;
		TABLE = ISBN_range_new;
		TABLE_index = ISBN_index_new;
	}
	else if (*result == '0')
	{							/* UPC */
		/* The string should be in this form: 000-00000000000-0" */
		type = UPC;
		TABLE = UPC_range;
		TABLE_index = UPC_index;
	}
	else
	{
		type = EAN13;
		TABLE = NULL;
		TABLE_index = NULL;
	}

	/* verify it's a logically valid EAN13/UPC/ISxN */
	digval = search;
	search = hyphenate(result + digval, result + digval + 2, TABLE, TABLE_index);

	/* verify it's a valid EAN13 */
	if (search == 0)
	{
		search = hyphenate(result + digval, result + digval + 2, NULL, NULL);
		goto okay;
	}

okay:
	/* convert to the old short type: */
	if (shortType)
		switch (type)
		{
			case ISBN:
				ean2ISBN(result);
				break;
			case ISMN:
				ean2ISMN(result);
				break;
			case ISSN:
				ean2ISSN(result);
				break;
			case UPC:
				ean2UPC(result);
				break;
			default:
				break;
		}
	return true;

eantoobig:
	if (!errorOK)
	{
		char		eanbuf[64];

		/*
		 * Format the number separately to keep the machine-dependent format
		 * code out of the translatable message text
		 */
		snprintf(eanbuf, sizeof(eanbuf), EAN13_FORMAT, ean);
		ereport(ERROR,
				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
				 errmsg("value \"%s\" is out of range for %s type",
						eanbuf, isn_names[type])));
	}
	return false;
}
示例#15
0
main(int argc, char *argv[])
{
    int c, done, i, j, h, l, len;

    unsigned char *q;
    int hyf[LINE_LENGTH];
    int hif[MAXPAT];
    unsigned char syllable[LINE_LENGTH];
    char *patterns_file = NULL, *prog_name;
    struct pattern *p;
    void syllabe(int, unsigned char *, unsigned char *);

    prog_name = argv[0];
    while (--argc > 0 && (*++argv)[0] == '-') {
        done=0;
        while ((!done) && (c = *++argv[0]))  /* allow -bcK like options */
            switch (c) {
            case 'd':
                if (*++argv[0] == '\0') {
                    argc--;
                    argv++;
                }
                logging = atoi(argv[0]);
                done = 1;
                break;
            case 'L':
                if (*++argv[0] == '\0') {
                    argc--;
                    argv++;
                }
                leftmin = atoi(argv[0]);
                done = 1;
                break;
            case 'R':
                if (*++argv[0] == '\0') {
                    argc--;
                    argv++;
                }
                rightmin = atoi(argv[0]);
                done = 1;
                break;
            default:
                fprintf(stderr, "%s: %c illegal option\n", prog_name, c);
                exit(1);
            }
    }

    if (argc != 1) usage(prog_name);

    patterns_file = argv[0];

    linep = line;
    read_patterns(patterns_file);

    *linep = '.';
    while (gets(linep+1)) {
        /* look first for an exception */
        i = search_exception(linep+1);
        if (i >= 0) {
            j=0;
            l = exclusive_length(exc[i]);
            for (q=exc[i]; *q != '\0'; q++) {
                if (*q != '-') {
                    putchar(*q);
                    j++;
                }
                else if (j>=leftmin && j <= l-rightmin)
                    putchar('-');
            }
            putchar('\n');
            continue;
        }

        len = strlen(linep+1);
        line[len+1] = '.';
        line[len+2] = '\0';
        for (i=0; i<=len+2; i++) hyf[i] = 0;
        for (i=0; i<=len; i++) {
            syllable[0] = tolow[line[i]];

            /* look for single alfanumeric letter first */
            syllable[1] = '\0';
            if (alpha[syllable[0]]) {
                j = key(syllable);
                if (j >= 0 && ((p = entry[j]) != NULL)) {
                    unpackhyfs(1, hif, p->hyfens);
                    hyf[i] = max(hyf[i], hif[0]);
                    hyf[i+1] = max(hyf[i+1], hif[1]);
                    if (logging & PATTERNS) {
                        showhyfs(syllable, hif);
                        putchar('\n');
                    }
                }
            }

            /* loop through list of patterns and match them with current
                   word */
            syllable[1] = tolow[line[i+1]];
            syllable[2] = '\0';
            j = key(syllable);
            if (j < 0 || (p = entry[j]) == NULL) continue;
            do {
                l = strlen((char *) p->name);
                if (equal(&line[i+2], p->name, l) == 0) {
                    strcpy((char *) &syllable[2], (char *) p->name);
                    unpackhyfs(l+2, hif, p->hyfens);
                    for (h=0; h <= strlen((char *) syllable); h++)
                        hyf[i+h] = max(hyf[i+h], hif[h]);
                    if (logging & PATTERNS) {
                        showhyfs(syllable, hif);
                        putchar('\n');
                    }
                }
            }
            while (p=p->next);
        }
        if (logging & PATTERNS) {
            showhyfs(line, hyf);
            putchar('\n');
        }
        hyphenate(line, hyf);
    }
}
示例#16
0
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;
    }
  }
}
示例#17
0
void paragraph::PutHandlingWordWrap(const wint_t ch,flags & flgs) // Called from GetPut, GetPutBullet and doTheSegmentation
    {
    if(flgs.inhtmltag || !Option.wordUnwrap)
        {
        Segment.Put(file,ch,flgs); // //
        }
    else
        {
        if(isSentencePunct(ch))
            {
            ++flgs.punctuationFound;
            }
        else if(isSemiPunct(ch))
            {
            ++flgs.semiPunctuationFound;
            }
        else if(ch == '-')
            {
            ++flgs.hyphenFound;
            }

        if(ch == '\n' || ch == '\r')
            {
            switch(last)
                {
                case '\n':
                    if(wait)
                        {
                        hyphenate(flgs);
                        wait = 0;
                        flgs.punctuationFound = 0;
                        flgs.hyphenFound = 0;
                        spaceAfterHyphen = false;
                        }
                    flgs.semiPunctuationFound = 0;
                    Segment.Put(file,'\n',flgs);
                    break;
                case '-':
                    {
                    int k;
                    int nonSpaceCount = 0;
                    bool nonAlphaFound = false;
                    dropHyphen = false;
                    int i;
                    // skip previous spaces
                    for( i = ind(lastWordIndex-1)
                       ;    i != lastWordIndex 
                         && isSpace(circularBuffer[ind(i)])
                       ; i = dec(i)
                       )
                        ;
                    allLower = allUpper = true;
                    bool Upper = false; 
                    /* This variable introduces "lag" of one iteration in 
                    changing the value of allLower. In that way, the case of 
                    first character in the string (the one last checked)
                    doesn't matter.
                    Example:
                    blah blah. Da-
                    vid did it.
                    */

                    for (
                        ;    i != lastWordIndex 
                          && ( k = circularBuffer[ind(i)]
                             , !isSpace(k)
                             )
                        ; i = dec(i)
                        )  // Look at casing of last word in retrograde fashion.
                        {
                        ++nonSpaceCount;
                        if(Upper)
                            allLower = false;
                        if(isAlpha(k) && k != '-')
                            {
                            if(!isLower(k))
                                Upper = true;
                            if(!isUpper(k))
                                allUpper = false;
                            }
                        else if(k != '-')
                            {
                            nonAlphaFound = true;
                            break;
                            }
                        if(isVowel(k))  // We need at least one vowel to admit
                            //interpretation of hyphen as the 
                            // effect of word wrap.
                            dropHyphen = true;
                        }
                    if(dropHyphen && !allLower && !allUpper)
                        dropHyphen = false; // Mixed case -> keep hyphen
                    if(!nonAlphaFound && nonSpaceCount >= 2)
                        {
                        /**/
                        lastWordIndex = 0;
                        wait = (sizeof(circularBuffer)/sizeof(circularBuffer[0]));
                        waited = 0;
                        }
                    break;
                    }
                default:
                    {
                    if(wait)
                        {
                        considerHyphenation(flgs);
                        wait = 0;
                        flgs.punctuationFound = 0;
                        flgs.semiPunctuationFound = 0;
                        flgs.hyphenFound = 0;
                        spaceAfterHyphen = false;
                        }
                    Segment.Put(file,'\n',flgs); // Treat newline as a blank
                    }
                }
            }
        else
            {
            if(wait)
                {
                if(!isFlatSpace(ch))
                    {
                    if(waited == wait)
                        {
                        hyphenate(flgs);
                        wait = 0;
                        flgs.punctuationFound = 0;
                        flgs.semiPunctuationFound = 0;
                        flgs.hyphenFound = 0;
                        spaceAfterHyphen = false;
                        Segment.Put(file,ch,flgs);
                        }
                    else
                        {
                        circularBuffer[waited++] = (wchar_t)ch;
                        }
                    }
                else if(waited > 0)
                    {
                    considerHyphenation(flgs);
                    wait = 0;
                    flgs.punctuationFound = 0;
                    flgs.semiPunctuationFound = 0;
                    flgs.hyphenFound = 0;
                    spaceAfterHyphen = false;
                    Segment.Put(file,' ',flgs);
                    }
                }
            else
                {
                if(!flgs.hyphenFound)
                    Segment.Put(file,ch,flgs);
                }
            }
        }
    if(!isFlatSpace(ch))
        {
        if(ch != '\n' && !isSentencePunct(ch) && !wait)
            flgs.punctuationFound = 0;

        if(ch != '\n' && !isSemiPunct(ch) && !wait)
            flgs.semiPunctuationFound = 0;

        if(ch != '\n' && ch != '-' && flgs.hyphenFound && !wait) // A-bomb
            {
            int k;
            for(k = 0;k < flgs.hyphenFound;++k)
                Segment.Put(file,'-',flgs);
            if(spaceAfterHyphen)
                Segment.Put(file,' ',flgs);
            spaceAfterHyphen = false;
            flgs.hyphenFound = 0;
            Segment.Put(file,ch,flgs);
            }
        last = ch; ///
        }
    else if(flgs.hyphenFound && last != '\n')
        {
        spaceAfterHyphen = true;
        }

    if(!wait)
        {
        if(  !isFlatSpace(ch) 
          || !isFlatSpace(circularBuffer[ind(lastWordIndex-1)])
          )
            {
            circularBuffer[lastWordIndex] = (wchar_t)ch;
            lastWordIndex = inc(lastWordIndex);
            }
        }
    }