Games-Axmud
view release on metacpan or search on metacpan
lib/Games/Axmud/Buffer.pm view on Meta::CPAN
# ->tagHash{tag} = reference_to_list_of_offsets_where_tags_occur
tagHash => {%$tagHashRef},
# Hash of 'mxpm_mode' tags that appear anywhere on this line, in the form
# $mxpModeHash{mode} = undef
# ...where 'mode' is a number in the range 10-12, 19, 20-99
mxpModeHash => {},
# List of Axmud colour/style tags that were applied to the first character of this line,
# when it was displayed in the 'main' window
# e.g. if the previous line used a 'blue' tag, but no 'attribs_off' after it, and if
# this line has no tags at all at offset 0, then the 'blue' tag still applies, and it
# exists in this list
# e.g. if this line has a 'red' tag at offset 0, then that tag exists in this list,
# rather than the 'blue' tag that applied at the end of the previous line
initialTagList => [@$initialListRef],
# List of Axmud colour/style tags that applied at the end of this line (i.e. the tags
# that will apply to the beginning of the next line, BEFORE any of the next line's
# tags are processed)
finalTagList => [], # Set below
# List of Axmud colour/style tags that applied at the end of the previous line (copied
# from the buffer object's ->finalTagList from the previous line)
previousTagList => [], # Set below
# MXP custom elements can define tag properties, e.g. from the MXP spec,
# <RName>...</RName>
# If a closing tag has been processed on this line, and if the element defines tag
# properties, the text between the matching tags is stored in this buffer object
# (If the text between the two matching tags contained newline characters, they have
# been removed)
# Hash in the form
# $mxpFlagHash{tag_property} = text
mxpFlagTextHash => {%$mxpFlagHashRef},
};
# Bless the object into existence
bless $self, $class;
# If we've got a complete line, we can set the final tag list (otherwise, we must wait until
# the call to $self->update)
if ($newLineFlag) {
$self->{finalTagList} = [$session->currentTabObj->textViewObj->listColourStyleTags()];
}
# If this isn't the first buffer line, we can also set the previous tag list
$prevBufferObj = $session->ivShow('displayBufferHash', ($number - 1));
if ($prevBufferObj) {
$self->{previousTagList} = [$prevBufferObj->finalTagList];
}
# Set the contents of $self->mxpModeHash, using any 'mxpm_mode' tags found in ->offsetHash
$self->updateModes();
return $self;
}
##################
# Methods
sub update {
# Called by GA::Session->updateDisplayBuffer when this object stores the most
# recently-displayed line of text from the world, and that line hasn't yet been terminated
# with a newline character
# Updates the stored IVs
#
# Expected arguments
# $line - The original line of text received from the world
# $stripLine - $line after being stripped of escape sequences
# $modLine - $stripLine after being modified by any matching interfaces (identical
# to $stripLine if none match)
# $newLineFlag - Flag set to TRUE if the line ends with a newline character; FALSE if
# not
# $offsetHashRef - Hash of Axmud colour/style tags in the form
# $offsetHash{$offset} = reference_to_list_of_Axmud_colour_style_tags
# - Each offset represents the position of a character in $modLine,
# immediately before which the equivalent escape sequence was
# received (see the comments in GA::Session->updateDisplayBuffer)
# $tagHashRef - Hash of Axmud colour/style tags in the form
# $tagHash{tag} = reference_to_list_of_offsets_where_tags_occur
# $mxpFlagHashRef - Hash of text appearing between matching custom elements which define
# tag properties in the form
# $mxpFlagHash{tag_property} = string
#
# Return values
# 'undef' on improper arguments
# 1 on success
my (
$self, $line, $stripLine, $modLine, $newLineFlag, $offsetHashRef, $tagHashRef,
$mxpFlagHashRef,
$check,
) = @_;
# Local variables
my (
$size,
%newTagHash, %newOffsetHash,
);
# Check for improper arguments
if (
! defined $line || ! defined $stripLine || ! defined $modLine || ! defined $newLineFlag
|| ! defined $offsetHashRef || ! defined $tagHashRef || defined $check
) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->update', @_);
}
# The contents of $tagHashRef must be merged with the existing contents of $self->tagHash
# At the same time, we must modify all the offsets in $tagHashRef; e.g. if the tag 'red'
# has the list of offsets [0, 4, 9], and if $self->modLine already contains 50
# characters, the offsets should be stored as [50, 54, 59]
# Get the existing size of $self->modLine
$size = length ($self->modLine);
# Import the current tag hash for speed...
%newTagHash = $self->tagHash;
# ...and then update it with the new data
foreach my $tag (keys %$tagHashRef) {
lib/Games/Axmud/Buffer.pm view on Meta::CPAN
}
# MXP tag properties for custom elements are rarer, so we don't need to import anything for
# speed
foreach my $key (keys %$mxpFlagHashRef) {
my $value = $$mxpFlagHashRef{$key};
# (Guard against possibly that two sets of tags, e.g. <RName>...</RName>, appear on the
# same line
if (! $self->ivExists('mxpFlagTextHash', $key)) {
$self->ivAdd('mxpFlagTextHash', $key, $value);
} else {
$self->ivAdd(
'mxpFlagTextHash',
$key,
$self->ivShow('mxpFlagTextHash', $key) . $value,
);
}
}
# Update IVs. If $line is an empty string, it's because a packet beginning with a newline
# character was processed (otherwise, $line is a string whose initial portion matches the
# contents of $self->line)
if (length ($line) > length ($self->line)) {
$self->ivPush('partList', substr($line, length($self->line)));
}
$self->ivPoke('line', $self->line . $line);
$self->ivPoke('stripLine', $self->stripLine . $stripLine);
$self->ivPoke('modLine', $self->modLine . $modLine);
$self->ivPoke('newLineFlag', $newLineFlag);
if ($self->modLine =~ m/^\s*[\n\r]*$/) {
$self->ivPoke('emptyFlag', TRUE);
} else {
$self->ivPoke('emptyFlag', FALSE);
}
$self->ivPoke('offsetHash', %newOffsetHash);
$self->ivPoke('tagHash', %newTagHash);
if ($newLineFlag) {
$self->ivPoke(
'finalTagList',
$self->session->currentTabObj->textViewObj->listColourStyleTags(),
);
}
# Update the ->mxpModeHash IV
$self->updateModes();
return 1;
}
sub updateModes {
# Called by $self->new and $self->update
# $self->mxpModeHash stores all the MXP modes (but only those in the range 10-12, 19, 20-99)
# that apply to this line
# Update the hash
#
# Expected arguments
# (none besides $self)
#
# Return values
# 'undef' on improper arguments
# 1 on success
my ($self, $check) = @_;
# Local variables
my (%offsetHash, %modeHash);
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->updateModes', @_);
}
# Import IVs (for convenience)
%offsetHash = $self->offsetHash;
%modeHash = $self->mxpModeHash;
foreach my $offset (keys %offsetHash) {
my ($listRef, $mode);
$listRef = $offsetHash{$offset};
foreach my $tag (@$listRef) {
if (substr($tag, 0, 5) eq 'mxpm_') {
$mode = substr($tag, 5);
$modeHash{$mode} = undef;
}
}
}
# Update the IV
$self->ivPoke('mxpModeHash', %modeHash);
return 1;
}
sub copyLine {
# Can be called by anything (for example, called by the Channels task)
# Copies the contents of the line stored in this object into another textview, preserving
# the colour and style of the original line
# Normal links (e.g. a line containing 'http://mywebsite.com') are clickable, but MXP links
# and so on are not
#
# Expected arguments
# $textViewObj - The textview object (GA::Obj::TextView) into which the line is copied
( run in 0.940 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )