diff --git a/src/include/clipboard.h b/src/include/clipboard.h index 1625cba..a710abf 100644 --- a/src/include/clipboard.h +++ b/src/include/clipboard.h @@ -44,6 +44,7 @@ { CLIPBOARD_TYPE_TEXT, CLIPBOARD_TYPE_CSV, + CLIPBOARD_TYPE_HTML, }; G_GNUC_INTERNAL void v3270_update_system_clipboard(GtkWidget *widget); @@ -51,6 +52,7 @@ /// @brief Get formatted contents as single text. 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); #endif // V3270_CLIPBOARD_H_INCLUDED diff --git a/src/selection/html.c b/src/selection/html.c new file mode 100644 index 0000000..64374d7 --- /dev/null +++ b/src/selection/html.c @@ -0,0 +1,150 @@ +/* + * "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 + #include + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static void get_element_colors(v3270 * terminal, unsigned short attr, gchar **fgColor, gchar **bgColor) +{ + GdkRGBA *fg; + GdkRGBA *bg = terminal->color+((attr & 0x00F0) >> 4); + + if(attr & LIB3270_ATTR_FIELD) + fg = terminal->color+(attr & 0x0003)+V3270_COLOR_FIELD; + else + fg = terminal->color+(attr & 0x000F); + + *fgColor = gdk_rgba_to_string(fg); + *bgColor = gdk_rgba_to_string(bg); + +} + +/// @brief Get formatted contents as HTML DIV. +static gchar * get_as_div(v3270 * terminal) +{ + GList * element = terminal->selection.blocks; + GString * string = g_string_new(""); + gchar * bgColor = gdk_rgba_to_string(terminal->color+V3270_COLOR_BACKGROUND); + gchar * fgColor; + + g_string_append_printf( + string, + "
", + terminal->font.family, + bgColor + ); + + g_free(bgColor); + + while(element) + { + lib3270_selection * block = ((lib3270_selection *) element->data); + unsigned int row, col, src = 0; + unsigned short flags = block->contents[0].flags; + + get_element_colors(terminal,flags,&fgColor,&bgColor); + + g_string_append_printf( + string, + "", + bgColor, + fgColor + ); + + g_free(bgColor); + g_free(fgColor); + +#ifdef DEBUG + g_string_append_c(string,'\n'); +#endif // DEBUG + + for(row=0; row < block->bounds.height; row++) + { + for(col=0; colbounds.width; col++) + { + if(flags != block->contents[src].flags) + { + flags = block->contents[src].flags; + + get_element_colors(terminal,flags,&fgColor,&bgColor); + + g_string_append_printf( + string, + "", + bgColor, + fgColor + ); + + g_free(bgColor); + g_free(fgColor); + + + } + + if(block->contents[src].flags & LIB3270_ATTR_SELECTED && !isspace(block->contents[src].chr)) + { + g_string_append_c(string,block->contents[src].chr); + } + else + { + g_string_append(string," "); + } + + src++; + + } + g_string_append(string,"
"); +#ifdef DEBUG + g_string_append_c(string,'\n'); +#endif // DEBUG + } + + g_string_append(string,"
"); + + element = g_list_next(element); + } + +#ifdef DEBUG + g_string_append_c(string,'\n'); +#endif // DEBUG + + g_string_append(string,"
"); + + return g_string_free(string,FALSE); + +} + +gchar * v3270_get_copy_as_html(v3270 * terminal) +{ + g_autofree char * text = get_as_div(terminal); + return g_convert(text, -1, "UTF-8", lib3270_get_display_charset(terminal->host), NULL, NULL, NULL); +} diff --git a/src/selection/linux/copy.c b/src/selection/linux/copy.c index ddee9b6..6d86938 100644 --- a/src/selection/linux/copy.c +++ b/src/selection/linux/copy.c @@ -65,7 +65,11 @@ static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionDa } else { +#ifdef DEBUG + text = v3270_get_copy_as_html(terminal); +#else text = v3270_get_copy_as_text(terminal); +#endif // DEBUG } gtk_selection_data_set_text(selection,text,-1); g_free(text); @@ -86,6 +90,20 @@ static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionDa } break; + case CLIPBOARD_TYPE_HTML: + { + g_autofree gchar *text = v3270_get_copy_as_html(terminal); + //debug("Selection:\n%s",text); + gtk_selection_data_set( + selection, + gdk_atom_intern_static_string("text/html"), + 8, + (guchar *) text, + strlen(text) + ); + } + break; + default: g_warning("Unexpected clipboard type %d\n",target); } @@ -110,7 +128,8 @@ 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/csv", 0, CLIPBOARD_TYPE_CSV }, + { "text/html", 0, CLIPBOARD_TYPE_HTML } }; GtkTargetList * list = gtk_target_list_new(internal_targets, G_N_ELEMENTS(internal_targets)); diff --git a/src/testprogram/testprogram.c b/src/testprogram/testprogram.c index 888f3e8..9ba4502 100644 --- a/src/testprogram/testprogram.c +++ b/src/testprogram/testprogram.c @@ -223,6 +223,11 @@ static void paste_clicked(GtkButton *button, GtkWidget *terminal) v3270_paste(terminal); } +static void copy_clicked(GtkButton *button, GtkWidget *terminal) +{ + v3270_copy_selection(terminal,V3270_SELECT_TEXT,FALSE); +} + static void color_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) { GtkWidget * dialog = v3270_dialog_new(terminal, _("Color setup"), _("_Save")); @@ -302,6 +307,7 @@ static void activate(GtkApplication* app, G_GNUC_UNUSED gpointer user_data) { { "gtk-home", G_CALLBACK(host_clicked), "Configure host" }, { "gtk-print", G_CALLBACK(print_clicked), "Print screen contents" }, { "gtk-harddisk", G_CALLBACK(ft_clicked), "Open file transfer dialog" }, + { "gtk-copy", G_CALLBACK(copy_clicked), "Copy data" }, { "gtk-paste", G_CALLBACK(paste_clicked), "Paste data" } }; diff --git a/v3270.cbp b/v3270.cbp index 615dd0a..e97b05e 100644 --- a/v3270.cbp +++ b/v3270.cbp @@ -146,6 +146,12 @@ + + + + @@ -158,6 +164,9 @@ + + -- libgit2 0.21.2