mod: use XPointer as absolute postion indicator inside document

pull/2/merge
Qingping Hou 12 years ago
parent 3992fdca0f
commit cb83e47875

@ -30,6 +30,7 @@ extern "C" {
typedef struct CreDocument {
LVDocView *text_view;
ldomDocument *dom_doc;
} CreDocument;
@ -55,9 +56,9 @@ static int openDocument(lua_State *L) {
doc->text_view->setViewMode(DVM_SCROLL, -1);
doc->text_view->Resize(width, height);
doc->text_view->LoadDocument(file_name);
doc->dom_doc = doc->text_view->getDocument();
doc->text_view->Render();
printf("gamma: %d\n", fontMan->GetGammaIndex());
return 1;
}
@ -99,7 +100,20 @@ static int getCurrentPage(lua_State *L) {
return 1;
}
static int getPos(lua_State *L) {
static int getPageFromXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *xpointer_str = luaL_checkstring(L, 2);
int page = 0;
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
page = doc->text_view->getBookmarkPage(xp);
lua_pushinteger(L, page);
return 1;
}
static int getCurrentPos(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->GetPos());
@ -107,7 +121,22 @@ static int getPos(lua_State *L) {
return 1;
}
static int getPosPercent(lua_State *L) {
//static int getPosFromXPointer(lua_State *L) {
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
//const char *xpointer_str = luaL_checkstring(L, 2);
//lvRect rc;
//int pos;
//ldomXPointer *xp = NULL;
//xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
//getCursorDocRect(*xp, rc);
//pos =
//return 1;
//}
static int getCurrentPercent(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->getPosPercent());
@ -115,6 +144,15 @@ static int getPosPercent(lua_State *L) {
return 1;
}
static int getXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
ldomXPointer xp = doc->text_view->getBookmark();
lua_pushstring(L, UnicodeToLocal(xp.toString()).c_str());
return 1;
}
static int getFullHeight(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
@ -138,7 +176,13 @@ static int walkTableOfContent(lua_State *L, LVTocItem *toc, int *count) {
/* set subtable, Toc entry */
lua_newtable(L);
lua_pushstring(L, "page");
lua_pushnumber(L, toc_tmp->getY());
lua_pushnumber(L, toc_tmp->getPercent());
lua_settable(L, -3);
lua_pushstring(L, "xpointer");
lua_pushstring(L, UnicodeToLocal(
toc_tmp->getXPointer().toString()).c_str()
);
lua_settable(L, -3);
lua_pushstring(L, "depth");
@ -163,8 +207,18 @@ static int walkTableOfContent(lua_State *L, LVTocItem *toc, int *count) {
/*
* Return a table like this:
* {
* {page=12, depth=1, title="chapter1"},
* {page=54, depth=1, title="chapter2"},
* {
* page=12,
* xpointer = "/body/DocFragment[11].0",
* depth=1,
* title="chapter1"
* },
* {
* page=54,
* xpointer = "/body/DocFragment[13].0",
* depth=1,
* title="chapter2"
* },
* }
*
* Warnning: not like pdf or djvu support, page here refers to the
@ -246,6 +300,21 @@ static int gotoPos(lua_State *L) {
return 0;
}
static int gotoXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *xpointer_str = luaL_checkstring(L, 2);
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
doc->text_view->goToBookmark(xp);
/* CREngine does not call checkPos() immediately after goToBookmark,
* so I have to manually update the pos in order to get a correctionColor
* return from GetPos() call. */
doc->text_view->SetPos(xp.toPoint().y);
return 0;
}
/* zoom font by given delta and return zoomed font size */
static int zoomFont(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
@ -265,6 +334,32 @@ static int toggleFontBolder(lua_State *L) {
return 0;
}
static int cursorRight(lua_State *L) {
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
//LVDocView *tv = doc->text_view;
//ldomXPointer p = tv->getCurrentPageMiddleParagraph();
//lString16 s = p.toString();
//printf("~~~~~~~~~~%s\n", UnicodeToLocal(s).c_str());
//tv->selectRange(*(tv->selectFirstPageLink()));
//ldomXRange *r = tv->selectNextPageLink(true);
//lString16 s = r->getRangeText();
//printf("------%s\n", UnicodeToLocal(s).c_str());
//tv->selectRange(*r);
//tv->updateSelections();
//LVPageWordSelector sel(doc->text_view);
//doc->text_view->doCommand(DCMD_SELECT_FIRST_SENTENCE);
//sel.moveBy(DIR_RIGHT, 2);
//sel.updateSelection();
//printf("---------------- %s\n", UnicodeToLocal(sel.getSelectedWord()->getText()).c_str());
return 0;
}
static int drawCurrentPage(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
@ -306,21 +401,26 @@ static const struct luaL_Reg cre_func[] = {
};
static const struct luaL_Reg credocument_meth[] = {
/* get methods */
/*--- get methods ---*/
{"getPages", getNumberOfPages},
{"getCurrentPage", getCurrentPage},
{"getPos", getPos},
{"getPosPercent", getPosPercent},
{"getPageFromXPointer", getPageFromXPointer},
{"getCurrentPos", getCurrentPos},
{"getCurrentPercent", getCurrentPercent},
{"getXPointer", getXPointer},
{"getFullHeight", getFullHeight},
{"getToc", getTableOfContent},
/* set methods */
/*--- set methods ---*/
{"setFontFace", setFontFace},
/* control methods */
/* --- control methods ---*/
{"gotoPage", gotoPage},
{"gotoPercent", gotoPercent},
{"gotoPos", gotoPos},
{"gotoXPointer", gotoXPointer},
{"zoomFont", zoomFont},
{"toggleFontBolder", toggleFontBolder},
//{"cursorLeft", cursorLeft},
//{"cursorRight", cursorRight},
{"drawCurrentPage", drawCurrentPage},
{"close", closeDocument},
{"__gc", closeDocument},

@ -3,7 +3,7 @@ require "inputbox"
require "selectmenu"
CREReader = UniReader:new{
pos = 0,
pos = nil,
percent = 0,
gamma_index = 15,
@ -33,6 +33,9 @@ function CREReader:open(filename)
return true
end
----------------------------------------------------
-- setting related methods
----------------------------------------------------
function CREReader:loadSpecialSettings()
local font_face = self.settings:readSetting("font_face")
self.font_face = font_face or "FreeSerif"
@ -46,7 +49,7 @@ end
function CREReader:getLastPageOrPos()
local last_percent = self.settings:readSetting("last_percent")
if last_percent then
return (last_percent * self.doc:getFullHeight()) / 10000
return math.floor((last_percent * self.doc:getFullHeight()) / 10000)
else
return 0
end
@ -61,24 +64,40 @@ function CREReader:saveLastPageOrPos()
self.settings:savesetting("last_percent", self.percent)
end
----------------------------------------------------
-- render related methods
----------------------------------------------------
-- we don't need setzoom in CREReader
function CREReader:setzoom(page, preCache)
return
end
function CREReader:addJump(pos, notes)
return
function CREReader:redrawCurrentPage()
self:goto(self.pos)
end
function CREReader:goto(pos)
local pos = math.min(pos, self.doc:getFullHeight())
pos = math.max(pos, 0)
----------------------------------------------------
-- goto related methods
----------------------------------------------------
function CREReader:goto(pos, pos_type)
local prev_xpointer = self.doc:getXPointer()
if pos_type == "xpointer" then
self.doc:gotoXPointer(pos)
pos = self.doc:getCurrentPos()
else -- pos_type is PERCENT * 100
pos = math.min(pos, self.doc:getFullHeight())
pos = math.max(pos, 0)
self.doc:gotoPos(pos)
end
-- add to jump_stack, distinguish jump from normal page turn
-- NOTE:
-- even though we have called gotoPos() or gotoXPointer() previously,
-- self.pos hasn't been updated yet here, so we can still make use of it.
if self.pos and math.abs(self.pos - pos) > height then
self:addJump(self.percent)
self:addJump(prev_xpointer)
end
self.doc:gotoPos(pos)
self.doc:drawCurrentPage(self.nulldc, fb.bb)
if self.rcount == self.rcountmax then
@ -93,13 +112,65 @@ function CREReader:goto(pos)
self.pos = pos
self.pageno = self.doc:getCurrentPage()
self.percent = self.doc:getPosPercent()
self.percent = self.doc:getCurrentPercent()
end
function CREReader:redrawCurrentPage()
self:goto(self.pos)
function CREReader:gotoPercent(percent)
self:goto(percent * self.doc:getFullHeight() / 10000)
end
function CREReader:gotoTocEntry(entry)
self:goto(entry.xpointer, "xpointer")
end
function CREReader:nextView()
return self.pos + height - self.pan_overlap_vertical
end
function CREReader:prevView()
return self.pos - height + self.pan_overlap_vertical
end
----------------------------------------------------
-- jump stack related methods
----------------------------------------------------
function CREReader:isSamePage(p1, p2)
return self.doc:getPageFromXPointer(p1) == self.doc:getPageFromXPointer(p2)
end
function CREReader:showJumpStack()
local menu_items = {}
print(dump(self.jump_stack))
for k,v in ipairs(self.jump_stack) do
table.insert(menu_items,
v.datetime.." -> page "..
(self.doc:getPageFromXPointer(v.page)).." "..v.notes)
end
jump_menu = SelectMenu:new{
menu_title = "Jump Keeper (current page: "..self.pageno..")",
item_array = menu_items,
no_item_msg = "No jump history.",
}
item_no = jump_menu:choose(0, fb.bb:getHeight())
if item_no then
local jump_item = self.jump_stack[item_no]
self:goto(jump_item.page, "xpointer")
else
self:redrawCurrentPage()
end
end
----------------------------------------------------
-- TOC related methods
----------------------------------------------------
function CREReader:getTocTitleOfCurrentPage()
return self:getTocTitleByPage(self.percent)
end
----------------------------------------------------
-- menu related methods
----------------------------------------------------
-- used in CREReader:showMenu()
function CREReader:_drawReadingInfo()
local ypos = height - 50
@ -109,7 +180,7 @@ function CREReader:_drawReadingInfo()
ypos = ypos + 15
local face, fhash = Font:getFaceAndHash(22)
local cur_section = self:getTocTitleByPage(self.pos)
local cur_section = self:getTocTitleOfCurrentPage()
if cur_section ~= "" then
cur_section = "Section: "..cur_section
end
@ -121,13 +192,7 @@ function CREReader:_drawReadingInfo()
5, 4, load_percent/100, 8)
end
function CREReader:nextView()
return self.pos + height - self.pan_overlap_vertical
end
function CREReader:prevView()
return self.pos - height + self.pan_overlap_vertical
end
function CREReader:adjustCreReaderCommands()
-- delete commands
@ -204,6 +269,14 @@ function CREReader:adjustCreReaderCommands()
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_BACK,nil,"back",
"back to last jump",
function(cr)
if #cr.jump_stack ~= 0 then
cr:goto(cr.jump_stack[1].page, "xpointer")
end
end
)
self.commands:add(KEY_VPLUS, nil, "vol+",
"increase gamma",
function(cr)

@ -563,22 +563,27 @@ function UniReader:show(no)
self.slot_visible = slot;
end
function UniReader:isSamePage(p1, p2)
return p1 == p2
end
--[[
@ pageno is the page you want to add to jump_stack
NOTE: for CREReader, pageno refers to xpointer
--]]
function UniReader:addJump(pageno, notes)
local jump_item = nil
local notes_to_add = notes
if not notes_to_add then
-- no notes given, auto generate from Toc entry
notes_to_add = self:getTocTitleByPage(self.pageno)
notes_to_add = self:getTocTitleOfCurrentPage()
if notes_to_add ~= "" then
notes_to_add = "in "..notes_to_add
end
end
-- move pageno page to jump_stack top if already in
for _t,_v in ipairs(self.jump_stack) do
if _v.page == pageno then
if self:isSamePage(_v.page, pageno) then
jump_item = _v
table.remove(self.jump_stack, _t)
-- if original notes is not empty, probably defined by users,
@ -762,29 +767,38 @@ function UniReader:getTocTitleByPage(pageno)
return self:cleanUpTocTitle(pre_entry.title)
end
function UniReader:getTocTitleOfCurrentPage()
return self:getTocTitleByPage(self.pageno)
end
function UniReader:gotoTocEntry(entry)
self:goto(entry.page)
end
function UniReader:showToc()
if not self.toc then
-- build toc when needed.
-- build toc if needed.
self:fillToc()
end
local menu_items = {}
local filtered_toc = {}
-- build menu items
local menu_items = {}
for k,v in ipairs(self.toc) do
table.insert(menu_items,
(" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title))
table.insert(filtered_toc,v.page)
end
toc_menu = SelectMenu:new{
menu_title = "Table of Contents",
item_array = menu_items,
no_item_msg = "This document does not have a Table of Contents.",
}
item_no = toc_menu:choose(0, fb.bb:getHeight())
if item_no then
self:goto(filtered_toc[item_no])
self:gotoTocEntry(self.toc[item_no])
else
self:goto(self.pageno)
self:redrawCurrentPage()
end
end
@ -849,7 +863,7 @@ function UniReader:_drawReadingInfo()
local ypos = height - 50
fb.bb:paintRect(0, ypos, width, 50, 0)
ypos = ypos + 15
local cur_section = self:getTocTitleByPage(self.pageno)
local cur_section = self:getTocTitleOfCurrentPage()
if cur_section ~= "" then
cur_section = "Section: "..cur_section
end

Loading…
Cancel
Save