1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00

v2.10.3.1

This commit is contained in:
gnosygnu
2015-10-18 22:17:57 -04:00
parent 8e18af05b6
commit 4f43f51b18
1935 changed files with 12500 additions and 12889 deletions

View File

@@ -0,0 +1,52 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.guis.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
public class Xog_history_itm {
private final boolean redirect_force;
public Xog_history_itm(byte[] wiki, byte[] page, byte[] anch, byte[] qarg, boolean redirect_force, String bmk_pos) {
this.key = Bry_.Add_w_dlm(Byte_ascii.Pipe, wiki, page, anch, qarg, redirect_force ? Bool_.Y_bry : Bool_.N_bry);
this.wiki = wiki; this.page = page; this.anch = anch; this.qarg = qarg;
this.redirect_force = redirect_force; this.bmk_pos = bmk_pos;
}
public byte[] Key() {return key;} private final byte[] key;
public byte[] Wiki() {return wiki;} private final byte[] wiki;
public byte[] Page() {return page;} private final byte[] page;
public byte[] Anch() {return anch;} private final byte[] anch;
public byte[] Qarg() {return qarg;} private final byte[] qarg;
public String Bmk_pos() {return bmk_pos;} public void Bmk_pos_(String v) {bmk_pos = v;} private String bmk_pos;
public boolean Eq_wo_bmk_pos(Xog_history_itm comp) {
return Bry_.Eq(wiki, comp.wiki)
&& Bry_.Eq(page, comp.page)
&& Bry_.Eq(anch, comp.anch)
&& Bry_.Eq(qarg, comp.qarg)
&& redirect_force == comp.redirect_force
;
}
public void Srl_save(Bry_bfr bfr) {
byte[] bmk_bry = Bry_.Replace(Bry_.new_u8(bmk_pos), Byte_ascii.Pipe, Byte_ascii.Tilde); // replace | with ~; EX: "0|1|2" -> "0~1~2"
bfr.Add(key).Add_byte_pipe().Add(bmk_bry).Add_byte_nl();
}
public static Xog_history_itm Srl_load(byte[] raw) {
byte[][] atrs = Bry_split_.Split(raw, Byte_ascii.Pipe);
byte[] bmk_bry = atrs.length == 6 ? atrs[5] : Bry_.Empty;
bmk_bry = Bry_.Replace(bmk_bry, Byte_ascii.Tilde, Byte_ascii.Pipe);
return new Xog_history_itm(atrs[0], atrs[1], atrs[2], atrs[3], atrs[4] == Bool_.Y_bry, String_.new_a7(bmk_bry));
}
public static final String Html_doc_pos_toc = "top";
public static final Xog_history_itm Null = new Xog_history_itm(null, null, null, null, false, null);
}

View File

@@ -0,0 +1,77 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.guis.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
public class Xog_history_mgr {
private final Ordered_hash hash = Ordered_hash_.New_bry(); private final Xog_history_stack stack = new Xog_history_stack();
public int Count() {return hash.Count();}
public Xoae_page Cur_page(Xowe_wiki wiki) {return Get_or_fetch(wiki, stack.Cur_itm());}
public Xoae_page Go_bwd(Xowe_wiki wiki) {return Go_by_dir(wiki, Bool_.N);}
public Xoae_page Go_fwd(Xowe_wiki wiki) {return Go_by_dir(wiki, Bool_.Y);}
public Xoae_page Go_by_dir(Xowe_wiki wiki, boolean fwd) {
Xog_history_itm itm = fwd ? stack.Go_fwd() : stack.Go_bwd();
if (itm == Xog_history_itm.Null) return Xoae_page.Empty;
Xoae_page rv = Get_or_fetch(wiki, itm);
byte[] anch_key = itm.Anch();
rv.Url().Anch_bry_(anch_key); // must override anchor as it may be different for cached page
rv.Html_data().Bmk_pos_(itm.Bmk_pos());
return rv;
}
public void Add(Xoae_page page) {
Xog_history_itm new_itm = Xog_history_mgr.new_(page);
stack.Add(new_itm);
byte[] page_key = Build_page_key(page);
if (!hash.Has(page_key))
hash.Add(page_key, page);
}
public void Update_html_doc_pos(Xoae_page page, byte history_nav_type) {
Xog_history_itm itm = Get_recent(page, history_nav_type);
if (itm != null) itm.Bmk_pos_(page.Html_data().Bmk_pos());
}
private Xog_history_itm Get_recent(Xoae_page page, byte history_nav_type) {
int pos = -1;
int list_pos = stack.Cur_pos();
switch (history_nav_type) {
case Xog_history_stack.Nav_fwd: pos = list_pos - 1; break;
case Xog_history_stack.Nav_bwd: pos = list_pos + 1; break;
case Xog_history_stack.Nav_by_anchor: pos = list_pos; break;
}
if (pos < 0 || pos >= stack.Len()) return null;
Xog_history_itm recent = stack.Get_at(pos);
Xog_history_itm page_itm = Xog_history_mgr.new_(page);
return page_itm.Eq_wo_bmk_pos(recent) ? recent : null; // check that recent page actually matches current; DATE:2014-05-10
}
private Xoae_page Get_or_fetch(Xowe_wiki wiki, Xog_history_itm itm) {
byte[] page_key = Build_page_key(itm.Wiki(), itm.Page(), itm.Qarg());
Xoae_page rv = (Xoae_page)hash.Get_by(page_key);
if (rv != null) return rv;
Xoa_ttl ttl = Xoa_ttl.parse(wiki, itm.Page());
return wiki.Data_mgr().Get_page(ttl, false);
}
private static byte[] Build_page_key(Xoae_page page) {return Build_page_key(page.Wiki().Domain_bry(), page.Ttl().Full_url(), page.Url().Qargs_mgr().To_bry());}
private static byte[] Build_page_key(byte[] wiki_key, byte[] page_key, byte[] args_key) {return Bry_.Add_w_dlm(Byte_ascii.Pipe, wiki_key, page_key, args_key);}
public static Xog_history_itm new_(Xoae_page pg) {
byte[] wiki = pg.Wiki().Domain_bry();
byte[] page = pg.Ttl().Full_url(); // get page_name only (no anchor; no query args)
byte[] anch = pg.Url().Anch_bry();
byte[] qarg = pg.Url().Qargs_mgr().To_bry();
boolean redirect_force = pg.Url().Qargs_mgr().Match(Xoa_url_.Qarg__redirect, Xoa_url_.Qarg__redirect__yes);
String bmk_pos = pg.Html_data().Bmk_pos();
if (bmk_pos == null) bmk_pos = Xog_history_itm.Html_doc_pos_toc; // never allow null doc_pos; set to top
return new Xog_history_itm(wiki, page, anch, qarg, redirect_force, bmk_pos);
}
}

View File

@@ -0,0 +1,70 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.guis.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
public class Xog_history_stack {
private final List_adp list = List_adp_.new_();
public int Len() {return list.Count();}
public void Clear() {list.Clear(); cur_pos = 0;}
public Xog_history_itm Get_at(int i) {return (Xog_history_itm)list.Get_at(i);}
public int Cur_pos() {return cur_pos;} private int cur_pos = 0;
public Xog_history_itm Cur_itm() {return list.Count() == 0 ? Xog_history_itm.Null : (Xog_history_itm)list.Get_at(cur_pos);}
public void Add(Xog_history_itm new_itm) {
Xog_history_itm cur_itm = this.Cur_itm();
if (cur_itm != Xog_history_itm.Null && cur_itm.Eq_wo_bmk_pos(new_itm)) return; // do not add if last itm is same;
this.Del_from(cur_pos + 1);
list.Add(new_itm);
cur_pos = list.Count() - 1;
}
public Xog_history_itm Go_bwd() {
if (list.Count() == 0) return Xog_history_itm.Null;
if (cur_pos == 0) return Xog_history_itm.Null;
--cur_pos;
return this.Cur_itm();
}
public Xog_history_itm Go_fwd() {
int list_count = list.Count();
if (list_count == 0) return Xog_history_itm.Null;
if (cur_pos == list_count - 1) return Xog_history_itm.Null;
++cur_pos;
return this.Cur_itm();
}
private void Del_from(int from) {
int len = list.Count();
if (from <= len - 1)
list.Del_range(from, len - 1);
}
public void Srl_save(Bry_bfr bfr) {
int len = list.Count();
for (int i = 0; i < len; ++i) {
Xog_history_itm itm = (Xog_history_itm)list.Get_at(i);
itm.Srl_save(bfr);
}
}
public void Srl_load(byte[] bry) {
list.Clear();
byte[][] lines = Bry_split_.Split_lines(bry);
int len = lines.length;
for (int i = 0; i < len; ++i) {
byte[] line = lines[i];
Xog_history_itm itm = Xog_history_itm.Srl_load(line);
this.Add(itm);
}
}
public void Cur_pos_(int v) {this.cur_pos = v;}
public static final byte Nav_fwd = 1, Nav_bwd = 2, Nav_by_anchor = 3;
}

View File

@@ -0,0 +1,85 @@
/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.guis.history; import gplx.*; import gplx.xowa.*; import gplx.xowa.guis.*;
import org.junit.*;
public class Xog_history_stack_tst {
@Before public void init() {fxt.Clear();} private Xog_history_stack_fxt fxt = new Xog_history_stack_fxt();
@Test public void Init() {fxt.Test_cur(null);}
@Test public void Add_1() {fxt.Exec_add_many("A").Test_cur("A").Test_len(1).Test_pos(0);}
@Test public void Add_same() {fxt.Exec_add_many("A", "A").Test_cur("A").Test_len(1).Test_pos(0);}
@Test public void Add_3() {fxt.Exec_add_many("A", "B", "C").Test_cur("C").Test_len(3).Test_pos(2);}
@Test public void Add_3_bwd() {fxt.Exec_add_many("A", "B", "C").Exec_go_bwd().Test_cur("B").Test_pos(1);}
@Test public void Add_3_bwd_fwd() {fxt.Exec_add_many("A", "B", "C").Exec_go_bwd().Exec_go_fwd().Test_cur("C").Test_pos(2);}
@Test public void Add_3_bwd_add() {fxt.Exec_add_many("A", "B", "C").Exec_go_bwd().Exec_add_many("D").Test_len(3).Test_cur("D").Test_pos(2);}
@Test public void Add_3_bwd_bwd_add() {fxt.Exec_add_many("A", "B", "C").Exec_go_bwd().Exec_go_bwd().Exec_add_many("D").Test_len(2).Test_cur("D").Test_pos(1);}
@Test public void Add_dif_ns() {fxt.Exec_add_many("A", "Help:A").Test_cur("Help:A");} // PURPOSE.fix: page_stack was only differtiating by Page_db, not Full; EX: Unicode -> Category:Unicode
@Test public void Add_qargs() {// PURPOSE.fix: page_stack was only differentiating by qtxt args
fxt .Exec_add_one("Special:AllPages", "?from=A")
.Exec_add_one("Special:AllPages", "?from=B")
.Exec_add_many("B")
.Exec_go_bwd()
.Test_cur("Special:AllPages")
.Test_cur_qargs("?from=B")
;
}
}
class Xog_history_stack_fxt {
public Xog_history_stack_fxt Clear() {
stack.Clear();
if (app == null) {
app = Xoa_app_fxt.app_();
wiki = Xoa_app_fxt.wiki_tst_(app);
}
return this;
} private Xoae_app app; private Xowe_wiki wiki; private Xog_history_stack stack = new Xog_history_stack();
public Xog_history_stack_fxt Test_cur(String expd) {
Xog_history_itm page = stack.Cur_itm();
String actl = page == null ? null : String_.new_u8(page.Page());
Tfds.Eq(expd, actl, "cur");
return this;
}
public Xog_history_stack_fxt Test_cur_qargs(String expd) {
Xog_history_itm page = stack.Cur_itm();
String actl = page == null ? null : String_.new_u8(page.Qarg());
Tfds.Eq(expd, actl, "cur_qargs");
return this;
}
public Xog_history_stack_fxt Exec_go_bwd() {stack.Go_bwd(); return this;}
public Xog_history_stack_fxt Exec_go_fwd() {stack.Go_fwd(); return this;}
public Xog_history_stack_fxt Exec_add_many(String... ary) {
int len = ary.length;
for (int i = 0; i < len; i++) {
String ttl = ary[i];
Exec_add_one(ttl, null);
}
return this;
}
public Xog_history_stack_fxt Exec_add_one(String ttl_str, String arg_str) {
byte[] ttl_bry = Bry_.new_u8(ttl_str);
Xoa_ttl ttl = Xoa_ttl.parse(wiki, ttl_bry);
Xoae_page page = Xoae_page.test_(wiki, ttl);
byte[] url_bry = ttl_bry;
if (arg_str != null) url_bry = Bry_.Add(url_bry, Bry_.new_u8(arg_str));
Xoa_url url = app.User().Wikii().Utl__url_parser().Parse(url_bry);
page.Url_(url); // set url b/c history_mgr.Add uses url
stack.Add(Xog_history_mgr.new_(page));
return this;
}
public Xog_history_stack_fxt Test_pos(int expd) {Tfds.Eq(expd, stack.Cur_pos(), "pos"); return this;}
public Xog_history_stack_fxt Test_len(int expd) {Tfds.Eq(expd, stack.Len(), "len"); return this;}
}