$VERSION
=
'0.19'
;
sub
new {
my
$class
=
shift
;
my
$self
=
$class
->SUPER::new(
@_
);
return
undef
unless
defined
$self
;
my
$page
=
$self
->ToolLeftPageAdd(
'Bookmarks'
,
'bookmarks'
,
undef
,
'Manage your bookmarks'
, 250);
$self
->cmdConfig(
bm_plug_next
=> [
'bmNext'
,
$self
],
bm_plug_previous
=> [
'bmPrevious'
,
$self
],
);
$self
->cmdHookAfter(
'bookmark_add'
,
'RefreshSelected'
,
$self
);
$self
->cmdHookAfter(
'bookmark_remove'
,
'RefreshSelected'
,
$self
);
$self
->{CURRENT} =
undef
;
$self
->{NEXT} = [];
$self
->{PREVIOUS} = [];
my
$tree
=
$page
->Scrolled(
'ITree'
,
-height
=> 4,
-browsecmd
=> [
'Select'
,
$self
],
-scrollbars
=>
'osoe'
,
-separator
=>
'@'
,
)->
pack
(
-padx
=> 2,
-pady
=> 2,
-expand
=> 1,
-fill
=>
'both'
);
$self
->{TREE} =
$tree
;
$self
->
after
(100, [
'Initialize'
,
$self
]);
return
$self
;
}
sub
_visible {
my
$self
=
shift
;
return
$self
->tree->ismapped;
}
sub
bmAdd {
my
$self
=
shift
;
my
$name
=
shift
;
my
$t
=
$self
->tree;
unless
(
$t
->infoExists(
$name
)) {
my
@ch
=
$t
->infoChildren(
''
);
my
@op
;
for
(
@ch
) {
if
(
$_
gt
$name
) {
push
@op
,
-before
=>
$_
;
last
;
}
}
$t
->add(
$name
,
-text
=>
$self
->abbreviate(
$name
, 30),
@op
);
}
while
(
@_
) {
my
$mark
=
shift
;
unless
(
$self
->bmExists(
$name
,
$mark
)) {
my
@ch
=
$t
->infoChildren(
$name
);
my
$newmark
=
$name
.
'@'
.
$mark
;
my
$line
=
$self
->bmLineNumber(
$newmark
);
my
@op
;
for
(
@ch
) {
my
$peer
=
$self
->bmLineNumber(
$_
);
if
(
$peer
>
$line
) {
push
@op
,
-before
=>
$_
;
last
;
}
}
$t
->add(
$newmark
,
-text
=>
$mark
,
@op
);
}
$t
->autosetmode(1);
}
}
sub
bmCompare {
my
(
$self
,
$mark1
,
$mark2
) =
@_
;
if
(
$mark1
=~ /^(\d+)/) {
$mark1
= $1
}
if
(
$mark2
=~ /^(\d+)/) {
$mark2
= $1
}
return
$mark1
eq
$mark2
}
sub
bmExists {
my
(
$self
,
$name
,
$mark
) =
@_
;
my
$t
=
$self
->tree;
return
''
unless
$t
->infoExists(
$name
);
my
@list
=
$t
->infoChildren(
$name
);
for
(
@list
) {
my
@targ
=
split
/\@/,
$_
;
return
1
if
$self
->bmCompare(
$mark
,
$targ
[1]);
}
return
''
}
sub
bmGo {
my
(
$self
,
$mark
) =
@_
;
my
(
$doc
,
$bm
) =
split
/\@/,
$mark
;
$bm
=
''
unless
defined
$bm
;
my
$mdi
=
$self
->mdi;
if
(
$bm
=~ /^(\d+)/) {
$self
->cmdExecute(
'doc_select'
,
$doc
);
my
$w
=
$mdi
->docGet(
$doc
)->CWidg;
$w
->bookmarkGo($1);
}
}
sub
bmLineNumber {
my
(
$self
,
$mark
) =
@_
;
my
(
$doc
,
$bm
) =
split
/\@/,
$mark
;
$bm
=
''
unless
defined
$bm
;
if
(
$bm
=~ /^(\d+)/) {
return
$1
}
}
sub
bmNext {
my
$self
=
shift
;
my
$nstack
=
$self
->{NEXT};
if
(
@$nstack
) {
my
$pstack
=
$self
->{PREVIOUS};
unshift
@$pstack
,
$self
->{CURRENT};
my
$new
=
shift
@$nstack
;
$self
->{CURRENT} =
$new
;
$self
->bmGo(
$new
);
}
}
sub
bmPrevious {
my
$self
=
shift
;
my
$pstack
=
$self
->{PREVIOUS};
if
(
@$pstack
) {
my
$nstack
=
$self
->{NEXT};
unshift
@$nstack
,
$self
->{CURRENT};
my
$new
=
shift
@$pstack
;
$self
->{CURRENT} =
$new
;
$self
->bmGo(
$new
);
}
}
sub
Collect {
my
(
$self
,
$name
) =
@_
;
my
@out
= ();
my
$mdi
=
$self
->mdi;
if
(
$mdi
->deferredExists(
$name
)) {
my
$o
=
$mdi
->deferredOptions(
$name
);
if
(
defined
$o
) {
if
(
my
$b
=
$o
->{
'bookmarks'
}) {
my
@marks
= ();
while
(
$b
=~ s/^(\d+)\s//) {
push
@marks
, $1;
}
my
$num
= 1;
if
(
open
IF,
'<'
,
$name
) {
while
(
my
$line
= <IF>) {
chomp
$line
;
if
(
$num
eq
$marks
[0]) {
shift
@marks
;
$line
=~ s/^\s+//;
my
$o
=
$line
;
$o
=
substr
(
$line
, 0, 20)
if
length
$line
> 20;
push
@out
,
"$num - $o"
;
}
$num
++;
last
unless
@marks
;
}
close
IF;
}
}
}
}
else
{
my
$w
=
$mdi
->docGet(
$name
)->CWidg;
my
@list
=
$w
->bookmarkList;
for
(
@list
) {
push
@out
,
"$_ - "
.
$w
->bookmarkText(
$_
);
}
}
return
@out
}
sub
docRefresh {
my
(
$self
,
$name
) =
@_
;
my
$t
=
$self
->tree;
my
$cursel
;
(
$cursel
) =
$t
->infoSelection;
if
(
$t
->infoExists(
$name
)) {
for
(
$t
->infoChildren(
$name
)) {
$t
->deleteEntry(
$_
);
}
}
my
@new
=
$self
->Collect(
$name
);
if
(
$t
->infoExists(
$name
)) {
$t
->deleteEntry(
$name
)
unless
@new
;
}
$self
->bmAdd(
$name
,
@new
)
if
@new
;
$t
->selectionSet(
$cursel
)
if
(
defined
$cursel
);
}
sub
histClearNext {
my
$self
=
shift
;
$self
->{NEXT} = [];
}
sub
Initialize {
my
$self
=
shift
;
my
$t
=
$self
->tree;
$t
->deleteAll;
my
$mdi
=
$self
->mdi;
for
(
$mdi
->deferredList,
$mdi
->docList) {
my
@marks
=
$self
->Collect(
$_
);
$self
->bmAdd(
$_
,
@marks
)
if
@marks
;
}
}
sub
Refresh {
my
$self
=
shift
;
$self
->SUPER::Refresh;
$self
->RefreshSelected;
}
sub
RefreshAll {
my
$self
=
shift
;
my
$t
=
$self
->tree;
my
@list
=
$t
->infoChildren(
''
);
for
(
@list
) {
$self
->docRefresh(
$_
);
}
}
sub
RefreshSelected {
my
$self
=
shift
;
my
$mdi
=
$self
->extGet(
'CoditMDI'
);
my
$doc
=
$mdi
->docSelected;
return
unless
defined
$doc
;
$self
->docRefresh(
$doc
);
}
sub
Select {
my
(
$self
,
$mark
) =
@_
;
my
@targ
=
split
/\@/,
$mark
;
return
unless
@targ
eq 2;
my
$cur
=
$self
->{CURRENT};
if
((
defined
$cur
) and (
$cur
ne
$mark
)) {
my
$prev
=
$self
->{PREVIOUS};
push
@$prev
,
$cur
;
$self
->histClearNext;
}
$self
->{CURRENT} =
$mark
;
$self
->bmGo(
$mark
);
}
sub
tree {
return
$_
[0]->{TREE} }
sub
ToolItems {
my
$self
=
shift
;
my
@items
=
$self
->SUPER::ToolItems;
return
(
@items
,
[
'tool_separator'
],
[
'tool_button'
,
'Previous'
,
'bm_plug_previous'
,
'bookmark_previous'
,
'Jump to previous bookmark'
],
[
'tool_button'
,
'Next'
,
'bm_plug_next'
,
'bookmark_next'
,
'Jump to next bookmark'
],
);
}
sub
Unload {
my
$self
=
shift
;
for
(
qw/
bm_plug_next
bm_plug_previous
/
) {
$self
->cmdRemove(
$_
);
}
$self
->cmdUnhookAfter(
'bookmark_add'
,
'RefreshSelected'
,
$self
);
$self
->cmdUnhookAfter(
'bookmark_remove'
,
'RefreshSelected'
,
$self
);
$self
->ToolLeftPageRemove(
'Bookmarks'
);
return
$self
->SUPER::Unload;
}
1;