/* * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a * aplicativos mainframe. Registro no INPI sob o nome G3270. * * Copyright (C) <2008> * * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela * Free Software Foundation. * * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para * obter mais detalhes. * * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA, 02111-1307, USA * * Este programa está nomeado como draw.c e possui - linhas de código. * * Contatos: * * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) * */ #include #include #include #include #include "v3270.h" #include "private.h" /*--[ Implement ]------------------------------------------------------------------------------------*/ gboolean v3270_draw(GtkWidget * widget, cairo_t * cr) { v3270 * terminal = GTK_V3270(widget); cairo_set_source_surface(cr,terminal->surface,0,0); cairo_paint(cr); if(lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_CROSSHAIR) && (terminal->cursor.show&2)) { GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_CROSS_HAIR); cairo_rectangle(cr, 0,terminal->cursor.rect.y+terminal->metrics.height,allocation.width,1); cairo_fill(cr); cairo_rectangle(cr, terminal->cursor.rect.x,0,1,terminal->oia_rect->y-3); cairo_fill(cr); } if(terminal->cursor.show == 3) { cairo_set_source_surface(cr,terminal->cursor.surface,terminal->cursor.rect.x,terminal->cursor.rect.y); if(lib3270_get_toggle(terminal->host,LIB3270_TOGGLE_INSERT)) { cairo_rectangle(cr, terminal->cursor.rect.x, terminal->cursor.rect.y, terminal->cursor.rect.width, terminal->cursor.rect.height ); } else { cairo_rectangle(cr, terminal->cursor.rect.x, terminal->cursor.rect.y+terminal->metrics.height, terminal->cursor.rect.width, terminal->metrics.descent ); } cairo_fill(cr); } return FALSE; } #if( !GTK_CHECK_VERSION(3,0,0)) gboolean v3270_expose(GtkWidget *widget, GdkEventExpose *event) { cairo_t *cr = gdk_cairo_create(widget->window); v3270_draw(widget,cr); cairo_destroy(cr); return FALSE; } #endif // GTk3 static void get_element_colors(unsigned short attr, GdkColor **fg, GdkColor **bg, GdkColor *color) { if(attr & LIB3270_ATTR_SELECTED) { *fg = color+V3270_COLOR_SELECTED_FG; *bg = color+V3270_COLOR_SELECTED_BG; } else { *bg = color+((attr & 0x00F0) >> 4); if(attr & LIB3270_ATTR_FIELD) *fg = color+(attr & 0x0003)+V3270_COLOR_FIELD; else *fg = color+(attr & 0x000F); } } void v3270_draw_element(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *color) { GdkColor *fg; GdkColor *bg; get_element_colors(attr,&fg,&bg,color); v3270_draw_char(cr,chr,attr,session,height,rect,fg,bg); } void v3270_draw_char(cairo_t *cr, unsigned char chr, unsigned short attr, H3270 *session, guint height, GdkRectangle *rect, GdkColor *fg, GdkColor *bg) { // Clear element area gdk_cairo_set_source_color(cr,bg); cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height); cairo_fill(cr); // Set foreground color gdk_cairo_set_source_color(cr,fg); // Draw char if(attr & LIB3270_ATTR_CG) { switch(chr) { case 0xd3: // CG 0xab, plus cairo_move_to(cr,rect->x+(rect->width/2),rect->y); cairo_rel_line_to(cr,0,rect->height); cairo_move_to(cr,rect->x,rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width,0); break; case 0xa2: // CG 0x92, horizontal line cairo_move_to(cr,rect->x,rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width,0); break; case 0x85: // CG 0x184, vertical line cairo_move_to(cr,rect->x+(rect->width/2),rect->y); cairo_rel_line_to(cr,0,rect->height); break; case 0xd4: // CG 0xac, LR corner cairo_move_to(cr,rect->x, rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width/2,0); cairo_rel_line_to(cr,0,-(rect->height/2)); break; case 0xd5: // CG 0xad, UR corner cairo_move_to(cr,rect->x, rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width/2,0); cairo_rel_line_to(cr,0,rect->height/2); break; case 0xc5: // CG 0xa4, UL corner cairo_move_to(cr,rect->x+rect->width,rect->y+(rect->height/2)); cairo_rel_line_to(cr,-(rect->width/2),0); cairo_rel_line_to(cr,0,(rect->height/2)); break; case 0xc4: // CG 0xa3, LL corner cairo_move_to(cr,rect->x+rect->width,rect->y+(rect->height/2)); cairo_rel_line_to(cr,-(rect->width/2),0); cairo_rel_line_to(cr,0,-(rect->height/2)); break; case 0xc6: // CG 0xa5, left tee cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width/2,0); cairo_move_to(cr,rect->x+(rect->width/2),rect->y); cairo_rel_line_to(cr,0,rect->height); break; case 0xd6: // CG 0xae, right tee cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2)); cairo_rel_line_to(cr,-(rect->width/2),0); cairo_move_to(cr,rect->x+(rect->width/2),rect->y); cairo_rel_line_to(cr,0,rect->height); break; case 0xc7: // CG 0xa6, bottom tee cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2)); cairo_rel_line_to(cr,0,-(rect->height/2)); cairo_move_to(cr,rect->x,rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width,0); break; case 0xd7: // CG 0xaf, top tee cairo_move_to(cr,rect->x+(rect->width/2),rect->y+(rect->height/2)); cairo_rel_line_to(cr,0,rect->height/2); cairo_move_to(cr,rect->x,rect->y+(rect->height/2)); cairo_rel_line_to(cr,rect->width,0); break; case 0x8c: // CG 0xf7, less or equal "≤" cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, "≤"); break; case 0xae: // CG 0xd9, greater or equal "≥" cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, "≥"); break; case 0xbe: // CG 0x3e, not equal "≠" cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, "≠"); break; case 0xad: // "[" cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, "["); break; case 0xbd: // "]" cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, "]"); break; default: cairo_rectangle(cr, rect->x+1, rect->y+1, rect->width-2, rect->height-2); } } else if(chr) { gchar *utf = g_convert((char *) &chr, 1, "UTF-8", lib3270_get_charset(session), NULL, NULL, NULL); if(utf) { cairo_move_to(cr,rect->x,rect->y+height); cairo_show_text(cr, utf); g_free(utf); } } cairo_stroke(cr); } void v3270_reload(GtkWidget *widget) { v3270 * terminal = GTK_V3270(widget); #if GTK_CHECK_VERSION(3,0,0) gint width = gtk_widget_get_allocated_width(widget); gint height = gtk_widget_get_allocated_height(widget); #else gint width = terminal->width; gint height = terminal->height; #endif GdkRectangle rect; int addr, cursor, r, rows, cols; cairo_t * cr; if(!gtk_widget_get_realized(widget)) return; // Create new terminal image if(terminal->surface) cairo_surface_destroy(terminal->surface); terminal->surface = (cairo_surface_t *) gdk_window_create_similar_surface(gtk_widget_get_window(widget),CAIRO_CONTENT_COLOR,width,height); // Update the created image cr = cairo_create(terminal->surface); v3270_update_font_metrics(terminal, cr, width, height); gdk_cairo_set_source_color(cr,terminal->color+V3270_COLOR_BACKGROUND); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); cairo_stroke(cr); // Draw terminal contents lib3270_get_screen_size(terminal->host,&rows,&cols); memset(&rect,0,sizeof(rect)); rect.y = terminal->metrics.top; rect.width = terminal->metrics.width; rect.height = terminal->metrics.spacing; addr = 0; cursor = lib3270_get_cursor_address(terminal->host); for(r = 0; r < rows; r++) { int c; rect.x = terminal->metrics.left; for(c=0;c < cols;c++) { unsigned char chr = 0; unsigned short attr; lib3270_get_contents(terminal->host,addr,addr,&chr,&attr); if(addr == cursor) v3270_update_cursor_rect(terminal,&rect,chr,attr); v3270_draw_element(cr,chr,attr,terminal->host,terminal->metrics.height,&rect,terminal->color); addr++; rect.x += rect.width; } rect.y += terminal->metrics.spacing; } v3270_draw_oia(cr, terminal->host, rect.y, cols, &terminal->metrics, terminal->color,terminal->oia_rect); cairo_destroy(cr); } void v3270_update_char(H3270 *session, int addr, unsigned char chr, unsigned short attr, unsigned char cursor) { v3270 * terminal = GTK_V3270(session->widget); cairo_t * cr; GdkRectangle rect; int rows,cols; if(!gtk_widget_get_realized(GTK_WIDGET(terminal))) return; if(!terminal->surface) { v3270_reload(GTK_WIDGET(terminal)); gtk_widget_queue_draw(GTK_WIDGET(terminal)); return; } lib3270_get_screen_size(terminal->host,&rows,&cols); memset(&rect,0,sizeof(rect)); rect.x = terminal->metrics.left + ((addr % cols) * terminal->metrics.width); rect.y = terminal->metrics.top + ((addr / cols) * terminal->metrics.spacing); rect.width = terminal->metrics.width; rect.height = terminal->metrics.spacing; // 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); cr = cairo_create(terminal->surface); cairo_set_scaled_font(cr,terminal->font_scaled); v3270_draw_element(cr, chr, attr, terminal->host, terminal->metrics.height, &rect,terminal->color); cairo_destroy(cr); if(cursor) v3270_update_cursor_rect(terminal,&rect,chr,attr); gtk_widget_queue_draw_area(GTK_WIDGET(terminal),rect.x,rect.y,rect.width,rect.height); } void v3270_update_cursor_surface(v3270 *widget,unsigned char chr,unsigned short attr) { if(widget->cursor.surface) { GdkRectangle rect = widget->cursor.rect; cairo_t * cr = cairo_create(widget->cursor.surface); GdkColor * fg; GdkColor * bg; get_element_colors(attr,&fg,&bg,widget->color); cairo_set_scaled_font(cr,widget->font_scaled); rect.x = 0; rect.y = 0; v3270_draw_char(cr,chr,attr,widget->host,widget->metrics.height,&rect,bg,fg); cairo_destroy(cr); } } void v3270_update_cursor_rect(v3270 *widget, GdkRectangle *rect, unsigned char chr, unsigned short attr) { widget->cursor.chr = chr; widget->cursor.rect = *rect; widget->cursor.attr = attr; widget->cursor.rect.height = widget->metrics.height + widget->metrics.descent; v3270_update_cursor_surface(widget,chr,attr); }