Compare commits

...

49 Commits

Author SHA1 Message Date
HW 202b6fc039 Merge pull request #178 from dpavlin/master
NuPogodi code drop from 2012-05-27
12 years ago
HW 497e1d89de added shortcuts for Kite
as per suggestion from NuPogodi:
http://www.mobileread.com/forums/showpost.php?p=2090800&postcount=465
12 years ago
HW ab400b97ac faster refresh path for the cursor 12 years ago
Dobrica Pavlinusic ae9be768ab use lfs.currentdir to specify clipboard directory
This will make clipboard usable on emulator
12 years ago
NuPogodi 944a3b5b05 NuPogodi code drop from 2012-05-27
- zip files don't require double extensions any more
- filechooser has 'H' shortcut to display keys
- new function for files and folders (^ == shift)
	^N - new folder
	Del - delete document/folder
	^C - copy file into clipboard
	^X - cut (move) file to clipboard
	^V - paste files from clipboard
	^R - rename file
- configurable keyboard for input box
12 years ago
{Qingping,Dave} Hou 78efdc77e3 Merge pull request #174 from dpavlin/NuPogodi_push
NuPogodi filechooser changes
12 years ago
NuPogodi 1831004da5 Add the new function ZipContentExt(zipfilename) which reads the content of zipfile and returns the extention of the first entry. 12 years ago
NuPogodi cccdf42892 use new input handling to enable help page 12 years ago
Dobrica Pavlinušić b1486ee4bd Merge pull request #173 from houqp/master
fix for djvu getPageText API changes
12 years ago
Qingping Hou d2d8ad84ed handle djvu getPageText API changes. 12 years ago
{Qingping,Dave} Hou 763b97744b Merge pull request #170 from dpavlin/NuPogodi
NuPogodi patch 19.05.2012
12 years ago
Dobrica Pavlinusic f55654f03e implement settings version #120 and migration #134
Latest changes for history support move configuration files into
history directory to keep them as timestamp for last read. This code
also adds reading of old configuration files (but does not remove them)
12 years ago
Dobrica Pavlinusic 9de055eb5d fix glymp caching name
With recent changes in font selector, we where hitting
glyphcache_max_memsize so glyphcache[k].glyph.bb:free() got
invoked and crashed reader.
12 years ago
Dobrica Pavlinusic d678510d9a return to file list with fiveway left
It's nice and symetrical to show info (fiveway right) so you don't have
to move hands from fiveway while having long names lookup
12 years ago
Dobrica Pavlinusic a08c35a52c added Screen:screenshot() 12 years ago
NuPogodi 86513c3793 added cr3.css for files without one 12 years ago
NuPogodi 3a76ec91fd integrate rest of @NuPogodi changes #166
- long lines (filenames in 'Document Info') are now splitted in more
  human-readable way (by spaces, dots, slashes or some other characters
- see screenshot)
- the selection of fonts in filemanager (key 'F' or 'Aa') looks now more
  user-friendly
- fixed too long strings in most menues (TOC, Bookmarks, Fonts...) and
  in the popup with the reading progress (called by key 'Menu')
- the position inside the cr-documents (epub, mobi...) now remain nearly
  the same after rescaling the document (i.e. changing the font face,
  size, boldface and interline distance)
- when you open TOC-menu or Fonts Menu, it highlights the current item
  (i.e. current chapter and current fontface).
- i've a bit changed the way to read the battery level values, it might
  now work even without Amazon Kindle framework.
12 years ago
NuPogodi f595d42431 change default title font to DroidSansBold 12 years ago
Qingping Hou 6f5bf4a3b8 bump crengine to version v3.0.57-14
This version also fixes segfault when
reading the Real Analysis - Maths.chm.

The test file is provided by medwatt
from mobileread.
12 years ago
{Qingping,Dave} Hou c43a312725 Merge pull request #169 from dpavlin/master
added Registering fonts dialog on startup
12 years ago
Dobrica Pavlinusic 28161ae3d0 added Registering fonts dialog on startup
This operation can take some time on device
12 years ago
NuPogodi 93b5da0d8d Update crereader.lua 12 years ago
NuPogodi 773a4d69b6 + added: saving & restoring the font size (new parameter > font_zoom)
+ fixed: too long strings in _drawReadingInfo() (called by key 'Menu')
+ fixed: floating the text when the font (face, size or boldface) and/or interline spacing modify the document height
12 years ago
NuPogodi cd046a0637 Update rendertext.lua 12 years ago
{Qingping,Dave} Hou eaaff0d9bc Merge pull request #162 from dpavlin/master
few more tweaks for manual crop rouler
12 years ago
Dobrica Pavlinusic 54657bb74c use hpkfont for ruler, increase size and fix aligment #35
This is maximum font size which allows vertical ruler to have
spacing between vertical letters.
12 years ago
Dobrica Pavlinusic bca64dd4ef use showInfoMsgWithDelay for new bbox and redraw page #153 12 years ago
Qingping Hou 121f154313 bump crengine to version v3.0.57-14
This version also fixes segfault when
reading the Real Analysis - Maths.chm.

The test file is provided by medwatt
from mobileread.
12 years ago
Dobrica Pavlinusic ba19ab7029 added .prc as alternative extension for mobi
This was reported by @valex in post at forum:
http://www.mobileread.com/forums/showpost.php?p=2064360&postcount=340
12 years ago
Dobrica Pavlinušić e73803603b Merge pull request #159 from houqp/master
bump crengine version.
12 years ago
Qingping Hou c2cb95f8e8 remove patch in cre.cpp since it is accepted by upstream 12 years ago
Qingping Hou 84eb0e338f bump crengine to version v3.0.57-14
This version also fixes segfault when
reading the Real Analysis - Maths.chm.

The test file is provided by medwatt
from mobileread.
12 years ago
Dobrica Pavlinušić 7e885198ec Merge pull request #157 from houqp/master
rewrite getpagtext for djvu module
12 years ago
Qingping Hou a73d9a5a52 Merge branch 'master' of github.com:hwhw/kindlepdfviewer 12 years ago
Qingping Hou a672cf4ee0 unified coordinates system in djvrereader
fix bug in showing manual corp area.
this also fixes #132.
12 years ago
Dobrica Pavlinušić 89f9a8c711 Merge pull request #156 from houqp/master
bug fix in jump history
12 years ago
Qingping Hou d21ea032e5 Merge branch 'master' of github.com:hwhw/kindlepdfviewer 12 years ago
Qingping Hou c275862ffe fix bug in jump_history
record current page when jump_history.cur points to
empty head.
12 years ago
Dobrica Pavlinušić 0d4d7e7fb9 Merge pull request #154 from houqp/master
Two bug fixes & patches from NuPogodi
12 years ago
Qingping Hou c818d7e90e screenshot shorcut patch by NuPogodi@mobileread 12 years ago
Qingping Hou 381b34cc04 detect file type in zip file, patched by NuPogodi@mobileread 12 years ago
Qingping Hou eb1fbebc5b change default font face for crereader, reported by NuPogodi@mobileread.
changed to Droid Sans Fallback
12 years ago
Qingping Hou 1e36018021 fix bug in inputbox
Redundant code in character deleting
12 years ago
{Qingping,Dave} Hou dad5b32331 Merge pull request #153 from dpavlin/issue_35_manual_crop
second try to implement ruler idea by @eLiNK2gl in #35
12 years ago
Dobrica Pavlinusic 55cdb26823 force next full refresh 12 years ago
Dobrica Pavlinusic de12c6aac0 second try to implement rouler idea by y @eLiNK2gl in #35 12 years ago
{Qingping,Dave} Hou 246619b9c4 Merge pull request #151 from dpavlin/issue_35_manual_crop
manually select page bounding box
12 years ago
Dobrica Pavlinusic 90b8860ed5 always use partial refresh 12 years ago
Dobrica Pavlinusic 31108d536c manually select page bounding box
I hope we can finally close #35 with this.
12 years ago

@ -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"
@ -201,11 +202,6 @@ thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) $(CRENGINELIBS)
INSTALL_DIR=kindlepdfviewer
install:
# install to kindle using USB networking
scp kpdfview *.lua root@192.168.2.2:/mnt/us/$(INSTALL_DIR)/
scp launchpad/* root@192.168.2.2:/mnt/us/launchpad/
VERSION?=$(shell git rev-parse --short HEAD)
customupdate: all
# ensure that build binary is for ARM
@ -220,6 +216,6 @@ customupdate: all
cp -rpL fonts $(INSTALL_DIR)
cp -r resources $(INSTALL_DIR)
mkdir $(INSTALL_DIR)/fonts/host
zip -9 -r kindlepdfviewer-$(VERSION).zip $(INSTALL_DIR) launchpad/
zip -9 -r kindlepdfviewer-$(VERSION).zip $(INSTALL_DIR) launchpad/ kite/
rm -Rf $(INSTALL_DIR)
@echo "copy kindlepdfviewer-$(VERSION).zip to /mnt/us/customupdates and install with shift+shift+I"

@ -308,10 +308,6 @@ static int gotoXPointer(lua_State *L) {
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
doc->text_view->goToBookmark(xp);
/* CREngine does not call checkPos() immediately after goToBookmark,
* so I have to manually update the pos in order to get a correct
* return from GetPos() call. */
doc->text_view->SetPos(xp.toPoint().y);
return 0;
}

@ -9,8 +9,15 @@ CREReader = UniReader:new{
gamma_index = 15,
font_face = nil,
font_zoom = 0,
line_space_percent = 100,
-- NuPogodi, 15.05.12: insert the parameter to store old doc height before rescaling.
-- One needs it to change font(face, size, bold) without appreciable changing of the
-- current position in document
old_doc_height = 0,
-- end of changes (NuPogodi)
}
function CREReader:init()
@ -25,24 +32,45 @@ function CREReader:init()
end
end
end
-- NuPogodi, 20.05.12: inspect the zipfile content
function CREReader:ZipContentExt(fname)
local outfile = "./data/zip_content"
local s = ""
os.execute("unzip ".."-l \""..fname.."\" > "..outfile)
local i = 1
if io.open(outfile,"r") then
for lines in io.lines(outfile) do
if i == 4 then s = lines break else i = i + 1 end
end
end
-- return the extention
return string.lower(string.match(s, ".+%.([^.]+)"))
end
-- open a CREngine supported file and its settings store
function CREReader:open(filename)
local ok
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
if file_type == "zip" then
-- NuPogodi, 20.05.12: read the content of zip-file
-- and return extention of the 1st file
file_type = self:ZipContentExt(filename)
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
end
self.doc:setDefaultInterlineSpace(self.line_space_percent)
return true
end
@ -51,7 +79,7 @@ end
----------------------------------------------------
function CREReader:loadSpecialSettings()
local font_face = self.settings:readSetting("font_face")
self.font_face = font_face or "FreeSerif"
self.font_face = font_face or "Droid Sans"
self.doc:setFontFace(self.font_face)
local gamma_index = self.settings:readSetting("gamma_index")
@ -60,10 +88,22 @@ 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
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()
local last_percent = self.settings:readSetting("last_percent")
local last_percent = self.settings:readSetting("last_percent")
if last_percent then
return math.floor((last_percent * self.doc:getFullHeight()) / 10000)
else
@ -75,6 +115,7 @@ 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)
self.settings:saveSetting("font_zoom", self.font_zoom)
end
function CREReader:saveLastPageOrPos()
@ -90,7 +131,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 NEARLY CONSTANT! it was NOT!
-- SEEMS TO BE FIXED by relacing self:goto(self.pos) on
self:goto(self.pos * (self.doc:getFullHeight() - G_height) / (self.old_doc_height - G_height))
end
-- there is no zoom mode in CREReader
@ -104,7 +150,7 @@ end
function CREReader:goto(pos, is_ignore_jump, pos_type)
local prev_xpointer = self.doc:getXPointer()
local width, height = G_width, G_height
if pos_type == "xpointer" then
self.doc:gotoXPointer(pos)
pos = self.doc:getCurrentPos()
@ -113,17 +159,16 @@ function CREReader:goto(pos, is_ignore_jump, pos_type)
pos = math.max(pos, 0)
self.doc:gotoPos(pos)
end
-- add to jump history, distinguish jump from normal page turn
-- NOTE:
-- even though we have called gotoPos() or gotoXPointer() previously,
-- even though we have called gotoPos() or gotoXPointer() previously,
-- self.pos hasn't been updated yet here, so we can still make use of it.
if not is_ignore_jump then
if self.pos and math.abs(self.pos - pos) > height then
self:addJump(prev_xpointer)
end
end
self.doc:drawCurrentPage(self.nulldc, fb.bb)
debug("## self.show_overlap "..self.show_overlap)
@ -147,6 +192,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)
@ -271,21 +318,27 @@ 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
function CREReader:adjustCreReaderCommands()
-- delete commands
self.commands:delGroup("[joypad]")
@ -311,7 +364,6 @@ function CREReader:adjustCreReaderCommands()
self.commands:del(KEY_N, MOD_SHIFT, "N") -- show highlights
-- overwrite commands
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)},
@ -323,9 +375,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.."< >",{
@ -335,24 +393,26 @@ 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, 15.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
-- end of changes (NuPogodi)
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 = {}
for i=1,10 do
numeric_keydefs[i]=Keydef:new(KEY_1+i-1, nil, tostring(i%10))
for i=1,10 do
numeric_keydefs[i]=Keydef:new(KEY_1+i-1, nil, tostring(i%10))
end
self.commands:addGroup("[1..0]", numeric_keydefs,
"jump to <key>*10% of document",
@ -363,20 +423,28 @@ 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)
item_no = nil
item_no = fonts_menu:choose(0, G_height)
debug(face_list[item_no])
-- NuPogodi, 15.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
-- end of changes (NuPogodi)
if item_no then
Screen:restoreFromSavedBB()
self.doc:setFontFace(face_list[item_no])
@ -384,13 +452,20 @@ 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, 15.05.12: storing old document height
self.old_doc_height = self.doc:getFullHeight()
-- end of changes (NuPogodi)
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",
@ -439,6 +514,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",

@ -230,6 +230,23 @@ static int getUsedBBox(lua_State *L) {
return 4;
}
static int getOriginalPageSize(lua_State *L) {
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
int pageno = luaL_checkint(L, 2);
ddjvu_status_t r;
ddjvu_pageinfo_t info;
while ((r=ddjvu_document_get_pageinfo(
doc->doc_ref, pageno-1, &info))<DDJVU_JOB_OK) {
handle(L, doc->context, TRUE);
}
lua_pushnumber(L, info.width);
lua_pushnumber(L, info.height);
return 2;
}
/*
* Return a table like following:
@ -255,6 +272,17 @@ static int getPageText(lua_State *L) {
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
int pageno = luaL_checkint(L, 2);
/* get page height for coordinates transform */
ddjvu_pageinfo_t info;
ddjvu_status_t r;
while ((r=ddjvu_document_get_pageinfo(
doc->doc_ref, pageno-1, &info))<DDJVU_JOB_OK) {
handle(L, doc->context, TRUE);
}
if (r>=DDJVU_JOB_FAILED)
return luaL_error(L, "cannot get page #%d information", pageno);
/* start retrieving page text */
miniexp_t sexp, se_line, se_word;
int i = 1, j = 1, counter_l = 1, counter_w=1,
nr_line = 0, nr_word = 0;
@ -292,16 +320,18 @@ static int getPageText(lua_State *L) {
lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_line)));
lua_settable(L, -3);
lua_pushstring(L, "y0");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(2, se_line)));
lua_pushstring(L, "y1");
lua_pushnumber(L,
info.height - miniexp_to_int(miniexp_nth(2, se_line)));
lua_settable(L, -3);
lua_pushstring(L, "x1");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_line)));
lua_settable(L, -3);
lua_pushstring(L, "y1");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(4, se_line)));
lua_pushstring(L, "y0");
lua_pushnumber(L,
info.height - miniexp_to_int(miniexp_nth(4, se_line)));
lua_settable(L, -3);
/* now loop through each word in the line */
@ -325,16 +355,18 @@ static int getPageText(lua_State *L) {
lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_word)));
lua_settable(L, -3);
lua_pushstring(L, "y0");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(2, se_word)));
lua_pushstring(L, "y1");
lua_pushnumber(L,
info.height - miniexp_to_int(miniexp_nth(2, se_word)));
lua_settable(L, -3);
lua_pushstring(L, "x1");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_word)));
lua_settable(L, -3);
lua_pushstring(L, "y1");
lua_pushnumber(L, miniexp_to_int(miniexp_nth(4, se_word)));
lua_pushstring(L, "y0");
lua_pushnumber(L,
info.height - miniexp_to_int(miniexp_nth(4, se_word)));
lua_settable(L, -3);
lua_pushstring(L, "word");
@ -457,7 +489,7 @@ static int drawPage(lua_State *L) {
static int getCacheSize(lua_State *L) {
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
unsigned long size = ddjvu_cache_get_size(doc->context);
printf("## ddjvu_cache_get_size = %d\n", size);
printf("## ddjvu_cache_get_size = %d\n", (int)size);
lua_pushnumber(L, size);
return 1;
}
@ -479,6 +511,7 @@ static const struct luaL_Reg djvudocument_meth[] = {
{"getPages", getNumberOfPages},
{"getToc", getTableOfContent},
{"getPageText", getPageText},
{"getOriginalPageSize", getOriginalPageSize},
{"close", closeDocument},
{"getCacheSize", getCacheSize},
{"cleanCache", cleanCache},

@ -31,68 +31,14 @@ function DJVUReader:getText(pageno)
return self.doc:getPageText(pageno)
end
----------------------------------------------------
-- In djvulibre library, some coordinates starts from
-- lower left conner, i.e. y is upside down in kpv's
-- coordinate. So y0 should be taken with special care.
----------------------------------------------------
function DJVUReader:zoomedRectCoordTransform(x0, y0, x1, y1)
local x,y = self:screenOffset()
return
x0 * self.globalzoom + x,
self.cur_full_height - (y1 * self.globalzoom) + y,
(x1 - x0) * self.globalzoom,
(y1 - y0) * self.globalzoom
end
-- make sure at least part of the box can be seen in next/previous view
-- @FIXME only works in FIT_TO_CONTENT_WIDTH mode 21.04 2012 (houqp)
-- @TODO use zoomedRectCoordTransform in unireader, no need to overwrite
-- it in here.
function DJVUReader:_isBoxInNextView(box)
return self.cur_full_height - (box.y0 * self.globalzoom) > -self.offset_y + G_height
end
function DJVUReader:_isBoxInPrevView(box)
return self.cur_full_height - (box.y1 * self.globalzoom) < -self.offset_y
end
-- 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:_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)
if not w then
return false
-- for incompatible API fixing
function DJVUReader:invertTextYAxel(pageno, text_table)
local _, height = self.doc:getOriginalPageSize(pageno)
for _,text in pairs(text_table) do
for _,line in ipairs(text) do
line.y0, line.y1 = (height - line.y1), (height - line.y0)
end
end
is_entire_word_out_of_screen_height =
(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)
is_entire_word_out_of_screen_width =
(w.x0 * self.globalzoom >= -self.offset_x + G_width
or w.x1 * self.globalzoom <= -self.offset_x)
return (not is_entire_word_out_of_screen_height) and
(not is_entire_word_out_of_screen_width)
return text_table
end

@ -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,
@ -20,9 +28,94 @@ FileChooser = {
page = 1,
current = 1,
oldcurrent = 0,
exception_message = nil
exception_message = nil,
-- NuPogodi, 20.05.12: added new parameters to make helppage available
pagedirty = true,
markerdirty = false,
perpage,
clipboard = lfs.currentdir() .. "/clipboard", -- NO finishing slash
}
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)
-- radius for round corners
local r = 6
-- redefine to ignore the input for background color
color = 3
fb.bb:paintRect(1, 1, fb.bb:getWidth() - 2, height - r, color)
blitbuffer.paintBorder(fb.bb, 1, height/2, fb.bb:getWidth() - 2, height/2, height/2, color, r)
-- to have a horisontal gap between text & background rectangle
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, height-10, 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, height-10, font_face, text, true)
else
local w = renderUtf8Text(fb.bb, lmargin, height-10, font_face, "...", true)
local txt = getProperTitleLength(text, font_face, max_width-w)
renderUtf8Text(fb.bb, w+lmargin, height-10, font_face, txt, true)
end
tw:free()
end
function DrawFooter(text,font_face,h)
local y = G_height - 7
local x = (G_width / 2) - 50
renderUtf8Text(fb.bb, x, y, font_face, text, true)
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 -- 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
-- end of old NuPogodi's functions
function getAbsolutePath(aPath)
local abs_path
if not aPath then
@ -49,23 +142,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 == "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,156 +177,397 @@ function FileChooser:setPath(newPath)
end
end
-- NuPogodi, 20.05.12: FileChooser:choose is totally rewritten
-- to make helppage with hotkeys available for users
function FileChooser:choose(ypos, height)
local perpage = math.floor(height / self.spacing) - 2
local pagedirty = true
local markerdirty = false
self.perpage = math.floor(height / self.spacing) - 2
self.pagedirty = true
self.markerdirty = false
local prevItem = function ()
if self.current == 1 then
if self.page > 1 then
self.current = perpage
self.page = self.page - 1
pagedirty = true
end
else
self.current = self.current - 1
markerdirty = true
end
end
local nextItem = function ()
if self.current == perpage then
if self.page < (self.items / perpage) then
self.current = 1
self.page = self.page + 1
pagedirty = true
end
else
if self.page ~= math.floor(self.items / perpage) + 1
or self.current + (self.page-1)*perpage < self.items then
self.current = self.current + 1
markerdirty = true
end
end
end
self:addAllCommands()
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
if self.pagedirty then
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
local c
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
for c = 1, self.perpage do
local i = (self.page - 1) * self.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
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
-- draw footer
all_page = math.ceil(self.items/self.perpage)
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)
markerdirty = true
-- draw header
DrawTitle(msg,self.margin_H,ypos,self.title_H,4,tface)
self.markerdirty = true
end
if markerdirty then
if not pagedirty then
if self.markerdirty then
local ymarker = ypos + 8 + self.title_H
if not self.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)
if not pagedirty then
fb:refresh(1, 30, ypos + self.spacing*self.current + 10, fb.bb:getWidth() - 60, 3)
fb.bb:paintRect(self.margin_H, ymarker+self.spacing*self.current, fb.bb:getWidth()-2*self.margin_H, 3, 15)
if not self.pagedirty then
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
self.markerdirty = false
end
if pagedirty then
if self.pagedirty then
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)
pagedirty = false
self.pagedirty = false
end
local ev = input.saveWaitForEvent()
--debug("key code:"..ev.code)
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
if ev.code == KEY_FW_UP then
prevItem()
elseif ev.code == KEY_FW_DOWN then
nextItem()
elseif ev.code == KEY_F then -- invoke fontchooser menu
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = Font:getFontList(),
}
local re, font = fonts_menu:choose(0, height)
if re then
Font.fontmap["cfont"] = font
Font:update()
end
pagedirty = true
elseif ev.code == KEY_S then -- invoke search input
keywords = InputBox:input(height-100, 100, "Search:")
if keywords then
-- call FileSearcher
--[[
This might looks a little bit dirty for using callback.
But I cannot come up with a better solution for renewing
the height argument according to screen rotation mode.
The callback might also be useful for calling system
settings menu in the future.
--]]
return nil, function()
InfoMessage:show("Searching...",0)
FileSearcher:init( self.path )
FileSearcher:choose(keywords)
end
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 ev.type ==
end -- while
end
-- NuPogodi, 20.05.12: add available commands
function FileChooser:addAllCommands()
self.commands = Commands:new{}
self.commands:add({KEY_SPACE}, nil, "Space",
"refresh page manually",
function(self)
self.pagedirty = true
end
)
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, ">",
"goto 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
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
self.current = self.items - self.page*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, "<",
"goto 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_FW_DOWN, nil, "joypad down",
"goto next item",
function(self)
if self.current == self.perpage then
if self.page < (self.items / self.perpage) then
self.current = 1
self.page = self.page + 1
pagedirty = true
else
self.current = self.items - (self.page-1)*perpage
markerdirty = true
self.pagedirty = true
end
elseif ev.code == KEY_PGBCK or ev.code == KEY_LPGBCK then
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
)
self.commands:add(KEY_FW_UP, nil, "joypad up",
"goto previous item",
function(self)
if self.current == 1 then
if self.page > 1 then
self.current = self.perpage
self.page = self.page - 1
pagedirty = true
else
self.current = 1
markerdirty = true
self.pagedirty = true
end
else
self.current = self.current - 1
self.markerdirty = true
end
end
)
self.commands:add({KEY_FW_RIGHT, KEY_I}, nil, "joypad right",
"show document information",
function(self)
if self:FullFileName() then
FileInfo:show(self.path,self.files[self.perpage*(self.page-1)+self.current - #self.dirs])
self.pagedirty = true
end
end
)
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "Enter",
"open document / goto folder",
function(self)
local newdir = self.dirs[self.perpage*(self.page-1)+self.current]
if newdir == ".." then
local path = string.gsub(self.path, "(.*)/[^/]+/?$", "%1")
self:setPath(path)
elseif newdir then
self:setPath(self.path.."/"..newdir)
else
self.pathfile = self.path.."/"..self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
openFile(self.pathfile)
end
self.pagedirty = true
end
)
-- NuPogodi, 23.05.12: modified to delete both files and empty folders
self.commands:add(KEY_DEL, nil, "Del",
"delete selected item",
function(self)
local folder = self.dirs[self.perpage*(self.page-1)+self.current]
if folder == ".." then
showInfoMsgWithDelay("<UP-DIR> can not be deleted! ",2000,1)
elseif folder then
InfoMessage:show("Press \'Y\' to confirm deleting... ",0)
if self:ReturnKey() == KEY_Y then
if lfs.rmdir(self.path.."/"..folder) then
self:setPath(self.path)
else
showInfoMsgWithDelay("This folder can not be deleted! ",2000,1)
end
end
self.pagedirty = true
else
local file_to_del = self.path.."/"..self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
InfoMessage:show("Press \'Y\' to confirm deleting... ",0)
if self:ReturnKey() == KEY_Y then
-- delete the file itself
os.execute("rm "..self:InQuotes(file_to_del))
-- and its history file, if any
os.execute("rm "..self:InQuotes(DocToHistory(file_to_del)))
-- to avoid showing just deleted file
self:setPath(self.path)
end
self.pagedirty = true
end -- if folder == ".."
end -- function
)
-- NuPogodi, 24.05.12: Added function to rename documents (extention comes from the old file)
self.commands:add(KEY_R, MOD_SHIFT, "R",
"rename document",
function(self)
local oldname = self:FullFileName()
if oldname then
local newname = InputBox:input(0, 0, "New filename:", "without extention", true)
if newname then
local ext = string.lower(string.match(oldname, ".+%.([^.]+)") or "")
newname = self.path.."/"..newname..'.'..ext
os.rename(oldname, newname)
os.rename(DocToHistory(oldname), DocToHistory(newname))
self:setPath(self.path)
end
self.pagedirty = true
end
end
)
-- end of changes (NuPogodi)
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"goto 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_H,nil,"H",
"show help page",
function(self)
HelpPage:show(0, G_height, self.commands)
self.pagedirty = true
end
)
self.commands:add(KEY_L, nil, "L",
"show last documents",
function(self)
lfs.mkdir("./history/")
FileHistory:init()
FileHistory:choose("")
self.pagedirty = true
return nil
end
)
self.commands:add(KEY_S, nil, "S",
"search among files",
function(self)
local keywords = InputBox:input(0, 0, "Search:")
if keywords then
InfoMessage:show("Searching... ",0)
FileSearcher:init( self.path )
FileSearcher:choose(keywords)
end
self.pagedirty = true
end -- function
)
-- NuPogodi, 23.05.12: new functions to manipulate (copy & move) files via clipboard
self.commands:add(KEY_C, MOD_SHIFT, "C",
"copy document to \'clipboard\'",
function(self)
local file = self:FullFileName()
if file then
lfs.mkdir(self.clipboard)
os.execute("cp "..self:InQuotes(file).." "..self.clipboard)
local fn = self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
os.execute("cp "..self:InQuotes(DocToHistory(file)).." "
..self:InQuotes(DocToHistory(self.clipboard.."/"..fn)) )
showInfoMsgWithDelay("file is copied to clipboard ", 1000, 1)
end
end
)
self.commands:add(KEY_X, MOD_SHIFT, "X",
"move document to \'clipboard\'",
function(self)
local file = self:FullFileName()
if file then
lfs.mkdir(self.clipboard)
os.execute("mv "..self:InQuotes(file).." "..self.clipboard)
local fn = self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
os.rename(DocToHistory(file), DocToHistory(self.clipboard.."/"..fn))
InfoMessage:show("file is moved to clipboard ", 0)
self:setPath(self.path)
self.pagedirty = true
end
end
)
self.commands:add(KEY_V, MOD_SHIFT, "V",
"paste documents from \'clipboard\'",
function(self)
InfoMessage:show("moving file(s) from clipboard ", 0)
for f in lfs.dir(self.clipboard) do
if lfs.attributes(self.clipboard.."/"..f, "mode") == "file" then
os.rename(self.clipboard.."/"..f, self.path.."/"..f)
os.rename(DocToHistory(self.clipboard.."/"..f), DocToHistory(self.path.."/"..f))
end
elseif ev.code == KEY_ENTER or ev.code == KEY_FW_PRESS then
local newdir = self.dirs[perpage*(self.page-1)+self.current]
if newdir == ".." then
local path = string.gsub(self.path, "(.*)/[^/]+/?$", "%1")
self:setPath(path)
elseif newdir then
local path = self.path.."/"..newdir
self:setPath(path)
else
return self.path.."/"..self.files[perpage*(self.page-1)+self.current - #self.dirs]
end
self:setPath(self.path)
self.pagedirty = true
end
)
self.commands:add(KEY_B, MOD_SHIFT, "B",
"show content of \'clipboard\'",
function(self)
lfs.mkdir(self.clipboard)
self:setPath(self.clipboard)
-- TODO: exit back from clipboard to last folder - Redefine Exit on FW_Right?
self.pagedirty = true
end
)
self.commands:add(KEY_N, MOD_SHIFT, "N",
"make new folder",
function(self)
local folder = InputBox:input(0, 0, "New Folder:")
if folder then
if lfs.mkdir(self.path.."/"..folder) then
self:setPath(self.path)
end
pagedirty = true
elseif ev.code == KEY_BACK or ev.code == KEY_HOME then
return nil
end
self.pagedirty = true
end
)
-- end of changes (NuPogodi)
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
Screen:screenshot()
end
)
self.commands:add({KEY_BACK, KEY_HOME}, nil, "Back",
"exit",
function(self)
return "break"
end
)
end
-- NuPogodi, 23.05.12: returns full filename or nil (if folder)
function FileChooser:FullFileName()
local file
local folder = self.dirs[self.perpage*(self.page-1)+self.current]
if folder == ".." then
showInfoMsgWithDelay("<UP-DIR> ",1000,1)
elseif folder then
showInfoMsgWithDelay("<DIR> ",1000,1)
else
file=self.path.."/"..self.files[self.perpage*(self.page-1)+self.current - #self.dirs]
end
return file
end
-- returns the keycode of released key and (if debug) shows the keycode on screen
function FileChooser:ReturnKey(debug)
while true do
ev = input.saveWaitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
break
end
end
if debug then showInfoMsgWithDelay("Keycode = "..ev.code,1000,1) end
return ev.code
end
function FileChooser:InQuotes(text)
return "\""..text.."\""
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,281 @@
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
-- NuPogodi, 26.05.12: a bit changed to return string from size
function FileInfo:FileSize(size)
if size < 1024 then
return size.." Bytes"
elseif size < 2^20 then
return string.format("%.2f", size/2^10).."KB \("..size.." Bytes\)"
else
return string.format("%.2f", size/2^20).."MB \("..size.." Bytes\)"
end
end -- end of changes (NuPogodi, 26.05.12)
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)
-- NuPogodi, 26.05.12: now one has to call FileInfo:FileSize(integer)
info_entry = {dir = "Size", name = FileInfo:FileSize(lfs.attributes(self.pathfile,"size"))}
table.insert(self.result, info_entry)
-- NuPogodi, 26.05.12: size & filename of unzipped entry for zips
if string.lower(string.match(fname, ".+%.([^.]+)")) == "zip" then
local outfile = "./data/zip_content"
local l, s = 1, ""
os.execute("unzip ".."-l \""..self.pathfile.."\" > "..outfile)
if io.open(outfile, "r") then
for lines in io.lines(outfile) do
if l == 4 then s = lines break else l = l + 1 end
end
-- due to rewriting FileInfo:FileSize(integer), one can use it now
info_entry = { dir = "Unpacked", name = FileInfo:FileSize(tonumber(string.sub(s,1,11))) }
table.insert(self.result, info_entry)
--[[ TODO: When the fileentry inside zips is encoded as ANSI (codes 128-255)
any attempt to print such fileentry causes crash by drawing!!! When fileentries
are encoded as UTF8, everything seems fine
info_entry = { dir = "Content", name = string.sub(s,29,-1) }
table.insert(self.result, info_entry) ]]
end
end -- end of changes (NuPogodi, 26.05.12)
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
fb.bb:paintRect(0, 0, G_width, G_height, 0)
-- draw menu title
DrawTitle("Document Information",self.margin_H,0,self.title_H,4,tface)
-- position of left column
local x1 = self.margin_H
-- 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, c = 5, 1
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)
dy = dy + renderUtf8Multiline(fb.bb, x2, y, cface, self.result[i].name, true,
G_width - self.margin_H - x2, 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
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{}
self.commands:add({KEY_SPACE}, nil, "Space",
"refresh page manually",
function(self)
self.pagedirty = true
end
)
self.commands:add(KEY_H,nil,"H",
"show help page",
function(self)
HelpPage:show(0, G_height, self.commands)
self.pagedirty = true
end
)
self.commands:add(KEY_L, nil, "L",
"last documents",
function(self)
FileHistory:init()
FileHistory:choose("")
self.pagedirty = true
end
)
self.commands:add({KEY_F, KEY_AA}, nil, "F",
"font menu",
function(self)
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,
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
)
-- make screenshot
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
Screen:screenshot()
end
)
self.commands:add({KEY_BACK, KEY_FW_LEFT}, nil, "Back",
"back",
function(self)
return "break"
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 == "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",

@ -85,7 +85,7 @@ function Cursor:setHeight(h)
self.line_w = math.floor(self.h / self.line_width_factor)
end
function Cursor:_draw(x, y)
function Cursor:_draw(x, y, refresh)
local up_down_width = math.floor(self.line_w / 2)
local body_h = self.h - (up_down_width * 2)
-- paint upper horizontal line
@ -95,19 +95,23 @@ function Cursor:_draw(x, y)
self.line_w, body_h)
-- paint lower horizontal line
fb.bb:invertRect(x, y + body_h + up_down_width, self.w, up_down_width)
if refresh then
fb:refresh(1, x, y, self.w, body_h + up_down_width * 2)
end
end
function Cursor:draw()
function Cursor:draw(refresh)
if self.is_cleared then
self.is_cleared = false
self:_draw(self.x_pos, self.y_pos)
self:_draw(self.x_pos, self.y_pos, refresh)
end
end
function Cursor:clear()
function Cursor:clear(refresh)
if not self.is_cleared then
self.is_cleared = true
self:_draw(self.x_pos, self.y_pos)
self:_draw(self.x_pos, self.y_pos, refresh)
end
end

@ -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)

@ -3,7 +3,6 @@ require "rendertext"
require "keys"
require "graphics"
----------------------------------------------------
-- General inputbox
----------------------------------------------------
@ -12,17 +11,12 @@ InputBox = {
-- Class vars:
h = 100,
input_slot_w = nil,
input_start_x = 145,
input_start_x = nil,
input_start_y = nil,
input_cur_x = nil, -- points to the start of next input pos
input_bg = 0,
input_string = "",
shiftmode = false,
altmode = false,
cursor = nil,
-- font for displaying input content
@ -32,6 +26,21 @@ InputBox = {
fwidth = 15,
commands = nil,
initialized = false,
-- NuPogodi, 25.05.12: for full UTF8 support
vk_bg = 3,
charlist = {}, -- table to store input string
charpos = 1,
INPUT_KEYS = {}, -- table to store layouts
-- values to control layouts: min & max
min_layout = 2,
max_layout = 9,
-- default layout = 2, i.e. shiftmode = symbolmode = utf8mode = false
layout = 2,
-- now bits to toggle the layout mode
shiftmode = false, -- toggle chars <> capitals, lowest bit in (layout-2)
symbolmode = false, -- toggle chars <> symbols, middle bit in (layout-2)
utf8mode = false, -- toggle english <> national, highest bit in (layout-2)
}
function InputBox:new(o)
@ -41,154 +50,118 @@ function InputBox:new(o)
return o
end
function InputBox:init()
if not self.initialized then
self:addAllCommands()
self.initialized = true
end
end
function InputBox:refreshText()
-- clear previous painted text
fb.bb:paintRect(140, self.input_start_y-19,
self.input_slot_w, self.fheight, self.input_bg)
fb.bb:paintRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg)
-- paint new text
renderUtf8Text(fb.bb, self.input_start_x, self.input_start_y,
self.face,
self.input_string, 0)
renderUtf8Text(fb.bb, self.input_start_x, self.input_start_y, self.face, self.input_string, true)
end
function InputBox:addChar(char)
self.cursor:clear()
-- draw new text
local cur_index = (self.cursor.x_pos + 3 - self.input_start_x)
/ self.fwidth
self.input_string = self.input_string:sub(1, cur_index)..char..
self.input_string:sub(cur_index+1)
local cur_index = (self.cursor.x_pos + 3 - self.input_start_x) / self.fwidth
table.insert(self.charlist, self.charpos, char)
self.charpos = self.charpos + 1
self.input_string = self:CharlistToString()
self:refreshText()
self.input_cur_x = self.input_cur_x + self.fwidth
-- draw new cursor
self.cursor:moveHorizontal(self.fwidth)
self.cursor:draw()
fb:refresh(1, self.input_start_x-5, self.input_start_y-25,
self.input_slot_w, self.h-25)
fb:refresh(1, self.input_start_x-5, self.input_start_y-25, self.input_slot_w, self.h-25)
end
function InputBox:delChar()
if self.input_start_x == self.input_cur_x then
return
end
local cur_index = (self.cursor.x_pos + 3 - self.input_start_x)
/ self.fwidth
if self.input_start_x == self.input_cur_x then return end
local cur_index = (self.cursor.x_pos + 3 - self.input_start_x) / self.fwidth
if cur_index == 0 then return end
self.cursor:clear()
-- draw new text
self.input_string = self.input_string:sub(1, cur_index-1)..
self.input_string:sub(cur_index+1, -1)
self.charpos = self.charpos - 1
table.remove(self.charlist, self.charpos)
self.input_string = self:CharlistToString()
self:refreshText()
self.input_cur_x = self.input_cur_x - self.fwidth
--fill last character with blank rectangle
fb.bb:paintRect(self.input_cur_x, self.input_start_y-19,
self.fwidth, self.fheight, self.input_bg)
-- fill last character with blank rectangle
fb.bb:paintRect(self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight, self.input_bg)
fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight)
self.input_string = self.input_string:sub(0,-2)
-- draw new cursor
self.cursor:moveHorizontal(-self.fwidth)
self.cursor:draw()
fb:refresh(1, self.input_start_x-5, self.input_start_y-25,
self.input_slot_w, self.h-25)
fb:refresh(1, self.input_start_x-5, self.input_start_y-25, self.input_slot_w, self.h-25)
end
function InputBox:clearText()
self.cursor:clear()
self.input_string = ""
self.charlist = {}
self.charpos = 1
self:refreshText()
self.cursor.x_pos = self.input_start_x - 3
self.cursor:draw()
fb:refresh(1, self.input_start_x-5, self.input_start_y-25,
self.input_slot_w, self.h-25)
end
function InputBox:drawHelpMsg(ypos, w, h)
return
fb:refresh(1, self.input_start_x-5, self.input_start_y-25, self.input_slot_w, self.h-25)
end
function InputBox:drawBox(ypos, w, h, title)
-- draw input border
fb.bb:paintRect(20, ypos, w, h, 5)
-- draw input slot
fb.bb:paintRect(140, ypos + 10, w - 130, h - 20, self.input_bg)
local r = 6 -- round corners
fb.bb:paintRect(1, ypos+r, w, h - r, self.vk_bg)
blitbuffer.paintBorder(fb.bb, 1, ypos, fb.bb:getWidth() - 2, r, r, self.vk_bg, r)
-- draw input title
renderUtf8Text(fb.bb, 35, self.input_start_y, self.face,
title, true)
self.input_start_y = ypos + 37
-- draw the box title > estimate the start point for future text & the text slot width
self.input_start_x = 25 + renderUtf8Text(fb.bb, 15, self.input_start_y, self.face, title, true)
self.input_slot_w = fb.bb:getWidth() - self.input_start_x - 5
-- draw input slot
fb.bb:paintRect(self.input_start_x - 5, ypos + 10, self.input_slot_w, h - 20, self.input_bg)
end
----------------------------------------------------------------------
-- InputBox:input()
--
-- @title: input prompt for the box
-- @d_text: default to nil (used to set default text in input slot)
-- @is_hint: if this arg is true, default text will be used as hint
-- message for input
-- @is_hint: if this arg is true, default text will be used as hint
-- message for input
----------------------------------------------------------------------
function InputBox:input(ypos, height, title, d_text, is_hint)
self:init()
-- To avoid confusion with old ypos & height parameters, I'd better define
-- my own position, at the bottom screen edge (NuPogodi, 26.05.12)
ypos = fb.bb:getHeight() - 165
-- at first, draw titled box and content
local h, w = 55, fb.bb:getWidth() - 2
self:drawBox(ypos, w, h, title)
-- do some initilization
self.ypos = ypos
self.h = height
self.input_start_y = ypos + 35
self.h = 100
self.input_cur_x = self.input_start_x
self.input_slot_w = fb.bb:getWidth() - 170
self:addAllCommands()
self.cursor = Cursor:new {
x_pos = self.input_start_x - 3,
y_pos = ypos + 13,
h = 30,
}
-- draw box and content
w = fb.bb:getWidth() - 40
h = height - 45
self:drawHelpMsg(ypos, w, h)
self:drawBox(ypos, w, h, title)
if d_text then
if is_hint then
-- print hint text
fb.bb:paintRect(140, self.input_start_y-19,
self.input_slot_w, self.fheight, self.input_bg)
renderUtf8Text(fb.bb, self.input_start_x+5, self.input_start_y,
self.face,
d_text, 0)
fb.bb:dimRect(140, self.input_start_y-19,
self.input_slot_w, self.fheight, self.input_bg)
-- print hint text
fb.bb:paintRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg)
renderUtf8Text(fb.bb, self.input_start_x+5, self.input_start_y, self.face, d_text, 0)
fb.bb:dimRect(self.input_start_x-5, self.input_start_y-19, self.input_slot_w, self.fheight, self.input_bg)
else
self.input_string = d_text
self.input_cur_x = self.input_cur_x + (self.fwidth * d_text:len())
self.cursor.x_pos = self.cursor.x_pos + (self.fwidth * d_text:len())
self.input_cur_x = self.input_cur_x + (self.fwidth * #self.charlist)
self.cursor.x_pos = self.cursor.x_pos + (self.fwidth * #self.charlist)
self:refreshText()
end
end
self.cursor:draw()
fb:refresh(1, 20, ypos, w, h)
fb:refresh(1, 1, ypos, w, h)
while true do
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))
@ -196,60 +169,184 @@ function InputBox:input(ypos, height, title, d_text, is_hint)
else
debug("command not found: "..tostring(command))
end
if ret_code == "break" then
ret_code = nil
break
end
end -- if
end -- while
local return_str = self.input_string
self.input_string = ""
self.charlist = {}
self.charpos = 1
return return_str
end
function InputBox:addAllCommands()
if self.commands then
-- we only initialize once
return
end
self.commands = Commands:new{}
INPUT_KEYS = {
{KEY_Q, "q"}, {KEY_W, "w"}, {KEY_E, "e"}, {KEY_R, "r"}, {KEY_T, "t"},
{KEY_Y, "y"}, {KEY_U, "u"}, {KEY_I, "i"}, {KEY_O, "o"}, {KEY_P, "p"},
{KEY_A, "a"}, {KEY_S, "s"}, {KEY_D, "d"}, {KEY_F, "f"}, {KEY_G, "g"},
{KEY_H, "h"}, {KEY_J, "j"}, {KEY_K, "k"}, {KEY_L, "l"},
{KEY_Z, "z"}, {KEY_X, "x"}, {KEY_C, "c"}, {KEY_V, "v"}, {KEY_B, "b"},
{KEY_N, "n"}, {KEY_M, "m"},
function InputBox:setLayoutsTable()
-- trying to read the layout from the user-defined file "mykeyboard.lua"
local ok, stored = pcall(dofile,"./mykeyboard.lua")
if ok then
self.INPUT_KEYS = stored
else -- if an error happens, we use the default layout
self.INPUT_KEYS = {
{ KEY_Q, "Q", "q", "1", "!", "Я", "я", "1", "!", },
{ KEY_W, "W", "w", "2", "?", "Ж", "ж", "2", "?", },
{ KEY_E, "E", "e", "3", "#", "Е", "е", "3", "«", },
{ KEY_R, "R", "r", "4", "@", "Р", "р", "4", "»", },
{ KEY_T, "T", "t", "5", "\%", "Т", "т", "5", ":", },
{ KEY_Y, "Y", "y", "6", "", "Ы", "ы", "6", ";", },
{ KEY_U, "U", "u", "7", "\'", "У", "у", "7", "~", },
{ KEY_I, "I", "i", "8", "`", "И", "и", "8", "\(",},
{ KEY_O, "O", "o", "9", ":", "О", "о", "9", "\)",},
{ KEY_P, "P", "p", "0", ";", "П", "п", "0", "=", },
-- middle raw
{ KEY_A, "A", "a", "+", "", "А", "а", "Ш", "ш", },
{ KEY_S, "S", "s", "-", "_", "С", "с", "Ѕ", "ѕ", },
{ KEY_D, "D", "d", "*", "¦", "Д", "д", "Э", "э", },
{ KEY_F, "F", "f", "/", "|", "Ф", "ф", "Ю", "ю", },
{ KEY_G, "G", "g", "\\", "", "Г", "г", "Ґ", "ґ", },
{ KEY_H, "H", "h", "=", "", "Ч", "ч", "Ј", "ј", },
{ KEY_J, "J", "j", "<", "", "Й", "й", "І", "і", },
{ KEY_K, "K", "k", "ˆ", "\"", "К", "к", "Ќ", "ќ", },
{ KEY_L, "L", "l", ">", "~", "Л", "л", "Љ", "љ", },
-- lowest raw
{ KEY_Z, "Z", "z", "\(", "$", "З", "з", "Щ", "щ", },
{ KEY_X, "X", "x", "\)", "", "Х", "х", "", "@", },
{ KEY_C, "C", "c", "\{", "¥", "Ц", "ц", "Џ", "џ", },
{ KEY_V, "V", "v", "\}", "£", "В", "в", "Ў", "ў", },
{ KEY_B, "B", "b", "\[", "", "Б", "б", "Ћ", "ћ", },
{ KEY_N, "N", "n", "\]", "", "Н", "н", "Њ", "њ", },
{ KEY_M, "M", "m", "&", "", "М", "м", "Ї", "ї", },
{ KEY_DOT, ".", ",", ".", ",", ".", ",", "Є", "є", },
-- Let us make key 'Space' the same for all layouts
{ KEY_SPACE," ", " ", " ", " ", " ", " ", " ", " ", },
-- Simultaneous pressing Alt + Q..P should also work properly
{ KEY_1, "1", " ", " ", " ", "1", " ", " ", " ", },
{ KEY_2, "2", " ", " ", " ", "2", " ", " ", " ", },
{ KEY_3, "3", " ", " ", " ", "3", " ", " ", " ", },
{ KEY_4, "4", " ", " ", " ", "4", " ", " ", " ", },
{ KEY_5, "5", " ", " ", " ", "5", " ", " ", " ", },
{ KEY_6, "6", " ", " ", " ", "6", " ", " ", " ", },
{ KEY_7, "7", " ", " ", " ", "7", " ", " ", " ", },
{ KEY_8, "8", " ", " ", " ", "8", " ", " ", " ", },
{ KEY_9, "9", " ", " ", " ", "9", " ", " ", " ", },
{ KEY_0, "0", " ", " ", " ", "0", " ", " ", " ", },
-- DXG keys
{ KEY_SLASH,"/", "\\", "/", "\\", "/", "\\", "/", "\\", },
}
end -- if ok
end
{KEY_1, "1"}, {KEY_2, "2"}, {KEY_3, "3"}, {KEY_4, "4"}, {KEY_5, "5"},
{KEY_6, "6"}, {KEY_7, "7"}, {KEY_8, "8"}, {KEY_9, "9"}, {KEY_0, "0"},
function InputBox:DrawVKey(key,x,y,face,rx,ry,t,c)
blitbuffer.paintBorder(fb.bb, x-11, y-ry-8, rx, ry, t, c, ry)
renderUtf8Text(fb.bb, x, y, face, key, true)
end
{KEY_SPACE, " "},
-- this function is designed for K3 keyboard, portrait mode
-- TODO: support for other Kindle models & orientations?
function InputBox:DrawVirtualKeyboard()
local vy = fb.bb:getHeight()-15
-- dx, dy = xy-distance between the button rows
-- lx - position of left button column
-- r, c, t = radius, color and thickness of circles around chars
-- h = y-correction to adjust cicles & chars
local dx, dy, lx, r, c, bg, t = 51, 36, 20, 17, 6, self.vk_bg, 2
fb.bb:paintRect(1, fb.bb:getHeight()-120, fb.bb:getWidth()-2, 120, bg)
-- font to draw characters - MUST have UTF8-support
local vkfont = Font:getFace("infont", 22)
for k,v in ipairs(self.INPUT_KEYS) do
if v[1] >= KEY_Q and v[1] <= KEY_P then -- upper raw
self:DrawVKey(v[self.layout], lx+(v[1]-KEY_Q)*dx, vy-2*dy, vkfont, r, r, t, c)
elseif v[1] >= KEY_A and v[1] <= KEY_L then -- middle raw
self:DrawVKey(v[self.layout], lx+(v[1]-KEY_A)*dx, vy-dy, vkfont, r, r, t, c)
elseif v[1] >= KEY_Z and v[1] <= KEY_M then -- lower raw
self:DrawVKey(v[self.layout], lx+(v[1]-KEY_Z)*dx, vy, vkfont, r, r, t, c)
elseif v[1] == KEY_DOT then
self:DrawVKey(v[self.layout], lx + 7*dx, vy, vkfont, r, r, t, c)
end
end
-- the rest symbols (manually)
local smfont = Font:getFace("infont", 14)
-- Del
blitbuffer.paintBorder(fb.bb, lx+9*dx-10, vy-dy-r-8, r, r, t, c, r)
renderUtf8Text(fb.bb, lx-5+9*dx, vy-dy-3, smfont, "Del", true)
-- Sym
blitbuffer.paintBorder(fb.bb, lx+8*dx-10, vy-r-8, r, r, t + (r-t)*number(self.symbolmode), c, r)
renderUtf8Text(fb.bb, lx-5+8*dx, vy-3, smfont, "Sym", true)
-- Enter
blitbuffer.paintBorder(fb.bb, lx+9*dx-10, vy-r-8, r, r, t, c, r)
renderUtf8Text(fb.bb, lx+9*dx, vy-2, vkfont, "«", true)
-- Menu
blitbuffer.paintBorder(fb.bb, lx+10*dx-8, vy-2*dy-r-8, r+50, r, t+(r-t)*number(self.utf8mode), c, r)
renderUtf8Text(fb.bb, lx+10*dx+11, vy-2*dy-3, smfont, "Menu", true)
-- fiveway
local h=dy+2*r-2
blitbuffer.paintBorder(fb.bb, lx+10*dx-8, vy-dy-r-6, h, h, 9, c, r)
renderUtf8Text(fb.bb, lx+10*dx+22, vy-20, smfont, (self.layout-1), true)
fb:refresh(1, 1, fb.bb:getHeight()-120, fb.bb:getWidth()-2, 120)
end
-- DXG keys
{KEY_DOT, "."}, {KEY_SLASH, "/"},
}
for k,v in ipairs(INPUT_KEYS) do
self.commands:add(v[1], nil, "",
"input "..v[2],
function InputBox:addCharCommands(layout)
-- at first, let's define self.layout and extract separate bits as layout modes
if layout then
-- to be sure layout is selected properly
layout = math.max(layout, self.min_layout)
layout = math.min(layout, self.max_layout)
self.layout = layout
-- fill the layout modes
layout = (layout - 2) % 4
self.shiftmode = (layout == 1 or layout == 3)
self.symbolmode = (layout == 2 or layout == 3)
self.utf8mode = (self.layout > 5)
else -- or, without input parameter, restore layout from current layout modes
self.layout = 2 + number(self.shiftmode) + 2 * number(self.symbolmode) + 4 * number(self.utf8mode)
end
-- adding the commands
for k,v in ipairs(self.INPUT_KEYS) do
-- seems to work without removing old commands,
self.commands:del(v[1], nil, "")
-- just redefining existing ones
self.commands:add(v[1], nil, "", "input "..v[self.layout],
function(self)
self:addChar(v[2])
self:addChar(v[self.layout])
end
)
end
self:DrawVirtualKeyboard()
end
function InputBox:CharlistToString()
local s, i = ""
for i=1, #self.charlist do
s = s .. self.charlist[i]
end
return s
end
function number(bool)
return bool and 1 or 0
end
function InputBox:addAllCommands()
-- we only initialize once
if self.commands then
self:DrawVirtualKeyboard()
return
end
self:setLayoutsTable()
self.commands = Commands:new{}
-- adding command to enter character commands
self:addCharCommands()
-- adding the rest commands (independent of the selected layout)
self.commands:add(KEY_FW_LEFT, nil, "",
"move cursor left",
function(self)
if (self.cursor.x_pos + 3) > self.input_start_x then
self.cursor:moveHorizontalAndDraw(-self.fwidth)
fb:refresh(1, self.input_start_x-5, self.ypos,
self.input_slot_w, self.h)
self.charpos = self.charpos - 1
fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h)
end
end
)
@ -258,8 +355,8 @@ function InputBox:addAllCommands()
function(self)
if (self.cursor.x_pos + 3) < self.input_cur_x then
self.cursor:moveHorizontalAndDraw(self.fwidth)
fb:refresh(1, self.input_start_x-5, self.ypos,
self.input_slot_w, self.h)
self.charpos = self.charpos + 1
fb:refresh(1, self.input_start_x-5, self.ypos, self.input_slot_w, self.h)
end
end
)
@ -291,112 +388,56 @@ function InputBox:addAllCommands()
return "break"
end
)
end
----------------------------------------------------
-- Inputbox for numbers only
-- Designed by eLiNK
----------------------------------------------------
NumInputBox = InputBox:new{
initialized = false,
commands = Commands:new{},
}
function NumInputBox:addAllCommands()
self.commands = Commands:new{}
INPUT_NUM_KEYS = {
{KEY_Q, "1"}, {KEY_W, "2"}, {KEY_E, "3"}, {KEY_R, "4"}, {KEY_T, "5"},
{KEY_Y, "6"}, {KEY_U, "7"}, {KEY_I, "8"}, {KEY_O, "9"}, {KEY_P, "0"},
{KEY_1, "1"}, {KEY_2, "2"}, {KEY_3, "3"}, {KEY_4, "4"}, {KEY_5, "5"},
{KEY_6, "6"}, {KEY_7, "7"}, {KEY_8, "8"}, {KEY_9, "9"}, {KEY_0, "0"},
}
for k,v in ipairs(INPUT_NUM_KEYS) do
self.commands:add(v[1], nil, "",
"input "..v[2],
function(self)
self:addChar(v[2])
end
)
end -- for
self.commands:add(KEY_FW_LEFT, nil, "",
"move cursor left",
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(self)
if (self.cursor.x_pos + 3) > self.input_start_x then
self.cursor:moveHorizontalAndDraw(-self.fwidth)
fb:refresh(1, self.input_start_x-5, self.ypos,
self.input_slot_w, self.h)
end
Screen:screenshot()
end
)
self.commands:add(KEY_FW_RIGHT, nil, "",
"move cursor right",
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
"goto next keyboard layout",
function(self)
if (self.cursor.x_pos + 3) < self.input_cur_x then
self.cursor:moveHorizontalAndDraw(self.fwidth)
fb:refresh(1, self.input_start_x-5, self.ypos,
self.input_slot_w, self.h)
end
if self.layout == self.max_layout then self:addCharCommands(self.min_layout)
else self:addCharCommands(self.layout+1) end
end
)
self.commands:add({KEY_ENTER, KEY_FW_PRESS}, nil, "",
"submit input content",
self.commands:add(KEY_FW_UP, nil, "joypad up",
"goto previous keyboard layout",
function(self)
if self.input_string == "" then
self.input_string = nil
end
return "break"
if self.layout == self.min_layout then self:addCharCommands(self.max_layout)
else self:addCharCommands(self.layout-1) end
end
)
self.commands:add(KEY_DEL, nil, "",
"delete one character",
self.commands:add(KEY_AA, nil, "Aa",
"toggle layout: chars <> CHARS",
function(self)
self:delChar()
self.shiftmode = not self.shiftmode
self:addCharCommands()
end
)
self.commands:add(KEY_DEL, MOD_SHIFT, "",
"empty inputbox",
self.commands:add(KEY_SYM, nil, "Sym",
"toggle layout: chars <> symbols",
function(self)
self:clearText()
self.symbolmode = not self.symbolmode
self:addCharCommands()
end
)
self.commands:add({KEY_BACK, KEY_HOME}, nil, "",
"cancel inputbox",
self.commands:add(KEY_MENU, nil, "Menu",
"toggle layout: english <> national",
function(self)
self.input_string = nil
return "break"
self.utf8mode = not self.utf8mode
self:addCharCommands()
end
)
end
function NumInputBox:drawHelpMsg(ypos, w, h)
local w = 415
local y = ypos - 60
local x = (G_width - w) / 2
local h = 50
local bw = 2
local face = Font:getFace("scfont", 22)
fb.bb:paintRect(x, y, w, h, 15)
fb.bb:paintRect(x+bw, y+bw, w-2*bw, h-2*bw, 0)
local font_y = y + 22
local font_x = x + 22
INPUT_NUM_KEYS = {
{"Q", "1"}, {"W", "2"}, {"E", "3"}, {"R", "4"}, {"T", "5"},
{"Y", "6"}, {"U", "7"}, {"I", "8"}, {"O", "9"}, {"P", "0"},
}
for k,v in ipairs(INPUT_NUM_KEYS) do
renderUtf8Text(fb.bb, font_x, font_y, face,
v[1], true)
renderUtf8Text(fb.bb, font_x, font_y + 22, face,
v[2], true)
font_x = font_x + 40
end
----------------------------------------------------
-- Inputbox for numbers only
-- Designed by eLiNK
----------------------------------------------------
fb:refresh(1, x, y, w, h)
end
NumInputBox = InputBox:new{
symbolmode = true,
layout = 4,
charlist = {}
}

@ -0,0 +1,3 @@
#!/bin/sh
/mnt/us/launchpad/kpdf.sh

@ -0,0 +1,3 @@
#!/bin/sh
/mnt/us/launchpad/kpdf.sh /mnt/us/documents

@ -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 }

@ -1 +1 @@
Subproject commit 7a73d1666538fe9dd7d84d7e18135b03c21be2ca
Subproject commit 99882134490b47ebb28107cebfbeb8eafb070f54

@ -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 == "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,10 @@ function Screen:restoreFromBB(bb)
debug("Got nil bb in restoreFromSavedBB!")
end
end
function Screen:screenshot()
lfs.mkdir("./screenshots")
local d = os.date("%Y%m%d%H%M%S")
showInfoMsgWithDelay("making screenshot... ", 1000, 1)
os.execute("dd ".."if=/dev/fb0 ".."of=/mnt/us/kindlepdfviewer/screenshots/" .. d .. ".raw")
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,72 @@
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
-- set up new history head
stored.jump_history.cur = #stored.jump_history + 1
end
end
-- update variable name
if stored.globalzoommode ~= nil then
stored.globalzoom_mode = stored.globalzoommode
stored.globalzoommode = nil
end
if stored.highlight ~= nil then
local file_type = string.lower(string.match(docfile, ".+%.([^.]+)"))
if file_type == "djvu" then
stored.highlight.to_fix = {"djvu invert y axle"}
end
end
stored.version = 2012.05
debug("upgraded", stored)
end
new.data = stored
end
return setmetatable(new, { __index = DocSettings})

@ -115,6 +115,7 @@ end
function UniReader:init()
-- initialize commands
InfoMessage:show("Registering fonts...", 1)
self:addAllCommands()
end
@ -149,6 +150,19 @@ function UniReader:zoomedRectCoordTransform(x0, y0, x1, y1)
(y1 - y0) * self.globalzoom
end
----------------------------------------------------
-- Given coordinates on the screen return positioni
-- in original page
----------------------------------------------------
function UniReader:screenToPageTransform(x, y)
local x_o,y_o = self:screenOffset()
local x_p,y_p =
( x - x_o ) / self.globalzoom,
( y - y_o ) / self.globalzoom
debug("screenToPage", x,y, "offset", x_o,y_o, "page", x_p,y_p)
return x_p, y_p
end
----------------------------------------------------
-- Given coordinates of four corners in original page
-- size and return rectangular area in screen. You
@ -337,7 +351,7 @@ function UniReader:drawCursorAfterWord(t, l, w)
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()
self.cursor:draw(true)
end
function UniReader:drawCursorBeforeWord(t, l, w)
@ -347,7 +361,7 @@ function UniReader:drawCursorBeforeWord(t, l, w)
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()
self.cursor:draw(true)
end
function UniReader:getText(pageno)
@ -549,8 +563,7 @@ function UniReader:startHighLightMode()
h = ch,
line_width_factor = 4,
}
self.cursor:draw()
fb:refresh(1)
self.cursor:draw(true)
-- first use cursor to place start pos for highlight
while running do
@ -561,7 +574,7 @@ function UniReader:startHighLightMode()
is_meet_end = false
l.new, w.new, is_meet_start = _prevGap(t, l.cur, w.cur)
self.cursor:clear()
self.cursor:clear(true)
if w.new ~= 0
and self:_isLineInPrevView(t[l.new])
and self:_isEntireWordInScreenWidthRange(t[l.new][w.new]) then
@ -585,7 +598,7 @@ function UniReader:startHighLightMode()
is_meet_start = false
l.new, w.new, is_meet_end = _nextGap(t, l.cur, w.cur)
self.cursor:clear()
self.cursor:clear(true)
-- we want to check whether the word is in screen range,
-- so trun gap into word
local tmp_w = w.new
@ -612,7 +625,7 @@ function UniReader:startHighLightMode()
is_meet_end = false
l.new, w.new, is_meet_start = _gapInPrevLine(t, l.cur, w.cur)
self.cursor:clear()
self.cursor:clear(true)
local tmp_w = w.new
if tmp_w == 0 then
@ -638,7 +651,7 @@ function UniReader:startHighLightMode()
is_meet_start = false
l.new, w.new, is_meet_end = _gapInNextLine(t, l.cur, w.cur)
self.cursor:clear()
self.cursor:clear(true)
local tmp_w = w.new
if w.cur == 0 then
@ -686,13 +699,12 @@ function UniReader:startHighLightMode()
l.new, w.new = l.cur, w.cur
l.start, w.start = l.cur, w.cur
running = false
self.cursor:clear()
self.cursor:clear(true)
elseif ev.code == KEY_BACK then
running = false
return
end -- if check key event
l.cur, w.cur = l.new, w.new
fb:refresh(1)
end
end -- while running
debug("start", l.cur, w.cur, l.start, w.start)
@ -976,6 +988,20 @@ function UniReader:loadSettings(filename)
local highlight = self.settings:readSetting("highlight")
self.highlight = highlight or {}
if self.highlight.to_fix ~= nil then
for _,fix_item in ipairs(self.highlight.to_fix) do
if fix_item == "djvu invert y axle" then
InfoMessage:show("Updating HighLight data...", 1)
for pageno,text_table in pairs(self.highlight) do
if type(pageno) == "number" then
text_table = self:invertTextYAxel(pageno, text_table)
end
end
end
end
debug(self.highlight)
self.highlight.to_fix = nil
end
local bbox = self.settings:readSetting("bbox")
debug("bbox loaded ", bbox)
@ -1670,6 +1696,10 @@ function UniReader:showJumpHist()
local jump_item = self.jump_history[item_no]
self.jump_history.cur = item_no
self:goto(jump_item.page, true)
-- set new head if we reached the top of backward stack
if self.jump_history.cur == #self.jump_history then
self.jump_history.cur = self.jump_history.cur + 1
end
else
self:redrawCurrentPage()
end
@ -1875,7 +1905,15 @@ function UniReader:addAllCommands()
self.commands:add(KEY_BACK,nil,"Back",
"go backward in jump history",
function(unireader)
local prev_jump_no = unireader.jump_history.cur - 1
local prev_jump_no = 0
if unireader.jump_history.cur > #unireader.jump_history then
-- if cur points to head, put current page in history
unireader:addJump(self.pageno)
prev_jump_no = unireader.jump_history.cur - 2
else
prev_jump_no = unireader.jump_history.cur - 1
end
if prev_jump_no >= 1 then
unireader.jump_history.cur = prev_jump_no
unireader:goto(unireader.jump_history[prev_jump_no].page, true)
@ -1890,6 +1928,10 @@ function UniReader:addAllCommands()
if next_jump_no <= #self.jump_history then
unireader.jump_history.cur = next_jump_no
unireader:goto(unireader.jump_history[next_jump_no].page, true)
-- set new head if we reached the top of backward stack
if unireader.jump_history.cur == #unireader.jump_history then
unireader.jump_history.cur = unireader.jump_history.cur + 1
end
else
showInfoMsgWithDelay("Already last jump!", 2000, 1)
end
@ -2090,7 +2132,180 @@ function UniReader:addAllCommands()
x,y,w,h = unireader:getRectInScreen( bbox["x0"], bbox["y0"], bbox["x1"], bbox["y1"] )
debug("inxertRect",x,y,w,h)
fb.bb:invertRect( x,y, w,h )
fb:refresh(0)
fb:refresh(1)
end)
self.commands:add(KEY_X,MOD_SHIFT,"X",
"modify page bbox",
function(unireader)
local bbox = unireader.cur_bbox
debug("bbox", bbox)
x,y,w,h = unireader:getRectInScreen( bbox["x0"], bbox["y0"], bbox["x1"], bbox["y1"] )
debug("getRectInScreen",x,y,w,h)
local new_bbox = bbox
local x_s, y_s = x,y
local running_corner = "top-left"
Screen:saveCurrentBB()
fb.bb:invertRect( 0,y_s, G_width,1 )
fb.bb:invertRect( x_s,0, 1,G_height )
InfoMessage:show(running_corner.." bbox");
fb:refresh(1)
local last_direction = { x = 0, y = 0 }
while running_corner do
local ev = input.saveWaitForEvent()
debug("ev",ev)
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value ~= EVENT_VALUE_KEY_RELEASE then
fb.bb:invertRect( 0,y_s, G_width,1 )
fb.bb:invertRect( x_s,0, 1,G_height )
local step = 10
local factor = 1
local x_direction, y_direction = 0,0
if ev.code == KEY_FW_LEFT then
x_direction = -1
elseif ev.code == KEY_FW_RIGHT then
x_direction = 1
elseif ev.code == KEY_FW_UP then
y_direction = -1
elseif ev.code == KEY_FW_DOWN then
y_direction = 1
elseif ev.code == KEY_FW_PRESS then
local p_x,p_y = unireader:screenToPageTransform(x_s,y_s)
if running_corner == "top-left" then
new_bbox["x0"] = p_x
new_bbox["y0"] = p_y
debug("change top-left", bbox, "to", new_bbox)
running_corner = "bottom-right"
Screen:restoreFromSavedBB()
InfoMessage:show(running_corner.." bbox")
fb:refresh(1)
x_s = x+w
y_s = y+h
else
new_bbox["x1"] = p_x
new_bbox["y1"] = p_y
running_corner = false
end
elseif ev.code >= KEY_Q and ev.code <= KEY_P then
factor = ev.code - KEY_Q + 1
x_direction = last_direction["x"]
y_direction = last_direction["y"]
debug("factor",factor,"deltas",x_direction,y_direction)
elseif ev.code >= KEY_A and ev.code <= KEY_L then
factor = ev.code - KEY_A + 11
x_direction = last_direction["x"]
y_direction = last_direction["y"]
elseif ev.code >= KEY_Z and ev.code <= KEY_M then
factor = ev.code - KEY_Z + 20
x_direction = last_direction["x"]
y_direction = last_direction["y"]
elseif ev.code == KEY_BACK or ev.code == KEY_HOME then
running_corner = false
end
debug("factor",factor,"deltas",x_direction,y_direction)
if running_corner then
local x_o = x_direction * step * factor
local y_o = y_direction * step * factor
debug("move slider",x_o,y_o)
if x_s+x_o >= 0 and x_s+x_o <= G_width then x_s = x_s + x_o end
if y_s+y_o >= 0 and y_s+y_o <= G_height then y_s = y_s + y_o end
if x_direction ~= 0 or y_direction ~= 0 then
Screen:restoreFromSavedBB()
end
fb.bb:invertRect( 0,y_s, G_width,1 )
fb.bb:invertRect( x_s,0, 1,G_height )
if x_direction or y_direction then
last_direction = { x = x_direction, y = y_direction }
debug("last_direction",last_direction)
-- FIXME partial duplicate of SelectMenu.item_shortcuts
local keys = {
"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
"A", "S", "D", "F", "G", "H", "J", "K", "L",
"Z", "X", "C", "V", "B", "N", "M",
}
local max = 0
if x_direction == 1 then
max = G_width - x_s
elseif x_direction == -1 then
max = x_s
elseif y_direction == 1 then
max = G_height - y_s
elseif y_direction == -1 then
max = y_s
else
print("ERROR: unknown direction!")
end
max = max / step
if max > #keys then max = #keys end
local face = Font:getFace("hpkfont", 11)
for i = 1, max, 1 do
local key = keys[i]
local tick = i * step * x_direction
if x_direction ~= 0 then
local tick = i * step * x_direction
debug("x tick",i,tick,key)
if running_corner == "top-left" then -- ticks must be inside page
fb.bb:invertRect( x_s+tick, y_s, 1, math.abs(tick))
else
fb.bb:invertRect( x_s+tick, y_s-math.abs(tick), 1, math.abs(tick))
end
if x_direction < 0 then tick = tick - step end
tick = tick - step * x_direction / 2
renderUtf8Text(fb.bb, x_s+tick+2, y_s+4, face, key)
else
local tick = i * step * y_direction
debug("y tick",i,tick,key)
if running_corner == "top-left" then -- ticks must be inside page
fb.bb:invertRect( x_s, y_s+tick, math.abs(tick),1)
else
fb.bb:invertRect( x_s-math.abs(tick), y_s+tick, math.abs(tick),1)
end
if y_direction > 0 then tick = tick + step end
tick = tick - step * y_direction / 2
renderUtf8Text(fb.bb, x_s-3, y_s+tick-1, face, key)
end
end
end
fb:refresh(1)
end
end
end
unireader.bbox[unireader.pageno] = new_bbox
unireader.bbox[unireader:oddEven(unireader.pageno)] = new_bbox
unireader.bbox.enabled = true
debug("crop bbox", bbox, "to", new_bbox)
Screen:restoreFromSavedBB()
x,y,w,h = unireader:getRectInScreen( new_bbox["x0"], new_bbox["y0"], new_bbox["x1"], new_bbox["y1"] )
fb.bb:invertRect( x,y, w,h )
--fb.bb:invertRect( x+1,y+1, w-2,h-2 ) -- just border?
showInfoMsgWithDelay("new page bbox", 2000, 1);
self:redrawCurrentPage()
self.rcount = self.rcountmax -- force next full refresh
--unireader:setglobalzoom_mode(unireader.ZOOM_FIT_TO_CONTENT)
end)
self.commands:add(KEY_MENU,nil,"Menu",
"toggle info box",
@ -2216,6 +2431,12 @@ function UniReader:addAllCommands()
unireader:goto(unireader.pageno)
end
)
self.commands:add(KEY_P, MOD_SHIFT, "P",
"make screenshot",
function(unireader)
Screen:screenshot()
end
)
-- commands.map is very large, impacts startup performance on device
--debug("defined commands "..dump(self.commands.map))
end

Loading…
Cancel
Save