Merge branch 'master' of github.com:hwhw/kindlepdfviewer

pull/2/merge
Dobrica Pavlinusic 12 years ago
commit 9add90a169

4
.gitignore vendored

@ -13,3 +13,7 @@ kindlepdfviewer-*.zip
/.project
/.reader.kpdfview
kpvcrlib/CMakeCache.txt
kpvcrlib/CMakeFiles/
kpvcrlib/cmake_install.cmake
kpvcrlib/Makefile

3
.gitmodules vendored

@ -7,3 +7,6 @@
[submodule "djvulibre"]
path = djvulibre
url = git://djvu.git.sourceforge.net/gitroot/djvu/djvulibre.git
[submodule "kpvcrlib/crengine"]
path = kpvcrlib/crengine
url = git://crengine.git.sourceforge.net/gitroot/crengine/crengine

@ -5,10 +5,15 @@ MUPDFDIR=mupdf
MUPDFTARGET=build/debug
MUPDFLIBDIR=$(MUPDFDIR)/$(MUPDFTARGET)
DJVUDIR=djvulibre
KPVCRLIGDIR=kpvcrlib
CRENGINEDIR=$(KPVCRLIGDIR)/crengine
FREETYPEDIR=$(MUPDFDIR)/thirdparty/freetype-2.4.8
LFSDIR=luafilesystem
# must point to directory with *.ttf fonts for crengine
TTF_FONTS_DIR=/usr/share/fonts/truetype/freefont/
# set this to your ARM cross compiler:
CC:=arm-unknown-linux-gnueabi-gcc
@ -55,15 +60,25 @@ KPDFREADER_CFLAGS=$(CFLAGS) -I$(LUADIR)/src -I$(MUPDFDIR)/
MUPDFLIBS := $(MUPDFLIBDIR)/libfitz.a
DJVULIBS := $(DJVUDIR)/build/libdjvu/.libs/libdjvulibre.a
CRENGINELIBS := $(CRENGINEDIR)/crengine/libcrengine.a \
$(CRENGINEDIR)/thirdparty/chmlib/libchmlib.a \
$(CRENGINEDIR)/thirdparty/libpng/libpng.a \
$(CRENGINEDIR)/thirdparty/antiword/libantiword.a
THIRDPARTYLIBS := $(MUPDFLIBDIR)/libfreetype.a \
$(MUPDFLIBDIR)/libjpeg.a \
$(MUPDFLIBDIR)/libopenjpeg.a \
$(MUPDFLIBDIR)/libjbig2dec.a \
$(MUPDFLIBDIR)/libz.a
$(MUPDFLIBDIR)/libopenjpeg.a \
$(MUPDFLIBDIR)/libjbig2dec.a \
$(MUPDFLIBDIR)/libjpeg.a \
$(MUPDFLIBDIR)/libz.a
#@TODO patch crengine to use the latest libjpeg 04.04 2012 (houqp)
#$(MUPDFLIBDIR)/libjpeg.a
#$(CRENGINEDIR)/thirdparty/libjpeg/libjpeg.a
LUALIB := $(LUADIR)/src/liblua.a
kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft.o lfs.o $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) djvu.o
all:kpdfview slider_watcher
kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft.o lfs.o $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) djvu.o $(DJVULIBS) cre.o $(CRENGINELIBS)
$(CC) -lm -ldl -lpthread $(EMU_LDFLAGS) -lstdc++ \
kpdfview.o \
einkfb.o \
@ -79,11 +94,16 @@ kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft
$(LUALIB) \
djvu.o \
$(DJVULIBS) \
cre.o \
$(CRENGINELIBS) \
-o kpdfview
einkfb.o input.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) $(EMU_CFLAGS) $< -o $@
slider_watcher: slider_watcher.c
$(CC) $(CFLAGS) $< -o $@
ft.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) -I$(FREETYPEDIR)/include $< -o $@
@ -93,25 +113,38 @@ kpdfview.o pdf.o blitbuffer.o util.o drawcontext.o: %.o: %.c
djvu.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) -I$(DJVUDIR)/ $< -o $@
cre.o: %.o: %.cpp
$(CC) -c -I$(CRENGINEDIR)/crengine/include/ -Ilua/src $< -o $@ -lstdc++
lfs.o: $(LFSDIR)/src/lfs.c
$(CC) -c $(CFLAGS) -I$(LUADIR)/src -I$(LFSDIR)/src $(LFSDIR)/src/lfs.c -o $@
fetchthirdparty:
-rm -Rf lua lua-5.1.4*
-rm -Rf lua lua-5.1.4
-rm -Rf mupdf/thirdparty
git submodule init
git submodule update
ln -sf kpvcrlib/crengine/cr3gui/data data
test -d fonts || ln -sf $(TTF_FONTS_DIR) fonts
test -f mupdf-thirdparty.zip || wget http://www.mupdf.com/download/mupdf-thirdparty.zip
unzip mupdf-thirdparty.zip -d mupdf
cd mupdf/thirdparty/jpeg-*/ && \
patch -N -p0 < ../../../kpvcrlib/jpeg_compress_struct_size.patch &&\
patch -N -p0 < ../../../kpvcrlib/jpeg_decompress_struct_size.patch
test -f lua-5.1.4.tar.gz || wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
tar xvzf lua-5.1.4.tar.gz && ln -s lua-5.1.4 lua
clean:
-rm -f *.o kpdfview
-rm -f *.o kpdfview slider_watcher
cleanthirdparty:
make -C $(LUADIR) clean
make -C $(MUPDFDIR) clean
make -C $(CRENGINEDIR)/thirdparty/antiword clean
make -C $(CRENGINEDIR)/thirdparty/chmlib clean
make -C $(CRENGINEDIR)/thirdparty/libpng clean
make -C $(CRENGINEDIR)/crengine clean
make -C $(KPVCRLIGDIR) clean
-rm -rf $(DJVUDIR)/build
-rm -f $(MUPDFDIR)/fontdump.host
-rm -f $(MUPDFDIR)/cmapdump.host
@ -139,10 +172,15 @@ else
endif
make -C $(DJVUDIR)/build
$(CRENGINELIBS):
cd $(KPVCRLIGDIR) && rm -rf CMakeCache.txt CMakeFiles && \
CFLAGS="$(CFLAGS)" CC="$(CC)" CXX="$(CXX)" cmake . && \
make
$(LUALIB):
make -C lua/src CC="$(CC)" CFLAGS="$(CFLAGS)" MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E" liblua.a
thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS)
thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) $(CRENGINELIBS)
INSTALL_DIR=kindlepdfviewer
@ -156,7 +194,9 @@ customupdate: kpdfview
# ensure that build binary is for ARM
file kpdfview | grep ARM || exit 1
mkdir $(INSTALL_DIR)
cp -p README.TXT COPYING kpdfview *.lua $(INSTALL_DIR)
cp -p README.TXT COPYING kpdfview slider_watcher *.lua $(INSTALL_DIR)
cp -rpL data $(INSTALL_DIR)
cp -rp fonts $(INSTALL_DIR)
zip -r kindlepdfviewer-$(VERSION).zip $(INSTALL_DIR) launchpad/
rm -Rf $(INSTALL_DIR)
@echo "copy kindlepdfviewer-$(VERSION).zip to /mnt/us/customupdates and install with shift+shift+I"

@ -5,6 +5,7 @@ Keydef = {
modifier = nil,
descr = nil
}
function Keydef:_new(obj)
-- obj definition
obj = obj or {}
@ -13,6 +14,7 @@ function Keydef:_new(obj)
self.__tostring=Keydef.tostring
return obj
end
function Keydef:new(keycode,modifier,descr)
obj = Keydef:_new()
obj.keycode = keycode
@ -20,13 +22,16 @@ function Keydef:new(keycode,modifier,descr)
obj.descr = descr
return obj
end
function Keydef:display()
return ((self.modifier and self.modifier.."+") or "")..(self.descr or "")
end
function Keydef:tostring()
return ((self.modifier and self.modifier.."+") or "").."["..(self.keycode or "").."]"..(self.descr or "")
end
Command = {
keydef = nil,
keygroup = nil,
@ -34,6 +39,7 @@ Command = {
help = nil,
order = nil
}
function Command:_new(obj)
-- obj definition
obj = obj or {}
@ -42,6 +48,7 @@ function Command:_new(obj)
self.__tostring=Command.tostring
return obj
end
function Command:new(keydef, func, help, keygroup, order)
obj = Command:_new()
obj.keydef = keydef
@ -52,6 +59,7 @@ function Command:new(keydef, func, help, keygroup, order)
--print("creating command: ["..tostring(keydef).."] keygroup:["..(keygroup or "").."] help:"..help)
return obj
end
function Command:tostring()
return tostring(self.keydef)..": "..(self.help or "<no help defined>")
end
@ -61,6 +69,7 @@ Commands = {
map = {},
size = 0
}
function Commands:add(keycode,modifier,keydescr,help,func)
if type(keycode) == "table" then
for i=1,#keycode,1 do
@ -72,11 +81,42 @@ function Commands:add(keycode,modifier,keydescr,help,func)
self:_addImpl(keydef,help,func)
end
end
function Commands:addGroup(keygroup,keys,help,func)
for _k,keydef in pairs(keys) do
self:_addImpl(keydef,help,func,keygroup)
end
end
--@TODO handle MOD_ANY 06.04 2012 (houqp)
function Commands:del(keycode, modifier, keydescr)
local keydef = nil
if not keydescr then
for k,v in pairs(self.map) do
if v.keydef.keycode == keycode
and v.keydef.modifier == modifier then
keydef = k
break
end
end -- EOF for
else
keydef = Keydef:new(keycode, modifier, keydescr)
end -- EOF if
self.map[keydef] = nil
end
function Commands:delGroup(keygroup)
if keygroup then
for k,v in pairs(self.map) do
if v.keygroup == keygroup then
self.map[k] = nil
end
end -- EOF for
end
end
function Commands:_addImpl(keydef,help,func,keygroup)
if keydef.modifier==MOD_ANY then
self:addGroup(keygroup or keydef.descr,{Keydef:new(keydef.keycode,nil), Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
@ -95,25 +135,32 @@ function Commands:_addImpl(keydef,help,func,keygroup)
end
end
end
function Commands:get(keycode,modifier)
return self.map[Keydef:new(keycode, modifier)]
end
function Commands:getByKeydef(keydef)
return self.map[keydef]
end
function Commands:new(obj)
-- obj definition
obj = obj or {}
obj.map = {}
obj.size = 0
setmetatable(obj, self)
self.__index = self
-- payload
local mt = {}
setmetatable(self.map,mt)
mt.__index=function (table, key)
mt.__index = function(table, key)
return rawget(table,(key.modifier or "").."@#@"..(key.keycode or ""))
end
mt.__newindex=function (table, key, value)
mt.__newindex = function(table, key, value)
return rawset(table,(key.modifier or "").."@#@"..(key.keycode or ""),value)
end
-- obj definition
obj = obj or {}
setmetatable(obj, self)
self.__index = self
setmetatable(obj.map, mt)
return obj
end

@ -0,0 +1,464 @@
/*
KindlePDFViewer: CREngine abstraction for Lua
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
Qingping Hou <qingping.hou@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern "C" {
#include "blitbuffer.h"
#include "drawcontext.h"
#include "cre.h"
}
#include "crengine.h"
//using namespace std;
typedef struct CreDocument {
LVDocView *text_view;
ldomDocument *dom_doc;
} CreDocument;
static int openDocument(lua_State *L) {
const char *file_name = luaL_checkstring(L, 1);
const char *style_sheet = luaL_checkstring(L, 2);
int width = luaL_checkint(L, 3);
int height = luaL_checkint(L, 4);
lString8 css;
CreDocument *doc = (CreDocument*) lua_newuserdata(L, sizeof(CreDocument));
luaL_getmetatable(L, "credocument");
lua_setmetatable(L, -2);
doc->text_view = new LVDocView();
doc->text_view->setBackgroundColor(0x000000);
if (LVLoadStylesheetFile(lString16(style_sheet), css)){
if (!css.empty()){
doc->text_view->setStyleSheet(css);
}
}
doc->text_view->setViewMode(DVM_SCROLL, -1);
doc->text_view->Resize(width, height);
doc->text_view->LoadDocument(file_name);
doc->dom_doc = doc->text_view->getDocument();
doc->text_view->Render();
return 1;
}
static int getGammaIndex(lua_State *L) {
lua_pushinteger(L, fontMan->GetGammaIndex());
return 1;
}
static int setGammaIndex(lua_State *L) {
int index = luaL_checkint(L, 1);
fontMan->SetGammaIndex(index);
return 0;
}
static int closeDocument(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
delete doc->text_view;
return 0;
}
static int getNumberOfPages(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->getPageCount());
return 1;
}
static int getCurrentPage(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->getCurPage());
return 1;
}
static int getPageFromXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *xpointer_str = luaL_checkstring(L, 2);
int page = 0;
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
page = doc->text_view->getBookmarkPage(xp);
lua_pushinteger(L, page);
return 1;
}
static int getCurrentPos(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->GetPos());
return 1;
}
//static int getPosFromXPointer(lua_State *L) {
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
//const char *xpointer_str = luaL_checkstring(L, 2);
//lvRect rc;
//int pos;
//ldomXPointer *xp = NULL;
//xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
//getCursorDocRect(*xp, rc);
//pos =
//return 1;
//}
static int getCurrentPercent(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->getPosPercent());
return 1;
}
static int getXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
ldomXPointer xp = doc->text_view->getBookmark();
lua_pushstring(L, UnicodeToLocal(xp.toString()).c_str());
return 1;
}
static int getFullHeight(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_pushinteger(L, doc->text_view->GetFullHeight());
return 1;
}
/*
* helper function for getTableOfContent()
*/
static int walkTableOfContent(lua_State *L, LVTocItem *toc, int *count) {
LVTocItem *toc_tmp = NULL;
int i = 0,
nr_child = toc->getChildCount();
for(i = 0; i < nr_child; i++) {
toc_tmp = toc->getChild(i);
lua_pushnumber(L, (*count)++);
/* set subtable, Toc entry */
lua_newtable(L);
lua_pushstring(L, "page");
lua_pushnumber(L, toc_tmp->getPercent());
lua_settable(L, -3);
lua_pushstring(L, "xpointer");
lua_pushstring(L, UnicodeToLocal(
toc_tmp->getXPointer().toString()).c_str()
);
lua_settable(L, -3);
lua_pushstring(L, "depth");
lua_pushnumber(L, toc_tmp->getLevel());
lua_settable(L, -3);
lua_pushstring(L, "title");
lua_pushstring(L, UnicodeToLocal(toc_tmp->getName()).c_str());
lua_settable(L, -3);
/* set Toc entry to Toc table */
lua_settable(L, -3);
if (toc_tmp->getChildCount() > 0) {
walkTableOfContent(L, toc_tmp, count);
}
}
return 0;
}
/*
* Return a table like this:
* {
* {
* page=12,
* xpointer = "/body/DocFragment[11].0",
* depth=1,
* title="chapter1"
* },
* {
* page=54,
* xpointer = "/body/DocFragment[13].0",
* depth=1,
* title="chapter2"
* },
* }
*
* Warnning: not like pdf or djvu support, page here refers to the
* percent of height within the document, not the real page number.
* We use page here just to keep consistent with other readers.
*
*/
static int getTableOfContent(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
LVTocItem * toc = doc->text_view->getToc();
int count = 0;
lua_newtable(L);
walkTableOfContent(L, toc, &count);
return 1;
}
/*
* Return a table like this:
* {
* "FreeMono",
* "FreeSans",
* "FreeSerif",
* }
*
*/
static int getFontFaces(lua_State *L) {
int i = 0;
lString16Collection face_list;
fontMan->getFaceList(face_list);
lua_newtable(L);
for (i = 0; i < face_list.length(); i++)
{
lua_pushnumber(L, i+1);
lua_pushstring(L, UnicodeToLocal(face_list[i]).c_str());
lua_settable(L, -3);
}
return 1;
}
static int setFontFace(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *face = luaL_checkstring(L, 2);
doc->text_view->setDefaultFontFace(lString8(face));
return 0;
}
static int gotoPage(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
int pageno = luaL_checkint(L, 2);
doc->text_view->goToPage(pageno);
return 0;
}
static int gotoPercent(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
int percent = luaL_checkint(L, 2);
doc->text_view->SetPos(percent * doc->text_view->GetFullHeight() / 10000);
return 0;
}
static int gotoPos(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
int pos = luaL_checkint(L, 2);
doc->text_view->SetPos(pos);
return 0;
}
static int gotoXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *xpointer_str = luaL_checkstring(L, 2);
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
doc->text_view->goToBookmark(xp);
/* CREngine does not call checkPos() immediately after goToBookmark,
* so I have to manually update the pos in order to get a correctionColor
* return from GetPos() call. */
doc->text_view->SetPos(xp.toPoint().y);
return 0;
}
/* zoom font by given delta and return zoomed font size */
static int zoomFont(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
int delta = luaL_checkint(L, 2);
doc->text_view->ZoomFont(delta);
lua_pushnumber(L, doc->text_view->getFontSize());
return 1;
}
static int toggleFontBolder(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
doc->text_view->doCommand(DCMD_TOGGLE_BOLD);
return 0;
}
static int cursorRight(lua_State *L) {
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
//LVDocView *tv = doc->text_view;
//ldomXPointer p = tv->getCurrentPageMiddleParagraph();
//lString16 s = p.toString();
//printf("~~~~~~~~~~%s\n", UnicodeToLocal(s).c_str());
//tv->selectRange(*(tv->selectFirstPageLink()));
//ldomXRange *r = tv->selectNextPageLink(true);
//lString16 s = r->getRangeText();
//printf("------%s\n", UnicodeToLocal(s).c_str());
//tv->selectRange(*r);
//tv->updateSelections();
//LVPageWordSelector sel(doc->text_view);
//doc->text_view->doCommand(DCMD_SELECT_FIRST_SENTENCE);
//sel.moveBy(DIR_RIGHT, 2);
//sel.updateSelection();
//printf("---------------- %s\n", UnicodeToLocal(sel.getSelectedWord()->getText()).c_str());
return 0;
}
static int drawCurrentPage(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
int w = bb->w,
h = bb->h;
LVGrayDrawBuf drawBuf(w, h, 8);
doc->text_view->Resize(w, h);
doc->text_view->Render();
doc->text_view->Draw(drawBuf);
uint8_t *bbptr = (uint8_t*)bb->data;
uint8_t *pmptr = (uint8_t*)drawBuf.GetScanLine(0);
int i,x;
for (i = 0; i < h; i++) {
for (x = 0; x < (bb->w / 2); x++) {
bbptr[x] = 255 - (((pmptr[x*2 + 1] & 0xF0) >> 4) |
(pmptr[x*2] & 0xF0));
}
if(bb->w & 1) {
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
}
bbptr += bb->pitch;
pmptr += w;
}
}
static const struct luaL_Reg cre_func[] = {
{"openDocument", openDocument},
{"getFontFaces", getFontFaces},
{"getGammaIndex", getGammaIndex},
{"setGammaIndex", setGammaIndex},
{NULL, NULL}
};
static const struct luaL_Reg credocument_meth[] = {
/*--- get methods ---*/
{"getPages", getNumberOfPages},
{"getCurrentPage", getCurrentPage},
{"getPageFromXPointer", getPageFromXPointer},
{"getCurrentPos", getCurrentPos},
{"getCurrentPercent", getCurrentPercent},
{"getXPointer", getXPointer},
{"getFullHeight", getFullHeight},
{"getToc", getTableOfContent},
/*--- set methods ---*/
{"setFontFace", setFontFace},
/* --- control methods ---*/
{"gotoPage", gotoPage},
{"gotoPercent", gotoPercent},
{"gotoPos", gotoPos},
{"gotoXPointer", gotoXPointer},
{"zoomFont", zoomFont},
{"toggleFontBolder", toggleFontBolder},
//{"cursorLeft", cursorLeft},
//{"cursorRight", cursorRight},
{"drawCurrentPage", drawCurrentPage},
{"close", closeDocument},
{"__gc", closeDocument},
{NULL, NULL}
};
int luaopen_cre(lua_State *L) {
luaL_newmetatable(L, "credocument");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_settable(L, -3);
luaL_register(L, NULL, credocument_meth);
lua_pop(L, 1);
luaL_register(L, "cre", cre_func);
/* initialize fonts for CREngine */
InitFontManager(lString8("./fonts"));
lString8 fontDir("./fonts");
LVContainerRef dir = LVOpenDirectory( LocalToUnicode(fontDir).c_str() );
if ( !dir.isNull() )
for ( int i=0; i<dir->GetObjectCount(); i++ ) {
const LVContainerItemInfo * item = dir->GetObjectInfo(i);
lString16 fileName = item->GetName();
if ( !item->IsContainer() && fileName.length()>4 && lString16(fileName, fileName.length()-4, 4)==L".ttf" ) {
lString8 fn = UnicodeToLocal(fileName);
printf("loading font: %s\n", fn.c_str());
if ( !fontMan->RegisterFont(fn) ) {
printf(" failed\n");
}
}
}
#ifdef DEBUG_CRENGINE
CRLog::setStdoutLogger();
CRLog::setLogLevel(CRLog::LL_DEBUG);
#endif
return 1;
}

28
cre.h

@ -0,0 +1,28 @@
/*
KindlePDFViewer: CREngine abstraction for Lua
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
Qingping Hou <qingping.hou@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CRENGING_H
#define _CRENGING_H
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int luaopen_cre(lua_State *L);
#endif

@ -0,0 +1,314 @@
require "unireader"
require "inputbox"
require "selectmenu"
CREReader = UniReader:new{
pos = nil,
percent = 0,
gamma_index = 15,
font_face = nil,
}
function CREReader:init()
self:addAllCommands()
self:adjustCreReaderCommands()
end
-- open a CREngine supported file and its settings store
function CREReader:open(filename)
local ok
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
-- these two format use the same css file
if file_type == "html" then
file_type = "htm"
end
local style_sheet = "./data/"..file_type..".css"
ok, self.doc = pcall(cre.openDocument, filename, style_sheet,
width, height)
if not ok then
return false, self.doc -- will contain error message
end
return true
end
----------------------------------------------------
-- setting related methods
----------------------------------------------------
function CREReader:loadSpecialSettings()
local font_face = self.settings:readSetting("font_face")
self.font_face = font_face or "FreeSerif"
self.doc:setFontFace(self.font_face)
local gamma_index = self.settings:readSetting("gamma_index")
self.gamma_index = gamma_index or self.gamma_index
cre.setGammaIndex(self.gamma_index)
end
function CREReader:getLastPageOrPos()
local last_percent = self.settings:readSetting("last_percent")
if last_percent then
return math.floor((last_percent * self.doc:getFullHeight()) / 10000)
else
return 0
end
end
function CREReader:saveSpecialSettings()
self.settings:savesetting("font_face", self.font_face)
self.settings:savesetting("gamma_index", self.gamma_index)
end
function CREReader:saveLastPageOrPos()
self.settings:savesetting("last_percent", self.percent)
end
----------------------------------------------------
-- render related methods
----------------------------------------------------
-- we don't need setzoom in CREReader
function CREReader:setzoom(page, preCache)
return
end
function CREReader:redrawCurrentPage()
self:goto(self.pos)
end
----------------------------------------------------
-- goto related methods
----------------------------------------------------
function CREReader:goto(pos, pos_type)
local prev_xpointer = self.doc:getXPointer()
if pos_type == "xpointer" then
self.doc:gotoXPointer(pos)
pos = self.doc:getCurrentPos()
else -- pos_type is PERCENT * 100
pos = math.min(pos, self.doc:getFullHeight())
pos = math.max(pos, 0)
self.doc:gotoPos(pos)
end
-- add to jump_stack, distinguish jump from normal page turn
-- NOTE:
-- even though we have called gotoPos() or gotoXPointer() previously,
-- self.pos hasn't been updated yet here, so we can still make use of it.
if self.pos and math.abs(self.pos - pos) > height then
self:addJump(prev_xpointer)
end
self.doc:drawCurrentPage(self.nulldc, fb.bb)
if self.rcount == self.rcountmax then
print("full refresh")
self.rcount = 1
fb:refresh(0)
else
print("partial refresh")
self.rcount = self.rcount + 1
fb:refresh(1)
end
self.pos = pos
self.pageno = self.doc:getCurrentPage()
self.percent = self.doc:getCurrentPercent()
end
function CREReader:gotoPercent(percent)
self:goto(percent * self.doc:getFullHeight() / 10000)
end
function CREReader:gotoTocEntry(entry)
self:goto(entry.xpointer, "xpointer")
end
function CREReader:nextView()
return self.pos + height - self.pan_overlap_vertical
end
function CREReader:prevView()
return self.pos - height + self.pan_overlap_vertical
end
----------------------------------------------------
-- jump stack related methods
----------------------------------------------------
function CREReader:isSamePage(p1, p2)
return self.doc:getPageFromXPointer(p1) == self.doc:getPageFromXPointer(p2)
end
function CREReader:showJumpStack()
local menu_items = {}
print(dump(self.jump_stack))
for k,v in ipairs(self.jump_stack) do
table.insert(menu_items,
v.datetime.." -> page "..
(self.doc:getPageFromXPointer(v.page)).." "..v.notes)
end
jump_menu = SelectMenu:new{
menu_title = "Jump Keeper (current page: "..self.pageno..")",
item_array = menu_items,
no_item_msg = "No jump history.",
}
item_no = jump_menu:choose(0, fb.bb:getHeight())
if item_no then
local jump_item = self.jump_stack[item_no]
self:goto(jump_item.page, "xpointer")
else
self:redrawCurrentPage()
end
end
----------------------------------------------------
-- TOC related methods
----------------------------------------------------
function CREReader:getTocTitleOfCurrentPage()
return self:getTocTitleByPage(self.percent)
end
----------------------------------------------------
-- menu related methods
----------------------------------------------------
-- used in CREReader:showMenu()
function CREReader:_drawReadingInfo()
local ypos = height - 50
local load_percent = self.percent/100
fb.bb:paintRect(0, ypos, width, 50, 0)
ypos = ypos + 15
local face, fhash = Font:getFaceAndHash(22)
local cur_section = self:getTocTitleOfCurrentPage()
if cur_section ~= "" then
cur_section = "Section: "..cur_section
end
renderUtf8Text(fb.bb, 10, ypos+6, face, fhash,
"Position: "..load_percent.."%".." "..cur_section, true)
ypos = ypos + 15
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
5, 4, load_percent/100, 8)
end
function CREReader:adjustCreReaderCommands()
-- delete commands
self.commands:delGroup("[joypad]")
self.commands:del(KEY_G, nil, "G")
self.commands:del(KEY_J, nil, "J")
self.commands:del(KEY_K, nil, "K")
self.commands:del(KEY_Z, nil, "Z")
self.commands:del(KEY_Z, MOD_SHIFT, "Z")
self.commands:del(KEY_Z, MOD_ALT, "Z")
self.commands:del(KEY_A, nil, "A")
self.commands:del(KEY_A, MOD_SHIFT, "A")
self.commands:del(KEY_A, MOD_ALT, "A")
self.commands:del(KEY_S, nil, "S")
self.commands:del(KEY_S, MOD_SHIFT, "S")
self.commands:del(KEY_S, MOD_ALT, "S")
self.commands:del(KEY_D, nil, "D")
self.commands:del(KEY_D, MOD_SHIFT, "D")
self.commands:del(KEY_D, MOD_ALT, "D")
self.commands:del(KEY_F, MOD_SHIFT, "F")
self.commands:del(KEY_F, MOD_ALT, "F")
-- overwrite commands
self.commands:add(KEY_PGFWD, MOD_SHIFT_OR_ALT, ">",
"increase font size",
function(cr)
cr.doc:zoomFont(1)
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_PGBCK, MOD_SHIFT_OR_ALT, "<",
"decrease font size",
function(cr)
cr.doc:zoomFont(-1)
cr:redrawCurrentPage()
end
)
local numeric_keydefs = {}
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",
function(cr, keydef)
print('jump to position: '..
math.floor(cr.doc:getFullHeight()*(keydef.keycode-KEY_1)/9)..
'/'..cr.doc:getFullHeight())
cr:goto(math.floor(cr.doc:getFullHeight()*(keydef.keycode-KEY_1)/9))
end
)
self.commands:add(KEY_F, nil, "F",
"invoke font menu",
function(cr)
local face_list = cre.getFontFaces()
local fonts_menu = SelectMenu:new{
menu_title = "Fonts Menu",
item_array = face_list,
}
local item_no = fonts_menu:choose(0, height)
print(face_list[item_no])
if item_no then
cr.doc:setFontFace(face_list[item_no])
self.font_face = face_list[item_no]
end
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_F, MOD_ALT, "F",
"Toggle font bolder attribute",
function(cr)
cr.doc:toggleFontBolder()
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_B, MOD_SHIFT, "B",
"add jump",
function(cr)
cr:addJump(self.doc:getXPointer())
end
)
self.commands:add(KEY_BACK,nil,"back",
"back to last jump",
function(cr)
if #cr.jump_stack ~= 0 then
cr:goto(cr.jump_stack[1].page, "xpointer")
end
end
)
self.commands:add(KEY_VPLUS, nil, "vol+",
"increase gamma",
function(cr)
cre.setGammaIndex(self.gamma_index + 1)
self.gamma_index = cre.getGammaIndex()
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_VMINUS, nil, "vol-",
"decrease gamma",
function(cr)
cre.setGammaIndex(self.gamma_index - 1)
self.gamma_index = cre.getGammaIndex()
cr:redrawCurrentPage()
end
)
self.commands:add(KEY_FW_UP, nil, "joypad up",
"pan "..self.shift_y.." pixels upwards",
function(cr)
cr:goto(cr.pos - cr.shift_y)
end
)
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
"pan "..self.shift_y.." pixels downwards",
function(cr)
cr:goto(cr.pos + cr.shift_y)
end
)
end

@ -473,7 +473,7 @@ static const struct luaL_Reg djvu_func[] = {
static const struct luaL_Reg djvudocument_meth[] = {
{"openPage", openPage},
{"getPages", getNumberOfPages},
{"getTOC", getTableOfContent},
{"getToc", getTableOfContent},
{"getPageText", getPageText},
{"close", closeDocument},
{"getCacheSize", getCacheSize},

@ -13,6 +13,27 @@ function DJVUReader:open(filename)
return ok
end
function DJVUReader:init()
self:addAllCommands()
self:adjustDjvuReaderCommand()
end
function DJVUReader:adjustDjvuReaderCommand()
self.commands:add(KEY_N, nil, "N",
"start highlight mode",
function(unireader)
unireader:startHighLightMode()
unireader:goto(unireader.pageno)
end
)
self.commands:add(KEY_N, MOD_SHIFT, "N",
"display all highlights",
function(unireader)
unireader:showHighLight()
unireader:goto(unireader.pageno)
end
)
end
-----------[ highlight support ]----------

@ -54,7 +54,11 @@ function FileChooser:readDir()
table.insert(self.dirs, f)
else
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" then
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 == "fb2" or file_type == "chm" then
table.insert(self.files, f)
end
end

@ -30,10 +30,16 @@ function FileSearcher:readDir()
for __, d in pairs(self.dirs) do
-- 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
table.insert(new_dirs, d.."/"..f)
elseif string.match(f, ".+%.[pP][dD][fF]$") or string.match(f, ".+%.[dD][jJ][vV][uU]$") then
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 == "fb2" or file_type == "chm" then
file_entry = {dir=d, name=f,}
table.insert(self.files, file_entry)
--print("file:"..d.."/"..f)

@ -22,8 +22,8 @@
#include <linux/input.h>
#include "input.h"
#define NUM_FDS 3
int inputfds[3] = { -1, -1, -1 };
#define NUM_FDS 4
int inputfds[4] = { -1, -1, -1, -1 };
static int openInputDevice(lua_State *L) {
#ifndef EMULATE_READER

@ -87,6 +87,9 @@ KEY_FW_UP = 122
KEY_FW_DOWN = 123
KEY_FW_PRESS = 92
KEY_INTO_SCREEN_SAVER = 10000
KEY_OUTOF_SCREEN_SAVER = 10001
-- constants from <linux/input.h>
EV_KEY = 1

@ -26,6 +26,8 @@
#include "blitbuffer.h"
#include "drawcontext.h"
#include "pdf.h"
#include "djvu.h"
#include "cre.h"
#include "einkfb.h"
#include "input.h"
#include "ft.h"
@ -53,6 +55,7 @@ int main(int argc, char **argv) {
luaopen_einkfb(L);
luaopen_pdf(L);
luaopen_djvu(L);
luaopen_cre(L);
luaopen_input(L);
luaopen_util(L);
luaopen_ft(L);

@ -0,0 +1,51 @@
PROJECT(kpvcrlib)
cmake_minimum_required(VERSION 2.6)
SET(MUPDF_DIR ../mupdf)
SET(MUPDF_3RDPARTY_DIR ${MUPDF_DIR}/thirdparty)
SET(CR_3RDPARTY_DIR crengine/thirdparty)
SET(CR3_PNG 1)
#SET(CR3_JPEG 1)
SET(FREETYPE_INCLUDE_DIRS ${CR_3RDPARTY_DIR}/freetype/include)
SET(ANTIWORD_INCLUDE_DIR ${CR_3RDPARTY_DIR}/antiword)
SET(CHM_INCLUDE_DIRS ${CR_3RDPARTY_DIR}/chmlib)
SET(PNG_INCLUDE_DIR ${CR_3RDPARTY_DIR}/libpng)
SET(ZLIB_INCLUDE_DIR ${MUPDF_3RDPARTY_DIR}/zlib-1.2.5)
#SET(ZLIB_INCLUDE_DIR ${CR_3RDPARTY_DIR}/zlib)
SET(JPEGLIB_INCLUDE_DIR ${MUPDF_3RDPARTY_DIR}/jpeg-8d)
#SET(JPEGLIB_INCLUDE_DIR ${CR_3RDPARTY_DIR}/libjpeg)
SET(JCONFIG_INCLUDE_DIR ${MUPDF_DIR}/scripts)
INCLUDE_DIRECTORIES(
${FREETYPE_INCLUDE_DIRS}
${ANTIWORD_INCLUDE_DIR}
${CHM_INCLUDE_DIRS}
${PNG_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
${JPEGLIB_INCLUDE_DIR}
${JCONFIG_INCLUDE_DIR}
)
ADD_DEFINITIONS(-DUSE_FONTCONFIG=0 -DUSE_FREETYPE=1 -DCR3_PATCH=1 -DNDEBUG=1)
message("Will build patched LIBCHM library")
ADD_DEFINITIONS(-DCHM_SUPPORT_ENABLED=1)
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/chmlib)
message("Will build patched LIBPNG library")
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/libpng)
#message("Will build patched JPEGLIB library")
#ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/libjpeg)
message("Will build patched ANTIWORD library")
ADD_DEFINITIONS(-DENABLE_ANTIWORD=1)
ADD_DEFINITIONS(-DCR3_ANTIWORD_PATCH=1)
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/antiword)
SET(GUI kpv)
#ADD_DEFINITIONS(-DJCONFIG_INCLUDED=1)
ADD_SUBDIRECTORY(crengine/crengine)

@ -0,0 +1 @@
Subproject commit ba469d33473670ca303e2ef7f9762452a86e18b1

@ -0,0 +1,15 @@
--- jcapimin.c 2012-04-04 00:02:30.000000000 +0800
+++ jcapimin-patched.c 2012-04-04 00:02:26.000000000 +0800
@@ -36,9 +36,9 @@
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
if (version != JPEG_LIB_VERSION)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
- if (structsize != SIZEOF(struct jpeg_compress_struct))
- ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
+ /*if (structsize != SIZEOF(struct jpeg_compress_struct))*/
+ /*ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, */
+ /*(int) SIZEOF(struct jpeg_compress_struct), (int) structsize);*/
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set

@ -0,0 +1,15 @@
--- jdapimin.c 2012-04-04 01:09:00.000000000 +0800
+++ jdapimin-patched.c 2012-04-04 01:42:44.000000000 +0800
@@ -36,9 +36,9 @@
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
if (version != JPEG_LIB_VERSION)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
- if (structsize != SIZEOF(struct jpeg_decompress_struct))
- ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
+ /*if (structsize != SIZEOF(struct jpeg_decompress_struct))*/
+ /*ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, */
+ /*(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);*/
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set

@ -1,8 +1,18 @@
#!/bin/sh
SLIDER_EVENT_PIPE="/tmp/event_slider"
export LC_ALL="en_US.UTF-8"
echo unlock > /proc/keypad
echo unlock > /proc/fiveway
cd /mnt/us/kindlepdfviewer/
./reader.lua $1
# create the named pipe for power slider event
if [ ! -p $SLIDER_EVENT_PIPE ]; then
mkfifo $SLIDER_EVENT_PIPE
fi
killall slider_watcher
./slider_watcher $SLIDER_EVENT_PIPE &
./reader.lua $1 2> /mnt/us/kindlepdfviewer/crash.log
killall -cont cvm
echo 1 > /proc/eink_fb/update_display

@ -445,7 +445,7 @@ static const struct luaL_Reg pdfdocument_meth[] = {
{"authenticatePassword", authenticatePassword},
{"openPage", openPage},
{"getPages", getNumberOfPages},
{"getTOC", getTableOfContent},
{"getToc", getTableOfContent},
{"close", closeDocument},
{"getCacheSize", getCacheSize},
{"cleanCache", cleanCache},

@ -20,6 +20,7 @@
require "alt_getopt"
require "pdfreader"
require "djvureader"
require "crereader"
require "filechooser"
require "settings"
require "screen"
@ -42,12 +43,14 @@ function openFile(filename)
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" then
reader = CREReader
end
if reader then
local ok, err = reader:open(filename)
if ok then
reader:loadSettings(filename)
page_num = reader.settings:readSetting("last_page") or 1
page_num = reader:getLastPageOrPos()
reader:goto(tonumber(page_num))
reader_settings:savesetting("lastfile", filename)
return reader:inputLoop()
@ -92,6 +95,7 @@ if optarg["d"] == "k3" then
input.open("/dev/input/event0")
input.open("/dev/input/event1")
input.open("/dev/input/event2")
input.open("/tmp/event_slider")
setK3Keycodes()
elseif optarg["d"] == "emu" then
input.open("")
@ -100,6 +104,7 @@ elseif optarg["d"] == "emu" then
else
input.open("/dev/input/event0")
input.open("/dev/input/event1")
input.open("/tmp/event_slider")
-- check if we are running on Kindle 3 (additional volume input)
local f=lfs.attributes("/dev/input/event2")
@ -119,7 +124,7 @@ fb = einkfb.open("/dev/fb0")
width, height = fb:getSize()
-- read current rotation mode
Screen:updateRotationMode()
origin_rotation_mode = Screen.cur_rotation_mode
Screen.native_rotation_mode = Screen.cur_rotation_mode
-- set up reader's setting: font
reader_settings = DocSettings:open(".reader")
@ -133,6 +138,7 @@ UniReader:initGlobalSettings(reader_settings)
-- initialize specific readers
PDFReader:init()
DJVUReader:init()
CREReader:init()
-- display directory or open file
local patharg = reader_settings:readSetting("lastfile")
@ -167,10 +173,10 @@ reader_settings:close()
-- @TODO dirty workaround, find a way to force native system poll
-- screen orientation and upside down mode 09.03 2012
fb:setOrientation(origin_rotation_mode)
fb:setOrientation(Screen.native_rotation_mode)
input.closeAll()
--os.execute('test -e /proc/keypad && echo "send '..KEY_HOME..'" > /proc/keypad ')
if optarg["d"] ~= "emu" then
--os.execute("killall -cont cvm")
os.execute('echo "send '..KEY_MENU..'" > /proc/keypad;echo "send '..KEY_MENU..'" > /proc/keypad')
end

@ -41,6 +41,9 @@ Codes for rotation modes:
Screen = {
cur_rotation_mode = 0,
-- these two variabls are used to help switching from framework to reader
native_rotation_mode = nil,
kpv_rotation_mode = nil,
}
-- @orien: 1 for clockwise rotate, -1 for anti-clockwise
@ -71,4 +74,3 @@ function Screen:updateRotationMode()
end
end

@ -2,6 +2,7 @@ require "rendertext"
require "keys"
require "graphics"
require "font"
require "commands"
SelectMenu = {
-- font for displaying item names
@ -32,10 +33,14 @@ SelectMenu = {
"Z", "X", "C", "V", "B", "N", "M", ".", "Sym", "Ent",
},
last_shortcut = 0,
-- state buffer
page = 1,
current = 1,
oldcurrent = 0,
selected_item = nil,
commands = nil,
}
function SelectMenu:new(o)
@ -46,10 +51,12 @@ function SelectMenu:new(o)
o.page = 1
o.current = 1
o.oldcurrent = 0
o.selected_item = nil
-- increase spacing for DXG so we don't have more than 30 shortcuts
if fb.bb:getHeight() == 1200 then
o.spacing = 37
end
o:addAllCommands()
return o
end
@ -62,43 +69,164 @@ function SelectMenu:getItemIndexByShortCut(c, perpage)
end
end
--[
-- return the index of selected item
--]
function SelectMenu:choose(ypos, height)
local perpage = math.floor(height / self.spacing) - 2
local pagedirty = true
local 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
function SelectMenu:addAllCommands()
self.commands = Commands:new{}
self.commands:add(KEY_FW_UP, nil, "",
"previous item",
function(sm)
if sm.current == 1 then
if sm.page > 1 then
sm.current = sm.perpage
sm.page = sm.page - 1
sm.pagedirty = true
end
else
sm.current = sm.current - 1
sm.markerdirty = true
end
else
self.current = self.current - 1
markerdirty = true
end
end
end)
self.commands:add(KEY_FW_DOWN, nil, "",
"next item",
function(sm)
if sm.current == sm.perpage then
if sm.page < (sm.items / sm.perpage) then
sm.current = 1
sm.page = sm.page + 1
sm.pagedirty = true
end
else
if sm.page ~= math.floor(sm.items / sm.perpage) + 1
or sm.current + (sm.page - 1) * sm.perpage < sm.items then
sm.current = sm.current + 1
sm.markerdirty = true
end
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
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, "",
"next page",
function(sm)
if sm.page < (sm.items / sm.perpage) then
if sm.current + sm.page * sm.perpage > sm.items then
sm.current = sm.items - sm.page * sm.perpage
end
sm.page = sm.page + 1
sm.pagedirty = true
else
sm.current = sm.items - (sm.page - 1) * sm.perpage
sm.markerdirty = 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)
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "",
"previous page",
function(sm)
if sm.page > 1 then
sm.page = sm.page - 1
sm.pagedirty = true
else
sm.current = 1
sm.markerdirty = true
end
end
end)
self.commands:add(KEY_FW_PRESS, nil, "",
"select menu item",
function(sm)
if sm.last_shortcut < 30 then
if sm.items == 0 then
return "break"
else
self.selected_item = (sm.perpage * (sm.page - 1)
+ sm.current)
end
end
end)
local KEY_Q_to_E = {}
for i = KEY_Q, KEY_P do
table.insert(KEY_Q_to_E, Keydef:new(i, nil, ""))
end
self.commands:addGroup("Q to E", KEY_Q_to_E,
"Select menu item with Q to E key as shortcut",
function(sm, keydef)
sm.selected_item = sm:getItemIndexByShortCut(
sm.item_shortcuts[ keydef.keycode - KEY_Q + 1 ], sm.perpage)
end)
local KEY_A_to_L = {}
for i = KEY_A, KEY_L do
table.insert(KEY_A_to_L, Keydef:new(i, nil, ""))
end
self.commands:addGroup("A to L", KEY_A_to_L,
"Select menu item with A to L key as shortcut",
function(sm, keydef)
sm.selected_item = sm:getItemIndexByShortCut(
sm.item_shortcuts[ keydef.keycode - KEY_A + 11 ], sm.perpage)
end)
local KEY_Z_to_M = {}
for i = KEY_Z, KEY_M do
table.insert(KEY_Z_to_M, Keydef:new(i, nil, ""))
end
self.commands:addGroup("Z to M", KEY_Z_to_M,
"Select menu item with Z to M key as shortcut",
function(sm, keydef)
sm.selected_item = sm:getItemIndexByShortCut(
sm.item_shortcuts[ keydef.keycode - KEY_Z + 21 ], sm.perpage)
end)
self.commands:add(KEY_DEL, nil, "",
"Select menu item with del key as shortcut",
function(sm)
sm.selected_item = sm:getItemIndexByShortCut("Del", sm.perpage)
end)
self.commands:add(KEY_DOT, nil, "",
"Select menu item with dot key as shortcut",
function(sm)
sm.selected_item = sm:getItemIndexByShortCut(".", sm.perpage)
end)
self.commands:add({KEY_SYM, KEY_SLASH}, nil, "",
"Select menu item with sym/slash key as shortcut",
function(sm)
-- DXG has slash after dot
sm.selected_item = sm:getItemIndexByShortCut("Sym", sm.perpage)
end)
self.commands:add(KEY_ENTER, nil, "",
"Select menu item with enter key as shortcut",
function(sm)
sm.selected_item = sm:getItemIndexByShortCut("Ent", sm.perpage)
end)
self.commands:add(KEY_BACK, nil, "",
"Exit menu",
function(sm)
return "break"
end)
end
function SelectMenu:clearCommands()
self.commands = Commands:new{}
self.commands:add(KEY_BACK, nil, "",
"Exit menu",
function(sm)
return "break"
end)
end
------------------------------------------------
-- return the index of selected item
------------------------------------------------
function SelectMenu:choose(ypos, height)
self.perpage = math.floor(height / self.spacing) - 2
self.pagedirty = true
self.markerdirty = false
self.last_shortcut = 0
while true do
@ -106,8 +234,8 @@ function SelectMenu:choose(ypos, height)
local tface, tfhash = Font:getFaceAndHash(25, Font.tfont)
local fface, ffhash = Font:getFaceAndHash(16, Font.ffont)
if pagedirty then
markerdirty = true
if self.pagedirty then
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)
@ -125,11 +253,12 @@ function SelectMenu:choose(ypos, height)
y = y + self.spacing
renderUtf8Text(fb.bb, 30, y, cface, cfhash,
self.no_item_msg, true)
markerdirty = false
self.markerdirty = false
self:clearCommands()
else
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.items then
y = ypos + self.title_H + (self.spacing * c)
@ -153,19 +282,21 @@ function SelectMenu:choose(ypos, height)
renderUtf8Text(fb.bb, 50, y, cface, cfhash,
self.item_array[i], true)
end
end
end
end -- EOF if i <= self.items
end -- EOF for
end -- EOF if
-- draw footer
y = ypos + self.title_H + (self.spacing * perpage) + self.foot_H + 5
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, ffhash,
"Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true)
"Page "..self.page.." of "..
(math.ceil(self.items / self.perpage)), true)
end
if markerdirty then
if not pagedirty then
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)
@ -175,72 +306,41 @@ function SelectMenu:choose(ypos, height)
-- 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)
if not pagedirty then
if not self.pagedirty then
fb:refresh(1, 45, y, fb.bb:getWidth() - 60, 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.waitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
local selected = nil
if ev.code == KEY_FW_UP then
prevItem()
elseif ev.code == KEY_FW_DOWN then
nextItem()
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
pagedirty = true
else
self.current = self.items - (self.page-1)*perpage
markerdirty = true
end
elseif ev.code == KEY_PGBCK or ev.code == KEY_LPGBCK then
if self.page > 1 then
self.page = self.page - 1
pagedirty = true
else
self.current = 1
markerdirty = true
end
elseif ev.code == KEY_FW_PRESS or ev.code == KEY_ENTER and self.last_shortcut < 30 then
if self.items == 0 then
return nil
else
return (perpage*(self.page-1) + self.current)
end
elseif ev.code >= KEY_Q and ev.code <= KEY_P then
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_Q + 1 ], perpage)
elseif ev.code >= KEY_A and ev.code <= KEY_L then
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_A + 11], perpage)
elseif ev.code >= KEY_Z and ev.code <= KEY_M then
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_Z + 21], perpage)
elseif ev.code == KEY_DEL then
selected = self:getItemIndexByShortCut("Del", perpage)
elseif ev.code == KEY_DOT then
selected = self:getItemIndexByShortCut(".", perpage)
elseif ev.code == KEY_SYM or ev.code == KEY_SLASH then -- DXG has slash after dot
selected = self:getItemIndexByShortCut("Sym", perpage)
elseif ev.code == KEY_ENTER then
selected = self:getItemIndexByShortCut("Ent", perpage)
elseif ev.code == KEY_BACK then
return nil
keydef = Keydef:new(ev.code, getKeyModifier())
print("key pressed: "..tostring(keydef))
command = self.commands:getByKeydef(keydef)
if command ~= nil then
print("command to execute: "..tostring(command))
ret_code = command.func(self, keydef)
else
print("command not found: "..tostring(command))
end
if selected ~= nil then
print("# selected "..selected)
return selected
if ret_code == "break" then
break
end
end
end
if self.selected_item ~= nil then
print("# selected "..self.selected_item)
return self.selected_item
end
end -- EOF if
end -- EOF while
return nil
end

@ -0,0 +1,87 @@
/*
KindlePDFViewer: power slider key event watcher
Copyright (C) 2012 Qingping Hou <dave2008713@gamil.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#define OUTPUT_SIZE 21
#define EVENT_PIPE "/tmp/event_slider"
#define CODE_IN_SAVER 10000
#define CODE_OUT_SAVER 10001
int
main ( int argc, char *argv[] )
{
int fd, ret;
FILE *fp;
char std_out[OUTPUT_SIZE] = "";
struct input_event ev;
__u16 key_code = 10000;
/* create the npipe if not exists */
/*if(access(argv[1], F_OK)){*/
/*printf("npipe %s not found, try to create it...\n", argv[1]);*/
/*if(mkfifo(argv[1], 0777)) {*/
/*printf("Create npipe %s failed!\n", argv[1]);*/
/*}*/
/*}*/
/* open npipe for writing */
fd = open(argv[1], O_RDWR | O_NONBLOCK);
if(fd < 0) {
printf("Open %s falied: %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
/* initialize event struct */
ev.type = EV_KEY;
ev.code = key_code;
ev.value = 1;
while(1) {
/* listen power slider events */
memset(std_out, 0, OUTPUT_SIZE);
fp = popen("lipc-wait-event -s 0 com.lab126.powerd goingToScreenSaver,outOfScreenSaver", "r");
ret = fread(std_out, OUTPUT_SIZE, 1, fp);
pclose(fp);
/* fill event struct */
gettimeofday(&ev.time, NULL);
if(std_out[0] == 'g') {
ev.code = CODE_IN_SAVER;
} else if(std_out[0] == 'o') {
ev.code = CODE_OUT_SAVER;
} else {
printf("Unrecognized event.\n");
exit(EXIT_FAILURE);
}
/* generate event */
ret = write(fd, &ev, sizeof(struct input_event));
}
close(fd);
return EXIT_SUCCESS;
}

@ -94,22 +94,23 @@ end
-- !!!!!!!!!!!!!!!!!!!!!!!!!
--
-- For a new specific reader,
-- you must always overwrite following two methods:
-- you must always overwrite following method:
--
-- * self:open()
-- * self:init()
--
-- overwrite other methods if needed.
----------------------------------------------------
function UniReader:init()
end
-- open a file and its settings store
-- tips: you can use self:loadSettings in open() method.
-- open a file
function UniReader:open(filename, cache_size)
return false
end
function UniReader:init()
-- initialize commands
self:addAllCommands()
end
----------------------------------------------------
-- You need to overwrite following two methods if your
-- reader supports highlight feature.
@ -128,7 +129,7 @@ function UniReader:toggleTextHighLight(word_list)
end
----------------------------------------------------
-- renderer memory
-- Renderer memory
----------------------------------------------------
function UniReader:getCacheSize()
@ -139,9 +140,46 @@ function UniReader:cleanCache()
return
end
----------------------------------------------------
-- Setting related methods
----------------------------------------------------
-- load special settings for specific reader
function UniReader:loadSpecialSettings()
return
end
-- save special settings for specific reader
function UniReader:saveSpecialSettings()
end
--[ following are default methods ]--
function UniReader:initGlobalSettings(settings)
local pan_overlap_vertical = settings:readSetting("pan_overlap_vertical")
if pan_overlap_vertical then
self.pan_overlap_vertical = pan_overlap_vertical
end
local cache_max_memsize = settings:readSetting("cache_max_memsize")
if cache_max_memsize then
self.cache_max_memsize = cache_max_memsize
end
local cache_max_ttl = settings:readSetting("cache_max_ttl")
if cache_max_ttl then
self.cache_max_ttl = cache_max_ttl
end
local rcountmax = settings:readSetting("partial_refresh_count")
if rcountmax then
self.rcountmax = rcountmax
end
end
-- This is a low-level method that can be shared with all readers.
function UniReader:loadSettings(filename)
if self.doc ~= nil then
self.settings = DocSettings:open(filename,self.cache_document_size)
@ -164,33 +202,18 @@ function UniReader:loadSettings(filename)
self.globalzoom = self.settings:readSetting("globalzoom") or 1.0
self.globalzoommode = self.settings:readSetting("globalzoommode") or -1
self:loadSpecialSettings()
return true
end
return false
end
function UniReader:initGlobalSettings(settings)
local pan_overlap_vertical = settings:readSetting("pan_overlap_vertical")
if pan_overlap_vertical then
self.pan_overlap_vertical = pan_overlap_vertical
end
-- initialize commands
self:addAllCommands()
local cache_max_memsize = settings:readSetting("cache_max_memsize")
if cache_max_memsize then
self.cache_max_memsize = cache_max_memsize
end
local cache_max_ttl = settings:readSetting("cache_max_ttl")
if cache_max_ttl then
self.cache_max_ttl = cache_max_ttl
end
function UniReader:getLastPageOrPos()
return self.settings:readSetting("last_page") or 1
end
local rcountmax = settings:readSetting("partial_refresh_count")
if rcountmax then
self.rcountmax = rcountmax
end
function UniReader:saveLastPageOrPos()
self.settings:savesetting("last_page", self.pageno)
end
-- guarantee that we have enough memory in cache
@ -282,7 +305,7 @@ function UniReader:drawOrCache(no, preCache)
tile.y = 0
tile.w = self.fullwidth
tile.h = self.fullheight
elseif (tile.w*tile.h / 2) > max_cache then
elseif (tile.w*tile.h / 2) < max_cache then
-- no, we can't. so generate a tile as big as we can go
-- grow area in steps of 10px
while ((tile.w+10) * (tile.h+10) / 2) < max_cache do
@ -297,7 +320,7 @@ function UniReader:drawOrCache(no, preCache)
tile.y = tile.y - 5
tile.h = tile.h + 5
end
if tile.y + tile.h < self.fullheigth then
if tile.y + tile.h < self.fullheight then
tile.h = tile.h + 5
end
end
@ -347,6 +370,8 @@ function UniReader:setzoom(page, preCache)
x1 = pwidth
y1 = pheight
end
if x1 == 0 then x1 = pwidth end
if y1 == 0 then y1 = pheight end
-- clamp to page BBox
if x0 < 0 then x0 = 0 end
if x1 > pwidth then x1 = pwidth end
@ -540,27 +565,32 @@ function UniReader:show(no)
self.slot_visible = slot;
end
function UniReader:isSamePage(p1, p2)
return p1 == p2
end
--[[
@ pageno is the page you want to add to jump_stack
NOTE: for CREReader, pageno refers to xpointer
--]]
function UniReader:addJump(pageno, notes)
local jump_item = nil
local notes_to_add = notes
if not notes_to_add then
-- no notes given, auto generate from TOC entry
notes_to_add = self:getTOCTitleByPage(self.pageno)
-- no notes given, auto generate from Toc entry
notes_to_add = self:getTocTitleOfCurrentPage()
if notes_to_add ~= "" then
notes_to_add = "in "..notes_to_add
end
end
-- move pageno page to jump_stack top if already in
for _t,_v in ipairs(self.jump_stack) do
if _v.page == pageno then
if self:isSamePage(_v.page, pageno) then
jump_item = _v
table.remove(self.jump_stack, _t)
-- if original notes is not empty, probably defined by users,
-- we use the original notes to overwrite auto generated notes
-- from TOC entry
-- from Toc entry
if jump_item.notes ~= "" then
notes_to_add = jump_item.notes
end
@ -618,6 +648,10 @@ function UniReader:goto(no)
end
end
function UniReader:redrawCurrentPage()
self:goto(self.pageno)
end
function UniReader:nextView()
local pageno = self.pageno
@ -673,14 +707,14 @@ end
function UniReader:modifyGamma(factor)
print("modifyGamma, gamma="..self.globalgamma.." factor="..factor)
self.globalgamma = self.globalgamma * factor;
self:goto(self.pageno)
self:redrawCurrentPage()
end
-- adjust zoom state and trigger re-rendering
function UniReader:setGlobalZoomMode(newzoommode)
if self.globalzoommode ~= newzoommode then
self.globalzoommode = newzoommode
self:goto(self.pageno)
self:redrawCurrentPage()
end
end
@ -689,13 +723,13 @@ function UniReader:setGlobalZoom(zoom)
if self.globalzoom ~= zoom then
self.globalzoommode = self.ZOOM_BY_VALUE
self.globalzoom = zoom
self:goto(self.pageno)
self:redrawCurrentPage()
end
end
function UniReader:setRotate(rotate)
self.globalrotate = rotate
self:goto(self.pageno)
self:redrawCurrentPage()
end
-- @ orien: 1 for clockwise rotate, -1 for anti-clockwise
@ -703,21 +737,21 @@ function UniReader:screenRotate(orien)
Screen:screenRotate(orien)
width, height = fb:getSize()
self:clearCache()
self:goto(self.pageno)
self:redrawCurrentPage()
end
function UniReader:cleanUpTOCTitle(title)
function UniReader:cleanUpTocTitle(title)
return title:gsub("\13", "")
end
function UniReader:fillTOC()
self.toc = self.doc:getTOC()
function UniReader:fillToc()
self.toc = self.doc:getToc()
end
function UniReader:getTOCTitleByPage(pageno)
function UniReader:getTocTitleByPage(pageno)
if not self.toc then
-- build toc when needed.
self:fillTOC()
self:fillToc()
end
-- no table of content
@ -732,32 +766,41 @@ function UniReader:getTOCTitleByPage(pageno)
end
pre_entry = _v
end
return self:cleanUpTOCTitle(pre_entry.title)
return self:cleanUpTocTitle(pre_entry.title)
end
function UniReader:showTOC()
function UniReader:getTocTitleOfCurrentPage()
return self:getTocTitleByPage(self.pageno)
end
function UniReader:gotoTocEntry(entry)
self:goto(entry.page)
end
function UniReader:showToc()
if not self.toc then
-- build toc when needed.
self:fillTOC()
-- build toc if needed.
self:fillToc()
end
local menu_items = {}
local filtered_toc = {}
-- build menu items
local menu_items = {}
for k,v in ipairs(self.toc) do
table.insert(menu_items,
(" "):rep(v.depth-1)..self:cleanUpTOCTitle(v.title))
table.insert(filtered_toc,v.page)
(" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title))
end
toc_menu = SelectMenu:new{
menu_title = "Table of Contents",
item_array = menu_items,
no_item_msg = "This document does not have a Table of Contents.",
}
item_no = toc_menu:choose(0, fb.bb:getHeight())
if item_no then
self:goto(filtered_toc[item_no])
self:gotoTocEntry(self.toc[item_no])
else
self:goto(self.pageno)
self:redrawCurrentPage()
end
end
@ -777,7 +820,7 @@ function UniReader:showJumpStack()
local jump_item = self.jump_stack[item_no]
self:goto(jump_item.page)
else
self:goto(self.pageno)
self:redrawCurrentPage()
end
end
@ -804,7 +847,9 @@ function UniReader:showHighLight()
end
end
function UniReader:showMenu()
-- used in UniReader:showMenu()
function UniReader:_drawReadingInfo()
local ypos = height - 50
local load_percent = (self.pageno / self.doc:getPages())
local face, fhash = Font:getFaceAndHash(22)
@ -820,7 +865,7 @@ function UniReader:showMenu()
local ypos = height - 50
fb.bb:paintRect(0, ypos, width, 50, 0)
ypos = ypos + 15
local cur_section = self:getTOCTitleByPage(self.pageno)
local cur_section = self:getTocTitleOfCurrentPage()
if cur_section ~= "" then
cur_section = "Section: "..cur_section
end
@ -831,6 +876,10 @@ function UniReader:showMenu()
ypos = ypos + 15
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
5, 4, load_percent, 8)
end
function UniReader:showMenu()
self:_drawReadingInfo()
fb:refresh(1)
while 1 do
@ -889,13 +938,14 @@ function UniReader:inputLoop()
self.doc:close()
end
if self.settings ~= nil then
self.settings:savesetting("last_page", self.pageno)
self:saveLastPageOrPos()
self.settings:savesetting("gamma", self.globalgamma)
self.settings:savesetting("jumpstack", self.jump_stack)
self.settings:savesetting("bbox", self.bbox)
self.settings:savesetting("globalzoom", self.globalzoom)
self.settings:savesetting("globalzoommode", self.globalzoommode)
self.settings:savesetting("highlight", self.highlight)
self:saveSpecialSettings()
self.settings:close()
end
@ -1025,12 +1075,12 @@ function UniReader:addAllCommands()
"show help page",
function(unireader)
HelpPage:show(0,height,unireader.commands)
unireader:goto(unireader.pageno)
unireader:redrawCurrentPage()
end)
self.commands:add(KEY_T,nil,"T",
"show table of content",
function(unireader)
unireader:showTOC()
unireader:showToc()
end)
self.commands:add(KEY_B,nil,"B",
"show jump stack",
@ -1062,18 +1112,6 @@ function UniReader:addAllCommands()
function(unireader)
unireader:screenRotate("anticlockwise")
end)
self.commands:add(KEY_N, nil, "N",
"start highlight mode",
function(unireader)
unireader:startHighLightMode()
unireader:goto(unireader.pageno)
end)
self.commands:add(KEY_N, MOD_SHIFT, "N",
"display all highlights",
function(unireader)
unireader:showHighLight()
unireader:goto(unireader.pageno)
end)
self.commands:add(KEY_R, MOD_SHIFT, "R",
"manual full screen refresh",
function(unireader)
@ -1118,7 +1156,7 @@ function UniReader:addAllCommands()
"open menu",
function(unireader)
unireader:showMenu()
unireader:goto(unireader.pageno)
unireader:redrawCurrentPage()
end)
-- panning
local panning_keys = {Keydef:new(KEY_FW_LEFT,MOD_ANY),Keydef:new(KEY_FW_RIGHT,MOD_ANY),Keydef:new(KEY_FW_UP,MOD_ANY),Keydef:new(KEY_FW_DOWN,MOD_ANY),Keydef:new(KEY_FW_PRESS,MOD_ANY)}
@ -1206,10 +1244,25 @@ function UniReader:addAllCommands()
end
if old_offset_x ~= unireader.offset_x
or old_offset_y ~= unireader.offset_y then
unireader:goto(unireader.pageno)
unireader:redrawCurrentPage()
end
end
end)
-- end panning
self.commands:add(KEY_INTO_SCREEN_SAVER,nil,"slider",
"toggle screen saver",
function(unireader)
Screen.kpv_rotation_mode = Screen.cur_rotation_mode
fb:setOrientation(Screen.native_rotation_mode)
os.execute("killall -cont cvm")
end)
self.commands:add(KEY_OUTOF_SCREEN_SAVER,nil,"slider",
"toggle screen saver",
function(unireader)
os.execute("sleep 1")
os.execute("killall -stop cvm")
fb:setOrientation(Screen.kpv_rotation_mode)
unireader:redrawCurrentPage()
end)
print("## defined commands "..dump(self.commands.map))
end

Loading…
Cancel
Save