diff --git a/src/clipboard/copy.c b/src/clipboard/copy.c index ffebbe9..c190e93 100644 --- a/src/clipboard/copy.c +++ b/src/clipboard/copy.c @@ -30,57 +30,92 @@ #include #include - LIB3270_EXPORT void v3270_copy(GtkWidget *widget, V3270_SELECT_FORMAT format, gboolean cut) + static void do_copy(v3270 *terminal) { - - g_return_if_fail(GTK_IS_V3270(widget)); - - v3270 * terminal = GTK_V3270(widget); - - terminal->selection.format = format; - - // Have data? Clear it? - v3270_clear_clipboard(terminal); - // Get selection bounds. + unsigned int row; + unsigned int col; + unsigned int width; + unsigned int height; - if(lib3270_get_selection_rectangle(terminal->host, &terminal->selection.bounds.row, &terminal->selection.bounds.col, &terminal->selection.bounds.width, &terminal->selection.bounds.height) != 0) + if(lib3270_get_selection_rectangle(terminal->host, &row, &col, &width, &height) != 0) return; debug("Selecion rectangle starts on %u,%u with size of %ux%u", - terminal->selection.bounds.row, terminal->selection.bounds.col, - terminal->selection.bounds.width, terminal->selection.bounds.height + row, col, + width, height ); + // Allocate buffer + struct selection * selection = g_malloc0(sizeof(struct selection) + (sizeof(struct v3270_character) * (width * height))); + + selection->bounds.row = row; + selection->bounds.col = col; + selection->bounds.width = width; + selection->bounds.height = height; // Copy terminal buffer unsigned int r, c; - terminal->selection.contents = g_new0(struct v3270_character,(terminal->selection.bounds.width * terminal->selection.bounds.height)); - int pos = 0; - for(r=0;r < terminal->selection.bounds.height; r++) + for(r=0;r < selection->bounds.height; r++) { // Get starting address. - int baddr = lib3270_translate_to_address(terminal->host, terminal->selection.bounds.row+r+1, terminal->selection.bounds.col+1); + int baddr = lib3270_translate_to_address(terminal->host, selection->bounds.row+r+1, selection->bounds.col+1); if(baddr < 0) { - g_message("Can't convert coordinate %u,%d",terminal->selection.bounds.row+r+1,terminal->selection.bounds.col+1); + g_message("Can't convert coordinate %u,%d",selection->bounds.row+r+1,selection->bounds.col+1); gdk_display_beep(gdk_display_get_default()); return; } - for(c=0;c < terminal->selection.bounds.width; c++) + for(c=0;c < selection->bounds.width; c++) { - lib3270_get_contents(terminal->host,baddr,baddr,&terminal->selection.contents[pos].chr,&terminal->selection.contents[pos].attr); - debug("pos=%d baddr=%u char=%c",pos,baddr,terminal->selection.contents[pos].chr); + lib3270_get_contents(terminal->host,baddr,baddr,&selection->contents[pos].chr,&selection->contents[pos].attr); + debug("pos=%d baddr=%u char=%c",pos,baddr,selection->contents[pos].chr); pos++; baddr++; } } + terminal->selection.blocks = g_list_append(terminal->selection.blocks,selection); + + } + + LIB3270_EXPORT void v3270_copy_selection(GtkWidget *widget, V3270_SELECT_FORMAT format, gboolean cut) + { + g_return_if_fail(GTK_IS_V3270(widget)); + + v3270 * terminal = GTK_V3270(widget); + + // Have data? Clear it? + v3270_clear_clipboard(terminal); + + terminal->selection.format = format; + do_copy(terminal); + v3270_update_system_clipboard(widget); + if(cut) + { + lib3270_erase_selected(terminal->host); + } + } + + LIB3270_EXPORT void v3270_append_selection(GtkWidget *widget, gboolean cut) + { + g_return_if_fail(GTK_IS_V3270(widget)); + + v3270 * terminal = GTK_V3270(widget); + + do_copy(terminal); + + v3270_update_system_clipboard(widget); + + if(cut) + { + lib3270_erase_selected(terminal->host); + } } diff --git a/src/clipboard/selection.c b/src/clipboard/selection.c index a884b4a..e59fcab 100644 --- a/src/clipboard/selection.c +++ b/src/clipboard/selection.c @@ -44,45 +44,48 @@ static void clipboard_clear(G_GNUC_UNUSED GtkClipboard *clipboard, G_GNUC_UNUSED } /// @brief Get formatted contents as single text. -static gchar * get_selection_as_text(v3270 * terminal) +static gchar * get_copy_as_text(v3270 * terminal) { - // Has formatted clipboard, convert it to text. - unsigned int r, c, src = 0, dst = 0; - g_autofree char * text = g_malloc0( (terminal->selection.bounds.width * terminal->selection.bounds.height) + terminal->selection.bounds.height + 2); + GList * element = terminal->selection.blocks; + GString * string = g_string_new(""); - for(r=0;r < terminal->selection.bounds.height;r++) + while(element) { - for(c=0;cselection.bounds.width;c++) + struct selection * block = ((struct selection *) element->data); + unsigned int row, col, src = 0; + + for(row=0; row < block->bounds.height; row++) { - if(terminal->selection.contents[src].attr & LIB3270_ATTR_SELECTED) - text[dst++] = terminal->selection.contents[src].chr; + for(col=0; colbounds.width; col++) + { + if(block->contents[src].attr & LIB3270_ATTR_SELECTED) + g_string_append_c(string,block->contents[src].chr); + + src++; - src++; + } + g_string_append_c(string,'\n'); } - text[dst++] = '\n'; + element = g_list_next(element); } + g_autofree char * text = g_string_free(string,FALSE); return g_convert(text, -1, "UTF-8", lib3270_get_display_charset(terminal->host), NULL, NULL, NULL); + } static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionData *selection, guint target, GObject *obj) { v3270 * terminal = GTK_V3270(obj); - debug("%s target=%u selection from with %ux%u", - __FUNCTION__, - (unsigned int) target, - terminal->selection.bounds.width, terminal->selection.bounds.height - ); - switch(target) { - case CLIPBOARD_TYPE_TEXT: /* Get clipboard contents as text */ + case CLIPBOARD_TYPE_TEXT: // Get clipboard contents as text - if(terminal->selection.contents) + if(terminal->selection.blocks) { - g_autofree gchar * converted = get_selection_as_text(terminal); + g_autofree gchar * converted = get_copy_as_text(terminal); gtk_selection_data_set_text(selection,converted,-1); } @@ -101,15 +104,11 @@ static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionDa */ void v3270_clear_clipboard(v3270 *terminal) { - memset(&terminal->selection.bounds,0,sizeof(terminal->selection.bounds)); - - if(terminal->selection.contents) + if(terminal->selection.blocks) { - g_free(terminal->selection.contents); - terminal->selection.contents = NULL; + g_list_free_full(terminal->selection.blocks,g_free); + terminal->selection.blocks = NULL; } - -// terminal->selection.text = lib3270_free(terminal->selection.text); } /** @@ -122,11 +121,14 @@ void v3270_clear_clipboard(v3270 *terminal) */ LIB3270_EXPORT gchar * v3270_get_selected(GtkWidget *widget, gboolean cut) { - const char *text; + lib3270_autoptr(char) text = NULL; g_return_val_if_fail(GTK_IS_V3270(widget),NULL); - text = v3270_update_selected_text(widget,cut); + if(cut) + text = lib3270_cut_selected(GTK_V3270(widget)->host); + else + text = lib3270_get_selected(GTK_V3270(widget)->host); if(text) return g_convert(text, -1, "UTF-8", lib3270_get_display_charset(GTK_V3270(widget)->host), NULL, NULL, NULL); @@ -136,26 +138,13 @@ LIB3270_EXPORT gchar * v3270_get_selected(GtkWidget *widget, gboolean cut) LIB3270_EXPORT gchar * v3270_get_copy(GtkWidget *widget) { - /* - const char *text; g_return_val_if_fail(GTK_IS_V3270(widget),NULL); - - text = GTK_V3270(widget)->selection.text; - - if(!text) - text = v3270_update_selected_text(widget,FALSE); - - if(text) - return g_convert(text, -1, "UTF-8", lib3270_get_display_charset(GTK_V3270(widget)->host), NULL, NULL, NULL); - - */ - - return NULL; + return get_copy_as_text(GTK_V3270(widget)); } + /* LIB3270_EXPORT void v3270_set_copy(GtkWidget *widget, const gchar *text) { - /* v3270 * terminal; gchar * isotext; @@ -187,14 +176,14 @@ LIB3270_EXPORT void v3270_set_copy(GtkWidget *widget, const gchar *text) g_free(isotext); g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, TRUE); - */ } + */ void v3270_update_system_clipboard(GtkWidget *widget) { v3270 * terminal = GTK_V3270(widget); - if(!terminal->selection.bounds.width) + if(!terminal->selection.blocks) { // No clipboard data, return. g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, FALSE); @@ -215,7 +204,6 @@ void v3270_update_system_clipboard(GtkWidget *widget) gtk_target_list_add_text_targets(list, CLIPBOARD_TYPE_TEXT); targets = gtk_target_table_new_from_list(list, &n_targets); - #ifdef DEBUG { int ix; @@ -244,16 +232,6 @@ void v3270_update_system_clipboard(GtkWidget *widget) } -LIB3270_EXPORT void v3270_copy_text(GtkWidget *widget, V3270_SELECT_FORMAT mode, gboolean cut) -{ - /* - g_return_if_fail(GTK_IS_V3270(widget)); - GTK_V3270(widget)->selection.format = mode; - v3270_update_selected_text(widget,cut); - v3270_update_system_clipboard(widget); - */ -} - LIB3270_EXPORT void v3270_unselect(GtkWidget *widget) { v3270_disable_updates(widget); diff --git a/src/clipboard/text.c b/src/clipboard/text.c index 5351d8d..e195419 100644 --- a/src/clipboard/text.c +++ b/src/clipboard/text.c @@ -30,42 +30,6 @@ #include -LIB3270_EXPORT void v3270_copy_text_append(GtkWidget *widget) -{ - /* - v3270 * terminal; - char * str; - - g_return_if_fail(GTK_IS_V3270(widget)); - - terminal = GTK_V3270(widget); - - if(!terminal->selection.text) - { - // Clipboard is empty, do a single copy - v3270_copy_text(widget, V3270_SELECT_TEXT, FALSE); - return; - } - - str = lib3270_get_selected(terminal->host); - - if(str) - { - size_t len = strlen(terminal->selection.text)+strlen(str)+2; - - terminal->selection.text = lib3270_realloc(terminal->selection.text,len); - - strncat(terminal->selection.text,"\n",len); - strncat(terminal->selection.text,str,len); - - lib3270_free(str); - } - - v3270_update_system_clipboard(widget); - */ - -} - const char * v3270_update_selected_text(GtkWidget *widget, gboolean cut) { /* diff --git a/src/include/clipboard.h b/src/include/clipboard.h index 69bdda4..4c5e1ac 100644 --- a/src/include/clipboard.h +++ b/src/include/clipboard.h @@ -45,6 +45,20 @@ CLIPBOARD_TYPE_TEXT, }; + struct selection + { + struct { + unsigned int row; + unsigned int col; + unsigned int width; + unsigned int height; + + } bounds; ///< @brief Clipboard rectangle. + + struct v3270_character contents[1]; + + }; + G_GNUC_INTERNAL void v3270_update_system_clipboard(GtkWidget *widget); G_GNUC_INTERNAL const char * v3270_update_selected_text(GtkWidget *widget, gboolean cut); diff --git a/src/include/terminal.h b/src/include/terminal.h index bf4b52c..7841508 100644 --- a/src/include/terminal.h +++ b/src/include/terminal.h @@ -117,29 +117,12 @@ G_BEGIN_DECLS struct { - int baddr; ///< @brief Selection address. - V3270_SELECT_FORMAT format; ///< @brief Copy format. + int baddr; ///< @brief Selection address. + V3270_SELECT_FORMAT format; ///< @brief Copy format. - struct { - unsigned int row; - unsigned int col; - unsigned int width; - unsigned int height; + GList * blocks; ///< @brief Selection blocks. - } bounds; ///< @brief Clipboard rectangle. - - struct v3270_character * contents; - - } selection; - - /* - struct - { - V3270_SELECT_FORMAT format; ///< Copy format - char * text; ///< Clipboard contents (lib3270 charset) - int baddr; ///< Selection addr } selection; - */ LIB3270_POINTER pointer_id; unsigned char pointer; /**< Mouse pointer ID */ diff --git a/src/include/v3270.h b/src/include/v3270.h index 5b9e62e..2c7b2ec 100644 --- a/src/include/v3270.h +++ b/src/include/v3270.h @@ -192,7 +192,7 @@ LIB3270_EXPORT gchar * v3270_get_selected(GtkWidget *widget, gboolean cut); LIB3270_EXPORT gchar * v3270_get_copy(GtkWidget *widget); - LIB3270_EXPORT void v3270_set_copy(GtkWidget *widget, const gchar *text); +// LIB3270_EXPORT void v3270_set_copy(GtkWidget *widget, const gchar *text); LIB3270_EXPORT gchar * v3270_get_text(GtkWidget *widget,int offset, int len); LIB3270_EXPORT gchar * v3270_get_region(GtkWidget *widget, gint start_pos, gint end_pos, gboolean all); @@ -208,8 +208,9 @@ LIB3270_EXPORT void v3270_select_region(GtkWidget *widget, gint start, gint end); LIB3270_EXPORT void v3270_copy(GtkWidget *widget, V3270_SELECT_FORMAT mode, gboolean cut); - LIB3270_EXPORT void v3270_copy_text(GtkWidget *widget, V3270_SELECT_FORMAT mode, gboolean cut); - LIB3270_EXPORT void v3270_copy_text_append(GtkWidget *widget); + + LIB3270_EXPORT void v3270_copy_selection(GtkWidget *widget, V3270_SELECT_FORMAT mode, gboolean cut); + LIB3270_EXPORT void v3270_append_selection(GtkWidget *widget, gboolean cut); LIB3270_EXPORT void v3270_paste(GtkWidget *widget); LIB3270_EXPORT void v3270_paste_text(GtkWidget *widget, const gchar *text, const gchar *encoding); diff --git a/src/trace/exec.c b/src/trace/exec.c index 7cc39b9..5b96be7 100644 --- a/src/trace/exec.c +++ b/src/trace/exec.c @@ -183,11 +183,11 @@ if(!(*arg && g_ascii_strcasecmp(arg,"text"))) { // No argument or "text" copy text. - v3270_copy(widget, V3270_SELECT_TEXT, FALSE); + v3270_copy_selection(widget, V3270_SELECT_TEXT, FALSE); } else if(!g_ascii_strcasecmp(arg,"table")) { - v3270_copy(widget, V3270_SELECT_TABLE, FALSE); + v3270_copy_selection(widget, V3270_SELECT_TABLE, FALSE); } return 0; -- libgit2 0.21.2