Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Dan Theisen
tn5250
Commits
06921364
Commit
06921364
authored
Dec 20, 1999
by
Jason 'Eraserhead' Felice
Browse files
Some API cleanup and rewrite of the save screen/restore screen code.
parent
08e8f9b6
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
464 additions
and
76 deletions
+464
-76
BUGS
BUGS
+9
-0
ChangeLog
ChangeLog
+9
-0
TODO
TODO
+7
-0
configure.in
configure.in
+1
-1
src/display.c
src/display.c
+4
-3
src/display.h
src/display.h
+5
-3
src/formattable.c
src/formattable.c
+30
-2
src/formattable.h
src/formattable.h
+7
-4
src/session.c
src/session.c
+51
-63
src/wtd.c
src/wtd.c
+262
-0
src/wtd.h
src/wtd.h
+79
-0
No files found.
BUGS
View file @
06921364
...
...
@@ -39,5 +39,14 @@
key handler under the 'default' clause, we get two decimal 410s. Why?
</bug>
<bug>
<date>
99.12.19.23.13.00
</date>
<owner
email=
"jasonf@nacs.net"
>
Jay 'Eraserhead' Felice
</owner>
Determining which line is the message line (and setting it) is horribly
broken. We should sort all this out. I don't think we're using the right
line in most cases.
</bug>
</bugs>
<!-- vi:set sts=2 sw=2 autoindent: -->
ChangeLog
View file @
06921364
1999-12-19 Jay 'Eraserhead' Felice <jasonf@nacs.net>
- CC1/CC2 bytes processed for Read MDT Fields and Read Input Fields commands
as they should be (previously only processed for Write to Display command).
- save/restore screen rewrite seems to work now - added wtd.c and wtd.h which
manage a ``WTD Context'' which can be used for generating commands and WTD
orders for creating a particular display and format table. This is designed
so that we can later do differentials (as in, for the 5250 server).
1999-12-17 Jay 'Eraserhead' Felice <jasonf@nacs.net>
- Partial work on save/restore screen rewrite finished.
...
...
TODO
View file @
06921364
...
...
@@ -51,5 +51,12 @@
handing the 400 a unique identifier.
</item>
<item>
We are currently ignoring some useful information in the format table
header (given to us with the SOH order). This includes the `Operator
Error Line' and a list of function keys which should be ignored (because
they aren't applicable for a particular screen).
</item>
</todo>
<!-- vi:set sts=2 sw=2 autoindent: -->
configure.in
View file @
06921364
...
...
@@ -2,7 +2,7 @@ dnl ** Process this file with autoconf to produce a configure script.
AC_INIT(src/tn5250.c)
dnl ** Automake Intialization
AM_INIT_AUTOMAKE(tn5250, 0.15.
3
)
AM_INIT_AUTOMAKE(tn5250, 0.15.
4
)
AM_CONFIG_HEADER(src/config.h)
dnl ** Checks for programs.
...
...
src/display.c
View file @
06921364
...
...
@@ -415,11 +415,13 @@ void tn5250_display_set_cursor_prev_field(Tn5250Display * This)
* to save our format table and display buffer. We assume the buffer
* has been initialized, and we append to it.
*/
void
tn5250_display_make_wtd_data
(
Tn5250Display
*
This
,
Tn5250Buffer
*
buf
)
void
tn5250_display_make_wtd_data
(
Tn5250Display
*
This
,
Tn5250Buffer
*
buf
,
Tn5250DBuffer
*
src_dbuffer
,
Tn5250Table
*
src_table
)
{
Tn5250WTDContext
*
ctx
;
if
((
ctx
=
tn5250_wtd_context_new
(
This
,
buf
))
==
NULL
)
if
((
ctx
=
tn5250_wtd_context_new
(
buf
,
src_dbuffer
,
src_table
,
This
->
display_buffers
,
This
->
format_tables
))
==
NULL
)
return
;
tn5250_wtd_context_convert
(
ctx
);
...
...
@@ -836,7 +838,6 @@ void tn5250_display_kf_dup(Tn5250Display * This)
int
y
,
x
,
i
;
Tn5250Field
*
field
;
unsigned
char
*
data
;
int
curfield
;
field
=
tn5250_display_current_field
(
This
);
if
(
field
==
NULL
||
tn5250_field_is_bypass
(
field
))
{
...
...
src/display.h
View file @
06921364
...
...
@@ -100,7 +100,9 @@ extern void tn5250_display_set_pending_insert (Tn5250Display *This,
int
y
,
int
x
);
extern
void
tn5250_display_make_wtd_data
(
Tn5250Display
*
This
,
struct
_Tn5250Buffer
*
b
);
struct
_Tn5250Buffer
*
b
,
struct
_Tn5250DBuffer
*
,
struct
_Tn5250Table
*
);
/* Key functions */
extern
void
tn5250_display_do_key
(
Tn5250Display
*
This
,
int
);
...
...
@@ -149,8 +151,8 @@ extern void tn5250_display_kf_delete (Tn5250Display *This);
(tn5250_dbuffer_roll((This)->display_buffers,(top),(bottom),(lines)))
#define tn5250_display_set_ic(This,y,x) \
(tn5250_dbuffer_set_ic((This)->display_buffers,(y),(x)))
#define tn5250_display_set_
message_line(This,y
) \
(tn5250_table_set_
message_line
((This)->format_tables,(
y
)))
#define tn5250_display_set_
header_data(This,data,len
) \
(tn5250_table_set_
header_data
((This)->format_tables,(
data),(len
)))
#define tn5250_display_clear_pending_insert(This) \
(void)((This)->pending_insert = 0)
#define tn5250_display_pending_insert(This) \
...
...
src/formattable.c
View file @
06921364
...
...
@@ -37,7 +37,8 @@ Tn5250Table *tn5250_table_new()
This
->
numfields
=
0
;
This
->
field_list
=
NULL
;
This
->
MasterMDT
=
0
;
This
->
message_line
=
25
;
This
->
header_data
=
NULL
;
This
->
header_length
=
0
;
This
->
next
=
This
->
prev
=
NULL
;
return
This
;
}
...
...
@@ -51,12 +52,35 @@ Tn5250Table *tn5250_table_copy(Tn5250Table *table)
memcpy
(
This
,
table
,
sizeof
(
Tn5250Table
));
This
->
next
=
This
->
prev
=
NULL
;
This
->
field_list
=
tn5250_field_list_copy
(
table
->
field_list
);
This
->
header_length
=
table
->
header_length
;
if
(
table
->
header_data
!=
NULL
)
{
This
->
header_data
=
(
unsigned
char
*
)
malloc
(
This
->
header_length
);
TN5250_ASSERT
(
This
->
header_data
!=
NULL
);
memcpy
(
This
->
header_data
,
table
->
header_data
,
table
->
header_length
);
}
else
This
->
header_data
=
NULL
;
return
This
;
}
void
tn5250_table_set_header_data
(
Tn5250Table
*
This
,
unsigned
char
*
data
,
int
len
)
{
This
->
header_length
=
len
;
if
(
This
->
header_data
!=
NULL
)
free
(
This
->
header_data
);
if
(
This
->
header_length
==
0
)
This
->
header_data
=
NULL
;
else
{
This
->
header_data
=
(
unsigned
char
*
)
malloc
(
This
->
header_length
);
TN5250_ASSERT
(
This
->
header_data
!=
NULL
);
memcpy
(
This
->
header_data
,
data
,
len
);
}
}
void
tn5250_table_destroy
(
Tn5250Table
*
This
)
{
(
void
)
tn5250_field_list_destroy
(
This
->
field_list
);
if
(
This
->
header_data
)
free
(
This
->
header_data
);
free
(
This
);
}
...
...
@@ -86,7 +110,11 @@ void tn5250_table_clear(Tn5250Table * This)
This
->
numfields
=
0
;
This
->
MasterMDT
=
0
;
This
->
message_line
=
24
;
This
->
header_length
=
0
;
if
(
This
->
header_data
)
{
free
(
This
->
header_data
);
This
->
header_data
=
NULL
;
}
TN5250_LOG
((
"FormatTable::Clear: entered.
\n
"
));
}
...
...
src/formattable.h
View file @
06921364
...
...
@@ -31,14 +31,19 @@ extern "C" {
Tn5250Field
/*@null@*/
*
field_list
;
int
numfields
;
int
MasterMDT
;
int
message_line
;
int
curfield
;
/* Header data (from SOH order) is saved here. We even save data that
* we don't understand here so we can insert that into our generated
* WTD orders for save/restore screen. */
unsigned
char
*
header_data
;
int
header_length
;
};
typedef
struct
_Tn5250Table
Tn5250Table
;
extern
Tn5250Table
*
tn5250_table_new
(
void
);
extern
Tn5250Table
*
tn5250_table_copy
(
Tn5250Table
*
table
);
extern
void
tn5250_table_set_header_data
(
Tn5250Table
*
This
,
unsigned
char
*
data
,
int
len
);
extern
void
tn5250_table_destroy
(
Tn5250Table
/*@only@*/
*
This
);
extern
void
tn5250_table_add_field
(
Tn5250Table
*
This
,
Tn5250Field
*
field
);
...
...
@@ -51,11 +56,9 @@ extern "C" {
#define tn5250_table_mdt(This) ((This)->MasterMDT)
#define tn5250_table_set_mdt(This) (void) ((This)->MasterMDT = 1)
#define tn5250_table_clear_mdt(This) (void) ((This)->MasterMDT = 0)
#define tn5250_table_set_message_line(This,row) (void) ((This)->message_line = (row))
#define tn5250_table_field_count(This) ((This)->numfields)
#define tn5250_table_mdt(This) ((This)->MasterMDT)
#define tn5250_table_message_line(This) ((This)->message_line)
#ifdef __cplusplus
}
...
...
src/session.c
View file @
06921364
...
...
@@ -54,7 +54,6 @@ static void tn5250_session_system_request(Tn5250Session * This);
static
void
tn5250_session_attention
(
Tn5250Session
*
This
);
static
void
tn5250_session_output_only
(
Tn5250Session
*
This
);
static
void
tn5250_session_save_screen
(
Tn5250Session
*
This
);
static
void
tn5250_session_restore_screen
(
Tn5250Session
*
This
);
static
void
tn5250_session_message_on
(
Tn5250Session
*
This
);
static
void
tn5250_session_message_off
(
Tn5250Session
*
This
);
static
void
tn5250_session_roll
(
Tn5250Session
*
This
);
...
...
@@ -69,6 +68,8 @@ static void tn5250_session_read_input_fields(Tn5250Session * This);
static
void
tn5250_session_read_mdt_fields
(
Tn5250Session
*
This
);
static
int
tn5250_session_valid_wtd_data_char
(
unsigned
char
c
);
static
int
tn5250_session_handle_aidkey
(
Tn5250Session
*
This
,
int
key
);
static
void
tn5250_session_handle_cc1
(
Tn5250Session
*
This
,
unsigned
char
cc1
);
static
void
tn5250_session_handle_cc2
(
Tn5250Session
*
This
,
unsigned
char
cc2
);
Tn5250Session
*
tn5250_session_new
()
{
...
...
@@ -435,7 +436,11 @@ static void tn5250_session_process_stream(Tn5250Session * This)
while
(
!
tn5250_record_is_chain_end
(
This
->
record
))
{
cur_command
=
tn5250_record_get_byte
(
This
->
record
);
TN5250_ASSERT
(
cur_command
==
ESC
);
if
(
cur_command
!=
ESC
)
{
TN5250_LOG
((
"cur_command != ESC; cur_pos = %d
\n
"
,
This
->
record
->
cur_pos
));
TN5250_ASSERT
(
0
);
}
cur_command
=
tn5250_record_get_byte
(
This
->
record
);
TN5250_LOG
((
"ProcessStream: cur_command = 0x%02X
\n
"
,
cur_command
));
...
...
@@ -470,9 +475,6 @@ static void tn5250_session_process_stream(Tn5250Session * This)
case
(
CMD_SAVE_SCREEN
):
tn5250_session_save_screen
(
This
);
break
;
case
(
CMD_RESTORE_SCREEN
):
tn5250_session_restore_screen
(
This
);
break
;
case
(
CMD_WRITE_ERROR_CODE
):
tn5250_session_write_error_code
(
This
);
break
;
...
...
@@ -685,6 +687,14 @@ static void tn5250_session_write_to_display(Tn5250Session * This)
tn5250_display_set_cursor
(
This
->
display
,
0
,
0
);
}
tn5250_session_handle_cc2
(
This
,
CC2
);
tn5250_display_update
(
This
->
display
);
}
static
void
tn5250_session_handle_cc2
(
Tn5250Session
*
This
,
unsigned
char
CC2
)
{
if
(
CC2
&
TN5250_SESSION_CTL_MESSAGE_ON
)
tn5250_display_indicator_set
(
This
->
display
,
TN5250_DISPLAY_IND_MESSAGE_WAITING
);
if
((
CC2
&
TN5250_SESSION_CTL_MESSAGE_OFF
)
&&
!
(
CC2
&
TN5250_SESSION_CTL_MESSAGE_ON
))
...
...
@@ -702,8 +712,6 @@ static void tn5250_session_write_to_display(Tn5250Session * This)
tn5250_display_beep
(
This
->
display
);
if
((
CC2
&
TN5250_SESSION_CTL_UNLOCK
)
!=
0
)
tn5250_display_indicator_clear
(
This
->
display
,
TN5250_DISPLAY_IND_X_SYSTEM
);
tn5250_display_update
(
This
->
display
);
}
static
void
tn5250_session_clear_unit
(
Tn5250Session
*
This
)
...
...
@@ -823,51 +831,22 @@ static void tn5250_session_save_screen(Tn5250Session * This)
TN5250_LOG
((
"SaveScreen: entered.
\n
"
));
tn5250_buffer_init
(
&
buffer
);
tn5250_display_make_wtd_data
(
This
->
display
,
&
buffer
,
NULL
,
NULL
);
/* Okay, now if we were in a Read MDT Fields or a Read Input Fields,
* we need to append a command which would put us back in the appropriate
* read. */
if
(
This
->
read_opcode
!=
0
)
{
tn5250_buffer_append_byte
(
&
buffer
,
ESC
);
tn5250_buffer_append_byte
(
&
buffer
,
This
->
read_opcode
);
tn5250_buffer_append_byte
(
&
buffer
,
0x00
);
/* FIXME: ? CC1 */
tn5250_buffer_append_byte
(
&
buffer
,
0x00
);
/* FIXME: ? CC2 */
}
/* Append dummy CC1/CC2 bytes for write_to_display later. */
tn5250_buffer_append_byte
(
&
buffer
,
0
);
tn5250_buffer_append_byte
(
&
buffer
,
0
);
tn5250_display_make_wtd_data
(
This
->
display
,
&
buffer
);
tn5250_stream_send_packet
(
This
->
stream
,
tn5250_buffer_length
(
&
buffer
),
TN5250_RECORD_FLOW_DISPLAY
,
TN5250_RECORD_H_NONE
,
TN5250_RECORD_OPCODE_SAVE_SCR
,
tn5250_buffer_data
(
&
buffer
));
tn5250_buffer_free
(
&
buffer
);
/* unsigned char outbuf[2 + sizeof(Tn5250DBuffer*) + sizeof(Tn5250Table*)];
int n;
outbuf[0] = 0x04;
outbuf[1] = 0x12;
*((Tn5250DBuffer**)&outbuf[2]) = tn5250_display_push_dbuffer(This->display);
*((Tn5250Table**)&outbuf[2+sizeof(Tn5250DBuffer*)]) =
tn5250_display_push_table(This->display);
tn5250_stream_send_packet(This->stream, sizeof(outbuf),
TN5250_RECORD_FLOW_DISPLAY, TN5250_RECORD_H_NONE,
TN5250_RECORD_OPCODE_SAVE_SCR, outbuf); */
}
static
void
tn5250_session_restore_screen
(
Tn5250Session
*
This
)
{
/*
int screen, format;
int i;
unsigned char rdata[sizeof (Tn5250DBuffer*) + sizeof (Tn5250Table*)];
TN5250_LOG(("RestoreScreen: entered.\n"));
for (i = 0; i < sizeof(rdata); i++)
rdata[i] = tn5250_record_get_byte(This->record);
TN5250_LOG(("RestoreScreen: screen = %d; format = %d\n", screen, format));
tn5250_display_restore_dbuffer (This->display, *((Tn5250DBuffer**)rdata));
tn5250_display_restore_table (This->display,
*((Tn5250Table**)(rdata + sizeof(Tn5250DBuffer*)))); */
tn5250_session_write_to_display
(
This
);
tn5250_display_update
(
This
->
display
);
}
static
void
tn5250_session_message_on
(
Tn5250Session
*
This
)
...
...
@@ -1022,28 +1001,30 @@ static void tn5250_session_start_of_field(Tn5250Session * This)
}
}
/*
* Clear the format table, get the table header data, and copy it to the
* table. This includes the operator error line (byte 4).
*/
static
void
tn5250_session_start_of_header
(
Tn5250Session
*
This
)
{
int
length
;
int
count
;
unsigned
char
temp
;
TN5250_LOG
((
"StartOfHeader: entered.
\n
"
));
int
i
,
n
;
unsigned
char
*
ptr
=
NULL
;
TN5250_LOG
((
"StartOfHeader: entered.
\n
"
));
tn5250_table_clear
(
tn5250_display_table
(
This
->
display
));
tn5250_display_indicator_set
(
This
->
display
,
TN5250_DISPLAY_IND_X_SYSTEM
);
length
=
tn5250_record_get_byte
(
This
->
record
);
TN5250_LOG
((
"StartOfHeader: length = %d
\n
StartOfHeader: data = "
,
length
));
for
(
count
=
0
;
count
<
length
;
count
++
)
{
temp
=
tn5250_record_get_byte
(
This
->
record
);
TN5250_LOG
((
"0x%02X "
,
temp
));
if
(
count
==
3
)
tn5250_display_set_message_line
(
This
->
display
,
temp
);
n
=
tn5250_record_get_byte
(
This
->
record
);
if
(
n
>
0
)
{
ptr
=
(
unsigned
char
*
)
malloc
(
n
);
TN5250_ASSERT
(
ptr
!=
NULL
);
}
TN5250_LOG
((
"
\n
"
));
tn5250_table_clear
(
tn5250_display_table
(
This
->
display
));
for
(
i
=
0
;
i
<
n
;
i
++
)
ptr
[
i
]
=
tn5250_record_get_byte
(
This
->
record
);
tn5250_display_set_header_data
(
This
->
display
,
ptr
,
n
);
if
(
ptr
!=
NULL
)
free
(
ptr
);
}
/*
...
...
@@ -1168,7 +1149,10 @@ static void tn5250_session_read_input_fields(Tn5250Session * This)
This
->
read_opcode
=
CMD_READ_INPUT_FIELDS
;
CC1
=
tn5250_record_get_byte
(
This
->
record
);
tn5250_session_handle_cc1
(
This
,
CC1
);
CC2
=
tn5250_record_get_byte
(
This
->
record
);
tn5250_session_handle_cc2
(
This
,
CC2
);
TN5250_LOG
((
"ReadInputFields: CC1 = 0x%02X; CC2 = 0x%02X
\n
"
,
CC1
,
CC2
));
tn5250_display_indicator_clear
(
This
->
display
,
...
...
@@ -1187,13 +1171,17 @@ static void tn5250_session_read_mdt_fields(Tn5250Session * This)
This
->
read_opcode
=
CMD_READ_MDT_FIELDS
;
CC1
=
tn5250_record_get_byte
(
This
->
record
);
tn5250_session_handle_cc1
(
This
,
CC1
);
CC2
=
tn5250_record_get_byte
(
This
->
record
);
tn5250_session_handle_cc2
(
This
,
CC2
);
TN5250_LOG
((
"ReadMDTFields: CC1 = 0x%02X; CC2 = 0x%02X
\n
"
,
CC1
,
CC2
));
tn5250_display_indicator_clear
(
This
->
display
,
TN5250_DISPLAY_IND_X_SYSTEM
|
TN5250_DISPLAY_IND_X_CLOCK
|
TN5250_DISPLAY_IND_INHIBIT
);
tn5250_display_update
(
This
->
display
);
}
...
...
src/wtd.c
0 → 100644
View file @
06921364
/* tn5250 -- an implentation of the 5250 telnet protocol.
* Copyright (C) 1997 Michael Madore
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include "utility.h"
#include "dbuffer.h"
#include "field.h"
#include "formattable.h"
#include "display.h"
#include "terminal.h"
#include "buffer.h"
#include "record.h"
#include "stream.h"
#include "session.h"
#include "codes5250.h"
#include "wtd.h"
static
void
tn5250_wtd_context_putc
(
Tn5250WTDContext
*
This
,
unsigned
char
c
);
static
void
tn5250_wtd_context_ra_putc
(
Tn5250WTDContext
*
This
,
unsigned
char
c
);
static
void
tn5250_wtd_context_ra_flush
(
Tn5250WTDContext
*
This
);
static
void
tn5250_wtd_context_write_field
(
Tn5250WTDContext
*
This
,
Tn5250Field
*
field
,
unsigned
char
attr
);
static
void
tn5250_wtd_context_convert_nosrc
(
Tn5250WTDContext
*
This
);
static
Tn5250Field
*
tn5250_wtd_context_peek_field
(
Tn5250WTDContext
*
This
);
/*
* Create a new instance of our WTD context object and initialize it.
*/
Tn5250WTDContext
*
tn5250_wtd_context_new
(
Tn5250Buffer
*
buffer
,
Tn5250DBuffer
*
sd
,
Tn5250Table
*
st
,
Tn5250DBuffer
*
dd
,
Tn5250Table
*
dt
)
{
Tn5250WTDContext
*
This
;
TN5250_ASSERT
(
dd
!=
NULL
);
TN5250_ASSERT
(
dt
!=
NULL
);
TN5250_ASSERT
(
buffer
!=
NULL
);
if
((
This
=
tn5250_new
(
Tn5250WTDContext
,
1
))
==
NULL
)
return
NULL
;
This
->
buffer
=
buffer
;
This
->
src_dbuffer
=
sd
;
This
->
src_table
=
st
;
This
->
dst_dbuffer
=
dd
;
This
->
dst_table
=
dt
;
This
->
ra_count
=
0
;
This
->
ra_char
=
0x00
;
This
->
clear_unit
=
0
;
return
This
;
}
/*
* Destroy a WTD context object.
*/
void
tn5250_wtd_context_destroy
(
Tn5250WTDContext
*
This
)
{
TN5250_ASSERT
(
This
!=
NULL
);
free
(
This
);
}
/*
* Convert the display info to WTD data.
*/
void
tn5250_wtd_context_convert
(
Tn5250WTDContext
*
This
)
{
/* The differential conversion is not yet implemented, and probably
* won't be until we implement the 5250 server. */
TN5250_ASSERT
(
This
->
src_dbuffer
==
NULL
&&
This
->
src_table
==
NULL
);
tn5250_wtd_context_convert_nosrc
(
This
);
}
/*
* This is our routine which is used when we don't know the prior state
* of the format table or display buffer.
*/
static
void
tn5250_wtd_context_convert_nosrc
(
Tn5250WTDContext
*
This
)
{
unsigned
char
c
;
Tn5250Field
*
field
;
int
fy
,
fx
;
TN5250_LOG
((
"wtd_context_convert entered.
\n
"
));
/* Since we don't know the unit's prior state, we clear the unit. */
tn5250_wtd_context_putc
(
This
,
ESC
);
if
(
tn5250_dbuffer_width
(
This
->
dst_dbuffer
)
!=
80
)
{
tn5250_wtd_context_putc
(
This
,
CMD_CLEAR_UNIT_ALTERNATE
);
tn5250_wtd_context_putc
(
This
,
0x00
);
}
else
tn5250_wtd_context_putc
(
This
,
CMD_CLEAR_UNIT
);
This
->
clear_unit
=
1
;
tn5250_wtd_context_putc
(
This
,
ESC
);
tn5250_wtd_context_putc
(
This
,
CMD_WRITE_TO_DISPLAY
);
/* FIXME: We will want to use different CC1/CC2 codes sometimes... */
tn5250_wtd_context_putc
(
This
,
0x00
);
/* CC1 */
tn5250_wtd_context_putc
(
This
,
0x00
);
/* CC2 */
/* If we have header data, start with a SOH order. */
if
(
This
->
dst_table
->
header_length
!=
0
)
{
int
i
;
tn5250_wtd_context_putc
(
This
,
SOH
);
tn5250_wtd_context_putc
(
This
,
This
->
dst_table
->
header_length
);
for
(
i
=
0
;
i
<
This
->
dst_table
->
header_length
;
i
++
)
tn5250_wtd_context_putc
(
This
,
This
->
dst_table
->
header_data
[
i
]);
}
/* FIXME: Set the insert-cursor address using IC if necessary. */
for
(
This
->
y
=
0
;
This
->
y
<
tn5250_dbuffer_height
(
This
->
dst_dbuffer
);
This
->
y
++
)
{
for
(
This
->
x
=
0
;
This
->
x
<
tn5250_dbuffer_width
(
This
->
dst_dbuffer
);
This
->
x
++
)
{
c
=
tn5250_dbuffer_char_at
(
This
->
dst_dbuffer
,
This
->
y
,
This
->
x
);
field
=
tn5250_wtd_context_peek_field
(
This
);
if
(
field
!=
NULL
)
{
/* Start of a field, write an SF order. We have to remove
* the last byte we put on the buffer (since its the attribute,
* which is taken care of here. */
tn5250_wtd_context_write_field
(
This
,
field
,
c
);
}
else
tn5250_wtd_context_ra_putc
(
This
,
c
);
}
}
TN5250_LOG_BUFFER
(
This
->
buffer
);
}
/*
* Return a pointer to the field that _starts_ at the next position on the
* display, or NULL if no field starts there.
*/
static
Tn5250Field
*
tn5250_wtd_context_peek_field
(
Tn5250WTDContext
*
This
)
{
int
nx
=
This
->
x
,
ny
=
This
->
y
;
Tn5250Field
*
field
;
if
(
++
nx
==
tn5250_dbuffer_width
(
This
->
dst_dbuffer
))
{
if
(
++
ny
==
tn5250_dbuffer_height
(
This
->
dst_dbuffer
))
return
NULL
;
}
field
=
tn5250_table_field_yx
(
This
->
dst_table
,
ny
,
nx
);
if
(
field
==
NULL
)
return
NULL
;
if
(
tn5250_field_start_row
(
field
)
!=
ny
||
tn5250_field_start_col
(
field
)
!=
nx
)
return
NULL
;
return
field
;
}
/*
* Put a character (which may be an attribute or a parameter for an order)
* directly into the buffer. Flush the RA buffer if necessary.
*/
static
void
tn5250_wtd_context_putc
(
Tn5250WTDContext
*
This
,
unsigned
char
c
)
{
tn5250_wtd_context_ra_flush
(
This
);
tn5250_buffer_append_byte
(
This
->
buffer
,
c
);
}
static
void
tn5250_wtd_context_ra_putc
(
Tn5250WTDContext
*
This
,
unsigned
char
c
)
{
if
(
This
->
ra_char
!=
c
)
tn5250_wtd_context_ra_flush
(
This
);
This
->
ra_char
=
c
;
This
->
ra_count
++
;
}
static
void
tn5250_wtd_context_ra_flush
(
Tn5250WTDContext
*
This
)
{
if
(
This
->
ra_count
==
0
)
return
;
/* Determine which is smaller, the RA/SBA order or just repeating the
* bytes. */
if
(
This
->
ra_count
<=
4
&&
!
(
This
->
ra_count
==
3
&&
This
->
ra_char
==
0x00
&&
This
->
clear_unit
))
{
/* Just repeating the bytes won. */
while
(
This
->
ra_count
>
0
)
{
tn5250_buffer_append_byte
(
This
->
buffer
,
This
->
ra_char
);
This
->
ra_count
--
;
}
}
else
{
/* We can just use an SBA if the character is a NUL and we've just
* cleared the unit. Yes, I'm being picky over saving one byte. */
if
(
This
->
clear_unit
&&
This
->
ra_char
==
0x00
)
{
tn5250_buffer_append_byte
(
This
->
buffer
,
SBA
);
tn5250_buffer_append_byte
(
This
->
buffer
,
This
->
y
+
1
);
tn5250_buffer_append_byte
(
This
->
buffer
,
This
->
x
+
1
);
}
else
{
int
px
=
This
->
x
,
py
=
This
->
y
;
if
(
px
==
0
)
{
px
=
tn5250_dbuffer_width
(
This
->
dst_dbuffer
)
-
1
;
TN5250_ASSERT
(
py
!=
0
);
py
--
;
}
else
px
--
;
tn5250_buffer_append_byte
(
This
->
buffer
,
RA
);
tn5250_buffer_append_byte
(
This
->
buffer
,
py
+
1
);
tn5250_buffer_append_byte
(
This
->
buffer
,
px
+
1
);
tn5250_buffer_append_byte
(
This
->
buffer
,
This
->
ra_char
);
}
}
This
->
ra_count
=
0
;
}
/*
* Write the SF order and the field's information.
*/
static
void
tn5250_wtd_context_write_field
(
Tn5250WTDContext
*
This
,
Tn5250Field
*
field
,
unsigned
char
attr
)
{
TN5250_LOG
((
"Writing SF order in stream data.
\n
"
));
tn5250_wtd_context_putc
(
This
,
SF
);