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; }
//================================================================ 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; }