NAME
Language::Zcode::Runtime::IO - IO for Perl runtimes created by L::Z translations
DESCRIPTION
This package contains a number of different packages that support the IO features needed for a running Z-machine. This includes windows, input and output streams, cursors, lines, and fonts. See the Z-machine Spec for descriptions of what all these things means.
This package supports more than one "terminal", i.e., Perl toolkit for handling the I/O into and out of the Z-machine. OK, right now, it only supports 2: dumb, which is just regular print statements; and win32, which involves Win32::Console tools. But in theory, it won't be hard to add support for Tk, Curses, and others. Why? Because I stole nearly all the code in these packages from Games::Rezrov, which already does support multiple terminal types.
This package implements many of the Z-machine I/O opcodes, things like print, output_stream, and read. It also handles the header, which mostly deals with I/O.
This package is currently the most hacked of all the packages in the Language::Zcode distribution. I hope it gets cleaner eventually.
# So [ADK] split to a SECOND window. This split will be internal to
# the Z-machine emulator: the Z-machine isn't able to split to more
# than one window (in v5), but presumably any I/O that can split once
# can split more than once. Put status in that window.
#
# Tk already does that. Just use manual_status_line for
# everything.
# ascii use constant LINEFEED => 10;
# Stolen from Games::Rezrov. I don't know what rezrov did with $zi arg. # read a single character # 10.7: only return characters defined in input stream # 3.8: character "10" (linefeed) only defined for output. sub read_char { my ($useless, $time, $routine) = @_; #my ($argv, $zi) = @_; PlotzPerl::Output::reset_write_count(); PlotzPerl::Output::flush(); die("read_char: 1st arg must be 1") unless $useless == 1; my $result = screen_zio()->get_input(1, 1, "-time" => $time, "-routine" => $routine, #"-zi" => $zi ); # remap keyboard "linefeed" to what the Z-machine will recognize as a # "carriage return". Required for startup form in "Bureaucracy" # XXX - does keyboard ever return 13 (non-IBM-clones)? # XXX can we just do s/\n/chr(Z_NEWLINE)/e? my $code = ord(substr($result,0,1)); $code = Games::Rezrov::ZConst::Z_NEWLINE if ($code == LINEFEED); return $code; }
This package handles (some) output from the game.
That output may go to various streams, one of which is the screen (which includes windows et al.)
if (($char >= 179 and $char <= 218) or
($char >= 0x18 and $char <= 0x1b)) {
# sect16.html; convert IBM PC graphics codes
$trans = $Z_TRANSLATIONS{$char} || "*";
# print STDERR "trans for $char => $trans\n";
}
wrote_something should only be set when doing stream 1? Also stream 2
will always be fixed font. In fact we will need to store x position
for stream 2 (but not y because we dont have to worry about scrolling)
PlotzPerl::OutputStream
This class handles a single output stream, like the screen or a transcript file.
PlotzPerl::OutputStream::File
This abstract class handles output streams that write to files.
PlotzPerl::OutputStream::Buffered
This abstract class handles output streams that write buffered (word-wrapped) output. We handle this by buffering output instead of writing it, and whenever we flush, we replace spaces near the edge of the current line with newlines.
Note that changing screen size, font changes the number of chars needed to
finish the line so I need to call maybe_flush (which flushes only if nec.)
from add_to_buffer as well as any time I change one of the above.
I need to call flush for sure any time I switch windows OR from, e.g.,
filename_prompt or read_command, where I want to make sure the user sees
something so that they can input. (Just call it from get_input instead?)
I shouldn't need to call word_wrap, tho, cuz anything that went into
buffer should already be wrapped.
PlotzPerl::OutputStream::Screen
This class handles the screen output stream.
Need to change this to just add newlines, not actually print!
#
# Variable font; graphical wrapping
#
my ($x, $y) = $zio->get_pixel_position();
my $total_width = ($zio->get_pixel_geometry())[0];
my $pixels_left = $total_width - $x;
my $plen;
while ($len = length($str)) {
$plen = $zio->string_width($str);
if ($plen < $pixels_left) {
# it'll fit; we're done
# print STDERR "fits: $str\n";
Add $str to $ret
$zio->write_string($str);
last;
} else {
my $wrapped = 0;
my $i = int(length($str) * ($pixels_left / $plen));
# print STDERR "pl=$pixels_left, plen=$plen i=$i\n";
# Do this with rindex
while (substr($str,$i,1) ne " ") {
# move ahead to a word boundary
# print STDERR "boundarizing\n";
last if ++$i >= $len;
}
while (1) {
$plen = $zio->string_width(substr($str,0,$i));
# printf STDERR "%s = %s\n", substr($str,0,$i), $plen;
if ($plen < $pixels_left) {
# it'll fit
Change this to add to $ret
$zio->write_string(substr($str,0,$i));
$zio->newline();
$str = substr($str, $i + 1);
$wrapped = 1;
last;
} else {
# retreat back a word
while (--$i >= 0 and substr($str,$i,1) ne " ") { }
last if ($i < 0);
}
}
$zio->newline() unless ($wrapped);
# if couldn't wrap at all on this line
$pixels_left = $total_width;
}
}
PlotzPerl::OutputStream::Transcript
This class handles the output stream that stores the user's commands (to @read) as well as the game's screen output.
PlotzPerl::OutputStream::Memory
This class handles the output stream that stores game output to memory.
PlotzPerl::OutputStream::UserInput
This class handles the output stream that stores the user's commands (to @read) as well as the game's screen output.
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 1749:
=pod directives shouldn't be over one line long! Ignoring all 7 lines of content
- Around line 2959:
=pod directives shouldn't be over one line long! Ignoring all 3 lines of content