int sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count) { int spaces, i_msg; int rc; /* * parse msg for escape sequences (\t,\v ...) and put formated * msg into an mto (created by sclp_initialize_mto). * * We have to do this work ourselfs because there is no support for * these characters on the native machine and only partial support * under VM (Why does VM interpret \n but the native machine doesn't ?) * * Depending on i/o-control setting the message is always written * immediately or we wait for a final new line maybe coming with the * next message. Besides we avoid a buffer overrun by writing its * content. * * RESTRICTIONS: * * \r and \b work within one line because we are not able to modify * previous output that have already been accepted by the SCLP. * * \t combined with following \r is not correctly represented because * \t is expanded to some spaces but \r does not know about a * previous \t and decreases the current position by one column. * This is in order to a slim and quick implementation. */ for (i_msg = 0; i_msg < count; i_msg++) { switch (msg[i_msg]) { case '\n': /* new line, line feed (ASCII) */ /* check if new mto needs to be created */ if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, 0); if (rc) return i_msg; } sclp_finalize_mto(buffer); break; case '\a': /* bell, one for several times */ /* set SCLP sound alarm bit in General Object */ buffer->sccb->msg_buf.mdb.go.general_msg_flags |= GNRLMSGFLGS_SNDALRM; break; case '\t': /* horizontal tabulator */ /* check if new mto needs to be created */ if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; } /* "go to (next htab-boundary + 1, same line)" */ do { if (buffer->current_length >= buffer->columns) break; /* ok, add a blank */ *buffer->current_line++ = 0x40; buffer->current_length++; } while (buffer->current_length % buffer->htab); break; case '\f': /* form feed */ case '\v': /* vertical tabulator */ /* "go to (actual column, actual line + 1)" */ /* = new line, leading spaces */ if (buffer->current_line != NULL) { spaces = buffer->current_length; sclp_finalize_mto(buffer); rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; memset(buffer->current_line, 0x40, spaces); buffer->current_line += spaces; buffer->current_length = spaces; } else { /* one an empty line this is the same as \n */ rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; sclp_finalize_mto(buffer); } break; case '\b': /* backspace */ /* "go to (actual column - 1, actual line)" */ /* decrement counter indicating position, */ /* do not remove last character */ if (buffer->current_line != NULL && buffer->current_length > 0) { buffer->current_length--; buffer->current_line--; } break; case 0x00: /* end of string */ /* transfer current line to SCCB */ if (buffer->current_line != NULL) sclp_finalize_mto(buffer); /* skip the rest of the message including the 0 byte */ i_msg = count - 1; break; default: /* no escape character */ /* do not output unprintable characters */ if (!isprint(msg[i_msg])) break; /* check if new mto needs to be created */ if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; } *buffer->current_line++ = sclp_ascebc(msg[i_msg]); buffer->current_length++; break; } /* check if current mto is full */ if (buffer->current_line != NULL && buffer->current_length >= buffer->columns) sclp_finalize_mto(buffer); } /* return number of processed characters */ return i_msg; }
/* * processing of a message including escape characters, * returns number of characters written to the output sccb * ("processed" means that is not guaranteed that the character have already * been sent to the SCLP but that it will be done at least next time the SCLP * is not busy) */ int sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count) { int spaces, i_msg; int rc; /* * parse msg for escape sequences (\t,\v ...) and put formated * msg into an mto (created by sclp_initialize_mto). * * We have to do this work ourselfs because there is no support for * these characters on the native machine and only partial support * under VM (Why does VM interpret \n but the native machine doesn't ?) * * Depending on i/o-control setting the message is always written * immediately or we wait for a final new line maybe coming with the * next message. Besides we avoid a buffer overrun by writing its * content. * * RESTRICTIONS: * * \r and \b work within one line because we are not able to modify * previous output that have already been accepted by the SCLP. * * \t combined with following \r is not correctly represented because * \t is expanded to some spaces but \r does not know about a * previous \t and decreases the current position by one column. * This is in order to a slim and quick implementation. */ for (i_msg = 0; i_msg < count; i_msg++) { switch (msg[i_msg]) { case '\n': if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, 0); if (rc) return i_msg; } sclp_finalize_mto(buffer); break; case '\a': buffer->sccb->msg_buf.mdb.go.general_msg_flags |= GNRLMSGFLGS_SNDALRM; break; case '\t': if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; } do { if (buffer->current_length >= buffer->columns) break; *buffer->current_line++ = 0x40; buffer->current_length++; } while (buffer->current_length % buffer->htab); break; case '\f': case '\v': if (buffer->current_line != NULL) { spaces = buffer->current_length; sclp_finalize_mto(buffer); rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; memset(buffer->current_line, 0x40, spaces); buffer->current_line += spaces; buffer->current_length = spaces; } else { rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; sclp_finalize_mto(buffer); } break; case '\b': if (buffer->current_line != NULL && buffer->current_length > 0) { buffer->current_length--; buffer->current_line--; } break; case 0x00: if (buffer->current_line != NULL) sclp_finalize_mto(buffer); i_msg = count - 1; break; default: if (!isprint(msg[i_msg])) break; if (buffer->current_line == NULL) { rc = sclp_initialize_mto(buffer, buffer->columns); if (rc) return i_msg; } *buffer->current_line++ = sclp_ascebc(msg[i_msg]); buffer->current_length++; break; } if (buffer->current_line != NULL && buffer->current_length >= buffer->columns) sclp_finalize_mto(buffer); } return i_msg; }