Commit 7cdd4cd9e39768592cf1c0ffcf48cf49b7243e9c

Authored by Perry Werneck
1 parent 864a22da
Exists in master and in 1 other branch develop

Reimplementing "copy-as-table" feature.

src/clipboard/copy.c
... ... @@ -105,6 +105,14 @@
105 105  
106 106 v3270_update_system_clipboard(widget);
107 107  
  108 +/*
  109 +#ifdef DEBUG
  110 + gchar *columns = v3270_get_copy_as_table(terminal,"---");
  111 + debug("Output:\n%s",columns);
  112 + g_free(columns);
  113 +#endif // DEBUG
  114 +*/
  115 +
108 116 }
109 117  
110 118 LIB3270_EXPORT void v3270_append_selection(GtkWidget *widget, gboolean cut)
... ...
src/clipboard/selection.c
... ... @@ -48,16 +48,42 @@ static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionDa
48 48 {
49 49 v3270 * terminal = GTK_V3270(obj);
50 50  
  51 + if(!terminal->selection.blocks)
  52 + {
  53 + return;
  54 + }
  55 +
51 56 switch(target)
52 57 {
53 58 case CLIPBOARD_TYPE_TEXT: // Get clipboard contents as text
54   -
55   - if(terminal->selection.blocks)
56 59 {
57   - g_autofree gchar * converted = v3270_get_copy_as_text(terminal);
58   - gtk_selection_data_set_text(selection,converted,-1);
  60 + gchar *text;
  61 +
  62 + if(terminal->selection.format == V3270_SELECT_TABLE)
  63 + {
  64 + text = v3270_get_copy_as_table(terminal,"\t");
  65 + }
  66 + else
  67 + {
  68 + text = v3270_get_copy_as_text(terminal);
  69 + }
  70 + gtk_selection_data_set_text(selection,text,-1);
  71 + g_free(text);
59 72 }
  73 + break;
60 74  
  75 + case CLIPBOARD_TYPE_CSV:
  76 + {
  77 + g_autofree gchar *text = v3270_get_copy_as_table(terminal,";");
  78 + debug("Selection:\n%s",text);
  79 + gtk_selection_data_set(
  80 + selection,
  81 + gdk_atom_intern_static_string("text/csv"),
  82 + 8,
  83 + (guchar *) text,
  84 + strlen(text)
  85 + );
  86 + }
61 87 break;
62 88  
63 89 default:
... ... @@ -117,17 +143,26 @@ void v3270_update_system_clipboard(GtkWidget *widget)
117 143 }
118 144  
119 145 // Has clipboard data, inform system.
  146 +//#ifdef DEBUG
  147 +// GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,GDK_SELECTION_PRIMARY);
  148 +//#else
120 149 GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,GDK_SELECTION_CLIPBOARD);
  150 +//#endif // DEBUG
121 151  
122 152 // Create target list
123 153 //
124 154 // Reference: https://cpp.hotexamples.com/examples/-/-/g_list_insert_sorted/cpp-g_list_insert_sorted-function-examples.html
125 155 //
126   - GtkTargetList * list = gtk_target_list_new(NULL, 0);
  156 + static const GtkTargetEntry internal_targets[] = {
  157 + { "text/csv", 0, CLIPBOARD_TYPE_CSV }
  158 + };
  159 +
  160 + GtkTargetList * list = gtk_target_list_new(internal_targets, G_N_ELEMENTS(internal_targets));
127 161 GtkTargetEntry * targets;
128 162 int n_targets;
129 163  
130 164 gtk_target_list_add_text_targets(list, CLIPBOARD_TYPE_TEXT);
  165 +
131 166 targets = gtk_target_table_new_from_list(list, &n_targets);
132 167  
133 168 #ifdef DEBUG
... ...
src/clipboard/table.c 0 → 100644
... ... @@ -0,0 +1,176 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 + #include <clipboard.h>
  31 + #include <ctype.h>
  32 + #include <lib3270/selection.h>
  33 +
  34 + struct ColumnDescription {
  35 + unsigned int begin;
  36 + unsigned int width;
  37 + };
  38 +
  39 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  40 +
  41 +/// @brief Check if column has data.
  42 +static gboolean hasDataOnColumn(v3270 * terminal, unsigned int col)
  43 +{
  44 + GList * element = terminal->selection.blocks;
  45 +
  46 + while(element)
  47 + {
  48 + lib3270_selection * block = ((lib3270_selection *) element->data);
  49 +
  50 + if( (col >= block->bounds.col) && ( col < (block->bounds.col + block->bounds.width)) )
  51 + {
  52 + unsigned int pos = col-block->bounds.col;
  53 + unsigned int row;
  54 +
  55 + for(row = 0; row < block->bounds.height; row++)
  56 + {
  57 + if(!isspace(block->contents[pos].chr))
  58 + {
  59 + return TRUE;
  60 + }
  61 + pos += block->bounds.width;
  62 + }
  63 +
  64 + }
  65 +
  66 + element = g_list_next(element);
  67 + }
  68 +
  69 + return FALSE;
  70 +}
  71 +
  72 +/// @brief Get column list.
  73 +GList * getColumns(v3270 * terminal)
  74 +{
  75 + unsigned int col = 0;
  76 + GList *rc = NULL;
  77 +
  78 + while(col < lib3270_get_width(terminal->host)) {
  79 +
  80 + // debug("col(%u): %s", col, hasDataOnColumn(terminal,col) ? "yes" : "no");
  81 +
  82 + // Get first column.
  83 + while(!hasDataOnColumn(terminal,col)) {
  84 + if(col >= lib3270_get_width(terminal->host))
  85 + return rc;
  86 + col++;
  87 + }
  88 +
  89 + // Alocate block, add it to list.
  90 + struct ColumnDescription * columndescription = g_new0(struct ColumnDescription,1);
  91 + columndescription->begin = col;
  92 + rc = g_list_append(rc,columndescription);
  93 +
  94 + // Get width.
  95 + while(hasDataOnColumn(terminal,col++)) {
  96 + columndescription->width++;
  97 + if(col >= lib3270_get_width(terminal->host))
  98 + return rc;
  99 + }
  100 + }
  101 +
  102 + return rc;
  103 +
  104 +}
  105 +
  106 +/// @brief Get formatted contents as single text.
  107 +gchar * v3270_get_copy_as_table(v3270 * terminal, const gchar *delimiter)
  108 +{
  109 + GString * string = g_string_new("");
  110 +
  111 + GList * columns = getColumns(terminal);
  112 +
  113 + debug("columns=%p",columns);
  114 +
  115 +#ifdef DEBUG
  116 + {
  117 + GList * column = columns;
  118 + while(column)
  119 + {
  120 + struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data;
  121 +
  122 + debug("Begin: %u Width: %u",columndescription->begin, columndescription->width);
  123 +
  124 + column = column->next;
  125 + }
  126 + }
  127 +#endif // DEBUG
  128 +
  129 + GList * element = terminal->selection.blocks;
  130 + unsigned int width = lib3270_get_width(terminal->host);
  131 + g_autofree gchar * line = g_malloc0(width+1);
  132 + GList * column;
  133 +
  134 + while(element)
  135 + {
  136 + lib3270_selection * block = ((lib3270_selection *) element->data);
  137 +
  138 + unsigned int row, col, src = 0;
  139 +
  140 + for(row=0; row < block->bounds.height; row++)
  141 + {
  142 +
  143 + // Build text line with selected data.
  144 + memset(line,' ',width);
  145 + for(col=0; col<block->bounds.width; col++)
  146 + {
  147 + if(block->contents[src].flags & LIB3270_ATTR_SELECTED)
  148 + {
  149 + line[block->bounds.col+col] = block->contents[src].chr;
  150 + }
  151 +
  152 + src++;
  153 + }
  154 +
  155 + debug("[%s]",line);
  156 +
  157 + // Extract columns
  158 + for(column = columns; column; column = column->next)
  159 + {
  160 + struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data;
  161 + g_string_append_len(string,line+columndescription->begin,columndescription->width);
  162 + if(column->next)
  163 + g_string_append(string,delimiter);
  164 + }
  165 + g_string_append(string,"\n");
  166 +
  167 + }
  168 +
  169 + element = g_list_next(element);
  170 + }
  171 +
  172 + g_list_free_full(columns,g_free);
  173 +
  174 + g_autofree char * text = g_string_free(string,FALSE);
  175 + return g_convert(text, -1, "UTF-8", lib3270_get_display_charset(terminal->host), NULL, NULL, NULL);
  176 +}
... ...
src/include/clipboard.h
... ... @@ -43,6 +43,7 @@
43 43 enum
44 44 {
45 45 CLIPBOARD_TYPE_TEXT,
  46 + CLIPBOARD_TYPE_CSV,
46 47 };
47 48  
48 49 G_GNUC_INTERNAL void v3270_update_system_clipboard(GtkWidget *widget);
... ... @@ -50,6 +51,7 @@
50 51  
51 52 /// @brief Get formatted contents as single text.
52 53 G_GNUC_INTERNAL gchar * v3270_get_copy_as_text(v3270 * terminal);
  54 + G_GNUC_INTERNAL gchar * v3270_get_copy_as_table(v3270 * terminal, const gchar *delimiter);
53 55  
54 56  
55 57 #endif // V3270_CLIPBOARD_H_INCLUDED
... ...
v3270.cbp
... ... @@ -51,6 +51,9 @@
51 51 <Unit filename="src/clipboard/selection.c">
52 52 <Option compilerVar="CC" />
53 53 </Unit>
  54 + <Unit filename="src/clipboard/table.c">
  55 + <Option compilerVar="CC" />
  56 + </Unit>
54 57 <Unit filename="src/clipboard/text.c">
55 58 <Option compilerVar="CC" />
56 59 </Unit>
... ...