static gsize
read_line (XeditDocumentInputStream *stream,
	   gchar                    *outbuf,
	   gsize                     space_left)
{
	GtkTextIter start, next, end;
	gchar *buf;
	gint bytes; /* int since it's what iter_get_offset returns */
	gsize bytes_to_write, newline_size, read;
	const gchar *newline;
	gboolean is_last;

	gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
					  &start,
					  stream->priv->pos);

	if (gtk_text_iter_is_end (&start))
		return 0;

	end = next = start;
	newline = get_new_line (stream);

	/* Check needed for empty lines */
	if (!gtk_text_iter_ends_line (&end))
		gtk_text_iter_forward_to_line_end (&end);

	gtk_text_iter_forward_line (&next);

	buf = gtk_text_iter_get_slice (&start, &end);

	/* the bytes of a line includes also the newline, so with the
	   offsets we remove the newline and we add the new newline size */
	bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;

	/* bytes_in_line includes the newlines, so we remove that assuming that
	   they are single byte characters */
	bytes = bytes - (gtk_text_iter_get_offset (&next) - gtk_text_iter_get_offset (&end));
	is_last = gtk_text_iter_is_end (&end);

	/* bytes_to_write contains the amount of bytes we would like to write.
	   This means its the amount of bytes in the line (without the newline
	   in the buffer) + the amount of bytes for the newline we want to
	   write (newline_size) */
	bytes_to_write = bytes;

	/* do not add the new newline_size for the last line */
	newline_size = get_new_line_size (stream);
	if (!is_last)
		bytes_to_write += newline_size;

	if (bytes_to_write > space_left)
	{
		gchar *ptr;
		gint char_offset;
		gint written;
		gsize to_write;

		/* Here the line does not fit in the buffer, we thus write
		   the amount of bytes we can still fit, storing the position
		   for the next read with the mark. Do not try to write the
		   new newline in this case, it will be handled in the next
		   iteration */
		to_write = MIN (space_left, bytes);
		ptr = buf;
		written = 0;
		char_offset = 0;

		while (written < to_write)
		{
			gint w;

			ptr = g_utf8_next_char (ptr);
			w = (ptr - buf);
			if (w > to_write)
			{
				break;
			}
			else
			{
				written = w;
				++char_offset;
			}
		}

		memcpy (outbuf, buf, written);

		/* Note: offset is one past what we wrote */
		gtk_text_iter_forward_chars (&start, char_offset);
		stream->priv->bytes_partial += written;
		read = written;
	}
	else
	{
		/* First just copy the bytes without the newline */
		memcpy (outbuf, buf, bytes);

		/* Then add the newline, but not for the last line */
		if (!is_last)
		{
			memcpy (outbuf + bytes, newline, newline_size);
		}

		start = next;
		stream->priv->bytes_partial = 0;
		read = bytes_to_write;
	}

	gtk_text_buffer_move_mark (stream->priv->buffer,
				   stream->priv->pos,
				   &start);

	g_free (buf);
	return read;
}
Example #2
0
//================================================================
  int GUI_edi_sel_ln (MemObj *mo, long lNr) {
//================================================================
/// \code
/// GUI_edi_sel_ln        select Line, set Curpos to Line.
/// Erste Zeile ist 1
/// rc -1: lNr does not exist
/// ACHTUNG: die ZeilenStart/Endposition wird aus dem mem gelesen !!!!
/// \endcode

  int   i1, irc=0, cNr;
  GtkTextIter it1, it2;


  // printf("GUI_edi_sel_ln %ld\n",lNr);

  // set GUI_ed1_view GUI_ed1_buff
  if(mo) {   // for internal call: mo=NULL
    if(GUI_ed1_decode(mo)) return -1;
  }

  GUI_ed1_stat = 1;
  // g_signal_handlers_block_by_func (   // geht ned ..
      // G_OBJECT (GUI_ed1_buff),
      // G_CALLBACK (GUI_ed1_cb2), GUI_ed1_ActObj->uFunc);


  --lNr;


  // get Iter at Linestart
  // DOES NOT WORK FOR LAST LINE !
  if(lNr == gtk_text_buffer_get_line_count (GUI_ed1_buff)) {
    irc = -2;
    goto L_exit;
  } else {
    gtk_text_buffer_get_iter_at_line (GUI_ed1_buff, &it1, lNr);
  }


  // move "insert" & "selection_bound"-marks
  gtk_text_buffer_place_cursor (GUI_ed1_buff, &it1);


  // get Iter at start of next Line
  // ++lNr;
  if(lNr == gtk_text_buffer_get_line_count (GUI_ed1_buff)) {
    gtk_text_buffer_get_end_iter (GUI_ed1_buff, &it2);
  } else {
    // gtk_text_buffer_get_iter_at_line (GUI_ed1_buff, &it2, lNr);
    cNr = gtk_text_iter_get_bytes_in_line (&it1);
      // printf(" cNr = %d\n",cNr);

    --cNr;  // LF
    gtk_text_iter_forward_chars (&it1, cNr);
  }

  // set mark
  gtk_text_buffer_move_mark_by_name (GUI_ed1_buff, "selection_bound", &it1);

  // scroll & focus
  GUI_edi_scroll_s (NULL);




  L_exit:
  GUI_ed1_stat = 0;
  // g_signal_handlers_unblock_by_func (    // geht ned ..
    // G_OBJECT (GUI_ed1_buff),
    // G_CALLBACK (GUI_ed1_cb2), GUI_ed1_ActObj->uFunc);

  // printf("ex GUI_edi_sel_ln\n");


  return irc;

}