From 56d4700001da79c8a273ea15e9ac035b817b4248 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 12 Apr 2012 11:23:22 +0800 Subject: [PATCH 1/4] mod: changes APIs in highlighting code --- djvureader.lua | 42 ++++++++++++++++++++------- pdfreader.lua | 13 ++------- unireader.lua | 79 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 82 insertions(+), 52 deletions(-) diff --git a/djvureader.lua b/djvureader.lua index 38efbedd8..dd1892103 100644 --- a/djvureader.lua +++ b/djvureader.lua @@ -24,24 +24,44 @@ function DJVUReader:adjustDjvuReaderCommand() end ------------[ highlight support ]---------- +---------------------------------------------------- +-- highlight support +---------------------------------------------------- +function DJVUReader:getText(pageno) + return self.doc:getPageText(pageno) +end ---------------------------------------------------- --- Given coordinates of four conners and return --- coordinate of upper left conner with with and height --- -- In djvulibre library, some coordinates starts from --- down left conner, i.e. y is upside down. This method --- only transform these coordinates. +-- lower left conner, i.e. y is upside down in kpv's +-- coordinate. So y0 should be taken with special care. ---------------------------------------------------- -function DJVUReader:rectCoordTransform(x0, y0, x1, y1) +function DJVUReader:zoomedRectCoordTransform(x0, y0, x1, y1) return - self.offset_x + x0 * self.globalzoom, - self.offset_y + self.cur_full_height - (y1 * self.globalzoom), + x0 * self.globalzoom, + self.cur_full_height - (y1 * self.globalzoom), (x1 - x0) * self.globalzoom, (y1 - y0) * self.globalzoom end -function DJVUReader:getText(pageno) - return self.doc:getPageText(pageno) +-- y axel in djvulibre starts from bottom +function DJVUReader:_isEntireWordInScreenHeightRange(w) + return (w ~= nil) and + (self.cur_full_height - (w.y1 * self.globalzoom) >= + -self.offset_y) and + (self.cur_full_height - (w.y0 * self.globalzoom) <= + -self.offset_y + G_height) end + +-- y axel in djvulibre starts from bottom +function DJVUReader:_isWordInScreenRange(w) + return (w ~= nil) and + (self.cur_full_height - (w.y0 * self.globalzoom) >= + -self.offset_y) and + (self.cur_full_height - (w.y1 * self.globalzoom) <= + -self.offset_y + G_height) and + (w.x1 * self.globalzoom >= -self.offset_x) and + (w.x0 * self.globalzoom <= -self.offset_x + G_width) +end + + diff --git a/pdfreader.lua b/pdfreader.lua index f998d4349..c6d55d9ad 100644 --- a/pdfreader.lua +++ b/pdfreader.lua @@ -31,16 +31,9 @@ function PDFReader:open(filename) return true end ------------[ highlight support ]---------- - -function PDFReader:rectCoordTransform(x0, y0, x1, y1) - return - x0 * self.globalzoom, - y1 * self.globalzoom - self.offset_y, - x1 - x0, - y1 - y0 -end - +---------------------------------------------------- +-- highlight support +---------------------------------------------------- function PDFReader:getText(pageno) local ok, page = pcall(self.doc.openPage, self.doc, pageno) if not ok then diff --git a/unireader.lua b/unireader.lua index 9ae8470ac..dcb229dab 100644 --- a/unireader.lua +++ b/unireader.lua @@ -112,20 +112,42 @@ function UniReader:init() self:addAllCommands() end ------------[ highlight support ]---------- +---------------------------------------------------- +-- highlight support +---------------------------------------------------- ---------------------------------------------------- --- Given coordinates of four conners and return --- coordinate of upper left conner with with and height +-- Given coordinates of four conners in oringinal page +-- size and return coordinate of upper left conner in +-- zoomed page size with width and height. ---------------------------------------------------- -function UniReader:rectCoordTransform(x0, y0, x1, y1) +function UniReader:zoomedRectCoordTransform(x0, y0, x1, y1) return x0 * self.globalzoom, - y1 * self.globalzoom - self.offset_y, + y0 * self.globalzoom, (x1 - x0) * self.globalzoom, (y1 - y0) * self.globalzoom end +---------------------------------------------------- +-- Given coordinates of four conners in oringinal page +-- size and return Rectangular area in screen. You +-- might want to call this when you want to draw stuff +-- on screen. +-- +-- NOTE: this method doese not check whether given area +-- is can be shown in current screen. Make sure to check +-- with _isEntireWordInScreenRange() before you want to +-- draw on screen. +---------------------------------------------------- +function UniReader:getRectInScreen(x0, y0, x1, y1) + x, y, w, h = self:zoomedRectCoordTransform(x0, y0, x1, y1) + return + x + self.offset_x, + y + self.offset_y, + w, h +end + -- make sure the whole word can be seen in screen function UniReader:_isEntireWordInScreenRange(w) return self:_isEntireWordInScreenHeightRange(w) and @@ -135,10 +157,8 @@ end -- y axel in djvulibre starts from bottom function UniReader:_isEntireWordInScreenHeightRange(w) return (w ~= nil) and - (self.cur_full_height - (w.y1 * self.globalzoom) >= - -self.offset_y) and - (self.cur_full_height - (w.y0 * self.globalzoom) <= - -self.offset_y + G_height) + (w.y1 * self.globalzoom) >= -self.offset_y + and (w.y0 * self.globalzoom) <= -self.offset_y + G_height end function UniReader:_isEntireWordInScreenWidthRange(w) @@ -150,12 +170,10 @@ end -- make sure at least part of the word can be seen in screen function UniReader:_isWordInScreenRange(w) return (w ~= nil) and - (self.cur_full_height - (w.y0 * self.globalzoom) >= - -self.offset_y) and - (self.cur_full_height - (w.y1 * self.globalzoom) <= - -self.offset_y + G_height) and - (w.x1 * self.globalzoom >= -self.offset_x) and - (w.x0 * self.globalzoom <= -self.offset_x + G_width) + (w.y0 * self.globalzoom) >= -self.offset_y + and w.y1 * self.globalzoom <= -self.offset_y + G_height + and w.x1 * self.globalzoom >= -self.offset_x + and w.x0 * self.globalzoom <= -self.offset_x + G_width end function UniReader:toggleTextHighLight(word_list) @@ -163,7 +181,7 @@ function UniReader:toggleTextHighLight(word_list) for _,line_item in ipairs(text_item) do -- make sure that line is in screen range if self:_isEntireWordInScreenHeightRange(line_item) then - local x, y, w, h = self:rectCoordTransform( + local x, y, w, h = self:getRectInScreen( line_item.x0, line_item.y0, line_item.x1, line_item.y1) -- slightly enlarge the highlight height @@ -183,9 +201,9 @@ function UniReader:toggleTextHighLight(word_list) elseif self.highlight.drawer == "marker" then fb.bb:invertRect(x, y, w, h) end - end -- EOF if isEntireWordInScreenHeightRange - end -- EOF for line_item - end -- EOF for text_item + end -- if isEntireWordInScreenHeightRange + end -- for line_item + end -- for text_item end function UniReader:_wordIterFromRange(t, l0, w0, l1, w1) @@ -217,7 +235,7 @@ function UniReader:_wordIterFromRange(t, l0, w0, l1, w1) end function UniReader:_toggleWordHighLight(t, l, w) - x, y, w, h = self:rectCoordTransform(t[l][w].x0, t[l].y0, + x, y, w, h = self:getRectInScreen(t[l][w].x0, t[l].y0, t[l][w].x1, t[l].y1) -- slightly enlarge the highlight range for better viewing experience x = x - w * 0.05 @@ -248,16 +266,20 @@ end -- remember to clear cursor before calling this function UniReader:drawCursorAfterWord(t, l, w) - local _, _, _, h = self:rectCoordTransform(0, t[l].y0, 0, t[l].y1) - local x, y, wd, h = self:rectCoordTransform(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) + -- get height of line t[l][w] is in + local _, _, _, h = self:zoomedRectCoordTransform(0, t[l].y0, 0, t[l].y1) + -- get rect of t[l][w] + local x, y, wd, h = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) self.cursor:setHeight(h) self.cursor:moveTo(x+wd, y) self.cursor:draw() end function UniReader:drawCursorBeforeWord(t, l, w) - local _, _, _, h = self:rectCoordTransform(0, t[l].y0, 0, t[l].y1) - local x, y, _, h = self:rectCoordTransform(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) + -- get height of line t[l][w] is in + local _, _, _, h = self:zoomedRectCoordTransform(0, t[l].y0, 0, t[l].y1) + -- get rect of t[l][w] + local x, y, _, h = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) self.cursor:setHeight(h) self.cursor:moveTo(x, y) self.cursor:draw() @@ -359,7 +381,7 @@ function UniReader:startHighLightMode() local is_meet_end = false local running = true - local cx, cy, cw, ch = self:rectCoordTransform( + local cx, cy, cw, ch = self:getRectInScreen( t[l.cur][w.cur].x0, t[l.cur][w.cur].y0, t[l.cur][w.cur].x1, @@ -716,18 +738,13 @@ function UniReader:startHighLightMode() running = false elseif ev.code == KEY_BACK then running = false - end -- EOF if key event + end -- if key event fb:refresh(1) end end -- EOF while end - - - - - ---------------------------------------------------- -- Renderer memory ---------------------------------------------------- From 66ab3a2f56f60104ddf16a22c60115a97e5b6dbc Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 12 Apr 2012 11:34:24 +0800 Subject: [PATCH 2/4] fix: typo in unireader's comment --- unireader.lua | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/unireader.lua b/unireader.lua index dcb229dab..d634ecb28 100644 --- a/unireader.lua +++ b/unireader.lua @@ -117,7 +117,7 @@ end ---------------------------------------------------- ---------------------------------------------------- --- Given coordinates of four conners in oringinal page +-- Given coordinates of four corners in original page -- size and return coordinate of upper left conner in -- zoomed page size with width and height. ---------------------------------------------------- @@ -130,15 +130,15 @@ function UniReader:zoomedRectCoordTransform(x0, y0, x1, y1) end ---------------------------------------------------- --- Given coordinates of four conners in oringinal page --- size and return Rectangular area in screen. You +-- Given coordinates of four corners in original page +-- size and return rectangular area in screen. You -- might want to call this when you want to draw stuff -- on screen. -- --- NOTE: this method doese not check whether given area +-- NOTE: this method does not check whether given area -- is can be shown in current screen. Make sure to check -- with _isEntireWordInScreenRange() before you want to --- draw on screen. +-- draw on the returned area. ---------------------------------------------------- function UniReader:getRectInScreen(x0, y0, x1, y1) x, y, w, h = self:zoomedRectCoordTransform(x0, y0, x1, y1) @@ -154,7 +154,6 @@ function UniReader:_isEntireWordInScreenRange(w) self:_isEntireWordInScreenWidthRange(w) end --- y axel in djvulibre starts from bottom function UniReader:_isEntireWordInScreenHeightRange(w) return (w ~= nil) and (w.y1 * self.globalzoom) >= -self.offset_y @@ -231,7 +230,7 @@ function UniReader:_wordIterFromRange(t, l0, w0, l1, w1) end return i, j end - end -- EOF closure + end -- closure end function UniReader:_toggleWordHighLight(t, l, w) From 75d5b5f98439c8dbb3415a0536e7273f3184b68d Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 12 Apr 2012 13:43:20 +0800 Subject: [PATCH 3/4] fix: three bugs in highlight mode * handle left end of first line in cursor move * properly highlight first word if cursor starts from left end of first line * handle right end of last line in cursor move --- unireader.lua | 62 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/unireader.lua b/unireader.lua index d634ecb28..d06f2b1d9 100644 --- a/unireader.lua +++ b/unireader.lua @@ -400,16 +400,23 @@ function UniReader:startHighLightMode() 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_LEFT then + if ev.code == KEY_FW_LEFT and not is_meet_start then + is_meet_end = false if w.cur == 1 then + -- goto left end of current line. _prevWord does not + -- understand and will not return zero w.cur + -- because zero does not point to a word, so we need to + -- handle left end manually here. w.cur = 0 w.new = 0 + if l.cur == 1 then + -- on left end of first line + is_meet_start = true + end else - if w.cur == 0 then - -- already at the left end of current line, - -- goto previous line (_prevWord does not understand - -- zero w.cur) - w.cur = 1 + -- handle left end manually. + if w.cur == 0 then + w.cur = 1 end l.new, w.new = _prevWord(t, l.cur, w.cur) end @@ -434,7 +441,9 @@ function UniReader:startHighLightMode() self:drawCursorAfterWord(t, l.new, w.new) end end - elseif ev.code == KEY_FW_RIGHT then + elseif ev.code == KEY_FW_RIGHT and not is_meet_end then + print(dump(l),dump(w)) + is_meet_start = false if w.cur == 0 then w.cur = 1 w.new = 1 @@ -447,6 +456,9 @@ function UniReader:startHighLightMode() w.new = 0 end end + if l.new == #t and w.new == #t[l.new] then + is_meet_end = true + end self.cursor:clear() @@ -470,13 +482,15 @@ function UniReader:startHighLightMode() self:drawCursorAfterWord(t, l.new, w.new) end end - elseif ev.code == KEY_FW_UP then + elseif ev.code == KEY_FW_UP and not is_meet_start then + is_meet_end = false if w.cur == 0 then -- goto left end of last line l.new = math.max(l.cur - 1, 1) elseif l.cur == 1 and w.cur == 1 then -- already first word, to the left end of first line w.new = 0 + is_meet_start = true else l.new, w.new = _wordInPrevLine(t, l.cur, w.cur) end @@ -503,7 +517,8 @@ function UniReader:startHighLightMode() self:drawCursorAfterWord(t, l.new, w.new) end end - elseif ev.code == KEY_FW_DOWN then + elseif ev.code == KEY_FW_DOWN and not is_meet_end then + is_meet_start = false if w.cur == 0 then -- on the left end of current line, -- goto left end of next line @@ -511,6 +526,9 @@ function UniReader:startHighLightMode() else l.new, w.new = _wordInNextLine(t, l.cur, w.cur) end + if l.new == #t and w.new == #t[l.new] then + is_meet_end = true + end self.cursor:clear() @@ -544,18 +562,14 @@ function UniReader:startHighLightMode() and t[l.cur][w.cur].x1 <= line_item.x1 then self.highlight[self.pageno][k] = nil end - end -- EOF for line_item - end -- EOF for text_item - end -- EOF if not highlight table + end -- for line_item + end -- for text_item + end -- if not highlight table if #self.highlight[self.pageno] == 0 then self.highlight[self.pageno] = nil end return elseif ev.code == KEY_FW_PRESS then - if w.cur == 0 then - w.cur = 1 - l.cur, w.cur = _prevWord(t, l.cur, w.cur) - end l.new, w.new = l.cur, w.cur l.start, w.start = l.cur, w.cur running = false @@ -563,15 +577,23 @@ function UniReader:startHighLightMode() elseif ev.code == KEY_BACK then running = false return - end -- EOF if key event + end -- if check key event l.cur, w.cur = l.new, w.new fb:refresh(1) end - end -- EOF while + end -- while running --print("start", l.cur, w.cur, l.start, w.start) -- two helper functions for highlight local function _togglePrevWordHighLight(t, l, w) + if w.cur == 0 then + if l.cur == 1 then + -- already at the begin of first line, nothing to toggle + return + else + w.cur = 1 + end + end l.new, w.new = _prevWord(t, l.cur, w.cur) if l.cur == 1 and w.cur == 1 then @@ -655,7 +677,7 @@ function UniReader:startHighLightMode() is_meet_start = false if not is_meet_end then l, w, is_meet_end = _toggleNextWordHighLight(t, l, w) - end -- EOF if is not is_meet_end + end -- if not is_meet_end elseif ev.code == KEY_FW_UP then is_meet_end = false if not is_meet_start then @@ -669,7 +691,7 @@ function UniReader:startHighLightMode() while not (tmp_l == l.cur and tmp_w == w.cur) do l, w, is_meet_start = _togglePrevWordHighLight(t, l, w) end - end + end -- not is_meet_start elseif ev.code == KEY_FW_DOWN then is_meet_start = false if not is_meet_end then From 3438d6749d8e0bf78c253890cc411af506cc7b62 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 12 Apr 2012 15:50:19 +0800 Subject: [PATCH 4/4] mod: rewrite part of highlight code * add _isEntireLineInScreenHeightRange() method For better page view navigation when highlighting or moving cursor. * bug fix in _isWordInScreenRange() method * add _nextGap(), _prevGap(), _gapInNextLine() and _gapInPrevLine() methods, so now key event handling code in cursor moving mode only focuses on drawing, calculation task is passed to these four methods. --- djvureader.lua | 20 +++-- unireader.lua | 203 ++++++++++++++++++++++++++++++------------------- 2 files changed, 138 insertions(+), 85 deletions(-) diff --git a/djvureader.lua b/djvureader.lua index dd1892103..ed90352cf 100644 --- a/djvureader.lua +++ b/djvureader.lua @@ -53,15 +53,23 @@ function DJVUReader:_isEntireWordInScreenHeightRange(w) -self.offset_y + G_height) end +-- y axel in djvulibre starts from bottom +function DJVUReader:_isEntireLineInScreenHeightRange(l) + return (l ~= nil) and + (self.cur_full_height - (l.y1 * self.globalzoom) >= + -self.offset_y) and + (self.cur_full_height - (l.y0 * self.globalzoom) <= + -self.offset_y + G_height) +end + -- y axel in djvulibre starts from bottom function DJVUReader:_isWordInScreenRange(w) return (w ~= nil) and - (self.cur_full_height - (w.y0 * self.globalzoom) >= - -self.offset_y) and - (self.cur_full_height - (w.y1 * self.globalzoom) <= - -self.offset_y + G_height) and - (w.x1 * self.globalzoom >= -self.offset_x) and - (w.x0 * self.globalzoom <= -self.offset_x + G_width) + (self.cur_full_height - (w.y0 * self.globalzoom) >= -self.offset_y + or self.cur_full_height - (w.y1 * self.globalzoom) <= -self.offset_y + G_height) + and + (w.x1 * self.globalzoom >= -self.offset_x + or w.x0 * self.globalzoom <= -self.offset_x + G_width) end diff --git a/unireader.lua b/unireader.lua index d06f2b1d9..c5d0c20d1 100644 --- a/unireader.lua +++ b/unireader.lua @@ -148,7 +148,15 @@ function UniReader:getRectInScreen(x0, y0, x1, y1) w, h end --- make sure the whole word can be seen in screen +-- make sure the whole word/line can be seen in screen +-- @TODO when not in FIT_TO_CONTENT_WIDTH mode, +-- self.offset_{x,y} might be negative. 12.04 2012 (houqp) +function UniReader:_isEntireLineInScreenHeightRange(l) + return (l ~= nil) and + (l.y0 * self.globalzoom) >= -self.offset_y + and (l.y1 * self.globalzoom) <= -self.offset_y + G_height +end + function UniReader:_isEntireWordInScreenRange(w) return self:_isEntireWordInScreenHeightRange(w) and self:_isEntireWordInScreenWidthRange(w) @@ -156,8 +164,8 @@ end function UniReader:_isEntireWordInScreenHeightRange(w) return (w ~= nil) and - (w.y1 * self.globalzoom) >= -self.offset_y - and (w.y0 * self.globalzoom) <= -self.offset_y + G_height + (w.y0 * self.globalzoom) >= -self.offset_y + and (w.y1 * self.globalzoom) <= -self.offset_y + G_height end function UniReader:_isEntireWordInScreenWidthRange(w) @@ -169,10 +177,11 @@ end -- make sure at least part of the word can be seen in screen function UniReader:_isWordInScreenRange(w) return (w ~= nil) and - (w.y0 * self.globalzoom) >= -self.offset_y - and w.y1 * self.globalzoom <= -self.offset_y + G_height - and w.x1 * self.globalzoom >= -self.offset_x - and w.x0 * self.globalzoom <= -self.offset_x + G_width + ((w.y1 * self.globalzoom) >= -self.offset_y + or w.y0 * self.globalzoom <= -self.offset_y + G_height) + and + (w.x1 * self.globalzoom >= -self.offset_x + or w.x0 * self.globalzoom <= -self.offset_x + G_width) end function UniReader:toggleTextHighLight(word_list) @@ -268,7 +277,7 @@ function UniReader:drawCursorAfterWord(t, l, w) -- get height of line t[l][w] is in local _, _, _, h = self:zoomedRectCoordTransform(0, t[l].y0, 0, t[l].y1) -- get rect of t[l][w] - local x, y, wd, h = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) + local x, y, wd, _ = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) self.cursor:setHeight(h) self.cursor:moveTo(x+wd, y) self.cursor:draw() @@ -278,7 +287,7 @@ function UniReader:drawCursorBeforeWord(t, l, w) -- get height of line t[l][w] is in local _, _, _, h = self:zoomedRectCoordTransform(0, t[l].y0, 0, t[l].y1) -- get rect of t[l][w] - local x, y, _, h = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) + local x, y, _, _ = self:getRectInScreen(t[l][w].x0, t[l][w].y0, t[l][w].x1, t[l][w].y1) self.cursor:setHeight(h) self.cursor:moveTo(x, y) self.cursor:draw() @@ -305,6 +314,13 @@ function UniReader:startHighLightMode() return nil end + local function _isMovingForward(l, w) + return l.cur > l.start or (l.cur == l.start and w.cur > w.start) + end + + --------------------------------------- + -- some word handling help functions + --------------------------------------- local function _prevWord(t, cur_l, cur_w) if cur_l == 1 then if cur_w == 1 then @@ -361,10 +377,88 @@ function UniReader:startHighLightMode() end end - local function _isMovingForward(l, w) - return l.cur > l.start or (l.cur == l.start and w.cur > w.start) + --------------------------------------- + -- some gap handling help functions + --------------------------------------- + local function _nextGap(t, cur_l, cur_w) + local is_meet_end = false + + -- handle left end of line as special case. + if cur_w == 0 then + if cur_l == #t and #t[cur_l] == 1 then + is_meet_end = true + end + return cur_l, 1, is_meet_end + end + + cur_l, cur_w = _nextWord(t, cur_l, cur_w) + if cur_w == 1 then + cur_w = 0 + end + if cur_w ~= 0 and cur_l == #t and cur_w == #t[cur_l] then + is_meet_end = true + end + return cur_l, cur_w, is_meet_end end + local function _prevGap(t, cur_l, cur_w) + local is_meet_start = false + + -- handle left end of line as special case. + if cur_l == 1 and (cur_w == 1 or cur_w == 0) then -- in the first line + is_meet_start = true + return cur_l, 0, is_meet_start + end + if cur_w == 1 then -- not in the first line + return cur_l, 0, is_meet_start + elseif cur_w == 0 then + -- set to 1 so _prevWord() can find previous word in previous line + cur_w = 1 + end + + cur_l, cur_w = _prevWord(t, cur_l, cur_w) + return cur_l, cur_w, is_meet_end + end + + local function _gapInNextLine(t, cur_l, cur_w) + local is_meet_end = false + + if cur_l == #t then + -- already in last line + cur_w = #t[cur_l] + is_meet_end = true + else + -- handle left end of line as special case. + if cur_w == 0 then + cur_l = math.min(cur_l + 1, #t) + else + cur_l, cur_w = _wordInNextLine(t, cur_l, cur_w) + end + end + + return cur_l, cur_w, is_meet_end + end + + local function _gapInPrevLine(t, cur_l, cur_w) + local is_meet_start = false + + if cur_l == 1 then + -- already in first line + is_meet_start = true + cur_w = 0 + else + if cur_w == 0 then + -- goto left end of previous line + cur_l = math.max(cur_l - 1, 1) + else + cur_l, cur_w = _wordInPrevLine(t, cur_l, cur_w) + end + end + + return cur_l, cur_w, is_meet_start + end + + local l = {} local w = {} @@ -402,28 +496,11 @@ function UniReader:startHighLightMode() if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then if ev.code == KEY_FW_LEFT and not is_meet_start then is_meet_end = false - if w.cur == 1 then - -- goto left end of current line. _prevWord does not - -- understand and will not return zero w.cur - -- because zero does not point to a word, so we need to - -- handle left end manually here. - w.cur = 0 - w.new = 0 - if l.cur == 1 then - -- on left end of first line - is_meet_start = true - end - else - -- handle left end manually. - if w.cur == 0 then - w.cur = 1 - end - l.new, w.new = _prevWord(t, l.cur, w.cur) - end + l.new, w.new, is_meet_start = _prevGap(t, l.cur, w.cur) self.cursor:clear() if w.new ~= 0 - and not self:_isEntireWordInScreenHeightRange(t[l.new][w.new]) + and not self:_isEntireLineInScreenHeightRange(t[l.new]) and self:_isEntireWordInScreenWidthRange(t[l.new][w.new]) then -- word is in previous view local pageno = self:prevView() @@ -431,10 +508,10 @@ function UniReader:startHighLightMode() end -- update cursor - if w.cur == 0 then + if w.new == 0 then -- meet line left end, must be handled as special case - if self:_isEntireWordInScreenRange(t[l.cur][1]) then - self:drawCursorBeforeWord(t, l.cur, 1) + if self:_isEntireWordInScreenRange(t[l.new][1]) then + self:drawCursorBeforeWord(t, l.new, 1) end else if self:_isEntireWordInScreenRange(t[l.new][w.new]) then @@ -442,37 +519,23 @@ function UniReader:startHighLightMode() end end elseif ev.code == KEY_FW_RIGHT and not is_meet_end then - print(dump(l),dump(w)) is_meet_start = false - if w.cur == 0 then - w.cur = 1 - w.new = 1 - else - l.new, w.new = _nextWord(t, l.cur, w.cur) - if w.new == 1 then - -- Must be come from the right end of previous line, - -- so goto the left end of current line. - w.cur = 0 - w.new = 0 - end - end - if l.new == #t and w.new == #t[l.new] then - is_meet_end = true - end + l.new, w.new, is_meet_end = _nextGap(t, l.cur, w.cur) self.cursor:clear() - + -- we want to check whether the word is in screen range, + -- so trun gap into word local tmp_w = w.new - if w.cur == 0 then + if tmp_w == 0 then tmp_w = 1 end - if not self:_isEntireWordInScreenHeightRange(t[l.new][tmp_w]) + if not self:_isEntireLineInScreenHeightRange(t[l.new]) and self:_isEntireWordInScreenWidthRange(t[l.new][tmp_w]) then local pageno = self:nextView() self:goto(pageno) end - if w.cur == 0 then + if w.new == 0 then -- meet line left end, must be handled as special case if self:_isEntireWordInScreenRange(t[l.new][1]) then self:drawCursorBeforeWord(t, l.new, 1) @@ -484,24 +547,15 @@ function UniReader:startHighLightMode() end elseif ev.code == KEY_FW_UP and not is_meet_start then is_meet_end = false - if w.cur == 0 then - -- goto left end of last line - l.new = math.max(l.cur - 1, 1) - elseif l.cur == 1 and w.cur == 1 then - -- already first word, to the left end of first line - w.new = 0 - is_meet_start = true - else - l.new, w.new = _wordInPrevLine(t, l.cur, w.cur) - end + l.new, w.new, is_meet_start = _gapInPrevLine(t, l.cur, w.cur) self.cursor:clear() local tmp_w = w.new - if w.cur == 0 then + if tmp_w == 0 then tmp_w = 1 end - if not self:_isEntireWordInScreenHeightRange(t[l.new][tmp_w]) + if not self:_isEntireLineInScreenHeightRange(t[l.new]) and self:_isEntireWordInScreenWidthRange(t[l.new][tmp_w]) then -- goto next view of current page local pageno = self:prevView() @@ -519,16 +573,7 @@ function UniReader:startHighLightMode() end elseif ev.code == KEY_FW_DOWN and not is_meet_end then is_meet_start = false - if w.cur == 0 then - -- on the left end of current line, - -- goto left end of next line - l.new = math.min(l.cur + 1, #t) - else - l.new, w.new = _wordInNextLine(t, l.cur, w.cur) - end - if l.new == #t and w.new == #t[l.new] then - is_meet_end = true - end + l.new, w.new, is_meet_end = _gapInNextLine(t, l.cur, w.cur) self.cursor:clear() @@ -536,7 +581,7 @@ function UniReader:startHighLightMode() if w.cur == 0 then tmp_w = 1 end - if not self:_isEntireWordInScreenHeightRange(t[l.new][tmp_w]) + if not self:_isEntireLineInScreenHeightRange(t[l.new]) and self:_isEntireWordInScreenWidthRange(t[l.new][tmp_w]) then -- goto next view of current page local pageno = self:nextView() @@ -589,7 +634,7 @@ function UniReader:startHighLightMode() if w.cur == 0 then if l.cur == 1 then -- already at the begin of first line, nothing to toggle - return + return l, w, true else w.cur = 1 end @@ -603,7 +648,7 @@ function UniReader:startHighLightMode() end if w.new ~= 0 and - not self:_isEntireWordInScreenHeightRange(t[l.new][w.new]) then + not self:_isEntireLineInScreenHeightRange(t[l.new][w.new]) then -- word out of left and right sides of current view should -- not trigger pan by page if self:_isEntireWordInScreenWidthRange(t[l.new][w.new]) then @@ -640,7 +685,7 @@ function UniReader:startHighLightMode() is_meet_end = true end - if not self:_isEntireWordInScreenHeightRange(t[l.new][w.new]) then + if not self:_isEntireLineInScreenHeightRange(t[l.new]) then if self:_isEntireWordInScreenWidthRange(t[l.new][w.new]) then local pageno = self:nextView() self:goto(pageno)