Bivio::Type::TextArea
# Copyright (c) 2000-2010 bivio Software, Inc. All rights reserved.
# $Id$
package Bivio::Type::TextArea;
use strict;
use Bivio::Base 'Type.Text';
sub LINE_WIDTH {
return 60;
}
sub from_literal {
my($proto, $value, $line_width) = @_;
$proto->internal_from_literal_warning
unless wantarray;
return (undef, undef)
unless defined($value) && length($value);
return (undef, Bivio::TypeError->TOO_LONG)
if length($value) > $proto->get_width;
my($pref, $req);
my($v);
$v = _wrap_lines($proto, $value, $line_width || $proto->LINE_WIDTH)
if defined($value)
and $req = Bivio::Agent::Request->get_current
and $pref = b_use('Model.RowTag')->new($req)
->row_tag_get_for_auth_user('TEXTAREA_WRAP_LINES')
and $pref;
$v = $proto->canonicalize_charset(\$value)
unless $v;
return (undef, undef)
unless $$v;
$$v .= "\n"
unless $$v =~ /\n$/;
return $$v;
}
sub get_width {
# Max size in browsers
return 0xffff;
}
sub _wrap_lines {
my($proto, $value, $width) = @_;
$width = 72
unless $width;
my($lines) = [];
my($formatted) = [];
my($indent) = 0;
foreach my $line (
Text::Tabs::expand(
@{[split(
/\n/,
${$proto->canonicalize_charset($value)},
)]},
),
) {
$line =~ s/\s+$//;
while (defined($line) && length($line) > $width) {
_wrap_line($formatted, \$line, $indent, $width);
}
push(@$formatted, $line)
if defined($line);
}
return \(join("\n", @$formatted, ''));
}
sub _wrap_line {
my($formatted, $line, $indent, $width) = @_;
$$line =~ /(^\s*(|[\-\*])\s+)/;
$indent = defined($1) ? substr($1, 0, $width) : '';
my($white_pos) = rindex($$line, ' ', $width);
$white_pos = index($$line, ' ', $width)
if $white_pos < length($indent);
# Line cannot be broken if no white-space found or quoted
if ($white_pos == -1 || $$line =~ /^\s*[>]/) {
push(@$formatted, $$line);
undef($$line);
}
else {
my($wrapped) = substr($$line, 0, $white_pos);
push(@$formatted, $wrapped);
$$line = substr($$line, $white_pos);
$$line =~ s/^\s+/' ' x length($indent)/e;
}
return;
}
1;