From 0bbb8fbbd0069be924e4106424f0e1f7bed5b381 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Fri, 19 Jul 2019 17:09:54 -0300 Subject: [PATCH] Working in the internal data for "smart paste" action. --- src/include/clipboard.h | 30 ++++++++++++++++++++++++++++++ src/selection/copy.c | 8 ++++++++ src/selection/datablock.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/linux/copy.c | 19 +++++++++++++++++-- v3270.cbp | 3 +++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 src/selection/datablock.c diff --git a/src/include/clipboard.h b/src/include/clipboard.h index 52ffa35..e1eed0a 100644 --- a/src/include/clipboard.h +++ b/src/include/clipboard.h @@ -45,14 +45,43 @@ CLIPBOARD_TYPE_TEXT, CLIPBOARD_TYPE_CSV, CLIPBOARD_TYPE_HTML, + CLIPBOARD_TYPE_V3270_UNPROTECTED }; + /// @brief Column from selection. struct ColumnDescription { unsigned int begin; unsigned int width; }; + /// @brief Selection data for sending to another application. + struct SelectionHeader + { + unsigned int length; ///< @brief Length of the data block. + unsigned int build; ///< @brief V3270 build id. + }; + + /// @brief Header of a list of fields. + struct SelectionBlockHeader + { + /// @brief Cursor address. + unsigned int cursor_address; + + /// @brief Number of records; + unsigned int records; + }; + + /// @brief Header for a field prefix. + struct SelectionFieldHeader + { + /// @brief Field address. + unsigned short baddr; + + /// @brief Field length. + unsigned short length; + + }; G_GNUC_INTERNAL void v3270_update_system_clipboard(GtkWidget *widget); G_GNUC_INTERNAL const char * v3270_update_selected_text(GtkWidget *widget, gboolean cut); @@ -63,6 +92,7 @@ G_GNUC_INTERNAL gchar * v3270_get_copy_as_text(v3270 * terminal); G_GNUC_INTERNAL gchar * v3270_get_copy_as_html(v3270 * terminal); G_GNUC_INTERNAL gchar * v3270_get_copy_as_table(v3270 * terminal, const gchar *delimiter); + G_GNUC_INTERNAL gchar * v3270_get_copy_as_data_block(v3270 * terminal); #endif // V3270_CLIPBOARD_H_INCLUDED diff --git a/src/selection/copy.c b/src/selection/copy.c index d94a1a7..f31304a 100644 --- a/src/selection/copy.c +++ b/src/selection/copy.c @@ -53,6 +53,14 @@ terminal->selection.format = format; do_copy(terminal,cut); +#ifdef DEBUG + { + // DEBUG DATA BLOCK + g_free(v3270_get_copy_as_data_block(terminal)); + } + +#endif // DEBUG + v3270_update_system_clipboard(widget); } diff --git a/src/selection/datablock.c b/src/selection/datablock.c new file mode 100644 index 0000000..d6623b2 --- /dev/null +++ b/src/selection/datablock.c @@ -0,0 +1,126 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + + #include + #include + + #define ALLOCATION_BLOCK_LENGTH 4096 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +/// @brief Get a list of all selected and unprotected contents. +static GList * getUnprotected(const lib3270_selection *selection) +{ + GList * list = NULL; + unsigned int row; + const lib3270_selection_element * element = selection->contents; + + for(row=0; row < selection->bounds.height; row++) + { + unsigned int col = 0; + + // Find selected and unprotected entries. + while(col < selection->bounds.width) + { + if((element[col].attribute.visual & LIB3270_ATTR_SELECTED) && !(element[col].attribute.field & LIB3270_FIELD_ATTRIBUTE_PROTECT)) + { + // Element is selected and not protected, get the length. + unsigned short start = col; + unsigned short length = 0; + while(col < selection->bounds.width) + { + if( !(element[col].attribute.visual & LIB3270_ATTR_SELECTED) || (element[col].attribute.field & LIB3270_FIELD_ATTRIBUTE_PROTECT)) + break; + + col++; + length++; + } + + debug( + "Row:%u Col: %u Length: %u", + row + selection->bounds.row, + start + selection->bounds.col, + (unsigned int) length + ); + + } + else + { + col++; + } + + } + + element += selection->bounds.width; + + } + + return list; +} + +gchar * v3270_get_copy_as_data_block(v3270 * terminal) +{ + + GList * element; + size_t szBlock = ALLOCATION_BLOCK_LENGTH + sizeof(struct SelectionHeader); + struct SelectionHeader * header = (struct SelectionHeader *) g_malloc0(szBlock+1); + + // Initialize header. + header->build = BUILD_DATE; + header->length = sizeof(struct SelectionHeader); + + // Insert elements. + for(element = terminal->selection.blocks; element; element = element->next) + { + lib3270_selection * block = ((lib3270_selection *) element->data); + size_t length = (block->bounds.height * block->bounds.width); + + if( (header->length+length) >= szBlock ) + { + szBlock += ALLOCATION_BLOCK_LENGTH + header->length + length; + header = (struct SelectionHeader *) g_realloc(header,szBlock+1); + } + + // Setup block header + struct SelectionBlockHeader * blockheader = (struct SelectionBlockHeader *) (((unsigned char *) header) + header->length); + header->length += sizeof(* blockheader); + + blockheader->cursor_address = block->cursor_address; + blockheader->records = 0; + + // Get values. + GList * values = getUnprotected((const lib3270_selection *) element->data); + + + g_list_free_full(values,g_free); + + } + + return (gchar *) g_realloc((gpointer) header, header->length+1); +} diff --git a/src/selection/linux/copy.c b/src/selection/linux/copy.c index bda1502..35799e6 100644 --- a/src/selection/linux/copy.c +++ b/src/selection/linux/copy.c @@ -90,6 +90,19 @@ static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionDa } break; + case CLIPBOARD_TYPE_V3270_UNPROTECTED: + { + g_autofree gchar *data = v3270_get_copy_as_data_block(terminal); + gtk_selection_data_set( + selection, + gdk_atom_intern_static_string("application/x-v3270-unprotected"), + 8, + (guchar *) data, + ((struct SelectionHeader *) data)->length + ); + } + break; + default: g_warning("Unexpected clipboard type %d\n",target); } @@ -114,8 +127,9 @@ void v3270_update_system_clipboard(GtkWidget *widget) // Reference: https://cpp.hotexamples.com/examples/-/-/g_list_insert_sorted/cpp-g_list_insert_sorted-function-examples.html // static const GtkTargetEntry internal_targets[] = { - { "text/csv", 0, CLIPBOARD_TYPE_CSV }, - { "text/html", 0, CLIPBOARD_TYPE_HTML } + { "text/csv", 0, CLIPBOARD_TYPE_CSV }, + { "text/html", 0, CLIPBOARD_TYPE_HTML }, + { "application/x-v3270-unprotected", 0, CLIPBOARD_TYPE_V3270_UNPROTECTED }, }; GtkTargetList * list = gtk_target_list_new(internal_targets, G_N_ELEMENTS(internal_targets)); @@ -153,3 +167,4 @@ void v3270_update_system_clipboard(GtkWidget *widget) g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, TRUE); } + diff --git a/v3270.cbp b/v3270.cbp index 5d72bf2..ecc6023 100644 --- a/v3270.cbp +++ b/v3270.cbp @@ -146,6 +146,9 @@ + + -- libgit2 0.21.2