Index: session.c =================================================================== RCS file: /cvsroot/tn5250/tn5250/src/session.c,v retrieving revision 1.38.2.11 diff -u -r1.38.2.11 session.c --- session.c 25 Aug 2003 23:04:17 -0000 1.38.2.11 +++ session.c 15 Jun 2004 22:31:59 -0000 @@ -60,6 +60,8 @@ static void tn5250_session_handle_cc1 (Tn5250Session *This, unsigned char cc1); static void tn5250_session_handle_cc2 (Tn5250Session *This, unsigned char cc2); static void tn5250_session_query_reply (Tn5250Session *This); +static void tn5250_session_create_window_structured_field(Tn5250Session *This, + int length); /****f* lib5250/tn5250_session_new * NAME @@ -1439,15 +1441,37 @@ This order is not really implemented. We just do enough to checking so we can handle data stream errors. */ + unsigned char class; unsigned char type; unsigned long errorcode; + int len; + + /* first two bytes are the length of the WDSF parameter (the length bytes + are included in the count) */ + + len = (tn5250_record_get_byte (This->record) << 8) | + tn5250_record_get_byte (This->record); + + /* 3rd byte is the class... 0xd9, I think, always */ + + class = tn5250_record_get_byte (This->record); + + if (class != 0xd9) + { + errorcode = TN5250_NR_INVALID_SF_CLASS_TYPE; + tn5250_session_send_error (This, errorcode); + return; + } + + /* 4th byte is the type of structured field */ type = tn5250_record_get_byte(This->record); + len-=4; + switch(type) { case DEFINE_SELECTION_FIELD: - case CREATE_WINDOW: case UNREST_WIN_CURS_MOVE: case DEFINE_SCROLL_BAR_FIELD: case WRITE_DATA: @@ -1458,8 +1482,20 @@ case REM_ALL_GUI_CONSTRUCTS: case DRAW_ERASE_GRID_LINES: case CLEAR_GRID_LINE_BUFFER: + TN5250_LOG(("Unhandled WDSF class=%02x type=%02d data=", class, type)); + while (len > 0) + { + TN5250_LOG(("%02x", tn5250_record_get_byte (This->record))); + len --; + } + TN5250_LOG(("\n")); + break; + case CREATE_WINDOW: + tn5250_session_create_window_structured_field (This, len); break; default: + TN5250_LOG(("tn5250_write_display_structured_field: Invalid SF Class: %02x\n", + type)); errorcode = TN5250_NR_INVALID_SF_CLASS_TYPE; tn5250_session_send_error(This, errorcode); return; @@ -1700,6 +1736,8 @@ if(temp[2] != 0xD9) { + TN5250_LOG(("tn5250_write_structured_field: Invalid SF Class: %02x\n", + temp[2])); errorcode = TN5250_NR_INVALID_SF_CLASS_TYPE; tn5250_session_send_error(This, errorcode); return; @@ -1726,6 +1764,8 @@ break; default: + TN5250_LOG(("tn5250_write_structured_field(2): Invalid SF Class: %02x\n", + temp[3])); errorcode = TN5250_NR_INVALID_SF_CLASS_TYPE; tn5250_session_send_error(This, errorcode); return; @@ -1824,19 +1864,40 @@ *****/ static void tn5250_session_query_reply(Tn5250Session * This) { - unsigned char temp[61]; + unsigned char temp[67]; const char *scan; - int dev_type, dev_model, i; + int dev_type, dev_model, i, enhanced; TN5250_LOG(("Sending QueryReply.\n")); + /* FIXME: We should really be asking the terminal object if + * it supports the enhanced 5250 capbilities, and *it* + * should be checking to see if the user wants them. + * This way, the more advanced terminals (WinTerm, GTKTerm) + * additional capabilities. + */ + + enhanced = tn5250_config_get_bool (This->config, "enhanced"); + if (enhanced) + { + TN5250_LOG(("turning on broken features\n")); + } + temp[0] = 0x00; /* Cursor Row/Column (set to zero) */ temp[1] = 0x00; temp[2] = 0x88; /* Inbound Write Structured Field Aid */ temp[3] = 0x00; /* Length of Query Reply */ - temp[4] = 0x3A; + + if (enhanced) + { + temp[4] = 0x40; + } + else + { + temp[4] = 0x3A; + } temp[5] = 0xD9; /* Command class */ @@ -1845,7 +1906,7 @@ temp[7] = 0x80; /* Flag byte */ temp[8] = 0x06; /* Controller hardware class */ - temp[9] = 0x00; + temp[9] = 0x00; /* 0x600 - Other WSF or another 5250 emulator */ temp[10] = 0x01; /* Controller code level (Version 1 Release 1.0 */ temp[11] = 0x01; @@ -1915,9 +1976,62 @@ temp[50] = 0x31; temp[51] = 0x00; /* Reserved */ temp[52] = 0x00; - temp[53] = 0x00; - temp[54] = 0x00; /* Reserved (set to zero) */ + /* byte 53: + * bits 0-2: B'000' = no graphics + * B'001' = 5292-style graphics + * B'010' = GDDM-OS/2 Link Graphics + * bit 3: extended 3270 data stream capability + * bit 4: pointer device (mouse) available + * bit 5: GUI-like characters available + * bit 6: Enhanced 5250 FCW & WDSFs + * bit 7: WRITE ERROR CODE TO WINDOW command support + * + * byte 54: + * bit 0: enhanced user interface support level 2 + * bit 1: GUI device w/all-points addressable windows, etc + * bit 2: WordPerfect support is available + * bit 3: Dynamic status & scale line + * bit 4: enhanced user interface support level 3 + * bit 5: cursor draw is supported in Office editor + * bits 6-7: video delivery capability B'00' = none, B'01'=5250 + * + * Enabling enhanced 5250 means we need to support: + * WDSFs: CREATE WINDOW + * UNRESTRICTED CURSOR MOVEMENT + * DEFINE SELECTION FIELD + * DEFINE SCROLL BAR FIELD + * REMOVE ALL GUI CONSTRUCTS + * REMOVE GUI WINDOW + * REMOVE GUI SELECTION FIELD + * REMOVE GUI SCROLL BAR FIELD + * READ SCREEN TO PRINT + * READ SCREEN TO PRINT WITH EXTENDED ATTRIBUTES + * WRITE ERROR CODE TO WINDOW + * SAVE PARTIAL SCREEN + * RESTORE PARTIAL SCREEN + * + * FCWs: Continued Fields + * Cursor Progression + * Highlighted + * Mouse Selection + * + * Enabling enhanced 5250 Level 2 means we also need to support: + * WDSFs: WRITE DATA + * PROGRAMMABLE MOUSE BUTTONS + * FCWs: Word Wrap + * Ideographic Continued Entry Fields + */ + if (enhanced) + { + temp[53] = 0x02; + temp[54] = 0x80; + } + else + { + temp[53] = 0x00; + temp[54] = 0x00; + } temp[55] = 0x00; temp[56] = 0x00; @@ -1925,10 +2039,184 @@ temp[58] = 0x00; temp[59] = 0x00; temp[60] = 0x00; + temp[61] = 0x00; + temp[62] = 0x00; + temp[63] = 0x00; + temp[64] = 0x00; + temp[65] = 0x00; + temp[66] = 0x00; + + tn5250_stream_send_packet(This->stream, temp[4] + 3, + TN5250_RECORD_FLOW_DISPLAY, + TN5250_RECORD_H_NONE, + TN5250_RECORD_OPCODE_NO_OP, + (unsigned char *) temp); +} + +/****i* lib5250/tn5250_session_create_window_structured_field + * NAME + * tn5250_session_create_window_structured_field + * SYNOPSIS + * tn5250_session_create_window_structured_field (This, len) + * INPUTS + * Tn5250Session * This - + * int length - + * DESCRIPTION + * DOCUMENT ME!!! + *****/ +static void tn5250_session_create_window_structured_field(Tn5250Session * This, + int length) +{ + int i; + unsigned char flagbyte1; + unsigned char depth; + unsigned char width; + unsigned char reserved; + unsigned char border_length, border_type, border_flags, border_mono; + unsigned char border_color, border_upperlchar, border_topchar; + unsigned char border_upperrchar, border_leftchar, border_rightchar; + unsigned char border_lowerlchar, border_bottomchar, border_lowerrchar; + + TN5250_LOG(("Entering tn5250_session_create_window_structured_field()\n")); + - tn5250_stream_send_packet(This->stream, 61, TN5250_RECORD_FLOW_DISPLAY, - TN5250_RECORD_H_NONE, TN5250_RECORD_OPCODE_NO_OP, - (unsigned char *) temp); + flagbyte1 = tn5250_record_get_byte (This->record); + + if (flagbyte1 & 0x80) + { + TN5250_LOG(("Cursor restricted to window\n")); + } + + if (flagbyte1 & 0x40) + { + TN5250_LOG(("Pull down window not supported\n")); + return; + } + + reserved = tn5250_record_get_byte (This->record); + reserved = tn5250_record_get_byte (This->record); + depth = tn5250_record_get_byte (This->record); + TN5250_LOG(("depth = 0x%02X (%d)\n", depth, (int) depth)); + width = tn5250_record_get_byte(This->record); + TN5250_LOG(("width = 0x%02X (%d)\n", width, (int) width)); + + if ((length - 5) > 0) + { + length = length - 5; + border_length = tn5250_record_get_byte (This->record); + TN5250_LOG(("border_length = 0x%02X (%d)\n", border_length, + (int) border_length)); + border_length = ((int) border_length) - 1; + length--; + if ((int) border_length > 0) + { + border_type = tn5250_record_get_byte (This->record); + TN5250_LOG(("Border type = 0x%02X\n", border_length)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_flags = tn5250_record_get_byte (This->record); + if (border_flags & 0x80) + { + TN5250_LOG(("Use border presentation characters (GUI-like NWS)\n")); + } + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_mono = tn5250_record_get_byte (This->record); + TN5250_LOG(("Monochrome border attribute = 0x%02X\n", border_mono)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_color = tn5250_record_get_byte (This->record); + TN5250_LOG(("Color border attribute = 0x%02X\n", border_color)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_upperlchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Upper left border character = 0x%02X\n", + border_upperlchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_topchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Top border character = 0x%02X\n", + border_topchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_upperrchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Upper right border character = 0x%02X\n", + border_upperrchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_leftchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Left border character = 0x%02X\n", + border_leftchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_rightchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Right border character = 0x%02X\n", + border_rightchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_lowerlchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Lower left border character = 0x%02X\n", + border_lowerlchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_bottomchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Bottom border character = 0x%02X\n", + border_bottomchar)); + ((int) border_length)--; + length--; + } + if ((int) border_length > 0) + { + border_lowerrchar = tn5250_record_get_byte (This->record); + TN5250_LOG(("Lower right border character = 0x%02X\n", + border_lowerrchar)); + ((int) border_length)--; + length--; + } + } + + while (length > 0) + { + reserved = tn5250_record_get_byte (This->record); + length--; + } + This->display->terminal->window_width = (int) width; + This->display->terminal->window_height = (int) depth; + fprintf (stderr, "depth = 0x%02X (%d (%d))\n", + depth, (int) depth, This->display->terminal->window_height); + fprintf (stderr, "width = 0x%02X (%d (%d))\n", + width, (int) width, This->display->terminal->window_width); + return; } /* vi:set sts=3 sw=3: */ Index: terminal.h =================================================================== RCS file: /cvsroot/tn5250/tn5250/src/terminal.h,v retrieving revision 1.9.2.7 diff -u -r1.9.2.7 terminal.h --- terminal.h 23 Apr 2003 16:03:06 -0000 1.9.2.7 +++ terminal.h 15 Jun 2004 22:32:00 -0000 @@ -163,6 +163,8 @@ void (* beep) (struct _Tn5250Terminal * This); int (*config) (struct _Tn5250Terminal * This, struct _Tn5250Config *config); + int window_width; + int window_height; }; typedef struct _Tn5250Terminal Tn5250Terminal;