diff --git a/djvureader.lua b/djvureader.lua index 755727d6a..808755371 100644 --- a/djvureader.lua +++ b/djvureader.lua @@ -19,12 +19,21 @@ function DJVUReader:open(filename) end function DJVUReader:_isWordInScreenRange(w) - return (self.cur_full_height-(w.y0*self.globalzoom) <= - -self.offset_y + width) and - (self.cur_full_height-(w.y1*self.globalzoom) >= - -self.offset_y) + -- y axel in djvulibre starts from bottom + return (w ~= nil) and ( + ( self.cur_full_height-(w.y0*self.globalzoom) <= + -self.offset_y + height ) and + ( self.cur_full_height-(w.y1*self.globalzoom) >= + -self.offset_y )) end +function DJVUReader:_isLastWordInPage(t, l, w) + return (l == #t) and (w == #(t[l].words)) +end + +function DJVUReader:_isFirstWordInPage(t, l, w) + return (l == 1) and (w == 1) +end ------------------------------------------------ -- @text text object returned from doc:getPageText() -- @l0 start line @@ -88,17 +97,20 @@ end function DJVUReader:startHighLightMode() local t = self.doc:getPageText(self.pageno) - local function _nextWord(t, cur_l, cur_w) + local function _posToNextWord(t, cur_l, cur_w) local new_l = cur_l local new_w = cur_w if new_w >= #(t[new_l].words) then - -- already the last word, goto next line - new_l = new_l + 1 - if new_l > #t or #(t[new_l].words) == 0 then - return cur_l, cur_w + if new_l == #t then + -- word to mark is the last word in last line + return new_l, #(t[new_l].words)+1 + else + -- word to mark is not the last word in last line, + -- goto next line + new_l = new_l + 1 + new_w = 1 end - new_w = 1 else -- simply move to next word in the same line new_w = new_w + 1 @@ -107,7 +119,7 @@ function DJVUReader:startHighLightMode() return new_l, new_w end - local function _prevWord(t, cur_l, cur_w) + local function _posToPrevWord(t, cur_l, cur_w) local new_l = cur_l local new_w = cur_w @@ -117,7 +129,7 @@ function DJVUReader:startHighLightMode() if new_l == 0 or #(t[new_l].words) == 0 then return cur_l, cur_w end - new_w = #(t[new_l].words) + 1 + new_w = #(t[new_l].words) else -- simply move to previous word in the same line new_w = new_w - 1 @@ -126,21 +138,22 @@ function DJVUReader:startHighLightMode() return new_l, new_w end - local function _nextLine(t, cur_l, cur_w) + local function _posToNextLine(t, cur_l, cur_w) local new_l = cur_l local new_w = cur_w if new_l >= #t then - return cur_l, cur_w + -- already last line, jump to line end instead + return new_l, #(t[new_l].words)+1 end new_l = new_l + 1 - new_w = math.min(new_w, #t[new_l].words+1) + new_w = math.min(new_w, #t[new_l].words) return new_l, new_w end - local function _prevLine(t, cur_l, cur_w) + local function _posToPrevLine(t, cur_l, cur_w) local new_l = cur_l local new_w = cur_w @@ -149,12 +162,14 @@ function DJVUReader:startHighLightMode() end new_l = new_l - 1 - new_w = math.min(new_w, #t[new_l].words+1) + new_w = math.min(new_w, #t[new_l].words) return new_l, new_w end + local start_l = 1 + local start_w = 1 -- next to be marked word position local cur_l = 1 --local cur_w = #(t[1].words) @@ -162,24 +177,87 @@ function DJVUReader:startHighLightMode() local new_l = 1 local new_w = 1 local iter + local meet_page_end = false + local meet_page_start = false while true do local ev = input.waitForEvent() ev.code = adjustKeyEvents(ev) if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then - if ev.code == KEY_FW_RIGHT then - new_l, new_w = _nextWord(t, cur_l, cur_w) - iter = self:_genTextIter(t, cur_l, cur_w, new_l, new_w) - elseif ev.code == KEY_FW_LEFT then - new_l, new_w = _prevWord(t, cur_l, cur_w) - iter = self:_genTextIter(t, new_l, new_w, cur_l, cur_w) - elseif ev.code == KEY_FW_DOWN then - new_l, new_w = _nextLine(t, cur_l, cur_w) - iter = self:_genTextIter(t, cur_l, cur_w, new_l, new_w) + if ev.code == KEY_FW_LEFT then + if self:_isFirstWordInPage(t, cur_l, cur_w) then + iter = function() return nil end + else + new_l, new_w = _posToPrevWord(t, cur_l, cur_w) + if not self:_isWordInScreenRange(t[new_l].words[new_w]) then + -- goto next view of current page + local pageno = self:prevView() + self:goto(pageno) + cur_l = start_l + cur_w = start_w + end + iter = self:_genTextIter(t, new_l, new_w, cur_l, cur_w) + meet_page_end = false + end + elseif ev.code == KEY_FW_RIGHT then + if meet_page_end then + iter = function() return nil end + else + new_l, new_w = _posToNextWord(t, cur_l, cur_w) + if not self:_isWordInScreenRange(t[new_l].words[new_w]) then + if self:_isLastWordInPage(t, new_l, new_w-1) then + -- meet the end of page, mark it + meet_page_end = true + else + -- goto next view of current page + local pageno = self:nextView() + self:goto(pageno) + cur_l = start_l + cur_w = start_w + end + end + iter = self:_genTextIter(t, cur_l, cur_w, new_l, new_w) + meet_page_start = false + end elseif ev.code == KEY_FW_UP then - new_l, new_w = _prevLine(t, cur_l, cur_w) - iter = self:_genTextIter(t, new_l, new_w, cur_l, cur_w) - end + if self:_isFirstWordInPage(t, cur_l, cur_w) then + iter = function() return nil end + else + new_l, new_w = _posToPrevLine(t, cur_l, cur_w) + if not self:_isWordInScreenRange(t[new_l].words[new_w]) then + -- goto next view of current page + local pageno = self:prevView() + self:goto(pageno) + cur_l = start_l + cur_w = start_w + end + iter = self:_genTextIter(t, new_l, new_w, cur_l, cur_w) + meet_page_end = false + end + elseif ev.code == KEY_FW_DOWN then + if meet_page_end then + -- already at the end of page, we don't do a pageturn + -- so do noting here + iter = function() return nil end + else + new_l, new_w = _posToNextLine(t, cur_l, cur_w) + if not self:_isWordInScreenRange(t[new_l].words[new_w]) then + if self:_isLastWordInPage(t, new_l, new_w-1) then + -- meet the end of page, mark it + meet_page_end = true + else + -- goto next view of current page + local pageno = self:nextView() + self:goto(pageno) + cur_l = start_l + cur_w = start_w + end + end + iter = self:_genTextIter(t, cur_l, cur_w, new_l, new_w) + meet_page_start = false + end + end -- EOF if keyevent + self:_drawTextHighLight(iter) fb:refresh(0) cur_l, cur_w = new_l, new_w