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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 | +} | ... | ... |