From 5084f86c04e050eaaa0a20fffc1718d38670dd2f Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Thu, 18 Jul 2019 09:59:54 -0300 Subject: [PATCH] Improving clipboard management. --- Makefile.in | 4 ++-- src/clipboard/copy.c | 129 --------------------------------------------------------------------------------------------------------------------------------- src/clipboard/linux/paste.c | 43 ------------------------------------------- src/clipboard/selection.c | 219 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/clipboard/table.c | 176 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/clipboard/text.c | 197 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/clipboard/windows/paste.c | 58 ---------------------------------------------------------- src/include/v3270.h | 5 ++--- src/selection/copy.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/linux/paste.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/selection.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/table.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/text.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/selection/windows/paste.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/testprogram/testprogram.c | 8 +++++++- v3270.cbp | 36 ++++++++++++++++++------------------ 16 files changed, 892 insertions(+), 846 deletions(-) delete mode 100644 src/clipboard/copy.c delete mode 100644 src/clipboard/linux/paste.c delete mode 100644 src/clipboard/selection.c delete mode 100644 src/clipboard/table.c delete mode 100644 src/clipboard/text.c delete mode 100644 src/clipboard/windows/paste.c create mode 100644 src/selection/copy.c create mode 100644 src/selection/linux/paste.c create mode 100644 src/selection/selection.c create mode 100644 src/selection/table.c create mode 100644 src/selection/text.c create mode 100644 src/selection/windows/paste.c diff --git a/Makefile.in b/Makefile.in index 88e6f8c..67c6a2d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -33,8 +33,8 @@ SOURCES= \ $(wildcard src/terminal/@OSNAME@/*.rc) \ $(wildcard src/terminal/@OSNAME@/*.c) \ $(wildcard src/filetransfer/*.c) \ - $(wildcard src/clipboard/*.c) \ - $(wildcard src/clipboard/@OSNAME@/*.c) \ + $(wildcard src/selection/*.c) \ + $(wildcard src/selection/@OSNAME@/*.c) \ $(wildcard src/trace/*.c) \ $(wildcard src/dialogs/*.c) \ $(wildcard src/dialogs/@OSNAME@/*.c) \ diff --git a/src/clipboard/copy.c b/src/clipboard/copy.c deleted file mode 100644 index afef411..0000000 --- a/src/clipboard/copy.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * "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 - - static void do_copy(v3270 *terminal, gboolean cut) - { - lib3270_selection * selection = lib3270_get_selection(terminal->host,cut); - - if(selection) - { - terminal->selection.blocks = g_list_append(terminal->selection.blocks,selection); - } - - /* - // Get selection bounds. - unsigned int row; - unsigned int col; - unsigned int width; - unsigned int height; - - 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", - 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; - - int pos = 0; - for(r=0;r < selection->bounds.height; r++) - { - // Get starting address. - 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",selection->bounds.row+r+1,selection->bounds.col+1); - gdk_display_beep(gdk_display_get_default()); - return; - } - - for(c=0;c < selection->bounds.width; c++) - { - 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_selection(terminal); - - terminal->selection.format = format; - do_copy(terminal,cut); - - v3270_update_system_clipboard(widget); - -/* -#ifdef DEBUG - gchar *columns = v3270_get_copy_as_table(terminal,"---"); - debug("Output:\n%s",columns); - g_free(columns); -#endif // DEBUG -*/ - - } - - 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,cut); - - v3270_update_system_clipboard(widget); - - } - diff --git a/src/clipboard/linux/paste.c b/src/clipboard/linux/paste.c deleted file mode 100644 index 1ccf4fa..0000000 --- a/src/clipboard/linux/paste.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * "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 selection.c 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 - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - -static void text_received(G_GNUC_UNUSED GtkClipboard *clipboard, const gchar *text, GtkWidget *widget) -{ - v3270_paste_text(widget,text,"UTF-8"); -} - -LIB3270_EXPORT void v3270_paste(GtkWidget *widget) -{ - gtk_clipboard_request_text(gtk_widget_get_clipboard(widget,GDK_SELECTION_CLIPBOARD),(GtkClipboardTextReceivedFunc) text_received,(gpointer) widget); -} - diff --git a/src/clipboard/selection.c b/src/clipboard/selection.c deleted file mode 100644 index d28588d..0000000 --- a/src/clipboard/selection.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * "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 selection.c 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 - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - -static void clipboard_clear(G_GNUC_UNUSED GtkClipboard *clipboard, G_GNUC_UNUSED GObject *obj) -{ - v3270 * terminal = GTK_V3270(obj); - - if(!lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_KEEP_SELECTED)) - { - v3270_unselect(GTK_WIDGET(obj)); - v3270_clear_selection(terminal); - } - -} - -static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionData *selection, guint target, GObject *obj) -{ - v3270 * terminal = GTK_V3270(obj); - - if(!terminal->selection.blocks) - { - return; - } - - switch(target) - { - case CLIPBOARD_TYPE_TEXT: // Get clipboard contents as text - { - gchar *text; - - if(terminal->selection.format == V3270_SELECT_TABLE) - { - text = v3270_get_copy_as_table(terminal,"\t"); - } - else - { - text = v3270_get_copy_as_text(terminal); - } - gtk_selection_data_set_text(selection,text,-1); - g_free(text); - } - break; - - case CLIPBOARD_TYPE_CSV: - { - g_autofree gchar *text = v3270_get_copy_as_table(terminal,";"); - debug("Selection:\n%s",text); - gtk_selection_data_set( - selection, - gdk_atom_intern_static_string("text/csv"), - 8, - (guchar *) text, - strlen(text) - ); - } - break; - - default: - g_warning("Unexpected clipboard type %d\n",target); - } -} - -/** - * Clear clipboard contents. - * - * @param terminal Pointer to the terminal Widget. - * - */ -void v3270_clear_selection(v3270 *terminal) -{ - if(terminal->selection.blocks) - { - g_list_free_full(terminal->selection.blocks,(GDestroyNotify) lib3270_free); - terminal->selection.blocks = NULL; - } -} - -/** - * Get lib3270 selection as a g_malloc buffer. - * - * @param widget Widget containing the desired section. - * - * @return NULL if error, otherwise the selected buffer contents (release with g_free). - * - */ -LIB3270_EXPORT gchar * v3270_get_selected(GtkWidget *widget, gboolean cut) -{ - lib3270_autoptr(char) text = NULL; - - g_return_val_if_fail(GTK_IS_V3270(widget),NULL); - - 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); - - return NULL; -} - -void v3270_update_system_clipboard(GtkWidget *widget) -{ - v3270 * terminal = GTK_V3270(widget); - - if(!terminal->selection.blocks) - { - // No clipboard data, return. - g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, FALSE); - return; - } - - // Has clipboard data, inform system. - GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,terminal->selection.target); - - // Create target list - // - // 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 } - }; - - GtkTargetList * list = gtk_target_list_new(internal_targets, G_N_ELEMENTS(internal_targets)); - GtkTargetEntry * targets; - int n_targets; - - gtk_target_list_add_text_targets(list, CLIPBOARD_TYPE_TEXT); - - targets = gtk_target_table_new_from_list(list, &n_targets); - -#ifdef DEBUG - { - int ix; - for(ix = 0; ix < n_targets; ix++) { - debug("target(%d)=\"%s\"",ix,targets[ix].target); - } - } -#endif // DEBUG - - if(gtk_clipboard_set_with_owner( - clipboard, - targets, - n_targets, - (GtkClipboardGetFunc) clipboard_get, - (GtkClipboardClearFunc) clipboard_clear, - G_OBJECT(widget) - )) - { - gtk_clipboard_set_can_store(clipboard,targets,1); - } - - gtk_target_table_free(targets, n_targets); - gtk_target_list_unref(list); - - g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, TRUE); - -} - -LIB3270_EXPORT void v3270_unselect(GtkWidget *widget) -{ - v3270_disable_updates(widget); - lib3270_unselect(v3270_get_session(widget)); - v3270_enable_updates(widget); -} - -gboolean v3270_get_selection_bounds(GtkWidget *widget, gint *start, gint *end) -{ - g_return_val_if_fail(GTK_IS_V3270(widget),FALSE); - return lib3270_get_selection_bounds(GTK_V3270(widget)->host,start,end) == 0 ? FALSE : TRUE; -} - -LIB3270_EXPORT void v3270_select_region(GtkWidget *widget, gint start, gint end) -{ - g_return_if_fail(GTK_IS_V3270(widget)); - lib3270_select_region(GTK_V3270(widget)->host,start,end); -} - -LIB3270_EXPORT void v3270_select_all(GtkWidget *widget) -{ - g_return_if_fail(GTK_IS_V3270(widget)); - v3270_disable_updates(widget); - lib3270_select_all(v3270_get_session(widget)); - v3270_enable_updates(widget); -} - - diff --git a/src/clipboard/table.c b/src/clipboard/table.c deleted file mode 100644 index d96db40..0000000 --- a/src/clipboard/table.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * "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 - - struct ColumnDescription { - unsigned int begin; - unsigned int width; - }; - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - -/// @brief Check if column has data. -static gboolean hasDataOnColumn(v3270 * terminal, unsigned int col) -{ - GList * element = terminal->selection.blocks; - - while(element) - { - lib3270_selection * block = ((lib3270_selection *) element->data); - - if( (col >= block->bounds.col) && ( col < (block->bounds.col + block->bounds.width)) ) - { - unsigned int pos = col-block->bounds.col; - unsigned int row; - - for(row = 0; row < block->bounds.height; row++) - { - if( (block->contents[pos].flags & LIB3270_ATTR_SELECTED) && !isspace(block->contents[pos].chr)) - { - return TRUE; - } - pos += block->bounds.width; - } - - } - - element = g_list_next(element); - } - - return FALSE; -} - -/// @brief Get column list. -GList * getColumns(v3270 * terminal) -{ - unsigned int col = 0; - GList *rc = NULL; - - while(col < lib3270_get_width(terminal->host)) { - - // debug("col(%u): %s", col, hasDataOnColumn(terminal,col) ? "yes" : "no"); - - // Get first column. - while(!hasDataOnColumn(terminal,col)) { - if(col >= lib3270_get_width(terminal->host)) - return rc; - col++; - } - - // Alocate block, add it to list. - struct ColumnDescription * columndescription = g_new0(struct ColumnDescription,1); - columndescription->begin = col; - rc = g_list_append(rc,columndescription); - - // Get width. - while(hasDataOnColumn(terminal,col++)) { - columndescription->width++; - if(col >= lib3270_get_width(terminal->host)) - return rc; - } - } - - return rc; - -} - -/// @brief Get formatted contents as single text. -gchar * v3270_get_copy_as_table(v3270 * terminal, const gchar *delimiter) -{ - GString * string = g_string_new(""); - - GList * columns = getColumns(terminal); - - debug("columns=%p",columns); - -#ifdef DEBUG - { - GList * column = columns; - while(column) - { - struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data; - - debug("Begin: %u Width: %u",columndescription->begin, columndescription->width); - - column = column->next; - } - } -#endif // DEBUG - - GList * element = terminal->selection.blocks; - unsigned int width = lib3270_get_width(terminal->host); - g_autofree gchar * line = g_malloc0(width+1); - GList * column; - - while(element) - { - lib3270_selection * block = ((lib3270_selection *) element->data); - - unsigned int row, col, src = 0; - - for(row=0; row < block->bounds.height; row++) - { - - // Build text line with selected data. - memset(line,' ',width); - for(col=0; colbounds.width; col++) - { - if(block->contents[src].flags & LIB3270_ATTR_SELECTED) - { - line[block->bounds.col+col] = block->contents[src].chr; - } - - src++; - } - - debug("[%s]",line); - - // Extract columns - for(column = columns; column; column = column->next) - { - struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data; - g_string_append_len(string,line+columndescription->begin,columndescription->width); - if(column->next) - g_string_append(string,delimiter); - } - g_string_append(string,"\n"); - - } - - element = g_list_next(element); - } - - g_list_free_full(columns,g_free); - - 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); -} diff --git a/src/clipboard/text.c b/src/clipboard/text.c deleted file mode 100644 index 8f75c3d..0000000 --- a/src/clipboard/text.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * "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 - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - -/// @brief Get formatted contents as single text. -gchar * v3270_get_copy_as_text(v3270 * terminal) -{ - GList * element = terminal->selection.blocks; - GString * string = g_string_new(""); - - while(element) - { - lib3270_selection * block = ((lib3270_selection *) element->data); - unsigned int row, col, src = 0; - - for(row=0; row < block->bounds.height; row++) - { - for(col=0; colbounds.width; col++) - { - if(block->contents[src].flags & LIB3270_ATTR_SELECTED) - g_string_append_c(string,block->contents[src].chr); - - src++; - - } - g_string_append_c(string,'\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); - -} - - -LIB3270_EXPORT void v3270_paste_text(GtkWidget *widget, const gchar *text, const gchar *encoding) -{ - gchar * buffer = NULL; - H3270 * session = v3270_get_session(widget); - const gchar * charset = lib3270_get_display_charset(session); - gboolean next; - - if(!text) - return; - else if(g_ascii_strcasecmp(encoding,charset)) - buffer = g_convert(text, -1, charset, encoding, NULL, NULL, NULL); - else - buffer = g_strdup(text); - - if(!buffer) - { - /* Conversion failed, update special chars and try again */ - size_t f; - - static const struct _xlat - { - const gchar *from; - const gchar *to; - } xlat[] = - { - { "–", "-" }, - { "→", "->" }, - { "←", "<-" }, - { "©", "(c)" }, - { "↔", "<->" }, - { "™", "(TM)" }, - { "®", "(R)" }, - { "“", "\"" }, - { "”", "\"" }, - { "…", "..." }, - { "•", "*" }, - { "․", "." }, - { "·", "*" }, - - }; - - gchar *string = g_strdup(text); - - // FIXME (perry#1#): Is there any better way for a "sed" here? - for(f=0;fmessage, ln[f]); - - gtk_dialog_run(GTK_DIALOG (dialog)); - gtk_widget_destroy(dialog); - - break; - } - else - { - g_free(str); - } - - } - g_strfreev(ln); - - } - - g_free(string); - } - - if(buffer) - { - /* Remove TABS */ - gchar *ptr; - - for(ptr = buffer;*ptr;ptr++) - { - if(*ptr == '\t') - *ptr = ' '; - } - } - else - { - g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, FALSE); - return; - } - - next = lib3270_paste(session,(unsigned char *) buffer) ? TRUE : FALSE; - - g_free(buffer); - - g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, next); - -} - -LIB3270_EXPORT gchar * v3270_get_copy(GtkWidget *widget) -{ - g_return_val_if_fail(GTK_IS_V3270(widget),NULL); - return v3270_get_copy_as_text(GTK_V3270(widget)); -} - diff --git a/src/clipboard/windows/paste.c b/src/clipboard/windows/paste.c deleted file mode 100644 index 277f826..0000000 --- a/src/clipboard/windows/paste.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * "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 selection.c 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 - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - -LIB3270_EXPORT void v3270_paste(GtkWidget *widget) -{ - HGLOBAL hglb; - - if (!IsClipboardFormatAvailable(CF_TEXT)) - return; - - if (!OpenClipboard(NULL)) - return; - - hglb = GetClipboardData(CF_TEXT); - if (hglb != NULL) - { - LPTSTR lptstr = GlobalLock(hglb); - if (lptstr != NULL) - { - v3270_paste_text(widget,lptstr,"CP1252"); - GlobalUnlock(hglb); - } - } - - CloseClipboard(); - -} diff --git a/src/include/v3270.h b/src/include/v3270.h index 2c7b2ec..3a81782 100644 --- a/src/include/v3270.h +++ b/src/include/v3270.h @@ -201,19 +201,18 @@ LIB3270_EXPORT void v3270_tab(GtkWidget *widget); LIB3270_EXPORT void v3270_backtab(GtkWidget *widget); - // Cut & Paste + // Selections LIB3270_EXPORT gboolean v3270_get_selection_bounds(GtkWidget *widget, gint *start, gint *end); LIB3270_EXPORT void v3270_unselect(GtkWidget *widget); LIB3270_EXPORT void v3270_select_all(GtkWidget *widget); 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_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); + LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const gchar *encoding); // Colors LIB3270_EXPORT void v3270_set_colors(GtkWidget *widget, const gchar *); diff --git a/src/selection/copy.c b/src/selection/copy.c new file mode 100644 index 0000000..afef411 --- /dev/null +++ b/src/selection/copy.c @@ -0,0 +1,129 @@ +/* + * "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 + + static void do_copy(v3270 *terminal, gboolean cut) + { + lib3270_selection * selection = lib3270_get_selection(terminal->host,cut); + + if(selection) + { + terminal->selection.blocks = g_list_append(terminal->selection.blocks,selection); + } + + /* + // Get selection bounds. + unsigned int row; + unsigned int col; + unsigned int width; + unsigned int height; + + 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", + 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; + + int pos = 0; + for(r=0;r < selection->bounds.height; r++) + { + // Get starting address. + 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",selection->bounds.row+r+1,selection->bounds.col+1); + gdk_display_beep(gdk_display_get_default()); + return; + } + + for(c=0;c < selection->bounds.width; c++) + { + 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_selection(terminal); + + terminal->selection.format = format; + do_copy(terminal,cut); + + v3270_update_system_clipboard(widget); + +/* +#ifdef DEBUG + gchar *columns = v3270_get_copy_as_table(terminal,"---"); + debug("Output:\n%s",columns); + g_free(columns); +#endif // DEBUG +*/ + + } + + 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,cut); + + v3270_update_system_clipboard(widget); + + } + diff --git a/src/selection/linux/paste.c b/src/selection/linux/paste.c new file mode 100644 index 0000000..b007552 --- /dev/null +++ b/src/selection/linux/paste.c @@ -0,0 +1,75 @@ +/* + * "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 selection.c 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 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static void text_received(G_GNUC_UNUSED GtkClipboard *clipboard, const gchar *text, GtkWidget *widget) +{ + v3270_input_text(widget,text,"UTF-8"); +} + +static gboolean has_target(const gchar *name, const GdkAtom *atoms, const gint n_atoms) +{ + gint ix; + + for(ix = 0; ix < n_atoms; ix++) + { + if(!g_ascii_strcasecmp(name,gdk_atom_name(atoms[ix]))) + return TRUE; + + } + + return FALSE; +} + +static void targets_received(GtkClipboard *clipboard, GdkAtom *atoms, gint n_atoms, GtkWidget *widget) +{ + if(has_target("application/x-" PACKAGE_NAME, atoms, n_atoms)) + { + debug("Clipboard as TN3270 \"%s\" data",PACKAGE_NAME); + return; + } + + // No special format available, request it as text. + gtk_clipboard_request_text(clipboard, (GtkClipboardTextReceivedFunc) text_received, (gpointer) widget); + +} + +LIB3270_EXPORT void v3270_paste(GtkWidget *widget) +{ + g_return_if_fail(GTK_IS_V3270(widget)); + + GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,GTK_V3270(widget)->selection.target); + + gtk_clipboard_request_targets(clipboard, (GtkClipboardTargetsReceivedFunc) targets_received, (gpointer) widget); + +} + diff --git a/src/selection/selection.c b/src/selection/selection.c new file mode 100644 index 0000000..d28588d --- /dev/null +++ b/src/selection/selection.c @@ -0,0 +1,219 @@ +/* + * "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 selection.c 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 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +static void clipboard_clear(G_GNUC_UNUSED GtkClipboard *clipboard, G_GNUC_UNUSED GObject *obj) +{ + v3270 * terminal = GTK_V3270(obj); + + if(!lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_KEEP_SELECTED)) + { + v3270_unselect(GTK_WIDGET(obj)); + v3270_clear_selection(terminal); + } + +} + +static void clipboard_get(G_GNUC_UNUSED GtkClipboard *clipboard, GtkSelectionData *selection, guint target, GObject *obj) +{ + v3270 * terminal = GTK_V3270(obj); + + if(!terminal->selection.blocks) + { + return; + } + + switch(target) + { + case CLIPBOARD_TYPE_TEXT: // Get clipboard contents as text + { + gchar *text; + + if(terminal->selection.format == V3270_SELECT_TABLE) + { + text = v3270_get_copy_as_table(terminal,"\t"); + } + else + { + text = v3270_get_copy_as_text(terminal); + } + gtk_selection_data_set_text(selection,text,-1); + g_free(text); + } + break; + + case CLIPBOARD_TYPE_CSV: + { + g_autofree gchar *text = v3270_get_copy_as_table(terminal,";"); + debug("Selection:\n%s",text); + gtk_selection_data_set( + selection, + gdk_atom_intern_static_string("text/csv"), + 8, + (guchar *) text, + strlen(text) + ); + } + break; + + default: + g_warning("Unexpected clipboard type %d\n",target); + } +} + +/** + * Clear clipboard contents. + * + * @param terminal Pointer to the terminal Widget. + * + */ +void v3270_clear_selection(v3270 *terminal) +{ + if(terminal->selection.blocks) + { + g_list_free_full(terminal->selection.blocks,(GDestroyNotify) lib3270_free); + terminal->selection.blocks = NULL; + } +} + +/** + * Get lib3270 selection as a g_malloc buffer. + * + * @param widget Widget containing the desired section. + * + * @return NULL if error, otherwise the selected buffer contents (release with g_free). + * + */ +LIB3270_EXPORT gchar * v3270_get_selected(GtkWidget *widget, gboolean cut) +{ + lib3270_autoptr(char) text = NULL; + + g_return_val_if_fail(GTK_IS_V3270(widget),NULL); + + 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); + + return NULL; +} + +void v3270_update_system_clipboard(GtkWidget *widget) +{ + v3270 * terminal = GTK_V3270(widget); + + if(!terminal->selection.blocks) + { + // No clipboard data, return. + g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, FALSE); + return; + } + + // Has clipboard data, inform system. + GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,terminal->selection.target); + + // Create target list + // + // 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 } + }; + + GtkTargetList * list = gtk_target_list_new(internal_targets, G_N_ELEMENTS(internal_targets)); + GtkTargetEntry * targets; + int n_targets; + + gtk_target_list_add_text_targets(list, CLIPBOARD_TYPE_TEXT); + + targets = gtk_target_table_new_from_list(list, &n_targets); + +#ifdef DEBUG + { + int ix; + for(ix = 0; ix < n_targets; ix++) { + debug("target(%d)=\"%s\"",ix,targets[ix].target); + } + } +#endif // DEBUG + + if(gtk_clipboard_set_with_owner( + clipboard, + targets, + n_targets, + (GtkClipboardGetFunc) clipboard_get, + (GtkClipboardClearFunc) clipboard_clear, + G_OBJECT(widget) + )) + { + gtk_clipboard_set_can_store(clipboard,targets,1); + } + + gtk_target_table_free(targets, n_targets); + gtk_target_list_unref(list); + + g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_CLIPBOARD], 0, TRUE); + +} + +LIB3270_EXPORT void v3270_unselect(GtkWidget *widget) +{ + v3270_disable_updates(widget); + lib3270_unselect(v3270_get_session(widget)); + v3270_enable_updates(widget); +} + +gboolean v3270_get_selection_bounds(GtkWidget *widget, gint *start, gint *end) +{ + g_return_val_if_fail(GTK_IS_V3270(widget),FALSE); + return lib3270_get_selection_bounds(GTK_V3270(widget)->host,start,end) == 0 ? FALSE : TRUE; +} + +LIB3270_EXPORT void v3270_select_region(GtkWidget *widget, gint start, gint end) +{ + g_return_if_fail(GTK_IS_V3270(widget)); + lib3270_select_region(GTK_V3270(widget)->host,start,end); +} + +LIB3270_EXPORT void v3270_select_all(GtkWidget *widget) +{ + g_return_if_fail(GTK_IS_V3270(widget)); + v3270_disable_updates(widget); + lib3270_select_all(v3270_get_session(widget)); + v3270_enable_updates(widget); +} + + diff --git a/src/selection/table.c b/src/selection/table.c new file mode 100644 index 0000000..d96db40 --- /dev/null +++ b/src/selection/table.c @@ -0,0 +1,176 @@ +/* + * "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 + + struct ColumnDescription { + unsigned int begin; + unsigned int width; + }; + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +/// @brief Check if column has data. +static gboolean hasDataOnColumn(v3270 * terminal, unsigned int col) +{ + GList * element = terminal->selection.blocks; + + while(element) + { + lib3270_selection * block = ((lib3270_selection *) element->data); + + if( (col >= block->bounds.col) && ( col < (block->bounds.col + block->bounds.width)) ) + { + unsigned int pos = col-block->bounds.col; + unsigned int row; + + for(row = 0; row < block->bounds.height; row++) + { + if( (block->contents[pos].flags & LIB3270_ATTR_SELECTED) && !isspace(block->contents[pos].chr)) + { + return TRUE; + } + pos += block->bounds.width; + } + + } + + element = g_list_next(element); + } + + return FALSE; +} + +/// @brief Get column list. +GList * getColumns(v3270 * terminal) +{ + unsigned int col = 0; + GList *rc = NULL; + + while(col < lib3270_get_width(terminal->host)) { + + // debug("col(%u): %s", col, hasDataOnColumn(terminal,col) ? "yes" : "no"); + + // Get first column. + while(!hasDataOnColumn(terminal,col)) { + if(col >= lib3270_get_width(terminal->host)) + return rc; + col++; + } + + // Alocate block, add it to list. + struct ColumnDescription * columndescription = g_new0(struct ColumnDescription,1); + columndescription->begin = col; + rc = g_list_append(rc,columndescription); + + // Get width. + while(hasDataOnColumn(terminal,col++)) { + columndescription->width++; + if(col >= lib3270_get_width(terminal->host)) + return rc; + } + } + + return rc; + +} + +/// @brief Get formatted contents as single text. +gchar * v3270_get_copy_as_table(v3270 * terminal, const gchar *delimiter) +{ + GString * string = g_string_new(""); + + GList * columns = getColumns(terminal); + + debug("columns=%p",columns); + +#ifdef DEBUG + { + GList * column = columns; + while(column) + { + struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data; + + debug("Begin: %u Width: %u",columndescription->begin, columndescription->width); + + column = column->next; + } + } +#endif // DEBUG + + GList * element = terminal->selection.blocks; + unsigned int width = lib3270_get_width(terminal->host); + g_autofree gchar * line = g_malloc0(width+1); + GList * column; + + while(element) + { + lib3270_selection * block = ((lib3270_selection *) element->data); + + unsigned int row, col, src = 0; + + for(row=0; row < block->bounds.height; row++) + { + + // Build text line with selected data. + memset(line,' ',width); + for(col=0; colbounds.width; col++) + { + if(block->contents[src].flags & LIB3270_ATTR_SELECTED) + { + line[block->bounds.col+col] = block->contents[src].chr; + } + + src++; + } + + debug("[%s]",line); + + // Extract columns + for(column = columns; column; column = column->next) + { + struct ColumnDescription * columndescription = (struct ColumnDescription *) column->data; + g_string_append_len(string,line+columndescription->begin,columndescription->width); + if(column->next) + g_string_append(string,delimiter); + } + g_string_append(string,"\n"); + + } + + element = g_list_next(element); + } + + g_list_free_full(columns,g_free); + + 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); +} diff --git a/src/selection/text.c b/src/selection/text.c new file mode 100644 index 0000000..79737e5 --- /dev/null +++ b/src/selection/text.c @@ -0,0 +1,203 @@ +/* + * "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 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +/// @brief Get formatted contents as single text. +gchar * v3270_get_copy_as_text(v3270 * terminal) +{ + GList * element = terminal->selection.blocks; + GString * string = g_string_new(""); + + while(element) + { + lib3270_selection * block = ((lib3270_selection *) element->data); + unsigned int row, col, src = 0; + + for(row=0; row < block->bounds.height; row++) + { + for(col=0; colbounds.width; col++) + { + if(block->contents[src].flags & LIB3270_ATTR_SELECTED) + g_string_append_c(string,block->contents[src].chr); + + src++; + + } + g_string_append_c(string,'\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); + +} + + +LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const gchar *encoding) +{ + gchar * buffer = NULL; + H3270 * session = v3270_get_session(widget); + const gchar * charset = lib3270_get_display_charset(session); + gboolean next; + + if(!text) + return; + else if(g_ascii_strcasecmp(encoding,charset)) + buffer = g_convert(text, -1, charset, encoding, NULL, NULL, NULL); + else + buffer = g_strdup(text); + + if(!buffer) + { + /* Conversion failed, update special chars and try again */ + size_t f; + + static const struct _xlat + { + const gchar *from; + const gchar *to; + } xlat[] = + { + { "–", "-" }, + { "→", "->" }, + { "←", "<-" }, + { "©", "(c)" }, + { "↔", "<->" }, + { "™", "(TM)" }, + { "®", "(R)" }, + { "“", "\"" }, + { "”", "\"" }, + { "…", "..." }, + { "•", "*" }, + { "․", "." }, + { "·", "*" }, + + }; + + gchar *string = g_strdup(text); + + // FIXME (perry#1#): Is there any better way for a "sed" here? + for(f=0;fmessage, ln[f]); + g_error_free(error); + error = NULL; + } + + gtk_dialog_run(GTK_DIALOG (dialog)); + gtk_widget_destroy(dialog); + + break; + } + else + { + g_free(str); + } + + } + g_strfreev(ln); + + } + + g_free(string); + } + + if(buffer) + { + /* Remove TABS */ + gchar *ptr; + + for(ptr = buffer;*ptr;ptr++) + { + if(*ptr == '\t') + *ptr = ' '; + } + } + else + { + g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, FALSE); + return; + } + + next = lib3270_paste(session,(unsigned char *) buffer) ? TRUE : FALSE; + + g_free(buffer); + + g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, next); + +} + +LIB3270_EXPORT gchar * v3270_get_copy(GtkWidget *widget) +{ + g_return_val_if_fail(GTK_IS_V3270(widget),NULL); + return v3270_get_copy_as_text(GTK_V3270(widget)); +} + diff --git a/src/selection/windows/paste.c b/src/selection/windows/paste.c new file mode 100644 index 0000000..227cb13 --- /dev/null +++ b/src/selection/windows/paste.c @@ -0,0 +1,61 @@ +/* + * "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 selection.c 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 + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + +LIB3270_EXPORT void v3270_paste(GtkWidget *widget) +{ + g_return_if_fail(GTK_IS_V3270(session)); + + if (!OpenClipboard(NULL)) + return; + + if (IsClipboardFormatAvailable(CF_TEXT)) + { + // Got text formatted clipboard. + HGLOBAL hglb; + + hglb = GetClipboardData(CF_TEXT); + if (hglb != NULL) + { + LPTSTR lptstr = GlobalLock(hglb); + if (lptstr != NULL) + { + v3270_input_text(widget,lptstr,"CP1252"); + GlobalUnlock(hglb); + } + } + } + + CloseClipboard(); + +} diff --git a/src/testprogram/testprogram.c b/src/testprogram/testprogram.c index ac643fc..888f3e8 100644 --- a/src/testprogram/testprogram.c +++ b/src/testprogram/testprogram.c @@ -218,6 +218,11 @@ static void ft_clicked(GtkButton *button, GtkWidget *terminal) } +static void paste_clicked(GtkButton *button, GtkWidget *terminal) +{ + v3270_paste(terminal); +} + static void color_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) { GtkWidget * dialog = v3270_dialog_new(terminal, _("Color setup"), _("_Save")); @@ -296,7 +301,8 @@ static void activate(GtkApplication* app, G_GNUC_UNUSED gpointer user_data) { { "gtk-select-color", G_CALLBACK(color_clicked), "Edit or change color scheme" }, { "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-harddisk", G_CALLBACK(ft_clicked), "Open file transfer dialog" }, + { "gtk-paste", G_CALLBACK(paste_clicked), "Paste data" } }; GtkWidget * toolbar = gtk_toolbar_new(); diff --git a/v3270.cbp b/v3270.cbp index c600b46..615dd0a 100644 --- a/v3270.cbp +++ b/v3270.cbp @@ -42,24 +42,6 @@ - - - - - - - - - - - - @@ -161,6 +143,24 @@ + + + + + + + + + + + + -- libgit2 0.21.2