package Kephra::Document::Property;
our $VERSION = '0.04';
use strict;
use warnings;
# some internal shortcut helper
sub _ep_ref { Kephra::Document::Data::_ep($_[0]) }
sub _doc_nr { Kephra::Document::Data::valid_or_current_doc_nr($_[0]) }
sub _is_current { $_[0] == Kephra::Document::Data::current_nr() }
sub _get_attr { Kephra::Document::Data::get_attribute(@_) }
sub _set_attr { Kephra::Document::Data::set_attribute(@_) }
#
# general API for single and multiple values (getter/setter)
#
sub get {
my $property = shift;
my $doc_nr = _doc_nr(shift);
return if $doc_nr < 0;
if (not ref $property) { _get_attr($property, $doc_nr) }
elsif (ref $property eq 'ARRAY') {
my @result;
push @result, _get_attr($_, $doc_nr) for @$property;
\@result;
}
}
sub _set{
my ($key, $v) = @_;
return unless defined $v;
return set_codepage($v) if $key eq 'codepage';
return set_EOL_mode($v) if $key eq 'EOL';
return set_readonly($v) if $key eq 'readonly';
return set_syntaxmode($v)if $key eq 'syntaxmode';
return set_tab_size($v) if $key eq 'tab_size';
return set_tab_mode($v) if $key eq 'tab_use';
}
sub set {
if (not ref $_[0] and defined $_[1]){_set(@_)}
elsif ( ref $_[0] eq 'HASH') {_set($_, $_[0]->{$_}) for keys %{$_[0]}}
}
sub get_file { _get_attr('file_path') }
sub set_file {
my ($file, $nr) = @_;
$nr = _doc_nr($nr);
return if $nr < 0;
Kephra::Document::Data::set_file_path($file, $nr);
Kephra::App::TabBar::refresh_label($nr);
Kephra::App::Window::refresh_title() if _is_current($nr);
}
#
# property specific API
#
#
# syntaxmode
sub get_syntaxmode { _get_attr('syntaxmode') }
sub set_syntaxmode { Kephra::Document::SyntaxMode::set(@_) }
#
#
sub get_codepage { _get_attr('codepage', $_[0]) }
sub set_codepage {
my ($new_value, $doc_nr) = @_;
$doc_nr = _doc_nr($doc_nr);
return if $doc_nr < 0 or not defined $new_value;
my $old_value = get_codepage($doc_nr);
my $ep = _ep_ref($doc_nr);
if ($old_value eq 'ascii' and $new_value eq 'utf8'){
#unless (Encode::is_utf8($ep->GetText())) {
Kephra::Document::Data::update_attributes($doc_nr);
eval {
#Encode::encode('ascii');
$ep->SetText( Encode::decode('utf8', $ep->GetText()) );
};
#print "$@\n";
Kephra::Document::Data::evaluate_attributes($doc_nr);
#}
#print Encode::is_utf8($ep->GetText())."\n";
}
elsif ($old_value eq 'utf8' and $new_value eq 'ascii') {
Kephra::Document::Data::update_attributes($doc_nr);
$ep->SetText( Encode::encode('utf8', $ep->GetText()) );
Kephra::Document::Data::evaluate_attributes($doc_nr);
}
#print "ask auto $mode\n";
#$ep->SetCodePage( &Wx::wxSTC_CP_UTF8 );
_set_attr('codepage', $new_value, $doc_nr);
Kephra::App::StatusBar::codepage_info($new_value);
}
sub switch_codepage {
set_codepage( get_codepage( _doc_nr() ) eq 'utf8' ? 'ascii' : 'utf8' );
}
#
# tab size
sub get_tab_size { _get_attr('tab_size', $_[0]) }
sub set_tab_size {
my ($size, $nr) = @_;
$nr = _doc_nr($nr);
return if not $size or $nr < 0;
my $ep = _ep_ref();
$ep->SetTabWidth($size);
$ep->SetIndent($size);
$ep->SetHighlightGuide($size);
_set_attr('tab_size', $size, $nr);
}
#
# tab use
sub get_tab_mode { _get_attr('tab_use', $_[0]) }
sub set_tab_mode {
my $mode = shift;
my $nr = _doc_nr(shift);
return if $nr < 0;
my $ep = _ep_ref();
if ($mode eq 'auto') {
if ($ep->GetTextLength){
my $line;
for my $lnr (0 .. $ep->GetLineCount()-1){
$line = $ep->GetLine($lnr);
if ($line =~ /^( |\t)/) {
$mode = $1 eq ' ' ? 0 : 1;
last;
}
}
}
else {
$mode = Kephra::File::_config()->{defaultsettings}{new}{tab_use};
}
}
$ep->SetUseTabs($mode);
_set_attr('tab_use', $mode, $nr);
Kephra::App::StatusBar::tab_info() if _is_current($nr);
}
sub set_tabs_hard { set_tab_mode(1) }
sub set_tabs_soft { set_tab_mode(0) }
sub switch_tab_mode{ get_tab_mode() ? set_tab_mode(0) : set_tab_mode(1) }
#
# EOL
sub EOL_length { _get_attr('EOL_length') }
sub get_EOL_mode { _get_attr('EOL') }
sub set_EOL_mode {
my $mode = shift;
return unless defined $mode;
if ($mode eq 'OS') {
if (&Wx::wxMSW) {$mode = 'cr+lf'}
elsif (&Wx::wxMAC) {$mode = 'cr' }
else {$mode = 'lf' }
}
$mode = detect_EOL_mode() if $mode eq 'auto';
my $ep = _ep_ref();
my $eoll = 1;
if ( $mode eq 'cr+lf'or $mode eq 'win') {$ep->SetEOLMode(&Wx::wxSTC_EOL_CRLF);
$eoll = 2;
}
elsif ( $mode eq 'cr'or $mode eq 'mac') {$ep->SetEOLMode(&Wx::wxSTC_EOL_CR) }
else {$ep->SetEOLMode(&Wx::wxSTC_EOL_LF) }
_set_attr('EOL', $mode);
_set_attr('EOL_length', $eoll);
Kephra::App::StatusBar::EOL_info($mode);
}
sub convert_EOL {
my $mode = shift || get_EOL_mode();
my $doc_nr = _doc_nr(shift);
my $ep = _ep_ref($doc_nr);
$mode = Kephra::File::_config()->{defaultsettings}{EOL_open} unless $mode;
$mode = detect_EOL_mode() if $mode eq 'auto';
Kephra::EventTable::freeze_group('edit');
if ($mode eq 'cr+lf' or $mode eq 'win') {$ep->ConvertEOLs(&Wx::wxSTC_EOL_CRLF)}
elsif ($mode eq 'cr' or $mode eq 'mac' ) {$ep->ConvertEOLs(&Wx::wxSTC_EOL_CR)}
else {$ep->ConvertEOLs(&Wx::wxSTC_EOL_LF)}
Kephra::EventTable::thaw_group('edit');
set_EOL_mode($mode);
}
sub detect_EOL_mode {
my $ep = _ep_ref();
my $end_pos = $ep->PositionFromLine(1);
my $begin_pos = $end_pos - 3;
$begin_pos = 0 if $begin_pos < 0;
my $text = $ep->GetTextRange( $begin_pos, $end_pos );
if ( length($text) < 1 ) { return 'auto' }
else {
#print "win \n" if $text =~ /\r\n/;
#return 'cr+lf' if $text =~ /\r\n/;
#return 'cr' if $text =~ /\r/;
#return 'lf' if $text =~ /\n/;
return 'auto';
}
}
#
# write protection
sub get_readonly { _get_attr('readonly') }
sub set_readonly {
my $status = shift;
my $ep = _ep_ref();
if (not $status or $status eq 'off' ) {
$ep->SetReadOnly(0);
$status = 'off';
} elsif ( $status eq 'on' or $status eq '1' ) {
$ep->SetReadOnly(1);
$status = 'on';
} elsif ( $status eq 'protect' or $status eq '2' ) {
my $file = Kephra::Document::Data::get_file_path();
if ( $file and not -w $file ) {$ep->SetReadOnly(1)}
else {$ep->SetReadOnly(0)}
$status = 'protect';
}
_set_attr('readonly', $status);
$status = $ep->GetReadOnly ? 1 : 0;
_set_attr('editable', $status);
Kephra::App::TabBar::refresh_current_label()
if Kephra::App::TabBar::_config()->{info_symbol};
}
sub set_readonly_on { set_readonly('on') }
sub set_readonly_off { set_readonly('off') }
sub set_readonly_protect { set_readonly('protect') }
1;
__END__
=head1 NAME
Kephra::Document::Property - external API for document handling
=head1 DESCRIPTION
=over 4
=item syntaxmode
=item codepage
=item readonly
=item tab size and usage
=item end of line marker
=back