Merge pull request #170 from dpavlin/NuPogodi

NuPogodi patch 19.05.2012
{Qingping,Dave} Hou 12 years ago
commit 763b97744b

@ -133,6 +133,7 @@ fetchthirdparty:
git submodule init
git submodule update
ln -sf kpvcrlib/crengine/cr3gui/data data
test -e data/cr3.css || ln kpvcrlib/cr3.css data/
test -d fonts || ln -sf $(TTF_FONTS_DIR) fonts
# CREngine patch: disable fontconfig
grep USE_FONTCONFIG $(CRENGINEDIR)/crengine/include/crsetup.h && grep -v USE_FONTCONFIG $(CRENGINEDIR)/crengine/include/crsetup.h > /tmp/new && mv /tmp/new $(CRENGINEDIR)/crengine/include/crsetup.h || echo "USE_FONTCONFIG already disabled"

@ -9,8 +9,15 @@ CREReader = UniReader:new{
gamma_index = 15,
font_face = nil,
-- NuPogodi, 17.05.12: to store fontsize changes
font_zoom = 0,
line_space_percent = 100,
-- NuPogodi, 17.05.12: insert new parameter to store old doc height before rescaling.
-- One needs it to change font(face & size) and / or interline spacig without
-- appreciable changing of the current position in document
old_doc_height = 0,
}
function CREReader:init()
@ -31,22 +38,24 @@ function CREReader:open(filename)
local ok
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
-- these two format use the same css file
if file_type == "html" then
file_type = "htm"
end
-- detect file type for documents inside zip file
-- @TODO do the detection after the file is unzipped 30.04 2012 (houqp)
-- try to find double extentions like fb2.zip or htm.zip
if file_type == "zip" then
-- store filename without zip-extention to fn
-- remove zip-extention
local fn = string.lower(string.sub(filename,0,-4))
-- if no double extention then default file_type
file_type = string.lower(string.match(fn, ".+%.([^.]+)") or "fb2")
end
file_type = string.lower(string.match(fn, ".+%.([^.]+)") or "cr3")
end
-- these two format use the same css file
if file_type == "html" then
file_type = "htm"
end
-- if native css-file doesn't exist, one needs to use default cr3.css
if not io.open("./data/"..file_type..".css") then
file_type = "cr3"
end
local style_sheet = "./data/"..file_type..".css"
ok, self.doc = pcall(cre.openDocument, filename, style_sheet,
ok, self.doc = pcall(cre.openDocument, filename, style_sheet,
G_width, G_height)
if not ok then
return false, self.doc -- will contain error message
@ -62,7 +71,7 @@ end
----------------------------------------------------
function CREReader:loadSpecialSettings()
local font_face = self.settings:readSetting("font_face")
self.font_face = font_face or "Droid Sans Fallback"
self.font_face = font_face or "Droid Sans"
self.doc:setFontFace(self.font_face)
local gamma_index = self.settings:readSetting("gamma_index")
@ -71,6 +80,19 @@ function CREReader:loadSpecialSettings()
local line_space_percent = self.settings:readSetting("line_space_percent")
self.line_space_percent = line_space_percent or self.line_space_percent
-- NuPogodi, 17.05.12: reading & setting the font size
self.font_zoom = self.settings:readSetting("font_zoom") or 0
if self.font_zoom ~= 0 then
local i = math.abs(self.font_zoom)
local step = self.font_zoom / i
while i>0 do
self.doc:zoomFont(step)
i=i-1
end
end
-- define the original document height
self.old_doc_height = self.doc:getFullHeight()
end
function CREReader:getLastPageOrPos()
@ -86,6 +108,8 @@ function CREReader:saveSpecialSettings()
self.settings:saveSetting("font_face", self.font_face)
self.settings:saveSetting("gamma_index", self.gamma_index)
self.settings:saveSetting("line_space_percent", self.line_space_percent)
-- NuPogodi, 17.05.12: saving the font size
self.settings:saveSetting("font_zoom", self.font_zoom)
end
function CREReader:saveLastPageOrPos()
@ -101,7 +125,12 @@ function CREReader:setzoom(page, preCache)
end
function CREReader:redrawCurrentPage()
self:goto(self.pos)
-- NuPogodi, 15.05.12: Something was wrong here!
-- self:goto(self.pos)
-- after changing the font(face, size or boldface) or interline spacing
-- the position inside document HAS TO REMAIN CONSTANT! it was NOT!
-- Fixed the problem by the following correction to new document height
self:goto(self.pos * (self.doc:getFullHeight() - G_height) / (self.old_doc_height - G_height))
end
-- there is no zoom mode in CREReader
@ -158,6 +187,8 @@ function CREReader:goto(pos, is_ignore_jump, pos_type)
self.pos = pos
self.pageno = self.doc:getCurrentPage()
self.percent = self.doc:getCurrentPercent()
-- NuPogodi, 18.05.12: storing new document height
self.old_doc_height = self.doc:getFullHeight()
end
function CREReader:gotoPercent(percent)
@ -282,17 +313,26 @@ function CREReader:_drawReadingInfo()
fb.bb:paintRect(0, ypos, G_width, 50, 0)
ypos = ypos + 15
local face = Font:getFace("rifont", 22)
-- NuPogodi 15.05.12: a bit smaller font 20 instead of 22
local face = Font:getFace("rifont", 20)
local cur_section = self:getTocTitleOfCurrentPage()
if cur_section ~= "" then
cur_section = "Section: "..cur_section
end
renderUtf8Text(fb.bb, 10, ypos+6, face,
"Position: "..load_percent.."%".." "..cur_section, true)
-- NuPogodi 15.05.12: Rewrite the following renderUtf8Text() in order to fix too long strings
local footer = "Position: "..load_percent.."\%".." "..cur_section
if sizeUtf8Text(10, fb.bb:getWidth(), face, footer, true).x < (fb.bb:getWidth() - 20) then
renderUtf8Text(fb.bb, 10, ypos+6, face, footer, true)
else
local gapx = sizeUtf8Text(10, fb.bb:getWidth(), face, "...", true).x
gapx = 10 + renderUtf8TextWidth(fb.bb, 10, ypos+6, face, footer, true, fb.bb:getWidth() - 30 - gapx).x
renderUtf8Text(fb.bb, gapx, ypos+6, face, "...", true)
end
-- end of changes (NuPogodi)
ypos = ypos + 15
blitbuffer.progressBar(fb.bb, 10, ypos, G_width - 20, 15,
5, 4, load_percent/100, 8)
blitbuffer.progressBar(fb.bb, 10, ypos, G_width - 20, 15, 5, 4, load_percent/100, 8)
end
@ -323,6 +363,13 @@ function CREReader:adjustCreReaderCommands()
-- overwrite commands
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(cr)
Screen:screenshot()
end
)
self.commands:addGroup(MOD_SHIFT.."< >",{
Keydef:new(KEY_PGBCK,MOD_SHIFT),Keydef:new(KEY_PGFWD,MOD_SHIFT),
Keydef:new(KEY_LPGBCK,MOD_SHIFT),Keydef:new(KEY_LPGFWD,MOD_SHIFT)},
@ -334,9 +381,15 @@ function CREReader:adjustCreReaderCommands()
delta = -1
change = "decrease"
end
InfoMessage:show(change.." font size", 0)
self.font_zoom = self.font_zoom + delta
InfoMessage:show(change.." font size to "..self.font_zoom, 0)
-- NuPogodi, 15.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
-- end of changes (NuPogodi)
self.doc:zoomFont(delta)
self:redrawCurrentPage()
-- NuPogodi, 18.05.12: storing new height of document & refreshing TOC
self:fillToc()
end
)
self.commands:addGroup(MOD_ALT.."< >",{
@ -346,19 +399,20 @@ function CREReader:adjustCreReaderCommands()
function(self)
if keydef.keycode == KEY_PGBCK or keydef.keycode == KEY_LPGBCK then
self.line_space_percent = self.line_space_percent - 10
if self.line_space_percent < 100 then
self.line_space_percent = 100
end
-- NuPogodi, 15.05.12: reduce lowest space_percent to 80
self.line_space_percent = math.max(self.line_space_percent, 80)
else
self.line_space_percent = self.line_space_percent + 10
if self.line_space_percent > 200 then
self.line_space_percent = 200
end
self.line_space_percent = math.min(self.line_space_percent, 200)
end
InfoMessage:show("line spacing "..self.line_space_percent.."%", 0)
InfoMessage:show("line spacing "..self.line_space_percent.."\%", 0)
debug("line spacing set to", self.line_space_percent)
-- NuPogodi, 17.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
self.doc:setDefaultInterlineSpace(self.line_space_percent)
self:redrawCurrentPage()
-- NuPogodi, 18.05.12: storing new height of document & refreshing TOC
self:fillToc()
end
)
local numeric_keydefs = {}
@ -374,20 +428,27 @@ function CREReader:adjustCreReaderCommands()
self:goto(math.floor(self.doc:getFullHeight()*(keydef.keycode-KEY_1)/9))
end
)
self.commands:add(KEY_F, nil, "F",
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"change document font",
function(self)
Screen:saveCurrentBB()
local face_list = cre.getFontFaces()
-- NuPogodi, 18.05.12: define the number of the current font in face_list
local item_no = 0
while face_list[item_no] ~= self.font_face and item_no < #face_list do
item_no = item_no + 1
end
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = face_list,
menu_title = "Fonts Menu ",
item_array = face_list,
current_entry = item_no - 1,
}
local item_no = fonts_menu:choose(0, G_height)
debug(face_list[item_no])
-- NuPogodi, 17.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
if item_no then
Screen:restoreFromSavedBB()
self.doc:setFontFace(face_list[item_no])
@ -395,13 +456,19 @@ function CREReader:adjustCreReaderCommands()
InfoMessage:show("Redrawing with "..face_list[item_no], 0)
end
self:redrawCurrentPage()
-- NuPogodi, 18.05.12: storing new height of document & refreshing TOC
self:fillToc()
end
)
self.commands:add(KEY_F, MOD_ALT, "F",
"Toggle font bolder attribute",
function(self)
-- NuPogodi, 17.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
self.doc:toggleFontBolder()
self:redrawCurrentPage()
-- NuPogodi, 18.05.12: storing new height of document & refreshing TOC
self:fillToc()
end
)
self.commands:add(KEY_B, MOD_ALT, "B",
@ -450,6 +517,8 @@ function CREReader:adjustCreReaderCommands()
cre.setGammaIndex(self.gamma_index+delta)
self.gamma_index = cre.getGammaIndex()
self:redrawCurrentPage()
-- NuPogodi, 16.05.12: FIXED! gamma_index -> self.gamma_index
showInfoMsgWithDelay("Redraw with gamma = "..self.gamma_index, 2000, 1)
end
)
self.commands:add(KEY_FW_UP, nil, "joypad up",

@ -0,0 +1,24 @@
-- List of acceptable extentions
ext = {
djvuRead = ";djvu;",
pdfRead = ";pdf;xps;cbz;",
creRead = ";epub;txt;rtf;htm;html;mobi;prc;azw;fb2;chm;pdb;doc;tcr;zip;"
-- seems to accept pdb-files for PalmDoc only
}
function ext:getReader(ftype)
local s = ";"
if ftype == "" then
return nil
elseif string.find(self.djvuRead,s..ftype..s) then
return DJVUReader
elseif string.find(self.pdfRead,s..ftype..s) then
return PDFReader
elseif string.find(self.creRead,s..ftype..s) then
return CREReader
else
return nil
end
end

@ -3,14 +3,22 @@ require "keys"
require "graphics"
require "font"
require "filesearcher"
require "filehistory"
require "fileinfo"
require "inputbox"
require "selectmenu"
require "dialog"
require "extentions"
FileChooser = {
-- Class vars:
-- title height
title_H = 40,
-- spacing between lines
spacing = 40,
spacing = 36,
-- foot height
foot_H = 28,
-- horisontal margin
margin_H = 10,
-- state buffer
dirs = nil,
@ -22,6 +30,66 @@ FileChooser = {
oldcurrent = 0,
exception_message = nil
}
-- to duplicate visual info by speaking
function say(text)
os.execute("say ".."\""..text.."\"")
end
-- make long headers for fit in title width by removing first characters
function getProperTitleLength(txt,font_face,max_width)
local tw = TextWidget:new({ text = txt, face = font_face})
-- 1st approximation for a point where to start title
local n = math.floor(string.len(txt) * (1 - max_width / tw:getSize().w)) - 2
n = math.max(n, 1)
while tw:getSize().w >= max_width do
tw:free()
tw = TextWidget:new({ text = string.sub(txt,n,-1), face = font_face})
n = n + 1
end
return string.sub(txt,n-1,-1)
end
function BatteryLevel()
local fn, battery = "./data/temporary", "?"
-- NuPogodi, 18.05.12: This command seems to work even without Amazon Kindle framework
os.execute("\(gasgauge-info ".."-s\) ".."> "..fn)
if io.open(fn,"r") then
for lines in io.lines(fn) do battery = " " .. lines end
else
battery = ""
end
return battery
end
function DrawTitle(text,lmargin,y,height,color,font_face)
fb.bb:paintRect(lmargin, y+10, fb.bb:getWidth() - lmargin*2, height, color)
-- to have a horisontal gap between text & background rectangle
lmargin = lmargin + 10
t = BatteryLevel() .. os.date(" %H:%M")
local tw = TextWidget:new({ text = t, face = font_face})
twidth = tw:getSize().w
renderUtf8Text(fb.bb, fb.bb:getWidth()-twidth-lmargin, y + height, font_face, t, true)
tw:free()
tw = TextWidget:new({ text = text, face = font_face})
local max_width = fb.bb:getWidth() - 2 * lmargin - twidth
if tw:getSize().w < max_width then
renderUtf8Text(fb.bb, lmargin, y + height, font_face, text, true)
else
tw:free()
-- separately draw the title prefix = ...
local tw = TextWidget:new({ text = "...", face = font_face})
renderUtf8Text(fb.bb, lmargin, y + height, font_face, "...", true)
-- then define proper text length and draw it
local txt = getProperTitleLength(text,font_face,max_width-tw:getSize().w)
renderUtf8Text(fb.bb, lmargin+tw:getSize().w, y + height, font_face, txt, true)
end
end
function DrawFooter(text,font_face,h)
y = G_height - 7
x = (G_width / 2) - 50
renderUtf8Text(fb.bb, x, y, font_face, text, true)
end
function getAbsolutePath(aPath)
local abs_path
@ -49,23 +117,19 @@ function FileChooser:readDir()
self.dirs = {}
self.files = {}
for f in lfs.dir(self.path) do
if lfs.attributes(self.path.."/"..f, "mode") == "directory" and f ~= "." and not (f==".." and self.path=="/") and not string.match(f, "^%.[^.]") then
--debug(self.path.." -> adding: '"..f.."'")
table.insert(self.dirs, f)
else
if lfs.attributes(self.path.."/"..f, "mode") == "directory" and f ~= "." and f~=".."
and not string.match(f, "^%.[^.]") then
table.insert(self.dirs, f)
elseif lfs.attributes(self.path.."/"..f, "mode") == "file"
and not string.match(f, "^%.[^.]") then
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
if file_type == "djvu"
or file_type == "pdf" or file_type == "xps" or file_type == "cbz"
or file_type == "epub" or file_type == "txt" or file_type == "rtf"
or file_type == "htm" or file_type == "html" or file_type == "mobi" or file_type == "prc"
or file_type == "fb2" or file_type == "chm" or file_type == "doc"
or file_type == "zip" then
if ext:getReader(file_type) then
table.insert(self.files, f)
end
end
end
--@TODO make sure .. is sortted to the first item 16.02 2012
table.sort(self.dirs)
if self.path~="/" then table.insert(self.dirs,1,"..") end
table.sort(self.files)
end
@ -88,6 +152,28 @@ function FileChooser:setPath(newPath)
end
end
function DrawFileItem(name,x,y,image)
-- define icon file for
if name == ".." then image = "upfolder" end
local fn = "./resources/"..image..".png"
-- check whether the icon file exists or not
if not io.open(fn, "r") then fn = "./resources/other.png" end
local iw = ImageWidget:new({ file = fn })
iw:paintTo(fb.bb, x, y - iw:getSize().h + 1)
-- then drawing filenames
local cface = Font:getFace("cfont", 22)
local xleft = x + iw:getSize().w + 9 -- 8-10 pixels = the gap between icon & filename
local width = fb.bb:getWidth() - xleft - x
-- now printing the name
if sizeUtf8Text(xleft, fb.bb:getWidth() - x, cface, name, true).x < width then
renderUtf8Text(fb.bb, xleft, y, cface, name, true)
else
local lgap = sizeUtf8Text(0, width, cface, " ...", true).x
local handle = renderUtf8TextWidth(fb.bb, xleft, y, cface, name, true, width - lgap - x)
renderUtf8Text(fb.bb, handle.x + lgap + x, y, cface, " ...", true)
end
end
function FileChooser:choose(ypos, height)
local perpage = math.floor(height / self.spacing) - 2
local pagedirty = true
@ -123,40 +209,46 @@ function FileChooser:choose(ypos, height)
end
while true do
local cface = Font:getFace("cfont", 25)
local tface = Font:getFace("tfont", 25)
local fface = Font:getFace("ffont", 16)
local cface = Font:getFace("cfont", 22)
if pagedirty then
-- starttime was to optimize drawing process
--local starttime = os.clock()
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
local c
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
if i <= #self.dirs then
-- resembles display in midnight commander: adds "/" prefix for directories
renderUtf8Text(fb.bb, 39, ypos + self.spacing*c, cface, "/", true)
renderUtf8Text(fb.bb, 50, ypos + self.spacing*c, cface, self.dirs[i], true)
DrawFileItem(self.dirs[i],self.margin_H,ypos+self.title_H+self.spacing*c,"folder")
elseif i <= self.items then
renderUtf8Text(fb.bb, 50, ypos + self.spacing*c, cface, self.files[i-#self.dirs], true)
local file_type = string.lower(string.match(self.files[i-#self.dirs], ".+%.([^.]+)") or "")
DrawFileItem(self.files[i-#self.dirs],self.margin_H,ypos+self.title_H+self.spacing*c,file_type)
end
end
-- draw footer
all_page = math.ceil(self.items/perpage)
renderUtf8Text(fb.bb, 5, ypos + self.spacing * perpage + 42, fface,
"Page "..self.page.." of "..all_page, true)
local msg = self.exception_message and self.exception_message:match("[^%:]+:%d+: (.*)") or "Path: "..self.path
DrawFooter("Page "..self.page.." of "..all_page,fface,self.foot_H)
-- draw menu title
local msg = self.exception_message and self.exception_message:match("[^%:]+:%d+: (.*)") or self.path
self.exception_message = nil
renderUtf8Text(fb.bb, 5, ypos + self.spacing * (perpage+1) + 27, fface, msg, true)
-- draw header
DrawTitle(msg,self.margin_H,ypos,self.title_H,4,tface)
--say("The page was drawn in "..string.format("%.2f",os.clock()-starttime).." seconds.")
markerdirty = true
end
if markerdirty then
local ymarker = ypos + 8 + self.title_H
if not pagedirty then
if self.oldcurrent > 0 then
fb.bb:paintRect(30, ypos + self.spacing*self.oldcurrent + 10, fb.bb:getWidth() - 60, 3, 0)
fb:refresh(1, 30, ypos + self.spacing*self.oldcurrent + 10, fb.bb:getWidth() - 60, 3)
fb.bb:paintRect(self.margin_H, ymarker+self.spacing*self.oldcurrent, fb.bb:getWidth()-2*self.margin_H, 3, 0)
fb:refresh(1, self.margin_H, ymarker+self.spacing*self.oldcurrent, fb.bb:getWidth() - 2*self.margin_H, 3)
end
end
fb.bb:paintRect(30, ypos + self.spacing*self.current + 10, fb.bb:getWidth() - 60, 3, 15)
fb.bb:paintRect(self.margin_H, ymarker+self.spacing*self.current, fb.bb:getWidth()-2*self.margin_H, 3, 15)
if not pagedirty then
fb:refresh(1, 30, ypos + self.spacing*self.current + 10, fb.bb:getWidth() - 60, 3)
fb:refresh(1, self.margin_H, ymarker+self.spacing*self.current, fb.bb:getWidth()-2*self.margin_H, 3)
end
self.oldcurrent = self.current
markerdirty = false
@ -174,10 +266,19 @@ function FileChooser:choose(ypos, height)
prevItem()
elseif ev.code == KEY_FW_DOWN then
nextItem()
elseif ev.code == KEY_F then -- invoke fontchooser menu
elseif ev.code == KEY_F or ev.code == KEY_AA then -- invoke fontchooser menu
-- NuPogodi, 18.05.12: define the number of the current font in face_list
local item_no = 0
local face_list = Font:getFontList()
while face_list[item_no] ~= Font.fontmap.cfont and item_no < #face_list do
item_no = item_no + 1
end
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = Font:getFontList(),
item_array = face_list,
-- NuPogodi, 18.05.12: define selected item
current_entry = item_no - 1,
}
local re, font = fonts_menu:choose(0, height)
if re then
@ -198,12 +299,21 @@ function FileChooser:choose(ypos, height)
settings menu in the future.
--]]
return nil, function()
InfoMessage:show("Searching...",0)
InfoMessage:show("Searching... ",0)
FileSearcher:init( self.path )
FileSearcher:choose(keywords)
end
end
pagedirty = true
elseif ev.code == KEY_L then -- last opened files
InfoMessage:show("Searching last docs... ",0)
if true then
return nil, function()
FileHistory:init()
FileHistory:choose("") -- show all files
end
end
pagedirty = true
elseif ev.code == KEY_PGFWD or ev.code == KEY_LPGFWD then
if self.page < (self.items / perpage) then
if self.current + self.page*perpage > self.items then
@ -235,6 +345,48 @@ function FileChooser:choose(ypos, height)
return self.path.."/"..self.files[perpage*(self.page-1)+self.current - #self.dirs]
end
pagedirty = true
elseif ev.code == KEY_P then -- make screenshot
Screen:screenshot()
elseif ev.code == KEY_FW_RIGHT or ev.code == KEY_I then -- show file info
return nil, function()
local newdir = self.dirs[perpage*(self.page-1)+self.current]
if newdir == ".." then
showInfoMsgWithDelay("<UP-DIR>",1000,1)
elseif newdir then
showInfoMsgWithDelay("<DIR>",1000,1)
else
FileInfo:show(self.path,self.files[perpage*(self.page-1)+self.current - #self.dirs])
pagedirty = true
end
end
elseif ev.code == KEY_SPACE then -- manual refresh
pagedirty = true
elseif ev.code == KEY_DEL then
local dir_to_del = self.dirs[perpage*(self.page-1)+self.current]
if dir_to_del == ".." then
showInfoMsgWithDelay("<UP-DIR>",1000,1)
elseif dir_to_del then
showInfoMsgWithDelay("<DIR>",1000,1)
else
local file_to_del=self.path.."/"..self.files[perpage*(self.page-1)+self.current - #self.dirs]
InfoMessage:show("Press \'Y\' to confirm deleting... ",0)
while true do
ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
if ev.code == KEY_Y then
-- delete the file itself
os.execute("rm \""..file_to_del.."\"")
-- and its history file, if any
os.execute("rm \""..DocToHistory(file_to_del).."\"")
-- to avoid showing just deleted file
self:setPath(self.path)
end
pagedirty = true
break
end
end -- while
end
elseif ev.code == KEY_BACK or ev.code == KEY_HOME then
return nil
end

@ -0,0 +1,388 @@
require "rendertext"
require "keys"
require "graphics"
require "font"
require "inputbox"
require "dialog"
require "filesearcher"
require "settings"
FileHistory = {
-- title height
title_H = 40,
-- spacing between lines
spacing = 36,
-- foot height
foot_H = 28,
-- horisontal margin
margin_H = 10,
-- state buffer
history_files = {},
files = {},
result = {},
items = 0,
page = 0,
current = 1,
oldcurrent = 1,
}
function FileHistory:init(history_path)
if history_path then
self:setPath(history_path)
else
self:setPath("./history")
end
self:addAllCommands()
end
function FileHistory:setPath(newPath)
self.path = newPath
self:readDir("-c ")
self.items = #self.files
if self.items == 0 then
return nil
end
self.page = 1
self.current = 1
return true
end
function FileHistory:readDir(order_criteria)
self.history_files = {}
self.files = {}
local listfile = self.path.."/.history.txt"
os.execute("ls "..order_criteria.."-1 "..self.path.." > "..listfile)
for f in io.lines(listfile) do
-- insert history files
file_entry = {dir=self.path, name=f}
table.insert(self.history_files, file_entry)
-- and corresponding path & file items
file_entry = {dir=HistoryToPath(f), name=HistoryToName(f)}
table.insert(self.files, file_entry)
end
end
function FileHistory:setSearchResult(keywords)
self.result = {}
if keywords == "" or keywords == " " then
-- show all history
self.result = self.files
else
-- select history files with keywords in the filename
for __,f in pairs(self.files) do
if string.find(string.lower(f.name), keywords) then
table.insert(self.result,f)
end
end
end
self.keywords = keywords
self.items = #self.result
self.page = 1
self.current = 1
end
function FileHistory:prevItem()
if self.current == 1 then
if self.page > 1 then
self.current = self.perpage
self.page = self.page - 1
self.pagedirty = true
end
else
self.current = self.current - 1
self.markerdirty = true
end
end
function FileHistory:nextItem()
if self.current == self.perpage then
if self.page < (self.items / self.perpage) then
self.current = 1
self.page = self.page + 1
self.pagedirty = true
end
else
if self.page ~= math.floor(self.items / self.perpage) + 1
or self.current + (self.page-1)*self.perpage < self.items then
self.current = self.current + 1
self.markerdirty = true
end
end
end
function FileHistory:addAllCommands()
self.commands = Commands:new{}
-- search among last documents
self.commands:add(KEY_S, nil, "S",
"search among files",
function(self)
old_keywords = self.keywords
self.keywords = InputBox:input(G_height - 100, 100,
"Search:", old_keywords)
if self.keywords then
self:setSearchResult(self.keywords)
else
self.keywords = old_keywords
end
self.pagedirty = true
end
)
-- last documents
self.commands:add(KEY_L, nil, "L",
"last documents",
function(self)
self:setSearchResult("")
self.pagedirty = true
end
)
-- show help page
self.commands:add(KEY_H, nil, "H",
"show help page",
function(self)
HelpPage:show(0, G_height, self.commands)
self.pagedirty = true
end
)
-- make screenshot
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
Screen:screenshot()
end
)
-- file info
self.commands:add({KEY_FW_RIGHT, KEY_I}, nil, "joypad right",
"document details",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
FileInfo:show(file_entry.dir,file_entry.name)
self.pagedirty = true
end
)
self.commands:add(KEY_FW_UP, nil, "joypad up",
"goto previous item",
function(self)
self:prevItem()
end
)
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
"goto next item",
function(self)
self:nextItem()
end
)
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
"next page",
function(self)
if self.page < (self.items / self.perpage) then
if self.current + self.page*self.perpage > self.items then
self.current = self.items - self.page*self.perpage
end
self.page = self.page + 1
self.pagedirty = true
else
self.current = self.items - (self.page-1)*self.perpage
self.markerdirty = true
end
end
)
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "<",
"previous page",
function(self)
if self.page > 1 then
self.page = self.page - 1
self.pagedirty = true
else
self.current = 1
self.markerdirty = true
end
end
)
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"font menu",
function(self)
-- NuPogodi, 18.05.12: define the number of the current font in face_list
local item_no = 0
local face_list = Font:getFontList()
while face_list[item_no] ~= Font.fontmap.cfont and item_no < #face_list do
item_no = item_no + 1
end
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = face_list,
-- NuPogodi, 18.05.12: define selected item
current_entry = item_no - 1,
}
local re, font = fonts_menu:choose(0, G_height)
if re then
Font.fontmap["cfont"] = font
Font:update()
end
self.pagedirty = true
end
)
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
"open selected item",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
file_full_path = file_entry.dir .. "/" .. file_entry.name
openFile(file_full_path)
--reset height and item index if screen has been rotated
local item_no = self.perpage * (self.page - 1) + self.current
self.perpage = math.floor(G_height / self.spacing) - 2
self.current = item_no % self.perpage
self.page = math.floor(item_no / self.perpage) + 1
self.pagedirty = true
end
)
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back",
"back",
function(self)
return "break"
end
)
self.commands:add({KEY_DEL}, nil, "Del",
"delete document",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
local file_to_del = file_entry.dir .. "/" .. file_entry.name
InfoMessage:show("Press \'Y\' to confirm deleting... ",0)
while true do
ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
if ev.code == KEY_Y then
-- delete the file itself
os.execute("rm \""..file_to_del.."\"")
-- and its history file, if any
os.execute("rm \""..DocToHistory(file_to_del).."\"")
-- to avoid showing just deleted file
self:init()
self:setSearchResult(self.keywords)
end
self.pagedirty = true
break
end -- if ev.type == EV_KEY
end -- while
end
)
self.commands:add({KEY_SPACE}, nil, "Space",
"refresh page manually",
function(self)
self.pagedirty = true
end
)
--[[ self.commands:add({KEY_B}, nil, "B",
"file browser",
function(self)
--FileChooser:setPath(".")
FileChooser:choose(0, G_height)
self.pagedirty = true
end
)]]
end
function FileHistory:choose(keywords)
self.perpage = math.floor(G_height / self.spacing) - 2
self.pagedirty = true
self.markerdirty = false
self:setSearchResult(keywords)
while true do
local cface = Font:getFace("cfont", 22)
local tface = Font:getFace("tfont", 25)
local fface = Font:getFace("ffont", 16)
if self.pagedirty then
self.markerdirty = true
fb.bb:paintRect(0, 0, G_width, G_height, 0)
-- draw header
local header = "Last Documents"
if self.keywords ~= "" and self.keywords ~= " " then
--header = header .. " (filter: \'" .. string.upper(self.keywords) .. "\')"
header = "Search Results for \'"..string.upper(self.keywords).."\'"
end
DrawTitle(header,self.margin_H,0,self.title_H,4,tface)
-- draw found results
local c
if self.items == 0 then -- nothing found
y = self.title_H + self.spacing * 2
renderUtf8Text(fb.bb, self.margin_H, y, cface,
"Sorry, no files found.", true)
self.markerdirty = false
else -- found something, draw it
for c = 1, self.perpage do
local i = (self.page - 1) * self.perpage + c
if i <= self.items then
y = self.title_H + (self.spacing * c) + 4
local ftype = string.lower(string.match(self.result[i].name, ".+%.([^.]+)") or "")
DrawFileItem(self.result[i].name,self.margin_H,y,ftype)
end
end
end
-- draw footer
all_page = math.ceil(self.items/self.perpage)
DrawFooter("Page "..self.page.." of "..all_page,fface,self.foot_H)
end
if self.markerdirty then
if not self.pagedirty then
if self.oldcurrent > 0 then
y = self.title_H + (self.spacing * self.oldcurrent) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 0)
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
end
-- draw new marker line
y = self.title_H + (self.spacing * self.current) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 15)
if not self.pagedirty then
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
self.oldcurrent = self.current
self.markerdirty = false
end
if self.pagedirty then
fb:refresh(0)
self.pagedirty = false
end
local ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
keydef = Keydef:new(ev.code, getKeyModifier())
debug("key pressed: "..tostring(keydef))
command = self.commands:getByKeydef(keydef)
if command ~= nil then
debug("command to execute: "..tostring(command))
ret_code = command.func(self, keydef)
else
debug("command not found: "..tostring(command))
end
if ret_code == "break" then
break
end
if self.selected_item ~= nil then
debug("# selected "..self.selected_item)
return self.selected_item
end
end -- if
end -- while true
return nil
end

@ -0,0 +1,301 @@
require "rendertext"
require "keys"
require "graphics"
require "font"
require "inputbox"
require "dialog"
require "settings"
--require "extentions"
FileInfo = {
-- title height
title_H = 40,
-- spacing between lines
spacing = 36,
-- foot height
foot_H = 28,
-- horisontal margin
margin_H = 10,
-- state buffer
result = {},
files = {},
lcolumn_width = 0,
items = 0,
page = 1,
current = 1,
pathfile = "",
}
function FileInfo:FileCreated(fname,attr)
return os.date("%d %b %Y, %H:%M:%S", lfs.attributes(fname,attr))
end
function FileInfo:FileSize(fname)
local size = lfs.attributes(fname,"size")
if size < 1024 then
return size.." Bytes"
elseif size < 1048576 then
return string.format("%.2f", size/1024).."KB \("..size.." Bytes\)"
else
return string.format("%.2f", size/1048576).."MB \("..size.." Bytes\)"
end
end
function FileInfo:init(path,fname)
self.pathfile = path.."/"..fname
self.result = {}
self:addAllCommands()
local info_entry = {dir = "Name", name = fname}
table.insert(self.result, info_entry)
info_entry = {dir = "Path", name = path}
table.insert(self.result, info_entry)
info_entry = {dir = "Size", name = FileInfo:FileSize(self.pathfile)}
table.insert(self.result, info_entry)
-- empty line
--info_entry = {dir = " ", name = " "}
--table.insert(self.result, info_entry)
info_entry = {dir = "Created", name = FileInfo:FileCreated(self.pathfile,"change")}
table.insert(self.result, info_entry)
info_entry = {dir = "Modified", name = FileInfo:FileCreated(self.pathfile,"modification")}
table.insert(self.result, info_entry)
-- if the document was already opened
local history = DocToHistory(self.pathfile)
local file, msg = io.open(history,"r")
if not file then
info_entry = {dir = "Last Read", name = "Never"}
table.insert(self.result, info_entry)
else
info_entry = {dir = "Last Read", name = FileInfo:FileCreated(history,"change")}
table.insert(self.result, info_entry)
local file_type = string.lower(string.match(self.pathfile, ".+%.([^.]+)"))
local to_search, add, factor = "\[\"last_percent\"\]", "\%", 100
if ext:getReader(file_type) ~= CREReader then
to_search = "\[\"last_page\"\]"
add = " pages"
factor = 1
end
for line in io.lines(history) do
if string.match(line,"%b[]") == to_search then
local cdc = tonumber(string.match(line, "%d+")) / factor
info_entry = {dir = "Completed", name = string.format("%d",cdc)..add }
table.insert(self.result, info_entry)
end
end
end
self.items = #self.result
-- now calculating the horizontal space for left column
local tw, width
for i = 1, self.items do
tw = TextWidget:new({text = self.result[i].dir, face = Font:getFace("tfont", 22)})
width = tw:getSize().w
if width > self.lcolumn_width then self.lcolumn_width = width end
tw:free()
end
end
function FileInfo:show(path,name)
-- at first, one has to test whether the file still exists or not
-- it's necessary for last documents
if not io.open(path.."/"..name,"r") then return nil end
-- then goto main functions
self.perpage = math.floor(G_height / self.spacing) - 2
self.pagedirty = true
self.markerdirty = false
FileInfo:init(path,name)
while true do
local cface = Font:getFace("cfont", 22)
local lface = Font:getFace("tfont", 22)
local tface = Font:getFace("tfont", 25)
local fface = Font:getFace("ffont", 16)
if self.pagedirty then
self.markerdirty = true
-- gap between title rectangle left & left text drawing point
local xgap = 10
fb.bb:paintRect(0, 0, G_width, G_height, 0)
-- draw menu title
DrawTitle("Document Information",self.margin_H,0,self.title_H,3,tface)
local c
-- position of left column
local x1 = self.margin_H + xgap
-- position of right column + its width + a small gap between columns
local x2 = x1 + self.lcolumn_width + 15
-- y-position correction because of the multiline drawing
local dy = 5
for c = 1, self.perpage do
local i = (self.page - 1) * self.perpage + c
if i <= self.items then
y = self.title_H + self.spacing * c + dy
renderUtf8Text(fb.bb, x1, y, lface, self.result[i].dir, true)
-- set interline spacing = 1.65 of the char height
-- or directly in pixels (if it exceeds 5)
dy = dy + renderUtf8Multiline(fb.bb, x2, y, cface, self.result[i].name, true,
G_width - self.margin_H - x2 - xgap, 1.65).y - y
end
end
-- draw footer
all_page = math.ceil(self.items/self.perpage)
DrawFooter("Page "..self.page.." of "..all_page,fface,self.foot_H)
end
--[[ -- may be used in future for selecting some of displayed items
if self.markerdirty then
if not self.pagedirty then
if self.oldcurrent > 0 then
y = self.title_H + (self.spacing * self.oldcurrent) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 15)
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
end
-- draw new marker line
y = self.title_H + (self.spacing * self.current) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 15)
if not self.pagedirty then
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
self.oldcurrent = self.current
self.markerdirty = false
end ]]
if self.pagedirty then
fb:refresh(0)
self.pagedirty = false
end
local ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
keydef = Keydef:new(ev.code, getKeyModifier())
debug("key pressed: "..tostring(keydef))
command = self.commands:getByKeydef(keydef)
if command ~= nil then
debug("command to execute: "..tostring(command))
ret_code = command.func(self, keydef)
else
debug("command not found: "..tostring(command))
end
if ret_code == "break" then break end
if self.selected_item ~= nil then
debug("# selected "..self.selected_item)
return self.selected_item
end
end -- if
end -- while true
return nil
end
function FileInfo:addAllCommands()
self.commands = Commands:new{}
-- show help page
self.commands:add(KEY_H,nil,"H",
"show help page",
function(self)
HelpPage:show(0, G_height, self.commands)
self.pagedirty = true
end
)
-- make screenshot
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
Screen:screenshot()
end
)
-- recent documents
self.commands:add(KEY_L, nil, "L",
"last documents",
function(self)
FileHistory:init()
FileHistory:choose("")
self.pagedirty = true
end
)
-- fonts
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"font menu",
function(self)
-- NuPogodi, 18.05.12: define the number of the current font in face_list
local item_no = 0
local face_list = Font:getFontList()
while face_list[item_no] ~= Font.fontmap.cfont and item_no < #face_list do
item_no = item_no + 1
end
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = face_list,
-- NuPogodi, 18.05.12: define selected item
current_entry = item_no - 1,
}
local re, font = fonts_menu:choose(0, G_height)
if re then
Font.fontmap["cfont"] = font
Font:update()
end
self.pagedirty = true
end
)
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
"next page",
function(self)
if self.page < (self.items / self.perpage) then
if self.current + self.page*self.perpage > self.items then
self.current = self.items - self.page*self.perpage
end
self.page = self.page + 1
self.pagedirty = true
else
self.current = self.items - (self.page-1)*self.perpage
self.markerdirty = true
end
end
)
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "<",
"previous page",
function(self)
if self.page > 1 then
self.page = self.page - 1
self.pagedirty = true
else
self.current = 1
self.markerdirty = true
end
end
)
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
"open document",
function(self)
openFile(self.pathfile)
self.pagedirty = true
end
)
self.commands:add({KEY_BACK, KEY_HOME, KEY_FW_LEFT}, nil, "Back",
"back",
function(self)
return "break"
end
)
self.commands:add({KEY_SPACE}, nil, "Space",
"refresh page manually",
function(self)
self.pagedirty = true
end
)
--[[ self.commands:add({KEY_B}, nil, "B",
"file browser",
function(self)
--FileChooser:setPath(".")
FileChooser:choose(0, G_height)
self.pagedirty = true
end
)]]
end

@ -2,14 +2,19 @@ require "rendertext"
require "keys"
require "graphics"
require "font"
require "inputbox"
require "dialog"
require "extentions"
FileSearcher = {
-- title height
title_H = 45,
title_H = 40,
-- spacing between lines
spacing = 40,
spacing = 36,
-- foot height
foot_H = 27,
foot_H = 28,
-- horisontal margin
margin_H = 10,
-- state buffer
dirs = {},
@ -31,16 +36,9 @@ function FileSearcher:readDir()
-- handle files in d
for f in lfs.dir(d) do
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
if lfs.attributes(d.."/"..f, "mode") == "directory"
and f ~= "." and f~= ".." and not string.match(f, "^%.[^.]") then
if lfs.attributes(d.."/"..f, "mode") == "directory" and f ~= "." and f~= ".." then
table.insert(new_dirs, d.."/"..f)
elseif file_type == "djvu" or file_type == "pdf"
or file_type == "xps" or file_type == "cbz"
or file_type == "epub" or file_type == "txt"
or file_type == "rtf" or file_type == "htm"
or file_type == "html" or file_type == "mobi" or file_type == "prc"
or file_type == "fb2" or file_type == "chm"
or file_type == "doc" or file_type == "zip" then
elseif ext:getReader(file_type) then
file_entry = {dir=d, name=f,}
table.insert(self.files, file_entry)
--debug("file:"..d.."/"..f)
@ -121,7 +119,41 @@ end
function FileSearcher:addAllCommands()
self.commands = Commands:new{}
-- last documents
self.commands:add(KEY_L, nil, "L",
"last documents",
function(self)
FileHistory:init()
FileHistory:choose("")
self.pagedirty = true
end
)
-- show help page
self.commands:add(KEY_H, nil, "H",
"show help page",
function(self)
HelpPage:show(0, G_height, self.commands)
self.pagedirty = true
end
)
-- make screenshot
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
Screen:screenshot()
end
)
-- file info
self.commands:add({KEY_FW_RIGHT, KEY_I}, nil, "joypad right",
"document details",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
FileInfo:show(file_entry.dir,file_entry.name)
self.pagedirty = true
end
)
self.commands:add(KEY_FW_UP, nil, "joypad up",
"goto previous item",
function(self)
@ -175,12 +207,21 @@ function FileSearcher:addAllCommands()
self.pagedirty = true
end
)
self.commands:add(KEY_F, nil, "F",
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"font menu",
function(self)
local fonts_menu = SelectMenu:new{
-- NuPogodi, 18.05.12: define the number of the current font in face_list
local item_no = 0
local face_list = Font:getFontList()
while face_list[item_no] ~= Font.fontmap.cfont and item_no < #face_list do
item_no = item_no + 1
end
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = Font:getFontList(),
item_array = face_list,
-- NuPogodi, 18.05.12: define selected item
current_entry = item_no - 1,
}
local re, font = fonts_menu:choose(0, G_height)
if re then
@ -190,8 +231,8 @@ function FileSearcher:addAllCommands()
self.pagedirty = true
end
)
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "",
"select item",
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
"open selected item",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
file_full_path = file_entry.dir .. "/" .. file_entry.name
@ -206,12 +247,50 @@ function FileSearcher:addAllCommands()
self.pagedirty = true
end
)
self.commands:add({KEY_BACK, KEY_HOME}, nil, "",
"back to file browser",
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back",
"back",
function(self)
return "break"
end
)
self.commands:add({KEY_DEL}, nil, "Del",
"delete document",
function(self)
file_entry = self.result[self.perpage*(self.page-1)+self.current]
local file_to_del = file_entry.dir .. "/" .. file_entry.name
InfoMessage:show("Press \'Y\' to confirm deleting... ",0)
while true do
ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
if ev.code == KEY_Y then
-- delete the file itself
os.execute("rm \""..file_to_del.."\"")
-- and its history file, if any
os.execute("rm \""..DocToHistory(file_to_del).."\"")
-- to avoid showing just deleted file
self:init( self.path )
self:choose(self.keywords)
end
self.pagedirty = true
break
end -- if ev.type == EV_KEY
end -- while
end
) self.commands:add({KEY_SPACE}, nil, "Space",
"refresh page manually",
function(self)
self.pagedirty = true
end
)
--[[ self.commands:add({KEY_B}, nil, "B",
"file browser",
function(self)
--FileChooser:setPath(".")
FileChooser:choose(0, G_height)
self.pagedirty = true
end
)]]
end
function FileSearcher:choose(keywords)
@ -236,50 +315,47 @@ function FileSearcher:choose(keywords)
fb.bb:paintRect(0, 0, G_width, G_height, 0)
-- draw menu title
renderUtf8Text(fb.bb, 30, 0 + self.title_H, tface,
"Search Result for: "..self.keywords, true)
DrawTitle("Search Results for \'"..string.upper(self.keywords).."\'",self.margin_H,0,self.title_H,4,tface)
-- draw results
local c
if self.items == 0 then -- nothing found
y = self.title_H + self.spacing * 2
renderUtf8Text(fb.bb, 20, y, cface,
renderUtf8Text(fb.bb, self.margin_H, y, cface,
"Sorry, no match found.", true)
renderUtf8Text(fb.bb, 20, y + self.spacing, cface,
renderUtf8Text(fb.bb, self.margin_H, y + self.spacing, cface,
"Please try a different keyword.", true)
self.markerdirty = false
else -- found something, draw it
for c = 1, self.perpage do
local i = (self.page - 1) * self.perpage + c
if i <= self.items then
y = self.title_H + (self.spacing * c)
renderUtf8Text(fb.bb, 50, y, cface,
self.result[i].name, true)
y = self.title_H + (self.spacing * c) + 4
local ftype = string.lower(string.match(self.result[i].name, ".+%.([^.]+)") or "")
DrawFileItem(self.result[i].name,self.margin_H,y,ftype)
end
end
end
-- draw footer
y = self.title_H + (self.spacing * self.perpage) + self.foot_H
x = (G_width / 2) - 50
all_page = math.ceil(self.items/self.perpage)
renderUtf8Text(fb.bb, x, y, fface,
"Page "..self.page.." of "..all_page, true)
DrawFooter("Page "..self.page.." of "..all_page,fface,self.foot_H)
end
if self.markerdirty then
if not self.pagedirty then
if self.oldcurrent > 0 then
y = self.title_H + (self.spacing * self.oldcurrent) + 10
fb.bb:paintRect(30, y, G_width - 60, 3, 0)
fb:refresh(1, 30, y, G_width - 60, 3)
y = self.title_H + (self.spacing * self.oldcurrent) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 0)
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
end
-- draw new marker line
y = self.title_H + (self.spacing * self.current) + 10
fb.bb:paintRect(30, y, G_width - 60, 3, 15)
y = self.title_H + (self.spacing * self.current) + 12
fb.bb:paintRect(self.margin_H, y, G_width - 2 * self.margin_H, 3, 15)
if not self.pagedirty then
fb:refresh(1, 30, y, G_width - 60, 3)
fb:refresh(1, self.margin_H, y, G_width - 2 * self.margin_H, 3)
end
self.oldcurrent = self.current
self.markerdirty = false

@ -4,7 +4,7 @@ Font = {
-- default font for menu contents
cfont = "droid/DroidSans.ttf",
-- default font for title
tfont = "NimbusSanL-BoldItal.cff",
tfont = "droid/DroidSansBold.ttf",
-- default font for footer
ffont = "droid/DroidSans.ttf",

@ -9,6 +9,14 @@ require "commands"
HelpPage = {
-- Other Class vars:
-- title height
title_H = 40,
-- horisontal margin
margin_H = 10,
-- foot height
foot_H = 28,
-- background color
bg_color = 4,
-- spacing between lines
spacing = 25,
@ -58,17 +66,20 @@ function HelpPage:show(ypos, height, commands)
fface_height = math.ceil(fface_height)
fface_ascender = math.ceil(fface_ascender)
local spacing = face_height + 5
local vert_S = self.title_H + 12
local perpage = math.floor( (height - ypos - 1 * (fface_height + 5)) / spacing )
local perpage = math.floor( (height - ypos - 1 * (fface_height + 5) - vert_S) / spacing )
local is_pagedirty = true
while true do
if is_pagedirty then
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
-- draw header
DrawTitle("Active Hotkeys",self.margin_H,0,self.title_H,self.bg_color,Font:getFace("tfont", 25))
local c
local max_x = 0
for c = 1, perpage do
local x = 5
local x = self.margin_H
local i = (self.page - 1) * perpage + c
if i <= self.items then
local key = self.commands[i].shortcut
@ -78,16 +89,16 @@ function HelpPage:show(ypos, height, commands)
if(modStart ~= nil) then
key = key:sub(1,modStart-1)..key:sub(modEnd+1)
local box = sizeUtf8Text( x, fb.bb:getWidth(), self.face, aMod.d, true)
fb.bb:paintRect(x, ypos + spacing*c - box.y_top, box.x, box.y_top + box.y_bottom, 4)
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c, self.face, aMod.d.." + ", true)
fb.bb:paintRect(x, ypos + spacing*c - box.y_top + vert_S, box.x + self.title_H, box.y_top + box.y_bottom, self.bg_color)
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c + vert_S, self.face, aMod.d.." + ", true)
x = x + pen_x
max_x = math.max(max_x, pen_x)
end
end
debug("key:"..key)
local box = sizeUtf8Text( x, fb.bb:getWidth(), self.face, key , true)
fb.bb:paintRect(x, ypos + spacing*c - box.y_top, box.x, box.y_top + box.y_bottom, 4)
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c, self.face, key, true)
fb.bb:paintRect(x, ypos + spacing*c - box.y_top + vert_S, box.x, box.y_top + box.y_bottom, self.bg_color)
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c + vert_S, self.face, key, true)
x = x + pen_x
max_x = math.max(max_x, x)
end
@ -95,11 +106,13 @@ function HelpPage:show(ypos, height, commands)
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
if i <= self.items then
renderUtf8Text(fb.bb, max_x + 20, ypos + spacing*c, self.hface, self.commands[i].help, true)
renderUtf8Text(fb.bb, max_x + 20, ypos + spacing*c + vert_S, self.hface, self.commands[i].help, true)
end
end
renderUtf8Text(fb.bb, 5, height - fface_height + fface_ascender - 5, self.fface,
"Page "..self.page.." of "..math.ceil(self.items / perpage).." - Back to close this page", true)
-- draw footer
local footer = "Page "..self.page.." of "..math.ceil(self.items / perpage).." - Back to close this page"
-- DrawFooter(footer,Font:getFace("ffont", 16),self.foot_H) --
renderUtf8Text(fb.bb, self.margin_H, height-7, self.fface, footer, true)
end
if is_pagedirty then
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)

@ -0,0 +1,74 @@
body { text-align: left; text-indent: 0px }
p { text-align: justify; text-indent: 2em; margin-top:0em; margin-bottom: 0em }
empty-line { height: 1em }
hr { height: 1px; /* background-color: #808080; */ margin-top: 0.5em; margin-bottom: 0.5em }
sub { vertical-align: sub; font-size: 70% }
sup { vertical-align: super; font-size: 70% }
strong, b { font-weight: bold }
emphasis, i { font-style: italic }
a { text-decoration: underline }
a[type="note"] { vertical-align: super; font-size: 70%; text-decoration: none }
image { text-align: center; text-indent: 0px }
p image { display: inline }
title p, subtitle p, h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { text-align: center; text-indent: 0px }
cite p, epigraph p { text-align: left; text-indent: 0px }
v { text-align: left; text-indent: 0px }
stanza + stanza { margin-top: 1em; }
stanza { margin-left: 30%; text-align: left; font-style: italic }
poem { margin-top: 1em; margin-bottom: 1em; text-indent: 0px }
text-author { font-weight: bold; font-style: italic; margin-left: 5%}
epigraph { margin-left: 25%; margin-right: 1em; text-align: left; text-indent:
1px; font-style: italic; margin-top: 15px; margin-bottom: 25px }
cite { font-style: italic; margin-left: 5%; margin-right: 5%; text-align: justify;
margin-top: 20px; margin-bottom: 20px }
title, h1, h2 { text-align: center; text-indent: 0px; font-weight: bold; hyphenate: none;
page-break-before: always; page-break-inside: avoid; page-break-after: avoid; }
subtitle, h3, h4, h5, h6 { text-align: center; text-indent: 0px; font-weight: bold;
hyphenate: none; page-break-inside: avoid; page-break-after: avoid; }
title { font-size: 110%; margin-top: 0.7em; margin-bottom: 0.5em }
subtitle { font-style: italic; margin-top: 0.3em; margin-bottom: 0.3em }
h1 { font-size: 150% }
h2 { font-size: 140% }
h3 { font-size: 130% }
h4 { font-size: 120% }
h5 { font-size: 110% }
table { font-size: 80% }
td, th { text-indent: 0px; padding: 3px }
th { font-weight: bold; /* background-color: #DDD */ }
table > caption { text-indent: 0px; padding: 4px; /* background-color: #EEE */ }
code, pre { display: block; white-space: pre; text-align: left;
font-family: "Droid Sans Mono", monospace; text-align: left }
body[name="notes"] { font-size: 70%; }
body[name="notes"] section title { display: run-in; text-align: left; font-size: 110%;
font-weight: bold; page-break-before: auto; page-break-inside: auto;
page-break-after: auto; }
body[name="notes"] section title p { display: inline }
description { display: block; }
title-info { display: block; }
annotation { margin-left: 5%; margin-right: 5%; font-size: 80%; font-style: italic;
text-align: justify; text-indent: 2em }
date { display: block; font-size: 80%; font-style: italic; text-align: center }
genre { display: none; }
author { display: none; }
book-title { display: none; }
keywords { display: none; }
lang { display: none; }
src-lang { display: none; }
translator { display: none; }
document-info { display: none; }
publish-info { display: none; }
custom-info { display: none; }
coverpage { display: none }

@ -27,6 +27,7 @@ require "screen"
require "keys"
require "commands"
require "dialog"
require "extentions"
-- option parsing:
longopts = {
@ -40,13 +41,8 @@ longopts = {
function openFile(filename)
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
local reader = nil
if file_type == "djvu" then
reader = DJVUReader
elseif file_type == "pdf" or file_type == "xps" or file_type == "cbz" then
reader = PDFReader
elseif file_type == "epub" or file_type == "txt" or file_type == "rtf" or file_type == "htm" or file_type == "html" or file_type == "fb2" or file_type == "chm" or file_type == "mobi" or file_type == "prc" or file_type == "doc" or file_type == "zip" then
reader = CREReader
end
reader = ext:getReader(file_type)
if reader then
InfoMessage:show("Opening document, please wait... ", 0)
reader:preLoadSettings(filename)

@ -30,12 +30,12 @@ function getGlyph(face, charcode)
glyphcache[hash] = {
age = glyphcache_max_age,
size = size,
g = glyph
glyph = glyph
}
else
glyphcache[hash].age = glyphcache_max_age
end
return glyphcache[hash].g
return glyphcache[hash].glyph
end
function glyphCacheHash(face, charcode)
return face..'_'..charcode;
@ -104,3 +104,84 @@ function renderUtf8Text(buffer, x, y, face, text, kerning)
end
return pen_x
end
-- NuPogodi: Some New Functions to render UTF8 text restricted by some width 'w'
function renderUtf8TextWidth(buffer, x, y, face, text, kerning, w)
if text == nil then
debug("renderUtf8Text called without text");
return nil
end
local pen_x = 0
local rest = ""
local prevcharcode = 0
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
if pen_x < w then
local charcode = util.utf8charcode(uchar)
local glyph = getGlyph(face, charcode)
if kerning and prevcharcode then
local kern = face.ftface:getKerning(prevcharcode, charcode)
pen_x = pen_x + kern
--debug("prev:"..string.char(prevcharcode).." curr:"..string.char(charcode).." pen_x:"..pen_x.." kern:"..kern)
buffer:addblitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
else
--debug(" curr:"..string.char(charcode))
buffer:blitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
end
pen_x = pen_x + glyph.ax
prevcharcode = charcode
else
-- accumulating the rest of text here
rest = rest .. uchar
end
end
return { leaved = rest, x = pen_x, y = y }
end
function SplitString(text)
local words = {}
local word = ""
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
if uchar == "/" or uchar == " " or uchar == "-" or uchar == "_" or uchar == "\." then
words[#words+1] = word .. uchar
word = ""
else
word = word .. uchar
end
end
-- add the rest of string as the last word
words[#words+1] = word
return words
end
function renderUtf8Multiline(buffer, x, y, face, text, kerning, w, line_spacing)
-- at first, split a text on separate words
local words = SplitString(text)
-- test whether it is inside of reasonable values 1.0 < line_spacing < 5.0 or given in pixels (>5)
-- default value is 1.75 ; getGlyph(face, 48).t = height of char '0'
if line_spacing<1 then line_spacing=math.ceil(getGlyph(face, 48).t) -- single = minimum
elseif line_spacing < 5 then line_spacing=math.ceil(getGlyph(face, 48).t * line_spacing)
-- if line_spacing>5 then it seems to be defined in pixels
elseif line_spacing>=5 then line_spacing=line_spacing
-- and, finally, default value
else line_spacing = math.ceil(getGlyph(face, 48).t * 1.75)
end
local lx = x
for i = 1, #words do
if sizeUtf8Text(lx, buffer:getWidth(), face, words[i], kerning).x < (w - lx + x) then
lx = lx + renderUtf8TextWidth(buffer, lx, y, face, words[i], kerning, w - lx + x).x
else
-- set lx to the line start
lx = x
-- add the y-distance between lines
y = y + line_spacing
-- and draw next word
lx = lx + renderUtf8TextWidth(buffer, lx, y, face, words[i], kerning, w - lx + x).x
end -- if
end --for
return { x = x, y = y }
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

@ -106,3 +106,12 @@ function Screen:restoreFromBB(bb)
debug("Got nil bb in restoreFromSavedBB!")
end
end
function Screen:screenshot()
--@TODO convert bitmap to png or jpeg 30.04 2012 (houqp)
os.execute("mkdir ".."/mnt/us/kindlepdfviewer/screenshots")
local d = os.date("%Y%m%d%H%M%S")
os.execute("dd if=/dev/fb0 of=/mnt/us/kindlepdfviewer/screenshots/" .. d .. ".raw")
showInfoMsgWithDelay("screenshot "..d.." created", 1000, 1)
end

@ -20,6 +20,10 @@ SelectMenu = {
spacing = 36,
-- foot height
foot_H = 27,
-- horisontal margin
margin_H = 10,
-- NuPogodi, 18.05.12: new parameter
current_entry = 0,
menu_title = "No Title",
no_item_msg = "No items found.",
@ -225,30 +229,41 @@ function SelectMenu:choose(ypos, height)
self.pagedirty = true
self.markerdirty = false
self.last_shortcut = 0
-- NuPogodi, 18.02.12: let us define the starting position
-- If it was, certainly, send before by SelectMenu:new() via current_entry
self.current_entry = math.min(self.current_entry,self.items)
-- self.current_entry = math.max(self.current_entry,1)
-- now calculating the page & cursor
self.page = math.floor(self.current_entry / self.perpage) + 1
self.page = math.max(1, self.page)
self.current = self.current_entry - (self.page - 1) * self.perpage + 1
self.current = math.max(1, self.current)
-- end of changes (NuPogodi)
while true do
local cface = Font:getFace("cfont", 22)
local tface = Font:getFace("tfont", 25)
local fface = Font:getFace("ffont", 16)
local lx = self.margin_H + 40
local fw = fb.bb:getWidth() - lx - self.margin_H
if self.pagedirty then
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
self.markerdirty = true
-- draw menu title
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), self.title_H + 10, 0)
fb.bb:paintRect(10, ypos + 10, fb.bb:getWidth() - 20, self.title_H, 5)
local x = 20
local y = ypos + self.title_H
renderUtf8Text(fb.bb, x, y, tface, self.menu_title, true)
-- draw menu title (new version with clock & battery)
DrawTitle(self.menu_title,self.margin_H,0,self.title_H,4,tface)
-- draw items
fb.bb:paintRect(0, ypos + self.title_H + 10, fb.bb:getWidth(), height - self.title_H, 0)
fb.bb:paintRect(0, ypos + self.title_H + self.margin_H, fb.bb:getWidth(), height - self.title_H, 0)
if self.items == 0 then
y = ypos + self.title_H + (self.spacing * 2)
renderUtf8Text(fb.bb, 30, y, cface,
renderUtf8Text(fb.bb, self.margin_H + 20, y, cface,
"Oops... Bad news for you:", true)
y = y + self.spacing
renderUtf8Text(fb.bb, 30, y, cface,
renderUtf8Text(fb.bb, self.margin_H + 20, y, cface,
self.no_item_msg, true)
self.markerdirty = false
self:clearCommands()
@ -257,54 +272,63 @@ function SelectMenu:choose(ypos, height)
for c = 1, self.perpage do
local i = (self.page - 1) * self.perpage + c
if i <= self.items then
y = ypos + self.title_H + (self.spacing * c)
y = ypos + self.title_H + (self.spacing * c) + 4
-- paint shortcut indications
if c <= 10 or c > 20 then
blitbuffer.paintBorder(fb.bb, 10, y-22, 29, 29, 2, 15)
blitbuffer.paintBorder(fb.bb, self.margin_H, y-22, 29, 29, 2, 15)
else
fb.bb:paintRect(10, y-22, 29, 29, 3)
fb.bb:paintRect(self.margin_H, y-22, 29, 29, 3)
end
if self.item_shortcuts[c] ~= nil and
string.len(self.item_shortcuts[c]) == 3 then
-- debug "Del", "Sym and "Ent"
renderUtf8Text(fb.bb, 13, y, fface,
renderUtf8Text(fb.bb, self.margin_H + 3, y, fface,
self.item_shortcuts[c], true)
else
renderUtf8Text(fb.bb, 18, y, self.sface,
renderUtf8Text(fb.bb, self.margin_H + 8, y, self.sface,
self.item_shortcuts[c], true)
end
self.last_shortcut = c
renderUtf8Text(fb.bb, 50, y, cface,
self.item_array[i], true)
-- NuPogodi, 15.05.12: paint items by own glyphs if the menu title == 'Fonts Menu',
-- but not "Fonts Menu " (crereader.lua); the problem is crereader creates own list
-- with the font families, rather then filenames of available fonts
local own_face = cface
if self.menu_title == "Fonts Menu" then
own_face = Font:getFace(self.item_array[i], 22)
end
-- NuPogodi, 18.05.12: rendering menu items ( fixed too long strings)
if sizeUtf8Text(lx,fb.bb:getWidth(),own_face,self.item_array[i],true).x < (fw - 10) then
renderUtf8Text(fb.bb,lx,y,own_face,self.item_array[i],true)
else
local gapx = sizeUtf8Text(0,fb.bb:getWidth(),own_face,"...", true).x
gapx = lx + renderUtf8TextWidth(fb.bb,lx,y,own_face,self.item_array[i],true,fw-gapx-15).x
renderUtf8Text(fb.bb,gapx,y,own_face,"...",true)
end
-- end of changes (NuPogodi)
end -- if i <= self.items
end -- for c=1, self.perpage
end -- if self.items == 0
-- draw footer
y = ypos + self.title_H + (self.spacing * self.perpage)
+ self.foot_H + 5
x = (fb.bb:getWidth() / 2) - 50
renderUtf8Text(fb.bb, x, y, fface,
"Page "..self.page.." of "..
(math.ceil(self.items / self.perpage)), true)
DrawFooter("Page "..self.page.." of "..(math.ceil(self.items / self.perpage)),fface,self.foot_H)
end
if self.markerdirty then
if not self.pagedirty then
if self.oldcurrent > 0 then
y = ypos + self.title_H + (self.spacing * self.oldcurrent) + 8
fb.bb:paintRect(45, y, fb.bb:getWidth() - 60, 3, 0)
fb:refresh(1, 45, y, fb.bb:getWidth() - 60, 3)
y = ypos + self.title_H + (self.spacing * self.oldcurrent) + 12
fb.bb:paintRect( lx, y, fw, 3, 0)
fb:refresh(1, lx, y, fw, 3)
end
end
-- draw new marker line
y = ypos + self.title_H + (self.spacing * self.current) + 8
fb.bb:paintRect(45, y, fb.bb:getWidth() - 60, 3, 15)
y = ypos + self.title_H + (self.spacing * self.current) + 12
fb.bb:paintRect(lx, y, fw, 3, 15)
if not self.pagedirty then
fb:refresh(1, 45, y, fb.bb:getWidth() - 60, 3)
fb:refresh(1, lx, y, fw, 3)
end
self.oldcurrent = self.current
self.markerdirty = false

@ -1,9 +1,63 @@
DocSettings = {}
DocSettings = {
}
function DocToHistory(fullname)
local i,j = 1,0
while i ~= nil do
i = string.find(fullname,"/",i+1)
if i==nil then break end
j = i
end
local f = string.sub(fullname,j+1,-1)
if j>0 then return "./history/\["..string.gsub(string.sub(fullname,1,j),"/","#").."\] "..f..".lua"
else return "./settings"..f..".lua" end
end
function HistoryToName(history)
-- at first, search for path length
local s = string.len(string.match(history,"%b[]"))
-- and return the rest of string without 4 last characters (".lua")
return string.sub(history, s+2, -5)
end
function HistoryToPath(history)
-- 1. select everything included in brackets
local s = string.match(history,"%b[]")
-- 2. crop the bracket-sign from both sides
-- 3. and finally replace decorative signs '#' to dir-char '/'
return string.gsub(string.sub(s,2,-3),"#","/")
end
function DocSettings:open(docfile)
local new = { file = docfile..".kpdfview.lua", data = {} }
-- history feature moves configuration files into history directory
lfs.mkdir("./history")
local new = { file = DocToHistory(docfile), data = {} }
local ok, stored = pcall(dofile,new.file)
if not ok then
ok, stored = pcall(dofile,docfile..".kpdfview.lua")
end
if ok then
if stored.version == nil then
stored.version = 0
end
if stored.version < 2012.05 then
debug("settings", docfile, stored)
if stored.jumpstack ~= nil then
stored.jump_history = stored.jumpstack
stored.jumpstack = nil
if not stored.jump_history.cur then
stored.jump_history.cur = 1
end
end
if stored.globalzoommode ~= nil then
stored.globalzoom_mode = stored.globalzoommode
stored.globalzoommode = nil
end
stored.version = 2012.05
debug("upgraded", stored)
end
new.data = stored
end
return setmetatable(new, { __index = DocSettings})

@ -2422,12 +2422,7 @@ function UniReader:addAllCommands()
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(unireader)
--@TODO convert bitmap to png or jpeg 30.04 2012 (houqp)
os.execute("mkdir ".."/mnt/us/kindlepdfviewer/screenshots")
local d = os.date("%Y%m%d%H%M%S")
InfoMessage:show("making screenshot...", 1)
os.execute("dd ".."if=/dev/fb0 ".."of=/mnt/us/kindlepdfviewer/screenshots/" .. d .. ".raw")
unireader:redrawCurrentPage()
Screen:screenshot()
end
)
-- commands.map is very large, impacts startup performance on device

Loading…
Cancel
Save