Commit b4195d4101a3ebc1bd27bd1b36220f386bbf0672

Authored by perry.werneck@gmail.com
0 parents
Exists in master and in 1 other branch develop

Renomeando diretorio de fontes da aplicacao para facilitar empacotamento

accessible.c 0 → 100644
  1 +++ a/accessible.c
... ... @@ -0,0 +1,865 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como accessible.c 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 <lib3270/config.h>
  31 +
  32 + #define ENABLE_NLS
  33 + #define GETTEXT_PACKAGE PACKAGE_NAME
  34 +
  35 + #include <gtk/gtk.h>
  36 + #include <libintl.h>
  37 + #include <glib/gi18n.h>
  38 +
  39 + #include <pw3270.h>
  40 + #include <malloc.h>
  41 + #include "v3270.h"
  42 + #include "private.h"
  43 + #include "accessible.h"
  44 +
  45 +// References:
  46 +//
  47 +// http://git.gnome.org/browse/gtk+/tree/gtk/a11y/gtkwidgetaccessible.c
  48 +// http://git.gnome.org/browse/gtk+/tree/gtk/a11y/gtkentryaccessible.c
  49 +//
  50 +
  51 +
  52 +/*--[ Prototipes ]-----------------------------------------------------------------------------------*/
  53 +
  54 +static void atk_component_interface_init (AtkComponentIface *iface);
  55 +static void atk_action_interface_init (AtkActionIface *iface);
  56 +static void v3270_accessible_class_init (v3270AccessibleClass *klass);
  57 +static void v3270_accessible_init (v3270Accessible *widget);
  58 +
  59 +static void atk_text_interface_init (AtkTextIface *iface);
  60 +
  61 +/*--[ Widget definition ]----------------------------------------------------------------------------*/
  62 +
  63 +G_DEFINE_TYPE_WITH_CODE (v3270Accessible, v3270_accessible, GTK_TYPE_ACCESSIBLE,
  64 + G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)
  65 + G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
  66 + G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
  67 + )
  68 +
  69 +// G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
  70 +
  71 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  72 +
  73 +static const gchar * v3270_accessible_get_description (AtkObject *accessible)
  74 +{
  75 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (accessible));
  76 +
  77 + if (widget == NULL)
  78 + return NULL;
  79 +
  80 + return _( "3270 screen" );
  81 +}
  82 +
  83 +static void v3270_accessible_focus_event(AtkObject *obj, gboolean focus_in)
  84 +{
  85 + AtkObject *focus_obj = g_object_get_data (G_OBJECT (obj), "gail-focus-object");
  86 +
  87 + if(focus_obj == NULL)
  88 + focus_obj = obj;
  89 +
  90 + atk_object_notify_state_change(focus_obj, ATK_STATE_FOCUSED, focus_in);
  91 +}
  92 +
  93 +static AtkAttributeSet * v3270_accessible_get_attributes (AtkObject *obj)
  94 +{
  95 + AtkAttributeSet * attributes;
  96 + AtkAttribute * toolkit = g_new(AtkAttribute, 1);
  97 +
  98 + toolkit->name = g_strdup("toolkit");
  99 + toolkit->value = g_strdup("gtk");
  100 +
  101 + attributes = g_slist_append (NULL, toolkit);
  102 +
  103 + return attributes;
  104 +}
  105 +
  106 +static void v3270_accessible_initialize (AtkObject *obj, gpointer data)
  107 +{
  108 + obj->role = ATK_ROLE_TEXT;
  109 +}
  110 +
  111 +static void v3270_accessible_class_init(v3270AccessibleClass *klass)
  112 +{
  113 + AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
  114 +
  115 + class->get_description = v3270_accessible_get_description;
  116 + class->focus_event = v3270_accessible_focus_event;
  117 + class->get_attributes = v3270_accessible_get_attributes;
  118 + class->initialize = v3270_accessible_initialize;
  119 +
  120 +/*
  121 + klass->notify_gtk = gtk_widget_accessible_notify_gtk;
  122 +
  123 + class->get_parent = gtk_widget_accessible_get_parent;
  124 + class->ref_relation_set = gtk_widget_accessible_ref_relation_set;
  125 + class->ref_state_set = gtk_widget_accessible_ref_state_set;
  126 + class->get_index_in_parent = gtk_widget_accessible_get_index_in_parent;
  127 +*/
  128 +}
  129 +
  130 +static gint v3270_accessible_get_n_actions(AtkAction *action)
  131 +{
  132 + return 1;
  133 +}
  134 +
  135 +static const gchar* v3270_accessible_action_get_name (AtkAction *action, gint i)
  136 +{
  137 + if (i != 0)
  138 + return NULL;
  139 +
  140 + return "activate";
  141 +}
  142 +
  143 +static gboolean v3270_accessible_do_action(AtkAction *action, gint i)
  144 +{
  145 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
  146 +
  147 + if(widget == NULL)
  148 + return FALSE;
  149 +
  150 + if(!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
  151 + return FALSE;
  152 +
  153 + if (i != 0)
  154 + return FALSE;
  155 +
  156 + gtk_widget_activate(widget);
  157 +
  158 + return TRUE;
  159 +}
  160 +
  161 +static void atk_action_interface_init(AtkActionIface *iface)
  162 +{
  163 + iface->get_name = v3270_accessible_action_get_name;
  164 + iface->get_n_actions = v3270_accessible_get_n_actions;
  165 + iface->do_action = v3270_accessible_do_action;
  166 +
  167 +/*
  168 + iface->get_keybinding = gtk_entry_accessible_get_keybinding;
  169 +*/
  170 +}
  171 +
  172 +static gunichar v3270_accessible_get_character_at_offset(AtkText *atk_text, gint offset)
  173 +{
  174 + GtkWidget * widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (atk_text));
  175 +
  176 + if(widget == NULL)
  177 + {
  178 + H3270 * host = v3270_get_session(widget);
  179 + gchar * text = lib3270_get_text(host,offset,1);
  180 +
  181 + if(text)
  182 + {
  183 + gunichar unichar;
  184 + gsize bytes_written;
  185 + GError * error = NULL;
  186 + gchar * utfstring = g_convert_with_fallback( text,
  187 + -1,
  188 + "UTF-8",
  189 + lib3270_get_charset(host),
  190 + " ",
  191 + NULL,
  192 + &bytes_written,
  193 + &error );
  194 +
  195 + if(error)
  196 + {
  197 + g_warning("%s failed: %s",__FUNCTION__,error->message);
  198 + g_error_free(error);
  199 + }
  200 + unichar = *utfstring;
  201 +
  202 + g_free(utfstring);
  203 +
  204 + return unichar;
  205 + }
  206 +
  207 + }
  208 +
  209 + return '\0';
  210 +}
  211 +
  212 +static gint v3270_accessible_get_caret_offset(AtkText *text)
  213 +{
  214 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE(text));
  215 +
  216 + if (widget == NULL)
  217 + return 0;
  218 +
  219 + return lib3270_get_cursor_address(GTK_V3270(widget)->host);
  220 +}
  221 +
  222 +static gint v3270_accessible_get_character_count(AtkText *text)
  223 +{
  224 + int rows,cols;
  225 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE(text));
  226 +
  227 + if(!widget)
  228 + return 0;
  229 +
  230 + return lib3270_get_length(GTK_V3270(widget)->host);
  231 +}
  232 +
  233 +static gint v3270_accessible_get_offset_at_point(AtkText *atk_text, gint x, gint y, AtkCoordType coords)
  234 +{
  235 + gint x_window,
  236 + y_window,
  237 + x_widget,
  238 + y_widget;
  239 + GdkWindow * window;
  240 + GtkWidget * widget = gtk_accessible_get_widget(GTK_ACCESSIBLE(atk_text));
  241 +
  242 + if(!widget)
  243 + return -1;
  244 +
  245 + window = gtk_widget_get_window(widget);
  246 + gdk_window_get_origin(window, &x_widget, &y_widget);
  247 +
  248 + switch(coords)
  249 + {
  250 + case ATK_XY_SCREEN:
  251 + x -= x_widget;
  252 + y -= y_widget;
  253 + break;
  254 +
  255 + case ATK_XY_WINDOW:
  256 + window = gdk_window_get_toplevel(window);
  257 + gdk_window_get_origin (window, &x_window, &y_window);
  258 + x = x - x_widget + x_window;
  259 + y = y - y_widget + y_window;
  260 + break;
  261 +
  262 + default:
  263 + return -1;
  264 +
  265 + }
  266 +
  267 + return v3270_get_offset_at_point(GTK_V3270(widget),x,y);
  268 +}
  269 +
  270 +/*
  271 +text : an AtkText
  272 +offset : The offset of the text character for which bounding information is required.
  273 +x : Pointer for the x cordinate of the bounding box
  274 +y : Pointer for the y cordinate of the bounding box
  275 +width : Pointer for the width of the bounding box
  276 +height : Pointer for the height of the bounding box
  277 +coords : specify whether coordinates are relative to the screen or widget window
  278 +*/
  279 +
  280 +static void v3270_accessible_get_character_extents( AtkText *text,
  281 + gint offset,
  282 + gint *x,
  283 + gint *y,
  284 + gint *width,
  285 + gint *height,
  286 + AtkCoordType coords )
  287 +{
  288 + v3270 * widget = (v3270 *) gtk_accessible_get_widget(GTK_ACCESSIBLE (text));
  289 + int rows, cols;
  290 + GdkWindow * window;
  291 +
  292 + if (widget == NULL)
  293 + return;
  294 +
  295 + lib3270_get_screen_size(widget->host,&rows,&cols);
  296 +
  297 + // Get screen position
  298 + window = gtk_widget_get_window(GTK_WIDGET(widget));
  299 + gdk_window_get_origin(window, x, y);
  300 +
  301 + // Get screen position
  302 + *x += widget->metrics.left + ((offset%cols) * widget->metrics.width);
  303 + *y += widget->metrics.top + ((offset/cols) * widget->metrics.spacing);
  304 + *width = widget->metrics.width;
  305 + *height = widget->metrics.spacing;
  306 +
  307 + if(coords == ATK_XY_WINDOW)
  308 + {
  309 + // Correct position based on toplevel
  310 + gint x_window, y_window;
  311 +
  312 + window = gdk_window_get_toplevel(window);
  313 + gdk_window_get_origin(window, &x_window, &y_window);
  314 + *x -= x_window;
  315 + *y -= y_window;
  316 + }
  317 +
  318 +// trace("%s: offset=%d x=%d y=%d %s",__FUNCTION__,offset,*x,*y,coords == ATK_XY_WINDOW ? "ATK_XY_WINDOW" : "");
  319 +
  320 +}
  321 +
  322 +static gchar * v3270_accessible_get_text_at_offset(AtkText *atk_text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
  323 +{
  324 + GtkWidget * widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (atk_text));
  325 + H3270 * host;
  326 + char * text;
  327 + int rows,cols,pos;
  328 +
  329 + if(!widget)
  330 + return NULL;
  331 +
  332 + host = GTK_V3270(widget)->host;
  333 + lib3270_get_screen_size(host,&rows,&cols);
  334 +
  335 + switch(boundary_type)
  336 + {
  337 + case ATK_TEXT_BOUNDARY_CHAR: // Boundary is the boundary between characters
  338 + // (including non-printing characters)
  339 +
  340 + text = lib3270_get_text(host,offset,1);
  341 + break;
  342 +
  343 + case ATK_TEXT_BOUNDARY_WORD_START: // Boundary is the start (i.e. first character) of a word.
  344 + return g_strdup("ATK_TEXT_BOUNDARY_WORD_START");
  345 + break;
  346 +
  347 + case ATK_TEXT_BOUNDARY_WORD_END: // Boundary is the end (i.e. last character) of a word.
  348 + return g_strdup("ATK_TEXT_BOUNDARY_WORD_END");
  349 + break;
  350 +
  351 + case ATK_TEXT_BOUNDARY_SENTENCE_START: // Boundary is the first character in a sentence.
  352 + return g_strdup("ATK_TEXT_BOUNDARY_SENTENCE_START");
  353 + break;
  354 +
  355 + case ATK_TEXT_BOUNDARY_SENTENCE_END: // Boundary is the last (terminal) character in
  356 + // a sentence; in languages which use "sentence stop" punctuation such as English, the boundary is thus the '.', '?', or
  357 + // similar terminal punctuation character.
  358 + return g_strdup("ATK_TEXT_BOUNDARY_SENTENCE_END");
  359 + break;
  360 +
  361 +
  362 + case ATK_TEXT_BOUNDARY_LINE_START: // Boundary is the initial character of the content or a character immediately following a newline,
  363 + // linefeed, or return character.
  364 + pos = (offset/cols)*cols;
  365 + if(pos == offset)
  366 + offset++;
  367 + text = lib3270_get_text(host,pos,(offset-pos));
  368 + break;
  369 +
  370 +
  371 + case ATK_TEXT_BOUNDARY_LINE_END: // Boundary is the linefeed, or return character.
  372 + return g_strdup("ATK_TEXT_BOUNDARY_LINE_END");
  373 + break;
  374 +
  375 + }
  376 +
  377 + if(text)
  378 + {
  379 + gsize bytes_written;
  380 + GError * error = NULL;
  381 + gchar * utfchar = g_convert_with_fallback( text,
  382 + -1,
  383 + "UTF-8",
  384 + lib3270_get_charset(host),
  385 + " ",
  386 + NULL,
  387 + &bytes_written,
  388 + &error );
  389 +
  390 + if(error)
  391 + {
  392 + g_warning("%s failed: %s",__FUNCTION__,error->message);
  393 + g_error_free(error);
  394 + }
  395 +
  396 + free(text);
  397 + return utfchar;
  398 + }
  399 +
  400 + return NULL;
  401 +}
  402 +
  403 +static gchar * v3270_accessible_get_text(AtkText *atk_text, gint start_pos, gint end_pos)
  404 +{
  405 + GtkWidget * widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (atk_text));
  406 + char * text;
  407 + H3270 * host;
  408 + gchar * utftext = NULL;
  409 +
  410 + if(widget == NULL)
  411 + return NULL;
  412 +
  413 + host = v3270_get_session(widget);
  414 + if(!host)
  415 + return NULL;
  416 +
  417 + if(!lib3270_connected(host))
  418 + return g_strdup( "" );
  419 +
  420 + text = lib3270_get_text(host,start_pos,end_pos < start_pos ? -1 : (end_pos - start_pos));
  421 +
  422 + if(text)
  423 + {
  424 + gsize bytes_written;
  425 + GError * error = NULL;
  426 +
  427 + utftext = g_convert_with_fallback(text,-1,"UTF-8",lib3270_get_charset(host)," ",NULL,&bytes_written, &error);
  428 +
  429 + if(error)
  430 + {
  431 + g_warning("%s failed: %s",__FUNCTION__,error->message);
  432 + g_error_free(error);
  433 + }
  434 +
  435 + free(text);
  436 +
  437 +// trace("%s:\n%s\n",__FUNCTION__,utftext);
  438 +
  439 + }
  440 +
  441 + return utftext;
  442 +}
  443 +
  444 +static gboolean v3270_set_caret_offset(AtkText *text, gint offset)
  445 +{
  446 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  447 + if (widget == NULL)
  448 + return FALSE;
  449 +
  450 + trace("%s - offset=%d",__FUNCTION__,offset);
  451 +
  452 + lib3270_set_cursor_address(GTK_V3270(widget)->host,offset);
  453 +
  454 + return TRUE;
  455 +}
  456 +
  457 +static gboolean v3270_accessible_remove_selection(AtkText *text, gint selection_num)
  458 +{
  459 + GtkWidget * widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  460 +
  461 + if (widget == NULL || selection_num != 0)
  462 + return FALSE;
  463 +
  464 + v3270_unselect(widget);
  465 +
  466 + return TRUE;
  467 +}
  468 +
  469 +static gint v3270_accessible_get_n_selections (AtkText *text)
  470 +{
  471 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  472 +
  473 + if(!widget)
  474 + return 0;
  475 +
  476 +// trace("%s: n_selections=%d",__FUNCTION__,v3270_get_selection_bounds(widget, NULL, NULL) ? 1 : 0);
  477 +
  478 + return v3270_get_selection_bounds(widget, NULL, NULL) ? 1 : 0;
  479 +}
  480 +
  481 +static gchar * v3270_accessible_get_selection(AtkText *atk_text, gint selection_num, gint *start_pos, gint *end_pos)
  482 +{
  483 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (atk_text));
  484 +
  485 +// trace("%s: selection_num=%d",__FUNCTION__,selection_num);
  486 + if (widget == NULL ||selection_num != 0)
  487 + return NULL;
  488 +
  489 + if(v3270_get_selection_bounds(widget, start_pos, end_pos))
  490 + {
  491 +// trace("%s: TRUE",__FUNCTION__);
  492 + return v3270_get_region(widget, *start_pos, *end_pos, FALSE);
  493 + }
  494 +
  495 +// trace("%s: FALSE",__FUNCTION__);
  496 + return NULL;
  497 +}
  498 +
  499 +static gboolean v3270_accessible_add_selection(AtkText *text, gint start_pos, gint end_pos)
  500 +{
  501 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  502 +
  503 + if (widget == NULL)
  504 + return FALSE;
  505 +
  506 + if(!v3270_get_selection_bounds(widget,NULL,NULL))
  507 + {
  508 + v3270_select_region(widget, start_pos, end_pos);
  509 + return TRUE;
  510 + }
  511 +
  512 + return FALSE;
  513 +}
  514 +
  515 +static gboolean v3270_accessible_set_selection(AtkText *text, gint selection_num, gint start_pos, gint end_pos)
  516 +{
  517 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  518 + gint start, end;
  519 +
  520 + if(widget == NULL || selection_num != 0)
  521 + return FALSE;
  522 +
  523 + if(!v3270_get_selection_bounds(widget,NULL,NULL))
  524 + {
  525 + v3270_select_region(widget, start_pos, end_pos);
  526 + return TRUE;
  527 + }
  528 +
  529 + return FALSE;
  530 +}
  531 +
  532 +static AtkAttributeSet *add_attribute(AtkAttributeSet * attributes, AtkTextAttribute attr, const gchar *value)
  533 +{
  534 + AtkAttribute *at = g_new(AtkAttribute, 1);
  535 +
  536 + at->name = g_strdup (atk_text_attribute_get_name (attr));
  537 + at->value = g_strdup (value);
  538 +
  539 + return g_slist_prepend (attributes, at);
  540 +}
  541 +
  542 +static AtkAttributeSet * v3270_accessible_get_default_attributes (AtkText *text)
  543 +{
  544 + GtkWidget * widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  545 + AtkAttributeSet * attributes = NULL;
  546 +
  547 + if(!widget)
  548 + return NULL;
  549 +
  550 + trace("%s is incomplete ***********************",__FUNCTION__);
  551 +
  552 + // http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute
  553 +
  554 + // The direction of the text, if set. Values are "none", "ltr" or "rtl"
  555 + attributes = add_attribute(attributes, ATK_TEXT_ATTR_DIRECTION,atk_text_attribute_get_value(ATK_TEXT_ATTR_DIRECTION,gtk_widget_get_direction(widget)));
  556 +
  557 + return attributes;
  558 +}
  559 +
  560 +/**
  561 + * Creates an AtkAttributeSet which consists of the attributes explicitly
  562 + * set at the position offset in the text. start_offset and end_offset are set
  563 + * to the start and end of the range around offset where the attributes are invariant.
  564 + * Note that end_offset is the offset of the first character after the range.
  565 + * See the enum AtkTextAttribute for types of text attributes that can be returned.
  566 + * Note that other attributes may also be returned.
  567 + *
  568 + * @param text an AtkText
  569 + * @param offset the offset at which to get the attributes, -1 means the offset of the character to be inserted at the caret location.
  570 + * @param start_offset the address to put the start offset of the range
  571 + * @param end_offset the address to put the end offset of the range
  572 + *
  573 + * @return an AtkAttributeSet which contains the attributes explicitly set at offset.
  574 + */
  575 +static AtkAttributeSet * v3270_accessible_get_run_attributes(AtkText *text, gint offset, gint * start_offset, gint * end_offset)
  576 +{
  577 + GtkWidget * widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
  578 + H3270 * host;
  579 + AtkAttributeSet * attributes = NULL;
  580 + int start, end;
  581 +
  582 + trace("%s is incomplete ***********************",__FUNCTION__);
  583 +
  584 + g_return_val_if_fail((widget && GTK_IS_V3270(widget)),NULL);
  585 +
  586 + host = v3270_get_session(widget);
  587 +
  588 + if(offset == -1)
  589 + offset = lib3270_get_cursor_address(host);
  590 +
  591 + if(!lib3270_get_field_bounds(host,offset,&start,&end))
  592 + {
  593 + *start_offset = start;
  594 + *end_offset = end;
  595 + }
  596 +
  597 + // http://developer.gnome.org/atk/stable/AtkText.html#AtkTextAttribute
  598 +
  599 + // The direction of the text, if set. Values are "none", "ltr" or "rtl"
  600 + attributes = add_attribute(attributes, ATK_TEXT_ATTR_DIRECTION,atk_text_attribute_get_value(ATK_TEXT_ATTR_DIRECTION,gtk_widget_get_direction(widget)));
  601 +
  602 + // ATK_TEXT_ATTR_LEFT_MARGIN
  603 + // The pixel width of the left margin
  604 +
  605 + // ATK_TEXT_ATTR_RIGHT_MARGIN
  606 + // The pixel width of the right margin
  607 +
  608 + // ATK_TEXT_ATTR_INVISIBLE
  609 + // Either "true" or "false" indicating whether text is visible or not
  610 +
  611 + // Either "true" or "false" indicating whether text is editable or not
  612 + attributes = add_attribute( attributes,
  613 + ATK_TEXT_ATTR_EDITABLE,
  614 + lib3270_is_protected(host,offset) ? "false" : "true" );
  615 +
  616 + // The background color. The value is an RGB value of the format "u,u,u"
  617 + // ATK_TEXT_ATTR_BG_COLOR
  618 +
  619 + // The foreground color. The value is an RGB value of the format "u,u,u"
  620 + // ATK_TEXT_ATTR_FG_COLOR
  621 +
  622 + // The font family name
  623 + attributes = add_attribute( attributes,
  624 + ATK_TEXT_ATTR_FAMILY_NAME,
  625 + GTK_V3270(widget)->font_family );
  626 +
  627 + return attributes;
  628 +}
  629 +
  630 +/*
  631 +static gchar * v3270_accessible_get_text_after_offset(AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset)
  632 +{
  633 + // http://developer.gnome.org/atk/stable/AtkText.html#atk-text-get-text-after-offset
  634 + trace("WARNING: %s is incomplete",__FUNCTION__);
  635 +
  636 +}
  637 +*/
  638 +
  639 +/*
  640 +static gchar * v3270_accessible_get_text_before_offset(AtkText *text,gint offset,AtkTextBoundary boundary_type,gint *start_offset,gint *end_offset)
  641 +{
  642 + // http://developer.gnome.org/atk/stable/AtkText.html#atk-text-get-text-before-offset
  643 + trace("WARNING: %s is incomplete",__FUNCTION__);
  644 +
  645 +}
  646 +*/
  647 +
  648 +static void atk_text_interface_init(AtkTextIface *iface)
  649 +{
  650 + iface->get_text = v3270_accessible_get_text;
  651 + iface->get_character_at_offset = v3270_accessible_get_character_at_offset;
  652 +
  653 + iface->get_text_at_offset = v3270_accessible_get_text_at_offset;
  654 +
  655 + iface->get_character_count = v3270_accessible_get_character_count;
  656 + iface->get_caret_offset = v3270_accessible_get_caret_offset;
  657 + iface->set_caret_offset = v3270_set_caret_offset;
  658 +
  659 + iface->get_character_extents = v3270_accessible_get_character_extents;
  660 + iface->get_offset_at_point = v3270_accessible_get_offset_at_point;
  661 +
  662 + iface->get_n_selections = v3270_accessible_get_n_selections;
  663 + iface->add_selection = v3270_accessible_add_selection;
  664 + iface->remove_selection = v3270_accessible_remove_selection;
  665 + iface->set_selection = v3270_accessible_set_selection;
  666 + iface->get_selection = v3270_accessible_get_selection;
  667 + iface->get_run_attributes = v3270_accessible_get_run_attributes;
  668 + iface->get_default_attributes = v3270_accessible_get_default_attributes;
  669 +// iface->get_text_after_offset = v3270_accessible_get_text_after_offset;
  670 +// iface->get_text_before_offset = v3270_accessible_get_text_before_offset;
  671 +
  672 +}
  673 +
  674 +static void v3270_accessible_init(v3270Accessible *widget)
  675 +{
  676 + AtkObject *obj = ATK_OBJECT(widget);
  677 + obj->role = ATK_ROLE_TEXT;
  678 +}
  679 +
  680 +void v3270_accessible_get_extents(AtkComponent *component, gint *x, gint *y,gint *width,gint *height, AtkCoordType coord_type)
  681 +{
  682 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (component));
  683 + GdkWindow *window;
  684 + gint x_window, y_window;
  685 + GtkAllocation allocation;
  686 +
  687 + if (widget == NULL)
  688 + return;
  689 +
  690 + gtk_widget_get_allocation (widget, &allocation);
  691 + *width = allocation.width;
  692 + *height = allocation.height;
  693 +
  694 + if(gtk_widget_get_parent(widget))
  695 + {
  696 + *x = allocation.x;
  697 + *y = allocation.y;
  698 + window = gtk_widget_get_parent_window (widget);
  699 + }
  700 + else
  701 + {
  702 + *x = 0;
  703 + *y = 0;
  704 + window = gtk_widget_get_window (widget);
  705 + }
  706 +
  707 + gdk_window_get_origin(window, &x_window, &y_window);
  708 + *x += x_window;
  709 + *y += y_window;
  710 +
  711 + if (coord_type == ATK_XY_WINDOW)
  712 + {
  713 + gint x_toplevel, y_toplevel;
  714 +
  715 + window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
  716 + gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
  717 +
  718 + *x -= x_toplevel;
  719 + *y -= y_toplevel;
  720 + }
  721 +}
  722 +
  723 +static void v3270_accessible_get_size(AtkComponent *component,gint *width, gint *height)
  724 +{
  725 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
  726 +
  727 + if (widget == NULL)
  728 + return;
  729 +
  730 + *width = gtk_widget_get_allocated_width (widget);
  731 + *height = gtk_widget_get_allocated_height (widget);
  732 +}
  733 +
  734 +static gboolean v3270_accessible_grab_focus(AtkComponent *component)
  735 +{
  736 + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
  737 + GtkWidget *toplevel;
  738 +
  739 + if (!widget)
  740 + return FALSE;
  741 +
  742 + gtk_widget_grab_focus (widget);
  743 +
  744 + toplevel = gtk_widget_get_toplevel (widget);
  745 + if (gtk_widget_is_toplevel (toplevel))
  746 + {
  747 + #ifdef GDK_WINDOWING_X11
  748 + gtk_window_present_with_time (GTK_WINDOW (toplevel),gdk_x11_get_server_time(gtk_widget_get_window(widget)));
  749 + #else
  750 + gtk_window_present (GTK_WINDOW (toplevel));
  751 + #endif
  752 + }
  753 +
  754 + return TRUE;
  755 +}
  756 +
  757 +static AtkLayer v3270_accessible_get_layer (AtkComponent *component)
  758 +{
  759 + return ATK_LAYER_WIDGET;
  760 +}
  761 +
  762 +static gboolean v3270_accessible_set_size(AtkComponent *component, gint width, gint height)
  763 +{
  764 + GtkWidget *widget = gtk_accessible_get_widget(GTK_ACCESSIBLE (component));
  765 +
  766 + if (widget == NULL)
  767 + return FALSE;
  768 +
  769 + gtk_widget_set_size_request(widget, width, height);
  770 + return TRUE;
  771 +}
  772 +
  773 +static void atk_component_interface_init(AtkComponentIface *iface)
  774 +{
  775 + iface->get_extents = v3270_accessible_get_extents;
  776 + iface->get_size = v3270_accessible_get_size;
  777 + iface->grab_focus = v3270_accessible_grab_focus;
  778 + iface->get_layer = v3270_accessible_get_layer;
  779 + iface->set_size = v3270_accessible_set_size;
  780 +}
  781 +
  782 +void v3270_acessible_set_state(GtkAccessible *obj, LIB3270_MESSAGE id)
  783 +{
  784 + #ifdef DEBUG
  785 + #define STATE_MESSAGE(x,c) { #x, x, c }
  786 + #else
  787 + #define STATE_MESSAGE(x,c) { x, c }
  788 + #endif
  789 +
  790 + static const struct _state
  791 + {
  792 + #ifdef DEBUG
  793 + const gchar * dbg;
  794 + #endif
  795 + AtkStateType atkstate;
  796 + V3270_STATE flag;
  797 + } table[] =
  798 + {
  799 + STATE_MESSAGE(ATK_STATE_BUSY, V3270_STATE_BUSY ),
  800 + STATE_MESSAGE(ATK_STATE_EDITABLE, V3270_STATE_EDITABLE ),
  801 + STATE_MESSAGE(ATK_STATE_ENABLED, V3270_STATE_ENABLED ),
  802 + STATE_MESSAGE(ATK_STATE_INVALID_ENTRY, V3270_STATE_INVALID_ENTRY ),
  803 + };
  804 +
  805 + V3270_STATE state = GTK_V3270_ACCESSIBLE(obj)->state;
  806 + V3270_STATE bits;
  807 + int f;
  808 +
  809 + switch(id)
  810 + {
  811 + case LIB3270_MESSAGE_NONE:
  812 + state = V3270_STATE_EDITABLE|V3270_STATE_ENABLED;
  813 + break;
  814 +
  815 + case LIB3270_MESSAGE_SYSWAIT:
  816 + case LIB3270_MESSAGE_TWAIT:
  817 + case LIB3270_MESSAGE_RESOLVING:
  818 + case LIB3270_MESSAGE_CONNECTING:
  819 + state = V3270_STATE_BUSY;
  820 + break;
  821 +
  822 + case LIB3270_MESSAGE_CONNECTED:
  823 + case LIB3270_MESSAGE_AWAITING_FIRST:
  824 + state = V3270_STATE_ENABLED;
  825 + break;
  826 +
  827 + case LIB3270_MESSAGE_DISCONNECTED:
  828 + state = 0;
  829 + break;
  830 +
  831 + case LIB3270_MESSAGE_MINUS:
  832 + case LIB3270_MESSAGE_INHIBIT:
  833 + case LIB3270_MESSAGE_X:
  834 + break;
  835 +
  836 + case LIB3270_MESSAGE_PROTECTED:
  837 + case LIB3270_MESSAGE_NUMERIC:
  838 + case LIB3270_MESSAGE_OVERFLOW:
  839 + case LIB3270_MESSAGE_KYBDLOCK:
  840 + state = V3270_STATE_INVALID_ENTRY|V3270_STATE_EDITABLE|V3270_STATE_ENABLED;
  841 + break;
  842 +
  843 + }
  844 +
  845 + if(state == GTK_V3270_ACCESSIBLE(obj)->state)
  846 + return;
  847 +
  848 + bits = GTK_V3270_ACCESSIBLE(obj)->state ^ state;
  849 +
  850 + trace("State change from %04x to %04x (bits=%04x)",
  851 + GTK_V3270_ACCESSIBLE(obj)->state,
  852 + state, bits );
  853 +
  854 + for(f=0;f<G_N_ELEMENTS(table);f++)
  855 + {
  856 + if(bits & table[f].flag)
  857 + {
  858 + trace("State %s is %s",table[f].dbg,(state & table[f].flag) ? "Yes" : "No");
  859 + atk_object_notify_state_change(ATK_OBJECT(obj),table[f].atkstate,(state & table[f].flag) ? TRUE : FALSE);
  860 + }
  861 + }
  862 +
  863 + GTK_V3270_ACCESSIBLE(obj)->state = state;
  864 +}
  865 +
... ...
accessible.h 0 → 100644
  1 +++ a/accessible.h
... ... @@ -0,0 +1,73 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como accessible.h 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 <gtk/gtk.h>
  31 +
  32 +G_BEGIN_DECLS
  33 +
  34 +#define GTK_TYPE_V3270_ACCESSIBLE (v3270_accessible_get_type ())
  35 +#define GTK_V3270_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270_ACCESSIBLE, v3270Accessible))
  36 +#define GTK_V3270_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270_ACCESSIBLE, v3270AccessibleClass))
  37 +#define GTK_IS_V3270_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270_ACCESSIBLE))
  38 +#define GTK_IS_V3270_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270_ACCESSIBLE))
  39 +#define GTK_V3270_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270_ACCESSIBLE, v3270AccessibleClass))
  40 +
  41 +typedef struct _v3270Accessible v3270Accessible;
  42 +typedef struct _v3270AccessibleClass v3270AccessibleClass;
  43 +
  44 +typedef enum _v3270_state
  45 +{
  46 + V3270_STATE_NONE = 0x0000,
  47 + V3270_STATE_EDITABLE = 0x0001,
  48 + V3270_STATE_BUSY = 0x0002,
  49 + V3270_STATE_ENABLED = 0x0004,
  50 + V3270_STATE_INVALID_ENTRY = 0x0008,
  51 +
  52 +} V3270_STATE;
  53 +
  54 +struct _v3270Accessible
  55 +{
  56 + GtkAccessible parent;
  57 + V3270_STATE state;
  58 +
  59 +// AtkLayer layer;
  60 +};
  61 +
  62 +struct _v3270AccessibleClass
  63 +{
  64 + GtkAccessibleClass parent_class;
  65 +
  66 +
  67 +};
  68 +
  69 +GType v3270_accessible_get_type(void);
  70 +
  71 +void v3270_acessible_set_state(GtkAccessible *obj, LIB3270_MESSAGE id);
  72 +
  73 +G_END_DECLS
... ...
draw.c 0 → 100644
  1 +++ a/draw.c
... ... @@ -0,0 +1,397 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como draw.c 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 <gtk/gtk.h>
  31 + #include <pw3270.h>
  32 + #include <lib3270.h>
  33 + #include <lib3270/session.h>
  34 + #include "v3270.h"
  35 + #include "private.h"
  36 +
  37 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  38 +
  39 +gboolean v3270_draw(GtkWidget * widget, cairo_t * cr)
  40 +{
  41 + v3270 * terminal = GTK_V3270(widget);
  42 +
  43 + cairo_set_source_surface(cr,terminal->surface,0,0);
  44 + cairo_paint(cr);
  45 +
  46 + if(lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_CROSSHAIR) && (terminal->cursor.show&2))
  47 + {
  48 + GtkAllocation allocation;
  49 + gtk_widget_get_allocation(widget, &allocation);
  50 +
  51 + gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_CROSS_HAIR);
  52 +
  53 + cairo_rectangle(cr, 0,terminal->cursor.rect.y+terminal->metrics.height,allocation.width,1);
  54 + cairo_fill(cr);
  55 +
  56 + cairo_rectangle(cr, terminal->cursor.rect.x,0,1,terminal->oia_rect->y-3);
  57 + cairo_fill(cr);
  58 + }
  59 +
  60 + if(terminal->cursor.show == 3)
  61 + {
  62 + cairo_set_source_surface(cr,terminal->cursor.surface,terminal->cursor.rect.x,terminal->cursor.rect.y);
  63 +
  64 + if(lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_INSERT))
  65 + {
  66 + cairo_rectangle(cr, terminal->cursor.rect.x,
  67 + terminal->cursor.rect.y,
  68 + terminal->cursor.rect.width,
  69 + terminal->cursor.rect.height );
  70 + }
  71 + else
  72 + {
  73 + cairo_rectangle(cr, terminal->cursor.rect.x,
  74 + terminal->cursor.rect.y+terminal->metrics.height,
  75 + terminal->cursor.rect.width,
  76 + terminal->metrics.descent );
  77 + }
  78 +
  79 + cairo_fill(cr);
  80 + }
  81 +
  82 + return FALSE;
  83 +}
  84 +
  85 +#if( !GTK_CHECK_VERSION(3,0,0))
  86 +gboolean v3270_expose(GtkWidget *widget, GdkEventExpose *event)
  87 +{
  88 + cairo_t *cr = gdk_cairo_create(widget->window);
  89 + v3270_draw(widget,cr);
  90 + cairo_destroy(cr);
  91 + return FALSE;
  92 +}
  93 +#endif // GTk3
  94 +
  95 +
  96 +static void get_element_colors(unsigned short attr, GdkColor **fg, GdkColor **bg, GdkColor *color)
  97 +{
  98 + if(attr & LIB3270_ATTR_SELECTED)
  99 + {
  100 + *fg = color+V3270_COLOR_SELECTED_FG;
  101 + *bg = color+V3270_COLOR_SELECTED_BG;
  102 + }
  103 + else
  104 + {
  105 + *bg = color+((attr & 0x00F0) >> 4);
  106 +
  107 + if(attr & LIB3270_ATTR_FIELD)
  108 + *fg = color+(attr & 0x0003)+V3270_COLOR_FIELD;
  109 + else
  110 + *fg = color+(attr & 0x000F);
  111 + }
  112 +}
  113 +
  114 +void v3270_draw_element(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *color)
  115 +{
  116 + GdkColor *fg;
  117 + GdkColor *bg;
  118 +
  119 + get_element_colors(attr,&fg,&bg,color);
  120 + v3270_draw_char(cr,chr,attr,session,height,rect,fg,bg);
  121 +}
  122 +
  123 +void v3270_draw_char(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *fg, GdkColor *bg)
  124 +{
  125 + // Clear element area
  126 + gdk_cairo_set_source_color(cr,bg);
  127 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  128 + cairo_fill(cr);
  129 +
  130 + // Set foreground color
  131 + gdk_cairo_set_source_color(cr,fg);
  132 +
  133 + // Draw char
  134 + if(attr & LIB3270_ATTR_CG)
  135 + {
  136 + switch(chr)
  137 + {
  138 + case 0xd3: // CG 0xab, plus
  139 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y);
  140 + cairo_rel_line_to(cr,0,rect->height);
  141 + cairo_move_to(cr,rect->x,rect->y+(rect->height/2));
  142 + cairo_rel_line_to(cr,rect->width,0);
  143 + break;
  144 +
  145 + case 0xa2: // CG 0x92, horizontal line
  146 + cairo_move_to(cr,rect->x,rect->y+(rect->height/2));
  147 + cairo_rel_line_to(cr,rect->width,0);
  148 + break;
  149 +
  150 + case 0x85: // CG 0x184, vertical line
  151 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y);
  152 + cairo_rel_line_to(cr,0,rect->height);
  153 + break;
  154 +
  155 + case 0xd4: // CG 0xac, LR corner
  156 + cairo_move_to(cr,rect->x, rect->y+(rect->height/2));
  157 + cairo_rel_line_to(cr,rect->width/2,0);
  158 + cairo_rel_line_to(cr,0,-(rect->height/2));
  159 + break;
  160 +
  161 + case 0xd5: // CG 0xad, UR corner
  162 + cairo_move_to(cr,rect->x, rect->y+(rect->height/2));
  163 + cairo_rel_line_to(cr,rect->width/2,0);
  164 + cairo_rel_line_to(cr,0,rect->height/2);
  165 + break;
  166 +
  167 + case 0xc5: // CG 0xa4, UL corner
  168 + cairo_move_to(cr,rect->x+rect->width,rect->y+(rect->height/2));
  169 + cairo_rel_line_to(cr,-(rect->width/2),0);
  170 + cairo_rel_line_to(cr,0,(rect->height/2));
  171 + break;
  172 +
  173 + case 0xc4: // CG 0xa3, LL corner
  174 + cairo_move_to(cr,rect->x+rect->width,rect->y+(rect->height/2));
  175 + cairo_rel_line_to(cr,-(rect->width/2),0);
  176 + cairo_rel_line_to(cr,0,-(rect->height/2));
  177 + break;
  178 +
  179 + case 0xc6: // CG 0xa5, left tee
  180 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2));
  181 + cairo_rel_line_to(cr,rect->width/2,0);
  182 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y);
  183 + cairo_rel_line_to(cr,0,rect->height);
  184 + break;
  185 +
  186 + case 0xd6: // CG 0xae, right tee
  187 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2));
  188 + cairo_rel_line_to(cr,-(rect->width/2),0);
  189 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y);
  190 + cairo_rel_line_to(cr,0,rect->height);
  191 + break;
  192 +
  193 + case 0xc7: // CG 0xa6, bottom tee
  194 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2));
  195 + cairo_rel_line_to(cr,0,-(rect->height/2));
  196 + cairo_move_to(cr,rect->x,rect->y+(rect->height/2));
  197 + cairo_rel_line_to(cr,rect->width,0);
  198 + break;
  199 +
  200 + case 0xd7: // CG 0xaf, top tee
  201 + cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2));
  202 + cairo_rel_line_to(cr,0,rect->height/2);
  203 + cairo_move_to(cr,rect->x,rect->y+(rect->height/2));
  204 + cairo_rel_line_to(cr,rect->width,0);
  205 + break;
  206 +
  207 + case 0x8c: // CG 0xf7, less or equal "≤"
  208 + cairo_move_to(cr,rect->x,rect->y+height);
  209 + cairo_show_text(cr, "≤");
  210 + break;
  211 +
  212 + case 0xae: // CG 0xd9, greater or equal "≥"
  213 + cairo_move_to(cr,rect->x,rect->y+height);
  214 + cairo_show_text(cr, "≥");
  215 + break;
  216 +
  217 + case 0xbe: // CG 0x3e, not equal "≠"
  218 + cairo_move_to(cr,rect->x,rect->y+height);
  219 + cairo_show_text(cr, "≠");
  220 + break;
  221 +
  222 + case 0xad: // "["
  223 + cairo_move_to(cr,rect->x,rect->y+height);
  224 + cairo_show_text(cr, "[");
  225 + break;
  226 +
  227 + case 0xbd: // "]"
  228 + cairo_move_to(cr,rect->x,rect->y+height);
  229 + cairo_show_text(cr, "]");
  230 + break;
  231 +
  232 + default:
  233 + cairo_rectangle(cr, rect->x+1, rect->y+1, rect->width-2, rect->height-2);
  234 + }
  235 + }
  236 + else if(chr)
  237 + {
  238 + gchar *utf = g_convert((char *) &chr, 1, "UTF-8", lib3270_get_charset(session), NULL, NULL, NULL);
  239 +
  240 + if(utf)
  241 + {
  242 + cairo_move_to(cr,rect->x,rect->y+height);
  243 + cairo_show_text(cr, utf);
  244 + g_free(utf);
  245 + }
  246 + }
  247 + cairo_stroke(cr);
  248 +}
  249 +
  250 +void v3270_reload(GtkWidget *widget)
  251 +{
  252 + v3270 * terminal = GTK_V3270(widget);
  253 +
  254 +#if GTK_CHECK_VERSION(3,0,0)
  255 + gint width = gtk_widget_get_allocated_width(widget);
  256 + gint height = gtk_widget_get_allocated_height(widget);
  257 +#else
  258 + gint width = terminal->width;
  259 + gint height = terminal->height;
  260 +#endif
  261 +
  262 + GdkRectangle rect;
  263 + int addr, cursor, r, rows, cols;
  264 +
  265 + cairo_t * cr;
  266 +
  267 + if(!gtk_widget_get_realized(widget))
  268 + return;
  269 +
  270 + // Create new terminal image
  271 + if(terminal->surface)
  272 + cairo_surface_destroy(terminal->surface);
  273 +
  274 + terminal->surface = (cairo_surface_t *) gdk_window_create_similar_surface(gtk_widget_get_window(widget),CAIRO_CONTENT_COLOR,width,height);
  275 +
  276 + // Update the created image
  277 + cr = cairo_create(terminal->surface);
  278 + v3270_update_font_metrics(terminal, cr, width, height);
  279 +
  280 + gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_BACKGROUND);
  281 + cairo_rectangle(cr, 0, 0, width, height);
  282 + cairo_fill(cr);
  283 + cairo_stroke(cr);
  284 +
  285 + // Draw terminal contents
  286 + lib3270_get_screen_size(terminal->host,&rows,&cols);
  287 +
  288 + memset(&rect,0,sizeof(rect));
  289 + rect.y = terminal->metrics.top;
  290 + rect.width = terminal->metrics.width;
  291 + rect.height = terminal->metrics.spacing;
  292 + addr = 0;
  293 + cursor = lib3270_get_cursor_address(terminal->host);
  294 +
  295 + for(r = 0; r < rows; r++)
  296 + {
  297 + int c;
  298 +
  299 + rect.x = terminal->metrics.left;
  300 +
  301 + for(c=0;c < cols;c++)
  302 + {
  303 + unsigned char chr = 0;
  304 + unsigned short attr;
  305 +
  306 + lib3270_get_contents(terminal->host,addr,addr,&chr,&attr);
  307 +
  308 + if(addr == cursor)
  309 + v3270_update_cursor_rect(terminal,&rect,chr,attr);
  310 +
  311 + v3270_draw_element(cr,chr,attr,terminal->host,terminal->metrics.height,&rect,terminal->color);
  312 +
  313 + addr++;
  314 + rect.x += rect.width;
  315 + }
  316 +
  317 + rect.y += terminal->metrics.spacing;
  318 +
  319 + }
  320 +
  321 + v3270_draw_oia(cr, terminal->host, rect.y, cols, &terminal->metrics, terminal->color,terminal->oia_rect);
  322 +
  323 + cairo_destroy(cr);
  324 +
  325 +}
  326 +
  327 +void v3270_update_char(H3270 *session, int addr, unsigned char chr, unsigned short attr, unsigned char cursor)
  328 +{
  329 + v3270 * terminal = GTK_V3270(session->widget);
  330 + cairo_t * cr;
  331 + GdkRectangle rect;
  332 + int rows,cols;
  333 +
  334 + if(!gtk_widget_get_realized(GTK_WIDGET(terminal)))
  335 + return;
  336 +
  337 + if(!terminal->surface)
  338 + {
  339 + v3270_reload(GTK_WIDGET(terminal));
  340 + gtk_widget_queue_draw(GTK_WIDGET(terminal));
  341 + return;
  342 + }
  343 +
  344 + lib3270_get_screen_size(terminal->host,&rows,&cols);
  345 +
  346 + memset(&rect,0,sizeof(rect));
  347 + rect.x = terminal->metrics.left + ((addr % cols) * terminal->metrics.width);
  348 + rect.y = terminal->metrics.top + ((addr / cols) * terminal->metrics.spacing);
  349 + rect.width = terminal->metrics.width;
  350 + rect.height = terminal->metrics.spacing;
  351 +
  352 +// trace("%s: c=%c attr=%04x addr=%d pos=%d,%d x=%d y=%d w=%d h=%d",__FUNCTION__,chr,(int) attr,addr,(addr / cols),(addr % cols),rect.x,rect.y,rect.width,rect.height);
  353 +
  354 + cr = cairo_create(terminal->surface);
  355 + cairo_set_scaled_font(cr,terminal->font_scaled);
  356 + v3270_draw_element(cr, chr, attr, terminal->host, terminal->metrics.height, &rect,terminal->color);
  357 + cairo_destroy(cr);
  358 +
  359 + if(cursor)
  360 + v3270_update_cursor_rect(terminal,&rect,chr,attr);
  361 +
  362 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),rect.x,rect.y,rect.width,rect.height);
  363 +
  364 +}
  365 +
  366 +void v3270_update_cursor_surface(v3270 *widget,unsigned char chr,unsigned short attr)
  367 +{
  368 + if(widget->cursor.surface)
  369 + {
  370 + GdkRectangle rect = widget->cursor.rect;
  371 + cairo_t * cr = cairo_create(widget->cursor.surface);
  372 + GdkColor * fg;
  373 + GdkColor * bg;
  374 +
  375 + get_element_colors(attr,&fg,&bg,widget->color);
  376 +
  377 + cairo_set_scaled_font(cr,widget->font_scaled);
  378 +
  379 + rect.x = 0;
  380 + rect.y = 0;
  381 + v3270_draw_char(cr,chr,attr,widget->host,widget->metrics.height,&rect,bg,fg);
  382 +
  383 + cairo_destroy(cr);
  384 + }
  385 +
  386 +
  387 +}
  388 +
  389 +void v3270_update_cursor_rect(v3270 *widget, GdkRectangle *rect, unsigned char chr, unsigned short attr)
  390 +{
  391 + widget->cursor.chr = chr;
  392 + widget->cursor.rect = *rect;
  393 + widget->cursor.attr = attr;
  394 + widget->cursor.rect.height = widget->metrics.height + widget->metrics.descent;
  395 + v3270_update_cursor_surface(widget,chr,attr);
  396 +}
  397 +
... ...
genmarshal 0 → 100644
  1 +++ a/genmarshal
... ... @@ -0,0 +1,11 @@
  1 +VOID:VOID
  2 +VOID:VOID,ENUM,BOOL,POINTER
  3 +VOID:VOID,ENUM
  4 +VOID:VOID,POINTER
  5 +VOID:POINTER
  6 +VOID:VOID,POINTER,POINTER
  7 +VOID:VOID,UINT,POINTER
  8 +BOOL:VOID,UINT,ENUM
  9 +VOID:VOID,BOOL
  10 +BOOL:VOID,BOOL,BOOL,POINTER
  11 +VOID:VOID,UINT,UINT
... ...
iocallback.c 0 → 100644
  1 +++ a/iocallback.c
... ... @@ -0,0 +1,349 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como iocallback.c 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 + * licinio@bb.com.br (Licínio Luis Branco)
  28 + * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
  29 + *
  30 + */
  31 +
  32 +#if defined(_WIN32) /*[*/
  33 + #include <windows.h>
  34 +#elif defined(__APPLE__)
  35 + #include <poll.h>
  36 + #include <string.h>
  37 +#else
  38 + #include <poll.h>
  39 + #include <string.h>
  40 +#endif /*]*/
  41 +
  42 +#include <stdio.h>
  43 +#include <glib.h>
  44 +#include "../globals.h"
  45 +
  46 +#ifdef HAVE_MALLOC_H
  47 + #include <malloc.h>
  48 +#endif
  49 +
  50 +static int static_CallAndWait(int(*callback)(H3270 *session, void *), H3270 *session, void *parm);
  51 +static unsigned long static_AddInput(int source, H3270 *session, void (*fn)(H3270 *session));
  52 +static void static_RemoveSource(unsigned long id);
  53 +
  54 +#if !defined(_WIN32) /*[*/
  55 +static unsigned long static_AddOutput(int source, H3270 *session, void (*fn)(H3270 *session));
  56 +#endif
  57 +
  58 +static unsigned long static_AddExcept(int source, H3270 *session, void (*fn)(H3270 *session));
  59 +static unsigned long static_AddTimeOut(unsigned long interval_ms, H3270 *session, void (*proc)(H3270 *session));
  60 +static void static_RemoveTimeOut(unsigned long timer);
  61 +static int static_Sleep(int seconds);
  62 +static int static_RunPendingEvents(int wait);
  63 +
  64 +static gboolean IO_prepare(GSource *source, gint *timeout);
  65 +static gboolean IO_check(GSource *source);
  66 +static gboolean IO_dispatch(GSource *source, GSourceFunc callback, gpointer user_data);
  67 +static void IO_finalize(GSource *source); /* Can be NULL */
  68 +static gboolean IO_closure(gpointer data);
  69 +
  70 +/*---[ Structs ]-------------------------------------------------------------------------------------------*/
  71 +
  72 + typedef struct _IO_Source
  73 + {
  74 + GSource gsrc;
  75 + GPollFD poll;
  76 + int source;
  77 + void (*fn)(H3270 *session);
  78 + H3270 *session;
  79 + } IO_Source;
  80 +
  81 + typedef struct _timer
  82 + {
  83 + unsigned char remove;
  84 + void (*fn)(H3270 *session);
  85 + H3270 *session;
  86 + } TIMER;
  87 +
  88 + static GSourceFuncs IOSources =
  89 + {
  90 + IO_prepare,
  91 + IO_check,
  92 + IO_dispatch,
  93 + IO_finalize,
  94 + IO_closure,
  95 + NULL
  96 + };
  97 +
  98 +/*---[ Implement ]-----------------------------------------------------------------------------------------*/
  99 +
  100 +static unsigned long AddSource(int source, H3270 *session, gushort events, void (*fn)(H3270 *session))
  101 +{
  102 + IO_Source *src = (IO_Source *) g_source_new(&IOSources,sizeof(IO_Source));
  103 +
  104 + src->source = source;
  105 + src->fn = fn;
  106 + src->poll.fd = source;
  107 + src->poll.events = events;
  108 +
  109 + g_source_attach((GSource *) src,NULL);
  110 + g_source_add_poll((GSource *) src,&src->poll);
  111 +
  112 + return (unsigned long) src;
  113 +}
  114 +
  115 +static unsigned long static_AddInput(int source, H3270 *session, void (*fn)(H3270 *session))
  116 +{
  117 + return AddSource(source,session,G_IO_IN|G_IO_HUP|G_IO_ERR,fn);
  118 +}
  119 +
  120 +static void static_RemoveSource(unsigned long id)
  121 +{
  122 + if(id)
  123 + g_source_destroy((GSource *) id);
  124 +}
  125 +
  126 +#if !defined(_WIN32) /*[*/
  127 +static unsigned long static_AddOutput(int source, H3270 *session, void (*fn)(H3270 *session))
  128 +{
  129 + return AddSource(source,session,G_IO_OUT|G_IO_HUP|G_IO_ERR,fn);
  130 +}
  131 +#endif /*]*/
  132 +
  133 +static unsigned long static_AddExcept(int source, H3270 *session, void (*fn)(H3270 *session))
  134 +{
  135 +#if defined(_WIN32) /*[*/
  136 + return 0;
  137 +#else
  138 + return AddSource(source,session,G_IO_HUP|G_IO_ERR,fn);
  139 +#endif
  140 +}
  141 +
  142 +static gboolean do_timer(TIMER *t)
  143 +{
  144 + if(!t->remove)
  145 + t->fn(t->session);
  146 + return FALSE;
  147 +}
  148 +
  149 +static unsigned long static_AddTimeOut(unsigned long interval, H3270 *session, void (*proc)(H3270 *session))
  150 +{
  151 + TIMER *t = g_malloc(sizeof(TIMER));
  152 +
  153 + t->remove = 0;
  154 + t->fn = proc;
  155 + t->session = session;
  156 +
  157 + g_timeout_add_full(G_PRIORITY_DEFAULT, (guint) interval, (GSourceFunc) do_timer, t, g_free);
  158 +
  159 + return (unsigned long) t;
  160 +}
  161 +
  162 +static void static_RemoveTimeOut(unsigned long timer)
  163 +{
  164 + // FIXME (perry#2#): It this really necessary? The timeout is removed as soon as it ticks.
  165 + ((TIMER *) timer)->remove++;
  166 +}
  167 +
  168 +static gboolean IO_prepare(GSource *source, gint *timeout)
  169 +{
  170 + /*
  171 + * Called before all the file descriptors are polled.
  172 + * If the source can determine that it is ready here
  173 + * (without waiting for the results of the poll() call)
  174 + * it should return TRUE.
  175 + *
  176 + * It can also return a timeout_ value which should be the maximum
  177 + * timeout (in milliseconds) which should be passed to the poll() call.
  178 + * The actual timeout used will be -1 if all sources returned -1,
  179 + * or it will be the minimum of all the timeout_ values
  180 + * returned which were >= 0.
  181 + *
  182 + */
  183 + return 0;
  184 +}
  185 +
  186 +static gboolean IO_check(GSource *source)
  187 +{
  188 + /*
  189 + * Called after all the file descriptors are polled.
  190 + * The source should return TRUE if it is ready to be dispatched.
  191 + * Note that some time may have passed since the previous prepare
  192 + * function was called, so the source should be checked again here.
  193 + *
  194 + */
  195 +#if defined(_WIN32) /*[*/
  196 +
  197 + if(WaitForSingleObject((HANDLE) ((IO_Source *) source)->source,0) == WAIT_OBJECT_0)
  198 + return TRUE;
  199 +
  200 +#else /*][*/
  201 +
  202 + struct pollfd fds;
  203 +
  204 + memset(&fds,0,sizeof(fds));
  205 +
  206 + fds.fd = ((IO_Source *) source)->poll.fd;
  207 + fds.events = ((IO_Source *) source)->poll.events;
  208 +
  209 + if(poll(&fds,1,0) > 0)
  210 + return TRUE;
  211 +
  212 +#endif /*]*/
  213 +
  214 + return FALSE;
  215 +}
  216 +
  217 +static gboolean IO_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
  218 +{
  219 + /*
  220 + * Called to dispatch the event source,
  221 + * after it has returned TRUE in either its prepare or its check function.
  222 + * The dispatch function is passed in a callback function and data.
  223 + * The callback function may be NULL if the source was never connected
  224 + * to a callback using g_source_set_callback(). The dispatch function
  225 + * should call the callback function with user_data and whatever additional
  226 + * parameters are needed for this type of event source.
  227 + */
  228 + ((IO_Source *) source)->fn(((IO_Source *) source)->session);
  229 + return TRUE;
  230 +}
  231 +
  232 +static void IO_finalize(GSource *source)
  233 +{
  234 +
  235 +}
  236 +
  237 +static gboolean IO_closure(gpointer data)
  238 +{
  239 + return 0;
  240 +}
  241 +
  242 +struct bgParameter
  243 +{
  244 + gboolean running;
  245 + H3270 *session;
  246 + int rc;
  247 + int(*callback)(H3270 *session, void *);
  248 + void *parm;
  249 +
  250 +};
  251 +
  252 +gpointer BgCall(struct bgParameter *p)
  253 +{
  254 + trace("%s starts",__FUNCTION__);
  255 + p->rc = p->callback(p->session, p->parm);
  256 + p->running = FALSE;
  257 + trace("%s ends",__FUNCTION__);
  258 + return 0;
  259 +}
  260 +
  261 +static int static_CallAndWait(int(*callback)(H3270 *session, void *), H3270 *session, void *parm)
  262 +{
  263 + struct bgParameter p = { TRUE, session, -1, callback, parm };
  264 + GThread *thread;
  265 +
  266 + trace("Starting auxiliary thread for callback %p",callback);
  267 +
  268 + p.running = TRUE;
  269 + thread = g_thread_create( (GThreadFunc) BgCall, &p, 0, NULL);
  270 +
  271 + if(!thread)
  272 + {
  273 + g_error("Can't start background thread");
  274 + return -1;
  275 + }
  276 +
  277 + while(p.running)
  278 + gtk_main_iteration();
  279 +
  280 + return p.rc;
  281 +}
  282 +
  283 +static int static_Sleep(int seconds)
  284 +{
  285 + time_t end = time(0) + seconds;
  286 +
  287 + while(time(0) < end)
  288 + gtk_main_iteration();
  289 +
  290 + return 0;
  291 +}
  292 +
  293 +static int static_RunPendingEvents(int wait)
  294 +{
  295 + int rc = 0;
  296 + while(gtk_events_pending())
  297 + {
  298 + rc = 1;
  299 + gtk_main_iteration();
  300 + }
  301 +
  302 + if(wait)
  303 + gtk_main_iteration();
  304 +
  305 + return rc;
  306 +}
  307 +
  308 +static void beep(H3270 *session)
  309 +{
  310 + gdk_beep();
  311 +}
  312 +
  313 +void v3270_register_io_handlers(v3270Class *cls)
  314 +{
  315 + static const struct lib3270_callbacks hdl =
  316 + {
  317 + sizeof(struct lib3270_callbacks),
  318 +
  319 + static_AddTimeOut,
  320 + static_RemoveTimeOut,
  321 +
  322 + static_AddInput,
  323 + static_RemoveSource,
  324 +
  325 + static_AddExcept,
  326 +
  327 +#if !defined(_WIN32)
  328 + static_AddOutput,
  329 +#endif
  330 +
  331 +#ifdef G_THREADS_ENABLED
  332 + static_CallAndWait,
  333 +#else
  334 + NULL,
  335 +#endif
  336 +
  337 + static_Sleep,
  338 + static_RunPendingEvents,
  339 + beep
  340 +
  341 + };
  342 +
  343 + if(lib3270_register_handlers(&hdl))
  344 + {
  345 + g_error("%s",_( "Can't set lib3270 I/O handlers" ) );
  346 + }
  347 +
  348 + trace("%s: I/O handlers OK",__FUNCTION__);
  349 +}
... ...
keyboard.c 0 → 100644
  1 +++ a/keyboard.c
... ... @@ -0,0 +1,241 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como keyboard.c 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 + * licinio@bb.com.br (Licínio Luis Branco)
  28 + * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
  29 + * macmiranda@bb.com.br (Marco Aurélio Caldas Miranda)
  30 + *
  31 + */
  32 +
  33 + #include <pw3270.h>
  34 + #include <lib3270.h>
  35 + #include <lib3270/actions.h>
  36 + #include <gtk/gtk.h>
  37 + #include <string.h>
  38 + #include <gdk/gdk.h>
  39 +
  40 + #include "v3270.h"
  41 + #include "private.h"
  42 +
  43 +#if GTK_CHECK_VERSION(3,0,0)
  44 + #include <gdk/gdkkeysyms-compat.h>
  45 +#else
  46 + #include <gdk/gdkkeysyms.h>
  47 +#endif
  48 +
  49 +#ifndef GDK_ALT_MASK
  50 + #define GDK_ALT_MASK GDK_MOD1_MASK
  51 +#endif
  52 +
  53 +#ifndef GDK_NUMLOCK_MASK
  54 + #define GDK_NUMLOCK_MASK GDK_MOD2_MASK
  55 +#endif
  56 +
  57 +
  58 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  59 +
  60 + #define keyval_is_alt() (event->keyval == GDK_Alt_L || event->keyval == GDK_Meta_L || event->keyval == GDK_ISO_Level3_Shift)
  61 +
  62 + static void update_keyboard_state(v3270 *terminal, GdkEventKey *event, gboolean status)
  63 + {
  64 + if(event->keyval == GDK_Shift_R || event->keyval == GDK_Shift_L)
  65 + {
  66 + if(status)
  67 + terminal->keyflags |= KEY_FLAG_SHIFT;
  68 + else
  69 + terminal->keyflags &= ~KEY_FLAG_SHIFT;
  70 + v3270_draw_shift_status(terminal);
  71 + }
  72 +
  73 + if(keyval_is_alt())
  74 + {
  75 + if(status)
  76 + terminal->keyflags |= KEY_FLAG_ALT;
  77 + else
  78 + terminal->keyflags &= ~KEY_FLAG_ALT;
  79 + v3270_draw_alt_status(terminal);
  80 + }
  81 +
  82 + }
  83 +
  84 + static gboolean check_keypress(v3270 *widget, GdkEventKey *event)
  85 + {
  86 + static const struct _keycode
  87 + {
  88 + guint keyval;
  89 + GdkModifierType state;
  90 + int (*exec)(H3270 *session);
  91 + } keycode[] =
  92 + {
  93 + { GDK_Left, 0, lib3270_cursor_left },
  94 + { GDK_Up, 0, lib3270_cursor_up },
  95 + { GDK_Right, 0, lib3270_cursor_right },
  96 + { GDK_Down, 0, lib3270_cursor_down },
  97 + { GDK_Tab, 0, lib3270_tab },
  98 + { GDK_ISO_Left_Tab, GDK_SHIFT_MASK, lib3270_backtab },
  99 + { GDK_KP_Left, 0, lib3270_cursor_left },
  100 + { GDK_KP_Up, 0, lib3270_cursor_up },
  101 + { GDK_KP_Right, 0, lib3270_cursor_right },
  102 + { GDK_KP_Down, 0, lib3270_cursor_down },
  103 +
  104 + { GDK_KP_Add, GDK_NUMLOCK_MASK, NULL },
  105 + { GDK_KP_Subtract, GDK_NUMLOCK_MASK, NULL },
  106 +
  107 + { GDK_3270_PrintScreen, 0, NULL },
  108 + { GDK_Sys_Req, 0, lib3270_sysreq },
  109 +
  110 + { GDK_Print, GDK_CONTROL_MASK, NULL },
  111 + { GDK_Print, GDK_SHIFT_MASK, lib3270_sysreq },
  112 + { GDK_Control_R, 0, NULL },
  113 + { GDK_Control_L, 0, NULL },
  114 +
  115 +#ifdef WIN32
  116 + { GDK_Pause, 0, NULL },
  117 +#endif
  118 + };
  119 +
  120 + int f;
  121 + int state = event->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_ALT_MASK);
  122 + gboolean handled = FALSE;
  123 +
  124 +#ifdef WIN32
  125 + // FIXME (perry#1#): Find a better way!
  126 + if( event->keyval == 0xffffff && event->hardware_keycode == 0x0013)
  127 + event->keyval = GDK_Pause;
  128 +
  129 + // Windows sets <ctrl> in left/right control
  130 + else if(state & GDK_CONTROL_MASK && (event->keyval == GDK_Control_R || event->keyval == GDK_Control_L))
  131 + state &= ~GDK_CONTROL_MASK;
  132 +#endif
  133 +
  134 + g_signal_emit(GTK_WIDGET(widget), v3270_widget_signal[SIGNAL_KEYPRESS], 0, event->keyval, state, &handled);
  135 + if(handled)
  136 + return TRUE;
  137 +
  138 + if(event->keyval >= GDK_F1 && event->keyval <= GDK_F12 && !(state & (GDK_CONTROL_MASK|GDK_ALT_MASK)))
  139 + {
  140 + int pfcode = (event->keyval - GDK_F1) + ((state & GDK_SHIFT_MASK) ? 13 : 1);
  141 + if(pfcode > 0 && pfcode < 25)
  142 + {
  143 + lib3270_pfkey(widget->host,pfcode);
  144 + return TRUE;
  145 + }
  146 + }
  147 +
  148 + for(f=0; f < G_N_ELEMENTS(keycode);f++)
  149 + {
  150 + if(keycode[f].keyval == event->keyval && state == keycode[f].state)
  151 + {
  152 + if(keycode[f].exec)
  153 + {
  154 + keycode[f].exec(widget->host);
  155 + return TRUE;
  156 + }
  157 + }
  158 + }
  159 +
  160 + return FALSE;
  161 + }
  162 +
  163 + gboolean v3270_key_press_event(GtkWidget *widget, GdkEventKey *event)
  164 + {
  165 + v3270 * terminal = GTK_V3270(widget);
  166 +
  167 + update_keyboard_state(terminal,event,TRUE);
  168 +
  169 + if(gtk_im_context_filter_keypress(terminal->input_method,event))
  170 + return TRUE;
  171 +
  172 + if(check_keypress(terminal,event))
  173 + {
  174 + gtk_im_context_reset(terminal->input_method);
  175 + return TRUE;
  176 + }
  177 +
  178 + return FALSE;
  179 +
  180 + }
  181 +
  182 + gboolean v3270_key_release_event(GtkWidget *widget, GdkEventKey *event)
  183 + {
  184 + v3270 * terminal = GTK_V3270(widget);
  185 +
  186 + update_keyboard_state(terminal,event,FALSE);
  187 +
  188 + if(gtk_im_context_filter_keypress(terminal->input_method,event))
  189 + return TRUE;
  190 +
  191 + return FALSE;
  192 +
  193 + }
  194 +
  195 + void v3270_tab(GtkWidget *widget)
  196 + {
  197 + g_return_if_fail(GTK_IS_V3270(widget));
  198 + lib3270_tab(GTK_V3270(widget)->host);
  199 + }
  200 +
  201 + void v3270_backtab(GtkWidget *widget)
  202 + {
  203 + g_return_if_fail(GTK_IS_V3270(widget));
  204 + lib3270_backtab(GTK_V3270(widget)->host);
  205 + }
  206 +
  207 + void v3270_set_string(GtkWidget *widget, const gchar *str)
  208 + {
  209 + H3270 *host;
  210 + gchar *utf;
  211 +
  212 + g_return_if_fail(GTK_IS_V3270(widget));
  213 +
  214 + host = GTK_V3270(widget)->host;
  215 +
  216 + utf = g_convert((char *) str, -1, lib3270_get_charset(host), "UTF-8", NULL, NULL, NULL);
  217 +
  218 + if(utf)
  219 + {
  220 + lib3270_set_string(host, (const unsigned char *) utf);
  221 + g_free(utf);
  222 + }
  223 +
  224 + }
  225 +
  226 + void v3270_key_commit(GtkIMContext *imcontext, gchar *str, v3270 *widget)
  227 + {
  228 + gchar *utf = g_convert((char *) str, -1, lib3270_get_charset(widget->host), "UTF-8", NULL, NULL, NULL);
  229 +
  230 + if(utf)
  231 + {
  232 + lib3270_set_string(GTK_V3270(widget)->host, (const unsigned char *) utf);
  233 + g_free(utf);
  234 + }
  235 + else
  236 + {
  237 + lib3270_ring_bell(widget->host);
  238 + }
  239 + }
  240 +
  241 +
... ...
locked.xbm 0 → 100644
  1 +++ a/locked.xbm
... ... @@ -0,0 +1,14 @@
  1 +#define locked_width 32
  2 +#define locked_height 32
  3 +static unsigned char locked_bits[] = {
  4 + 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x07, 0xe0, 0x00,
  5 + 0x80, 0x03, 0xc0, 0x01, 0xc0, 0xf1, 0x8f, 0x03, 0xc0, 0xf8, 0x1f, 0x03,
  6 + 0xc0, 0x1c, 0x38, 0x03, 0xc0, 0x0c, 0x30, 0x03, 0xc0, 0x0c, 0x30, 0x03,
  7 + 0xc0, 0x0c, 0x30, 0x03, 0xc0, 0x0c, 0x30, 0x03, 0xc0, 0x0c, 0x30, 0x03,
  8 + 0xc0, 0x0c, 0x30, 0x03, 0xc0, 0x0c, 0x30, 0x03, 0xf0, 0xff, 0xff, 0x0f,
  9 + 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xcc, 0xcc, 0x0c, 0xf0, 0xcc, 0xcc, 0x0c,
  10 + 0x30, 0x33, 0x33, 0x0f, 0x30, 0x33, 0x33, 0x0f, 0xf0, 0xcc, 0xcc, 0x0c,
  11 + 0xf0, 0xcc, 0xcc, 0x0c, 0x30, 0x33, 0x33, 0x0f, 0x30, 0x33, 0x33, 0x0f,
  12 + 0xf0, 0xcc, 0xcc, 0x0c, 0xf0, 0xcc, 0xcc, 0x0c, 0x30, 0x33, 0x33, 0x0f,
  13 + 0x30, 0x33, 0x33, 0x0f, 0xf0, 0xcc, 0xcc, 0x0c, 0xf0, 0xcc, 0xcc, 0x0c,
  14 + 0xf0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x0f };
... ...
mouse.c 0 → 100644
  1 +++ a/mouse.c
... ... @@ -0,0 +1,263 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como mouse.c 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 <gtk/gtk.h>
  31 + #include <gdk/gdk.h>
  32 + #include <pw3270.h>
  33 + #include "v3270.h"
  34 + #include "private.h"
  35 + #include <lib3270/selection.h>
  36 + #include <lib3270/actions.h>
  37 +
  38 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  39 +
  40 +gint v3270_get_offset_at_point(v3270 *widget, gint x, gint y)
  41 +{
  42 + GdkPoint point;
  43 + int r,c;
  44 +
  45 + if(x > 0 && y > 0)
  46 + {
  47 + point.x = ((x-widget->metrics.left)/widget->metrics.width);
  48 + point.y = ((y-widget->metrics.top)/widget->metrics.spacing);
  49 +
  50 + lib3270_get_screen_size(widget->host,&r,&c);
  51 +
  52 + if(point.x >= 0 && point.y >= 0 && point.x < c && point.y < r)
  53 + return (point.y * c) + point.x;
  54 + }
  55 +
  56 + return -1;
  57 +}
  58 +
  59 +static void single_click(v3270 *widget, int baddr)
  60 +{
  61 + switch(lib3270_get_selection_flags(widget->host,baddr))
  62 + {
  63 + case 0x00:
  64 + // Unselected area, move cursor and remove selection
  65 + lib3270_set_cursor_address(widget->host,baddr);
  66 + lib3270_unselect(widget->host);
  67 + widget->selecting = 1;
  68 + break;
  69 +
  70 +
  71 + default:
  72 + // Move selected area
  73 + trace("%s: default action",__FUNCTION__);
  74 + widget->selection_addr = baddr;
  75 + widget->moving = 1;
  76 + }
  77 +
  78 +
  79 +}
  80 +
  81 +static void button_1_press(GtkWidget *widget, GdkEventType type, int baddr)
  82 +{
  83 + switch(type)
  84 + {
  85 + case GDK_BUTTON_PRESS: // Single click - set mode
  86 + single_click(GTK_V3270(widget),baddr);
  87 + break;
  88 +
  89 + case GDK_2BUTTON_PRESS: // Double click - Select word
  90 + if(lib3270_select_word_at(GTK_V3270(widget)->host,baddr));
  91 + lib3270_ring_bell(GTK_V3270(widget)->host);
  92 + break;
  93 +
  94 + case GDK_3BUTTON_PRESS: // Triple clock - Select field
  95 + if(lib3270_select_field_at(GTK_V3270(widget)->host,baddr))
  96 + lib3270_ring_bell(GTK_V3270(widget)->host);
  97 + break;
  98 +
  99 +#ifdef DEBUG
  100 + default:
  101 + trace("Unexpected button 1 type %d",type);
  102 +#endif
  103 + }
  104 +}
  105 +
  106 +void v3270_emit_popup(v3270 *widget, int baddr, GdkEventButton *event)
  107 +{
  108 + unsigned char chr = 0;
  109 + unsigned short attr;
  110 + gboolean handled = FALSE;
  111 +
  112 + lib3270_get_contents(widget->host,baddr,baddr,&chr,&attr);
  113 +
  114 + g_signal_emit(GTK_WIDGET(widget), v3270_widget_signal[SIGNAL_POPUP], 0,
  115 + (attr & LIB3270_ATTR_SELECTED) ? TRUE : FALSE,
  116 + lib3270_connected(widget->host) ? TRUE : FALSE,
  117 + event,
  118 + &handled);
  119 +
  120 + if(handled)
  121 + return;
  122 +
  123 + gdk_beep();
  124 +}
  125 +
  126 +gboolean v3270_button_press_event(GtkWidget *widget, GdkEventButton *event)
  127 +{
  128 + int baddr = v3270_get_offset_at_point(GTK_V3270(widget),event->x,event->y);
  129 +
  130 + if(baddr < 0)
  131 + return FALSE;
  132 +
  133 +// trace("%s button=%d type=%d",__FUNCTION__,event->button,event->type);
  134 +
  135 + switch(event->button)
  136 + {
  137 + case 1: // Left button
  138 + button_1_press(widget,event->type,baddr);
  139 + break;
  140 +
  141 + case 3: // Right button
  142 + if(event->type == GDK_BUTTON_PRESS)
  143 + v3270_emit_popup(GTK_V3270(widget),baddr,event);
  144 + break;
  145 +
  146 + default:
  147 + trace("%s button=%d type=%d",__FUNCTION__,event->button,event->type);
  148 + }
  149 +
  150 + return FALSE;
  151 +}
  152 +
  153 +gboolean v3270_button_release_event(GtkWidget *widget, GdkEventButton*event)
  154 +{
  155 + switch(event->button)
  156 + {
  157 + case 1:
  158 + GTK_V3270(widget)->selecting = 0;
  159 + GTK_V3270(widget)->moving = 0;
  160 + GTK_V3270(widget)->resizing = 0;
  161 + break;
  162 +
  163 + default:
  164 + trace("%s button=%d type=%d",__FUNCTION__,event->button,event->type);
  165 + }
  166 +
  167 +
  168 + return FALSE;
  169 +}
  170 +
  171 +
  172 +static void update_mouse_pointer(GtkWidget *widget, int baddr)
  173 +{
  174 + v3270 *terminal = GTK_V3270(widget);
  175 +
  176 + if(baddr >= 0 && terminal->pointer_id == LIB3270_CURSOR_EDITABLE)
  177 + {
  178 + int id = terminal->pointer;
  179 +
  180 + switch(lib3270_get_selection_flags(terminal->host,baddr) & 0x8f)
  181 + {
  182 + case 0x80:
  183 + id = V3270_CURSOR_MOVE_SELECTION;
  184 + break;
  185 +
  186 + case 0x82:
  187 + id = V3270_CURSOR_SELECTION_TOP;
  188 + break;
  189 +
  190 + case 0x86:
  191 + id = V3270_CURSOR_SELECTION_TOP_RIGHT;
  192 + break;
  193 +
  194 + case 0x84:
  195 + id = V3270_CURSOR_SELECTION_RIGHT;
  196 + break;
  197 +
  198 + case 0x81:
  199 + id = V3270_CURSOR_SELECTION_LEFT;
  200 + break;
  201 +
  202 + case 0x89:
  203 + id = V3270_CURSOR_SELECTION_BOTTOM_LEFT;
  204 + break;
  205 +
  206 + case 0x88:
  207 + id = V3270_CURSOR_SELECTION_BOTTOM;
  208 + break;
  209 +
  210 + case 0x8c:
  211 + id = V3270_CURSOR_SELECTION_BOTTOM_RIGHT;
  212 + break;
  213 +
  214 + case 0x83:
  215 + id = V3270_CURSOR_SELECTION_TOP_LEFT;
  216 + break;
  217 +
  218 + default:
  219 + id = lib3270_is_protected(terminal->host,baddr) ? V3270_CURSOR_PROTECTED : V3270_CURSOR_UNPROTECTED;
  220 +
  221 + }
  222 +
  223 + gdk_window_set_cursor(gtk_widget_get_window(widget),v3270_cursor[id]);
  224 + }
  225 +
  226 +}
  227 +
  228 +void v3270_update_mouse_pointer(GtkWidget *widget)
  229 +{
  230 + gint x, y;
  231 +
  232 +#if GTK_CHECK_VERSION(3,4,0)
  233 + #warning Implement gdk_window_get_device_position
  234 +#endif // GTK(3,4,0)
  235 +
  236 + gtk_widget_get_pointer(widget,&x,&y);
  237 + update_mouse_pointer(widget,v3270_get_offset_at_point(GTK_V3270(widget),x,y));
  238 +}
  239 +
  240 +gboolean v3270_motion_notify_event(GtkWidget *widget, GdkEventMotion *event)
  241 +{
  242 + v3270 * terminal = GTK_V3270(widget);
  243 + int baddr = v3270_get_offset_at_point(terminal,event->x,event->y);
  244 +
  245 + if(baddr >= 0)
  246 + {
  247 + if(terminal->selecting) // Select region
  248 + {
  249 + lib3270_select_to(terminal->host,baddr);
  250 + }
  251 + if(terminal->moving) // Move selected area
  252 + {
  253 + terminal->selection_addr = lib3270_drag_selection(terminal->host,terminal->pointer,terminal->selection_addr,baddr);
  254 + }
  255 + else
  256 + {
  257 + terminal->pointer = lib3270_get_selection_flags(terminal->host,baddr);
  258 + update_mouse_pointer(widget,baddr);
  259 + }
  260 + }
  261 +
  262 + return FALSE;
  263 +}
... ...
oia.c 0 → 100644
  1 +++ a/oia.c
... ... @@ -0,0 +1,1032 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como oia.c 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 <pw3270.h>
  31 + #include <lib3270.h>
  32 + #include <lib3270/session.h>
  33 + #include <lib3270/config.h>
  34 + #include <gtk/gtk.h>
  35 + #include <string.h>
  36 +
  37 + #ifdef HAVE_LIBM
  38 + #include <math.h>
  39 + #endif // HAVE_LIBM
  40 +
  41 + #include "v3270.h"
  42 + #include "private.h"
  43 +
  44 +/*--[ Prototipes ]-----------------------------------------------------------------------------------*/
  45 +
  46 +static void draw_cursor_position(cairo_t *cr, GdkRectangle *rect, struct v3270_metrics *metrics, int row, int col);
  47 +
  48 +/*--[ Statics ]--------------------------------------------------------------------------------------*/
  49 +
  50 + #include "locked.xbm"
  51 + #include "unlocked.xbm"
  52 +
  53 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  54 +
  55 +static void short2string(char *ptr, unsigned short vlr, size_t sz)
  56 +{
  57 + int f;
  58 +
  59 + for(f=sz-1;f>=0;f--)
  60 + {
  61 + ptr[f] = '0'+(vlr%10);
  62 + vlr /= 10;
  63 + }
  64 +}
  65 +
  66 +
  67 +#ifdef HAVE_LIBM
  68 +static gint draw_spinner(cairo_t *cr, GdkRectangle *r, GdkColor *color, gint step)
  69 +{
  70 + static const guint num_steps = 10;
  71 +
  72 + gdouble dx = r->width/2;
  73 + gdouble dy = r->height/2;
  74 + gdouble radius = MIN (r->width / 2, r->height / 2);
  75 + gdouble half = num_steps / 2;
  76 + gint i;
  77 +
  78 + cairo_save(cr);
  79 + cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
  80 +
  81 + cairo_rectangle(cr, r->x, r->y, r->width, r->height);
  82 + cairo_clip(cr);
  83 + cairo_translate(cr, r->x, r->y);
  84 +
  85 + step++;
  86 + step %= num_steps;
  87 +
  88 + for (i = 0; i < num_steps; i++)
  89 + {
  90 + gint inset = 0.7 * radius;
  91 +
  92 + /* transparency is a function of time and intial value */
  93 + gdouble t = (gdouble) ((i + num_steps - step) % num_steps) / num_steps;
  94 +
  95 + cairo_save(cr);
  96 +
  97 + cairo_set_source_rgba (cr,
  98 + color[V3270_COLOR_OIA_SPINNER].red / 65535.,
  99 + color[V3270_COLOR_OIA_SPINNER].green / 65535.,
  100 + color[V3270_COLOR_OIA_SPINNER].blue / 65535.,
  101 + t);
  102 +
  103 + cairo_set_line_width (cr, 2.0);
  104 + cairo_move_to (cr,
  105 + dx + (radius - inset) * cos (i * G_PI / half),
  106 + dy + (radius - inset) * sin (i * G_PI / half));
  107 + cairo_line_to (cr,
  108 + dx + radius * cos (i * G_PI / half),
  109 + dy + radius * sin (i * G_PI / half));
  110 + cairo_stroke (cr);
  111 +
  112 + cairo_restore (cr);
  113 + }
  114 +
  115 + cairo_restore(cr);
  116 +
  117 + return step;
  118 +}
  119 +#endif // HAVE_LIBM
  120 +
  121 +static void setup_cursor_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  122 +{
  123 + rect->width = metrics->width * 8;
  124 + rect->x -= rect->width;
  125 +
  126 + if(lib3270_get_toggle(host,LIB3270_TOGGLE_CURSOR_POS))
  127 + {
  128 + int addr = lib3270_get_cursor_address(host);
  129 + draw_cursor_position(cr,rect,metrics,addr/cols,addr%cols);
  130 + }
  131 +}
  132 +
  133 +static void setup_timer_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  134 +{
  135 + char buffer[7];
  136 + cairo_text_extents_t extents;
  137 +
  138 + short2string(buffer,0,2);
  139 + buffer[2] = ':';
  140 + short2string(buffer+3,0,2);
  141 + buffer[5] = 0;
  142 +
  143 + cairo_text_extents(cr,buffer,&extents);
  144 + rect->width = ((int) extents.width + 2);
  145 + rect->x -= rect->width;
  146 +}
  147 +
  148 +static void setup_spinner_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  149 +{
  150 + rect->width = rect->height;
  151 + rect->x -= rect->width;
  152 +// draw_spinner(cr,rect,color,0);
  153 +}
  154 +
  155 +static void setup_luname_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  156 +{
  157 + const char *luname = lib3270_get_luname(host);
  158 +
  159 + rect->width *= 16;
  160 + rect->x -= rect->width;
  161 +
  162 + cairo_save(cr);
  163 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  164 + cairo_clip(cr);
  165 +
  166 +#ifdef DEBUG
  167 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  168 +#else
  169 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_BACKGROUND);
  170 +#endif
  171 +
  172 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  173 + cairo_fill(cr);
  174 +
  175 + if(luname)
  176 + {
  177 + cairo_move_to(cr,rect->x,rect->y+metrics->height);
  178 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_LUNAME);
  179 + cairo_show_text(cr,luname);
  180 + cairo_stroke(cr);
  181 + }
  182 +
  183 + cairo_restore(cr);
  184 +
  185 +}
  186 +
  187 +static void setup_single_char_right(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  188 +{
  189 + rect->x -= rect->width;
  190 +
  191 +#ifdef DEBUG
  192 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  193 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  194 + cairo_fill(cr);
  195 +#endif
  196 +
  197 +}
  198 +
  199 +static void setup_insert_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  200 +{
  201 + if(rect->width > rect->height)
  202 + {
  203 + rect->width = rect->height;
  204 + }
  205 + else if(rect->height > rect->width)
  206 + {
  207 + rect->y += (rect->height - rect->width)/2;
  208 + rect->height = rect->width;
  209 + }
  210 +
  211 + rect->x -= rect->width;
  212 +
  213 +#ifdef DEBUG
  214 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  215 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  216 + cairo_fill(cr);
  217 +#endif
  218 +
  219 +}
  220 +
  221 +
  222 +
  223 +static void setup_double_char_position(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color)
  224 +{
  225 + rect->width <<= 1;
  226 + rect->x -= rect->width;
  227 +
  228 +#ifdef DEBUG
  229 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  230 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  231 + cairo_fill(cr);
  232 +#endif
  233 +
  234 +}
  235 +
  236 +static void draw_undera(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect)
  237 +{
  238 +#ifdef DEBUG
  239 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  240 +#else
  241 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_BACKGROUND);
  242 +#endif
  243 +
  244 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  245 + cairo_fill(cr);
  246 +
  247 + if(lib3270_get_undera(host))
  248 + {
  249 + const gchar *chr = lib3270_in_e(host) ? "B" : "A";
  250 + cairo_text_extents_t extents;
  251 + int x,y;
  252 +
  253 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_BACKGROUND);
  254 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  255 + cairo_fill(cr);
  256 +
  257 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  258 +
  259 + cairo_text_extents(cr,chr,&extents);
  260 +
  261 + x = rect->x + ((rect->width/2) - ((extents.width+extents.x_bearing)/2));
  262 + y = rect->y + extents.height+((rect->height/2) - (extents.height/2));
  263 +
  264 + cairo_move_to(cr,x,y);
  265 + cairo_show_text(cr,chr);
  266 +
  267 + cairo_move_to(cr,x+extents.x_bearing,y+2);
  268 + cairo_rel_line_to(cr,extents.width,0);
  269 +
  270 + cairo_stroke(cr);
  271 +
  272 + }
  273 +
  274 +}
  275 +
  276 +void v3270_draw_connection(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect)
  277 +{
  278 + cairo_text_extents_t extents;
  279 + gchar *str = "?";
  280 +
  281 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  282 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  283 + cairo_stroke(cr);
  284 +
  285 + if(lib3270_get_oia_box_solid(host))
  286 + {
  287 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  288 + cairo_fill(cr);
  289 + return;
  290 + }
  291 +
  292 + if(lib3270_in_ansi(host))
  293 + *str = 'N';
  294 + else if(lib3270_in_sscp(host))
  295 + *str = 'S';
  296 +
  297 + cairo_text_extents(cr,str,&extents);
  298 + cairo_move_to(cr,rect->x+((rect->width/2)-(extents.width/2)),rect->y+extents.height+( (rect->height/2) - (extents.height/2)));
  299 + cairo_show_text(cr,str);
  300 +
  301 +}
  302 +
  303 +void v3270_draw_ssl_status(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect)
  304 +{
  305 + cairo_surface_t * icon;
  306 + double sz = rect->width < rect->height ? rect->width : rect->height;
  307 + int idx = lib3270_get_ssl_state(host) ? 1 : 0;
  308 +
  309 + static const struct
  310 + {
  311 + unsigned short width;
  312 + unsigned short height;
  313 + unsigned char * bits;
  314 + } bitmap[] =
  315 + {
  316 + { unlocked_width, unlocked_height, unlocked_bits },
  317 + { locked_width, locked_height, locked_bits },
  318 + };
  319 +
  320 +#ifdef DEBUG
  321 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  322 +#else
  323 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_BACKGROUND);
  324 +#endif
  325 +
  326 + cairo_translate(cr, rect->x, rect->y);
  327 +
  328 + cairo_rectangle(cr, 0, 0, rect->width, rect->height);
  329 + cairo_fill(cr);
  330 +
  331 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  332 +
  333 + icon = cairo_image_surface_create_for_data( (unsigned char *) bitmap[idx].bits,
  334 + CAIRO_FORMAT_A1,
  335 + bitmap[idx].width,bitmap[idx].height,
  336 + cairo_format_stride_for_width(CAIRO_FORMAT_A1,locked_width));
  337 +
  338 + cairo_scale(cr, sz / ((double) bitmap[idx].width),
  339 + sz / ((double) bitmap[idx].height));
  340 +
  341 + cairo_mask_surface(cr,icon,(rect->width-sz)/2,(rect->height-sz)/2);
  342 +
  343 + cairo_surface_destroy(icon);
  344 +
  345 +}
  346 +
  347 +static void draw_status_message(cairo_t *cr, LIB3270_MESSAGE id, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect)
  348 +{
  349 + #ifdef DEBUG
  350 + #define OIA_MESSAGE(x,c,y) { #x, c, y }
  351 + #else
  352 + #define OIA_MESSAGE(x,c,y) { c, y }
  353 + #endif
  354 +
  355 + static const struct _message
  356 + {
  357 + #ifdef DEBUG
  358 + const gchar * dbg;
  359 + #endif
  360 + enum V3270_COLOR
  361 + color;
  362 + const gchar * msg;
  363 + } message[] =
  364 + {
  365 + OIA_MESSAGE( LIB3270_MESSAGE_NONE,
  366 + V3270_COLOR_OIA_STATUS_OK,
  367 + NULL ),
  368 +
  369 + OIA_MESSAGE( LIB3270_MESSAGE_SYSWAIT,
  370 + V3270_COLOR_OIA_STATUS_OK,
  371 + N_( "X System" ) ),
  372 +
  373 + OIA_MESSAGE( LIB3270_MESSAGE_TWAIT,
  374 + V3270_COLOR_OIA_STATUS_OK,
  375 + N_( "X Wait" ) ),
  376 +
  377 + OIA_MESSAGE( LIB3270_MESSAGE_CONNECTED,
  378 + V3270_COLOR_OIA_STATUS_OK,
  379 + NULL ),
  380 +
  381 + OIA_MESSAGE( LIB3270_MESSAGE_DISCONNECTED,
  382 + V3270_COLOR_OIA_STATUS_INVALID,
  383 + N_( "X Not Connected" ) ),
  384 +
  385 + OIA_MESSAGE( LIB3270_MESSAGE_AWAITING_FIRST,
  386 + V3270_COLOR_OIA_STATUS_OK,
  387 + N_( "X" ) ),
  388 +
  389 + OIA_MESSAGE( LIB3270_MESSAGE_MINUS,
  390 + V3270_COLOR_OIA_STATUS_OK,
  391 + N_( "X -f" ) ),
  392 +
  393 + OIA_MESSAGE( LIB3270_MESSAGE_PROTECTED,
  394 + V3270_COLOR_OIA_STATUS_INVALID,
  395 + N_( "X Protected" ) ),
  396 +
  397 + OIA_MESSAGE( LIB3270_MESSAGE_NUMERIC,
  398 + V3270_COLOR_OIA_STATUS_INVALID,
  399 + N_( "X Numeric" ) ),
  400 +
  401 + OIA_MESSAGE( LIB3270_MESSAGE_OVERFLOW,
  402 + V3270_COLOR_OIA_STATUS_INVALID,
  403 + N_( "X Overflow" ) ),
  404 +
  405 + OIA_MESSAGE( LIB3270_MESSAGE_INHIBIT,
  406 + V3270_COLOR_OIA_STATUS_INVALID,
  407 + N_( "X Inhibit" ) ),
  408 +
  409 + OIA_MESSAGE( LIB3270_MESSAGE_KYBDLOCK,
  410 + V3270_COLOR_OIA_STATUS_INVALID,
  411 + N_( "X") ),
  412 +
  413 + OIA_MESSAGE( LIB3270_MESSAGE_X,
  414 + V3270_COLOR_OIA_STATUS_INVALID,
  415 + N_( "X" ) ),
  416 +
  417 + OIA_MESSAGE( LIB3270_MESSAGE_RESOLVING,
  418 + V3270_COLOR_OIA_STATUS_WARNING,
  419 + N_( "X Resolving" ) ),
  420 +
  421 + OIA_MESSAGE( LIB3270_MESSAGE_CONNECTING,
  422 + V3270_COLOR_OIA_STATUS_WARNING,
  423 + N_( "X Connecting" ) ),
  424 +
  425 +
  426 + };
  427 +
  428 + const gchar *msg = message[0].msg;
  429 +
  430 +// trace("%s: id=%d",__FUNCTION__,id);
  431 +
  432 + if(id >= 0 && id < G_N_ELEMENTS(message))
  433 + {
  434 + msg = message[id].msg;
  435 +#ifdef DEBUG
  436 + if(!msg)
  437 + msg = message[id].dbg;
  438 +#endif // DEBUG
  439 + }
  440 +
  441 + if(msg)
  442 + {
  443 + gdk_cairo_set_source_color(cr,color+message[id].color);
  444 + cairo_move_to(cr,rect->x,rect->y+metrics->height);
  445 + cairo_show_text(cr,gettext(msg));
  446 + }
  447 +
  448 +}
  449 +
  450 +static void draw_insert(cairo_t *cr, H3270 *host, GdkColor *color, GdkRectangle *rect)
  451 +{
  452 + if(lib3270_get_toggle(host,LIB3270_TOGGLE_INSERT))
  453 + {
  454 + double y = rect->y+(rect->height-2);
  455 +
  456 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  457 + cairo_clip(cr);
  458 +
  459 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  460 +
  461 + cairo_move_to(cr,rect->x,y);
  462 + cairo_rel_line_to(cr,rect->width/2,-(rect->height/1.7));
  463 + cairo_line_to(cr,rect->x+rect->width,y);
  464 + cairo_stroke(cr);
  465 + }
  466 +
  467 +}
  468 +
  469 +void v3270_draw_oia(cairo_t *cr, H3270 *host, int row, int cols, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect)
  470 +{
  471 + static const struct _right_fields
  472 + {
  473 + V3270_OIA_FIELD id;
  474 + void (*draw)(GdkRectangle *rect, struct v3270_metrics *metrics, cairo_t *cr, H3270 *host, int cols, GdkColor *color);
  475 + } right[] =
  476 + {
  477 + { V3270_OIA_CURSOR_POSITION, setup_cursor_position },
  478 + { V3270_OIA_TIMER, setup_timer_position },
  479 + { V3270_OIA_SPINNER, setup_spinner_position },
  480 + { V3270_OIA_LUNAME, setup_luname_position },
  481 +#ifdef X3270_PRINTER
  482 + { V3270_OIA_PRINTER, setup_single_char_right },
  483 +#endif // X3270_PRINTER
  484 + { V3270_OIA_SCRIPT, setup_single_char_right },
  485 + { V3270_OIA_INSERT, setup_insert_position },
  486 + { V3270_OIA_TYPEAHEAD, setup_single_char_right },
  487 + { V3270_OIA_SHIFT, setup_double_char_position },
  488 +// { V3270_OIA_CAPS, setup_single_char_right },
  489 + { V3270_OIA_ALT, setup_single_char_right },
  490 + { V3270_OIA_SSL, setup_double_char_position },
  491 + };
  492 +
  493 + int f;
  494 + int rCol = metrics->left+(cols*metrics->width);
  495 + int lCol = metrics->left+1;
  496 +
  497 + row += OIA_TOP_MARGIN;
  498 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_SEPARATOR);
  499 + cairo_rectangle(cr, metrics->left, row, cols*metrics->width, 1);
  500 + cairo_fill(cr);
  501 +
  502 + row += 2;
  503 +
  504 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_BACKGROUND);
  505 + cairo_rectangle(cr, metrics->left, row, cols*metrics->width, metrics->spacing);
  506 + cairo_fill(cr);
  507 +
  508 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  509 +
  510 + for(f=0;f<G_N_ELEMENTS(right);f++)
  511 + {
  512 + GdkRectangle *r = rect+right[f].id;
  513 +
  514 + memset(r,0,sizeof(GdkRectangle));
  515 + r->x = rCol;
  516 + r->y = row;
  517 + r->width = metrics->width;
  518 + r->height = metrics->spacing;
  519 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  520 + right[f].draw(r,metrics,cr,host,cols,color);
  521 + rCol = r->x - (metrics->width/3);
  522 + }
  523 +
  524 + gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND);
  525 +
  526 + const gchar *str = "4";
  527 + cairo_text_extents_t extents;
  528 +
  529 + cairo_text_extents(cr,str,&extents);
  530 + cairo_move_to(cr,lCol+(((metrics->width+2)/2)-(extents.width/2)),row+extents.height+( (metrics->spacing/2) - (extents.height/2)));
  531 + cairo_show_text(cr,str);
  532 +
  533 + cairo_stroke(cr);
  534 + cairo_rectangle(cr, lCol, row, metrics->width+2, metrics->spacing);
  535 + cairo_stroke(cr);
  536 +
  537 + lCol += (metrics->width+5);
  538 +
  539 + // Undera indicator
  540 + rect[V3270_OIA_UNDERA].x = lCol;
  541 + rect[V3270_OIA_UNDERA].y = row;
  542 + rect[V3270_OIA_UNDERA].width = metrics->width+3;
  543 + rect[V3270_OIA_UNDERA].height = metrics->spacing;
  544 + draw_undera(cr,host,metrics,color,rect+V3270_OIA_UNDERA);
  545 +
  546 + lCol += (3 + rect[V3270_OIA_UNDERA].width);
  547 +
  548 + // Connection indicator
  549 + rect[V3270_OIA_CONNECTION].x = lCol;
  550 + rect[V3270_OIA_CONNECTION].y = row;
  551 + rect[V3270_OIA_CONNECTION].width = metrics->width+3;
  552 + rect[V3270_OIA_CONNECTION].height = metrics->spacing;
  553 + v3270_draw_connection(cr,host,metrics,color,rect+V3270_OIA_CONNECTION);
  554 +
  555 + lCol += (4 + rect[V3270_OIA_CONNECTION].width);
  556 +
  557 + memset(rect+V3270_OIA_MESSAGE,0,sizeof(GdkRectangle));
  558 +
  559 + if(lCol < rCol)
  560 + {
  561 + GdkRectangle *r = rect+V3270_OIA_MESSAGE;
  562 + r->x = lCol;
  563 + r->y = row;
  564 + r->width = rCol - lCol;
  565 + r->height = metrics->spacing;
  566 + draw_status_message(cr,lib3270_get_program_message(host),metrics,color,r);
  567 + }
  568 +
  569 + cairo_save(cr);
  570 + v3270_draw_ssl_status(cr,host,metrics,color,rect+V3270_OIA_SSL);
  571 + cairo_restore(cr);
  572 +
  573 + cairo_save(cr);
  574 + draw_insert(cr,host,color,rect+V3270_OIA_INSERT);
  575 + cairo_restore(cr);
  576 +}
  577 +
  578 +/**
  579 + * Begin update of a specific OIA field.
  580 + *
  581 + * @param terminal 3270 terminal widget.
  582 + * @param r Rectangle to receive updated region.
  583 + * @param id Field id.
  584 + *
  585 + * @return cairo object for drawing.
  586 + *
  587 + */
  588 +static cairo_t * set_update_region(v3270 * terminal, GdkRectangle **r, V3270_OIA_FIELD id)
  589 +{
  590 + GdkRectangle * rect = terminal->oia_rect + id;
  591 + cairo_t * cr = cairo_create(terminal->surface);
  592 +
  593 + cairo_set_scaled_font(cr,terminal->font_scaled);
  594 +
  595 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  596 + cairo_clip(cr);
  597 +
  598 + *r = rect;
  599 +
  600 +#ifdef DEBUG
  601 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  602 +#else
  603 + gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_OIA_BACKGROUND);
  604 +#endif
  605 +
  606 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  607 + cairo_fill(cr);
  608 +
  609 + gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_OIA_FOREGROUND);
  610 +
  611 + return cr;
  612 +}
  613 +
  614 +void v3270_update_luname(GtkWidget *widget,const gchar *name)
  615 +{
  616 + cairo_t * cr;
  617 + GdkRectangle * rect;
  618 + v3270 * terminal = GTK_V3270(widget);
  619 +
  620 + if(!terminal->surface)
  621 + return;
  622 +
  623 +// trace("%s",__FUNCTION__);
  624 +
  625 + cr = set_update_region(terminal,&rect,V3270_OIA_LUNAME);
  626 +
  627 + if(name)
  628 + {
  629 + cairo_move_to(cr,rect->x,rect->y+terminal->metrics.height);
  630 + gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_OIA_LUNAME);
  631 + cairo_show_text(cr,name);
  632 + cairo_stroke(cr);
  633 + }
  634 +
  635 + cairo_destroy(cr);
  636 +
  637 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),rect->x,rect->y,rect->width,rect->height);
  638 +}
  639 +
  640 +void v3270_update_message(v3270 *widget, LIB3270_MESSAGE id)
  641 +{
  642 + cairo_t * cr;
  643 + GdkRectangle * rect;
  644 +
  645 + if(!widget->surface)
  646 + return;
  647 +
  648 + cr = set_update_region(widget,&rect,V3270_OIA_MESSAGE);
  649 +
  650 + draw_status_message(cr,id,&widget->metrics,widget->color,rect);
  651 +
  652 + cairo_destroy(cr);
  653 +
  654 + gtk_widget_queue_draw_area(GTK_WIDGET(widget),rect->x,rect->y,rect->width,rect->height);
  655 +
  656 + if(widget->accessible)
  657 + v3270_acessible_set_state(widget->accessible,id);
  658 +}
  659 +
  660 +static void draw_cursor_position(cairo_t *cr, GdkRectangle *rect, struct v3270_metrics *metrics, int row, int col)
  661 +{
  662 + cairo_text_extents_t extents;
  663 + char buffer[10];
  664 +
  665 + short2string(buffer,row+1,3);
  666 + buffer[3] = '/';
  667 + short2string(buffer+4,col+1,3);
  668 + buffer[7] = 0;
  669 +
  670 + cairo_text_extents(cr,buffer,&extents);
  671 +
  672 + cairo_move_to(cr,(rect->x+rect->width)-(extents.width+2),rect->y+metrics->height);
  673 + cairo_show_text(cr, buffer);
  674 + cairo_stroke(cr);
  675 +}
  676 +
  677 +void v3270_update_cursor(H3270 *session, unsigned short row, unsigned short col, unsigned char c, unsigned short attr)
  678 +{
  679 + v3270 * terminal = GTK_V3270(session->widget);
  680 + GdkRectangle saved;
  681 +
  682 + if(!terminal->surface)
  683 + return;
  684 +
  685 + // Update cursor rectangle
  686 + saved = terminal->cursor.rect;
  687 +
  688 + terminal->cursor.rect.x = terminal->metrics.left + (col * terminal->cursor.rect.width);
  689 + terminal->cursor.rect.y = terminal->metrics.top + (row * terminal->metrics.spacing);
  690 + terminal->cursor.rect.width = terminal->metrics.width;
  691 + terminal->cursor.rect.height = terminal->metrics.height+terminal->metrics.descent;
  692 + terminal->cursor.show |= 1;
  693 +
  694 + gtk_widget_queue_draw_area( GTK_WIDGET(terminal), saved.x,
  695 + saved.y,
  696 + saved.width,
  697 + saved.height);
  698 +
  699 +
  700 + v3270_update_cursor_surface(terminal,c,attr);
  701 +
  702 + gtk_widget_queue_draw_area( GTK_WIDGET(terminal),
  703 + terminal->cursor.rect.x,terminal->cursor.rect.y,
  704 + terminal->cursor.rect.width,terminal->cursor.rect.height);
  705 +
  706 + if(lib3270_get_toggle(session,LIB3270_TOGGLE_CROSSHAIR))
  707 + {
  708 + GtkAllocation allocation;
  709 + gtk_widget_get_allocation(GTK_WIDGET(terminal), &allocation);
  710 +
  711 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),0,saved.y+terminal->metrics.height,allocation.width,1);
  712 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),saved.x,0,1,terminal->oia_rect->y-3);
  713 +
  714 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),0,terminal->cursor.rect.y+terminal->metrics.height,allocation.width,1);
  715 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),terminal->cursor.rect.x,0,1,terminal->oia_rect->y-3);
  716 + }
  717 +
  718 + if(lib3270_get_toggle(session,LIB3270_TOGGLE_CURSOR_POS))
  719 + {
  720 + // Update OIA
  721 + GdkRectangle * rect;
  722 + cairo_t * cr;
  723 +
  724 + cr = set_update_region(terminal,&rect,V3270_OIA_CURSOR_POSITION);
  725 +
  726 + draw_cursor_position(cr,rect,&terminal->metrics,row,col);
  727 +
  728 + cairo_destroy(cr);
  729 +
  730 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),rect->x,rect->y,rect->width,rect->height);
  731 + }
  732 +
  733 + if(terminal->accessible)
  734 + g_signal_emit_by_name(ATK_TEXT(terminal->accessible),"text-caret-moved",lib3270_get_cursor_address(session));
  735 +
  736 +}
  737 +
  738 +struct timer_info
  739 +{
  740 + time_t start;
  741 + time_t last;
  742 +#ifdef HAVE_LIBM
  743 + gint step;
  744 +#endif // HAVE_LIBM
  745 + v3270 * terminal;
  746 +};
  747 +
  748 +static void release_timer(struct timer_info *info)
  749 +{
  750 +// trace("Timer %p stops",info);
  751 + info->terminal->timer = NULL;
  752 +
  753 + if(info->terminal->surface)
  754 + {
  755 + // Erase timer info
  756 + static const int id[] = { V3270_OIA_TIMER,
  757 +#ifdef HAVE_LIBM
  758 + V3270_OIA_SPINNER
  759 +#endif // HAVE_LIBM
  760 + };
  761 + int f;
  762 +
  763 + cairo_t *cr = cairo_create(info->terminal->surface);
  764 +
  765 +#ifdef DEBUG
  766 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  767 +#else
  768 + gdk_cairo_set_source_color(cr,info->terminal->color+V3270_COLOR_OIA_BACKGROUND);
  769 +#endif
  770 +
  771 + for(f=0;f<G_N_ELEMENTS(id);f++)
  772 + {
  773 + GdkRectangle *rect = info->terminal->oia_rect + id[f];
  774 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  775 + cairo_fill(cr);
  776 + gtk_widget_queue_draw_area(GTK_WIDGET(info->terminal),rect->x,rect->y,rect->width,rect->height);
  777 + }
  778 + cairo_destroy(cr);
  779 + }
  780 +
  781 + g_free(info);
  782 +}
  783 +
  784 +void v3270_draw_shift_status(v3270 *terminal)
  785 +{
  786 + GdkRectangle *r;
  787 + cairo_t *cr;
  788 +
  789 + if(!terminal->surface)
  790 + return;
  791 +
  792 + cr = set_update_region(terminal,&r,V3270_OIA_SHIFT);
  793 + cairo_translate(cr, r->x, r->y+1);
  794 +
  795 + trace("%s: %s",__FUNCTION__,(terminal->keyflags & KEY_FLAG_SHIFT) ? "Yes" : "No");
  796 +
  797 + if(r->width > 2 && r->height > 7 && (terminal->keyflags & KEY_FLAG_SHIFT))
  798 + {
  799 + int b,x,y,w,h,l;
  800 + int height = r->height-6;
  801 +
  802 + if(height > r->width)
  803 + {
  804 + w = r->width;
  805 + h = w*1.5;
  806 + }
  807 + else // width > height
  808 + {
  809 + h = height;
  810 + w = h/1.5;
  811 + }
  812 +
  813 + // Set image position
  814 + x = (r->width - w)/2;
  815 + y = (height - h)/2;
  816 + l = (w/3);
  817 + b = y+(w/1.5);
  818 +
  819 + cairo_move_to(cr,x+(w/2),y);
  820 + cairo_line_to(cr,x+w,b);
  821 + cairo_line_to(cr,(x+w)-l,b);
  822 + cairo_line_to(cr,(x+w)-l,y+h);
  823 + cairo_line_to(cr,x+l,y+h);
  824 + cairo_line_to(cr,x+l,b);
  825 + cairo_line_to(cr,x,b);
  826 + cairo_close_path(cr);
  827 +
  828 + cairo_stroke(cr);
  829 +
  830 + }
  831 +
  832 + cairo_destroy(cr);
  833 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  834 +
  835 +}
  836 +
  837 +static void update_text_field(v3270 *terminal, gboolean flag, V3270_OIA_FIELD id, const gchar *text)
  838 +{
  839 + GdkRectangle *r;
  840 + cairo_t *cr;
  841 +
  842 + if(!terminal->surface)
  843 + return;
  844 +
  845 + cr = set_update_region(terminal,&r,id);
  846 + cairo_translate(cr, r->x, r->y);
  847 +
  848 + if(flag)
  849 + {
  850 + cairo_move_to(cr,0,terminal->metrics.height);
  851 + cairo_show_text(cr, text);
  852 + cairo_stroke(cr);
  853 + }
  854 +
  855 + cairo_destroy(cr);
  856 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  857 +}
  858 +
  859 +void v3270_draw_alt_status(v3270 *terminal)
  860 +{
  861 + update_text_field(terminal,terminal->keyflags & KEY_FLAG_ALT,V3270_OIA_ALT,"A");
  862 +}
  863 +
  864 +void v3270_draw_ins_status(v3270 *terminal)
  865 +{
  866 + GdkRectangle *r;
  867 + cairo_t *cr;
  868 +
  869 + if(!terminal->surface)
  870 + return;
  871 +
  872 + cr = set_update_region(terminal,&r,V3270_OIA_INSERT);
  873 +
  874 + draw_insert(cr,terminal->host,terminal->color,r);
  875 +
  876 + cairo_destroy(cr);
  877 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  878 +
  879 +}
  880 +
  881 +static gboolean update_timer(struct timer_info *info)
  882 +{
  883 + cairo_t * cr;
  884 + time_t now = time(0);
  885 + GdkRectangle * rect;
  886 +
  887 + if(!info->terminal->surface)
  888 + return TRUE;
  889 +
  890 + cr = cairo_create(info->terminal->surface);
  891 +
  892 + if(now != info->last)
  893 + {
  894 + time_t seconds = now - info->start;
  895 + char buffer[7];
  896 +
  897 + rect = info->terminal->oia_rect + V3270_OIA_TIMER;
  898 +
  899 +#ifdef DEBUG
  900 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  901 +#else
  902 + gdk_cairo_set_source_color(cr,info->terminal->color+V3270_COLOR_OIA_BACKGROUND);
  903 +#endif
  904 +
  905 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  906 + cairo_fill(cr);
  907 +
  908 + gdk_cairo_set_source_color(cr,info->terminal->color+V3270_COLOR_OIA_FOREGROUND);
  909 +
  910 + short2string(buffer,seconds/60,2);
  911 + buffer[2] = ':';
  912 + short2string(buffer+3,seconds%60,2);
  913 + buffer[5] = 0;
  914 +
  915 + cairo_set_scaled_font(cr,info->terminal->font_scaled);
  916 + cairo_move_to(cr,rect->x,rect->y+info->terminal->metrics.height);
  917 + cairo_show_text(cr, buffer);
  918 + cairo_stroke(cr);
  919 +
  920 + info->last = now;
  921 + gtk_widget_queue_draw_area(GTK_WIDGET(info->terminal),rect->x,rect->y,rect->width,rect->height);
  922 + }
  923 +
  924 +#ifdef HAVE_LIBM
  925 + rect = info->terminal->oia_rect + V3270_OIA_SPINNER;
  926 +
  927 +#ifdef DEBUG
  928 + cairo_set_source_rgb(cr,0.1,0.1,0.1);
  929 +#else
  930 + gdk_cairo_set_source_color(cr,info->terminal->color+V3270_COLOR_OIA_BACKGROUND);
  931 +#endif
  932 + cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
  933 + cairo_fill(cr);
  934 +
  935 + gdk_cairo_set_source_color(cr,info->terminal->color+V3270_COLOR_OIA_FOREGROUND);
  936 +
  937 + info->step = draw_spinner(cr, rect, info->terminal->color, info->step);
  938 + gtk_widget_queue_draw_area(GTK_WIDGET(info->terminal),rect->x,rect->y,rect->width,rect->height);
  939 +#endif // HAVE_LIBM
  940 +
  941 + cairo_destroy(cr);
  942 +
  943 + return TRUE;
  944 +}
  945 +
  946 +void v3270_start_timer(GtkWidget *widget)
  947 +{
  948 + struct timer_info *info;
  949 + v3270 *terminal = GTK_V3270(widget);
  950 +
  951 + if(terminal->timer)
  952 + {
  953 + g_source_ref(terminal->timer);
  954 + return;
  955 + }
  956 +
  957 + info = g_new0(struct timer_info,1);
  958 + info->terminal = terminal;
  959 + info->start = time(0);
  960 +
  961 + terminal->timer = g_timeout_source_new(100);
  962 + g_source_set_callback(terminal->timer,(GSourceFunc) update_timer, info, (GDestroyNotify) release_timer);
  963 +
  964 + g_source_attach(terminal->timer, NULL);
  965 + g_source_unref(terminal->timer);
  966 +
  967 + trace("Timer %p starts",info);
  968 +}
  969 +
  970 +void v3270_stop_timer(GtkWidget *widget)
  971 +{
  972 + v3270 *terminal = GTK_V3270(widget);
  973 +
  974 + if(!terminal->timer)
  975 + return;
  976 +
  977 +// trace("Timer=%p",terminal->timer);
  978 + if(terminal->timer->ref_count < 2)
  979 + g_source_destroy(terminal->timer);
  980 +
  981 + if(terminal->timer)
  982 + g_source_unref(terminal->timer);
  983 +
  984 +}
  985 +
  986 +void v3270_update_oia(H3270 *session, LIB3270_FLAG id, unsigned char on)
  987 +{
  988 + cairo_t *cr;
  989 + GdkRectangle *r;
  990 +
  991 + v3270 *terminal = GTK_V3270(session->widget);
  992 +
  993 + if(!terminal->surface)
  994 + return;
  995 +
  996 + switch(id)
  997 + {
  998 + case LIB3270_FLAG_BOXSOLID:
  999 + cr = set_update_region(terminal,&r,V3270_OIA_CONNECTION);
  1000 + v3270_draw_connection(cr,terminal->host,&terminal->metrics,terminal->color,r);
  1001 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  1002 + cairo_destroy(cr);
  1003 + break;
  1004 +
  1005 + case LIB3270_FLAG_UNDERA:
  1006 + cr = set_update_region(terminal,&r,V3270_OIA_UNDERA);
  1007 + draw_undera(cr,terminal->host,&terminal->metrics,terminal->color,r);
  1008 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  1009 + cairo_destroy(cr);
  1010 + break;
  1011 +
  1012 + case LIB3270_FLAG_SECURE:
  1013 + cr = set_update_region(terminal,&r,V3270_OIA_SSL);
  1014 + v3270_draw_ssl_status(cr,terminal->host,&terminal->metrics,terminal->color,r);
  1015 + gtk_widget_queue_draw_area(GTK_WIDGET(terminal),r->x,r->y,r->width,r->height);
  1016 + cairo_destroy(cr);
  1017 + break;
  1018 +
  1019 + case LIB3270_FLAG_TYPEAHEAD:
  1020 + update_text_field(terminal,on,V3270_OIA_TYPEAHEAD,"T");
  1021 + break;
  1022 +
  1023 +#if defined(LIB3270_FLAG_PRINTER) && defined(X3270_PRINTER)
  1024 + case LIB3270_FLAG_PRINTER:
  1025 + update_text_field(terminal,on,V3270_OIA_PRINTER,"P");
  1026 + break;
  1027 +#endif // LIB3270_FLAG_PRINTER
  1028 +
  1029 + default:
  1030 + return;
  1031 + }
  1032 +}
... ...
private.h 0 → 100644
  1 +++ a/private.h
... ... @@ -0,0 +1,236 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como private.h 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 + * licinio@bb.com.br (Licínio Luis Branco)
  28 + * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
  29 + *
  30 + */
  31 +
  32 +#include <gtk/gtk.h>
  33 +
  34 +#define ENABLE_NLS
  35 +#define GETTEXT_PACKAGE PACKAGE_NAME
  36 +
  37 +#include <libintl.h>
  38 +#include <glib/gi18n.h>
  39 +
  40 +#ifndef V3270_H_INCLUDED
  41 + #include "v3270.h"
  42 +#endif
  43 +
  44 +G_BEGIN_DECLS
  45 +
  46 +
  47 + struct _v3270Class
  48 + {
  49 + GtkWidgetClass parent_class;
  50 +
  51 + /* Signals */
  52 + void (*activate)(GtkWidget *widget);
  53 + void (*toggle_changed)(v3270 *widget,LIB3270_TOGGLE toggle_id,gboolean toggle_state,const gchar *toggle_name);
  54 + void (*message_changed)(v3270 *widget, LIB3270_MESSAGE id);
  55 + void (*luname_changed)(GtkWidget *widget,const gchar *luname);
  56 + gboolean (*keypress)(GtkWidget *widget,guint keyval,GdkModifierType state);
  57 +
  58 + };
  59 +
  60 +/*--[ Defines]---------------------------------------------------------------------------------------*/
  61 +
  62 + #define OIA_TOP_MARGIN 2
  63 +
  64 + #define KEY_FLAG_SHIFT 0x0001
  65 + #define KEY_FLAG_ALT 0x0002
  66 +
  67 + enum
  68 + {
  69 + SIGNAL_TOGGLE_CHANGED,
  70 + SIGNAL_MESSAGE_CHANGED,
  71 + SIGNAL_LUNAME_CHANGED,
  72 + SIGNAL_KEYPRESS,
  73 + SIGNAL_CONNECTED,
  74 + SIGNAL_DISCONNECTED,
  75 + SIGNAL_UPDATE_CONFIG,
  76 + SIGNAL_MODEL_CHANGED,
  77 + SIGNAL_SELECTING,
  78 + SIGNAL_POPUP,
  79 + SIGNAL_PASTENEXT,
  80 + SIGNAL_CLIPBOARD,
  81 + SIGNAL_CHANGED,
  82 +
  83 + LAST_SIGNAL
  84 + };
  85 +
  86 +/*--[ Globals ]--------------------------------------------------------------------------------------*/
  87 +
  88 + #define V3270_CURSOR_UNPROTECTED LIB3270_CURSOR_EDITABLE
  89 + #define V3270_CURSOR_WAITING LIB3270_CURSOR_WAITING
  90 + #define V3270_CURSOR_LOCKED LIB3270_CURSOR_LOCKED
  91 +
  92 + #define V3270_CURSOR_PROTECTED LIB3270_CURSOR_USER
  93 + #define V3270_CURSOR_MOVE_SELECTION LIB3270_CURSOR_USER+1
  94 + #define V3270_CURSOR_SELECTION_TOP_LEFT LIB3270_CURSOR_USER+2
  95 + #define V3270_CURSOR_SELECTION_TOP_RIGHT LIB3270_CURSOR_USER+3
  96 + #define V3270_CURSOR_SELECTION_TOP LIB3270_CURSOR_USER+4
  97 + #define V3270_CURSOR_SELECTION_BOTTOM_LEFT LIB3270_CURSOR_USER+5
  98 + #define V3270_CURSOR_SELECTION_BOTTOM_RIGHT LIB3270_CURSOR_USER+6
  99 + #define V3270_CURSOR_SELECTION_BOTTOM LIB3270_CURSOR_USER+7
  100 + #define V3270_CURSOR_SELECTION_LEFT LIB3270_CURSOR_USER+8
  101 + #define V3270_CURSOR_SELECTION_RIGHT LIB3270_CURSOR_USER+9
  102 +
  103 + #define V3270_CURSOR_COUNT LIB3270_CURSOR_USER+10
  104 +
  105 +
  106 + struct v3270_metrics
  107 + {
  108 + guint width;
  109 + guint height;
  110 + guint ascent;
  111 + guint descent;
  112 +
  113 + guint spacing;
  114 +
  115 + guint left;
  116 + guint top;
  117 + };
  118 +
  119 +/*--[ Widget data ]----------------------------------------------------------------------------------*/
  120 +
  121 + struct _v3270
  122 + {
  123 + GtkWidget parent;
  124 +
  125 + // flags
  126 + int selecting : 1; /**< Selecting region */
  127 + int moving : 1; /**< Moving selected region */
  128 + int resizing : 1; /**< Resizing selected region */
  129 + int table : 1; /**< Copy mode is table */
  130 +
  131 +#if GTK_CHECK_VERSION(3,0,0)
  132 +
  133 +#else
  134 + gint width;
  135 + gint height;
  136 +#endif // GTK_CHECK_VERSION(3,0,0)
  137 +
  138 + GSource * timer;
  139 + GtkIMContext * input_method;
  140 + unsigned short keyflags;
  141 + gchar * clipboard; /**< Clipboard contents (text only) */
  142 +
  143 + LIB3270_CURSOR pointer_id;
  144 + unsigned char pointer; /** Mouse pointer ID */
  145 + int selection_addr; /** Selection addr */
  146 +
  147 + // Font info
  148 + gchar * font_family;
  149 + cairo_font_weight_t font_weight;
  150 + cairo_scaled_font_t * font_scaled;
  151 + cairo_surface_t * surface;
  152 +
  153 + struct v3270_metrics metrics;
  154 +
  155 + gint minimum_width;
  156 + gint minimum_height;
  157 +
  158 + // Colors
  159 + GdkColor color[V3270_COLOR_COUNT]; /**< Terminal widget colors */
  160 +
  161 + // Regions
  162 + GdkRectangle oia_rect[V3270_OIA_FIELD_COUNT];
  163 +
  164 + struct
  165 + {
  166 + unsigned char show; /**< Cursor flag */
  167 + unsigned char chr; /**< Char at cursor position */
  168 + unsigned short attr; /**< Attribute at cursor position */
  169 + GdkRectangle rect; /**< Cursor rectangle */
  170 + GSource * timer; /**< Cursor blinking timer */
  171 + cairo_surface_t * surface; /**< Cursor image */
  172 + } cursor;
  173 +
  174 + // Acessibility
  175 + GtkAccessible * accessible;
  176 +
  177 + // lib3270 stuff
  178 + H3270 * host; /**< Related 3270 session */
  179 +
  180 + };
  181 +
  182 +/*--[ Globals ]--------------------------------------------------------------------------------------*/
  183 +
  184 + G_GNUC_INTERNAL guint v3270_widget_signal[LAST_SIGNAL];
  185 + G_GNUC_INTERNAL GdkCursor * v3270_cursor[V3270_CURSOR_COUNT];
  186 +
  187 +/*--[ Prototipes ]-----------------------------------------------------------------------------------*/
  188 +
  189 +const GtkWidgetClass * v3270_get_parent_class(void);
  190 +
  191 +gboolean v3270_draw(GtkWidget * widget, cairo_t * cr);
  192 +void v3270_draw_oia(cairo_t *cr, H3270 *host, int row, int cols, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect);
  193 +void v3270_update_mouse_pointer(GtkWidget *widget);
  194 +
  195 +#if ! GTK_CHECK_VERSION(3,0,0)
  196 + gboolean v3270_expose(GtkWidget * widget, GdkEventExpose *event);
  197 +#endif // GTK 3
  198 +
  199 +void v3270_draw_shift_status(v3270 *terminal);
  200 +void v3270_draw_alt_status(v3270 *terminal);
  201 +void v3270_draw_ins_status(v3270 *terminal);
  202 +
  203 +void v3270_update_cursor_surface(v3270 *widget,unsigned char chr,unsigned short attr);
  204 +
  205 +void v3270_register_io_handlers(v3270Class *cls);
  206 +
  207 +void v3270_draw_char(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *fg, GdkColor *bg);
  208 +
  209 +void v3270_start_timer(GtkWidget *terminal);
  210 +void v3270_stop_timer(GtkWidget *terminal);
  211 +
  212 +void v3270_draw_connection(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect);
  213 +void v3270_draw_ssl_status(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect);
  214 +
  215 +void v3270_update_char(H3270 *session, int addr, unsigned char chr, unsigned short attr, unsigned char cursor);
  216 +
  217 +void v3270_update_font_metrics(v3270 *terminal, cairo_t *cr, int width, int height);
  218 +
  219 +void v3270_update_cursor_rect(v3270 *widget, GdkRectangle *rect, unsigned char chr, unsigned short attr);
  220 +
  221 +void v3270_update_luname(GtkWidget *widget,const gchar *name);
  222 +void v3270_update_message(v3270 *widget, LIB3270_MESSAGE id);
  223 +void v3270_update_cursor(H3270 *session, unsigned short row, unsigned short col, unsigned char c, unsigned short attr);
  224 +void v3270_update_oia(H3270 *session, LIB3270_FLAG id, unsigned char on);
  225 +
  226 +// Keyboard & Mouse
  227 +gboolean v3270_key_press_event(GtkWidget *widget, GdkEventKey *event);
  228 +gboolean v3270_key_release_event(GtkWidget *widget, GdkEventKey *event);
  229 +void v3270_key_commit(GtkIMContext *imcontext, gchar *str, v3270 *widget);
  230 +gboolean v3270_button_press_event(GtkWidget *widget, GdkEventButton *event);
  231 +gboolean v3270_button_release_event(GtkWidget *widget, GdkEventButton*event);
  232 +gboolean v3270_motion_notify_event(GtkWidget *widget, GdkEventMotion *event);
  233 +void v3270_emit_popup(v3270 *widget, int baddr, GdkEventButton *event);
  234 +gint v3270_get_offset_at_point(v3270 *widget, gint x, gint y);
  235 +
  236 +G_END_DECLS
... ...
selection.c 0 → 100644
  1 +++ a/selection.c
... ... @@ -0,0 +1,476 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como clipboard.c 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 <gtk/gtk.h>
  31 + #include <pw3270.h>
  32 + #include <malloc.h>
  33 + #include "v3270.h"
  34 + #include "private.h"
  35 + #include <lib3270/selection.h>
  36 +
  37 +/*--[ Globals ]--------------------------------------------------------------------------------------*/
  38 +
  39 + enum
  40 + {
  41 + CLIPBOARD_TYPE_TEXT,
  42 + };
  43 +
  44 + static const GtkTargetEntry targets[] =
  45 + {
  46 + { "COMPOUND_TEXT", 0, CLIPBOARD_TYPE_TEXT },
  47 + { "UTF8_STRING", 0, CLIPBOARD_TYPE_TEXT },
  48 + };
  49 +
  50 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  51 +
  52 +static void clipboard_clear(GtkClipboard *clipboard, GObject *obj)
  53 +{
  54 + trace("%s widget=%p",__FUNCTION__,obj);
  55 +
  56 +}
  57 +
  58 +static void clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection, guint target, GObject *obj)
  59 +{
  60 + v3270 * widget = GTK_V3270(obj);
  61 +
  62 + trace("%s: widget=%p target=\"%s\"",__FUNCTION__,obj,targets[target].target);
  63 +
  64 + switch(target)
  65 + {
  66 + case CLIPBOARD_TYPE_TEXT:
  67 + if(!widget->clipboard)
  68 + lib3270_ring_bell(widget->host);
  69 + else
  70 + gtk_selection_data_set_text(selection,widget->clipboard,-1);
  71 + break;
  72 +
  73 + default:
  74 + g_warning("Unexpected clipboard type %d\n",target);
  75 + }
  76 +}
  77 +
  78 +gchar * v3270_get_text(GtkWidget *widget, int offset, int len)
  79 +{
  80 + v3270 * terminal;
  81 + gchar * text;
  82 + char * str;
  83 +
  84 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  85 +
  86 + terminal = GTK_V3270(widget);
  87 +
  88 + str = lib3270_get_text(terminal->host, offset, len);
  89 +
  90 + if(!str)
  91 + return NULL;
  92 +
  93 + text = g_convert(str, -1, "UTF-8", lib3270_get_charset(terminal->host), NULL, NULL, NULL);
  94 +
  95 + free(str);
  96 + return text;
  97 +}
  98 +
  99 +/**
  100 + * Get lib3270 selection as a g_malloc buffer.
  101 + *
  102 + * @param widget Widget containing the desired section.
  103 + *
  104 + * @return NULL if error, otherwise the selected buffer contents (release with g_free).
  105 + *
  106 + */
  107 +static gchar * v3270_get_selected(v3270 *widget)
  108 +{
  109 + gchar *text = lib3270_get_selected(widget->host);
  110 + if(text)
  111 + {
  112 + gchar *str = g_strdup(text);
  113 + free(text);
  114 + return str;
  115 + }
  116 + return NULL;
  117 +}
  118 +
  119 +const gchar * v3270_get_selected_text(GtkWidget *widget)
  120 +{
  121 + v3270 *terminal;
  122 + gchar *text;
  123 +
  124 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  125 +
  126 + terminal = GTK_V3270(widget);
  127 +
  128 + if(terminal->clipboard)
  129 + {
  130 + g_free(terminal->clipboard);
  131 + terminal->clipboard = NULL;
  132 + }
  133 +
  134 + text = v3270_get_selected(terminal);
  135 +
  136 + if(!text)
  137 + {
  138 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_CLIPBOARD], 0, FALSE);
  139 + lib3270_ring_bell(terminal->host);
  140 + return NULL;
  141 + }
  142 +
  143 + if(terminal->table)
  144 + {
  145 + // Convert text to table
  146 + gchar **ln = g_strsplit(text,"\n",-1);
  147 + int width = lib3270_get_width(terminal->host);
  148 + gboolean cols[width];
  149 + int l;
  150 + GString * buffer;
  151 +
  152 + memset(cols,0,sizeof(gboolean)*width);
  153 +
  154 + // Find column delimiters
  155 + for(l=0;ln[l];l++)
  156 + {
  157 + int c;
  158 + gchar * ptr = ln[l];
  159 + GString * buffer;
  160 +
  161 + for(c=0;c<width && *ptr;c++)
  162 + {
  163 + if(!g_ascii_isspace(*ptr))
  164 + cols[c] = TRUE;
  165 +
  166 + ptr++;
  167 + }
  168 +
  169 + }
  170 +
  171 + // Read screen contents
  172 + buffer = g_string_sized_new(strlen(text));
  173 + for(l=0;ln[l];l++)
  174 + {
  175 + int col = 0;
  176 + gchar * src = ln[l];
  177 +
  178 + while(col < width && *src)
  179 + {
  180 + if(col)
  181 + g_string_append_c(buffer,'\t');
  182 +
  183 + // Find column start
  184 + while(!cols[col] && col < width && *src)
  185 + {
  186 + col++;
  187 + src++;
  188 + }
  189 +
  190 + if(col < width && *src)
  191 + {
  192 + gchar tmp[width+1];
  193 + gchar * dst = tmp;
  194 +
  195 + // Copy column content
  196 + while(cols[col] && col < width && *src)
  197 + {
  198 + *dst = *src;
  199 + col++;
  200 + dst++;
  201 + src++;
  202 + }
  203 + *dst = 0;
  204 + g_string_append(buffer,g_strstrip(tmp));
  205 + }
  206 +
  207 + }
  208 + g_string_append_c(buffer,'\n');
  209 +
  210 + }
  211 +
  212 + g_strfreev(ln);
  213 + g_free(text);
  214 +
  215 + text = g_string_free(buffer,FALSE);
  216 + }
  217 +
  218 + terminal->clipboard = g_convert(text, -1, "UTF-8", lib3270_get_charset(terminal->host), NULL, NULL, NULL);
  219 +
  220 + g_free(text);
  221 +
  222 +
  223 + return terminal->clipboard;
  224 +}
  225 +
  226 +const gchar * v3270_get_copy(GtkWidget *widget)
  227 +{
  228 + v3270 *terminal;
  229 +
  230 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  231 +
  232 + terminal = GTK_V3270(widget);
  233 +
  234 + return terminal->clipboard;
  235 +}
  236 +
  237 +const gchar * v3270_copy_append(GtkWidget *widget)
  238 +{
  239 + v3270 * terminal;
  240 + char * str;
  241 + gchar * text;
  242 + gchar * clip;
  243 +
  244 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  245 +
  246 + terminal = GTK_V3270(widget);
  247 +
  248 + if(!terminal->clipboard)
  249 + return v3270_get_selected_text(widget);
  250 +
  251 + str = lib3270_get_selected(terminal->host);
  252 +
  253 + if(!str)
  254 + return terminal->clipboard;
  255 +
  256 + text = g_convert(str, -1, "UTF-8", lib3270_get_charset(terminal->host), NULL, NULL, NULL);
  257 +
  258 + free(str);
  259 +
  260 + clip = g_strconcat(terminal->clipboard,"\n",text,NULL);
  261 +
  262 + g_free(text);
  263 + g_free(terminal->clipboard);
  264 +
  265 + terminal->clipboard = clip;
  266 +
  267 + gtk_clipboard_set_text(gtk_widget_get_clipboard(widget,GDK_SELECTION_CLIPBOARD),terminal->clipboard,-1);
  268 +
  269 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_CLIPBOARD], 0, TRUE);
  270 +
  271 + return terminal->clipboard;
  272 +}
  273 +
  274 +const gchar * v3270_copy(GtkWidget *widget, V3270_SELECT_FORMAT mode)
  275 +{
  276 + const gchar * text;
  277 + GtkClipboard * clipboard = gtk_widget_get_clipboard(widget,GDK_SELECTION_CLIPBOARD);
  278 +
  279 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  280 +
  281 + GTK_V3270(widget)->table = (mode == V3270_SELECT_TABLE ? 1 : 0);
  282 +
  283 + text = v3270_get_selected_text(widget);
  284 +
  285 + if(text)
  286 + {
  287 + if(gtk_clipboard_set_with_owner( clipboard,
  288 + targets,
  289 + G_N_ELEMENTS(targets),
  290 + (GtkClipboardGetFunc) clipboard_get,
  291 + (GtkClipboardClearFunc) clipboard_clear,
  292 + G_OBJECT(widget)
  293 + ))
  294 + {
  295 + gtk_clipboard_set_can_store(clipboard,targets,1);
  296 + }
  297 +
  298 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_CLIPBOARD], 0, TRUE);
  299 + }
  300 +
  301 + return text;
  302 +
  303 +}
  304 +
  305 +void v3270_paste_string(GtkWidget *widget, const gchar *text, const gchar *encoding)
  306 +{
  307 + gchar * buffer = NULL;
  308 + H3270 * session = v3270_get_session(widget);
  309 + const gchar * charset = lib3270_get_charset(session);
  310 + gboolean next;
  311 +
  312 + if(!text)
  313 + return;
  314 + else if(g_strcasecmp(encoding,charset))
  315 + buffer = g_convert(text, -1, charset, encoding, NULL, NULL, NULL);
  316 + else
  317 + buffer = g_strdup(text);
  318 +
  319 + if(!buffer)
  320 + {
  321 + /* Conversion failed, update special chars and try again */
  322 + int f;
  323 +
  324 + static const struct _xlat
  325 + {
  326 + const gchar *from;
  327 + const gchar *to;
  328 + } xlat[] =
  329 + {
  330 + { "–", "-" },
  331 + { "→", "->" },
  332 + { "←", "<-" },
  333 + { "©", "(c)" },
  334 + { "↔", "<->" },
  335 + { "™", "(TM)" },
  336 + { "®", "(R)" },
  337 + { "“", "\"" },
  338 + { "”", "\"" },
  339 + { "…", "..." },
  340 + { "•", "*" },
  341 + { "․", "." },
  342 + { "·", "*" },
  343 +
  344 + };
  345 +
  346 + gchar *string = g_strdup(text);
  347 +
  348 + // FIXME (perry#1#): Is there any better way for a "sed" here?
  349 + for(f=0;f<G_N_ELEMENTS(xlat);f++)
  350 + {
  351 + gchar *ptr = g_strstr_len(string,-1,xlat[f].from);
  352 +
  353 + if(ptr)
  354 + {
  355 + gchar *old = string;
  356 + gchar **tmp = g_strsplit(old,xlat[f].from,-1);
  357 + string = g_strjoinv(xlat[f].to,tmp);
  358 + g_strfreev(tmp);
  359 + g_free(old);
  360 + }
  361 + }
  362 +
  363 + buffer = g_convert(string, -1, charset, encoding, NULL, NULL, NULL);
  364 +
  365 + if(!buffer)
  366 + {
  367 + // Still failing, convert line by line
  368 + gchar **ln = g_strsplit(string,"\n",-1);
  369 +
  370 + for(f=0;ln[f];f++)
  371 + {
  372 + GError *error = NULL;
  373 + gchar *str = g_convert(ln[f], -1, charset, encoding, NULL, NULL, &error);
  374 +
  375 + if(!str)
  376 + {
  377 + GtkWidget *dialog = gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel(widget)),
  378 + GTK_DIALOG_DESTROY_WITH_PARENT,
  379 + GTK_MESSAGE_ERROR,
  380 + GTK_BUTTONS_OK,
  381 + _( "Can't convert line %d from %s to %s" ),f+1, encoding, charset);
  382 +
  383 + gtk_window_set_title(GTK_WINDOW(dialog), _( "Charset error" ) );
  384 + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s\n%s",error->message, ln[f]);
  385 +
  386 + gtk_dialog_run(GTK_DIALOG (dialog));
  387 + gtk_widget_destroy(dialog);
  388 +
  389 + break;
  390 + }
  391 + else
  392 + {
  393 + g_free(str);
  394 + }
  395 +
  396 + }
  397 + g_strfreev(ln);
  398 +
  399 + }
  400 +
  401 + g_free(string);
  402 + }
  403 +
  404 + if(buffer)
  405 + {
  406 + /* Remove TABS */
  407 + gchar *ptr;
  408 +
  409 + for(ptr = buffer;*ptr;ptr++)
  410 + {
  411 + if(*ptr == '\t')
  412 + *ptr = ' ';
  413 + }
  414 + }
  415 + else
  416 + {
  417 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_PASTENEXT], 0, FALSE);
  418 + return;
  419 + }
  420 +
  421 + next = lib3270_paste(session,(unsigned char *) buffer) ? TRUE : FALSE;
  422 +
  423 + trace("Pastenext is %s",next ? "On" : "Off");
  424 +
  425 + g_free(buffer);
  426 +
  427 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_PASTENEXT], 0, next);
  428 +
  429 +}
  430 +
  431 +static void text_received(GtkClipboard *clipboard, const gchar *text, GtkWidget *widget)
  432 +{
  433 + v3270_paste_string(widget,text,"UTF-8");
  434 +}
  435 +
  436 +void v3270_paste(GtkWidget *widget)
  437 +{
  438 + gtk_clipboard_request_text(gtk_widget_get_clipboard(widget,GDK_SELECTION_CLIPBOARD),(GtkClipboardTextReceivedFunc) text_received,(gpointer) widget);
  439 +}
  440 +
  441 +void v3270_unselect(GtkWidget *widget)
  442 +{
  443 + lib3270_unselect(v3270_get_session(widget));
  444 +}
  445 +
  446 +gboolean v3270_get_selection_bounds(GtkWidget *widget, gint *start, gint *end)
  447 +{
  448 + g_return_val_if_fail(GTK_IS_V3270(widget),FALSE);
  449 + return lib3270_get_selection_bounds(GTK_V3270(widget)->host,start,end) == 0 ? FALSE : TRUE;
  450 +}
  451 +
  452 +gchar * v3270_get_region(GtkWidget *widget, gint start_pos, gint end_pos, gboolean all)
  453 +{
  454 + char * str;
  455 + gchar * utftext;
  456 +
  457 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  458 +
  459 + str = lib3270_get_region(GTK_V3270(widget)->host,start_pos,end_pos,all);
  460 + if(!str)
  461 + return NULL;
  462 +
  463 + utftext = g_convert(str, -1, "UTF-8", lib3270_get_charset(GTK_V3270(widget)->host), NULL, NULL, NULL);
  464 +
  465 + free(str);
  466 +
  467 + return utftext;
  468 +}
  469 +
  470 + void v3270_select_region(GtkWidget *widget, gint start, gint end)
  471 + {
  472 + g_return_if_fail(GTK_IS_V3270(widget));
  473 + lib3270_select_region(GTK_V3270(widget)->host,start,end);
  474 + }
  475 +
  476 +
... ...
sources.mak 0 → 100644
  1 +++ a/sources.mak
... ... @@ -0,0 +1,2 @@
  1 +V3270_SRC=marshal.c widget.c oia.c iocallback.c keyboard.c draw.c mouse.c selection.c accessible.c
  2 +
... ...
unlocked.xbm 0 → 100644
  1 +++ a/unlocked.xbm
... ... @@ -0,0 +1,14 @@
  1 +#define unlocked_width 32
  2 +#define unlocked_height 32
  3 +static unsigned char unlocked_bits[] = {
  4 + 0x00, 0x00, 0xff, 0x0f, 0x00, 0x80, 0xff, 0x1f, 0x00, 0xc0, 0x01, 0x38,
  5 + 0x00, 0xe0, 0x00, 0x70, 0x00, 0x70, 0xfc, 0xe3, 0x00, 0x30, 0xfe, 0xc7,
  6 + 0x00, 0x30, 0x07, 0xce, 0x00, 0x30, 0x03, 0xcc, 0x00, 0x30, 0x03, 0xcc,
  7 + 0x00, 0x30, 0x03, 0xcc, 0x00, 0x30, 0x03, 0xcc, 0x00, 0x30, 0x03, 0xcc,
  8 + 0x00, 0x30, 0x03, 0xfc, 0x00, 0x30, 0x03, 0xfc, 0xff, 0xff, 0x3f, 0x00,
  9 + 0xff, 0xff, 0x3f, 0x00, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x33, 0x00,
  10 + 0xcf, 0xcc, 0x3c, 0x00, 0xcf, 0xcc, 0x3c, 0x00, 0x33, 0x33, 0x33, 0x00,
  11 + 0x33, 0x33, 0x33, 0x00, 0xcf, 0xcc, 0x3c, 0x00, 0xcf, 0xcc, 0x3c, 0x00,
  12 + 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x33, 0x00, 0xcf, 0xcc, 0x3c, 0x00,
  13 + 0xcf, 0xcc, 0x3c, 0x00, 0x33, 0x33, 0x33, 0x00, 0x33, 0x33, 0x33, 0x00,
  14 + 0xff, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x3f, 0x00 };
... ...
v3270.h 0 → 100644
  1 +++ a/v3270.h
... ... @@ -0,0 +1,190 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como v3270.h 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 + * licinio@bb.com.br (Licínio Luis Branco)
  28 + * kraucer@bb.com.br (Kraucer Fernandes Mazuco)
  29 + *
  30 + */
  31 +
  32 +#ifndef V3270_H_INCLUDED
  33 +
  34 + #include <lib3270/config.h>
  35 + #include <lib3270.h>
  36 +
  37 + #define V3270_H_INCLUDED 1
  38 +
  39 + G_BEGIN_DECLS
  40 +
  41 + #define GTK_TYPE_V3270 (v3270_get_type ())
  42 + #define GTK_V3270(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270, v3270))
  43 + #define GTK_V3270_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270, v3270Class))
  44 + #define GTK_IS_V3270(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270))
  45 + #define GTK_IS_V3270_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270))
  46 + #define GTK_V3270_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270, v3270Class))
  47 +
  48 +
  49 + typedef struct _v3270 v3270;
  50 + typedef struct _v3270Class v3270Class;
  51 +
  52 + enum V3270_COLOR
  53 + {
  54 + V3270_COLOR_BACKGROUND,
  55 + V3270_COLOR_BLUE,
  56 + V3270_COLOR_RED,
  57 + V3270_COLOR_PINK,
  58 + V3270_COLOR_GREEN,
  59 + V3270_COLOR_TURQUOISE,
  60 + V3270_COLOR_YELLOW,
  61 + V3270_COLOR_WHITE,
  62 + V3270_COLOR_BLACK,
  63 + V3270_COLOR_DARK_BLUE,
  64 + V3270_COLOR_ORANGE,
  65 + V3270_COLOR_PURPLE,
  66 + V3270_COLOR_DARK_GREEN,
  67 + V3270_COLOR_DARK_TURQUOISE,
  68 + V3270_COLOR_MUSTARD,
  69 + V3270_COLOR_GRAY,
  70 +
  71 + V3270_COLOR_FIELD,
  72 + V3270_COLOR_FIELD_INTENSIFIED,
  73 + V3270_COLOR_FIELD_PROTECTED,
  74 + V3270_COLOR_FIELD_PROTECTED_INTENSIFIED,
  75 +
  76 + V3270_COLOR_SELECTED_BG,
  77 + V3270_COLOR_SELECTED_FG,
  78 +
  79 + V3270_COLOR_CROSS_HAIR,
  80 +
  81 + // Oia Colors (Must be the last block)
  82 + V3270_COLOR_OIA_BACKGROUND,
  83 + V3270_COLOR_OIA_FOREGROUND,
  84 + V3270_COLOR_OIA_SEPARATOR,
  85 + V3270_COLOR_OIA_STATUS_OK,
  86 + V3270_COLOR_OIA_STATUS_INVALID,
  87 +
  88 + V3270_COLOR_COUNT
  89 + };
  90 +
  91 + #define V3270_COLOR_OIA_STATUS_WARNING V3270_COLOR_OIA_STATUS_OK
  92 +
  93 + typedef enum _v3270_oia_field
  94 + {
  95 + V3270_OIA_UNDERA, /**< "A" underlined */
  96 + V3270_OIA_CONNECTION, /**< solid box if connected, "?" in a box if not */
  97 + V3270_OIA_MESSAGE, /**< message area */
  98 + V3270_OIA_SSL, /**< SSL Status */
  99 + /**< Meta indication ("M" or blank) */
  100 + V3270_OIA_ALT, /**< Alt indication ("A" or blank) */
  101 + /**< Compose indication ("C" or blank) */
  102 + /**< Compose first character */
  103 + V3270_OIA_SHIFT, /**< Shift Status */
  104 + V3270_OIA_TYPEAHEAD, /**< Typeahead indication ("T" or blank) */
  105 + V3270_OIA_INSERT, /**< Insert mode indication (Special symbol/"I" or blank) */
  106 + V3270_OIA_SCRIPT, /**< Script indication ("S" or blank) */
  107 + V3270_OIA_LUNAME, /**< LU Name */
  108 + V3270_OIA_SPINNER, /**< command timing spinner */
  109 + V3270_OIA_TIMER, /**< command timing (mmm:ss, or blank) */
  110 + V3270_OIA_CURSOR_POSITION, /**< cursor position (rrr/ccc or blank) */
  111 +
  112 +// V3270_OIA_CAPS, /**< Caps indication ("A" or blank) */
  113 +
  114 +#ifdef X3270_PRINTER
  115 + V3270_OIA_PRINTER, /**< Printer indication ("P" or blank) */
  116 +#endif // X3270_PRINTER
  117 +
  118 + V3270_OIA_FIELD_COUNT
  119 +
  120 + } V3270_OIA_FIELD;
  121 +
  122 +
  123 + #define V3270_COLOR_OIA_SPINNER V3270_COLOR_OIA_FOREGROUND
  124 + #define V3270_COLOR_OIA_LUNAME V3270_COLOR_OIA_FOREGROUND
  125 + #define V3270_COLOR_OIA_INSERT V3270_COLOR_OIA_FOREGROUND
  126 +
  127 + #ifndef v3270char
  128 + #define v3270char void
  129 + #endif // v3270_char
  130 +
  131 + GtkWidget * v3270_new(void);
  132 + GType v3270_get_type(void);
  133 +
  134 + void v3270_reload(GtkWidget * widget);
  135 +
  136 + void v3270_set_font_family(GtkWidget *widget, const gchar *name);
  137 + const gchar * v3270_get_font_family(GtkWidget *widget);
  138 +
  139 + H3270 * v3270_get_session(GtkWidget *widget);
  140 +
  141 + int v3270_connect(GtkWidget *widget, const gchar *host);
  142 + void v3270_disconnect(GtkWidget *widget);
  143 +
  144 + // Clipboard
  145 + typedef enum _v3270_select_format
  146 + {
  147 + V3270_SELECT_TEXT,
  148 + V3270_SELECT_TABLE,
  149 +
  150 + V3270_SELECT_MAX
  151 + } V3270_SELECT_FORMAT;
  152 +
  153 + const gchar * v3270_copy(GtkWidget *widget, V3270_SELECT_FORMAT mode);
  154 + const gchar * v3270_copy_append(GtkWidget *widget);
  155 +
  156 + const gchar * v3270_get_selected_text(GtkWidget *widget);
  157 + const gchar * v3270_get_copy(GtkWidget *widget);
  158 + gchar * v3270_get_text(GtkWidget *widget,int offset, int len);
  159 + gchar * v3270_get_region(GtkWidget *widget, gint start_pos, gint end_pos, gboolean all);
  160 +
  161 + void v3270_set_string(GtkWidget *widget, const gchar *str);
  162 + void v3270_tab(GtkWidget *widget);
  163 + void v3270_backtab(GtkWidget *widget);
  164 +
  165 + // Cut & Paste
  166 + gboolean v3270_get_selection_bounds(GtkWidget *widget, gint *start, gint *end);
  167 + void v3270_unselect(GtkWidget *widget);
  168 + void v3270_paste(GtkWidget *widget);
  169 + void v3270_paste_string(GtkWidget *widget, const gchar *text, const gchar *encoding);
  170 + void v3270_select_region(GtkWidget *widget, gint start, gint end);
  171 +
  172 + // Colors
  173 + void v3270_set_colors(GtkWidget *widget, const gchar *);
  174 + void v3270_set_color_table(GdkColor *table, const gchar *colors);
  175 + const GdkColor * v3270_get_color_table(GtkWidget *widget);
  176 + void v3270_set_mono_color_table(GdkColor *table, const gchar *fg, const gchar *bg);
  177 + void v3270_draw_element(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *color);
  178 + void v3270_set_color(GtkWidget *widget, enum V3270_COLOR id, GdkColor *color);
  179 + GdkColor * v3270_get_color(GtkWidget *widget, enum V3270_COLOR id);
  180 +
  181 + // Misc
  182 + GtkIMContext * v3270_get_im_context(GtkWidget *widget);
  183 + gboolean v3270_get_toggle(GtkWidget *widget, LIB3270_TOGGLE ix);
  184 +
  185 + void v3270_set_host(GtkWidget *widget, const gchar *uri);
  186 +
  187 +
  188 +G_END_DECLS
  189 +
  190 +#endif // V3270_H_INCLUDED
... ...
widget.c 0 → 100644
  1 +++ a/widget.c
... ... @@ -0,0 +1,1221 @@
  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., 59 Temple
  19 + * Place, Suite 330, Boston, MA, 02111-1307, USA
  20 + *
  21 + * Este programa está nomeado como widget.c 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 <gtk/gtk.h>
  31 + #include <pw3270.h>
  32 + #include <lib3270.h>
  33 + #include <lib3270/session.h>
  34 + #include <lib3270/actions.h>
  35 + #include <lib3270/log.h>
  36 + #include <malloc.h>
  37 + #include "v3270.h"
  38 + #include "private.h"
  39 + #include "accessible.h"
  40 + #include "marshal.h"
  41 +
  42 + #define WIDTH_IN_PIXELS(terminal,x) (x * cols)
  43 + #define HEIGHT_IN_PIXELS(terminal,x) (x * (rows+1))
  44 +
  45 + #define CONTENTS_WIDTH(terminal) (cols * terminal->metrics.width)
  46 + #define CONTENTS_HEIGHT(terminal) (((rows+1) * terminal->metrics.spacing)+OIA_TOP_MARGIN+2)
  47 +
  48 +/*--[ Widget definition ]----------------------------------------------------------------------------*/
  49 +
  50 + G_DEFINE_TYPE(v3270, v3270, GTK_TYPE_WIDGET);
  51 +
  52 +/*--[ Globals ]--------------------------------------------------------------------------------------*/
  53 +
  54 + guint v3270_widget_signal[LAST_SIGNAL] = { 0 };
  55 + GdkCursor * v3270_cursor[V3270_CURSOR_COUNT] = { 0 };
  56 +
  57 +/*--[ Prototipes ]-----------------------------------------------------------------------------------*/
  58 +
  59 + // http://git.gnome.org/browse/gtk+/tree/gtk/gtkdrawingarea.c?h=gtk-3-0
  60 +
  61 +static void v3270_realize ( GtkWidget * widget) ;
  62 +static void v3270_size_allocate ( GtkWidget * widget,
  63 + GtkAllocation * allocation );
  64 +static void v3270_send_configure ( v3270 * terminal );
  65 +static AtkObject * v3270_get_accessible ( GtkWidget * widget );
  66 +
  67 +// Signals
  68 +static void v3270_activate (GtkWidget *widget);
  69 +
  70 +gboolean v3270_focus_in_event(GtkWidget *widget, GdkEventFocus *event);
  71 +gboolean v3270_focus_out_event(GtkWidget *widget, GdkEventFocus *event);
  72 +
  73 +#if GTK_CHECK_VERSION(3,0,0)
  74 +
  75 +static void v3270_destroy (GtkWidget * object);
  76 +
  77 +#else
  78 +
  79 +static void v3270_destroy (GtkObject * object);
  80 +
  81 +#endif // gtk3
  82 +
  83 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  84 +
  85 +static void v3270_cursor_draw(v3270 *widget)
  86 +{
  87 + int pos = lib3270_get_cursor_address(widget->host);
  88 + unsigned char c;
  89 + unsigned short attr;
  90 +
  91 + lib3270_get_contents(widget->host,pos,pos,&c,&attr);
  92 + v3270_update_cursor_surface(widget,c,attr);
  93 + gtk_widget_queue_draw_area( GTK_WIDGET(widget),
  94 + widget->cursor.rect.x,widget->cursor.rect.y,
  95 + widget->cursor.rect.width,widget->cursor.rect.height);
  96 +
  97 +}
  98 +
  99 +static void v3270_toggle_changed(v3270 *widget,LIB3270_TOGGLE toggle_id, gboolean toggle_state,const gchar *toggle_name)
  100 +{
  101 + trace("%s: toggle %d (%s)=%s",__FUNCTION__,toggle_id,toggle_name,toggle_state ? "Yes" : "No");
  102 +
  103 + switch(toggle_id)
  104 + {
  105 + case LIB3270_TOGGLE_CURSOR_POS:
  106 + case LIB3270_TOGGLE_CROSSHAIR:
  107 + v3270_reload(GTK_WIDGET(widget));
  108 + gtk_widget_queue_draw(GTK_WIDGET(widget));
  109 + break;
  110 +
  111 + case LIB3270_TOGGLE_CURSOR_BLINK:
  112 + widget->cursor.show |= 1;
  113 + break;
  114 +
  115 + case LIB3270_TOGGLE_INSERT:
  116 + v3270_draw_ins_status(widget);
  117 + v3270_cursor_draw(widget);
  118 + break;
  119 +
  120 + case LIB3270_TOGGLE_BOLD:
  121 + v3270_reload(GTK_WIDGET(widget));
  122 + gtk_widget_queue_draw(GTK_WIDGET(widget));
  123 + break;
  124 +
  125 + default:
  126 + return;
  127 +
  128 + }
  129 +
  130 +}
  131 +
  132 +static void loghandler(H3270 *session, const char *module, int rc, const char *fmt, va_list args)
  133 +{
  134 + g_logv(module,rc ? G_LOG_LEVEL_WARNING : G_LOG_LEVEL_MESSAGE, fmt, args);
  135 +}
  136 +
  137 +static gboolean v3270_popup_menu(GtkWidget * widget)
  138 +{
  139 + GdkEventButton event;
  140 +
  141 + memset(&event,0,sizeof(event));
  142 +
  143 + event.time = gtk_get_current_event_time();
  144 + event.button = 3;
  145 + event.type = GDK_BUTTON_PRESS;
  146 +
  147 + v3270_emit_popup( GTK_V3270(widget),
  148 + lib3270_get_cursor_address(GTK_V3270(widget)->host),
  149 + &event );
  150 +
  151 + return TRUE;
  152 +}
  153 +
  154 +#if GTK_CHECK_VERSION(3,0,0)
  155 +
  156 +static GtkSizeRequestMode get_request_mode(GtkWidget *widget)
  157 +{
  158 + int rows, cols;
  159 +
  160 + trace("%s",__FUNCTION__);
  161 +
  162 + lib3270_get_screen_size(GTK_V3270(widget)->host,&rows,&cols);
  163 +
  164 + return rows > cols ? GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT : GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
  165 +
  166 +}
  167 +
  168 +void get_preferred_height(GtkWidget *widget, gint *minimum_height, gint *natural_height)
  169 +{
  170 + int height = GTK_V3270(widget)->minimum_height;
  171 +
  172 + if(minimum_height)
  173 + *minimum_height = height ? height : 10;
  174 +
  175 + if(natural_height)
  176 + *natural_height = 400;
  177 +
  178 +}
  179 +
  180 +void get_preferred_width(GtkWidget *widget, gint *minimum_width, gint *natural_width)
  181 +{
  182 + int width = GTK_V3270(widget)->minimum_width;
  183 +
  184 + if(minimum_width)
  185 + *minimum_width = width ? width : 10;
  186 +
  187 + if(natural_width)
  188 + *natural_width = 600;
  189 +}
  190 +
  191 +/*
  192 +void get_preferred_height_for_width(GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height)
  193 +{
  194 + trace("%s",__FUNCTION__);
  195 +
  196 + if(minimum_height)
  197 + *minimum_height = 10;
  198 +
  199 + if(natural_height)
  200 + *natural_height = 10;
  201 +}
  202 +
  203 +static void get_preferred_width_for_height(GtkWidget *widget,gint height, gint *minimum_width, gint *natural_width)
  204 +{
  205 + trace("%s",__FUNCTION__);
  206 +
  207 + if(minimum_width)
  208 + *minimum_width = 10;
  209 +
  210 + if(natural_width)
  211 + *natural_width = 10;
  212 +
  213 +}
  214 +*/
  215 +
  216 +#endif // GTK(3,0,0)
  217 +
  218 +static void v3270_class_init(v3270Class *klass)
  219 +{
  220 + GObjectClass * gobject_class = G_OBJECT_CLASS(klass);
  221 + GtkWidgetClass * widget_class = GTK_WIDGET_CLASS(klass);
  222 +
  223 + lib3270_set_log_handler(loghandler);
  224 +
  225 + widget_class->realize = v3270_realize;
  226 + widget_class->size_allocate = v3270_size_allocate;
  227 + widget_class->key_press_event = v3270_key_press_event;
  228 + widget_class->key_release_event = v3270_key_release_event;
  229 + widget_class->focus_in_event = v3270_focus_in_event;
  230 + widget_class->focus_out_event = v3270_focus_out_event;
  231 + widget_class->button_press_event = v3270_button_press_event;
  232 + widget_class->button_release_event = v3270_button_release_event;
  233 + widget_class->motion_notify_event = v3270_motion_notify_event;
  234 + widget_class->popup_menu = v3270_popup_menu;
  235 +
  236 + /* Accessibility support */
  237 + widget_class->get_accessible = v3270_get_accessible;
  238 +
  239 + klass->activate = v3270_activate;
  240 + klass->toggle_changed = v3270_toggle_changed;
  241 + klass->message_changed = v3270_update_message;
  242 + klass->luname_changed = v3270_update_luname;
  243 +
  244 +#if GTK_CHECK_VERSION(3,0,0)
  245 +
  246 + widget_class->get_preferred_height = get_preferred_height;
  247 + widget_class->get_preferred_width = get_preferred_width;
  248 +// widget_class->get_preferred_width_for_height = get_preferred_width_for_height;
  249 +// widget_class->get_preferred_height_for_width = get_preferred_height_for_width;
  250 +
  251 + widget_class->destroy = v3270_destroy;
  252 + widget_class->draw = v3270_draw;
  253 +
  254 +#else
  255 +
  256 + {
  257 + GtkObjectClass *object_class = (GtkObjectClass*) klass;
  258 +
  259 + object_class->destroy = v3270_destroy;
  260 + }
  261 +
  262 + widget_class->expose_event = v3270_expose;
  263 +
  264 +
  265 +#endif // GTK3
  266 +
  267 + v3270_register_io_handlers(klass);
  268 +
  269 + // Cursors
  270 + {
  271 +#ifdef WIN32
  272 + static const gchar * cr[V3270_CURSOR_COUNT] =
  273 + {
  274 + "ibeam", // V3270_CURSOR_UNPROTECTED
  275 + "wait", // V3270_CURSOR_WAITING
  276 + "arrow", // V3270_CURSOR_LOCKED
  277 + "arrow", // V3270_CURSOR_PROTECTED
  278 + "hand", // V3270_CURSOR_MOVE_SELECTION
  279 + "sizenwse", // V3270_CURSOR_SELECTION_TOP_LEFT
  280 + "sizenesw", // V3270_CURSOR_SELECTION_TOP_RIGHT
  281 + "sizens", // V3270_CURSOR_SELECTION_TOP
  282 + "sizenesw", // V3270_CURSOR_SELECTION_BOTTOM_LEFT
  283 + "sizenwse", // V3270_CURSOR_SELECTION_BOTTOM_RIGHT
  284 + "sizens", // V3270_CURSOR_SELECTION_BOTTOM
  285 + "sizewe", // V3270_CURSOR_SELECTION_LEFT
  286 + "sizewe", // V3270_CURSOR_SELECTION_RIGHT
  287 + };
  288 +#else
  289 + static const int cr[V3270_CURSOR_COUNT] =
  290 + {
  291 + GDK_XTERM, // V3270_CURSOR_UNPROTECTED
  292 + GDK_WATCH, // V3270_CURSOR_WAITING
  293 + GDK_X_CURSOR, // V3270_CURSOR_LOCKED
  294 + GDK_ARROW, // V3270_CURSOR_PROTECTED
  295 + GDK_HAND1, // V3270_CURSOR_MOVE_SELECTION
  296 + GDK_TOP_LEFT_CORNER, // V3270_CURSOR_SELECTION_TOP_LEFT
  297 + GDK_TOP_RIGHT_CORNER, // V3270_CURSOR_SELECTION_TOP_RIGHT
  298 + GDK_TOP_SIDE, // V3270_CURSOR_SELECTION_TOP
  299 + GDK_BOTTOM_LEFT_CORNER, // V3270_CURSOR_SELECTION_BOTTOM_LEFT
  300 + GDK_BOTTOM_RIGHT_CORNER, // V3270_CURSOR_SELECTION_BOTTOM_RIGHT
  301 + GDK_BOTTOM_SIDE, // V3270_CURSOR_SELECTION_BOTTOM
  302 + GDK_LEFT_SIDE, // V3270_CURSOR_SELECTION_LEFT
  303 + GDK_RIGHT_SIDE, // V3270_CURSOR_SELECTION_RIGHT
  304 + };
  305 +#endif // WIN32
  306 +
  307 + int f;
  308 +
  309 + for(f=0;f<V3270_CURSOR_COUNT;f++)
  310 + {
  311 + #ifdef WIN32
  312 + v3270_cursor[f] = gdk_cursor_new_from_name(gdk_display_get_default(),cr[f]);
  313 + #else
  314 + v3270_cursor[f] = gdk_cursor_new(cr[f]);
  315 + #endif
  316 + }
  317 + }
  318 +
  319 + // Signals
  320 + widget_class->activate_signal =
  321 + g_signal_new( "activate",
  322 + G_OBJECT_CLASS_TYPE (gobject_class),
  323 + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
  324 + G_STRUCT_OFFSET (v3270Class, activate),
  325 + NULL, NULL,
  326 + pw3270_VOID__VOID,
  327 + G_TYPE_NONE, 0);
  328 +
  329 + v3270_widget_signal[SIGNAL_TOGGLE_CHANGED] =
  330 + g_signal_new( "toggle_changed",
  331 + G_OBJECT_CLASS_TYPE (gobject_class),
  332 + G_SIGNAL_RUN_FIRST,
  333 + G_STRUCT_OFFSET (v3270Class, toggle_changed),
  334 + NULL, NULL,
  335 + pw3270_VOID__VOID_ENUM_BOOL_POINTER,
  336 + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_STRING);
  337 +
  338 + v3270_widget_signal[SIGNAL_MESSAGE_CHANGED] =
  339 + g_signal_new( "message_changed",
  340 + G_OBJECT_CLASS_TYPE (gobject_class),
  341 + G_SIGNAL_RUN_FIRST,
  342 + G_STRUCT_OFFSET (v3270Class, message_changed),
  343 + NULL, NULL,
  344 + pw3270_VOID__VOID_ENUM,
  345 + G_TYPE_NONE, 1, G_TYPE_UINT);
  346 +
  347 + v3270_widget_signal[SIGNAL_LUNAME_CHANGED] =
  348 + g_signal_new( "luname_changed",
  349 + G_OBJECT_CLASS_TYPE (gobject_class),
  350 + G_SIGNAL_RUN_FIRST,
  351 + G_STRUCT_OFFSET (v3270Class, luname_changed),
  352 + NULL, NULL,
  353 + pw3270_VOID__VOID_POINTER,
  354 + G_TYPE_NONE, 1, G_TYPE_STRING);
  355 +
  356 + v3270_widget_signal[SIGNAL_KEYPRESS] =
  357 + g_signal_new( "keypress",
  358 + G_OBJECT_CLASS_TYPE (gobject_class),
  359 + G_SIGNAL_RUN_LAST,
  360 + G_STRUCT_OFFSET (v3270Class, keypress),
  361 + NULL, NULL,
  362 + pw3270_BOOL__VOID_UINT_ENUM,
  363 + G_TYPE_BOOLEAN, 2, G_TYPE_UINT, G_TYPE_UINT);
  364 +
  365 + v3270_widget_signal[SIGNAL_CONNECTED] =
  366 + g_signal_new( "connected",
  367 + G_OBJECT_CLASS_TYPE (gobject_class),
  368 + G_SIGNAL_RUN_FIRST,
  369 + 0,
  370 + NULL, NULL,
  371 + pw3270_VOID__POINTER,
  372 + G_TYPE_NONE, 1, G_TYPE_STRING);
  373 +
  374 + v3270_widget_signal[SIGNAL_DISCONNECTED] =
  375 + g_signal_new( "disconnected",
  376 + G_OBJECT_CLASS_TYPE (gobject_class),
  377 + G_SIGNAL_RUN_FIRST,
  378 + 0,
  379 + NULL, NULL,
  380 + pw3270_VOID__VOID,
  381 + G_TYPE_NONE, 0);
  382 +
  383 + v3270_widget_signal[SIGNAL_UPDATE_CONFIG] =
  384 + g_signal_new( "update_config",
  385 + G_OBJECT_CLASS_TYPE (gobject_class),
  386 + G_SIGNAL_RUN_FIRST,
  387 + 0,
  388 + NULL, NULL,
  389 + pw3270_VOID__VOID_POINTER_POINTER,
  390 + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
  391 +
  392 + v3270_widget_signal[SIGNAL_MODEL_CHANGED] =
  393 + g_signal_new( "model_changed",
  394 + G_OBJECT_CLASS_TYPE (gobject_class),
  395 + G_SIGNAL_RUN_FIRST,
  396 + 0,
  397 + NULL, NULL,
  398 + pw3270_VOID__VOID_UINT_POINTER,
  399 + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
  400 +
  401 + v3270_widget_signal[SIGNAL_SELECTING] =
  402 + g_signal_new( "selecting",
  403 + G_OBJECT_CLASS_TYPE (gobject_class),
  404 + G_SIGNAL_RUN_FIRST,
  405 + 0,
  406 + NULL, NULL,
  407 + pw3270_VOID__VOID_BOOL,
  408 + G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
  409 +
  410 + v3270_widget_signal[SIGNAL_POPUP] =
  411 + g_signal_new( "popup",
  412 + G_OBJECT_CLASS_TYPE (gobject_class),
  413 + G_SIGNAL_RUN_LAST,
  414 + 0,
  415 + NULL, NULL,
  416 + pw3270_BOOL__VOID_BOOL_BOOL_POINTER,
  417 + G_TYPE_BOOLEAN, 3, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_POINTER);
  418 +
  419 + v3270_widget_signal[SIGNAL_PASTENEXT] =
  420 + g_signal_new( "pastenext",
  421 + G_OBJECT_CLASS_TYPE (gobject_class),
  422 + G_SIGNAL_RUN_FIRST,
  423 + 0,
  424 + NULL, NULL,
  425 + pw3270_VOID__VOID_BOOL,
  426 + G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
  427 +
  428 + v3270_widget_signal[SIGNAL_CLIPBOARD] =
  429 + g_signal_new( "has_text",
  430 + G_OBJECT_CLASS_TYPE (gobject_class),
  431 + G_SIGNAL_RUN_FIRST,
  432 + 0,
  433 + NULL, NULL,
  434 + pw3270_VOID__VOID_BOOL,
  435 + G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
  436 +
  437 + v3270_widget_signal[SIGNAL_CHANGED] =
  438 + g_signal_new( "changed",
  439 + G_OBJECT_CLASS_TYPE (gobject_class),
  440 + G_SIGNAL_RUN_FIRST,
  441 + 0,
  442 + NULL, NULL,
  443 + pw3270_VOID__VOID_UINT_UINT,
  444 + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
  445 +
  446 +}
  447 +
  448 +void v3270_update_font_metrics(v3270 *terminal, cairo_t *cr, int width, int height)
  449 +{
  450 + // update font metrics
  451 + static const int font_size[] = { 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72, 0 };
  452 + int f, rows, cols, hFont;
  453 + int size = font_size[0];
  454 +
  455 + cairo_font_extents_t extents;
  456 +
  457 + lib3270_get_screen_size(terminal->host,&rows,&cols);
  458 +
  459 + terminal->font_weight = lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_BOLD) ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL;
  460 +
  461 + cairo_select_font_face(cr, terminal->font_family, CAIRO_FONT_SLANT_NORMAL,terminal->font_weight);
  462 +
  463 + for(f=0;font_size[f];f++)
  464 + {
  465 + cairo_set_font_size(cr,font_size[f]);
  466 + cairo_font_extents(cr,&extents);
  467 +
  468 + if(f == 0)
  469 + {
  470 + terminal->minimum_width = (cols * extents.max_x_advance);
  471 + terminal->minimum_height = ((rows+1) * (extents.height + extents.descent)) + (OIA_TOP_MARGIN+2);
  472 + }
  473 +
  474 + if( HEIGHT_IN_PIXELS(terminal,(extents.height+extents.descent)) < height && WIDTH_IN_PIXELS(terminal,extents.max_x_advance) < width )
  475 + size = font_size[f];
  476 + }
  477 +
  478 + cairo_set_font_size(cr,size);
  479 +
  480 +#if !GTK_CHECK_VERSION(3,0,0)
  481 + gtk_widget_set_size_request(GTK_WIDGET(terminal),terminal->minimum_width,terminal->minimum_height);
  482 +#endif // !GTK(3,0,0)
  483 +
  484 +/*
  485 + double sx, sy;
  486 + cairo_matrix_t font_matrix;
  487 +
  488 + cairo_set_font_size(cr,10);
  489 + cairo_font_extents(cr,&extents);
  490 +
  491 + trace("font - extents.height=%f extents.width=%f",extents.height,extents.max_x_advance);
  492 +
  493 + sx = ((double) width) / (((double) terminal->cols) * extents.max_x_advance);
  494 + sy = ((double) height) / (((double) terminal->rows) * extents.height);
  495 +
  496 + trace("sy=%f sx=%f ",sy,sx);
  497 +
  498 + cairo_get_font_matrix(cr,&font_matrix);
  499 + cairo_matrix_scale(&font_matrix, sx, sy);
  500 + cairo_set_font_matrix(cr,&font_matrix);
  501 +*/
  502 +
  503 + /* Save scaled font for use on next drawings */
  504 + if(terminal->font_scaled)
  505 + cairo_scaled_font_destroy(terminal->font_scaled);
  506 +
  507 + terminal->font_scaled = cairo_get_scaled_font(cr);
  508 + cairo_scaled_font_reference(terminal->font_scaled);
  509 +
  510 + cairo_scaled_font_extents(terminal->font_scaled,&extents);
  511 +
  512 + terminal->metrics.width = (int) extents.max_x_advance;
  513 + terminal->metrics.height = (int) extents.height;
  514 + terminal->metrics.ascent = (int) extents.ascent;
  515 + terminal->metrics.descent = (int) extents.descent;
  516 +
  517 + hFont = terminal->metrics.height + terminal->metrics.descent;
  518 +
  519 + // Create new cursor surface
  520 + if(terminal->cursor.surface)
  521 + cairo_surface_destroy(terminal->cursor.surface);
  522 +
  523 + terminal->cursor.surface = gdk_window_create_similar_surface(gtk_widget_get_window(GTK_WIDGET(terminal)),CAIRO_CONTENT_COLOR,terminal->metrics.width,hFont);
  524 +
  525 + // Center image
  526 + size = CONTENTS_WIDTH(terminal);
  527 + terminal->metrics.left = (width >> 1) - ((size) >> 1);
  528 +
  529 + terminal->metrics.spacing = height / (rows+2);
  530 + if(terminal->metrics.spacing < hFont)
  531 + terminal->metrics.spacing = hFont;
  532 +
  533 + size = CONTENTS_HEIGHT(terminal);
  534 +
  535 + terminal->metrics.top = (height >> 1) - (size >> 1);
  536 +
  537 +}
  538 +
  539 +static void set_timer(H3270 *session, unsigned char on)
  540 +{
  541 + GtkWidget *widget = GTK_WIDGET(session->widget);
  542 +
  543 + if(on)
  544 + v3270_start_timer(widget);
  545 + else
  546 + v3270_stop_timer(widget);
  547 +
  548 +}
  549 +
  550 +static void update_toggle(H3270 *session, LIB3270_TOGGLE ix, unsigned char value, LIB3270_TOGGLE_TYPE reason, const char *name)
  551 +{
  552 + g_signal_emit(GTK_WIDGET(session->widget), v3270_widget_signal[SIGNAL_TOGGLE_CHANGED], 0, (guint) ix, (gboolean) (value != 0), (gchar *) name);
  553 +}
  554 +
  555 +static void update_message(H3270 *session, LIB3270_MESSAGE id)
  556 +{
  557 + g_signal_emit(GTK_WIDGET(session->widget), v3270_widget_signal[SIGNAL_MESSAGE_CHANGED], 0, (gint) id);
  558 +}
  559 +
  560 +static void update_luname(H3270 *session, const char *name)
  561 +{
  562 + g_signal_emit(GTK_WIDGET(session->widget), v3270_widget_signal[SIGNAL_LUNAME_CHANGED], 0, (gchar *) name);
  563 +}
  564 +
  565 +static void select_cursor(H3270 *session, LIB3270_CURSOR id)
  566 +{
  567 + GtkWidget *widget = GTK_WIDGET(session->widget);
  568 +
  569 + if(gtk_widget_get_realized(widget) && gtk_widget_get_has_window(widget))
  570 + {
  571 + GTK_V3270(widget)->pointer_id = id;
  572 + v3270_update_mouse_pointer(widget);
  573 + }
  574 +}
  575 +
  576 +static void ctlr_done(H3270 *session)
  577 +{
  578 + GtkWidget *widget = GTK_WIDGET(session->widget);
  579 +
  580 + if(gtk_widget_get_realized(widget) && gtk_widget_get_has_window(widget))
  581 + {
  582 + v3270_update_mouse_pointer(widget);
  583 + }
  584 +
  585 +}
  586 +
  587 +static void update_connect(H3270 *session, unsigned char connected)
  588 +{
  589 + v3270 *widget = GTK_V3270(session->widget);
  590 +
  591 + if(connected)
  592 + {
  593 + widget->cursor.show |= 2;
  594 + g_signal_emit(GTK_WIDGET(widget), v3270_widget_signal[SIGNAL_CONNECTED], 0, session->full_current_host);
  595 + }
  596 + else
  597 + {
  598 + widget->cursor.show &= ~2;
  599 + g_signal_emit(GTK_WIDGET(widget), v3270_widget_signal[SIGNAL_DISCONNECTED], 0);
  600 + }
  601 +
  602 + gtk_widget_queue_draw(GTK_WIDGET(widget));
  603 +}
  604 +
  605 +static void update_screen_size(H3270 *session,unsigned short rows, unsigned short cols)
  606 +{
  607 +// trace("Widget %p changes to %dx%d",session->widget,cols,rows);
  608 + v3270_reload(GTK_WIDGET(session->widget));
  609 + gtk_widget_queue_draw(GTK_WIDGET(session->widget));
  610 +}
  611 +
  612 +static void update_model(H3270 *session, const char *name, int model, int rows, int cols)
  613 +{
  614 + g_signal_emit(GTK_WIDGET(session->widget),v3270_widget_signal[SIGNAL_MODEL_CHANGED], 0, (guint) model, name);
  615 +}
  616 +
  617 +static void changed(H3270 *session, int offset, int len)
  618 +{
  619 + GtkWidget * widget = session->widget;
  620 + GtkAccessible * obj = GTK_V3270(widget)->accessible;
  621 +
  622 + trace("%s: offset=%d len=%d",__FUNCTION__,offset,len)
  623 +
  624 + if(obj)
  625 + {
  626 + // Get new text, notify atk
  627 + gsize bytes_written = 0;
  628 + char * text = lib3270_get_text(session,offset,len);
  629 +
  630 + if(text)
  631 + {
  632 + GError * error = NULL;
  633 + gchar * utfchar = g_convert_with_fallback( text,
  634 + -1,
  635 + "UTF-8",
  636 + lib3270_get_charset(session),
  637 + " ",
  638 + NULL,
  639 + &bytes_written,
  640 + &error );
  641 +
  642 + free(text);
  643 +
  644 + if(error)
  645 + {
  646 + g_warning("%s failed: %s",__FUNCTION__,error->message);
  647 + g_error_free(error);
  648 + }
  649 +
  650 + if(utfchar)
  651 + {
  652 + g_signal_emit_by_name(obj, "text-insert", offset, bytes_written, utfchar);
  653 + g_free(utfchar);
  654 + }
  655 +
  656 + }
  657 + }
  658 +
  659 + g_signal_emit(GTK_WIDGET(widget),v3270_widget_signal[SIGNAL_CHANGED], 0, (guint) offset, (guint) len);
  660 +
  661 +}
  662 +
  663 +static void set_selection(H3270 *session, unsigned char status)
  664 +{
  665 + GtkWidget * widget = GTK_WIDGET(session->widget);
  666 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_SELECTING], 0, status ? TRUE : FALSE);
  667 +}
  668 +
  669 +static void update_selection(H3270 *session, int start, int end)
  670 +{
  671 + // Selected region changed
  672 + GtkWidget * widget = GTK_WIDGET(session->widget);
  673 + GtkAccessible * atk_obj = GTK_V3270(widget)->accessible;
  674 +
  675 + if(atk_obj)
  676 + g_signal_emit_by_name(atk_obj,"text-selection-changed");
  677 +
  678 +}
  679 +
  680 +static void v3270_init(v3270 *widget)
  681 +{
  682 + trace("%s",__FUNCTION__);
  683 + widget->host = lib3270_session_new("");
  684 +
  685 + if(widget->host->sz != sizeof(H3270))
  686 + {
  687 + g_error( _( "Unexpected signature in H3270 object, possible version mismatch in lib3270") );
  688 + return;
  689 + }
  690 +
  691 + widget->host->widget = widget;
  692 +
  693 + widget->host->update = v3270_update_char;
  694 + widget->host->changed = changed;
  695 + widget->host->set_timer = set_timer;
  696 +
  697 + widget->host->set_selection = set_selection;
  698 + widget->host->update_selection = update_selection;
  699 +
  700 + widget->host->update_luname = update_luname;
  701 + widget->host->configure = update_screen_size;
  702 + widget->host->update_status = update_message;
  703 + widget->host->update_cursor = v3270_update_cursor;
  704 + widget->host->update_toggle = update_toggle;
  705 + widget->host->update_oia = v3270_update_oia;
  706 + widget->host->cursor = select_cursor;
  707 + widget->host->update_connect = update_connect;
  708 + widget->host->update_model = update_model;
  709 + widget->host->changed = changed;
  710 + widget->host->ctlr_done = ctlr_done;
  711 +
  712 +
  713 + // Setup input method
  714 + widget->input_method = gtk_im_multicontext_new();
  715 + g_signal_connect(G_OBJECT(widget->input_method),"commit",G_CALLBACK(v3270_key_commit),widget);
  716 +
  717 + gtk_widget_set_can_default(GTK_WIDGET(widget),TRUE);
  718 + gtk_widget_set_can_focus(GTK_WIDGET(widget),TRUE);
  719 +
  720 + // Setup events
  721 + gtk_widget_add_events(GTK_WIDGET(widget),GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_MOTION_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK|GDK_ENTER_NOTIFY_MASK);
  722 +
  723 +}
  724 +
  725 +GtkWidget * v3270_new(void)
  726 +{
  727 + return g_object_new(GTK_TYPE_V3270, NULL);
  728 +}
  729 +
  730 +#if GTK_CHECK_VERSION(3,0,0)
  731 +static void v3270_destroy(GtkWidget *widget)
  732 +#else
  733 +static void v3270_destroy(GtkObject *widget)
  734 +#endif
  735 +{
  736 + v3270 * terminal = GTK_V3270(widget);
  737 +
  738 + trace("%s %p",__FUNCTION__,widget);
  739 +
  740 + if(terminal->accessible)
  741 + {
  742 + gtk_accessible_set_widget(terminal->accessible, NULL);
  743 + g_object_unref(terminal->accessible);
  744 + terminal->accessible = NULL;
  745 + }
  746 +
  747 + if(terminal->host)
  748 + {
  749 + lib3270_session_free(terminal->host);
  750 + terminal->host = NULL;
  751 + }
  752 +
  753 + if(terminal->font_family)
  754 + {
  755 + g_free(terminal->font_family);
  756 + terminal->font_family = 0;
  757 + }
  758 +
  759 + if(terminal->font_scaled)
  760 + {
  761 + cairo_scaled_font_destroy(terminal->font_scaled);
  762 + terminal->font_scaled = NULL;
  763 + }
  764 +
  765 + if(terminal->surface)
  766 + {
  767 + cairo_surface_destroy(terminal->surface);
  768 + terminal->surface = NULL;
  769 + }
  770 +
  771 + if(terminal->cursor.surface)
  772 + {
  773 + cairo_surface_destroy(terminal->cursor.surface);
  774 + terminal->cursor.surface = NULL;
  775 + }
  776 +
  777 + if(terminal->timer)
  778 + {
  779 + g_source_destroy(terminal->timer);
  780 + while(terminal->timer)
  781 + g_source_unref(terminal->timer);
  782 + }
  783 +
  784 + if(terminal->cursor.timer)
  785 + {
  786 + g_source_destroy(terminal->cursor.timer);
  787 + while(terminal->cursor.timer)
  788 + g_source_unref(terminal->cursor.timer);
  789 + }
  790 +
  791 + if(terminal->input_method)
  792 + {
  793 + g_object_unref(terminal->input_method);
  794 + terminal->input_method = NULL;
  795 + }
  796 +
  797 + if(terminal->clipboard)
  798 + {
  799 + g_free(terminal->clipboard);
  800 + terminal->clipboard = NULL;
  801 + }
  802 +
  803 +#if GTK_CHECK_VERSION(3,0,0)
  804 + GTK_WIDGET_CLASS(v3270_parent_class)->destroy(widget);
  805 +#else
  806 + GTK_OBJECT_CLASS(v3270_parent_class)->destroy(widget);
  807 +#endif // GTK3
  808 +
  809 +}
  810 +
  811 +static gboolean timer_tick(v3270 *widget)
  812 +{
  813 + if(lib3270_get_toggle(widget->host,LIB3270_TOGGLE_CURSOR_BLINK))
  814 + {
  815 + widget->cursor.show ^= 1;
  816 + gtk_widget_queue_draw_area(GTK_WIDGET(widget), widget->cursor.rect.x,
  817 + widget->cursor.rect.y,
  818 + widget->cursor.rect.width,
  819 + widget->cursor.rect.height );
  820 + }
  821 +
  822 + return TRUE;
  823 +}
  824 +
  825 +static void release_timer(v3270 *widget)
  826 +{
  827 + widget->cursor.timer = NULL;
  828 +}
  829 +
  830 +static void v3270_realize(GtkWidget * widget)
  831 +{
  832 + if(!gtk_widget_get_has_window(widget))
  833 + {
  834 + GTK_WIDGET_CLASS(v3270_parent_class)->realize(widget);
  835 + }
  836 + else
  837 + {
  838 + GtkAllocation allocation;
  839 + GdkWindow *window;
  840 + GdkWindowAttr attributes;
  841 + gint attributes_mask;
  842 +
  843 +
  844 + gtk_widget_set_realized (widget, TRUE);
  845 +
  846 + gtk_widget_get_allocation (widget, &allocation);
  847 +
  848 + attributes.window_type = GDK_WINDOW_CHILD;
  849 + attributes.x = allocation.x;
  850 + attributes.y = allocation.y;
  851 + attributes.width = allocation.width;
  852 + attributes.height = allocation.height;
  853 + attributes.wclass = GDK_INPUT_OUTPUT;
  854 + attributes.visual = gtk_widget_get_visual (widget);
  855 + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
  856 +
  857 + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
  858 +
  859 + window = gdk_window_new(gtk_widget_get_parent_window (widget),&attributes, attributes_mask);
  860 + gdk_window_set_user_data (window, widget);
  861 + gtk_widget_set_window(widget, window);
  862 +
  863 + gtk_im_context_set_client_window(GTK_V3270(widget)->input_method,window);
  864 +
  865 + }
  866 +
  867 +#if !GTK_CHECK_VERSION(3,0,0)
  868 + widget->style = gtk_style_attach (widget->style, widget->window);
  869 + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
  870 +#endif // !GTK3
  871 +
  872 + v3270_reload(widget);
  873 +
  874 + v3270_send_configure(GTK_V3270(widget));
  875 +
  876 + if(!GTK_V3270(widget)->cursor.timer)
  877 + {
  878 + // Setup cursor blink timer
  879 + v3270 *terminal = GTK_V3270(widget);
  880 +
  881 + terminal->cursor.timer = g_timeout_source_new(500);
  882 + g_source_set_callback(terminal->cursor.timer,(GSourceFunc) timer_tick, widget, (GDestroyNotify) release_timer);
  883 +
  884 + g_source_attach(terminal->cursor.timer, NULL);
  885 + g_source_unref(terminal->cursor.timer);
  886 + }
  887 +
  888 +}
  889 +
  890 +static void v3270_size_allocate(GtkWidget * widget, GtkAllocation * allocation)
  891 +{
  892 + g_return_if_fail(GTK_IS_V3270(widget));
  893 + g_return_if_fail(allocation != NULL);
  894 +
  895 +// trace("Widget size changes to %dx%d",allocation->width,allocation->height);
  896 +
  897 + gtk_widget_set_allocation(widget, allocation);
  898 +
  899 +#if !GTK_CHECK_VERSION(3,0,0)
  900 + {
  901 + v3270 *terminal = GTK_V3270(widget);
  902 +
  903 + terminal->width = allocation->width;
  904 + terminal->height = allocation->height;
  905 + }
  906 +#endif
  907 +
  908 + if(gtk_widget_get_realized(widget))
  909 + {
  910 + if(gtk_widget_get_has_window(widget))
  911 + gdk_window_move_resize(gtk_widget_get_window (widget),allocation->x, allocation->y,allocation->width, allocation->height);
  912 +
  913 + v3270_reload(widget);
  914 + v3270_send_configure(GTK_V3270(widget));
  915 + }
  916 +}
  917 +
  918 +static void v3270_send_configure(v3270 * terminal)
  919 +{
  920 + GtkAllocation allocation;
  921 + GtkWidget *widget;
  922 + GdkEvent *event = gdk_event_new(GDK_CONFIGURE);
  923 +
  924 + widget = GTK_WIDGET(terminal);
  925 +
  926 + gtk_widget_get_allocation(widget, &allocation);
  927 +
  928 + event->configure.window = g_object_ref(gtk_widget_get_window(widget));
  929 + event->configure.send_event = TRUE;
  930 + event->configure.x = allocation.x;
  931 + event->configure.y = allocation.y;
  932 + event->configure.width = allocation.width;
  933 + event->configure.height = allocation.height;
  934 +
  935 +#if( !GTK_CHECK_VERSION(3,0,0))
  936 + terminal->width = allocation.width;
  937 + terminal->height = allocation.height;
  938 +#endif
  939 +
  940 + gtk_widget_event(widget, event);
  941 + gdk_event_free(event);
  942 +}
  943 +
  944 +void v3270_set_colors(GtkWidget *widget, const gchar *colors)
  945 +{
  946 + g_return_if_fail(GTK_IS_V3270(widget));
  947 +
  948 + if(!colors)
  949 + {
  950 + colors = "#000000," // V3270_COLOR_BACKGROUND
  951 + "#7890F0," // V3270_COLOR_BLUE
  952 + "#FF0000," // V3270_COLOR_RED
  953 + "#FF00FF," // V3270_COLOR_PINK
  954 + "#00FF00," // V3270_COLOR_GREEN
  955 + "#00FFFF," // V3270_COLOR_TURQUOISE
  956 + "#FFFF00," // V3270_COLOR_YELLOW
  957 + "#FFFFFF," // V3270_COLOR_WHITE
  958 + "#000000," // V3270_COLOR_BLACK
  959 + "#000080," // V3270_COLOR_DARK_BLUE
  960 + "#FFA200," // V3270_COLOR_ORANGE
  961 + "#800080," // V3270_COLOR_PURPLE
  962 + "#008000," // V3270_COLOR_DARK_GREEN
  963 + "#008080," // V3270_COLOR_DARK_TURQUOISE
  964 + "#A0A000," // V3270_COLOR_MUSTARD
  965 + "#C0C0C0," // V3270_COLOR_GRAY
  966 +
  967 + "#00FF00," // V3270_COLOR_FIELD_DEFAULT
  968 + "#FF0000," // V3270_COLOR_FIELD_INTENSIFIED
  969 + "#00FFFF," // V3270_COLOR_FIELD_PROTECTED
  970 + "#FFFFFF," // V3270_COLOR_FIELD_PROTECTED_INTENSIFIED
  971 +
  972 + "#404040," // V3270_COLOR_SELECTED_BG
  973 + "#FFFFFF," // V3270_COLOR_SELECTED_FG,
  974 +
  975 + "#00FF00," // V3270_COLOR_CROSS_HAIR
  976 +
  977 + "#000000," // V3270_COLOR_OIA_BACKGROUND
  978 + "#00FF00," // V3270_COLOR_OIA
  979 + "#7890F0," // V3270_COLOR_OIA_SEPARATOR
  980 + "#FFFFFF," // V3270_COLOR_OIA_STATUS_OK
  981 + "#FF0000"; // V3270_COLOR_OIA_STATUS_INVALID
  982 +
  983 + }
  984 +
  985 + v3270_set_color_table(GTK_V3270(widget)->color,colors);
  986 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_UPDATE_CONFIG], 0, "colors", colors);
  987 + v3270_reload(widget);
  988 +
  989 +}
  990 +
  991 +void v3270_set_color(GtkWidget *widget, enum V3270_COLOR id, GdkColor *color)
  992 +{
  993 + g_return_if_fail(GTK_IS_V3270(widget));
  994 +
  995 + GTK_V3270(widget)->color[id] = *color;
  996 +
  997 +#if !GTK_CHECK_VERSION(3,0,0)
  998 + gdk_colormap_alloc_color(gtk_widget_get_default_colormap(),color,TRUE,TRUE);
  999 +#endif // !GTK(3,0,0)
  1000 +
  1001 +}
  1002 +GdkColor * v3270_get_color(GtkWidget *widget, enum V3270_COLOR id)
  1003 +{
  1004 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  1005 + return GTK_V3270(widget)->color+id;
  1006 +}
  1007 +
  1008 +const GdkColor * v3270_get_color_table(GtkWidget *widget)
  1009 +{
  1010 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  1011 + return GTK_V3270(widget)->color;
  1012 +}
  1013 +
  1014 +void v3270_set_mono_color_table(GdkColor *clr, const gchar *fg, const gchar *bg)
  1015 +{
  1016 + int f;
  1017 +
  1018 + gdk_color_parse(bg,clr);
  1019 + gdk_color_parse(fg,clr+1);
  1020 +
  1021 + for(f=2;f<V3270_COLOR_COUNT;f++)
  1022 + clr[f] = clr[1];
  1023 +
  1024 + clr[V3270_COLOR_BLACK] = *clr;
  1025 + clr[V3270_COLOR_OIA_BACKGROUND] = *clr;
  1026 + clr[V3270_COLOR_SELECTED_BG] = clr[V3270_COLOR_WHITE];
  1027 + clr[V3270_COLOR_SELECTED_FG] = clr[V3270_COLOR_BLACK];
  1028 +
  1029 +
  1030 +}
  1031 +
  1032 +void v3270_set_color_table(GdkColor *table, const gchar *colors)
  1033 +{
  1034 + gchar **clr;
  1035 + guint cnt;
  1036 + int f;
  1037 +
  1038 + clr = g_strsplit(colors,",",V3270_COLOR_COUNT+1);
  1039 + cnt = g_strv_length(clr);
  1040 + switch(cnt)
  1041 + {
  1042 + case V3270_COLOR_COUNT: // Complete string
  1043 + for(f=0;f < V3270_COLOR_COUNT;f++)
  1044 + gdk_color_parse(clr[f],table+f);
  1045 + break;
  1046 +
  1047 + default:
  1048 +
  1049 + g_warning("Color table has %d elements; should be %d.",cnt,V3270_COLOR_COUNT);
  1050 +
  1051 + for(f=0;f < cnt;f++)
  1052 + gdk_color_parse(clr[f],table+f);
  1053 +
  1054 + for(f=cnt; f < V3270_COLOR_COUNT;f++)
  1055 + gdk_color_parse(clr[cnt-1],table+f);
  1056 +
  1057 + clr[V3270_COLOR_OIA_BACKGROUND] = clr[0];
  1058 + clr[V3270_COLOR_SELECTED_BG] = clr[0];
  1059 +
  1060 + }
  1061 +
  1062 + g_strfreev(clr);
  1063 +
  1064 +}
  1065 +
  1066 +void v3270_set_font_family(GtkWidget *widget, const gchar *name)
  1067 +{
  1068 + v3270 * terminal;
  1069 +
  1070 + g_return_if_fail(GTK_IS_V3270(widget));
  1071 +
  1072 + terminal = GTK_V3270(widget);
  1073 +
  1074 + if(terminal->font_family)
  1075 + {
  1076 + if(!g_strcasecmp(terminal->font_family,name))
  1077 + return;
  1078 + g_free(terminal->font_family);
  1079 + terminal->font_family = NULL;
  1080 + }
  1081 +
  1082 + if(!name)
  1083 + {
  1084 + // TODO (perry#3#): Get default font family from currrent style
  1085 + name = "courier new";
  1086 + }
  1087 +
  1088 + terminal->font_family = g_strdup(name);
  1089 + terminal->font_weight = lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_BOLD) ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL;
  1090 +
  1091 + trace("%s: %s (%p)",__FUNCTION__,terminal->font_family,terminal->font_family);
  1092 +
  1093 + g_signal_emit(widget,v3270_widget_signal[SIGNAL_UPDATE_CONFIG], 0, "font-family", name);
  1094 +
  1095 + v3270_reload(widget);
  1096 + gtk_widget_queue_draw(widget);
  1097 +
  1098 +
  1099 +}
  1100 +
  1101 +const gchar * v3270_get_font_family(GtkWidget *widget)
  1102 +{
  1103 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  1104 + return GTK_V3270(widget)->font_family;
  1105 +}
  1106 +
  1107 +void v3270_disconnect(GtkWidget *widget)
  1108 +{
  1109 + g_return_if_fail(GTK_IS_V3270(widget));
  1110 + lib3270_disconnect(GTK_V3270(widget)->host);
  1111 +}
  1112 +
  1113 +H3270 * v3270_get_session(GtkWidget *widget)
  1114 +{
  1115 + g_return_val_if_fail(GTK_IS_V3270(widget),NULL);
  1116 +
  1117 + return GTK_V3270(widget)->host;
  1118 +}
  1119 +
  1120 +int v3270_connect(GtkWidget *widget, const gchar *host)
  1121 +{
  1122 + v3270 * terminal;
  1123 + int rc = -1;
  1124 +
  1125 + trace("%s widget=%p host=%p",__FUNCTION__,widget,host);
  1126 +
  1127 + g_return_val_if_fail(GTK_IS_V3270(widget),EINVAL);
  1128 +
  1129 + terminal = GTK_V3270(widget);
  1130 +
  1131 + rc = lib3270_connect(terminal->host,host,0);
  1132 +
  1133 + trace("%s exits with rc=%d (%s)",__FUNCTION__,rc,strerror(rc));
  1134 +
  1135 + return rc;
  1136 +}
  1137 +
  1138 +static gboolean notify_focus(GtkWidget *widget, GdkEventFocus *event)
  1139 +{
  1140 + GtkAccessible *obj = GTK_V3270(widget)->accessible;
  1141 +
  1142 + if(obj)
  1143 + g_signal_emit_by_name (obj, "focus-event", event->in);
  1144 +
  1145 + return FALSE;
  1146 +}
  1147 +gboolean v3270_focus_in_event(GtkWidget *widget, GdkEventFocus *event)
  1148 +{
  1149 + v3270 * terminal = GTK_V3270(widget);
  1150 +
  1151 + gtk_im_context_focus_in(terminal->input_method);
  1152 +
  1153 + return notify_focus(widget,event);
  1154 +}
  1155 +
  1156 +gboolean v3270_focus_out_event(GtkWidget *widget, GdkEventFocus *event)
  1157 +{
  1158 + v3270 * terminal = GTK_V3270(widget);
  1159 +
  1160 + gtk_im_context_focus_out(terminal->input_method);
  1161 +
  1162 + return notify_focus(widget,event);
  1163 +}
  1164 +
  1165 +static void v3270_activate(GtkWidget *widget)
  1166 +{
  1167 + v3270 * terminal = GTK_V3270(widget);
  1168 +
  1169 + trace("%s: %p",__FUNCTION__,terminal);
  1170 +
  1171 + if(lib3270_connected(terminal->host))
  1172 + lib3270_enter(terminal->host);
  1173 + else if(lib3270_get_host(terminal->host))
  1174 + v3270_connect(widget,NULL);
  1175 + else
  1176 + g_warning("Terminal widget %p activated without connection or valid hostname",terminal);
  1177 +}
  1178 +
  1179 +const GtkWidgetClass * v3270_get_parent_class(void)
  1180 +{
  1181 + return GTK_WIDGET_CLASS(v3270_parent_class);
  1182 +}
  1183 +
  1184 +static AtkObject * v3270_get_accessible(GtkWidget * widget)
  1185 +{
  1186 + v3270 * terminal = GTK_V3270(widget);
  1187 +
  1188 +// trace("%s acc=%p",__FUNCTION__,terminal->accessible);
  1189 +
  1190 + if(!terminal->accessible)
  1191 + {
  1192 + terminal->accessible = g_object_new(GTK_TYPE_V3270_ACCESSIBLE,NULL);
  1193 + atk_object_initialize(ATK_OBJECT(terminal->accessible), widget);
  1194 + gtk_accessible_set_widget(GTK_ACCESSIBLE(terminal->accessible),widget);
  1195 + g_object_ref(terminal->accessible);
  1196 + }
  1197 +
  1198 + return ATK_OBJECT(terminal->accessible);
  1199 +}
  1200 +
  1201 +GtkIMContext * v3270_get_im_context(GtkWidget *widget)
  1202 +{
  1203 + return GTK_V3270(widget)->input_method;
  1204 +}
  1205 +
  1206 +gboolean v3270_get_toggle(GtkWidget *widget, LIB3270_TOGGLE ix)
  1207 +{
  1208 + g_return_val_if_fail(GTK_IS_V3270(widget),FALSE);
  1209 +
  1210 + if(ix < LIB3270_TOGGLE_COUNT)
  1211 + return lib3270_get_toggle(GTK_V3270(widget)->host,ix) ? TRUE : FALSE;
  1212 +
  1213 + return FALSE;
  1214 +}
  1215 +
  1216 +void v3270_set_host(GtkWidget *widget, const gchar *uri)
  1217 +{
  1218 + g_return_if_fail(GTK_IS_V3270(widget));
  1219 + g_return_if_fail(uri != NULL);
  1220 + lib3270_set_host(GTK_V3270(widget)->host,uri);
  1221 +}
... ...