char * text_get_string_copy(const Text *text) { int num,i; char *str; num = 0; for (i=0;i<text->numlines;i++) { /* This is for allocation, so it should not use g_utf8_strlen() */ num += strlen(text_get_line(text, i))+1; } str = g_malloc(num); *str = 0; for (i=0;i<text->numlines;i++) { strcat(str, text_get_line(text, i)); if (i != (text->numlines-1)) { strcat(str, "\n"); } } return str; }
END_TEST START_TEST (test_text_line) { text *text; int i; char buf[128]; const char *p; int ret; int len; text = text_create (); fail_unless (text != NULL); for (i = 0; i < 120; i++) { sprintf (buf, "Line nr %d", i); ret = text_add_line (text, buf); fail_unless (ret == i + 1); fail_unless (text_nr_of_lines (text) == i + 1); } for (i = 0; i < 120; i++) { sprintf (buf, "Line nr %d", i); p = text_get_line (text, i, &len); fail_unless (p != NULL); fail_unless (strlen (buf) == len); fail_unless (strcmp (p, buf) == 0); } p = text_get_line (text, 500, &len); fail_unless (p == NULL); p = text_get_line (text, -50, &len); fail_unless (p == NULL); text_clear (text); fail_unless (text_nr_of_lines (text) == 0); ret = text_add_line (text, "\001"); fail_unless (ret < 0); fail_unless (text_nr_of_lines (text) == 0); ret = text_add_line (text, "\t"); fail_unless (ret == 1); fail_unless (text_nr_of_lines (text) == 1); p = text_get_line (text, 0, &len); fail_unless (p != NULL); fail_unless (len == 2); fail_unless (strcmp (p, " ") == 0); text_free (text); }
gboolean text_delete_key_handler(Focus *focus, ObjectChange ** change) { Text *text; int row, i; const char *utf; gunichar c; text = focus->text; row = text->cursor_row; if (text->cursor_pos >= text_get_line_strlen(text, row)) { if (row+1 < text->numlines) { *change = text_create_change(text, TYPE_JOIN_ROW, 'Q', text->cursor_pos, row, focus->obj); } else { return FALSE; } } else { utf = text_get_line(text, row); for (i = 0; i < text->cursor_pos; i++) utf = g_utf8_next_char (utf); c = g_utf8_get_char (utf); *change = text_create_change (text, TYPE_DELETE_FORWARD, c, text->cursor_pos, text->cursor_row, focus->obj); } text_delete_forward(text); return TRUE;; }
static void text_insert_char(Text *text, gunichar c) { gchar ch[7]; int unilen; int row; gchar *line, *str; gchar *utf8_before; gchar *str1; /* Make a string of the the char */ unilen = g_unichar_to_utf8 (c, ch); ch[unilen] = 0; row = text->cursor_row; /* Copy the before and after parts with the new char in between */ line = text_get_line(text, row); utf8_before = g_utf8_offset_to_pointer(line, (glong)(text->cursor_pos)); str1 = g_strndup(line, utf8_before - line); str = g_strconcat(str1, ch, utf8_before, NULL); text_set_line_text(text, row, str); g_free(str); g_free(str1); text->cursor_pos++; text->max_width = MAX(text->max_width, text_get_line_width(text, row)); }
static void text_split_line(Text *text) { int i; char *line; real width; gchar *utf8_before; gchar *str1, *str2; /* Split the lines at cursor_pos */ line = text_get_line(text, text->cursor_row); text_insert_line(text, text->cursor_row); utf8_before = g_utf8_offset_to_pointer(line, (glong)(text->cursor_pos)); str1 = g_strndup(line, utf8_before - line); str2 = g_strdup(utf8_before); /* Must copy before dealloc */ text_set_line_text(text, text->cursor_row, str1); text_set_line_text(text, text->cursor_row + 1, str2); g_free(str2); g_free(str1); text->cursor_row ++; text->cursor_pos = 0; width = 0.0; for (i=0;i<text->numlines;i++) { width = MAX(width, text_get_line_width(text, i)); } text->max_width = width; }
void text_draw(Text *text, DiaRenderer *renderer) { DIA_RENDERER_GET_CLASS(renderer)->draw_text(renderer, text); if ((renderer->is_interactive) && (text->focus.has_focus)) { real curs_x, curs_y; real str_width_first; real str_width_whole; Point p1, p2; real height = text->ascent+text->descent; curs_y = text->position.y - text->ascent + text->cursor_row*text->height; DIA_RENDERER_GET_CLASS(renderer)->set_font(renderer, text->font, text->height); str_width_first = DIA_RENDERER_GET_CLASS(renderer)->get_text_width(renderer, text_get_line(text, text->cursor_row), text->cursor_pos); str_width_whole = DIA_RENDERER_GET_CLASS(renderer)->get_text_width(renderer, text_get_line(text, text->cursor_row), text_get_line_strlen(text, text->cursor_row)); curs_x = text->position.x + str_width_first; switch (text->alignment) { case ALIGN_LEFT: break; case ALIGN_CENTER: curs_x -= str_width_whole / 2.0; break; case ALIGN_RIGHT: curs_x -= str_width_whole; break; } p1.x = curs_x; p1.y = curs_y; p2.x = curs_x; p2.y = curs_y + height; DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID); DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, height/CURSOR_HEIGHT_RATIO); DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &p1, &p2, &color_black); } }
static void text_join_lines(Text *text, int first_line) { gchar *combined_line; int len1; len1 = text_get_line_strlen(text, first_line); combined_line = g_strconcat(text_get_line(text, first_line), text_get_line(text, first_line + 1), NULL); text_delete_line(text, first_line); text_set_line_text(text, first_line, combined_line); g_free(combined_line); text->max_width = MAX(text->max_width, text_get_line_width(text, first_line)); text->cursor_row = first_line; text->cursor_pos = len1; }
static char *modem_read_old_version(char *version, size_t size) { ssize_t readlen; char buff[1024]; readlen = modem_send_at_command(MODEM_ATCMD_READ_VERSION, buff, sizeof(buff)); if (readlen < 0) { print_error("modem_send_at_command"); return NULL; } buff[readlen] = 0; text_get_line(buff, version, 3); return version; }
static void text_delete_backward(Text *text) { int row; int i; real width; gchar *line; gchar *utf8_before, *utf8_after; gchar *str1, *str; row = text->cursor_row; if (text->cursor_pos <= 0) { if (row > 0) text_join_lines(text, row-1); return; } line = text_get_line(text, row); utf8_before = g_utf8_offset_to_pointer(line, (glong)(text->cursor_pos - 1)); utf8_after = g_utf8_offset_to_pointer(utf8_before, 1); str1 = g_strndup(line, utf8_before - line); str = g_strconcat(str1, utf8_after, NULL); text_set_line_text(text, row, str); g_free(str); g_free(str1); text->cursor_pos --; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); width = 0.0; for (i = 0; i < text->numlines; i++) { width = MAX(width, text_get_line_width(text, i)); } text->max_width = width; }
END_TEST START_TEST (test_text_load) { text *text; int i; int ret; char buf[64]; const char *p; int len; text = text_load_file (CONFDIR "/text_WRONG.txt"); fail_unless (text == NULL); text = text_load_file (CONFDIR "/text_test.txt"); fail_unless (text != NULL); for (i = 0; i < 120; i++) { sprintf (buf, " Line %d", i); p = text_get_line (text, i, &len); fail_unless (p != NULL); fail_unless (strlen (buf) == len, "%d len = %d != %d", i, len, strlen (buf)); fail_unless (strcmp (p, buf) == 0); } fail_unless (text_nr_of_lines (text) == 120); text_clear (text); fail_unless (text_nr_of_lines (text) == 0); ret = text_update_from_file (text, CONFDIR "/text_WRONG.txt"); fail_unless (ret < 0); ret = text_update_from_file (text, CONFDIR "/text_test.txt"); fail_unless (ret == 0); for (i = 0; i < 120; i++) { sprintf (buf, " Line %d", i); p = text_get_line (text, i, &len); fail_unless (p != NULL); fail_unless (strlen (buf) == len); fail_unless (strcmp (p, buf) == 0); } fail_unless (text_nr_of_lines (text) == 120); ret = text_update_from_file (text, CONFDIR "/text_test.txt"); fail_unless (ret == 0); for (i = 0; i < 120; i++) { sprintf (buf, " Line %d", i); p = text_get_line (text, i, &len); fail_unless (p != NULL); fail_unless (strlen (buf) == len); fail_unless (strcmp (p, buf) == 0); } fail_unless (text_nr_of_lines (text) == 120); ret = text_update_from_file (text, CONFDIR "/text_test_bad.txt"); fail_unless (ret < 0); text_free (text); }
static int text_key_event(Focus *focus, guint keystate, guint keyval, const gchar *str, int strlen, ObjectChange **change) { Text *text; int return_val = FALSE; int row, i; const char *utf; gunichar c; *change = NULL; text = focus->text; switch(keyval) { case GDK_Up: case GDK_KP_Up: text->cursor_row--; if (text->cursor_row<0) text->cursor_row = 0; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Down: case GDK_KP_Down: text->cursor_row++; if (text->cursor_row >= text->numlines) text->cursor_row = text->numlines - 1; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Left: case GDK_KP_Left: if (keystate & GDK_CONTROL_MASK) text_move_cursor(text, WORD_START); else text->cursor_pos--; if (text->cursor_pos<0) text->cursor_pos = 0; break; case GDK_Right: case GDK_KP_Right: if (keystate & GDK_CONTROL_MASK) text_move_cursor(text, WORD_END); else text->cursor_pos++; if (text->cursor_pos > text_get_line_strlen(text, text->cursor_row)) text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Home: case GDK_KP_Home: text->cursor_pos = 0; break; case GDK_End: case GDK_KP_End: text->cursor_pos = text_get_line_strlen(text, text->cursor_row); break; case GDK_Delete: case GDK_KP_Delete: return_val = text_delete_key_handler(focus, change); break; case GDK_BackSpace: return_val = TRUE; row = text->cursor_row; if (text->cursor_pos <= 0) { if (row > 0) { *change = text_create_change(text, TYPE_JOIN_ROW, 'Q', text_get_line_strlen(text, row-1), row-1, focus->obj); } else { return_val = FALSE; break; } } else { utf = text_get_line(text, row); for (i = 0; i < (text->cursor_pos - 1); i++) utf = g_utf8_next_char (utf); c = g_utf8_get_char (utf); *change = text_create_change (text, TYPE_DELETE_BACKWARD, c, text->cursor_pos - 1, text->cursor_row, focus->obj); } text_delete_backward(text); break; case GDK_Return: case GDK_KP_Enter: return_val = TRUE; *change = text_create_change(text, TYPE_SPLIT_ROW, 'Q', text->cursor_pos, text->cursor_row, focus->obj); text_split_line(text); break; case GDK_Shift_L: case GDK_Shift_R: case GDK_Control_L: case GDK_Control_R: case GDK_Alt_L: case GDK_Alt_R: case GDK_Meta_L: case GDK_Meta_R: return_val = FALSE; /* no text change for modifiers */ break; default: if (str || (strlen>0)) { if (str && *str == '\r') break; /* avoid putting junk into our string */ return_val = TRUE; *change = change_list_create(); for (utf = str; utf && *utf && strlen > 0 ; utf = g_utf8_next_char (utf), strlen--) { ObjectChange *step; c = g_utf8_get_char (utf); step = text_create_change (text, TYPE_INSERT_CHAR, c, text->cursor_pos, text->cursor_row, focus->obj); change_list_add (*change, step); text_insert_char (text, c); } } break; } return return_val; }
/* The renderer is only used to determine where the click is, so is not * required when no point is given. */ void text_set_cursor(Text *text, Point *clicked_point, DiaRenderer *renderer) { real str_width_whole; real str_width_first; real top; real start_x; int row; int i; if (clicked_point != NULL) { top = text->position.y - text->ascent; row = (int)floor((clicked_point->y - top) / text->height); if (row < 0) row = 0; if (row >= text->numlines) row = text->numlines - 1; text->cursor_row = row; text->cursor_pos = 0; if (!renderer->is_interactive) { g_warning("Internal error: Select gives non interactive renderer!\n" "val: %d\n", renderer->is_interactive); return; } DIA_RENDERER_GET_CLASS(renderer)->set_font(renderer, text->font, text->height); str_width_whole = DIA_RENDERER_GET_CLASS(renderer)->get_text_width(renderer, text_get_line(text, row), text_get_line_strlen(text, row)); start_x = text->position.x; switch (text->alignment) { case ALIGN_LEFT: break; case ALIGN_CENTER: start_x -= str_width_whole / 2.0; break; case ALIGN_RIGHT: start_x -= str_width_whole; break; } /* Do an ugly linear search for the cursor index: TODO: Change to binary search */ for (i=0;i<=text_get_line_strlen(text, row);i++) { str_width_first = DIA_RENDERER_GET_CLASS(renderer)->get_text_width(renderer, text_get_line(text, row), i); if (clicked_point->x - start_x >= str_width_first) { text->cursor_pos = i; } else { return; } } text->cursor_pos = text_get_line_strlen(text, row); } else { /* No clicked point, leave cursor where it is */ } }