diff --git a/100_core/src_110_primitive/gplx/Bry_bfr.java b/100_core/src_110_primitive/gplx/Bry_bfr.java index cb81215de..5d2c8489f 100644 --- a/100_core/src_110_primitive/gplx/Bry_bfr.java +++ b/100_core/src_110_primitive/gplx/Bry_bfr.java @@ -65,7 +65,7 @@ public class Bry_bfr { bfr_len += len; return this; } - public Bry_bfr Add_bfr(Bry_bfr src) { + public Bry_bfr Add_bfr_and_preserve(Bry_bfr src) { int len = src.bfr_len; if (bfr_len + len > bfr_max) Resize((bfr_max + len) * 2); Bry_.Copy_by_pos(src.bfr, 0, len, bfr, bfr_len); @@ -74,10 +74,15 @@ public class Bry_bfr { return this; } public Bry_bfr Add_bfr_and_clear(Bry_bfr src) { - Add_bfr(src); + Add_bfr_and_preserve(src); src.ClearAndReset(); return this; } + public Bry_bfr Add_bfr_or_mid(boolean escaped, Bry_bfr tmp_bfr, byte[] src, int src_bgn, int src_end) { + return escaped + ? this.Add_bfr_and_clear(tmp_bfr) + : this.Add_mid(src, src_bgn, src_end); + } public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end) {return Add_bfr_trim_and_clear(src, trim_bgn, trim_end, Bry_.Trim_ary_ws);} public Bry_bfr Add_bfr_trim_and_clear(Bry_bfr src, boolean trim_bgn, boolean trim_end, byte[] trim_ary) { int src_len = src.bfr_len; @@ -326,7 +331,7 @@ public class Bry_bfr { else if (o_type == Byte.class) Add_byte(Byte_.cast_(o)); else if (o_type == Long.class) Add_long_variable(Long_.cast_(o)); else if (o_type == String.class) Add_str((String)o); - else if (o_type == Bry_bfr.class) Add_bfr((Bry_bfr)o); + else if (o_type == Bry_bfr.class) Add_bfr_and_preserve((Bry_bfr)o); else if (o_type == DateAdp.class) Add_dte((DateAdp)o); else if (o_type == Io_url.class) Add(((Io_url)o).RawBry()); else if (o_type == boolean.class) Add_yn(Bool_.cast_(o)); @@ -377,6 +382,20 @@ public class Bry_bfr { if (new_len > -1) bfr_len = new_len; return this; } + public Bry_bfr Trim_end(byte trim_byte) { + if (bfr_len == 0) return this; + int count = 0; + for (int i = bfr_len - 1; i > -1; --i) { + byte b = bfr[i]; + if (b == trim_byte) + ++count; + else + break; + } + if (count > 0) + this.Del_by(count); + return this; + } public Bry_bfr Concat_skip_empty(byte[] dlm, byte[]... ary) { int ary_len = ary.length; for (int i = 0; i < ary_len; i++) { diff --git a/100_core/src_110_primitive/gplx/Bry_bfr_.java b/100_core/src_110_primitive/gplx/Bry_bfr_.java new file mode 100644 index 000000000..69ecca449 --- /dev/null +++ b/100_core/src_110_primitive/gplx/Bry_bfr_.java @@ -0,0 +1,37 @@ +/* +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 . +*/ +package gplx; +public class Bry_bfr_ { + public static void Assert_at_end(Bry_bfr bfr, byte assert_byte) { + int len = bfr.Len(); if (len == 0) return; + int assert_count = 0; + byte[] bfr_bry = bfr.Bfr(); + for (int i = len - 1; i > -1; --i) { + byte b = bfr_bry[i]; + if (b == assert_byte) + ++assert_count; + else + break; + } + switch (assert_count) { + case 0: bfr.Add_byte(assert_byte); break; + case 1: break; + default: bfr.Del_by(assert_count - 1); break; + } + } +} diff --git a/100_core/src_110_primitive/gplx/Bry_finder.java b/100_core/src_110_primitive/gplx/Bry_finder.java index 333af9e1a..716591942 100644 --- a/100_core/src_110_primitive/gplx/Bry_finder.java +++ b/100_core/src_110_primitive/gplx/Bry_finder.java @@ -117,7 +117,7 @@ public class Bry_finder { } return rv; } - public static int Find_bwd_non_ws(byte[] src, int cur, int end) { // get pos of 1st char that is not ws; + public static int Find_bwd_non_ws_or_not_found(byte[] src, int cur, int end) { // get pos of 1st char that is not ws; if (cur >= src.length) return Bry_finder.Not_found; for (int i = cur; i >= end; i--) { byte b = src[i]; @@ -130,6 +130,19 @@ public class Bry_finder { } return Bry_finder.Not_found; } + public static int Find_bwd_non_ws_or_end(byte[] src, int cur, int end) { + if (cur >= src.length) return Bry_finder.Not_found; + for (int i = cur; i >= end; i--) { + byte b = src[i]; + switch (b) { + case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.NewLine: case Byte_ascii.CarriageReturn: + break; + default: + return i; + } + } + return end; + } public static int Find_bwd_while(byte[] src, int cur, int end, byte while_byte) { --cur; while (true) { diff --git a/100_core/src_110_primitive/gplx/Bry_fmtr_arg_.java b/100_core/src_110_primitive/gplx/Bry_fmtr_arg_.java index b7f8ae135..1417d1530 100644 --- a/100_core/src_110_primitive/gplx/Bry_fmtr_arg_.java +++ b/100_core/src_110_primitive/gplx/Bry_fmtr_arg_.java @@ -23,7 +23,7 @@ public class Bry_fmtr_arg_ { public static Bry_fmtr_arg_byt byt_(byte v) {return new Bry_fmtr_arg_byt(v);} public static Bry_fmtr_arg_int int_(int v) {return new Bry_fmtr_arg_int(v);} public static Bry_fmtr_arg_bfr bfr_(Bry_bfr v) {return new Bry_fmtr_arg_bfr(v);} - public static Bry_fmtr_arg_bfr_retain bfr_retain_(Bry_bfr v) {return new Bry_fmtr_arg_bfr_retain(v);} + public static Bry_fmtr_arg_bfr_preserve bfr_retain_(Bry_bfr v) {return new Bry_fmtr_arg_bfr_preserve(v);} public static Bry_fmtr_arg fmtr_(Bry_fmtr v, Bry_fmtr_arg... arg_ary) {return new Bry_fmtr_arg_fmtr(v, arg_ary);} public static Bry_fmtr_arg_fmtr_objs fmtr_null_() {return new Bry_fmtr_arg_fmtr_objs(null, null);} public static final Bry_fmtr_arg Null = new Bry_fmtr_arg_null(); diff --git a/100_core/src_110_primitive/gplx/Byte_ascii.java b/100_core/src_110_primitive/gplx/Byte_ascii.java index 781fb61e7..7188f592a 100644 --- a/100_core/src_110_primitive/gplx/Byte_ascii.java +++ b/100_core/src_110_primitive/gplx/Byte_ascii.java @@ -70,7 +70,16 @@ public class Byte_ascii { ; } public static final byte[] - Dot_bry = new byte[] {Byte_ascii.Dot} - , NewLine_bry = new byte[] {Byte_ascii.NewLine} + Dot_bry = new byte[] {Byte_ascii.Dot} + , NewLine_bry = new byte[] {Byte_ascii.NewLine} + , Colon_bry = new byte[] {Byte_ascii.Colon} + , Lt_bry = new byte[] {Byte_ascii.Lt} + , Gt_bry = new byte[] {Byte_ascii.Gt} + , Brack_bgn_bry = new byte[] {Byte_ascii.Brack_bgn} + , Apos_bry = new byte[] {Byte_ascii.Apos} + , Pipe_bry = new byte[] {Byte_ascii.Pipe} + , Underline_bry = new byte[] {Byte_ascii.Underline} + , Asterisk_bry = new byte[] {Byte_ascii.Asterisk} + , Space_bry = new byte[] {Byte_ascii.Space} ; } diff --git a/100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_retain.java b/100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_preserve.java similarity index 71% rename from 100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_retain.java rename to 100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_preserve.java index e81a8e83e..162036ba3 100644 --- a/100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_retain.java +++ b/100_core/src_110_primitive/gplx/brys/Bry_fmtr_arg_bfr_preserve.java @@ -16,8 +16,8 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.brys; import gplx.*; -public class Bry_fmtr_arg_bfr_retain implements Bry_fmtr_arg { - public Bry_fmtr_arg_bfr_retain Data_(Bry_bfr v) {bfr = v; return this;} - public void XferAry(Bry_bfr trg, int idx) {trg.Add_bfr(bfr);} - public Bry_fmtr_arg_bfr_retain(Bry_bfr bfr) {this.bfr = bfr;} Bry_bfr bfr; +public class Bry_fmtr_arg_bfr_preserve implements Bry_fmtr_arg { + public Bry_fmtr_arg_bfr_preserve Data_(Bry_bfr v) {bfr = v; return this;} + public void XferAry(Bry_bfr trg, int idx) {trg.Add_bfr_and_preserve(bfr);} + public Bry_fmtr_arg_bfr_preserve(Bry_bfr bfr) {this.bfr = bfr;} Bry_bfr bfr; } diff --git a/100_core/src_140_list/gplx/Hash_adp_bry.java b/100_core/src_140_list/gplx/Hash_adp_bry.java index 2a3f027f8..88019b38b 100644 --- a/100_core/src_140_list/gplx/Hash_adp_bry.java +++ b/100_core/src_140_list/gplx/Hash_adp_bry.java @@ -16,18 +16,23 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx; +import gplx.intl.*; public class Hash_adp_bry extends gplx.lists.HashAdp_base implements HashAdp { - Hash_adp_bry(boolean case_match) { - this.case_match = case_match; - key_ref = new Hash_adp_bry_ref(case_match, null, -1, -1); - } private final boolean case_match; private Hash_adp_bry_ref key_ref; - public Object Get_by_bry(byte[] src) {return super.Fetch_base(key_ref.Src_all_(src));} - public Object Get_by_mid(byte[] src, int bgn, int end) {return super.Fetch_base(key_ref.Src_all_set_(src, bgn, end));} - public Hash_adp_bry Add_bry_bry(byte[] key) {this.Add_base(key, key); return this;} - public Hash_adp_bry Add_str_byte(String key, byte val) {this.Add_base(Bry_.new_utf8_(key), Byte_obj_val.new_(val)); return this;} - public Hash_adp_bry Add_str_obj(String key, Object val) {this.Add_base(Bry_.new_utf8_(key), val); return this;} - public Hash_adp_bry Add_bry_byte(byte[] key, byte val) {this.Add_base(key, Byte_obj_val.new_(val)); return this;} - public Hash_adp_bry Add_bry_obj(byte[] key, Object val) {this.Add_base(key, val); return this;} + private final Hash_adp_bry_itm_base proto, key_ref; + Hash_adp_bry(Hash_adp_bry_itm_base proto) { + this.proto = proto; + key_ref = proto.New(); + } + @Override protected Object Fetch_base(Object key) {return super.Fetch_base(key_ref.Init((byte[])key));} + @Override protected void Del_base(Object key) {super.Del_base(key_ref.Init((byte[])key));} + @Override protected boolean Has_base(Object key) {return super.Has_base(key_ref.Init((byte[])key));} + public Object Get_by_bry(byte[] src) {return super.Fetch_base(key_ref.Init(src));} + public Object Get_by_mid(byte[] src, int bgn, int end) {return super.Fetch_base(key_ref.Init(src, bgn, end));} + public Hash_adp_bry Add_bry_bry(byte[] key) {this.Add_base(key, key); return this;} + public Hash_adp_bry Add_str_byte(String key, byte val) {this.Add_base(Bry_.new_utf8_(key), Byte_obj_val.new_(val)); return this;} + public Hash_adp_bry Add_str_obj(String key, Object val) {this.Add_base(Bry_.new_utf8_(key), val); return this;} + public Hash_adp_bry Add_bry_byte(byte[] key, byte val) {this.Add_base(key, Byte_obj_val.new_(val)); return this;} + public Hash_adp_bry Add_bry_obj(byte[] key, Object val) {this.Add_base(key, val); return this;} public Hash_adp_bry Add_many_str(String... ary) { int ary_len = ary.length; for (int i = 0; i < ary_len; i++) { @@ -39,38 +44,57 @@ public class Hash_adp_bry extends gplx.lists.HashAdp_base implements HashAdp { } @Override protected void Add_base(Object key, Object val) { byte[] key_bry = (byte[])key; - super.Add_base(new Hash_adp_bry_ref(case_match, key_bry, 0, key_bry.length), val); + Hash_adp_bry_itm_base key_itm = proto.New(); + key_itm.Init(key_bry, 0, key_bry.length); + super.Add_base(key_itm, val); } - @Override protected void Del_base(Object key) {super.Del_base(key_ref.Src_all_((byte[])key));} - @Override protected boolean Has_base(Object key) {return super.Has_base(key_ref.Src_all_((byte[])key));} - @Override protected Object Fetch_base(Object key) {return super.Fetch_base(key_ref.Src_all_((byte[])key));} - public static Hash_adp_bry cs_() {return new Hash_adp_bry(true);} - public static Hash_adp_bry ci_() {return new Hash_adp_bry(false);} - public static Hash_adp_bry ci_ascii_() {return new Hash_adp_bry(false);} + public static Hash_adp_bry cs_() {return new Hash_adp_bry(Hash_adp_bry_itm_cs._);} + public static Hash_adp_bry ci_ascii_() {return new Hash_adp_bry(Hash_adp_bry_itm_ci_ascii._);} + public static Hash_adp_bry ci_utf8_(Gfo_case_mgr case_mgr) {return new Hash_adp_bry(Hash_adp_bry_itm_ci_utf8.get_or_new(case_mgr));} + public static Hash_adp_bry c__utf8_(boolean case_match, Gfo_case_mgr case_mgr) {return case_match ? cs_() : ci_utf8_(case_mgr);} + public static Hash_adp_bry ci_() {return new Hash_adp_bry(Hash_adp_bry_itm_ci_ascii._);} } -class Hash_adp_bry_ref { - public Hash_adp_bry_ref(boolean case_match, byte[] src, int src_bgn, int src_end) {this.case_match = case_match; this.src = src; this.src_bgn = src_bgn; this.src_end = src_end;} - final boolean case_match; - public byte[] Src() {return src;} private byte[] src; - public Hash_adp_bry_ref Src_all_(byte[] v) { - this.src = v; - this.src_bgn = 0; - this.src_end = v.length; - return this; - } - public Hash_adp_bry_ref Src_all_set_(byte[] v, int src_bgn, int src_end) { - this.src = v; - this.src_bgn = src_bgn; - this.src_end = src_end; - return this; - } - public int Src_bgn() {return src_bgn;} int src_bgn; - public int Src_end() {return src_end;} int src_end; +abstract class Hash_adp_bry_itm_base { + public abstract Hash_adp_bry_itm_base New(); + public Hash_adp_bry_itm_base Init(byte[] src) {return this.Init(src, 0, src.length);} + public abstract Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end); +} +class Hash_adp_bry_itm_cs extends Hash_adp_bry_itm_base { + private byte[] src; int src_bgn, src_end; + @Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_cs();} + @Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;} @Override public int hashCode() { int rv = 0; for (int i = src_bgn; i < src_end; i++) { int b_int = src[i] & 0xFF; // JAVA: patch - if (!case_match && b_int > 64 && b_int < 91) // 64=before A; 91=after Z; NOTE: lowering upper-case on PERF assumption that there will be more lower-case letters than upper-case + rv = (31 * rv) + b_int; + } + return rv; + } + @Override public boolean equals(Object obj) { + if (obj == null) return false; + Hash_adp_bry_itm_cs comp = (Hash_adp_bry_itm_cs)obj; + byte[] comp_src = comp.src; int comp_bgn = comp.src_bgn, comp_end = comp.src_end; + int comp_len = comp_end - comp_bgn, src_len = src_end - src_bgn; + if (comp_len != src_len) return false; + for (int i = 0; i < comp_len; i++) { + int src_pos = src_bgn + i; + if (src_pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc + if (src[src_pos] != comp_src[i + comp_bgn]) return false; + } + return true; + } + public static final Hash_adp_bry_itm_cs _ = new Hash_adp_bry_itm_cs(); Hash_adp_bry_itm_cs() {} +} +class Hash_adp_bry_itm_ci_ascii extends Hash_adp_bry_itm_base { + private byte[] src; int src_bgn, src_end; + @Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_ci_ascii();} + @Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;} + @Override public int hashCode() { + int rv = 0; + for (int i = src_bgn; i < src_end; i++) { + int b_int = src[i] & 0xFF; // JAVA: patch + if (b_int > 64 && b_int < 91) // 64=before A; 91=after Z; NOTE: lowering upper-case on PERF assumption that there will be more lower-case letters than upper-case b_int += 32; rv = (31 * rv) + b_int; } @@ -78,24 +102,77 @@ class Hash_adp_bry_ref { } @Override public boolean equals(Object obj) { if (obj == null) return false; - Hash_adp_bry_ref comp = (Hash_adp_bry_ref)obj; - byte[] comp_src = comp.Src(); int comp_bgn = comp.Src_bgn(), comp_end = comp.Src_end(); + Hash_adp_bry_itm_ci_ascii comp = (Hash_adp_bry_itm_ci_ascii)obj; + byte[] comp_src = comp.src; int comp_bgn = comp.src_bgn, comp_end = comp.src_end; int comp_len = comp_end - comp_bgn, src_len = src_end - src_bgn; if (comp_len != src_len) return false; for (int i = 0; i < comp_len; i++) { int src_pos = src_bgn + i; if (src_pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc - if (case_match) { - if (src[src_pos] != comp_src[i + comp_bgn]) return false; + byte src_byte = src[src_pos]; + if (src_byte > 64 && src_byte < 91) src_byte += 32; + byte comp_byte = comp_src[i + comp_bgn]; + if (comp_byte > 64 && comp_byte < 91) comp_byte += 32; + if (src_byte != comp_byte) return false; + } + return true; + } + public static final Hash_adp_bry_itm_ci_ascii _ = new Hash_adp_bry_itm_ci_ascii(); Hash_adp_bry_itm_ci_ascii() {} +} +class Hash_adp_bry_itm_ci_utf8 extends Hash_adp_bry_itm_base { + private final Gfo_case_mgr case_mgr; + Hash_adp_bry_itm_ci_utf8(Gfo_case_mgr case_mgr) {this.case_mgr = case_mgr;} + private byte[] src; int src_bgn, src_end; + @Override public Hash_adp_bry_itm_base New() {return new Hash_adp_bry_itm_ci_utf8(case_mgr);} + @Override public Hash_adp_bry_itm_base Init(byte[] src, int src_bgn, int src_end) {this.src = src; this.src_bgn = src_bgn; this.src_end = src_end; return this;} + @Override public int hashCode() { + int rv = 0; + for (int i = src_bgn; i < src_end; i++) { + byte b = src[i]; + int b_int = b & 0xFF; // JAVA: patch + Gfo_case_itm itm = case_mgr.Get_or_null(b, src, i, src_end); + if (itm == null) { // unknown itm; byte is a number, symbol, or unknown; just use the existing byte + } + else { // known itm; use its hash_code + b_int = itm.Hashcode_lo(); + i += itm.Len_lo() - 1; + } + rv = (31 * rv) + b_int; + } + return rv; + } + @Override public boolean equals(Object obj) { + if (obj == null) return false; + Hash_adp_bry_itm_ci_utf8 trg_itm = (Hash_adp_bry_itm_ci_utf8)obj; + byte[] trg = trg_itm.src; int trg_bgn = trg_itm.src_bgn, trg_end = trg_itm.src_end; + int trg_len = trg_end - trg_bgn, src_len = src_end - src_bgn; + if (trg_len != src_len) return false; + for (int i = 0; i < trg_len; i++) { // ASSUME: upper/lower have same width; i.e.: upper'ing a character doesn't go from a 2-width byte to a 3-width byte + int src_pos = src_bgn + i; + if (src_pos >= src_end) return false; // ran out of src; exit; EX: src=ab; find=abc + byte src_byte = src[src_pos]; + byte trg_byte = trg[i + trg_bgn]; + Gfo_case_itm src_case_itm = case_mgr.Get_or_null(src_byte, src, i, src_len); + Gfo_case_itm trg_case_itm = case_mgr.Get_or_null(trg_byte, trg, i, trg_len); + if (src_case_itm != null && trg_case_itm == null) return false; + else if (src_case_itm == null && trg_case_itm != null) return false; + else if (src_case_itm == null && trg_case_itm == null) { + if (src_byte != trg_byte) return false; } else { - byte src_byte = src[src_pos]; - if (src_byte > 64 && src_byte < 91) src_byte += 32; - byte comp_byte = comp_src[i + comp_bgn]; - if (comp_byte > 64 && comp_byte < 91) comp_byte += 32; - if (src_byte != comp_byte) return false; + if (!src_case_itm.Eq_lo(trg_case_itm)) return false; + i += src_case_itm.Len_lo() - 1; } } return true; } + public static Hash_adp_bry_itm_ci_utf8 get_or_new(Gfo_case_mgr case_mgr) { + switch (case_mgr.Tid()) { + case Gfo_case_mgr_.Tid_ascii: if (Itm_ascii == null) Itm_ascii = new Hash_adp_bry_itm_ci_utf8(case_mgr); return Itm_ascii; + case Gfo_case_mgr_.Tid_utf8: if (Itm_utf8 == null) Itm_utf8 = new Hash_adp_bry_itm_ci_utf8(case_mgr); return Itm_utf8; + case Gfo_case_mgr_.Tid_custom: return new Hash_adp_bry_itm_ci_utf8(case_mgr); + default: throw Err_.unhandled(case_mgr.Tid()); + } + } + private static Hash_adp_bry_itm_ci_utf8 Itm_ascii, Itm_utf8; } diff --git a/100_core/src_150_text/gplx/intl/Gfo_case_itm.java b/100_core/src_150_text/gplx/intl/Gfo_case_itm.java new file mode 100644 index 000000000..c3d7974ed --- /dev/null +++ b/100_core/src_150_text/gplx/intl/Gfo_case_itm.java @@ -0,0 +1,23 @@ +/* +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 . +*/ +package gplx.intl; import gplx.*; +public interface Gfo_case_itm { + boolean Eq_lo(Gfo_case_itm itm); + int Hashcode_lo(); + int Len_lo(); +} diff --git a/100_core/src_150_text/gplx/intl/Gfo_case_mgr.java b/100_core/src_150_text/gplx/intl/Gfo_case_mgr.java new file mode 100644 index 000000000..ee46b4c35 --- /dev/null +++ b/100_core/src_150_text/gplx/intl/Gfo_case_mgr.java @@ -0,0 +1,22 @@ +/* +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 . +*/ +package gplx.intl; import gplx.*; +public interface Gfo_case_mgr { + byte Tid(); + Gfo_case_itm Get_or_null(byte bgn_byte, byte[] src, int bgn, int end); +} diff --git a/100_core/src_150_text/gplx/intl/Gfo_case_mgr_.java b/100_core/src_150_text/gplx/intl/Gfo_case_mgr_.java new file mode 100644 index 000000000..6f026c305 --- /dev/null +++ b/100_core/src_150_text/gplx/intl/Gfo_case_mgr_.java @@ -0,0 +1,21 @@ +/* +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 . +*/ +package gplx.intl; import gplx.*; +public class Gfo_case_mgr_ { + public static final byte Tid_ascii = 0, Tid_utf8 = 1, Tid_custom = 2; +} diff --git a/150_gfui/src_300_gxw/gplx/gfui/Gxw_html.java b/150_gfui/src_300_gxw/gplx/gfui/Gxw_html.java index 278255ff2..b78eb65b3 100644 --- a/150_gfui/src_300_gxw/gplx/gfui/Gxw_html.java +++ b/150_gfui/src_300_gxw/gplx/gfui/Gxw_html.java @@ -24,6 +24,7 @@ public interface Gxw_html extends GxwElem { String Html_doc_selected_get_src_or_empty(); boolean Html_doc_find(String id, String find, boolean dir_fwd, boolean case_match, boolean wrap_find); void Html_doc_body_focus(); + void Html_doc_selection_focus_toggle(); String Html_elem_atr_get_str (String id, String atr_key); boolean Html_elem_atr_get_bool (String id, String atr_key); boolean Html_elem_atr_set (String id, String atr_key, String val); diff --git a/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html.java b/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html.java index b72fef49f..ea915317d 100644 --- a/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html.java +++ b/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html.java @@ -25,6 +25,7 @@ public class Gfui_html extends GfuiElemBase { public String Html_doc_selected_get_src_or_empty() {return under.Html_doc_selected_get_src_or_empty();} public boolean Html_doc_find(String elem_id, String find, boolean dir_fwd, boolean case_match, boolean wrap_find) {return under.Html_doc_find(elem_id, find, dir_fwd, case_match, wrap_find);} public void Html_doc_body_focus() {under.Html_doc_body_focus();} + public void Html_doc_selection_focus_toggle() {under.Html_doc_selection_focus_toggle();} @gplx.Virtual public String Html_elem_atr_get_str(String elem_id, String atr_key) {return under.Html_elem_atr_get_str(elem_id, atr_key);} @gplx.Virtual public boolean Html_elem_atr_get_bool(String elem_id, String atr_key) {return under.Html_elem_atr_get_bool(elem_id, atr_key);} public boolean Html_elem_atr_set(String elem_id, String atr_key, String v) {return under.Html_elem_atr_set(elem_id, atr_key, v);} diff --git a/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html_cfg.java b/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html_cfg.java index 4ad9b6204..246db8cd3 100644 --- a/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html_cfg.java +++ b/150_gfui/src_420_box_basic/gplx/gfui/Gfui_html_cfg.java @@ -19,6 +19,7 @@ package gplx.gfui; import gplx.*; public class Gfui_html_cfg implements GfoInvkAble { public String Doc_html() {return Exec_fmt(fmtr_doc_html);} private Bry_fmtr fmtr_doc_html = Bry_fmtr.new_(); public String Doc_body_focus() {return Exec_fmt(fmtr_doc_body_focus);} private Bry_fmtr fmtr_doc_body_focus = Bry_fmtr.new_(); + public String Doc_selection_focus_toggle() {return Exec_fmt(fmtr_doc_selection_focus_toggle);} private Bry_fmtr fmtr_doc_selection_focus_toggle = Bry_fmtr.new_(); public String Doc_selected_get_text_or_href() {return Exec_fmt(fmtr_doc_selected_get_text_or_href);} private Bry_fmtr fmtr_doc_selected_get_text_or_href = Bry_fmtr.keys_(); public String Doc_selected_get_href_or_text() {return Exec_fmt(fmtr_doc_selected_get_href_or_text);} private Bry_fmtr fmtr_doc_selected_get_href_or_text = Bry_fmtr.keys_(); public String Doc_selected_get_src_or_empty() {return Exec_fmt(fmtr_doc_selected_get_src_or_empty);} private Bry_fmtr fmtr_doc_selected_get_src_or_empty = Bry_fmtr.keys_(); @@ -63,6 +64,7 @@ public class Gfui_html_cfg implements GfoInvkAble { public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_doc_html_)) fmtr_doc_html.Fmt_(m.ReadBry("v")); else if (ctx.Match(k, Invk_doc_body_focus_)) fmtr_doc_body_focus.Fmt_(m.ReadBry("v")); + else if (ctx.Match(k, Invk_doc_selection_focus_toggle_)) fmtr_doc_selection_focus_toggle.Fmt_(m.ReadBry("v")); else if (ctx.Match(k, Invk_doc_selected_get_text_or_href_)) fmtr_doc_selected_get_text_or_href.Fmt_(m.ReadBry("v")); else if (ctx.Match(k, Invk_doc_selected_get_href_or_text_)) fmtr_doc_selected_get_href_or_text.Fmt_(m.ReadBry("v")); else if (ctx.Match(k, Invk_doc_selected_get_src_or_empty_)) fmtr_doc_selected_get_src_or_empty.Fmt_(m.ReadBry("v")); @@ -95,7 +97,8 @@ public class Gfui_html_cfg implements GfoInvkAble { node_path.Val_(node_path_val); } public static final String Invk_debug_file_ = "debug_file_" - , Invk_doc_html_ = "doc_html_", Invk_doc_body_focus_ = "doc_body_focus_", Invk_doc_active_atr_get_ = "doc_active_atr_get_", Invk_doc_find_html_ = "doc_find_html_", Invk_doc_find_edit_ = "doc_find_edit_" + , Invk_doc_html_ = "doc_html_", Invk_doc_body_focus_ = "doc_body_focus_", Invk_doc_selection_focus_toggle_ = "doc_selection_focus_toggle_" + , Invk_doc_active_atr_get_ = "doc_active_atr_get_", Invk_doc_find_html_ = "doc_find_html_", Invk_doc_find_edit_ = "doc_find_edit_" , Invk_doc_selected_get_text_or_href_ = "doc_selected_get_text_or_href_", Invk_doc_selected_get_href_or_text_ = "doc_selected_get_href_or_text_", Invk_doc_selected_get_src_or_empty_ = "doc_selected_get_src_or_empty_" , Invk_win_print_preview_ = "win_print_preview_" , Invk_elem_atr_get_ = "elem_atr_get_", Invk_elem_atr_get_toString_ = "elem_atr_get_toString_", Invk_elem_atr_set_ = "elem_atr_set_", Invk_elem_atr_set_append_ = "elem_atr_set_append_" diff --git a/150_gfui/src_700_env/gplx/gfui/Mem_html.java b/150_gfui/src_700_env/gplx/gfui/Mem_html.java index 4322552b5..fc053d741 100644 --- a/150_gfui/src_700_env/gplx/gfui/Mem_html.java +++ b/150_gfui/src_700_env/gplx/gfui/Mem_html.java @@ -62,6 +62,7 @@ class Mem_html extends GxwTextMemo_lang implements Gxw_html { public String Htm return rv == null ? or : rv; } public void Html_doc_body_focus() {} + public void Html_doc_selection_focus_toggle() {} public String Html_window_vpos() {return "";} public boolean Html_window_vpos_(String v) {return true;} public boolean Html_elem_focus(String v) {return true;} diff --git a/150_gfui/xtn/gplx/gfui/Swt_html.java b/150_gfui/xtn/gplx/gfui/Swt_html.java index 50dd303ba..42b787a1a 100644 --- a/150_gfui/xtn/gplx/gfui/Swt_html.java +++ b/150_gfui/xtn/gplx/gfui/Swt_html.java @@ -52,6 +52,7 @@ class Swt_html implements Gxw_html, Swt_control, FocusListener { public String Html_doc_selected_get_href_or_text() {return Eval_script_as_str(kit.Html_cfg().Doc_selected_get_href_or_text());} public String Html_doc_selected_get_src_or_empty() {return Eval_script_as_str(kit.Html_cfg().Doc_selected_get_src_or_empty());} public void Html_doc_body_focus() {Eval_script_as_exec(kit.Html_cfg().Doc_body_focus());} + public void Html_doc_selection_focus_toggle() {Eval_script_as_exec(kit.Html_cfg().Doc_selection_focus_toggle());} public String Html_elem_atr_get_str(String elem_id, String atr_key) {return Eval_script_as_str(kit.Html_cfg().Elem_atr_get(elem_id, atr_key));} public boolean Html_elem_atr_get_bool(String elem_id, String atr_key) {return Bool_.parse_((String)Eval_script(kit.Html_cfg().Elem_atr_get_toString(elem_id, atr_key)));} public Object Html_elem_atr_get_obj(String elem_id, String atr_key) {return Eval_script(kit.Html_cfg().Elem_atr_get(elem_id, atr_key));} diff --git a/400_xowa/src/gplx/core/regxs/Gfo_pattern.java b/400_xowa/src/gplx/core/regxs/Gfo_pattern.java new file mode 100644 index 000000000..d4317b4be --- /dev/null +++ b/400_xowa/src/gplx/core/regxs/Gfo_pattern.java @@ -0,0 +1,50 @@ +/* +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 . +*/ +package gplx.core.regxs; import gplx.*; import gplx.core.*; +public class Gfo_pattern { + private Gfo_pattern_itm[] itms; int itms_len; + public Gfo_pattern(byte[] raw) { + this.raw = raw; + itms = Gfo_pattern_itm_.Compile(raw); + itms_len = itms.length; + } + public byte[] Raw() {return raw;} private byte[] raw; + private Gfo_pattern_ctx ctx = new Gfo_pattern_ctx(); + public boolean Match(byte[] val) { + int val_len = val.length; + int val_pos = 0; + ctx.Init(itms_len); + for (int i = 0; i < itms_len; ++i) { + Gfo_pattern_itm itm = itms[i]; + ctx.Itm_idx_(i); + val_pos = itm.Match(ctx, val, val_len, val_pos); + if (!ctx.Rslt_pass()) return false; + } + return ctx.Rslt_pass() && val_pos == val_len; + } + public static Gfo_pattern[] Parse_to_ary(byte[] raw) { + byte[][] patterns = Bry_.Split(raw, Byte_ascii.Semic, true); + int patterns_len = patterns.length; + Gfo_pattern[] rv = new Gfo_pattern[patterns_len]; + for (int i = 0; i < patterns_len; ++i) { + byte[] pattern = patterns[i]; + rv[i] = new Gfo_pattern(pattern); + } + return rv; + } +} diff --git a/400_xowa/src/gplx/core/regxs/Gfo_pattern_ctx.java b/400_xowa/src/gplx/core/regxs/Gfo_pattern_ctx.java new file mode 100644 index 000000000..b7319ff31 --- /dev/null +++ b/400_xowa/src/gplx/core/regxs/Gfo_pattern_ctx.java @@ -0,0 +1,30 @@ +/* +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 . +*/ +package gplx.core.regxs; import gplx.*; import gplx.core.*; +public class Gfo_pattern_ctx { + public boolean Rslt_pass() {return rslt;} private boolean rslt; + public void Rslt_fail_() {rslt = false;} + public boolean Prv_was_wild() {return prv_was_wild;} public void Prv_was_wild_(boolean v) {prv_was_wild = v;} private boolean prv_was_wild; + private int itm_len; + public int Itm_idx() {return itm_idx;} public void Itm_idx_(int v) {itm_idx = v;} private int itm_idx; + public boolean Itm_idx_is_last() {return itm_idx == itm_len - 1;} + public void Init(int itm_len) { + rslt = true; + this.itm_len = itm_len; + } +} diff --git a/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm.java b/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm.java new file mode 100644 index 000000000..8fedbf415 --- /dev/null +++ b/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm.java @@ -0,0 +1,63 @@ +/* +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 . +*/ +package gplx.core.regxs; import gplx.*; import gplx.core.*; +public interface Gfo_pattern_itm { + byte Tid(); + void Compile(byte[] src, int bgn, int end); + int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos); + void Xto_str(String_bldr sb); +} +class Gfo_pattern_itm_text implements Gfo_pattern_itm { + public Gfo_pattern_itm_text() {} + public byte Tid() {return Gfo_pattern_itm_.Tid_text;} + public byte[] Text() {return text;} private byte[] text; private int text_len; + public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|" + String_.new_utf8_(text));} + public void Compile(byte[] src, int bgn, int end) { + this.text = Bry_.Mid(src, bgn, end); + this.text_len = end - bgn; + } + public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) { + boolean pass = false; + int text_end = pos + text_len; + if (text_end > src_len) text_end = src_len; + if (ctx.Prv_was_wild()) { + int text_bgn = Bry_finder.Find_fwd(src, text, pos); + pass = text_bgn != Bry_finder.Not_found; + if (pass) + pos = text_bgn + text_len; + } + else { + pass = Bry_.Match(src, pos, text_end, text); + if (pass) + pos = text_end; + } + if (!pass) ctx.Rslt_fail_(); + ctx.Prv_was_wild_(false); + return pos; + } +} +class Gfo_pattern_itm_wild implements Gfo_pattern_itm { + public byte Tid() {return Gfo_pattern_itm_.Tid_wild;} + public void Compile(byte[] src, int bgn, int end) {} + public int Match(Gfo_pattern_ctx ctx, byte[] src, int src_len, int pos) { + ctx.Prv_was_wild_(true); + return ctx.Itm_idx_is_last() ? src_len : pos; + } + public void Xto_str(String_bldr sb) {sb.Add(this.Tid()).Add("|*");} + public static final Gfo_pattern_itm_wild _ = new Gfo_pattern_itm_wild(); Gfo_pattern_itm_wild() {} +} diff --git a/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm_.java b/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm_.java new file mode 100644 index 000000000..fa3f439f3 --- /dev/null +++ b/400_xowa/src/gplx/core/regxs/Gfo_pattern_itm_.java @@ -0,0 +1,51 @@ +/* +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 . +*/ +package gplx.core.regxs; import gplx.*; import gplx.core.*; +public class Gfo_pattern_itm_ { + public static final byte Tid_text = 0, Tid_wild = 1; + public static Gfo_pattern_itm[] Compile(byte[] raw) { + ListAdp rv = ListAdp_.new_(); + int raw_len = raw.length; + int itm_bgn = -1; + Gfo_pattern_itm itm = null; + int pos = 0; + while (true) { + boolean last = pos == raw_len; + byte b = last ? Byte_ascii.Nil : raw[pos]; + switch (b) { + case Byte_ascii.Nil: + if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null;} + break; + case Byte_ascii.Asterisk: + if (itm != null) {itm.Compile(raw, itm_bgn, pos); itm = null;} + rv.Add(Gfo_pattern_itm_wild._); + break; + default: + if (itm_bgn == -1) { + itm_bgn = pos; + itm = new Gfo_pattern_itm_text(); + rv.Add(itm); + } + break; + } + ++pos; + if (last) break; + } + return (Gfo_pattern_itm[])rv.XtoAryAndClear(Gfo_pattern_itm.class); + } +} diff --git a/400_xowa/src/gplx/core/regxs/Gfo_pattern_tst.java b/400_xowa/src/gplx/core/regxs/Gfo_pattern_tst.java new file mode 100644 index 000000000..bb68e689e --- /dev/null +++ b/400_xowa/src/gplx/core/regxs/Gfo_pattern_tst.java @@ -0,0 +1,83 @@ +/* +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 . +*/ +package gplx.core.regxs; import gplx.*; import gplx.core.*; +import org.junit.*; +public class Gfo_pattern_tst { + @Before public void init() {fxt.Clear();} private Gfo_pattern_itm_fxt fxt = new Gfo_pattern_itm_fxt(); + @Test public void Compile() { + fxt.Test_Compile("a" , fxt.itm_text_("a")); + fxt.Test_Compile("*" , fxt.itm_wild_()); + fxt.Test_Compile("a*" , fxt.itm_text_("a"), fxt.itm_wild_()); + fxt.Test_Compile("*a" , fxt.itm_wild_(), fxt.itm_text_("a")); + fxt.Test_Compile("*ab*" , fxt.itm_wild_(), fxt.itm_text_("ab"), fxt.itm_wild_()); + fxt.Test_Compile("" ); + } + @Test public void Match() { + Gfo_pattern pattern = fxt.pattern_("abc"); + fxt.Test_Match_y(pattern, "abc"); + fxt.Test_Match_n(pattern, "ab", "a", "bc", "Abc", ""); + } + @Test public void Match_all() { + Gfo_pattern pattern = fxt.pattern_("*"); + fxt.Test_Match_y(pattern, "a", "abc", ""); + } + @Test public void Match_bgn() { + Gfo_pattern pattern = fxt.pattern_("abc*"); + fxt.Test_Match_y(pattern, "abc", "abcdef"); + fxt.Test_Match_n(pattern, "abd", "aabc", ""); + } + @Test public void Match_end() { + Gfo_pattern pattern = fxt.pattern_("*abc"); + fxt.Test_Match_y(pattern, "abc", "xyzabc"); + fxt.Test_Match_n(pattern, "abcd", ""); + } +} +class Gfo_pattern_itm_fxt { + public void Clear() {} + public Gfo_pattern pattern_(String raw) {return new Gfo_pattern(Bry_.new_utf8_(raw));} + public void Test_Match_y(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.Y);} + public void Test_Match_n(Gfo_pattern pattern, String... itms) {Test_Match(pattern, itms, Bool_.N);} + private void Test_Match(Gfo_pattern pattern, String[] itms, boolean expd) { + int len = itms.length; + for (int i = 0; i < len; i++) { + String itm = itms[i]; + Tfds.Eq(expd, pattern.Match(Bry_.new_utf8_(itm)), "pattern={0} itm={1} expd={2}", String_.new_utf8_(pattern.Raw()), itm, expd); + } + } + public Gfo_pattern_itm_wild itm_wild_() {return Gfo_pattern_itm_wild._;} + public Gfo_pattern_itm_text itm_text_(String raw) { + Gfo_pattern_itm_text rv = new Gfo_pattern_itm_text(); + byte[] bry = Bry_.new_utf8_(raw); + rv.Compile(bry, 0, bry.length); + return rv; + } + public void Test_Compile(String raw, Gfo_pattern_itm... expd) { + Gfo_pattern_itm[] actl = Gfo_pattern_itm_.Compile(Bry_.new_utf8_(raw)); + Tfds.Eq(Ary_xto_str(expd), Ary_xto_str(actl)); + } + private static String Ary_xto_str(Gfo_pattern_itm[] ary) { + int len = ary.length; + String_bldr sb = String_bldr_.new_(); + for (int i = 0; i < len; i++) { + if (i != 0) sb.Add_char_nl(); + Gfo_pattern_itm itm = ary[i]; + itm.Xto_str(sb); + } + return sb.XtoStrAndClear(); + } +} diff --git a/400_xowa/src/gplx/gfs/Gfs_parser_tst.java b/400_xowa/src/gplx/gfs/Gfs_parser_tst.java index 27ff6362a..116dd9081 100644 --- a/400_xowa/src/gplx/gfs/Gfs_parser_tst.java +++ b/400_xowa/src/gplx/gfs/Gfs_parser_tst.java @@ -184,7 +184,7 @@ class Gfs_parser_fxt { } private void To_str_atr(Bry_bfr bfr, Bry_bfr path_bfr, byte[] src, byte[] name, byte[] val, int val_bgn, int val_end) { if (val == null && val_bgn == -1 && val_end == -1) return; - bfr.Add_bfr(path_bfr).Add_byte(Byte_ascii.Colon); + bfr.Add_bfr_and_preserve(path_bfr).Add_byte(Byte_ascii.Colon); bfr.Add(name); if (val == null) bfr.Add_mid(src, val_bgn, val_end); diff --git a/400_xowa/src/gplx/html/Html_atrs.java b/400_xowa/src/gplx/html/Html_atr_.java similarity index 96% rename from 400_xowa/src/gplx/html/Html_atrs.java rename to 400_xowa/src/gplx/html/Html_atr_.java index bb3e75ca0..5197ceec0 100644 --- a/400_xowa/src/gplx/html/Html_atrs.java +++ b/400_xowa/src/gplx/html/Html_atr_.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.html; import gplx.*; -public class Html_atrs { +public class Html_atr_ { public static final String Src_str = "src" ; diff --git a/400_xowa/src/gplx/html/Html_consts.java b/400_xowa/src/gplx/html/Html_entity_.java similarity index 58% rename from 400_xowa/src/gplx/html/Html_consts.java rename to 400_xowa/src/gplx/html/Html_entity_.java index 4274f1626..6d4c51aa2 100644 --- a/400_xowa/src/gplx/html/Html_consts.java +++ b/400_xowa/src/gplx/html/Html_entity_.java @@ -16,27 +16,19 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.html; import gplx.*; -public class Html_consts { - public static final String Nl_str = " "; +public class Html_entity_ { public static final String - Comm_bgn_str = "" - , Img_str = "img" + Nl_str = " " ; public static final byte[] - Lt = Bry_.new_ascii_("<"), Gt = Bry_.new_ascii_(">") - , Amp = Bry_.new_ascii_("&"), Quote = Bry_.new_ascii_("""), Apos = Bry_.new_ascii_("'") - , Eq = Bry_.new_ascii_("=") + Lt_bry = Bry_.new_ascii_("<"), Gt_bry = Bry_.new_ascii_(">") + , Amp_bry = Bry_.new_ascii_("&"), Quote_bry = Bry_.new_ascii_(""") + , Apos_num_bry = Bry_.new_ascii_("'") + , Apos_key_bry = Bry_.new_ascii_("'") + , Eq_bry = Bry_.new_ascii_("=") , Nl_bry = Bry_.new_ascii_(Nl_str), Space_bry = Bry_.new_ascii_(" ") - , Comm_bgn = Bry_.new_ascii_(Comm_bgn_str), Comm_end = Bry_.new_ascii_(Comm_end_str) - , Hr_bry = Bry_.new_ascii_("
") - , Br_bry = Bry_.new_ascii_("
") - , Td_bgn_bry = Bry_.new_ascii_("") - , Td_end_bry = Bry_.new_ascii_("") - , Ul_tag_bry = Bry_.new_ascii_("ul") - ; - public static final int - Comm_bgn_len = Comm_bgn.length - , Comm_end_len = Comm_end.length + , Pipe_bry = Bry_.new_ascii_("|") + , Colon_bry = Bry_.new_ascii_(":"), Underline_bry = Bry_.new_ascii_("_"), Asterisk_bry = Bry_.new_ascii_("*") + , Brack_bgn_bry = Bry_.new_ascii_("[") ; } diff --git a/400_xowa/src/gplx/html/Html_tags.java b/400_xowa/src/gplx/html/Html_tag_.java similarity index 75% rename from 400_xowa/src/gplx/html/Html_tags.java rename to 400_xowa/src/gplx/html/Html_tag_.java index 8ab6e61cb..612cbeae9 100644 --- a/400_xowa/src/gplx/html/Html_tags.java +++ b/400_xowa/src/gplx/html/Html_tag_.java @@ -16,10 +16,9 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.html; import gplx.*; -public class Html_tags { - public static final String - A_str = "a" - , Img_str = "img" +public class Html_tag_ { + public static final byte[] + Ul_name_bry = Bry_.new_ascii_("ul") ; public static final byte[] Body_lhs = Bry_.new_ascii_("") @@ -32,5 +31,17 @@ public class Html_tags { , Script_lhs = Bry_.new_ascii_("") + , Hr_bry = Bry_.new_ascii_("
") + ; + public static final String + Comm_bgn_str = "" + ; + public static final byte[] + Comm_bgn = Bry_.new_ascii_(Comm_bgn_str), Comm_end = Bry_.new_ascii_(Comm_end_str) + ; + public static final int + Comm_bgn_len = Comm_bgn.length + , Comm_end_len = Comm_end.length ; } diff --git a/400_xowa/src/gplx/html/Html_utl.java b/400_xowa/src/gplx/html/Html_utl.java index 447023623..9b94af9e6 100644 --- a/400_xowa/src/gplx/html/Html_utl.java +++ b/400_xowa/src/gplx/html/Html_utl.java @@ -17,23 +17,25 @@ along with this program. If not, see . */ package gplx.html; import gplx.*; public class Html_utl { - public static byte[] Escape_for_atr_val_as_bry(String s, byte quote_byte) { - Bry_bfr tmp_bfr = null; + public static byte[] Escape_for_atr_val_as_bry(Bry_bfr tmp_bfr, byte quote_byte, String s) { if (s == null) return null; byte[] bry = Bry_.new_utf8_(s); + int bry_len = bry.length; + boolean dirty = Escape_for_atr_val_as_bry(tmp_bfr, quote_byte, bry, 0, bry_len); + return dirty ? tmp_bfr.XtoAryAndClear() : bry; + } + public static boolean Escape_for_atr_val_as_bry(Bry_bfr tmp_bfr, byte quote_byte, byte[] src, int bgn, int end) { boolean dirty = false; - int len = bry.length; - for (int i = 0; i < len; i++) { - byte b = bry[i]; + for (int i = bgn; i < end; i++) { + byte b = src[i]; if (b == quote_byte) { if (!dirty) { - tmp_bfr = Bry_bfr.reset_(256); - tmp_bfr.Add_mid(bry, 0, i); + tmp_bfr.Add_mid(src, bgn, i); dirty = true; } switch (quote_byte) { - case Byte_ascii.Apos: tmp_bfr.Add(Html_consts.Apos); break; - case Byte_ascii.Quote: tmp_bfr.Add(Html_consts.Quote); break; + case Byte_ascii.Apos: tmp_bfr.Add(Html_entity_.Apos_num_bry); break; + case Byte_ascii.Quote: tmp_bfr.Add(Html_entity_.Quote_bry); break; default: throw Err_.unhandled(quote_byte); } } @@ -42,7 +44,7 @@ public class Html_utl { tmp_bfr.Add_byte(b); } } - return dirty ? tmp_bfr.XtoAryAndClear() : bry; + return dirty; } public static String Escape_html_as_str(String v) {return String_.new_utf8_(Escape_html_as_bry(Bry_.new_utf8_(v)));} public static byte[] Escape_html_as_bry(Bry_bfr tmp, byte[] bry) {return Escape_html(false, tmp, bry, 0, bry.length, true, true, true, true, true);} @@ -60,11 +62,11 @@ public class Html_utl { for (int i = bgn; i < end; i++) { byte b = bry[i]; switch (b) { - case Byte_ascii.Lt: if (escape_lt) escaped = Html_consts.Lt; break; - case Byte_ascii.Gt: if (escape_gt) escaped = Html_consts.Gt; break; - case Byte_ascii.Amp: if (escape_amp) escaped = Html_consts.Amp; break; - case Byte_ascii.Quote: if (escape_quote) escaped = Html_consts.Quote; break; - case Byte_ascii.Apos: if (escape_apos) escaped = Html_consts.Apos; break; + case Byte_ascii.Lt: if (escape_lt) escaped = Html_entity_.Lt_bry; break; + case Byte_ascii.Gt: if (escape_gt) escaped = Html_entity_.Gt_bry; break; + case Byte_ascii.Amp: if (escape_amp) escaped = Html_entity_.Amp_bry; break; + case Byte_ascii.Quote: if (escape_quote) escaped = Html_entity_.Quote_bry; break; + case Byte_ascii.Apos: if (escape_apos) escaped = Html_entity_.Apos_num_bry; break; default: if (dirty || write_to_bfr) bfr.Add_byte(b); @@ -91,11 +93,11 @@ public class Html_utl { } private static final ByteTrieMgr_slim unescape_trie = ByteTrieMgr_slim.ci_ascii_() - .Add_bry_bval(Html_consts.Lt , Byte_ascii.Lt) - .Add_bry_bval(Html_consts.Gt , Byte_ascii.Gt) - .Add_bry_bval(Html_consts.Amp , Byte_ascii.Amp) - .Add_bry_bval(Html_consts.Quote , Byte_ascii.Quote) - .Add_bry_bval(Html_consts.Apos , Byte_ascii.Apos) + .Add_bry_bval(Html_entity_.Lt_bry , Byte_ascii.Lt) + .Add_bry_bval(Html_entity_.Gt_bry , Byte_ascii.Gt) + .Add_bry_bval(Html_entity_.Amp_bry , Byte_ascii.Amp) + .Add_bry_bval(Html_entity_.Quote_bry , Byte_ascii.Quote) + .Add_bry_bval(Html_entity_.Apos_num_bry , Byte_ascii.Apos) ; public static String Unescape_as_str(String src) { Bry_bfr bfr = Bry_bfr.reset_(255); @@ -149,18 +151,18 @@ public class Html_utl { public static byte[] Del_comments(Bry_bfr bfr, byte[] src, int pos, int end) { while (true) { if (pos >= end) break; - int comm_bgn = Bry_finder.Find_fwd(src, Html_consts.Comm_bgn, pos); // look for + int comm_end = Bry_finder.Find_fwd(src, Html_tag_.Comm_end, comm_bgn + Html_tag_.Comm_bgn_len); // look for --> if (comm_end == Bry_finder.Not_found) { // not found; consume rest bfr.Add_mid(src, pos, end); break; } bfr.Add_mid(src, pos, comm_bgn); // add everything between pos and comm_bgn - pos = comm_end + Html_consts.Comm_end_len; // reposition pos after comm_end + pos = comm_end + Html_tag_.Comm_end_len; // reposition pos after comm_end } return bfr.XtoAryAndClear(); } diff --git a/400_xowa/src/gplx/html/Html_utl_tst.java b/400_xowa/src/gplx/html/Html_utl_tst.java index b1d1b7a2e..c71aca609 100644 --- a/400_xowa/src/gplx/html/Html_utl_tst.java +++ b/400_xowa/src/gplx/html/Html_utl_tst.java @@ -51,7 +51,7 @@ class Html_utl_fxt { Tfds.Eq(expd, String_.new_ascii_(actl)); } public void Test_escape_for_atr(String src, boolean quote_is_apos, String expd) { - byte[] actl = Html_utl.Escape_for_atr_val_as_bry(src, quote_is_apos ? Byte_ascii.Apos : Byte_ascii.Quote); + byte[] actl = Html_utl.Escape_for_atr_val_as_bry(tmp_bfr, quote_is_apos ? Byte_ascii.Apos : Byte_ascii.Quote, src); Tfds.Eq(expd, String_.new_utf8_(actl)); } public void Test_unescape_html(boolean lt, boolean gt, boolean amp, boolean quote, boolean apos, String src, String expd) { diff --git a/400_xowa/src/gplx/srls/dsvs/Dsv_wkr_base.java b/400_xowa/src/gplx/srls/dsvs/Dsv_wkr_base.java index b7af2bec2..26766a3fb 100644 --- a/400_xowa/src/gplx/srls/dsvs/Dsv_wkr_base.java +++ b/400_xowa/src/gplx/srls/dsvs/Dsv_wkr_base.java @@ -26,7 +26,9 @@ public abstract class Dsv_wkr_base implements GfoInvkAble { tbl_parser.Init(this, this.Fld_parsers()); tbl_parser.Parse(src); tbl_parser.Rls(); + Load_by_bry_end(); } + @gplx.Virtual public void Load_by_bry_end() {} public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_load_by_str)) Load_by_bry(m.ReadBry("v")); else return GfoInvkAble_.Rv_unhandled; diff --git a/400_xowa/src/gplx/xowa/Xoa_app_.java b/400_xowa/src/gplx/xowa/Xoa_app_.java index 9f688cf0c..c86c6f2e0 100644 --- a/400_xowa/src/gplx/xowa/Xoa_app_.java +++ b/400_xowa/src/gplx/xowa/Xoa_app_.java @@ -23,7 +23,7 @@ public class Xoa_app_ { boot_mgr.Run(args); } public static final String Name = "xowa"; - public static final String Version = "1.6.5.1"; + public static final String Version = "1.7.1.1"; public static String Build_date = "2012-12-30 00:00:00"; public static String Op_sys; public static String User_agent = ""; diff --git a/400_xowa/src/gplx/xowa/Xoa_app_fxt.java b/400_xowa/src/gplx/xowa/Xoa_app_fxt.java index 7e7e1a8fc..03b6e880b 100644 --- a/400_xowa/src/gplx/xowa/Xoa_app_fxt.java +++ b/400_xowa/src/gplx/xowa/Xoa_app_fxt.java @@ -36,7 +36,7 @@ public class Xoa_app_fxt { public static Xow_wiki wiki_(Xoa_app app, String key) {return wiki_(app, key, app.Lang_mgr().Lang_en());} public static Xow_wiki wiki_(Xoa_app app, String key, Xol_lang lang) { Io_url wiki_dir = app.Fsys_mgr().Wiki_dir().GenSubDir(key); - Xow_wiki rv = new Xow_wiki(app, wiki_dir, Xow_ns_mgr_.default_(), lang); + Xow_wiki rv = new Xow_wiki(app, wiki_dir, Xow_ns_mgr_.default_(lang.Case_mgr()), lang); rv.File_mgr().Meta_mgr().Depth_(2); // TEST: written for 2 depth rv.Props().Main_page_(Xoa_page_.Main_page_bry); // TEST: default to Main Page (nothing tests loading Main Page from wiki.gfs) rv.Ns_mgr().Ids_get_or_null(Xow_ns_.Id_main).Subpages_enabled_(true); diff --git a/400_xowa/src/gplx/xowa/apis/xowa/gui/browsers/Xoapi_html_box.java b/400_xowa/src/gplx/xowa/apis/xowa/gui/browsers/Xoapi_html_box.java index 30866d09e..fd598d68d 100644 --- a/400_xowa/src/gplx/xowa/apis/xowa/gui/browsers/Xoapi_html_box.java +++ b/400_xowa/src/gplx/xowa/apis/xowa/gui/browsers/Xoapi_html_box.java @@ -27,10 +27,16 @@ public class Xoapi_html_box implements GfoInvkAble { if (tab.View_mode() != Xog_page_mode.Tid_read) // if edit / html, place focus in edit box html_box.Html_elem_focus(Xog_html_itm.Elem_id__xowa_edit_data_box); } + public void Selection_focus() { + Xog_tab_itm tab = win.Active_tab(); if (tab == Xog_tab_itm_.Null) return; + Gfui_html html_box = tab.Html_itm().Html_box(); + html_box.Html_doc_selection_focus_toggle(); + } public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_focus)) this.Focus(); + else if (ctx.Match(k, Invk_selection_focus_toggle)) this.Selection_focus(); else return GfoInvkAble_.Rv_unhandled; return this; } - private static final String Invk_focus = "focus"; + private static final String Invk_focus = "focus", Invk_selection_focus_toggle = "selection_focus_toggle"; } diff --git a/400_xowa/src/gplx/xowa/apis/xowa/html/modules/Xoapi_popups.java b/400_xowa/src/gplx/xowa/apis/xowa/html/modules/Xoapi_popups.java index 418a81e2d..4f543e616 100644 --- a/400_xowa/src/gplx/xowa/apis/xowa/html/modules/Xoapi_popups.java +++ b/400_xowa/src/gplx/xowa/apis/xowa/html/modules/Xoapi_popups.java @@ -24,25 +24,33 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { } public GfoEvMgr EvMgr() {return evMgr;} private GfoEvMgr evMgr; public void Init_by_app(Xoa_app app) {this.app = app;} - public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled = false; - public int Show_init_word_count() {return show_init_word_count;} private int show_init_word_count = Dflt_show_init_word_count; - public int Show_more_word_count() {return show_more_word_count;} private int show_more_word_count = Dflt_show_more_word_count; - public int Show_all_if_less_than() {return show_all_if_less_than;} public void Show_all_if_less_than_(int v) {show_all_if_less_than = v;} private int show_all_if_less_than = Dflt_show_all_if_less_than; - public byte[] Html_fmt() {return html_fmt;} private byte[] html_fmt = Dflt_html_fmt; - public byte[] Html_fmt_dflt() {return html_fmt_dflt;} private byte[] html_fmt_dflt = Dflt_html_fmt; - public int Win_show_delay() {return win_show_delay;} private int win_show_delay = Dflt_win_show_delay; - public int Win_hide_delay() {return win_hide_delay;} private int win_hide_delay = Dflt_win_hide_delay; - public int Win_max_w() {return win_max_w;} private int win_max_w = Dflt_win_max_w; - public int Win_max_h() {return win_max_h;} private int win_max_h = Dflt_win_max_h; - public int Win_show_all_max_w() {return win_show_all_max_w;} private int win_show_all_max_w = Dflt_win_show_all_max_w; - public boolean Win_bind_focus_blur() {return win_bind_focus_blur;} private boolean win_bind_focus_blur = Dflt_win_bind_focus_blur; - public byte[] Xnde_ignore_ids() {return xnde_ignore_ids;} private byte[] xnde_ignore_ids = Dflt_coordinates; - public int Scan_len() {return scan_len;} private int scan_len = Dflt_scan_len; - public int Scan_max() {return scan_max;} private int scan_max = Dflt_scan_max; - public byte[] Ns_allowed() {return ns_allowed;} private byte[] ns_allowed = Dflt_ns_allowed; - public int Read_til_stop_fwd() {return read_til_stop_fwd;} private int read_til_stop_fwd = Dflt_read_til_stop_fwd; - public int Read_til_stop_bwd() {return read_til_stop_bwd;} private int read_til_stop_bwd = Dflt_read_til_stop_bwd; - public int Tmpl_tkn_max() {return tmpl_tkn_max;} private int tmpl_tkn_max = Dflt_tmpl_tkn_max; + public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled = true; + public int Show_init_word_count() {return show_init_word_count;} private int show_init_word_count = Dflt_show_init_word_count; + public int Show_more_word_count() {return show_more_word_count;} private int show_more_word_count = Dflt_show_more_word_count; + public int Show_all_if_less_than() {return show_all_if_less_than;} private int show_all_if_less_than = Dflt_show_all_if_less_than; + public int Win_show_delay() {return win_show_delay;} private int win_show_delay = Dflt_win_show_delay; + public int Win_hide_delay() {return win_hide_delay;} private int win_hide_delay = Dflt_win_hide_delay; + public int Win_max_w() {return win_max_w;} private int win_max_w = Dflt_win_max_w; + public int Win_max_h() {return win_max_h;} private int win_max_h = Dflt_win_max_h; + public int Win_show_all_max_w() {return win_show_all_max_w;} private int win_show_all_max_w = Dflt_win_show_all_max_w; + public boolean Win_bind_focus_blur() {return win_bind_focus_blur;} private boolean win_bind_focus_blur = Dflt_win_bind_focus_blur; + public byte[] Xnde_ignore_ids() {return xnde_ignore_ids;} private byte[] xnde_ignore_ids = Dflt_xnde_ignore_ids; + public int Scan_len() {return scan_len;} private int scan_len = Dflt_scan_len; + public int Scan_max() {return scan_max;} private int scan_max = Dflt_scan_max; + public byte[] Ns_allowed() {return ns_allowed;} private byte[] ns_allowed = Dflt_ns_allowed; + public int Read_til_stop_fwd() {return read_til_stop_fwd;} private int read_til_stop_fwd = Dflt_read_til_stop_fwd; + public int Read_til_stop_bwd() {return read_til_stop_bwd;} private int read_til_stop_bwd = Dflt_read_til_stop_bwd; + public int Stop_if_hdr_after() {return stop_if_hdr_after;} private int stop_if_hdr_after = Dflt_stop_if_hdr_after; + public int Tmpl_tkn_max() {return tmpl_tkn_max;} private int tmpl_tkn_max = Dflt_tmpl_tkn_max; + public byte[] Tmpl_keeplist() {return tmpl_keeplist;} private byte[] tmpl_keeplist = Dflt_tmpl_keeplist; + public byte[] Html_fmtr_popup() {return html_fmtr_popup;} private byte[] html_fmtr_popup = Dflt_html_fmtr_popup; + public byte[] Html_fmtr_popup_dflt() {return html_fmtr_popup_dflt;} private byte[] html_fmtr_popup_dflt = Dflt_html_fmtr_popup; + public byte[] Html_fmtr_viewed() {return html_fmtr_viewed;} private byte[] html_fmtr_viewed = Dflt_html_fmtr_viewed; + public byte[] Html_fmtr_viewed_dflt() {return html_fmtr_viewed_dflt;} private byte[] html_fmtr_viewed_dflt = Dflt_html_fmtr_viewed; + public byte[] Html_fmtr_wiki() {return html_fmtr_wiki;} private byte[] html_fmtr_wiki = Dflt_html_fmtr_wiki; + public byte[] Html_fmtr_wiki_dflt() {return html_fmtr_wiki_dflt;} private byte[] html_fmtr_wiki_dflt = Dflt_html_fmtr_wiki; + public byte[] Html_fmtr_next_sect_fmt() {return html_fmtr_next_sect;} private byte[] html_fmtr_next_sect = Dflt_html_fmtr_next_sect; + public byte[] Html_fmtr_next_sect_fmt_dflt() {return html_fmtr_next_sect_dflt;} private byte[] html_fmtr_next_sect_dflt = Dflt_html_fmtr_next_sect; public void Show_more(String popup_id) { Xow_wiki wiki = app.Gui_mgr().Browser_win().Active_tab().Page().Wiki(); wiki.Html_mgr().Module_mgr().Popup_mgr().Show_more(popup_id); @@ -80,18 +88,34 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { else if (ctx.Match(k, Invk_scan_len_)) {scan_len = Set_int_gt_0(m, scan_len, Evt_scan_len_changed);} else if (ctx.Match(k, Invk_scan_max)) return scan_max; else if (ctx.Match(k, Invk_scan_max_)) {scan_max = Set_int_gt_0(m, scan_max, Evt_scan_max_changed);} - else if (ctx.Match(k, Invk_html_fmt)) return String_.new_utf8_(html_fmt); - else if (ctx.Match(k, Invk_html_fmt_)) {html_fmt = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_html_fmt_changed, html_fmt);} - else if (ctx.Match(k, Invk_html_fmt_dflt)) return String_.new_utf8_(html_fmt_dflt); - else if (ctx.Match(k, Invk_html_fmt_dflt_)) {html_fmt_dflt = m.ReadBry("v");} else if (ctx.Match(k, Invk_read_til_stop_fwd)) return read_til_stop_fwd; else if (ctx.Match(k, Invk_read_til_stop_fwd_)) {read_til_stop_fwd = m.ReadInt("v"); GfoEvMgr_.PubVal(this, Evt_read_til_stop_fwd_changed, read_til_stop_fwd);} else if (ctx.Match(k, Invk_read_til_stop_bwd)) return read_til_stop_bwd; else if (ctx.Match(k, Invk_read_til_stop_bwd_)) {read_til_stop_bwd = m.ReadInt("v"); GfoEvMgr_.PubVal(this, Evt_read_til_stop_bwd_changed, read_til_stop_bwd);} + else if (ctx.Match(k, Invk_stop_if_hdr_after)) return stop_if_hdr_after; + else if (ctx.Match(k, Invk_stop_if_hdr_after_)) {stop_if_hdr_after = m.ReadInt("v"); GfoEvMgr_.PubVal(this, Evt_stop_if_hdr_after_changed, stop_if_hdr_after);} else if (ctx.Match(k, Invk_ns_allowed)) return String_.new_utf8_(ns_allowed); else if (ctx.Match(k, Invk_ns_allowed_)) {ns_allowed = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_ns_allowed_changed, ns_allowed);} - else if (ctx.Match(k, Invk_tmpl_tkn_max)) return tmpl_tkn_max; - else if (ctx.Match(k, Invk_tmpl_tkn_max_)) {tmpl_tkn_max = m.ReadInt("v"); GfoEvMgr_.PubVal(this, Evt_tmpl_tkn_max_changed, tmpl_tkn_max);} + else if (ctx.Match(k, Invk_tmpl_tkn_max)) return tmpl_tkn_max; + else if (ctx.Match(k, Invk_tmpl_tkn_max_)) {tmpl_tkn_max = m.ReadInt("v"); GfoEvMgr_.PubVal(this, Evt_tmpl_tkn_max_changed, tmpl_tkn_max);} + else if (ctx.Match(k, Invk_tmpl_keeplist)) return String_.new_utf8_(tmpl_keeplist); + else if (ctx.Match(k, Invk_tmpl_keeplist_)) {tmpl_keeplist = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_tmpl_keeplist_changed, tmpl_keeplist);} + else if (ctx.Match(k, Invk_html_fmtr_popup)) return String_.new_utf8_(html_fmtr_popup); + else if (ctx.Match(k, Invk_html_fmtr_popup_)) {html_fmtr_popup = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_html_fmtr_popup_changed, html_fmtr_popup);} + else if (ctx.Match(k, Invk_html_fmtr_popup_dflt)) return String_.new_utf8_(html_fmtr_popup_dflt); + else if (ctx.Match(k, Invk_html_fmtr_popup_dflt_)) {html_fmtr_popup_dflt = m.ReadBry("v");} + else if (ctx.Match(k, Invk_html_fmtr_viewed)) return String_.new_utf8_(html_fmtr_viewed); + else if (ctx.Match(k, Invk_html_fmtr_viewed_)) {html_fmtr_viewed = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_html_fmtr_viewed_changed, html_fmtr_viewed);} + else if (ctx.Match(k, Invk_html_fmtr_viewed_dflt)) return String_.new_utf8_(html_fmtr_viewed_dflt); + else if (ctx.Match(k, Invk_html_fmtr_viewed_dflt_)) {html_fmtr_viewed_dflt = m.ReadBry("v");} + else if (ctx.Match(k, Invk_html_fmtr_wiki)) return String_.new_utf8_(html_fmtr_wiki); + else if (ctx.Match(k, Invk_html_fmtr_wiki_)) {html_fmtr_wiki = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_html_fmtr_wiki_changed, html_fmtr_wiki);} + else if (ctx.Match(k, Invk_html_fmtr_wiki_dflt)) return String_.new_utf8_(html_fmtr_wiki_dflt); + else if (ctx.Match(k, Invk_html_fmtr_wiki_dflt_)) {html_fmtr_wiki_dflt = m.ReadBry("v");} + else if (ctx.Match(k, Invk_html_fmtr_next_sect)) return String_.new_utf8_(html_fmtr_next_sect); + else if (ctx.Match(k, Invk_html_fmtr_next_sect_)) {html_fmtr_next_sect = m.ReadBry("v"); GfoEvMgr_.PubVal(this, Evt_html_fmtr_next_sect_changed, html_fmtr_next_sect);} + else if (ctx.Match(k, Invk_html_fmtr_next_sect_dflt)) return String_.new_utf8_(html_fmtr_next_sect_dflt); + else if (ctx.Match(k, Invk_html_fmtr_next_sect_dflt_)) {html_fmtr_next_sect_dflt = m.ReadBry("v");} else return GfoInvkAble_.Rv_unhandled; return this; } @@ -115,8 +139,14 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { , Invk_scan_len = "scan_len", Invk_scan_len_ = "scan_len_" , Invk_scan_max = "scan_max", Invk_scan_max_ = "scan_max_" , Invk_show_more = "show_more", Invk_show_all = "show_all" - , Invk_html_fmt = "html_fmt", Invk_html_fmt_ = "html_fmt_" - , Invk_html_fmt_dflt = "html_fmt_dflt", Invk_html_fmt_dflt_ = "html_fmt_dflt_" + , Invk_html_fmtr_popup = "html_fmtr_popup" , Invk_html_fmtr_popup_ = "html_fmtr_popup" + , Invk_html_fmtr_viewed = "html_fmtr_viewed" , Invk_html_fmtr_viewed_ = "html_fmtr_viewed_" + , Invk_html_fmtr_wiki = "html_fmtr_wiki" , Invk_html_fmtr_wiki_ = "html_fmtr_wiki_" + , Invk_html_fmtr_next_sect = "html_fmtr_next_sect" , Invk_html_fmtr_next_sect_ = "html_fmtr_next_sect_" + , Invk_html_fmtr_popup_dflt = "html_fmtr_popup_dflt" , Invk_html_fmtr_popup_dflt_ = "html_fmtr_popup_dflt_" + , Invk_html_fmtr_viewed_dflt = "html_fmtr_viewed_dflt" , Invk_html_fmtr_viewed_dflt_ = "html_fmtr_viewed_dflt_" + , Invk_html_fmtr_wiki_dflt = "html_fmtr_wiki_dflt" , Invk_html_fmtr_wiki_dflt_ = "html_fmtr_wiki_dflt_" + , Invk_html_fmtr_next_sect_dflt = "html_fmtr_next_sect_dflt" , Invk_html_fmtr_next_sect_dflt_ = "html_fmtr_next_sect_dflt_" , Invk_win_show_delay = "win_show_delay", Invk_win_show_delay_ = "win_show_delay_" , Invk_win_hide_delay = "win_hide_delay", Invk_win_hide_delay_ = "win_hide_delay_" , Invk_win_bind_focus_blur = "win_bind_focus_blur", Invk_win_bind_focus_blur_ = "win_bind_focus_blur_" @@ -125,8 +155,10 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { , Invk_win_show_all_max_w = "win_show_all_max_w", Invk_win_show_all_max_w_ = "win_show_all_max_w_" , Invk_read_til_stop_fwd = "read_til_stop_fwd", Invk_read_til_stop_fwd_ = "read_til_stop_fwd_" , Invk_read_til_stop_bwd = "read_til_stop_bwd", Invk_read_til_stop_bwd_ = "read_til_stop_bwd_" + , Invk_stop_if_hdr_after = "stop_if_hdr_after", Invk_stop_if_hdr_after_ = "stop_if_hdr_after_" , Invk_ns_allowed = "ns_allowed", Invk_ns_allowed_ = "ns_allowed_" , Invk_tmpl_tkn_max = "tmpl_tkn_max", Invk_tmpl_tkn_max_ = "tmpl_tkn_max_" + , Invk_tmpl_keeplist = "tmpl_keeplist", Invk_tmpl_keeplist_ = "tmpl_keeplist_" ; public static final String Evt_show_init_word_count_changed = "show_init_word_count_changed" @@ -139,23 +171,29 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { , Evt_xnde_ignore_ids_changed = "xnde_ignore_ids_changed" , Evt_scan_len_changed = "scan_len_changed" , Evt_scan_max_changed = "scan_max_changed" - , Evt_html_fmt_changed = "html_fmt_changed" , Evt_read_til_stop_fwd_changed = "read_til_stop_fwd_changed" , Evt_read_til_stop_bwd_changed = "read_til_stop_bwd_changed" + , Evt_stop_if_hdr_after_changed = "stop_if_hdr_after_changed" , Evt_ns_allowed_changed = "ns_allowed_changed" , Evt_tmpl_tkn_max_changed = "tmpl_tkn_max_changed" + , Evt_tmpl_keeplist_changed = "tmpl_keeplist" + , Evt_html_fmtr_popup_changed = "html_fmtr_popup_changed" + , Evt_html_fmtr_viewed_changed = "html_fmtr_viewed_changed" + , Evt_html_fmtr_wiki_changed = "html_fmtr_wiki_changed" + , Evt_html_fmtr_next_sect_changed = "html_fmtr_next_sect_changed" ; public static final byte[] - Dflt_coordinates = Bry_.new_ascii_("coordinates") - , Dflt_html_fmt = Bry_.new_ascii_(String_.Concat_lines_nl_skip_last + Dflt_xnde_ignore_ids = Bry_.new_ascii_("coordinates") + , Dflt_tmpl_keeplist = Bry_.new_ascii_("en.wikipedia.org|formatnum;age_in_days;as_of;gregorian_serial_date;currentminute;currentsecond;dmca;spaced_ndash;trim;month*;convert*;worldpop*;ipa*;lang*;nowrap*;h:*;vgy;iso_639_name;transl;translate;linktext;zh;nihongo;japanese_name;ko-hhrm;|\n") + , Dflt_html_fmtr_popup = Bry_.new_ascii_(String_.Concat_lines_nl_skip_last ( "
" , "
~{content}" , "
" , "
" , "
" , " ~{page_title}~{wiki_item}" - , " ~{<>msgs.get('api-xowa.html.modules.popups.msgs.size-name');<>}:~{page_size}" - , " ~{<>msgs.get('api-xowa.html.modules.popups.msgs.edited-name');<>}:~{edit_time}~{view_time_item}" + , " ~{<>msgs.get('api-xowa.html.modules.popups.msgs.size-name');<>}~{page_size}" + , " ~{<>msgs.get('api-xowa.html.modules.popups.msgs.edited-name');<>}~{edit_time}~{view_time_item}" , "
" , "
" , "
" @@ -165,28 +203,38 @@ public class Xoapi_popups implements GfoInvkAble, GfoEvMgrOwner { , " }'>" , " }'>" , " }'> " + , " }'>" , " }'>" , "
" , "
" )) + , Dflt_html_fmtr_viewed = Bry_.new_ascii_("\n ~{<>msgs.get('api-xowa.html.modules.popups.msgs.view_time-name');<>}~{viewed_val}") + , Dflt_html_fmtr_wiki = Bry_.new_ascii_("\n ~{<>msgs.get('api-xowa.html.modules.popups.msgs.wiki-name');<>}~{wiki_val}") + , Dflt_html_fmtr_next_sect = Bry_.new_ascii_("\n\n~{<>msgs.get('api-xowa.html.modules.popups.msgs.next_sect-name');<>}~{next_sect_val}") + ; + public static final String[] + Dflt_html_fmtr_popup_keys = String_.Ary("content", "page_lang_ltr", "page_url", "page_title", "popup_id", "wiki_item", "page_size", "edit_time", "view_time_item", "xowa_root_dir") + , Dflt_html_fmtr_viewed_keys = String_.Ary("viewed_val") + , Dflt_html_fmtr_wiki_keys = String_.Ary("wiki_val") + , Dflt_html_fmtr_next_sect_keys = String_.Ary("next_sect_val") ; - public static final String[] Dflt_html_fmt_keys = String_.Ary("content", "page_lang_ltr", "page_url", "page_title", "wiki_domain", "wiki_item", "page_size", "edit_time", "view_time_item", "xowa_root_dir", "popup_id"); public static final byte[] Dflt_ns_allowed = Bry_.Empty ; public static final int - Dflt_show_init_word_count = 64 - , Dflt_show_more_word_count = 64 + Dflt_show_init_word_count = 128 + , Dflt_show_more_word_count = 192 , Dflt_show_all_if_less_than = -1 , Dflt_show_all_win_max_w = -1 - , Dflt_win_show_delay = 400, Dflt_win_hide_delay = 400 + , Dflt_win_show_delay = 600, Dflt_win_hide_delay = 600 , Dflt_win_max_w = -1, Dflt_win_max_h = -1 - , Dflt_win_show_all_max_w = -1 + , Dflt_win_show_all_max_w = 800 , Dflt_scan_len = 1 * Io_mgr.Len_kb , Dflt_scan_max = 32 * Io_mgr.Len_kb - , Dflt_read_til_stop_fwd = -1 - , Dflt_read_til_stop_bwd = -1 - , Dflt_tmpl_tkn_max = 8192 + , Dflt_read_til_stop_fwd = 32 + , Dflt_read_til_stop_bwd = 16 + , Dflt_stop_if_hdr_after = 96 + , Dflt_tmpl_tkn_max = 8 * Io_mgr.Len_kb ; public static final boolean Dflt_win_bind_focus_blur = false diff --git a/400_xowa/src/gplx/xowa/apps/Xoa_gfs_mgr.java b/400_xowa/src/gplx/xowa/apps/Xoa_gfs_mgr.java index 25a056aa7..60b963660 100644 --- a/400_xowa/src/gplx/xowa/apps/Xoa_gfs_mgr.java +++ b/400_xowa/src/gplx/xowa/apps/Xoa_gfs_mgr.java @@ -37,7 +37,12 @@ public class Xoa_gfs_mgr implements GfoInvkAble, GfoInvkRootWkr { else if (String_.Eq(type, "xowa_user_cfg")) url = fsys_mgr.App_data_cfg_user_fil(); else if (String_.Eq(type, "xowa")) url = app.Fsys_mgr().Root_dir().GenSubFil("xowa.gfs"); else throw Err_mgr._.fmt_(GRP_KEY, "invalid_gfs_type", "invalid gfs type: ~{0}", type); - Run_url(url); + try {Run_url(url);} + catch (Exception e) { // gfs is corrupt; may happen if multiple XOWAs opened, and "Close all" chosen in OS; DATE:2014-07-01 + if (!String_.Eq(type, "xowa")) // check if user.gfs + Io_mgr._.MoveFil(url, url.GenNewNameOnly(url.NameOnly() + "-" + DateAdp_.Now().XtoStr_fmt_yyyyMMdd_HHmmss())); // move file + app.Usr_dlg().Warn_many("", "", "invalid gfs; obsoleting: src=~{0} err=~{1}", url.Raw(), Err_.Message_gplx(e)); + } } public GfoMsg Parse_root_msg(String v) {return gplx.gfs.Gfs_msg_bldr._.ParseToMsg(v);} public Gfs_wtr Wtr() {return wtr;} private Gfs_wtr wtr = new Gfs_wtr(); diff --git a/400_xowa/src/gplx/xowa/apps/ttls/Xoa_ttl__i18n_tst.java b/400_xowa/src/gplx/xowa/apps/ttls/Xoa_ttl__i18n_tst.java index 9df294909..4822ec9d7 100644 --- a/400_xowa/src/gplx/xowa/apps/ttls/Xoa_ttl__i18n_tst.java +++ b/400_xowa/src/gplx/xowa/apps/ttls/Xoa_ttl__i18n_tst.java @@ -28,14 +28,14 @@ public class Xoa_ttl__i18n_tst { fxt.Init_ttl("ⱥ").Expd_full_txt("ⱥ").Test(); } @Test public void First_char_is_multi_byte() { // PURPOSE: if multi-byte, uppercasing is complicated; EX: µ -> Μ; DATE:2013-11-27 - fxt.Wiki().Lang().Case_mgr().Add_bulk(Xol_case_itm_.Universal); + fxt.Wiki().Lang().Case_mgr_utf8_(); fxt.Init_ttl("µ").Expd_full_txt("Μ").Test(); // NOTE: this is not an ASCII "Μ" fxt.Init_ttl("µab").Expd_full_txt("Μab").Test(); // check that rest of title works fine fxt.Init_ttl("Help:µab").Expd_full_txt("Help:Μab").Test(); // check ns fxt.Init_ttl("Ι").Expd_full_txt("Ι").Test(); // check that Ι is not upper-cased to COMBINING GREEK YPOGEGRAMMENI; DATE:2014-02-24 } @Test public void First_char_is_multi_byte_assymetrical() { // PURPOSE: test multi-byte asymmetry (lc is 3 bytes; uc is 2 bytes) - fxt.Wiki().Lang().Case_mgr().Add_bulk(Xol_case_itm_.Universal); + fxt.Wiki().Lang().Case_mgr_utf8_(); fxt.Init_ttl("ⱥ").Expd_full_txt("Ⱥ").Test(); fxt.Init_ttl("ⱥab").Expd_full_txt("Ⱥab").Test(); // check that rest of title works fine fxt.Init_ttl("Help:ⱥab").Expd_full_txt("Help:Ⱥab").Test(); // check ns diff --git a/400_xowa/src/gplx/xowa/bldrs/files/Xob_lnki_temp_wkr.java b/400_xowa/src/gplx/xowa/bldrs/files/Xob_lnki_temp_wkr.java index e1b919a0c..018a96e5d 100644 --- a/400_xowa/src/gplx/xowa/bldrs/files/Xob_lnki_temp_wkr.java +++ b/400_xowa/src/gplx/xowa/bldrs/files/Xob_lnki_temp_wkr.java @@ -56,7 +56,7 @@ public class Xob_lnki_temp_wkr extends Xob_dump_mgr_base implements Xop_lnki_log property_wkr = this.Property_wkr(); // set member reference property_wkr = log_mgr.Make_wkr_property(); wiki.App().Wiki_mgr().Wdata_mgr().Enabled_(wdata_enabled); - if (!xtn_ref_enabled) gplx.xowa.xtns.refs.References_nde.Enabled = false; + if (!xtn_ref_enabled) gplx.xowa.xtns.cite.References_nde.Enabled = false; gplx.xowa.xtns.gallery.Gallery_xnde.Log_wkr = log_mgr.Make_wkr().Save_src_str_(Bool_.Y); gplx.xowa.xtns.imageMap.Xop_imageMap_xnde.Log_wkr = log_mgr.Make_wkr(); gplx.xowa.Xop_xnde_wkr.Timeline_log_wkr = log_mgr.Make_wkr(); diff --git a/400_xowa/src/gplx/xowa/bldrs/imports/Xob_init_base_tst.java b/400_xowa/src/gplx/xowa/bldrs/imports/Xob_init_base_tst.java index 211618c02..c3dcd352b 100644 --- a/400_xowa/src/gplx/xowa/bldrs/imports/Xob_init_base_tst.java +++ b/400_xowa/src/gplx/xowa/bldrs/imports/Xob_init_base_tst.java @@ -27,7 +27,7 @@ public class Xob_init_base_tst { app.User().Wiki().Xwiki_mgr().Add_full("en.wikipedia.org", "en.wikipedia.org"); Tfds.Eq("", wikis_list.Itms_as_html()); // still empty new Xob_init_txt(app.Bldr(), wiki).Cmd_end(); // mock "init" task - Tfds.Eq("\n
  • en.wikipedia.org
  • ", wikis_list.Itms_as_html()); // no longer empty + Tfds.Eq("\n
  • en.wikipedia.org
  • ", wikis_list.Itms_as_html()); // no longer empty } } class Xob_init_base_fxt { diff --git a/400_xowa/src/gplx/xowa/bldrs/langs/Xol_mw_lang_parser_tst.java b/400_xowa/src/gplx/xowa/bldrs/langs/Xol_mw_lang_parser_tst.java index d91893b13..b4a316781 100644 --- a/400_xowa/src/gplx/xowa/bldrs/langs/Xol_mw_lang_parser_tst.java +++ b/400_xowa/src/gplx/xowa/bldrs/langs/Xol_mw_lang_parser_tst.java @@ -78,7 +78,7 @@ public class Xol_mw_lang_parser_tst { ; } @Test public void Xtn_keywords_fr() {fxt.Parse_xtn("$magicWords['fr'] = array('if' => array(0, 'si' ));").Tst_parse("{{si:|y|n}}", "n");} - @Test public void Xtn_keywords_de() {fxt.Parse_xtn("$magicWords['de'] = array('if' => array(0, 'si' ));").Tst_parse("{{si:|y|n}}", "Template:si:");} + @Test public void Xtn_keywords_de() {fxt.Parse_xtn("$magicWords['de'] = array('if' => array(0, 'si' ));").Tst_parse("{{si:|y|n}}", "Template:Si:");} // should be "Si", not "si"; ALSO, should probably be "{{si:|y|n}}" not "[[:Template:si:]]" DATE:2014-07-04 @Test public void Core_messages() { fxt.Parse_core("$messages = array('sunday' => 'dimanche');") .Tst_message("sunday", 0, "dimanche", false) diff --git a/400_xowa/src/gplx/xowa/bldrs/xmls/Xob_xml_parser_tst.java b/400_xowa/src/gplx/xowa/bldrs/xmls/Xob_xml_parser_tst.java index ee7b7f28f..763301ddf 100644 --- a/400_xowa/src/gplx/xowa/bldrs/xmls/Xob_xml_parser_tst.java +++ b/400_xowa/src/gplx/xowa/bldrs/xmls/Xob_xml_parser_tst.java @@ -23,7 +23,7 @@ public class Xob_xml_parser_tst { Io_mgr._.InitEngine_mem(); Xoa_app app = Xoa_app_fxt.app_(); bldr = new Xob_bldr(app); - } private Xow_ns_mgr ns_mgr = Xow_ns_mgr_.default_(); + } private Xow_ns_mgr ns_mgr = Xow_ns_mgr_.default_(gplx.xowa.langs.cases.Xol_case_mgr_.Ascii()); @Test public void Basic_docs_1() { Xodb_page doc = doc_(1, "a", "a a", Date_1); fil = page_bldr.Add(doc).XtoByteStreamRdr(); diff --git a/400_xowa/src/gplx/xowa/cfgs/gui/Xocfg_pref_mgr.java b/400_xowa/src/gplx/xowa/cfgs/gui/Xocfg_pref_mgr.java new file mode 100644 index 000000000..90186f21a --- /dev/null +++ b/400_xowa/src/gplx/xowa/cfgs/gui/Xocfg_pref_mgr.java @@ -0,0 +1,106 @@ +/* +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 . +*/ +package gplx.xowa.cfgs.gui; import gplx.*; import gplx.xowa.*; import gplx.xowa.cfgs.*; +class Test_api implements GfoInvkAble { + public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { + if (ctx.Match(k, Invk_meta)) return meta_mgr.Get_or_null(m.ReadStr("v")); + else return GfoInvkAble_.Rv_unhandled; +// return this; + } private static final String Invk_meta = "meta"; + private static final String Invk_prop_1 = "prop_1", Invk_prop_2 = "prop_2", Invk_prop_3 = "prop_3", Invk_prop_bry = "bry", Invk_prop_enm = "enm"; + private static final boolean Dflt_prop_1 = false; + private static final int Dflt_prop_2 = 2; + private static final String Dflt_prop_3 = "3"; + private static final byte[] Dflt_prop_bry = Bry_.new_ascii_("bry"); + private static final int Dflt_prop_enm = 5; + private static final Xocfg_meta_mgr meta_mgr = new Xocfg_meta_mgr().Add + ( Xocfg_meta_itm_.bool_ (Invk_prop_1, Dflt_prop_1) + , Xocfg_meta_itm_.int_ (Invk_prop_2, Dflt_prop_2).Rng_bgn_(-1) + , Xocfg_meta_itm_.str_ (Invk_prop_3, Dflt_prop_3) + , Xocfg_meta_itm_.bry_ (Invk_prop_bry, Dflt_prop_bry) + , Xocfg_meta_itm_.enm_ (Invk_prop_enm, Dflt_prop_enm).Itms_list_("a", "b", "c") + , Xocfg_meta_itm_.str_ (Invk_prop_3, Dflt_prop_3).Gui_itm_(Xocfg_gui_itm_.memo_(40, 60)) +// , Xocfg_meta_itm_.enum_ (Invk_prop_3, Dflt_prop_3).Add("a", "b").Add("b", "c").Data(Xocfg_gui.list("a")) + ) + ; +} +interface Xocfg_gui_itm { +} +class Xocfg_gui_itm_ { + public static Xocfg_gui_itm_memo memo_(int box_w, int box_h) {return new Xocfg_gui_itm_memo(box_w, box_h);} +} +class Xocfg_gui_itm_fld { +} +class Xocfg_gui_itm_memo implements Xocfg_gui_itm { + public Xocfg_gui_itm_memo(int box_w, int box_h) {this.box_w = box_w; this.box_h = box_h;} + public int Box_w() {return box_w;} private int box_w; + public int Box_h() {return box_h;} private int box_h; +} +class Xocfg_meta_mgr { + private HashAdp hash = HashAdp_.new_(); + public Xocfg_meta_mgr Add(Xocfg_meta_itm_base... ary) { + int len = ary.length; + for (int i = 0; i < len; i++) { + Xocfg_meta_itm_base itm = (Xocfg_meta_itm_base)ary[i]; + hash.Add(itm.Prop_key(), itm); + } + return this; + } + public Xocfg_meta_itm_base Get_or_null(String key) {return (Xocfg_meta_itm_base)hash.Fetch(key);} +} +abstract class Xocfg_meta_itm_base { + public void Set(int prop_type, String prop_key, Object prop_dflt) { + this.prop_key = prop_key; this.prop_type = prop_type; this.prop_dflt = prop_dflt; + } + public String Prop_key() {return prop_key;} private String prop_key; + public Object Prop_dflt() {return prop_dflt;} private Object prop_dflt; + public int Prop_type() {return prop_type;} private int prop_type; +} +class Xocfg_meta_itm_ { + public static Xocfg_meta_itm_bool bool_(String key, boolean dflt) {return new Xocfg_meta_itm_bool(key, dflt);} + public static Xocfg_meta_itm_int int_(String key, int dflt) {return new Xocfg_meta_itm_int(key, dflt);} + public static Xocfg_meta_itm_str str_(String key, String dflt) {return new Xocfg_meta_itm_str(key, dflt);} + public static Xocfg_meta_itm_bry bry_(String key, byte[] dflt) {return new Xocfg_meta_itm_bry(key, dflt);} + public static Xocfg_meta_itm_enm enm_(String key, int dflt) {return new Xocfg_meta_itm_enm(key, dflt);} +} +class Xodfg_pref_itm_type_ { + public static final int Tid_bool = 1, Tid_int = 2, Tid_str = 3, Tid_bry = 4, Tid_enm = 5; +} +class Xocfg_meta_itm_bool extends Xocfg_meta_itm_base { + public Xocfg_meta_itm_bool(String prop_key, boolean prop_dflt) {this.Set(Xodfg_pref_itm_type_.Tid_bool, prop_key, prop_dflt);} +} +class Xocfg_meta_itm_int extends Xocfg_meta_itm_base { + public Xocfg_meta_itm_int(String prop_key, int prop_dflt) {this.Set(Xodfg_pref_itm_type_.Tid_int, prop_key, prop_dflt);} + public Xocfg_meta_itm_int Rng_bgn_(int bgn) {return Rng_(bgn, Int_.MaxValue);} + public Xocfg_meta_itm_int Rng_(int bgn, int end) { + return this; + } +} +class Xocfg_meta_itm_str extends Xocfg_meta_itm_base { + public Xocfg_meta_itm_str(String prop_key, String prop_dflt) {this.Set(Xodfg_pref_itm_type_.Tid_str, prop_key, prop_dflt);} + public Xocfg_gui_itm Gui_itm() {return gui_itm;} public Xocfg_meta_itm_base Gui_itm_(Xocfg_gui_itm v) {gui_itm = v; return this;} private Xocfg_gui_itm gui_itm; +} +class Xocfg_meta_itm_bry extends Xocfg_meta_itm_base { + public Xocfg_meta_itm_bry(String prop_key, byte[] prop_dflt) {this.Set(Xodfg_pref_itm_type_.Tid_bry, prop_key, prop_dflt);} +} +class Xocfg_meta_itm_enm extends Xocfg_meta_itm_base { + public Xocfg_meta_itm_enm(String prop_key, int prop_dflt) {this.Set(Xodfg_pref_itm_type_.Tid_enm, prop_key, prop_dflt);} + public Xocfg_meta_itm_enm Itms_list_(String... ary) { + return this; + } +} diff --git a/400_xowa/src/gplx/xowa/ctgs/Xoctg_html_mgr.java b/400_xowa/src/gplx/xowa/ctgs/Xoctg_html_mgr.java index c02d4e372..d6ceb4001 100644 --- a/400_xowa/src/gplx/xowa/ctgs/Xoctg_html_mgr.java +++ b/400_xowa/src/gplx/xowa/ctgs/Xoctg_html_mgr.java @@ -31,7 +31,7 @@ public class Xoctg_html_mgr implements GfoInvkAble { Bld_html_v2(wiki, page, tmp_bfr); else Bld_html_v1(wiki, page, tmp_bfr); - bfr.Add_bfr(tmp_bfr.Mkr_rls()); + bfr.Add_bfr_and_preserve(tmp_bfr.Mkr_rls()); } catch (Exception e) { // ctg error should never cause page to fail tmp_bfr.Mkr_rls(); diff --git a/400_xowa/src/gplx/xowa/dbs/Xodb_ns_map_mgr.java b/400_xowa/src/gplx/xowa/dbs/Xodb_ns_map_mgr.java index dec1e5a08..3d4c0571b 100644 --- a/400_xowa/src/gplx/xowa/dbs/Xodb_ns_map_mgr.java +++ b/400_xowa/src/gplx/xowa/dbs/Xodb_ns_map_mgr.java @@ -21,7 +21,7 @@ class Xodb_ns_map_mgr { public static Xodb_ns_map_mgr Parse(byte[] src) { byte[][] lines = Bry_.Split(src, Byte_ascii.NewLine); int lines_len = lines.length; - Xow_ns_mgr canonical_ns_mgr = Xow_ns_mgr_.default_(); + Xow_ns_mgr canonical_ns_mgr = Xow_ns_mgr_.default_(gplx.xowa.langs.cases.Xol_case_mgr_.Ascii()); Xodb_ns_map_mgr rv = new Xodb_ns_map_mgr(); ListAdp itms = ListAdp_.new_(); for (int i = 0; i < lines_len; i++) { diff --git a/400_xowa/src/gplx/xowa/files/Xow_file_mgr.java b/400_xowa/src/gplx/xowa/files/Xow_file_mgr.java index 8e48d2033..770afed3f 100644 --- a/400_xowa/src/gplx/xowa/files/Xow_file_mgr.java +++ b/400_xowa/src/gplx/xowa/files/Xow_file_mgr.java @@ -93,6 +93,14 @@ public class Xow_file_mgr implements GfoInvkAble { return xfer_itm.Atrs_calc_for_html(); } } + public boolean Exists(byte[] ttl_bry) { + if (this.Version_1_y()) { + Xof_meta_itm meta = meta_mgr.Get_itm_or_new(ttl_bry); + return meta.Orig_exists() == Bool_.Y_byte || meta.Thumbs().length != 0; + } + else + return fsdb_mgr.Reg_select_itm_exists(ttl_bry); + } public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_repos)) return repo_mgr; diff --git a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr.java b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr.java index 65ef434c2..2c11bfba5 100644 --- a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr.java +++ b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr.java @@ -39,4 +39,5 @@ public interface Xof_fsdb_mgr extends RlsAble { void Reg_insert(Xof_fsdb_itm itm, byte repo_id, byte status); void Reg_select(Xoa_page page, byte exec_tid, ListAdp itms); void Reg_select_only(Xoa_page page, byte exec_tid, ListAdp itms, OrderedHash hash); + boolean Reg_select_itm_exists(byte[] ttl); } diff --git a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_mem.java b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_mem.java index c27c5d53c..1647606c3 100644 --- a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_mem.java +++ b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_mem.java @@ -93,6 +93,7 @@ public class Xof_fsdb_mgr_mem implements Xof_fsdb_mgr, Xof_bin_wkr { } Xof_fsdb_mgr_._.Fsdb_search(this, fs_dir, page, exec_tid, itms, bin_mgr.Repo_mgr(), url_bldr); } + public boolean Reg_select_itm_exists(byte[] ttl) {return reg_hash.Has(ttl);} public byte Bin_wkr_tid() {return Xof_bin_wkr_.Tid_fsdb_wiki;} public gplx.ios.Io_stream_rdr Bin_wkr_get_as_rdr(ListAdp temp_files, Xof_fsdb_itm itm, boolean is_thumb, int w) { byte[] wiki = itm.Orig_wiki(); diff --git a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_sql.java b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_sql.java index 142b6a8e6..c0c1f05f4 100644 --- a/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_sql.java +++ b/400_xowa/src/gplx/xowa/files/fsdb/Xof_fsdb_mgr_sql.java @@ -80,6 +80,7 @@ public class Xof_fsdb_mgr_sql implements Xof_fsdb_mgr, GfoInvkAble { bin_wkr_fsdb = new Xof_bin_wkr_fsdb_sql(this).Bin_bfr_len_(64 * Io_mgr.Len_kb); // most thumbs are 40 kb cache_mgr = wiki.App().File_mgr().Cache_mgr(); } private boolean init = false; + public boolean Reg_select_itm_exists(byte[] ttl) {return Xof_wiki_orig_tbl.Select_itm_exists(img_regy_provider, ttl);} public void Reg_select_only(Xoa_page page, byte exec_tid, ListAdp itms, OrderedHash hash) { Xof_wiki_orig_tbl.Select_list(wiki.App().Usr_dlg(), img_regy_provider, exec_tid, itms, hash, url_bldr, bin_mgr.Repo_mgr()); } diff --git a/400_xowa/src/gplx/xowa/files/fsdb/fs_roots/Fs_root_fsdb_mgr.java b/400_xowa/src/gplx/xowa/files/fsdb/fs_roots/Fs_root_fsdb_mgr.java index eed40146c..c1c19d787 100644 --- a/400_xowa/src/gplx/xowa/files/fsdb/fs_roots/Fs_root_fsdb_mgr.java +++ b/400_xowa/src/gplx/xowa/files/fsdb/fs_roots/Fs_root_fsdb_mgr.java @@ -52,8 +52,8 @@ public class Fs_root_fsdb_mgr implements Xof_fsdb_mgr, GfoInvkAble { Js_img_mgr.Update_img(page, itm); } } - public void Reg_select_only(Xoa_page page, byte exec_tid, ListAdp itms, OrderedHash hash) { - } + public void Reg_select_only(Xoa_page page, byte exec_tid, ListAdp itms, OrderedHash hash) {} + public boolean Reg_select_itm_exists(byte[] ttl) {throw Err_.not_implemented_();} public void Rls() {} private Io_url Xto_url(byte[] v) { if (Op_sys.Cur().Tid_is_wnt()) diff --git a/400_xowa/src/gplx/xowa/gui/bnds/Xog_bnd_mgr.java b/400_xowa/src/gplx/xowa/gui/bnds/Xog_bnd_mgr.java index 41d09f992..7f884dccb 100644 --- a/400_xowa/src/gplx/xowa/gui/bnds/Xog_bnd_mgr.java +++ b/400_xowa/src/gplx/xowa/gui/bnds/Xog_bnd_mgr.java @@ -123,8 +123,8 @@ public class Xog_bnd_mgr { Init_itm(Xog_cmd_itm_.Key_gui_page_view_mode_read , Xog_bnd_box_.Tid_browser , "mod.c+key.m,mod.c+key.r"); Init_itm(Xog_cmd_itm_.Key_gui_page_view_mode_edit , Xog_bnd_box_.Tid_browser , "mod.c+key.m,mod.c+key.e"); Init_itm(Xog_cmd_itm_.Key_gui_page_view_mode_html , Xog_bnd_box_.Tid_browser , "mod.c+key.m,mod.c+key.h"); - Init_itm(Xog_cmd_itm_.Key_gui_page_view_reload , Xog_bnd_box_.Tid_browser , "key.f5"); - Init_itm(Xog_cmd_itm_.Key_gui_page_view_refresh , Xog_bnd_box_.Tid_browser , "mod.s+key.f5"); + Init_itm(Xog_cmd_itm_.Key_gui_page_view_reload , Xog_bnd_box_.Tid_browser , "mod.s+key.f5"); + Init_itm(Xog_cmd_itm_.Key_gui_page_view_refresh , Xog_bnd_box_.Tid_browser , "key.f5"); Init_itm(Xog_cmd_itm_.Key_gui_page_view_save_as , Xog_bnd_box_.Tid_browser , ""); Init_itm(Xog_cmd_itm_.Key_gui_page_view_print , Xog_bnd_box_.Tid_browser , ""); @@ -148,7 +148,7 @@ public class Xog_bnd_mgr { Init_itm(Xog_cmd_itm_.Key_gui_browser_search_exec , Xog_bnd_box_.Tid_browser_search , "key.enter"); Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_new_dflt__at_dflt__focus_y , Xog_bnd_box_.Tid_browser , "mod.c+key.t"); Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_new_link__at_dflt__focus_n , Xog_bnd_box_.Tid_browser_html , "mouse.middle"); - Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_new_href__at_dflt__focus_y , Xog_bnd_box_.Tid_browser , "mod.c+key.g"); + Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_new_href__at_dflt__focus_y , Xog_bnd_box_.Tid_browser , "mod.c+key.g,mod.c+key.f"); Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_close_cur , Xog_bnd_box_.Tid_browser , "mod.c+key.w"); Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_close_others , Xog_bnd_box_.Tid_browser , "mod.cs+key.w,mod.cs+key.w"); Init_itm(Xog_cmd_itm_.Key_gui_browser_tabs_close_to_bgn , Xog_bnd_box_.Tid_browser , "mod.cs+key.w,mod.cs+key.left"); @@ -172,6 +172,7 @@ public class Xog_bnd_mgr { Init_itm(Xog_cmd_itm_.Key_gui_browser_html_focus , 2, Xog_bnd_box_.Tid_browser_search , "key.escape"); Init_itm(Xog_cmd_itm_.Key_gui_browser_html_focus , 3, Xog_bnd_box_.Tid_browser_prog , "key.escape"); Init_itm(Xog_cmd_itm_.Key_gui_browser_html_focus , 4, Xog_bnd_box_.Tid_browser_info , "key.escape"); + Init_itm(Xog_cmd_itm_.Key_gui_browser_html_selection_focus_toggle , Xog_bnd_box_.Tid_browser , "mod.c+key.g,mod.c+key.g"); Init_itm(Xog_cmd_itm_.Key_gui_browser_find_show , Xog_bnd_box_.Tid_browser , "mod.c+key.f"); Init_itm(Xog_cmd_itm_.Key_gui_browser_find_show_by_paste , Xog_bnd_box_.Tid_browser , ""); Init_itm(Xog_cmd_itm_.Key_gui_browser_find_hide , Xog_bnd_box_.Tid_browser_find , "key.escape"); diff --git a/400_xowa/src/gplx/xowa/gui/cmds/Xog_cmd_itm_.java b/400_xowa/src/gplx/xowa/gui/cmds/Xog_cmd_itm_.java index 2e92c0d2d..59ef6f9e2 100644 --- a/400_xowa/src/gplx/xowa/gui/cmds/Xog_cmd_itm_.java +++ b/400_xowa/src/gplx/xowa/gui/cmds/Xog_cmd_itm_.java @@ -103,6 +103,7 @@ public class Xog_cmd_itm_ { , Key_gui_browser_tabs_close_undo = new_dflt_(Xog_ctg_itm_.Tid_tabs , "xowa.gui.browser.tabs.close_undo") , Key_gui_browser_tabs_pin_toggle = new_dflt_(Xog_ctg_itm_.Tid_tabs , "xowa.gui.browser.tabs.pin_toggle") , Key_gui_browser_html_focus = new_dflt_(Xog_ctg_itm_.Tid_browser , "xowa.gui.browser.html.focus") + , Key_gui_browser_html_selection_focus_toggle = new_dflt_(Xog_ctg_itm_.Tid_browser , "xowa.gui.browser.html.selection_focus_toggle") , Key_gui_browser_find_show = new_dflt_(Xog_ctg_itm_.Tid_browser , "xowa.gui.browser.find.show") , Key_gui_browser_find_show_by_paste = new_dflt_(Xog_ctg_itm_.Tid_browser , "xowa.gui.browser.find.show_by_paste") , Key_gui_browser_find_hide = new_dflt_(Xog_ctg_itm_.Tid_browser , "xowa.gui.browser.find.hide") diff --git a/400_xowa/src/gplx/xowa/gui/menus/Xog_menu_mgr.java b/400_xowa/src/gplx/xowa/gui/menus/Xog_menu_mgr.java index 0cb7a39f0..bfec379b9 100644 --- a/400_xowa/src/gplx/xowa/gui/menus/Xog_menu_mgr.java +++ b/400_xowa/src/gplx/xowa/gui/menus/Xog_menu_mgr.java @@ -18,6 +18,7 @@ along with this program. If not, see . package gplx.xowa.gui.menus; import gplx.*; import gplx.xowa.*; import gplx.xowa.gui.*; import gplx.xowa.gui.menus.dom.*; public class Xog_menu_mgr implements GfoInvkAble { + private Xoa_app app; public Xog_menu_mgr(Xoa_gui_mgr gui_mgr) { menu_bldr = new Xog_mnu_bldr(); regy = new Xog_mnu_regy(gui_mgr); @@ -31,11 +32,16 @@ public class Xog_menu_mgr implements GfoInvkAble { public void Init_by_app(Xoa_app app) { this.app = app; regy.Init_by_app(app); - } private Xoa_app app; + } public void Init_by_kit() { - popup_mnu_mgr.Init_by_kit(); - window_mnu_mgr.Init_by_kit(); - Lang_changed(app.User().Lang()); + try { + popup_mnu_mgr.Init_by_kit(); + window_mnu_mgr.Init_by_kit(); + Lang_changed(app.User().Lang()); + } + catch (Exception e) { // ignore errors while loading custom menus, else fatal error; DATE:2014-07-01 + app.Usr_dlg().Warn_many("", "", "error while loading menus; err=~{0}", Err_.Message_gplx(e)); + } } public void Lang_changed(Xol_lang lang) { window_mnu_mgr.Lang_changed(lang); diff --git a/400_xowa/src/gplx/xowa/gui/views/Xog_html_js_cbk.java b/400_xowa/src/gplx/xowa/gui/views/Xog_html_js_cbk.java index eea405767..710554f7a 100644 --- a/400_xowa/src/gplx/xowa/gui/views/Xog_html_js_cbk.java +++ b/400_xowa/src/gplx/xowa/gui/views/Xog_html_js_cbk.java @@ -80,8 +80,12 @@ public class Xog_html_js_cbk implements GfoInvkAble { return html_itm.Owner_tab().Page().Wiki().Html_mgr().Module_mgr().Popup_mgr().Show_init(href_bry, popups_id); } catch (Exception e) {Err_.Noop(e); return null;} } - private String[] Get_title_meta(Xow_wiki wiki, byte[] ttl) { - Pfunc_ifexist.Exists(tmp_page, wiki.Ctx(), ttl); + private String[] Get_title_meta(Xow_wiki wiki, byte[] ttl_bry) { + synchronized (tmp_page) { + tmp_page.Clear(); + Xoa_ttl ttl = Xoa_ttl.parse_(wiki, ttl_bry); + wiki.Db_mgr().Load_mgr().Load_by_ttl(tmp_page, ttl.Ns(), ttl.Page_db()); + } return String_.Ary(tmp_page.Exists() ? "1" : "0", Int_.XtoStr(tmp_page.Id()), Int_.XtoStr(tmp_page.Ns_id()), String_.new_utf8_(tmp_page.Ttl_wo_ns()), Bool_.XtoStr_lower(tmp_page.Type_redirect()), tmp_page.Modified_on().XtoStr_fmt("yyyy-MM-dd HH:mm:ss"), Int_.XtoStr(tmp_page.Text_len())); } private static final Xodb_page tmp_page = Xodb_page.tmp_(); private String[][] Get_titles_meta(GfoMsg m) { @@ -98,7 +102,7 @@ public class Xog_html_js_cbk implements GfoInvkAble { } catch (Exception e) {Err_.Noop(e); return null;} } private boolean Get_title_exists(Xow_wiki wiki, byte[] ttl) { - return Pfunc_ifexist.Exists(tmp_page, wiki.Ctx(), ttl); + return Pfunc_ifexist.Exists(wiki, ttl); } private String[] Get_titles_exists(GfoMsg m) { Xow_wiki wiki = html_itm.Owner_tab().Page().Wiki(); diff --git a/400_xowa/src/gplx/xowa/html/Xoh_html_wtr.java b/400_xowa/src/gplx/xowa/html/Xoh_html_wtr.java index 733c9cc21..ac2d9ea00 100644 --- a/400_xowa/src/gplx/xowa/html/Xoh_html_wtr.java +++ b/400_xowa/src/gplx/xowa/html/Xoh_html_wtr.java @@ -16,9 +16,9 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.html; import gplx.*; import gplx.xowa.*; -import gplx.xowa.wikis.*; import gplx.xowa.net.*; +import gplx.html.*; import gplx.xowa.wikis.*; import gplx.xowa.net.*; import gplx.xowa.parsers.apos.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.parsers.lnkes.*; -import gplx.xowa.xtns.*; import gplx.xowa.xtns.dynamicPageList.*; import gplx.xowa.xtns.math.*; import gplx.xowa.langs.vnts.*; import gplx.xowa.xtns.refs.*; +import gplx.xowa.xtns.*; import gplx.xowa.xtns.dynamicPageList.*; import gplx.xowa.xtns.math.*; import gplx.xowa.langs.vnts.*; import gplx.xowa.xtns.cite.*; public class Xoh_html_wtr { private Xow_wiki wiki; private Xoa_app app; private Xoa_page page; private Xop_xatr_whitelist_mgr whitelist_mgr; public Xoh_html_wtr(Xow_wiki wiki, Xow_html_mgr html_mgr) { @@ -583,9 +583,9 @@ public class Xoh_html_wtr { break; default: byte[] tag_name = sub_xnde.Tag().Name_bry(); - bfr.Add(Xop_xnde_wkr.Bry_escape_lt).Add(tag_name); + bfr.Add(Html_entity_.Lt_bry).Add(tag_name); if (xnde.Atrs_bgn() > Xop_tblw_wkr.Atrs_ignore_check) Xnde_atrs(sub_xnde.Tag().Id(), hctx, src, sub_xnde.Atrs_bgn(), sub_xnde.Atrs_end(), xnde.Atrs_ary(), bfr); - bfr.Add(Xop_xnde_wkr.Bry_escape_gt); + bfr.Add(Html_entity_.Gt_bry); break; } Xnde_subs_escape(ctx, hctx, bfr, src, sub_xnde, amp_enable, false); diff --git a/400_xowa/src/gplx/xowa/html/Xoh_html_wtr_escaper.java b/400_xowa/src/gplx/xowa/html/Xoh_html_wtr_escaper.java index e4e0c36f3..70a1766ab 100644 --- a/400_xowa/src/gplx/xowa/html/Xoh_html_wtr_escaper.java +++ b/400_xowa/src/gplx/xowa/html/Xoh_html_wtr_escaper.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.html; import gplx.*; import gplx.xowa.*; -import gplx.xowa.parsers.amps.*; +import gplx.html.*; import gplx.xowa.parsers.amps.*; public class Xoh_html_wtr_escaper { public static byte[] Escape(Xoa_app app, Bry_bfr tmp_bfr, byte[] src) { Escape(app, tmp_bfr, src, 0, src.length, true, false); @@ -40,17 +40,17 @@ public class Xoh_html_wtr_escaper { } } } - bfr.Add(Xop_xnde_wkr.Bry_escape_lt); + bfr.Add(Html_entity_.Lt_bry); break; case Byte_ascii.Gt: - bfr.Add(Xop_xnde_wkr.Bry_escape_gt); + bfr.Add(Html_entity_.Gt_bry); break; case Byte_ascii.Amp: if (interpret_amp) { int text_bgn = i + 1; // i is &; i + 1 is first char after amp Object o = (text_bgn < end) ? amp_trie.MatchAtCur(src, text_bgn, end) : null; // check if this is a valid &; note must check that text_bgn < end or else arrayIndex error; occurs when src is just "&"; DATE:2013-12-19 if (o == null) // invalid; EX: "a&b"; "&bad;"; "&#letters;"; - bfr.Add(Xop_xnde_wkr.Bry_escape_amp); // escape & and continue + bfr.Add(Html_entity_.Amp_bry); // escape & and continue else { // is either (1) a name or (2) an ncr (hex/dec) Xop_amp_trie_itm itm = (Xop_amp_trie_itm)o; int match_pos = amp_trie.Match_pos(); @@ -67,15 +67,15 @@ public class Xoh_html_wtr_escaper { i = end_pos - 1; } else // parse failed; escape and continue - bfr.Add(Xop_xnde_wkr.Bry_escape_amp); + bfr.Add(Html_entity_.Amp_bry); } } } else - bfr.Add(Xop_xnde_wkr.Bry_escape_amp); + bfr.Add(Html_entity_.Amp_bry); break; case Byte_ascii.Quote: - bfr.Add(Xop_xnde_wkr.Bry_escape_quote); + bfr.Add(Html_entity_.Quote_bry); break; default: bfr.Add_byte(b); diff --git a/400_xowa/src/gplx/xowa/html/Xoh_page_wtr_wkr_.java b/400_xowa/src/gplx/xowa/html/Xoh_page_wtr_wkr_.java index 977eaecd9..7f31e99d4 100644 --- a/400_xowa/src/gplx/xowa/html/Xoh_page_wtr_wkr_.java +++ b/400_xowa/src/gplx/xowa/html/Xoh_page_wtr_wkr_.java @@ -35,7 +35,7 @@ public class Xoh_page_wtr_wkr_ { public static void Bld_head_end(Bry_bfr html_bfr, Xoa_page page) { byte[] head_end = page.Html_data().Custom_head_end(); if (head_end == null) return; - int insert_pos = Bry_finder.Find_fwd(html_bfr.Bfr(), Html_tags.Head_rhs); + int insert_pos = Bry_finder.Find_fwd(html_bfr.Bfr(), Html_tag_.Head_rhs); if (insert_pos == Bry_finder.Not_found) { page.App().Usr_dlg().Warn_many("", "", "could not find "); return; @@ -45,7 +45,7 @@ public class Xoh_page_wtr_wkr_ { public static void Bld_html_end(Bry_bfr html_bfr, Xoa_page page) { byte[] html_end = page.Html_data().Custom_html_end(); if (html_end == null) return; - int insert_pos = Bry_finder.Find_bwd(html_bfr.Bfr(), Html_tags.Html_rhs, html_bfr.Len()); + int insert_pos = Bry_finder.Find_bwd(html_bfr.Bfr(), Html_tag_.Html_rhs, html_bfr.Len()); if (insert_pos == Bry_finder.Not_found) { page.App().Usr_dlg().Warn_many("", "", "could not find "); return; diff --git a/400_xowa/src/gplx/xowa/html/Xohp_title_wkr.java b/400_xowa/src/gplx/xowa/html/Xohp_title_wkr.java index a8be64862..965d76dd8 100644 --- a/400_xowa/src/gplx/xowa/html/Xohp_title_wkr.java +++ b/400_xowa/src/gplx/xowa/html/Xohp_title_wkr.java @@ -34,7 +34,7 @@ public class Xohp_title_wkr implements Bry_fmtr_arg { if (tkn.Tkn_tid() == Xop_tkn_itm_.Tid_xnde) { Xop_xnde_tkn xnde = (Xop_xnde_tkn)tkn; if (xnde.Tag().Id() == Xop_xnde_tag_.Tid_ref) { // if ref, disable tkn - gplx.xowa.xtns.refs.Ref_nde ref_xnde = (gplx.xowa.xtns.refs.Ref_nde)xnde.Xnde_xtn(); + gplx.xowa.xtns.cite.Ref_nde ref_xnde = (gplx.xowa.xtns.cite.Ref_nde)xnde.Xnde_xtn(); ref_xnde.Exists_in_lnki_title_(true); // ref found during html_title_wkr's generation; mark ref; will be ignored by references_html_wtr later; DATE:2014-03-05 } } diff --git a/400_xowa/src/gplx/xowa/html/modules/Xoh_module_wtr.java b/400_xowa/src/gplx/xowa/html/modules/Xoh_module_wtr.java index 36ad3f49c..0709092ed 100644 --- a/400_xowa/src/gplx/xowa/html/modules/Xoh_module_wtr.java +++ b/400_xowa/src/gplx/xowa/html/modules/Xoh_module_wtr.java @@ -33,7 +33,7 @@ public class Xoh_module_wtr { public void Write_css_style_bgn() { reset_bgn = bfr.Len(); Write_nl_and_indent(); - bfr.Add(Html_tags.Style_lhs_w_type); + bfr.Add(Html_tag_.Style_lhs_w_type); Indent_add(); reset_end = bfr.Len(); } @@ -41,7 +41,7 @@ public class Xoh_module_wtr { Indent_del(); if (Reset()) return; Write_nl_and_indent(); - bfr.Add(Html_tags.Style_rhs); + bfr.Add(Html_tag_.Style_rhs); } public void Write_css_style_itm(byte[] bry) { Write_nl_and_indent(); @@ -54,7 +54,7 @@ public class Xoh_module_wtr { public void Write_js_script_bgn() { reset_bgn = bfr.Len(); Write_nl_and_indent(); - bfr.Add(Html_tags.Script_lhs_w_type); + bfr.Add(Html_tag_.Script_lhs_w_type); Indent_add(); reset_end = bfr.Len(); } @@ -62,7 +62,7 @@ public class Xoh_module_wtr { Indent_del(); if (Reset()) return; Write_nl_and_indent(); - bfr.Add(Html_tags.Script_rhs); + bfr.Add(Html_tag_.Script_rhs); } public void Write_js_head_global_bgn() { reset_bgn = bfr.Len(); diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xopg_popup_mgr.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xopg_popup_mgr.java new file mode 100644 index 000000000..b7d003460 --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xopg_popup_mgr.java @@ -0,0 +1,24 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +public class Xopg_popup_mgr { + public OrderedHash Itms() {return itms;} private OrderedHash itms = OrderedHash_.new_(); + public void Clear() { + itms.Clear(); + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_cfg.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_cfg.java new file mode 100644 index 000000000..37762e63c --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_cfg.java @@ -0,0 +1,34 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +import gplx.xowa.apis.xowa.html.modules.*; +public class Xow_popup_cfg { + public int Show_all_if_less_than() {return show_all_if_less_than;} public void Show_all_if_less_than_(int v) {show_all_if_less_than = v;} private int show_all_if_less_than = Xoapi_popups.Dflt_show_all_if_less_than; + public int Tmpl_read_max() {return tmpl_read_max;} public void Tmpl_read_max_(int v) {tmpl_read_max = v;} private int tmpl_read_max = Xoapi_popups.Dflt_scan_max; + public int Tmpl_read_len() {return tmpl_read_len;} public void Tmpl_read_len_(int v) {tmpl_read_len = v;} private int tmpl_read_len = Xoapi_popups.Dflt_scan_len; + public int Read_til_stop_fwd() {return read_til_stop_fwd;} public void Read_til_stop_fwd_(int v) {read_til_stop_fwd = v;} private int read_til_stop_fwd = Xoapi_popups.Dflt_read_til_stop_fwd; + public int Read_til_stop_bwd() {return read_til_stop_bwd;} public void Read_til_stop_bwd_(int v) {read_til_stop_bwd = v;} private int read_til_stop_bwd = Xoapi_popups.Dflt_read_til_stop_bwd; + public int Stop_if_hdr_after() {return stop_if_hdr_after;} public void Stop_if_hdr_after_(int v) {stop_if_hdr_after = v;} private int stop_if_hdr_after = Xoapi_popups.Dflt_stop_if_hdr_after; + public boolean Stop_if_hdr_after_enabled() {return stop_if_hdr_after > 0;} + public byte[] Ellipsis() {return ellipsis;} public void Ellipsis_(byte[] v) {ellipsis = v;} private byte[] ellipsis = Bry_.Empty; + public byte[] Notoc() {return notoc;} public void Notoc_(byte[] v) {notoc = v;} private byte[] notoc = Notoc_const; + public static final byte[] + Notoc_const = Bry_.new_ascii_("\n__NOTOC__") // NOTE: always add a whitespace tkn else __NOTOC__ will be deactivated if last tkn is lnke; DATE:2014-06-22 + , Msg_key_ellipsis = Bry_.new_ascii_("ellipsis") + ; +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder.java new file mode 100644 index 000000000..662b17204 --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder.java @@ -0,0 +1,49 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +class Xow_popup_hdr_finder { + private byte[] src, hdr; + private int src_len; + private int nl_pos; + public int Find(byte[] src, int src_len, byte[] hdr, int bgn) { + this.src = src; this.src_len = src_len; this.hdr = hdr; + int lhs_bgn = bgn; + while (true) { + boolean found = Find_hdr(lhs_bgn); + if (found) return lhs_bgn; + lhs_bgn = Bry_finder.Find_fwd(src, Hdr_bgn, nl_pos, src_len); + if (lhs_bgn == Bry_.NotFound) break; // "\n=" not found; exit; + ++lhs_bgn; // skip \n + } + return Bry_finder.Not_found; + } + private boolean Find_hdr(int lhs_bgn) { + nl_pos = Bry_finder.Find_fwd(src, Byte_ascii.NewLine, lhs_bgn, src_len); // look for \n + if (nl_pos == Bry_finder.Not_found) nl_pos = src_len - 1; // no more \n; set to last idx + int lhs_end = Bry_finder.Find_fwd_while(src, lhs_bgn, nl_pos, Byte_ascii.Eq); // skip eq; EX: "\n===" + int rhs_end = Bry_finder.Find_bwd_non_ws_or_end(src, nl_pos, lhs_end); // skip ws bwd; EX: "== \n" + int rhs_bgn = Bry_finder.Find_bwd_while(src, rhs_end, lhs_end, Byte_ascii.Eq); // skip eq + if (rhs_bgn < lhs_end) return false; // eq found, but < lhs_end; exit; EX: "\n== \n" + ++rhs_bgn; // rhs_bgn is 1st char before eq; position at eq; + if (rhs_end - rhs_bgn < 1) return false; // no eq; exit; EX: "\n==abc \n" + int txt_end = Bry_finder.Find_bwd_non_ws_or_end(src, rhs_bgn, lhs_end); // skip ws before ==; EX: "\n==a ==\n" + int txt_bgn = Bry_finder.Find_fwd_while_space_or_tab(src, lhs_end, nl_pos); // skip spaces after eq + return Bry_.Eq(hdr, src, txt_bgn, txt_end); // check for strict match + } + private static final byte[] Hdr_bgn = Bry_.new_ascii_("\n="); +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder_tst.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder_tst.java new file mode 100644 index 000000000..fb8d0f34f --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_hdr_finder_tst.java @@ -0,0 +1,69 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +import org.junit.*; +import gplx.xowa.apis.xowa.html.modules.*; +import gplx.xowa.gui.views.*; +public class Xow_popup_hdr_finder_tst { + @Before public void init() {fxt.Clear();} private Xop_popup_hdr_finder_fxt fxt = new Xop_popup_hdr_finder_fxt(); + @Test public void Basic() { + String src_str = String_.Concat_lines_nl_skip_last + ( "a" + , "==b1==" + , "c" + ); + fxt.Test_find(src_str, "b1", 2); + fxt.Test_find_not(src_str, "b"); + fxt.Test_find_not(src_str, "a"); + } + @Test public void Mid() { + String src_str = String_.Concat_lines_nl_skip_last + ( "a" + , "==b==" + , "c" + , "==d==" + , "e" + ); + fxt.Test_find(src_str, "d", 10); + } + @Test public void Eos() { + String src_str = String_.Concat_lines_nl_skip_last + ( "a" + , "==b==" + ); + fxt.Test_find(src_str, "b", 2); + } + @Test public void Bos() { + String src_str = String_.Concat_lines_nl_skip_last + ( "==a==" + , "b" + ); + fxt.Test_find(src_str, "a", 0); + } +} +class Xop_popup_hdr_finder_fxt { + private Xow_popup_hdr_finder finder = new Xow_popup_hdr_finder(); + public void Clear() { + } + public void Test_find_not(String src_str, String hdr_str) {Test_find(src_str, hdr_str, Bry_finder.Not_found);} + public void Test_find(String src_str, String hdr_str, int expd) { + byte[] src = Bry_.new_utf8_(src_str); + byte[] hdr = Bry_.new_utf8_(hdr_str); + Tfds.Eq(expd, finder.Find(src, src.length, hdr, 0), hdr_str); + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_html_mkr.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_html_mkr.java new file mode 100644 index 000000000..53a81de02 --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_html_mkr.java @@ -0,0 +1,69 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +import gplx.xowa.apis.xowa.html.modules.*; +public class Xow_popup_html_mkr { + private Xoa_app app; private Xow_wiki wiki; + public Bry_fmtr Fmtr_popup() {return fmtr_popup;} private Bry_fmtr fmtr_popup = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_popup_keys); + public Bry_fmtr Fmtr_viewed() {return fmtr_viewed;} private Bry_fmtr fmtr_viewed = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_viewed_keys); + public Bry_fmtr Fmtr_wiki() {return fmtr_wiki;} private Bry_fmtr fmtr_wiki = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_wiki_keys); + public Bry_fmtr Fmtr_next_sect() {return fmtr_next_sect;} private Bry_fmtr fmtr_next_sect = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmtr_next_sect_keys); + public void Output_js_clean_(boolean v) {output_js_clean = v;} private boolean output_js_clean = true; + public void Output_tidy_(boolean v) {output_tidy = v;} private boolean output_tidy = true; + public void Ctor(Xoa_app app, Xow_wiki wiki) { + this.wiki = wiki; this.app = app; + wiki.Eval_mgr().Eval_mgr_(fmtr_popup, fmtr_viewed, fmtr_wiki, fmtr_next_sect); + } + public byte[] Bld(Xow_wiki cur_wiki, Xoa_page page, Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) { + if (output_js_clean) app.Html_mgr().Js_cleaner().Clean_bfr(wiki, page.Ttl(), wrdx_bfr, 0); + if (output_tidy) app.Html_mgr().Tidy_mgr().Run_tidy_html(page, wrdx_bfr); + byte[] hdom_bry = wrdx_bfr.XtoAryAndClear(); + String page_url = wrdx_bfr.Add(page.Wiki().Domain_bry()).Add(Xoa_consts.Url_wiki_intermediary).Add(app.Url_converter_href() + .Encode(page.Ttl().Full_db())) // NOTE: was page.Url().Raw(), but that doesn't work for Special:Search; PAGE:en.w:Earth and "Quotations"; DATE:2014-06-29 + .XtoStrAndClear() + ; + fmtr_popup.Bld_bfr_many + ( wrdx_bfr + , hdom_bry + , wiki.Lang().Dir_bry() + , page_url + , String_.new_utf8_(page.Ttl().Full_txt()) + , popup_itm.Popup_id() + , Xow_popup_html_bldr_.Bld_fmtr_wiki(fmtr_wiki, wrdx_bfr, cur_wiki.Domain_bry(), page.Wiki().Domain_bry()) // NOTE: use cur_wiki, not page_wiki; DATE:2014-06-28 + , gplx.ios.Io_size_.Xto_str(page.Data_raw().length) + , page.Revision_data().Modified_on().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss() + , Xow_popup_html_bldr_.Bld_fmtr_viewed(fmtr_viewed, app, wiki, wrdx_bfr, page.Ttl()) + , app.Fsys_mgr().Root_dir().To_http_file_bry() + ); + return wrdx_bfr.XtoAryAndClear(); + } +} +class Xow_popup_html_bldr_ { + public static byte[] Bld_fmtr_wiki(Bry_fmtr fmtr, Bry_bfr wrdx_bfr, byte[] wiki_domain, byte[] page_domain) { + return Bry_.Eq(wiki_domain, page_domain) + ? Bry_.Empty // same domain; return ""; + : fmtr.Bld_bry_many(wrdx_bfr, page_domain); + } + public static byte[] Bld_fmtr_viewed(Bry_fmtr fmtr, Xoa_app app, Xow_wiki wiki, Bry_bfr wrdx_bfr, Xoa_ttl ttl) { + byte[] view_time_item = Bry_.Empty; + gplx.xowa.users.history.Xou_history_itm history_itm = app.User().History_mgr().Get_or_null(wiki.Domain_bry(), ttl.Full_txt()); + if (history_itm != null) + view_time_item = fmtr.Bld_bry_many(wrdx_bfr, history_itm.View_end().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss()); + return view_time_item; + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_itm.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_itm.java index f8991a748..9a2e4bc1b 100644 --- a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_itm.java +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_itm.java @@ -25,21 +25,25 @@ public class Xow_popup_itm implements Cancelable { public boolean Canceled() {return canceled;} private boolean canceled = false; public void Cancel() {canceled = true;} public void Cancel_reset() {canceled = false;} - public byte Mode() {return mode;} private byte mode = Mode_init; + public byte Mode() {return mode;} private byte mode = Mode_tid_init; public Xow_popup_itm Mode_more_(int more_words) { - mode = Mode_more; - words_needed = popup_html_word_count + more_words; + mode = Mode_tid_more; + words_needed = words_found + more_words; return this; } + public boolean Mode_all() {return mode == Mode_tid_all;} public Xow_popup_itm Mode_all_() { - mode = Mode_all; + mode = Mode_tid_all; words_needed = Int_.MaxValue; return this; } public String Popup_id() {return popup_id;} private String popup_id; - public byte[] Popup_html() {return popup_html;} public Xow_popup_itm Popup_html_(byte[] v) {popup_html = v; return this;} private byte[] popup_html; + public byte[] Popup_html() {return popup_html;} public void Popup_html_(byte[] v) {popup_html = v;} private byte[] popup_html; + public byte[] Wiki_domain() {return wiki_domain;} private byte[] wiki_domain; public byte[] Page_href() {return page_href;} private byte[] page_href; - public int Popup_html_word_count() {return popup_html_word_count;} public void Popup_html_word_count_(int v) {popup_html_word_count = v;} private int popup_html_word_count; + public Xoa_ttl Page_ttl() {return page_ttl;} private Xoa_ttl page_ttl; + public void Init(byte[] wiki_domain, Xoa_ttl page_ttl) {this.wiki_domain = wiki_domain; this.page_ttl = page_ttl;} public int Words_needed() {return words_needed;} private int words_needed; - public static final byte Mode_init = 0, Mode_more = 1, Mode_all = 2; + public int Words_found() {return words_found;} public void Words_found_(int v) {words_found = v;} private int words_found; + public static final byte Mode_tid_init = 0, Mode_tid_more = 1, Mode_tid_all = 2; } diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_mgr.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_mgr.java index 34f56acff..4488573e6 100644 --- a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_mgr.java +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_mgr.java @@ -37,26 +37,27 @@ public class Xow_popup_mgr implements GfoInvkAble, GfoEvObj { show_init_word_count = api_popups.Show_init_word_count(); show_more_word_count = api_popups.Show_more_word_count(); Ns_allowed_(api_popups.Ns_allowed()); - parser.Show_all_if_less_than_(api_popups.Show_all_if_less_than()); - parser.Xnde_ignore_ids_(api_popups.Xnde_ignore_ids()); - parser.Scan_len_(api_popups.Scan_len()); - parser.Scan_max_(api_popups.Scan_max()); - parser.Html_fmtr().Fmt_(api_popups.Html_fmt()); - parser.Read_til_stop_fwd_(api_popups.Read_til_stop_fwd()); - parser.Read_til_stop_bwd_(api_popups.Read_til_stop_bwd()); + parser.Cfg().Show_all_if_less_than_(api_popups.Show_all_if_less_than()); + parser.Cfg().Tmpl_read_len_(api_popups.Scan_len()); + parser.Cfg().Tmpl_read_max_(api_popups.Scan_max()); + parser.Cfg().Read_til_stop_fwd_(api_popups.Read_til_stop_fwd()); + parser.Cfg().Read_til_stop_bwd_(api_popups.Read_til_stop_bwd()); + parser.Cfg().Stop_if_hdr_after_(api_popups.Stop_if_hdr_after()); parser.Tmpl_tkn_max_(api_popups.Tmpl_tkn_max()); + if (!Env_.Mode_testing()) + parser.Tmpl_keeplist_init_(api_popups.Tmpl_keeplist()); + parser.Wrdx_mkr().Xnde_ignore_ids_(api_popups.Xnde_ignore_ids()); + parser.Html_mkr().Fmtr_popup().Fmt_(api_popups.Html_fmtr_popup()); + parser.Html_mkr().Fmtr_viewed().Fmt_(api_popups.Html_fmtr_viewed()); + parser.Html_mkr().Fmtr_wiki().Fmt_(api_popups.Html_fmtr_wiki()); + parser.Html_mkr().Fmtr_next_sect().Fmt_(api_popups.Html_fmtr_next_sect_fmt()); GfoEvMgr_.SubSame_many(api_popups, this - , Xoapi_popups.Evt_show_init_word_count_changed - , Xoapi_popups.Evt_show_more_word_count_changed - , Xoapi_popups.Evt_show_all_if_less_than_changed - , Xoapi_popups.Evt_xnde_ignore_ids_changed - , Xoapi_popups.Evt_scan_len_changed - , Xoapi_popups.Evt_scan_max_changed - , Xoapi_popups.Evt_html_fmt_changed - , Xoapi_popups.Evt_read_til_stop_fwd_changed - , Xoapi_popups.Evt_read_til_stop_bwd_changed + , Xoapi_popups.Evt_show_init_word_count_changed, Xoapi_popups.Evt_show_more_word_count_changed , Xoapi_popups.Evt_show_all_if_less_than_changed + , Xoapi_popups.Evt_scan_len_changed, Xoapi_popups.Evt_scan_max_changed + , Xoapi_popups.Evt_read_til_stop_fwd_changed, Xoapi_popups.Evt_read_til_stop_bwd_changed, Xoapi_popups.Evt_stop_if_hdr_after_changed , Xoapi_popups.Evt_ns_allowed_changed - , Xoapi_popups.Evt_tmpl_tkn_max_changed + , Xoapi_popups.Evt_xnde_ignore_ids_changed, Xoapi_popups.Evt_tmpl_tkn_max_changed, Xoapi_popups.Evt_tmpl_keeplist_changed + , Xoapi_popups.Evt_html_fmtr_popup_changed, Xoapi_popups.Evt_html_fmtr_viewed_changed, Xoapi_popups.Evt_html_fmtr_wiki_changed, Xoapi_popups.Evt_html_fmtr_next_sect_changed ); } public String Show_init(byte[] href, int id) { @@ -93,14 +94,15 @@ public class Xow_popup_mgr implements GfoInvkAble, GfoEvObj { try { synchronized (async_thread_guard) { if (itm.Canceled()) return null; - cur_page.Popup_itms().AddReplace(itm.Popup_id(), itm); + cur_page.Popup_mgr().Itms().AddReplace(itm.Popup_id(), itm); app.Href_parser().Parse(temp_href, itm.Page_href(), wiki, cur_page.Ttl().Page_url()); Xow_wiki popup_wiki = app.Wiki_mgr().Get_by_key_or_null(temp_href.Wiki()); popup_wiki.Init_assert(); Xoa_ttl popup_ttl = Xoa_ttl.parse_(popup_wiki, temp_href.Page()); if (ns_allowed_regy.Count() > 0 && !ns_allowed_regy.Has(ns_allowed_regy_key.Val_(popup_ttl.Ns().Id()))) return Bry_.Empty; + itm.Init(popup_wiki.Domain_bry(), popup_ttl); Xoa_page popup_page = popup_wiki.Data_mgr().Get_page(popup_ttl, false); - byte[] rv = popup_wiki.Html_mgr().Module_mgr().Popup_mgr().Parser().Parse(itm, popup_page, wiki.Domain_bry(), cur_page.Tab()); + byte[] rv = popup_wiki.Html_mgr().Module_mgr().Popup_mgr().Parser().Parse(wiki, popup_page, cur_page.Tab(), itm); Xog_win_itm__prog_href_mgr.Hover(app, cur_page, String_.new_utf8_(itm.Page_href())); // set page ttl again in prog bar; DATE:2014-06-28 return rv; } @@ -163,20 +165,26 @@ public class Xow_popup_mgr implements GfoInvkAble, GfoEvObj { return (Int_obj_ref[])rv.XtoAry(Int_obj_ref.class); } private HashAdp ns_allowed_regy = HashAdp_.new_(); private Int_obj_ref ns_allowed_regy_key = Int_obj_ref.zero_(); private Xoa_page Cur_page() {return app.Gui_mgr().Browser_win().Active_page();} - private Xow_popup_itm Itms_get_or_null(Xoa_page page, String popup_id) {return (Xow_popup_itm)page.Popup_itms().Fetch(popup_id);} + private Xow_popup_itm Itms_get_or_null(Xoa_page page, String popup_id) {return (Xow_popup_itm)page.Popup_mgr().Itms().Fetch(popup_id);} public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_show_popup_async)) Show_popup_async(); else if (ctx.Match(k, Invk_show_popup)) Show_popup(); else if (ctx.Match(k, Xoapi_popups.Evt_show_init_word_count_changed)) show_init_word_count = m.ReadInt("v"); else if (ctx.Match(k, Xoapi_popups.Evt_show_more_word_count_changed)) show_more_word_count = m.ReadInt("v"); - else if (ctx.Match(k, Xoapi_popups.Evt_show_all_if_less_than_changed)) parser.Show_all_if_less_than_(m.ReadInt("v")); - else if (ctx.Match(k, Xoapi_popups.Evt_xnde_ignore_ids_changed)) parser.Xnde_ignore_ids_(m.ReadBry("v")); - else if (ctx.Match(k, Xoapi_popups.Evt_scan_len_changed)) parser.Scan_len_(m.ReadInt("v")); - else if (ctx.Match(k, Xoapi_popups.Evt_scan_max_changed)) parser.Scan_max_(m.ReadInt("v")); - else if (ctx.Match(k, Xoapi_popups.Evt_html_fmt_changed)) parser.Html_fmtr().Fmt_(m.ReadBry("v")); - else if (ctx.Match(k, Xoapi_popups.Evt_read_til_stop_fwd_changed)) parser.Read_til_stop_fwd_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_show_all_if_less_than_changed)) parser.Cfg().Show_all_if_less_than_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_xnde_ignore_ids_changed)) parser.Wrdx_mkr().Xnde_ignore_ids_(m.ReadBry("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_scan_len_changed)) parser.Cfg().Tmpl_read_len_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_scan_max_changed)) parser.Cfg().Tmpl_read_max_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_read_til_stop_bwd_changed)) parser.Cfg().Read_til_stop_bwd_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_read_til_stop_fwd_changed)) parser.Cfg().Read_til_stop_fwd_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_stop_if_hdr_after_changed)) parser.Cfg().Stop_if_hdr_after_(m.ReadInt("v")); else if (ctx.Match(k, Xoapi_popups.Evt_ns_allowed_changed)) Ns_allowed_(m.ReadBry("v")); else if (ctx.Match(k, Xoapi_popups.Evt_tmpl_tkn_max_changed)) parser.Tmpl_tkn_max_(m.ReadInt("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_tmpl_keeplist_changed)) parser.Tmpl_keeplist_init_(m.ReadBry("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_html_fmtr_popup_changed)) parser.Html_mkr().Fmtr_popup().Fmt_(m.ReadBry("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_html_fmtr_viewed_changed)) parser.Html_mkr().Fmtr_viewed().Fmt_(m.ReadBry("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_html_fmtr_wiki_changed)) parser.Html_mkr().Fmtr_wiki().Fmt_(m.ReadBry("v")); + else if (ctx.Match(k, Xoapi_popups.Evt_html_fmtr_next_sect_changed)) parser.Html_mkr().Fmtr_next_sect().Fmt_(m.ReadBry("v")); else return GfoInvkAble_.Rv_unhandled; return this; } diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser.java index 6cc153d83..2760f04f9 100644 --- a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser.java +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser.java @@ -16,388 +16,187 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; -import gplx.html.*; import gplx.xowa.apis.xowa.html.modules.*; -import gplx.xowa.parsers.lnkes.*; import gplx.xowa.gui.views.*; +import gplx.xowa.html.modules.popups.keeplists.*; public class Xow_popup_parser { private Xoa_app app; private Xow_wiki wiki; private Xop_parser parser; - private ByteTrieMgr_fast orig_trie, wtxt_trie; private Xop_tkn_mkr tkn_mkr; - private Xop_ctx orig_ctx; private Xop_root_tkn orig_root, wtxt_root; private Xot_compile_data orig_props = new Xot_compile_data(); - private Bry_bfr hdom_bfr = Bry_bfr.reset_(255); + private ByteTrieMgr_fast tmpl_trie, wtxt_trie; private Xop_tkn_mkr tkn_mkr; + private Xop_ctx tmpl_ctx; private Xop_root_tkn tmpl_root, wtxt_root; private Xot_compile_data tmpl_props = new Xot_compile_data(); private Xoh_html_wtr_ctx hctx = Xoh_html_wtr_ctx.Popup; - private boolean add_wtxt_skip_space = false; - private boolean stop_at_hdr_done; - private int words_found; - private int words_needed = -1; - private Cancelable cancelable; private Bry_bfr tmp_bfr = Bry_bfr.reset_(32); + public Xow_popup_cfg Cfg() {return cfg;} private Xow_popup_cfg cfg = new Xow_popup_cfg(); + public Xow_popup_wrdx_mkr Wrdx_mkr() {return wrdx_mkr;} private Xow_popup_wrdx_mkr wrdx_mkr = new Xow_popup_wrdx_mkr(); + public Xow_popup_html_mkr Html_mkr() {return html_mkr;} private Xow_popup_html_mkr html_mkr = new Xow_popup_html_mkr(); + public Xow_popup_parser_data Data() {return data;} private Xow_popup_parser_data data = new Xow_popup_parser_data(); + public Xop_keeplist_wiki Tmpl_keeplist() {return tmpl_keeplist;} private Xop_keeplist_wiki tmpl_keeplist; // private byte[] tmpl_keeplist_bry = Bry_.Empty; public Xop_ctx Wtxt_ctx() {return wtxt_ctx;} private Xop_ctx wtxt_ctx; - private ListAdp words_found_list = ListAdp_.new_(); - public int Scan_len() {return scan_len;} public void Scan_len_(int v) {scan_len = v;} private int scan_len = Xoapi_popups.Dflt_scan_len; - public int Scan_max() {return scan_max;} public void Scan_max_(int v) {scan_max = v;} private int scan_max = Xoapi_popups.Dflt_scan_max; - public int Show_all_if_less_than() {return show_all_if_less_than;} public void Show_all_if_less_than_(int v) {show_all_if_less_than = v;} private int show_all_if_less_than = Xoapi_popups.Dflt_show_all_if_less_than; - public byte[] Ellipsis() {return ellipsis;} public void Ellipsis_(byte[] v) {ellipsis = v;} private byte[] ellipsis = Ellipsis_const; - public byte[] Notoc() {return notoc;} public void Notoc_(byte[] v) {notoc = v;} private byte[] notoc = Notoc_const; - public boolean Stop_at_hdr() {return stop_at_hdr;} public void Stop_at_hdr_(boolean v) {stop_at_hdr = v;} private boolean stop_at_hdr = false; - public boolean Output_js_clean() {return output_js_clean;} public void Output_js_clean_(boolean v) {output_js_clean = v;} private boolean output_js_clean = true; - public boolean Output_tidy() {return output_tidy;} public void Output_tidy_(boolean v) {output_tidy = v;} private boolean output_tidy = true; - public int Read_til_stop_fwd() {return read_til_stop_fwd;} public void Read_til_stop_fwd_(int v) {read_til_stop_fwd = v;} private int read_til_stop_fwd = Xoapi_popups.Dflt_read_til_stop_fwd; - public int Read_til_stop_bwd() {return read_til_stop_bwd;} public void Read_til_stop_bwd_(int v) {read_til_stop_bwd = v;} private int read_til_stop_bwd = Xoapi_popups.Dflt_read_til_stop_bwd; - public int Tmpl_tkn_max() {return tmpl_tkn_max;} public void Tmpl_tkn_max_(int v) { if (v < 0) v = Int_.MaxValue; // allow -1 as shortcut to deactivate - orig_ctx.Tmpl_tkn_max_(v); + tmpl_ctx.Tmpl_tkn_max_(v); wtxt_ctx.Tmpl_tkn_max_(v); - } private int tmpl_tkn_max = Xoapi_popups.Dflt_tmpl_tkn_max; - public Bry_fmtr Html_fmtr() {return html_fmtr;} + } public void Init_by_wiki(Xow_wiki wiki) { this.wiki = wiki; this.app = wiki.App(); this.parser = wiki.Parser(); this.tkn_mkr = app.Tkn_mkr(); - this.orig_ctx = Xop_ctx.new_(wiki); this.wtxt_ctx = Xop_ctx.new_(wiki); - Xop_lxr_mgr orig_lxr_mgr = Xop_lxr_mgr.Popup_lxr_mgr; - orig_lxr_mgr.Init_by_wiki(wiki); - this.orig_trie = orig_lxr_mgr.Trie(); this.wtxt_trie = parser.Wtxt_lxr_mgr().Trie(); - orig_ctx.Parse_tid_(Xop_parser_.Parse_tid_page_tmpl); wtxt_ctx.Parse_tid_(Xop_parser_.Parse_tid_page_wiki); - orig_ctx.Xnde_names_tid_(Xop_parser_.Parse_tid_page_wiki); - orig_ctx.Tid_is_popup_(true); wtxt_ctx.Tid_is_popup_(true); - orig_root = tkn_mkr.Root(Bry_.Empty); wtxt_root = tkn_mkr.Root(Bry_.Empty); - html_fmtr.Eval_mgr_(wiki.Eval_mgr()); - view_time_fmtr.Eval_mgr_(wiki.Eval_mgr()); - xwiki_fmtr.Eval_mgr_(wiki.Eval_mgr()); - ellipsis = wiki.Msg_mgr().Val_by_key_obj(Msg_key_ellipsis); - } private static byte[] Msg_key_ellipsis = Bry_.new_ascii_("ellipsis"); - private Hash_adp_bry xnde_id_ignore_list = Hash_adp_bry.ci_ascii_(); - public void Xnde_ignore_ids_(byte[] xnde_id_ignore_bry) { - byte[][] ary = Bry_.Split(xnde_id_ignore_bry, Byte_ascii.Pipe); - int ary_len = ary.length; - xnde_id_ignore_list.Clear(); - for (int i = 0; i < ary_len; i++) { - byte[] bry = ary[i]; - if (bry.length == 0) continue; // ignore empty entries; EX: "a|" - xnde_id_ignore_list.Add(bry, bry); - } + this.tmpl_ctx = Xop_ctx.new_(wiki); this.wtxt_ctx = Xop_ctx.new_(wiki); + Xop_lxr_mgr tmpl_lxr_mgr = Xop_lxr_mgr.Popup_lxr_mgr; + tmpl_lxr_mgr.Init_by_wiki(wiki); + this.tmpl_trie = tmpl_lxr_mgr.Trie(); this.wtxt_trie = parser.Wtxt_lxr_mgr().Trie(); + tmpl_ctx.Parse_tid_(Xop_parser_.Parse_tid_page_tmpl); wtxt_ctx.Parse_tid_(Xop_parser_.Parse_tid_page_wiki); + tmpl_ctx.Xnde_names_tid_(Xop_parser_.Parse_tid_page_wiki); + tmpl_ctx.Tid_is_popup_(true); wtxt_ctx.Tid_is_popup_(true); + tmpl_root = tkn_mkr.Root(Bry_.Empty); wtxt_root = tkn_mkr.Root(Bry_.Empty); + html_mkr.Ctor(app, wiki); + cfg.Ellipsis_(wiki.Msg_mgr().Val_by_key_obj(Xow_popup_cfg.Msg_key_ellipsis)); } - private int words_needed_orig = -1; - public byte[] Parse(Xow_popup_itm popup_itm, Xoa_page page, byte[] cur_wiki_domain, Xog_tab_itm cur_tab) { - byte[] orig_src = page.Data_raw(); int orig_len = orig_src.length; if (orig_len == 0) return Bry_.Empty; - String page_url = hdom_bfr.Add(page.Wiki().Domain_bry()).Add(Xoa_consts.Url_wiki_intermediary).Add(app.Url_converter_href() - .Encode(page.Ttl().Full_db())) // NOTE: was page.Url().Raw(), but that doesn't work for Special:Search; PAGE:en.w:Earth and "Quotations"; DATE:2014-06-29 - .XtoStrAndClear() - ; - this.cancelable = popup_itm; - int orig_pos = Xop_parser_.Doc_bgn_bos; - orig_ctx.Clear(); - orig_ctx.Cur_page().Ttl_(page.Ttl()); // NOTE: must set cur_page, else page-dependent templates won't work; EX: {{FULLPAGENAME}}; PAGE:en.w:June_20; DATE:2014-06-20 - orig_ctx.Page_bgn(orig_root, orig_src); - Wtxt_ctx_init(true, orig_src); - orig_ctx.Cur_page().Ttl_(page.Ttl()); // NOTE: must set cur_page, or rel lnkis won't work; EX: [[../A]] - hdom_bfr.Clear(); - int scan_cur = scan_len; - words_found_list.Clear(); - words_needed = popup_itm.Words_needed(); words_found = 0; stop_at_hdr_done = false; - if (read_til_stop_fwd > 0 && words_needed != Int_.MaxValue) { - words_needed_orig = words_needed; - words_needed += read_til_stop_fwd; + public void Tmpl_keeplist_(Xop_keeplist_wiki v) {this.tmpl_keeplist = v;} + public void Tmpl_keeplist_init_(byte[] raw) { + if (tmpl_keeplist == null) { + tmpl_keeplist = new Xop_keeplist_wiki(wiki); + tmpl_ctx.Tmpl_keeplist_(tmpl_keeplist); } - else - words_needed_orig = -1; - if (orig_len < show_all_if_less_than) words_needed = Int_.MaxValue; - if (words_needed == Int_.MaxValue) scan_max = Int_.MaxValue; // if max words, automatically set scan to max - while (words_found < words_needed) { - if (cancelable.Canceled()) return null; - orig_root.Clear(); - int orig_end = orig_pos + scan_cur; if (orig_end > orig_len) orig_end = orig_len; // limit to orig_len; EX: page is 16 bytes, but block is 1024 - if (cur_tab != null && cur_tab.Tab_is_loading()) return null; - int new_pos = parser.Parse_to_stack_end(orig_root, orig_ctx, tkn_mkr, orig_src, orig_len, orig_trie, orig_pos, orig_end); - if (cur_tab != null && cur_tab.Tab_is_loading()) return null; - byte[] wtxt_bry = Parse_to_wtxt(orig_src); - int wtxt_len = wtxt_bry.length; // if (wtxt_len == 0) {break;}// no wtxt; continue; EX: blank page + if (!Bry_.HasAtEnd(raw, Byte_ascii.NewLine_bry)) raw = Bry_.Add(raw, Byte_ascii.NewLine_bry); + tmpl_keeplist.Srl().Load_by_bry(raw); + } + private boolean Canceled(Xow_popup_itm popup_itm, Xog_tab_itm cur_tab) {return popup_itm.Canceled() || cur_tab != null && cur_tab.Tab_is_loading();} + private void Init_ctxs(byte[] tmpl_src, Xoa_ttl ttl) { + tmpl_ctx.Clear(); + tmpl_ctx.Cur_page().Ttl_(ttl); // NOTE: must set cur_page, else page-dependent templates won't work; EX: {{FULLPAGENAME}}; PAGE:en.w:June_20; DATE:2014-06-20 + tmpl_ctx.Cur_page().Html_data().Restricted_(data.Html_restricted()); // NOTE: must set data.Html_restricted() if Special:XowaPopupHistory + tmpl_ctx.Page_bgn(tmpl_root, tmpl_src); + Wtxt_ctx_init(true, tmpl_src); + wtxt_ctx.Cur_page().Ttl_(ttl); // NOTE: must set cur_page, or rel lnkis won't work; EX: [[../A]] + } + public byte[] Parse(Xow_wiki cur_wiki, Xoa_page page, Xog_tab_itm cur_tab, Xow_popup_itm popup_itm) { // NOTE: must pass cur_wiki for xwiki label; DATE:2014-07-02 + byte[] tmpl_src = page.Data_raw(); int tmpl_len = tmpl_src.length; if (tmpl_len == 0) return Bry_.Empty; + int tmpl_bgn = Xop_parser_.Doc_bgn_bos; + int tmpl_read_len_cur = cfg.Tmpl_read_len(); + wrdx_mkr.Init(); + data.Init(cfg, popup_itm, tmpl_len); + Init_ctxs(tmpl_src, page.Ttl()); + while (data.Words_needed_chk()) { + if (Canceled(popup_itm, cur_tab)) return null; + tmpl_root.Clear(); + int tmpl_end = tmpl_bgn + tmpl_read_len_cur; if (tmpl_end > tmpl_len) tmpl_end = tmpl_len; // limit to tmpl_len; EX: page is 16 bytes, but block is 1024 + int new_tmpl_bgn = parser.Parse_to_stack_end(tmpl_root, tmpl_ctx, tkn_mkr, tmpl_src, tmpl_len, tmpl_trie, tmpl_bgn, tmpl_end); + if (Canceled(popup_itm, cur_tab)) return null; + byte[] wtxt_bry = Parse_to_wtxt(tmpl_src); + int wtxt_len = wtxt_bry.length; wtxt_root.Clear(); - int wtxt_bgn = (orig_pos == Xop_parser_.Doc_bgn_bos) ? Xop_parser_.Doc_bgn_bos : 0; // if first pass, parse from -1; needed for lxrs which assume nl at bos; EX: "*a" - if (cur_tab != null && cur_tab.Tab_is_loading()) return null; + int wtxt_bgn = (tmpl_bgn == Xop_parser_.Doc_bgn_bos) ? Xop_parser_.Doc_bgn_bos : 0; // if first pass, parse from -1; needed for lxrs which assume nl at bos; EX: "*a" + if (Canceled(popup_itm, cur_tab)) return null; parser.Parse_to_src_end(wtxt_root, wtxt_ctx, tkn_mkr, wtxt_bry, wtxt_trie, wtxt_bgn, wtxt_len); - if ( wtxt_ctx.Stack_len() > 0 // dangling lnki / hdr / tblw - && (orig_pos + scan_cur) < scan_max // too much read; stop and give whatever's available; PAGE:en.w:List_of_air_forces; DATE:2014-06-18 - && scan_cur < orig_len // only reparse if scan_cur is < entire page; needed for pages which have dangling items; EX:"a" + if ( wtxt_ctx.Stack_len() > 0 // dangling lnki / hdr / tblw + && (tmpl_bgn + tmpl_read_len_cur) < data.Tmpl_max() // too much read; stop and give whatever's available; PAGE:en.w:List_of_air_forces; DATE:2014-06-18 + && tmpl_read_len_cur < tmpl_len // only reparse if tmpl_read_len_cur is < entire page; needed for pages which have dangling items; EX:"a" ) { - new_pos = orig_pos; //;stack_0.Src_bgn(); - scan_cur += scan_len; + new_tmpl_bgn = tmpl_bgn; + tmpl_read_len_cur += cfg.Tmpl_read_len(); wtxt_ctx.Clear(); } else { - Add_to_hdom_bfr(wtxt_root, wtxt_bry, wtxt_len); - scan_cur = scan_len; + wrdx_mkr.Process_tkn(cfg, data, data.Wrdx_bfr(), wtxt_root, wtxt_bry, wtxt_len); + tmpl_read_len_cur = cfg.Tmpl_read_len(); } - orig_pos = new_pos; - if ( orig_pos == orig_len - || orig_pos > scan_max // too much read; stop and give whatever's available - ) break; + tmpl_bgn = new_tmpl_bgn; + if ( tmpl_bgn == tmpl_len // end of template + || tmpl_bgn > data.Tmpl_max() // too much read; stop and give whatever's available + ) + break; } - Adjust_for_header(); - if ( words_found >= words_needed // don't add ellipsis if words_found < words_needed. note that it will add "..." if words_on_page == words_needed; DATE:2014-06-18 - && !stop_at_hdr_done // don't add ellipsis if stopped at hdr - ) - hdom_bfr.Add(ellipsis); - if (cancelable.Canceled()) return null; - if (cur_tab != null && cur_tab.Tab_is_loading()) return null; - byte[] rv = Parse_to_html(page); - html_fmtr.Bld_bfr_many(hdom_bfr - , rv - , wiki.Lang().Dir_bry() - , page_url, String_.new_utf8_(page.Ttl().Full_txt()) - , cur_wiki_domain // NOTE: use cur_wiki, not page_wiki; DATE:2014-06-28 - , Get_xwiki_item(tmp_bfr, cur_wiki_domain, page.Wiki().Domain_bry()) - , gplx.ios.Io_size_.Xto_str(page.Data_raw().length), page.Revision_data().Modified_on().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss() - , Get_view_time(page.Ttl()) - , app.Fsys_mgr().Root_dir().To_http_file_bry() - , popup_itm.Popup_id() - ); - if (cancelable.Canceled()) return null; - popup_itm.Popup_html_word_count_(words_found); - return hdom_bfr.XtoAryAndClear(); + if (Canceled(popup_itm, cur_tab)) return null; + Parse_wrdx_to_html(popup_itm, data.Wrdx_bfr()); + byte[] rv = html_mkr.Bld(cur_wiki, page, popup_itm, data.Wrdx_bfr()); + return (Canceled(popup_itm, cur_tab)) ? null : rv; } - private void Adjust_for_header() { - Xow_popup_word[] words_found_ary = (Xow_popup_word[])words_found_list.XtoAryAndClear(Xow_popup_word.class); - int words_found_all = words_found_ary.length; - boolean read_til_stop_done = false; - if (read_til_stop_fwd != -1 && words_needed_orig != -1) { - Xow_popup_word hdr_word = null; - for (int i = words_needed_orig; i < words_found_all; ++i) { - Xow_popup_word word = words_found_ary[i]; + private void Parse_wrdx_to_html(Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) { + Adjust_wrdx_end(popup_itm, wrdx_bfr); + wrdx_bfr.Add(cfg.Notoc()); // always add notoc at end + byte[] wrdx_bry = wrdx_bfr.XtoAryAndClear(); + wtxt_root.Clear(); // now start parsing wrdx_bry from wtxt to html + Wtxt_ctx_init(false, wrdx_bry); + parser.Parse_to_src_end(wtxt_root, wtxt_ctx, tkn_mkr, wrdx_bry, wtxt_trie, Xop_parser_.Doc_bgn_bos, wrdx_bry.length); + wtxt_ctx.Page_end(wtxt_root, wrdx_bry, wrdx_bry.length); + wiki.Html_mgr().Html_wtr().Write_all(wrdx_bfr, wtxt_ctx, hctx, wrdx_bry, wtxt_root); + } + private void Adjust_wrdx_end(Xow_popup_itm popup_itm, Bry_bfr wrdx_bfr) { + popup_itm.Words_found_(data.Words_found()); + if (popup_itm.Mode_all()) return; // mode_all needs no adjustments + Xow_popup_word[] words = data.Words_found_ary(); + int words_len = words.length; + int last_word_idx = -1; Xow_popup_word last_hdr_tkn = null; + int words_needed_val = data.Words_needed_val(); + if (cfg.Read_til_stop_fwd() != -1) { + for (int i = words_needed_val; i < words_len; ++i) { // find hdr after orig + Xow_popup_word word = words[i]; if (word.Tid() == Xop_tkn_itm_.Tid_hdr) { - hdr_word = word; + last_hdr_tkn = word; break; } } - if (hdr_word == null) { - if (words_needed_orig < words_found_all) { - hdr_word = words_found_ary[words_needed_orig - 1]; - hdom_bfr.Delete_rng_to_end(hdr_word.Bfr_end()); - } - } - else { - hdr_word = words_found_ary[hdr_word.Idx() - 1]; - hdom_bfr.Delete_rng_to_end(hdr_word.Bfr_end()); - read_til_stop_done = true; - } + last_word_idx = (last_hdr_tkn == null) // no hdr found + ? words_needed_val - ListAdp_.Base1 // get last word + : last_hdr_tkn.Idx() - 1 // get word before hdr + ; + if (last_word_idx >= words_len) + last_word_idx = -1; } - if ( read_til_stop_bwd != -1 - && !read_til_stop_done + boolean page_partially_parsed = data.Words_found() == data.Words_needed_max(); // adhoc way of figuring out if parsing prematurely stopped before eos; PAGE:en.q:Anaximander DATE:2014-07-02 + if ( cfg.Read_til_stop_bwd() != -1 + && page_partially_parsed // never read bwd if entire tmpl is read; DATE:2014-07-01 ) { -// Xow_popup_word hdr_word = null; -// for (int i = words_needed_orig; i < words_found_all; ++i) { -// Xow_popup_word word = words_found_ary[i]; -// if (word.Tid() == Xop_tkn_itm_.Tid_hdr) { -// hdr_word = word; -// break; -// } -// } + int read_bwd_end = last_word_idx == -1 ? words_len - 1 : last_word_idx; // if !cfg.Read_til_stop_fwd() use last_wrd, else use read_fwd's last_word + int read_bwd_bgn = read_bwd_end - cfg.Read_til_stop_bwd(); + if (read_bwd_bgn > -1) { // handle pages with "==a==" near start + int last_hdr_idx = -1; + for (int i = read_bwd_end; i >= read_bwd_bgn; i--) { + Xow_popup_word word = words[i]; + if (word.Tid() == Xop_tkn_itm_.Tid_hdr) { + if (last_hdr_idx == -1) // last_hdr_idx not set + last_hdr_idx = i; // set it + else { // last_hdr_idx set + if (i + 1 == last_hdr_idx) // two consecutive hdrs; update earlier and continue + last_hdr_idx = i; + else // earlier hdr; ignore it and take later one + break; + } + last_hdr_tkn = word; + } + } + if (last_hdr_idx != -1) // hdr found + last_word_idx = last_hdr_idx - 1; // get word before last_word_idx + } + } + if (last_word_idx != -1) { + Xow_popup_word last_word = words[last_word_idx]; + wrdx_bfr.Delete_rng_to_end(last_word.Bfr_end());// delete everything after last_word + popup_itm.Words_found_(last_word_idx + ListAdp_.Base1); // last_word_idx = 0 -> words_found = 1 + if (last_word.Tid() == Xop_tkn_itm_.Tid_hdr) // on odd case where hdr is still last word, add \n else text will literally be "==A==" b/c no trailing \n + wrdx_bfr.Add_byte_nl(); + } + if (last_hdr_tkn != null) { + wrdx_bfr.Trim_end(Byte_ascii.NewLine); + byte[] last_hdr_bry = ((Xop_hdr_tkn)last_hdr_tkn.Tkn()).Hdr_toc_text(); + html_mkr.Fmtr_next_sect().Bld_bfr_one(wrdx_bfr, last_hdr_bry); + } + else { + if (page_partially_parsed) + wrdx_bfr.Add(cfg.Ellipsis()); } - } - private byte[] Parse_to_wtxt(byte[] src) { - int subs_len = orig_root.Subs_len(); - for (int i = 0; i < subs_len; i++) - orig_root.Subs_get(i).Tmpl_compile(orig_ctx, src, orig_props); - return Xot_tmpl_wtr._.Write_all(orig_ctx, orig_root, src); - } - private byte[] Parse_to_html(Xoa_page page) { - hdom_bfr.Add(notoc); - byte[] hdom_bry = hdom_bfr.XtoAryAndClear(); - wtxt_root.Clear(); - Wtxt_ctx_init(Bool_.N, hdom_bry); - parser.Parse_to_src_end(wtxt_root, wtxt_ctx, tkn_mkr, hdom_bry, wtxt_trie, Xop_parser_.Doc_bgn_bos, hdom_bry.length); - wtxt_ctx.Page_end(wtxt_root, hdom_bry, hdom_bry.length); - wiki.Html_mgr().Html_wtr().Write_all(hdom_bfr, wtxt_ctx, hctx, hdom_bry, wtxt_root); - app.Html_mgr().Js_cleaner().Clean_bfr(wiki, page.Ttl(), hdom_bfr, 0); - if (output_tidy) - app.Html_mgr().Tidy_mgr().Run_tidy_html(page, hdom_bfr); - return hdom_bfr.XtoAryAndClear(); } private void Wtxt_ctx_init(boolean incremental, byte[] bry) { wtxt_ctx.Clear(); + wtxt_ctx.Cur_page().Html_data().Restricted_(data.Html_restricted()); wtxt_ctx.Para().Enabled_(!incremental); // NOTE: if incremental, disable para; easier to work with \n rather than

    ; also, must be enabled before Page_bgn; DATE:2014-06-18DATE:2014-06-18 wtxt_ctx.Lnke().Dangling_goes_on_stack_(incremental); wtxt_ctx.Page_bgn(wtxt_root, bry); } - private byte[] Get_view_time(Xoa_ttl ttl) { - byte[] view_time_item = Bry_.Empty; - gplx.xowa.users.history.Xou_history_itm history_itm = app.User().History_mgr().Get_or_null(wiki.Domain_bry(), ttl.Full_txt()); - if (history_itm != null) - view_time_item = view_time_fmtr.Bld_bry_many(hdom_bfr, history_itm.View_end().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss()); - return view_time_item; + private byte[] Parse_to_wtxt(byte[] src) { + int subs_len = tmpl_root.Subs_len(); + for (int i = 0; i < subs_len; i++) + tmpl_root.Subs_get(i).Tmpl_compile(tmpl_ctx, src, tmpl_props); + return Xot_tmpl_wtr._.Write_all(tmpl_ctx, tmpl_root, src); } - private byte[] Get_xwiki_item(Bry_bfr tmp_bfr, byte[] wiki_domain, byte[] page_domain) { - return Bry_.Eq(wiki_domain, page_domain) - ? Bry_.Empty // same domain; return ""; - : xwiki_fmtr.Bld_bry_many(tmp_bfr, page_domain); - } - private void Increment_words_found(Xop_tkn_itm tkn) { - words_found_list.Add(new Xow_popup_word(tkn.Tkn_tid(), hdom_bfr.Len(), words_found, tkn.Src_bgn(), tkn.Src_end())); - ++words_found; - } - private void Add_to_hdom_bfr(Xop_tkn_itm tkn, byte[] wtxt_bry, int wtxt_len) { - if (cancelable.Canceled()) return; - boolean add = true, recur = true; Xop_xnde_tkn xnde = null; - int tkn_src_bgn = tkn.Src_bgn(), tkn_src_end = tkn.Src_end(); - switch (tkn.Tkn_tid()) { - case Xop_tkn_itm_.Tid_root: - add = false; // don't add root - break; - case Xop_tkn_itm_.Tid_txt: - Increment_words_found(tkn); - break; - case Xop_tkn_itm_.Tid_tblw_tb: case Xop_tkn_itm_.Tid_tblw_tc: case Xop_tkn_itm_.Tid_tblw_td: - case Xop_tkn_itm_.Tid_tblw_te: case Xop_tkn_itm_.Tid_tblw_th: case Xop_tkn_itm_.Tid_tblw_tr: - add = recur = false; // skip tblws - break; - case Xop_tkn_itm_.Tid_xnde: - xnde = (Xop_xnde_tkn)tkn; - switch (xnde.Tag().Id()) { - case Xop_xnde_tag_.Tid_ref: - case Xop_xnde_tag_.Tid_div: - case Xop_xnde_tag_.Tid_gallery: - case Xop_xnde_tag_.Tid_imageMap: - case Xop_xnde_tag_.Tid_xowa_html: // needed for Help:Options, else \n at top of doc; DATE:2014-06-22 - case Xop_xnde_tag_.Tid_table: case Xop_xnde_tag_.Tid_tr: case Xop_xnde_tag_.Tid_td: case Xop_xnde_tag_.Tid_th: - case Xop_xnde_tag_.Tid_caption: case Xop_xnde_tag_.Tid_thead: case Xop_xnde_tag_.Tid_tfoot: case Xop_xnde_tag_.Tid_tbody: - add = recur = false; // skip tblxs - xnde = null; - break; - case Xop_xnde_tag_.Tid_br: - if (hdom_bfr.Len_eq_0()) // don't add
    to start of document; needed for Help:Options, but good to have everywhere; DATE:2014-06-22 - add = recur = false; - break; - default: - add = false; // don't add xnde, but still recur - if (Xnde_id_ignore_list_chk(xnde, wtxt_bry)) { - recur = false; - xnde = null; - } - break; - } - break; - case Xop_tkn_itm_.Tid_lnke: - Xop_lnke_tkn lnke = (Xop_lnke_tkn)tkn; - switch (lnke.Lnke_typ()) { - case Xop_lnke_tkn.Lnke_typ_brack: - Add_to_hdom_bfr_recurse(tkn, wtxt_bry, wtxt_len, Bool_.N); // add subs which are caption tkns; note that Bool_.N will add all words so that captions don't get split; EX: "a [http://a.org b c d]" -> "a b c d" if words_needed == 2; - add = recur = false; // ignore lnke, but add any text tkns; EX: [http://a.org b c d] -> "b c d" - break; - case Xop_lnke_tkn.Lnke_typ_text: - Increment_words_found(tkn); // increment words_found; EX: a http://b.org c -> 3 words; - break; - } - break; - case Xop_tkn_itm_.Tid_lnki: - Xop_lnki_tkn lnki = (Xop_lnki_tkn)tkn; - switch (lnki.Ns_id()) { - case Xow_ns_.Id_category: // skip [[Category:]] - case Xow_ns_.Id_file: // skip [[File:]] - add = recur = false; - break; - default: - Increment_words_found(tkn); // increment words_found; EX: a [[B|c d e]] f -> 3 words; - break; - } - break; - case Xop_tkn_itm_.Tid_space: - if ( add_wtxt_skip_space // previous tkn skipped add and set add_wtxt_skip_space to true - && hdom_bfr.Match_end_byt_nl_or_bos() // only ignore space if it will cause pre; note that some s will have spaces that should be preserved; EX:"ab c"; PAGE:en.w:Mehmed_the_Conqueror; DATE:2014-06-18 - ) - add = false; // skip ws - break; - case Xop_tkn_itm_.Tid_newLine: { - // heuristic to handle skipped

    / which does not skip \n; EX:"
    a
    \nb"; div is skipped, but "\n" remains; PAGE:en.w:Eulogy;DATE:2014-06-18 - int hdom_bfr_len = hdom_bfr.Len(); - if (hdom_bfr_len == 0) // don't add \n at bos; does not handle pages where bos intentionally has multiple \n\n - add = false; - else if (hdom_bfr_len > 2) { // bounds check - if (Wtxt_bfr_ends_w_2_nl(hdom_bfr_len)) // don't add \n if "\n\n"; does not handle intentional sequences of 2+ \n; - add = false; - } - break; - } - case Xop_tkn_itm_.Tid_hdr: { - if (stop_at_hdr && words_found != 0) { // if 1st word is header (no intro para), don't exit - words_found = words_needed; - stop_at_hdr_done = true; - return; - } - Increment_words_found(tkn); // count entire header as one word; not worth counting words in header - recur = false; // add entire tkn; do not recur - int hdom_bfr_len = hdom_bfr.Len(); - if (hdom_bfr_len > 2) { // bounds check - if (Wtxt_bfr_ends_w_2_nl(hdom_bfr_len)) // heuristic: 2 \n in bfr, and about to add a hdr tkn which starts with "\n"; delete last \n - hdom_bfr.Del_by_1(); - } - if ( tkn_src_end < wtxt_len // bounds check - && wtxt_bry[tkn_src_end] == Byte_ascii.NewLine // hdr_tkn will not include trailing "\n". add it; note that this behavior is by design. NOTE:hdr.trailing_nl; DATE:2014-06-17 - ) { - hdom_bfr.Add_mid(wtxt_bry, tkn_src_bgn, tkn_src_end + 1); // +1 to add the trailing \n - add = false; - } - break; - } - default: - break; - } - add_wtxt_skip_space = false; // always reset; only used once above for Tid_space; DATE:2014-06-17 - if (add) { - if (tkn_src_end - tkn_src_bgn > 0) // handle paras which have src_bgn == src_end - hdom_bfr.Add_mid(wtxt_bry, tkn_src_bgn, tkn_src_end); - } - else // tkn not added - add_wtxt_skip_space = true; // skip next space; note this is done with member variable to handle recursive iteration; DATE:2014-06-17 - if (recur) { - if (xnde != null) hdom_bfr.Add_mid(wtxt_bry, xnde.Tag_open_bgn(), xnde.Tag_open_end()); // add open tag; EX: "" - Add_to_hdom_bfr_recurse(tkn, wtxt_bry, wtxt_len, Bool_.Y); - if (xnde != null) hdom_bfr.Add_mid(wtxt_bry, xnde.Tag_close_bgn(), xnde.Tag_close_end()); // add close tag; EX: "" - } - } - private void Add_to_hdom_bfr_recurse(Xop_tkn_itm tkn, byte[] wtxt_bry, int wtxt_len, boolean chk_words_found) { - int subs_len = tkn.Subs_len(); - for (int i = 0; i < subs_len; i++) { - Xop_tkn_itm sub = tkn.Subs_get(i); - Add_to_hdom_bfr(sub, wtxt_bry, wtxt_len); - if (chk_words_found && words_found >= words_needed) break; - } - } - private boolean Xnde_id_ignore_list_chk(Xop_xnde_tkn xnde, byte[] src) { - Xop_xatr_itm[] atrs_ary = xnde.Atrs_ary(); - int atrs_len = atrs_ary.length; - for (int i = 0; i < atrs_len; i++) { - Xop_xatr_itm atr = atrs_ary[i]; - if ( Bry_.Eq(atr.Key_bry(), Html_atrs.Id_bry) - && xnde_id_ignore_list.Get_by_bry(atr.Val_as_bry(src)) != null - ) { - return true; - } - } - return false; - } - private boolean Wtxt_bfr_ends_w_2_nl(int hdom_bfr_len) { - byte[] hdom_bfr_bry = hdom_bfr.Bfr(); - return - ( hdom_bfr_bry[hdom_bfr_len - 1] == Byte_ascii.NewLine // prv 2 bytes are \n - && hdom_bfr_bry[hdom_bfr_len - 2] == Byte_ascii.NewLine - ); - } - private static final byte[] - Notoc_const = Bry_.new_ascii_(" __NOTOC__") // NOTE: always add a space else __NOTOC__ will be deactivated if last tkn is lnke; DATE:2014-06-22 - , Ellipsis_const = Bry_.new_ascii_("...") - ; - private Bry_fmtr - html_fmtr = Bry_fmtr.keys_(Xoapi_popups.Dflt_html_fmt_keys) - , view_time_fmtr = Bry_fmtr.new_("\n ~{<>msgs.get('api-xowa.html.modules.popups.msgs.viewed-name');<>}:~{view_time}", "view_time") - , xwiki_fmtr = Bry_fmtr.new_("\n ~{<>msgs.get('api-xowa.html.modules.popups.msgs.wiki-name');<>}:~{wiki_domain}", "wiki_domain") - ; -} -class Xow_popup_word { - public Xow_popup_word(int tid, int bfr_bgn, int idx, int bgn, int end) {this.tid = tid; this.bfr_bgn = bfr_bgn; this.idx = idx; this.bgn = bgn; this.end = end;} - public int Tid() {return tid;} private int tid; - public int Bfr_bgn() {return bfr_bgn;} private int bfr_bgn; - public int Bfr_end() {return bfr_bgn + this.Len();} - public int Idx() {return idx;} private int idx; - public int Bgn() {return bgn;} private int bgn; - public int End() {return end;} private int end; - public int Len() {return end - bgn;} + private static final String Comment_txt_str = "XOWA_SKIP"; + public static final byte[] Comment_txt = Bry_.new_ascii_(Comment_txt_str); + public static final byte[] Comment_tkn = Bry_.new_ascii_(""); } diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_data.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_data.java new file mode 100644 index 000000000..2c2b1a87e --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_data.java @@ -0,0 +1,62 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +import gplx.xowa.apis.xowa.html.modules.*; +public class Xow_popup_parser_data { + public int Tmpl_max() {return tmpl_max;} private int tmpl_max; + public int Words_needed_val() {return words_needed_val;} private int words_needed_val; + public int Words_needed_max() {return words_needed_max;} private int words_needed_max; + private int words_needed_min; + public int Words_found() {return words_found;} private int words_found; + public Bry_bfr Wrdx_bfr() {return wrdx_bfr;} private Bry_bfr wrdx_bfr = Bry_bfr.reset_(255); + public Xow_popup_word[] Words_found_ary() {return (Xow_popup_word[])words_found_list.XtoAryAndClear(Xow_popup_word.class);} private ListAdp words_found_list = ListAdp_.new_(); + private Xow_popup_itm popup_itm; + public boolean Html_restricted() {return html_restricted;} private boolean html_restricted; + public void Init(Xow_popup_cfg cfg, Xow_popup_itm popup_itm, int tmpl_len) { + words_found = 0; + words_found_list.Clear(); + wrdx_bfr.Clear(); + + html_restricted = !gplx.xowa.specials.xowa.popup_history.Popup_history_page.Ttl_chk(popup_itm.Page_ttl()); + this.popup_itm = popup_itm; + if (tmpl_len < cfg.Show_all_if_less_than()) popup_itm.Mode_all_(); + words_needed_min = popup_itm.Words_found(); + words_needed_val = words_needed_max = popup_itm.Words_needed(); + switch (popup_itm.Mode()) { + case Xow_popup_itm.Mode_tid_all: + tmpl_max = Int_.MaxValue; + break; + case Xow_popup_itm.Mode_tid_init: + case Xow_popup_itm.Mode_tid_more: + tmpl_max = cfg.Tmpl_read_max(); + if (cfg.Read_til_stop_fwd() > 0) + words_needed_max += cfg.Read_til_stop_fwd(); + break; + } + } + public boolean Words_needed_chk() {return words_found < words_needed_max;} + public void Words_found_add(Xop_tkn_itm tkn) { + words_found_list.Add(new Xow_popup_word(tkn.Tkn_tid(), wrdx_bfr.Len(), words_found, tkn.Src_bgn(), tkn.Src_end(), tkn)); + ++words_found; + } + public boolean Stop_if_hdr_after_chk(Xow_popup_cfg cfg) { + boolean rv = words_found > words_needed_min + cfg.Stop_if_hdr_after() && !popup_itm.Mode_all(); + if (rv) words_needed_max = words_found; + return rv; + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_tst.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_tst.java index 7670955d5..ef715e800 100644 --- a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_tst.java +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_parser_tst.java @@ -58,14 +58,14 @@ public class Xow_popup_parser_tst { )); } @Test public void Lnke_brack() { // PURPOSE: count lnke caption words; DATE:2014-06-20 - fxt.Init_scan_len_(32).Init_word_min_(5).Test_parse + fxt.Init_tmpl_read_len_(32).Init_word_needed_(5).Test_parse ( "a [http://b.org b c] d e f g", String_.Concat_lines_nl_skip_last ( "

    a b c d e" , "

    " )); } @Test public void Lnke_text() { // PURPOSE: count entire lnke as one word - fxt.Init_scan_len_(32).Init_word_min_(5).Test_parse + fxt.Init_tmpl_read_len_(32).Init_word_needed_(5).Test_parse ( "a http://b.org c d e f g", String_.Concat_lines_nl_skip_last ( "

    a http://b.org c d e" , "

    " @@ -144,6 +144,24 @@ public class Xow_popup_parser_tst { , "

    " )); } + @Test public void Xnde_br() { // PURPOSE: check that br is added correctly; PAGE:en.q:Earth; DATE:2014-06-30 + fxt.Init_word_needed_(3).Test_parse + ( "a
    b
    " + , String_.Concat_lines_nl_skip_last + ( "

    a
    b
    " + , "

    " + )); + } + @Test public void Xnde_math() { // PURPOSE: should be treated as one word; PAGE:en.w:System_of_polynomial_equations; DATE:2014-07-01 + fxt .Init_word_needed_(5) // need to read more words to pick up 1st word after header + .Init_read_til_stop_bwd_(2) // need to do read_bwd to start counting before ==e== into node + .Test_parse + ( "a b c d \n==e==\nf g h i" + , String_.Concat_lines_nl_skip_last + ( "

    a b c d (e)" // used to fail as

    a <math>b c d (e) + , "

    " + )); + } @Test public void Ignore_tblw() {// also checks for tbl spanning multiple blocks; PAGE:en.w:Stratosphere; DATE:2014-06-17 fxt.Test_parse(String_.Concat_lines_nl_skip_last ( "a " @@ -284,7 +302,7 @@ public class Xow_popup_parser_tst { )); } @Test public void End_early_dangling() { // PURPOSE: dangling tkn is too long; end early; PAGE:en.w:List_of_air_forces; DATE:2014-06-18 - fxt.Init_scan_max_(8).Test_parse + fxt.Init_tmpl_read_max_(8).Test_parse ( "a [[File:Test.png]] k" , String_.Concat_lines_nl_skip_last ( "

    a " @@ -304,21 +322,13 @@ public class Xow_popup_parser_tst { ( "

    a" , "

    " )); - fxt.Test_parse // no ellipsis: entire extract with skip + fxt.Test_parse // no ellipsis: entire extract multiple reads ( "a
    b
    " , String_.Concat_lines_nl_skip_last ( "

    a " , "

    " )); } - @Test public void Stop_at_hdr() { - fxt.Init_ellipsis_("...").Init_stop_at_header_(true).Test_parse - ( "a\n==b==\nc" - , String_.Concat_lines_nl_skip_last - ( "

    a" - , "

    " - )); - } @Test public void Ns_allowed() { fxt.Test_ns_allowed("Help" , Xow_ns_.Id_help); fxt.Test_ns_allowed("(Main)" , Xow_ns_.Id_main); @@ -326,24 +336,80 @@ public class Xow_popup_parser_tst { fxt.Test_ns_allowed("(Main)|Help" , Xow_ns_.Id_main, Xow_ns_.Id_help); } @Test public void Read_til_stop_fwd() { - fxt.Init_word_min_(2).Init_read_til_stop_fwd_(2).Test_parse("a b c\n==d==", String_.Concat_lines_nl_skip_last - ( "

    a b c" + fxt.Init_word_needed_(2).Init_read_til_stop_fwd_(2) // read fwd found hdr + .Test_parse("a b c\n==d==", String_.Concat_lines_nl_skip_last + ( "

    a b c (d)" , "

    " )); - fxt.Init_word_min_(2).Init_read_til_stop_fwd_(2).Test_parse("a b c d", String_.Concat_lines_nl_skip_last + fxt.Init_word_needed_(2).Init_read_til_stop_fwd_(2) // read fwd did not find hdr; reset back to min + .Test_parse("a b c d", String_.Concat_lines_nl_skip_last ( "

    a b" , "

    " )); } + @Test public void Read_til_stop_bwd() { + fxt.Init_word_needed_(8).Init_read_til_stop_bwd_(4) // read bwd found hdr + .Test_parse("01 02 03 04 05\n==06==\n07 08 09 10 11 12 13 14 15 16", String_.Concat_lines_nl_skip_last + ( "

    01 02 03 04 05 (06)" + , "

    " + )); + fxt.Init_tmpl_read_len_(40).Init_word_needed_(5).Init_read_til_stop_bwd_(3) // read bwd at eos should not return "next_sect"; DATE:2014-07-01 + .Test_parse("01 02 03 \n==04==\n", String_.Concat_lines_nl_skip_last + ( "

    01 02 03 " + , "

    " + , "" + , "

    04

    " + )); + } + @Test public void Stop_if_hdr_after() { + fxt.Init_word_needed_(5).Init_stop_if_hdr_after_(1) + .Test_parse("a b\n==c==\nd e", String_.Concat_lines_nl_skip_last + ( "

    a b" + , "

    " + , "" + , "

    c

    " + )); + } @Test public void Tmpl_tkn_max() { - fxt.Init_tmpl_tkn_max_(5).Init_page("Template:A", "a"); + fxt.Init_tmpl_tkn_max_(5).Init_page("Template:A", "a"); // eval fxt.Test_parse ( "{{A}}" , String_.Concat_lines_nl_skip_last ( "

    a" , "

    " )); - fxt.Test_parse( "{{A|b|c}}", "

    \n

    "); + fxt.Test_parse("{{A|b|c}}" , ""); // skip; NOTE: output should be blank, not

    \n

    ; PAGE:en.w:List_of_countries_by_GDP_(PPP); DATE:2014-07-01 + } + @Test public void Tmpl_tkn_max__comment_and_tblw() { // PURPOSE: garbled popup when tmpl_tkn_max is set and comments in front of tblw; PAGE:en.w:Gwynedd; DATE:2014-07-01 + fxt .Init_tmpl_tkn_max_(5) // set tmpl_tkn_max + .Init_tmpl_read_len_(20) // set read_len to 20 (must read entire "\n{|" at once + .Test_parse(String_.Concat_lines_nl_skip_last + ( "{{A|b}}" + , "{{A|b}}" + , "{|" + , "|-" + , "|a b c d" + , "|}" + ), ""); // should be blank, not
    ] + } + @Test public void Tmpl_tkn_max__apos() { // PURPOSE: handle apos around skipped tmpl token; PAGE:en.w:Somalia; DATE:2014-07-02 + fxt.Init_tmpl_tkn_max_(5).Test_parse("a''{{A|b}}''b", String_.Concat_lines_nl_skip_last + ( "

    a b" + , "

    " + )); + } + @Test public void Notoc_and_para_issue() { // PURPOSE.fix: issue with "\s__NOTOC__" and "a\n"b; PAGE:en.w:Spain; DATE:2014-07-05 + fxt.Init_word_needed_(3).Init_notoc_(" __NOTOC__").Test_parse("a\nb", String_.Concat_lines_nl_skip_last + ( "

    a" // was

    a

    b + , "b " + , "

    " + )); + } + @Test public void Test_Assert_at_end() { + fxt.Test_Assert_at_end("a" , "a\n"); // add one + fxt.Test_Assert_at_end("a\n" , "a\n"); // noop + fxt.Test_Assert_at_end("a\n\n\n" , "a\n"); // remove til one + fxt.Test_Assert_at_end("" , ""); // empty check } } class Xop_popup_parser_fxt { @@ -354,26 +420,31 @@ class Xop_popup_parser_fxt { this.wiki = Xoa_app_fxt.wiki_(app, "en.wiki"); parser = wiki.Html_mgr().Module_mgr().Popup_mgr().Parser(); parser.Init_by_wiki(wiki); - parser.Scan_len_(4); - parser.Html_fmtr().Fmt_("~{content}"); - parser.Ellipsis_(Bry_.Empty); - parser.Notoc_(Bry_.Empty); - parser.Stop_at_hdr_(false); - parser.Output_js_clean_(false); - parser.Output_tidy_(false); - parser.Show_all_if_less_than_(-1); - parser.Xnde_ignore_ids_(Xoapi_popups.Dflt_coordinates); - parser.Read_til_stop_fwd_(-1); + parser.Cfg().Tmpl_read_len_(4); + parser.Cfg().Ellipsis_(Bry_.Empty); + parser.Cfg().Notoc_(Bry_.Empty); + parser.Cfg().Show_all_if_less_than_(-1); + parser.Cfg().Read_til_stop_fwd_(-1); + parser.Cfg().Read_til_stop_bwd_(-1); + parser.Cfg().Stop_if_hdr_after_(-1); + parser.Html_mkr().Fmtr_popup().Fmt_("~{content}"); + parser.Html_mkr().Output_js_clean_(false); + parser.Html_mkr().Output_tidy_(false); + parser.Html_mkr().Fmtr_next_sect().Fmt_(" (~{next_sect_val})"); + parser.Wrdx_mkr().Xnde_ignore_ids_(Xoapi_popups.Dflt_xnde_ignore_ids); word_min = 2; } - public Xop_popup_parser_fxt Init_scan_len_(int v) {parser.Scan_len_(v); return this;} - public Xop_popup_parser_fxt Init_scan_max_(int v) {parser.Scan_max_(v); return this;} - public Xop_popup_parser_fxt Init_word_min_(int v) {word_min = v; return this;} + public Xop_popup_parser_fxt Init_notoc_(String v) {parser.Cfg().Notoc_(Bry_.new_utf8_(v)); return this;} + public Xop_popup_parser_fxt Init_tmpl_read_len_(int v) {parser.Cfg().Tmpl_read_len_(v); return this;} + public Xop_popup_parser_fxt Init_tmpl_read_max_(int v) {parser.Cfg().Tmpl_read_max_(v); return this;} + public Xop_popup_parser_fxt Init_word_needed_(int v) {word_min = v; return this;} public Xop_popup_parser_fxt Init_para_enabled_(boolean v) {parser.Wtxt_ctx().Para().Enabled_(v); return this;} - public Xop_popup_parser_fxt Init_stop_at_header_(boolean v) {parser.Stop_at_hdr_(v); return this;} - public Xop_popup_parser_fxt Init_ellipsis_(String v) {parser.Ellipsis_(Bry_.new_utf8_(v)); return this;} - public Xop_popup_parser_fxt Init_read_til_stop_fwd_(int v) {parser.Read_til_stop_fwd_(v); return this;} + public Xop_popup_parser_fxt Init_ellipsis_(String v) {parser.Cfg().Ellipsis_(Bry_.new_utf8_(v)); return this;} + public Xop_popup_parser_fxt Init_read_til_stop_fwd_(int v) {parser.Cfg().Read_til_stop_fwd_(v); return this;} + public Xop_popup_parser_fxt Init_read_til_stop_bwd_(int v) {parser.Cfg().Read_til_stop_bwd_(v); return this;} + public Xop_popup_parser_fxt Init_stop_if_hdr_after_(int v) {parser.Cfg().Stop_if_hdr_after_(v); return this;} public Xop_popup_parser_fxt Init_tmpl_tkn_max_(int v) {parser.Tmpl_tkn_max_(v); return this;} + public Xop_popup_parser_fxt Init_fmtr_next_sect_(String v) {parser.Html_mkr().Fmtr_next_sect().Fmt_(v); return this;} public Xop_popup_parser_fxt Init_page(String ttl, String txt) {Xop_fxt.Init_page_create_static(wiki, ttl, txt); return this;} public Xop_popup_parser_fxt Test_ns_allowed(String raw, int... expd) { Int_obj_ref[] ids = Xow_popup_mgr.Ns_allowed_parse(wiki, Bry_.new_utf8_(raw)); @@ -384,7 +455,14 @@ class Xop_popup_parser_fxt { Xoa_page page = Xoa_page.create_(wiki, Xoa_ttl.parse_(wiki, Bry_.new_ascii_("Test_1"))); page.Data_raw_(Bry_.new_utf8_(raw)); Xow_popup_itm itm = new Xow_popup_itm(1, Bry_.new_utf8_(raw), word_min); - byte[] actl = parser.Parse(itm, page, wiki.Domain_bry(), null); + itm.Init(wiki.Domain_bry(), page.Ttl()); + byte[] actl = parser.Parse(wiki, page, null, itm); Tfds.Eq_str_lines(expd, String_.new_utf8_(actl)); } + public void Test_Assert_at_end(String raw, String expd) { + if (test_bfr == null) test_bfr = Bry_bfr.new_(); + test_bfr.Clear().Add_str(raw); + Bry_bfr_.Assert_at_end(test_bfr, Byte_ascii.NewLine); + Tfds.Eq(expd, test_bfr.XtoStrAndClear()); + } private Bry_bfr test_bfr; } diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_word.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_word.java new file mode 100644 index 000000000..23d7aa9ac --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_word.java @@ -0,0 +1,29 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +public class Xow_popup_word { + public Xow_popup_word(int tid, int bfr_bgn, int idx, int bgn, int end, Xop_tkn_itm tkn) {this.tid = tid; this.bfr_bgn = bfr_bgn; this.idx = idx; this.bgn = bgn; this.end = end; this.tkn = tkn;} + public int Tid() {return tid;} private int tid; + public int Bfr_bgn() {return bfr_bgn;} private int bfr_bgn; + public int Bfr_end() {return bfr_bgn + this.Len();} + public int Idx() {return idx;} private int idx; + public int Bgn() {return bgn;} private int bgn; + public int End() {return end;} private int end; + public int Len() {return end - bgn;} + public Xop_tkn_itm Tkn() {return tkn;} private Xop_tkn_itm tkn; +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_wrdx_mkr.java b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_wrdx_mkr.java new file mode 100644 index 000000000..9922e133f --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/Xow_popup_wrdx_mkr.java @@ -0,0 +1,202 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; +import gplx.html.*; +import gplx.xowa.parsers.lnkes.*; +public class Xow_popup_wrdx_mkr { + private boolean skip_space; + private Xop_tkn_itm prv_tkn_seen, prv_tkn_added; + public Hash_adp_bry Xnde_id_ignore_list() {return xnde_id_ignore_list;} private Hash_adp_bry xnde_id_ignore_list = Hash_adp_bry.ci_ascii_(); + public void Init() { + skip_space = false; + prv_tkn_seen = prv_tkn_added = null; + } + public void Process_tkn(Xow_popup_cfg cfg, Xow_popup_parser_data data, Bry_bfr wrdx_bfr, Xop_tkn_itm tkn, byte[] wtxt_bry, int wtxt_len) { + boolean add_tkn = true, add_subs = true; Xop_xnde_tkn xnde = null; + int tkn_src_bgn = tkn.Src_bgn(), tkn_src_end = tkn.Src_end(); + prv_tkn_seen = tkn; + switch (tkn.Tkn_tid()) { + case Xop_tkn_itm_.Tid_root: + add_tkn = false; // don't add_tkn root + break; + case Xop_tkn_itm_.Tid_txt: + data.Words_found_add(tkn); + break; + case Xop_tkn_itm_.Tid_apos: + if ( prv_tkn_added != null + && prv_tkn_seen != prv_tkn_added // prv seen tkn was skipped + && prv_tkn_added.Tkn_tid() == Xop_tkn_itm_.Tid_apos // prv added tkn was apos + ) + wrdx_bfr.Add_byte_space(); // prv && cur are apos, but something was skipped inbetween; add a space so that apos doesn't combine EX:''{{skip}}'' x> ''''; PAGE:en.w:Somalia; DATE:2014-07-02 + break; + case Xop_tkn_itm_.Tid_ignore: // always skip ignores, particularly comments; PAGE:en.w:List_of_countries_by_GDP_(PPP); DATE:2014-07-01 + case Xop_tkn_itm_.Tid_tblw_tb: case Xop_tkn_itm_.Tid_tblw_tc: case Xop_tkn_itm_.Tid_tblw_td: + case Xop_tkn_itm_.Tid_tblw_te: case Xop_tkn_itm_.Tid_tblw_th: case Xop_tkn_itm_.Tid_tblw_tr: + add_tkn = add_subs = false; // skip tblws + break; + case Xop_tkn_itm_.Tid_xnde: + xnde = (Xop_xnde_tkn)tkn; + switch (xnde.Tag().Id()) { + case Xop_xnde_tag_.Tid_div: + case Xop_xnde_tag_.Tid_table: case Xop_xnde_tag_.Tid_tr: case Xop_xnde_tag_.Tid_td: case Xop_xnde_tag_.Tid_th: + case Xop_xnde_tag_.Tid_caption: case Xop_xnde_tag_.Tid_thead: case Xop_xnde_tag_.Tid_tfoot: case Xop_xnde_tag_.Tid_tbody: + case Xop_xnde_tag_.Tid_ref: case Xop_xnde_tag_.Tid_gallery: case Xop_xnde_tag_.Tid_imageMap: case Xop_xnde_tag_.Tid_timeline: + case Xop_xnde_tag_.Tid_xowa_html: // needed for Help:Options, else \n at top of doc; DATE:2014-06-22 + add_tkn = add_subs = false; // skip tblxs + xnde = null; + break; + case Xop_xnde_tag_.Tid_math: // add as one unit; PAGE:en.w:System_of_polynomial_equations DATE:2014-07-01 + add_subs = false; // never recur + xnde = null; + data.Words_found_add(tkn); // treat it as one word + break; + case Xop_xnde_tag_.Tid_br: + add_tkn = false; // never add_tkn Src_bgn / Src_end; note add_subs should still be true; PAGE:en.q:Earth; DATE:2014-06-30 + if (wrdx_bfr.Len_eq_0()) // don't add
    to start of document; needed for Help:Options, but good to have everywhere; DATE:2014-06-22 + add_subs = false; + break; + default: + add_tkn = false; // don't add_tkn xnde, but still add_subs + if (Xnde_id_ignore_list_chk(xnde, wtxt_bry)) { + add_subs = false; + xnde = null; + } + break; + } + break; + case Xop_tkn_itm_.Tid_lnke: + Xop_lnke_tkn lnke = (Xop_lnke_tkn)tkn; + switch (lnke.Lnke_typ()) { + case Xop_lnke_tkn.Lnke_typ_brack: + Process_subs(cfg, data, wrdx_bfr, tkn, wtxt_bry, wtxt_len, Bool_.N); // add subs which are caption tkns; note that Bool_.N will add all words so that captions don't get split; EX: "a [http://a.org b c d]" -> "a b c d" if words_needed == 2; + add_tkn = add_subs = false; // ignore lnke, but add any text tkns; EX: [http://a.org b c d] -> "b c d" + break; + case Xop_lnke_tkn.Lnke_typ_text: + data.Words_found_add(tkn); // increment words_found; EX: a http://b.org c -> 3 words; + break; + } + break; + case Xop_tkn_itm_.Tid_lnki: + Xop_lnki_tkn lnki = (Xop_lnki_tkn)tkn; + switch (lnki.Ns_id()) { + case Xow_ns_.Id_category: // skip [[Category:]] + case Xow_ns_.Id_file: // skip [[File:]] + add_tkn = add_subs = false; + break; + default: + data.Words_found_add(tkn); // increment words_found; EX: a [[B|c d e]] f -> 3 words; + break; + } + break; + case Xop_tkn_itm_.Tid_space: + if ( skip_space // previous tkn skipped add and set skip_space to true + && wrdx_bfr.Match_end_byt_nl_or_bos() // only ignore space if it will cause pre; note that some s will have spaces that should be preserved; EX:"ab c"; PAGE:en.w:Mehmed_the_Conqueror; DATE:2014-06-18 + ) + add_tkn = false; // skip ws + break; + case Xop_tkn_itm_.Tid_newLine: { + // heuristic to handle skipped
    /
    which does not skip \n; EX:"
    a
    \nb"; div is skipped, but "\n" remains; PAGE:en.w:Eulogy;DATE:2014-06-18 + int wrdx_bfr_len = wrdx_bfr.Len(); + if (wrdx_bfr_len == 0) // don't add_tkn \n at bos; does not handle pages where bos intentionally has multiple \n\n + add_tkn = false; + else if (wrdx_bfr_len > 2) { // bounds check + if (Wtxt_bfr_ends_w_2_nl(wrdx_bfr, wrdx_bfr_len)) // don't add \n if "\n\n"; does not handle intentional sequences of 2+ \n; + add_tkn = false; + } + break; + } + case Xop_tkn_itm_.Tid_hdr: { + data.Words_found_add(tkn); // count entire header as one word; not worth counting words in header + add_subs = false; // add entire tkn; do not add_subs + int wrdx_bfr_len = wrdx_bfr.Len(); + if (wrdx_bfr_len > 2) { // bounds check + if (Wtxt_bfr_ends_w_2_nl(wrdx_bfr, wrdx_bfr_len)) // heuristic: 2 \n in bfr, and about to add a hdr tkn which starts with "\n"; delete last \n + wrdx_bfr.Del_by_1(); + } + if ( tkn_src_end < wtxt_len // bounds check + && wtxt_bry[tkn_src_end] == Byte_ascii.NewLine // hdr_tkn will not include trailing "\n". add it; note that this behavior is by design. NOTE:hdr.trailing_nl; DATE:2014-06-17 + ) { + wrdx_bfr.Add_mid(wtxt_bry, tkn_src_bgn, tkn_src_end + 1); // +1 to add the trailing \n + add_tkn = false; + } + break; + } + default: + break; + } + skip_space = false; // always reset; only used once above for Tid_space; DATE:2014-06-17 + if (add_tkn && xnde == null) { + if (tkn_src_end - tkn_src_bgn > 0) { // handle paras which have src_bgn == src_end + wrdx_bfr.Add_mid(wtxt_bry, tkn_src_bgn, tkn_src_end); + prv_tkn_added = tkn; + } + } + else // tkn not added + skip_space = true; // skip next space; note this is done with member variable to handle recursive iteration; DATE:2014-06-17 + if (add_subs) { + if (xnde != null) wrdx_bfr.Add_mid(wtxt_bry, xnde.Tag_open_bgn(), xnde.Tag_open_end()); // add open tag; EX: "" + Process_subs(cfg, data, wrdx_bfr, tkn, wtxt_bry, wtxt_len, Bool_.Y); + if (xnde != null) wrdx_bfr.Add_mid(wtxt_bry, xnde.Tag_close_bgn(), xnde.Tag_close_end()); // add close tag; EX: "" + } + switch (tkn.Tkn_tid()) { + case Xop_tkn_itm_.Tid_hdr: + if ( cfg.Stop_if_hdr_after_enabled() + && data.Stop_if_hdr_after_chk(cfg)) + return; + break; + } + } + private void Process_subs(Xow_popup_cfg cfg, Xow_popup_parser_data data, Bry_bfr wrdx_bfr, Xop_tkn_itm tkn, byte[] wtxt_bry, int wtxt_len, boolean chk_words_found) { + int subs_len = tkn.Subs_len(); + for (int i = 0; i < subs_len; i++) { + Xop_tkn_itm sub = tkn.Subs_get(i); + Process_tkn(cfg, data, wrdx_bfr, sub, wtxt_bry, wtxt_len); + if (chk_words_found && !data.Words_needed_chk()) break; + } + } + private boolean Xnde_id_ignore_list_chk(Xop_xnde_tkn xnde, byte[] src) { + Xop_xatr_itm[] atrs_ary = xnde.Atrs_ary(); + int atrs_len = atrs_ary.length; + for (int i = 0; i < atrs_len; i++) { + Xop_xatr_itm atr = atrs_ary[i]; + if ( Bry_.Eq(atr.Key_bry(), Html_atr_.Id_bry) + && xnde_id_ignore_list.Get_by_bry(atr.Val_as_bry(src)) != null + ) { + return true; + } + } + return false; + } + public void Xnde_ignore_ids_(byte[] xnde_id_ignore_bry) { + byte[][] ary = Bry_.Split(xnde_id_ignore_bry, Byte_ascii.Pipe); + int ary_len = ary.length; + xnde_id_ignore_list.Clear(); + for (int i = 0; i < ary_len; i++) { + byte[] bry = ary[i]; + if (bry.length == 0) continue; // ignore empty entries; EX: "a|" + xnde_id_ignore_list.Add(bry, bry); + } + } + private boolean Wtxt_bfr_ends_w_2_nl(Bry_bfr wrdx_bfr, int wrdx_bfr_len) { + byte[] hdom_bfr_bry = wrdx_bfr.Bfr(); + return + ( hdom_bfr_bry[wrdx_bfr_len - 1] == Byte_ascii.NewLine // prv 2 bytes are \n + && hdom_bfr_bry[wrdx_bfr_len - 2] == Byte_ascii.NewLine + ); + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_rule.java b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_rule.java new file mode 100644 index 000000000..069f38817 --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_rule.java @@ -0,0 +1,47 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups.keeplists; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; import gplx.xowa.html.modules.popups.*; +import gplx.core.regxs.*; +public class Xop_keeplist_rule { + public Xop_keeplist_rule(Gfo_pattern[] includes, Gfo_pattern[] excludes) { + this.includes = includes; this.includes_len = includes.length; + this.excludes = excludes; this.excludes_len = excludes.length; + } + public Gfo_pattern[] Includes() {return includes;} private Gfo_pattern[] includes; private int includes_len; + private Gfo_pattern[] excludes; private int excludes_len; + public boolean Match(byte[] ttl) { + boolean match_found = false; + for (int i = 0; i < includes_len; ++i) { + Gfo_pattern skip = includes[i]; + if (skip.Match(ttl)) { + match_found = true; + break; + } + } + if (match_found) { + for (int i = 0; i < excludes_len; ++i) { + Gfo_pattern keep = excludes[i]; + if (keep.Match(ttl)) { + match_found = false; + break; + } + } + } + return match_found; + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki.java b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki.java new file mode 100644 index 000000000..c6b624806 --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki.java @@ -0,0 +1,49 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups.keeplists; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; import gplx.xowa.html.modules.popups.*; +import gplx.core.regxs.*; +public class Xop_keeplist_wiki { + public Xop_keeplist_wiki(Xow_wiki wiki) { + srl = new Xop_keeplist_wiki_srl(wiki); + } + public boolean Enabled() {return enabled;} public void Enabled_(boolean v) {enabled = v;} private boolean enabled = false; // NOTE: default to false, b/c wikis that are not listed in cfg will not call Rules_seal + public Xop_keeplist_rule[] Rules() {return rules;} private Xop_keeplist_rule[] rules; private int rules_len; + public Xop_keeplist_wiki_srl Srl() {return srl;} private Xop_keeplist_wiki_srl srl; + public void Rules_add(Xop_keeplist_rule rule) {rules_list.Add(rule);} private ListAdp rules_list = ListAdp_.new_(); + public void Rules_seal() { + this.rules = (Xop_keeplist_rule[])rules_list.XtoAryAndClear(Xop_keeplist_rule.class); + this.rules_len = rules.length; + if (rules_len == 0) return; + if (rules_len == 1) { + Xop_keeplist_rule rule_0 = rules[0]; + if (rule_0.Includes().length == 0) + enabled = false; + else + enabled = true; + } + else + enabled = true; + } + public boolean Match(byte[] ttl) { + for (int i = 0; i < rules_len; ++i) { + Xop_keeplist_rule rule = rules[i]; + if (rule.Match(ttl)) return true; + } + return false; + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_srl.java b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_srl.java new file mode 100644 index 000000000..ddcdafbbc --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_srl.java @@ -0,0 +1,66 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups.keeplists; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; import gplx.xowa.html.modules.popups.*; +import gplx.srls.dsvs.*; +import gplx.core.regxs.*; +import gplx.xowa.langs.cases.*; +public class Xop_keeplist_wiki_srl extends Dsv_wkr_base { + private Xol_case_mgr case_mgr; private Xow_wiki wiki; + private byte[] wiki_bry; + private byte[] keeps_bry; + private byte[] skips_bry; + private int rules_count; + public Xop_keeplist_wiki_srl(Xow_wiki wiki) {this.wiki = wiki; this.case_mgr = wiki.Lang().Case_mgr();} + @Override public Dsv_fld_parser[] Fld_parsers() {return new Dsv_fld_parser[] {Dsv_fld_parser_.Bry_parser, Dsv_fld_parser_.Bry_parser, Dsv_fld_parser_.Bry_parser};} + @Override public boolean Write_bry(Dsv_tbl_parser parser, int fld_idx, byte[] src, int bgn, int end) { + switch (fld_idx) { + case 0: wiki_bry = Xoa_ttl.Replace_spaces(case_mgr.Case_build_lower(Bry_.Mid(src, bgn, end))); return true; + case 1: keeps_bry = Xoa_ttl.Replace_spaces(case_mgr.Case_build_lower(Bry_.Mid(src, bgn, end))); return true; + case 2: skips_bry = Xoa_ttl.Replace_spaces(case_mgr.Case_build_lower(Bry_.Mid(src, bgn, end))); return true; + default: return false; + } + } + @Override public void Commit_itm(Dsv_tbl_parser parser, int pos) { + if (wiki_bry == null) throw parser.Err_row_bgn("wikis missing", pos); + if (keeps_bry == null) throw parser.Err_row_bgn("keeps missing", pos); + if (skips_bry == null) throw parser.Err_row_bgn("skips missing", pos); + if (!Bry_.Eq(wiki_bry, wiki.Domain_bry())) return; + Xop_keeplist_wiki tmpl_keeplist = Get_tmpl_keeplist(); + Gfo_pattern[] keeps = Gfo_pattern.Parse_to_ary(keeps_bry); + Gfo_pattern[] skips = Gfo_pattern.Parse_to_ary(skips_bry); + Xop_keeplist_rule rule = new Xop_keeplist_rule(keeps, skips); + tmpl_keeplist.Rules_add(rule); + wiki_bry = skips_bry = keeps_bry = null; + ++rules_count; + } + @Override public void Load_by_bry_end() { + if (rules_count == 0) return; // NOTE: keeplist set in global cfg, so fires when each wiki loads; if loading wiki does not match keeplist, then noop; DATE:2014-07-05 + Xop_keeplist_wiki tmpl_keeplist = Get_tmpl_keeplist(); + tmpl_keeplist.Rules_seal(); + rules_count = 0; + } + public Xop_keeplist_wiki Get_tmpl_keeplist() { + Xow_popup_parser popup_parser = wiki.Html_mgr().Module_mgr().Popup_mgr().Parser(); + Xop_keeplist_wiki rv = popup_parser.Tmpl_keeplist(); + if (rv == null) { + rv = new Xop_keeplist_wiki(wiki); + popup_parser.Tmpl_keeplist_(rv); + } + return rv; + } +} diff --git a/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_tst.java b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_tst.java new file mode 100644 index 000000000..81d8640fa --- /dev/null +++ b/400_xowa/src/gplx/xowa/html/modules/popups/keeplists/Xop_keeplist_wiki_tst.java @@ -0,0 +1,61 @@ +/* +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 . +*/ +package gplx.xowa.html.modules.popups.keeplists; import gplx.*; import gplx.xowa.*; import gplx.xowa.html.*; import gplx.xowa.html.modules.*; import gplx.xowa.html.modules.popups.*; +import org.junit.*; +public class Xop_keeplist_wiki_tst { + @Before public void init() {fxt.Clear();} private Xop_keeplist_wiki_fxt fxt = new Xop_keeplist_wiki_fxt(); + @Test public void Tmpl_keeplist() { + Xop_keeplist_wiki keeplist_wiki = fxt.keeplist_wiki_(String_.Concat_lines_nl + ( "enwiki|a*|abc*" + )); + fxt.Test_Match_y(keeplist_wiki, "a", "ab"); + fxt.Test_Match_n(keeplist_wiki, "abc", "abcd", "d"); + } + @Test public void Tmpl_keeplist2() { + Xop_keeplist_wiki keeplist_wiki = fxt.keeplist_wiki_(String_.Concat_lines_nl + ( "enwiki|a*|abc*" + , "enwiki|b*|*xyz" + )); + fxt.Test_Match_y(keeplist_wiki, "a", "ab"); + fxt.Test_Match_n(keeplist_wiki, "d", "abc", "abcd"); + fxt.Test_Match_y(keeplist_wiki, "b", "bxy"); + fxt.Test_Match_n(keeplist_wiki, "bxyz", "bcdxyz"); + } +} +class Xop_keeplist_wiki_fxt { + public void Clear() { + } + public Xop_keeplist_wiki keeplist_wiki_(String raw) { + Xoa_app app = Xoa_app_fxt.app_(); + Xow_wiki wiki = Xoa_app_fxt.wiki_(app, "enwiki"); + Xow_popup_mgr popup_mgr = wiki.Html_mgr().Module_mgr().Popup_mgr(); + popup_mgr.Init_by_wiki(wiki); + popup_mgr.Parser().Tmpl_keeplist_init_(Bry_.new_utf8_(raw)); + Xop_keeplist_wiki rv = popup_mgr.Parser().Tmpl_keeplist(); + return rv; + } + public void Test_Match_y(Xop_keeplist_wiki keeplist_wiki, String... itms) {Test_Match(keeplist_wiki, itms, Bool_.Y);} + public void Test_Match_n(Xop_keeplist_wiki keeplist_wiki, String... itms) {Test_Match(keeplist_wiki, itms, Bool_.N);} + private void Test_Match(Xop_keeplist_wiki keeplist_wiki, String[] itms, boolean expd) { + int len = itms.length; + for (int i = 0; i < len; i++) { + String itm = itms[i]; + Tfds.Eq(expd, keeplist_wiki.Match(Bry_.new_utf8_(itm)), "itm={0} expd={1}", itm, expd); + } + } +} diff --git a/400_xowa/src/gplx/xowa/html/sidebar/Xowh_sidebar_mgr_tst.java b/400_xowa/src/gplx/xowa/html/sidebar/Xowh_sidebar_mgr_tst.java index 279135a96..7a9ca2b10 100644 --- a/400_xowa/src/gplx/xowa/html/sidebar/Xowh_sidebar_mgr_tst.java +++ b/400_xowa/src/gplx/xowa/html/sidebar/Xowh_sidebar_mgr_tst.java @@ -190,6 +190,7 @@ class Xowh_sidebar_mgr_fxt { sidebar_mgr = wiki.Html_mgr().Portal_mgr().Sidebar_mgr(); bfr = Bry_bfr.reset_(Io_mgr.Len_kb); comment_bfr = Bry_bfr.reset_(Io_mgr.Len_kb); + Init_popups_enabled_(false); // } return this; } diff --git a/400_xowa/src/gplx/xowa/html/tidy/Xoh_tidy_mgr.java b/400_xowa/src/gplx/xowa/html/tidy/Xoh_tidy_mgr.java index bddf9f71b..daf18c46c 100644 --- a/400_xowa/src/gplx/xowa/html/tidy/Xoh_tidy_mgr.java +++ b/400_xowa/src/gplx/xowa/html/tidy/Xoh_tidy_mgr.java @@ -63,9 +63,9 @@ public class Xoh_tidy_mgr implements GfoInvkAble { } public static boolean Tidy_unwrap(Bry_bfr bfr) { byte[] bfr_bry = bfr.Bfr(); - int find = Bry_finder.Find_fwd(bfr_bry, Html_tags.Body_lhs); if (find == Bry_finder.Not_found) return false; - bfr.Delete_rng_to_bgn(find + Html_tags.Body_lhs.length); - find = Bry_finder.Find_bwd(bfr_bry, Html_tags.Body_rhs, bfr.Len()); if (find == Bry_finder.Not_found) return false; + int find = Bry_finder.Find_fwd(bfr_bry, Html_tag_.Body_lhs); if (find == Bry_finder.Not_found) return false; + bfr.Delete_rng_to_bgn(find + Html_tag_.Body_lhs.length); + find = Bry_finder.Find_bwd(bfr_bry, Html_tag_.Body_rhs, bfr.Len()); if (find == Bry_finder.Not_found) return false; bfr.Delete_rng_to_end(find); return true; } diff --git a/400_xowa/src/gplx/xowa/html/utils/Xoh_js_cleaner.java b/400_xowa/src/gplx/xowa/html/utils/Xoh_js_cleaner.java index afe89e898..eab3662e8 100644 --- a/400_xowa/src/gplx/xowa/html/utils/Xoh_js_cleaner.java +++ b/400_xowa/src/gplx/xowa/html/utils/Xoh_js_cleaner.java @@ -48,7 +48,7 @@ public class Xoh_js_cleaner { int frag_len = frag.length; if (frag[0] == Byte_ascii.Lt) { // jscript node; EX: