Commit b4195d4101a3ebc1bd27bd1b36220f386bbf0672
0 parents
Exists in
master
and in
1 other branch
Renomeando diretorio de fontes da aplicacao para facilitar empacotamento
Showing
15 changed files
with
5384 additions
and
0 deletions
Show diff stats
1 | +++ a/accessible.c | ||
@@ -0,0 +1,865 @@ | @@ -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 | + |
1 | +++ a/accessible.h | ||
@@ -0,0 +1,73 @@ | @@ -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 |
1 | +++ a/draw.c | ||
@@ -0,0 +1,397 @@ | @@ -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 | + |
1 | +++ a/genmarshal | ||
@@ -0,0 +1,11 @@ | @@ -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 |
1 | +++ a/iocallback.c | ||
@@ -0,0 +1,349 @@ | @@ -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 | +} |
1 | +++ a/keyboard.c | ||
@@ -0,0 +1,241 @@ | @@ -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 | + |
1 | +++ a/locked.xbm | ||
@@ -0,0 +1,14 @@ | @@ -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 }; |
1 | +++ a/mouse.c | ||
@@ -0,0 +1,263 @@ | @@ -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 | +} |
1 | +++ a/oia.c | ||
@@ -0,0 +1,1032 @@ | @@ -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 | +} |
1 | +++ a/private.h | ||
@@ -0,0 +1,236 @@ | @@ -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 |
1 | +++ a/selection.c | ||
@@ -0,0 +1,476 @@ | @@ -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 | + |
1 | +++ a/unlocked.xbm | ||
@@ -0,0 +1,14 @@ | @@ -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 }; |
1 | +++ a/v3270.h | ||
@@ -0,0 +1,190 @@ | @@ -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 |
1 | +++ a/widget.c | ||
@@ -0,0 +1,1221 @@ | @@ -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 | +} |