1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 10:49:24 +02:00

bookmarks improvements

mobipocket support (in progress)
misc fixes


git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@967 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
Nikolay Pultsin 2009-05-06 11:37:36 +00:00
parent b346321526
commit 1f14fd2b58
57 changed files with 897 additions and 1242 deletions

View file

@ -221,10 +221,14 @@
</group> </group>
<group name="Unicode"> <group name="Unicode">
<encoding region="Unicode" name="UTF-8"> <encoding region="Unicode" name="UTF-8">
<code number="65001"/>
</encoding> </encoding>
<encoding region="Unicode" name="UTF-7"> <encoding region="Unicode" name="UTF-7">
<code number="65000"/>
</encoding> </encoding>
<encoding region="Unicode" name="UTF-16"> <encoding region="Unicode" name="UTF-16">
</encoding> </encoding>
<encoding region="Unicode" name="UTF-16BE">
</encoding>
</group> </group>
</known-encodings> </known-encodings>

View file

@ -50,6 +50,7 @@
<data android:pathPattern=".*\\.epub" /> <data android:pathPattern=".*\\.epub" />
<data android:pathPattern=".*\\.oeb" /> <data android:pathPattern=".*\\.oeb" />
<data android:pathPattern=".*\\.fb2" /> <data android:pathPattern=".*\\.fb2" />
<data android:pathPattern=".*\\.mobi" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 B

View file

@ -12,14 +12,33 @@
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:singleLine="true" android:singleLine="true"
/> />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="5dip"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:orientation="vertical"
android:gravity="center_vertical|left"
>
<TextView <TextView
android:id="@+id/bookmark_item_text" android:id="@+id/bookmark_item_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="wrap_content"
android:layout_marginLeft="5dip" android:layout_alignParentTop="true"
android:layout_marginTop="5dip" android:singleLine="false"
android:layout_marginBottom="5dip"
android:gravity="center_vertical|left"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical|left"
/> />
<TextView
android:id="@+id/bookmark_item_booktitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dip"
android:layout_below="@id/bookmark_item_text"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -13,7 +13,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="5dip" android:paddingTop="5dip"
/> />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"

View file

@ -68,7 +68,8 @@ public class BookDownloader extends Activity {
ourFileName = path.get(path.size() - 1); ourFileName = path.get(path.size() - 1);
if (!ourFileName.endsWith(".fb2.zip") && if (!ourFileName.endsWith(".fb2.zip") &&
!ourFileName.endsWith(".fb2") && !ourFileName.endsWith(".fb2") &&
!ourFileName.endsWith(".epub")) { !ourFileName.endsWith(".epub") &&
!ourFileName.endsWith(".mobi")) {
startNextMatchingActivity(intent); startNextMatchingActivity(intent);
finish(); finish();
return; return;
@ -126,6 +127,10 @@ public class BookDownloader extends Activity {
private void runFBReader(final File file) { private void runFBReader(final File file) {
finish(); finish();
final Activity oldActivity = org.geometerplus.android.fbreader.FBReader.Instance;
if (oldActivity != null) {
oldActivity.finish();
}
startActivity(new Intent(Intent.ACTION_VIEW, Uri.fromFile(file), this, FBReader.class)); startActivity(new Intent(Intent.ACTION_VIEW, Uri.fromFile(file), this, FBReader.class));
} }

View file

@ -28,16 +28,27 @@ import android.content.Context;
import org.geometerplus.zlibrary.ui.android.R; import org.geometerplus.zlibrary.ui.android.R;
class SimpleContainer extends ViewGroup { class SimpleContainer extends ViewGroup {
private final View myChild; private final View myEditText;
private final Button myOkButton;
private final Button myCancelButton;
SimpleContainer(Context context, View child) { SimpleContainer(Context context) {
super(context); super(context);
myChild = child; myEditText = new EditText(context);
addView(child); myOkButton = new Button(context);
myOkButton.setText("ok");
myCancelButton = new Button(context);
myCancelButton.setText("cancel");
addView(myOkButton);
addView(myCancelButton);
addView(myEditText);
} }
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
myChild.layout(left + 5, top + 5, right - 5, bottom - 5); final int buttonHeight = Math.max(54, Math.max(myOkButton.getHeight(), myCancelButton.getHeight()));
myEditText.layout(left + 8, top + 8, right - 8, bottom - buttonHeight - 16);
myOkButton.layout(left + 8, bottom - buttonHeight - 8, (left + right) / 2 - 4, bottom - 8);
myCancelButton.layout((left + right) / 2 + 4, bottom - buttonHeight - 8, right - 8, bottom - 8);
} }
} }
@ -46,21 +57,7 @@ public class BookmarkEditActivity extends Activity {
public void onCreate(Bundle bundle) { public void onCreate(Bundle bundle) {
super.onCreate(bundle); super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_NO_TITLE);
final LinearLayout v = new LinearLayout(this); final SimpleContainer container = new SimpleContainer(this);
v.setOrientation(LinearLayout.VERTICAL);
v.addView(new EditText(this));
/*
final LinearLayout h = new LinearLayout(this);
v.addView(h);
final Button okButton = new Button(this);
okButton.setText("ok");
h.addView(okButton);
final Button cancelButton = new Button(this);
cancelButton.setText("cancel");
h.addView(cancelButton);
*/
final SimpleContainer container = new SimpleContainer(this, v);
//final SimpleContainer container = new SimpleContainer(this, new EditText(this));
setContentView(container); setContentView(container);
} }
} }

View file

@ -74,7 +74,10 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte
AllBooksBookmarks = Bookmark.bookmarks(); AllBooksBookmarks = Bookmark.bookmarks();
Collections.sort(AllBooksBookmarks, new Bookmark.ByTimeComparator()); Collections.sort(AllBooksBookmarks, new Bookmark.ByTimeComparator());
final long bookId = ((FBReader)FBReader.Instance()).Model.Book.getId(); final FBReader fbreader = (FBReader)FBReader.Instance();
if (fbreader.Model != null) {
final long bookId = fbreader.Model.Book.getId();
for (Bookmark bookmark : AllBooksBookmarks) { for (Bookmark bookmark : AllBooksBookmarks) {
if (bookmark.getBookId() == bookId) { if (bookmark.getBookId() == bookId) {
myThisBookBookmarks.add(bookmark); myThisBookBookmarks.add(bookmark);
@ -83,6 +86,9 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte
myThisBookView = createTab("thisBook", R.id.this_book); myThisBookView = createTab("thisBook", R.id.this_book);
new BookmarksAdapter(myThisBookView, myThisBookBookmarks, true); new BookmarksAdapter(myThisBookView, myThisBookBookmarks, true);
} else {
findViewById(R.id.this_book).setVisibility(View.GONE);
}
myAllBooksView = createTab("allBooks", R.id.all_books); myAllBooksView = createTab("allBooks", R.id.all_books);
new BookmarksAdapter(myAllBooksView, AllBooksBookmarks, false); new BookmarksAdapter(myAllBooksView, AllBooksBookmarks, false);
@ -196,25 +202,52 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte
final ZLTextPosition position = new ZLTextPosition(cursor); final ZLTextPosition position = new ZLTextPosition(cursor);
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
int wordCounter = 0; final StringBuilder sentenceBuilder = new StringBuilder();
cursor = new ZLTextWordCursor(cursor); cursor = new ZLTextWordCursor(cursor);
int wordCounter = 0;
int sentenceCounter = 0;
int storedWordCounter = 0;
boolean lineIsNonEmpty = false;
mainLoop: mainLoop:
do { while ((wordCounter < 20) && (sentenceCounter < 3)) {
for (; !cursor.isEndOfParagraph(); cursor.nextWord()) { while (cursor.isEndOfParagraph()) {
if (!cursor.nextParagraph()) {
break mainLoop;
}
if (sentenceBuilder.length() > 0) {
builder.append(sentenceBuilder);
builder.append("\n");
sentenceBuilder.delete(0, sentenceBuilder.length());
++sentenceCounter;
storedWordCounter = wordCounter;
lineIsNonEmpty = false;
}
}
final ZLTextElement element = cursor.getElement(); final ZLTextElement element = cursor.getElement();
if (element instanceof ZLTextWord) { if (element instanceof ZLTextWord) {
final ZLTextWord word = (ZLTextWord)element; final ZLTextWord word = (ZLTextWord)element;
if (builder.length() > 0) { if (lineIsNonEmpty) {
builder.append(" "); sentenceBuilder.append(" ");
} }
builder.append(word.Data, word.Offset, word.Length); sentenceBuilder.append(word.Data, word.Offset, word.Length);
if (++wordCounter >= 10) { ++wordCounter;
break mainLoop; lineIsNonEmpty = true;
switch (word.Data[word.Offset + word.Length - 1]) {
case '.':
case '!':
case '?':
builder.append(sentenceBuilder);
sentenceBuilder.delete(0, sentenceBuilder.length());
++sentenceCounter;
storedWordCounter = wordCounter;
} }
} }
cursor.nextWord();
}
if (storedWordCounter < 4) {
builder.append(sentenceBuilder);
} }
} while ((builder.length() == 0) && cursor.nextParagraph());
// TODO: text edit dialog // TODO: text edit dialog
final Bookmark bookmark = new Bookmark(fbreader.Model.Book, builder.toString(), position); final Bookmark bookmark = new Bookmark(fbreader.Model.Book, builder.toString(), position);
@ -227,7 +260,7 @@ mainLoop:
bookmark.onOpen(); bookmark.onOpen();
final FBReader fbreader = (FBReader)FBReader.Instance(); final FBReader fbreader = (FBReader)FBReader.Instance();
final long bookId = bookmark.getBookId(); final long bookId = bookmark.getBookId();
if (fbreader.Model.Book.getId() != bookId) { if ((fbreader.Model == null) || (fbreader.Model.Book.getId() != bookId)) {
final Book book = Book.getById(bookId); final Book book = Book.getById(bookId);
if (book != null) { if (book != null) {
finish(); finish();
@ -247,11 +280,11 @@ mainLoop:
private final class BookmarksAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener { private final class BookmarksAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener {
private final List<Bookmark> myBookmarks; private final List<Bookmark> myBookmarks;
private final boolean myShowAddBookmarkButton; private final boolean myCurrentBook;
BookmarksAdapter(ListView listView, List<Bookmark> bookmarks, boolean showAddBookmarkButton) { BookmarksAdapter(ListView listView, List<Bookmark> bookmarks, boolean currentBook) {
myBookmarks = bookmarks; myBookmarks = bookmarks;
myShowAddBookmarkButton = showAddBookmarkButton; myCurrentBook = currentBook;
listView.setAdapter(this); listView.setAdapter(this);
listView.setOnItemClickListener(this); listView.setOnItemClickListener(this);
listView.setOnCreateContextMenuListener(this); listView.setOnCreateContextMenuListener(this);
@ -259,11 +292,11 @@ mainLoop:
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position; final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
if (position > 0) { if (getItem(position) != null) {
menu.setHeaderTitle(getItem(position).getText()); menu.setHeaderTitle(getItem(position).getText());
final ZLResource resource = ZLResource.resource("bookmarksView"); final ZLResource resource = ZLResource.resource("bookmarksView");
menu.add(0, OPEN_ITEM_ID, 0, resource.getResource("open").getValue()); menu.add(0, OPEN_ITEM_ID, 0, resource.getResource("open").getValue());
menu.add(0, EDIT_ITEM_ID, 0, resource.getResource("edit").getValue()); //menu.add(0, EDIT_ITEM_ID, 0, resource.getResource("edit").getValue());
menu.add(0, DELETE_ITEM_ID, 0, resource.getResource("delete").getValue()); menu.add(0, DELETE_ITEM_ID, 0, resource.getResource("delete").getValue());
} }
} }
@ -271,7 +304,27 @@ mainLoop:
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
final View view = (convertView != null) ? convertView : final View view = (convertView != null) ? convertView :
LayoutInflater.from(parent.getContext()).inflate(R.layout.bookmark_item, parent, false); LayoutInflater.from(parent.getContext()).inflate(R.layout.bookmark_item, parent, false);
final ImageView imageView = (ImageView)view.findViewById(R.id.bookmark_item_icon);
final TextView textView = (TextView)view.findViewById(R.id.bookmark_item_text);
final TextView bookTitleView = (TextView)view.findViewById(R.id.bookmark_item_booktitle);
final Bookmark bookmark = getItem(position); final Bookmark bookmark = getItem(position);
if (bookmark == null) {
imageView.setVisibility(View.VISIBLE);
imageView.setImageResource(R.drawable.tree_icon_plus);
textView.setText(ZLResource.resource("bookmarksView").getResource("new").getValue());
bookTitleView.setVisibility(View.GONE);
} else {
imageView.setVisibility(View.GONE);
textView.setText(bookmark.getText());
if (myCurrentBook) {
bookTitleView.setVisibility(View.GONE);
} else {
bookTitleView.setVisibility(View.VISIBLE);
bookTitleView.setText(bookmark.getBookTitle());
}
}
/*
((ImageView)view.findViewById(R.id.bookmark_item_icon)).setImageResource( ((ImageView)view.findViewById(R.id.bookmark_item_icon)).setImageResource(
(bookmark != null) ? R.drawable.tree_icon_strut : R.drawable.tree_icon_plus (bookmark != null) ? R.drawable.tree_icon_strut : R.drawable.tree_icon_plus
); );
@ -280,6 +333,7 @@ mainLoop:
bookmark.getText() : bookmark.getText() :
ZLResource.resource("bookmarksView").getResource("new").getValue() ZLResource.resource("bookmarksView").getResource("new").getValue()
); );
*/
return view; return view;
} }
@ -296,14 +350,14 @@ mainLoop:
} }
public final Bookmark getItem(int position) { public final Bookmark getItem(int position) {
if (myShowAddBookmarkButton) { if (myCurrentBook) {
--position; --position;
} }
return (position >= 0) ? myBookmarks.get(position) : null; return (position >= 0) ? myBookmarks.get(position) : null;
} }
public final int getCount() { public final int getCount() {
return myShowAddBookmarkButton ? myBookmarks.size() + 1 : myBookmarks.size(); return myCurrentBook ? myBookmarks.size() + 1 : myBookmarks.size();
} }
public final void onItemClick(AdapterView parent, View view, int position, long id) { public final void onItemClick(AdapterView parent, View view, int position, long id) {

View file

@ -54,9 +54,9 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
final TabHost host = getTabHost(); final TabHost host = getTabHost();
LayoutInflater.from(this).inflate(R.layout.library, host.getTabContentView(), true); LayoutInflater.from(this).inflate(R.layout.library, host.getTabContentView(), true);
new LibraryAdapter(createTab("byAuthor", R.id.by_author), Library.Instance().byAuthor()); new LibraryAdapter(createTab("byAuthor", R.id.by_author), Library.Instance().byAuthor(), false);
new LibraryAdapter(createTab("byTag", R.id.by_tag), Library.Instance().byTag()); new LibraryAdapter(createTab("byTag", R.id.by_tag), Library.Instance().byTag(), false);
new LibraryAdapter(createTab("recent", R.id.recent), Library.Instance().recentBooks()); new LibraryAdapter(createTab("recent", R.id.recent), Library.Instance().recentBooks(), true);
findViewById(R.id.search_results).setVisibility(View.GONE); findViewById(R.id.search_results).setVisibility(View.GONE);
host.setCurrentTabByTag(mySelectedTabOption.getValue()); host.setCurrentTabByTag(mySelectedTabOption.getValue());
@ -66,7 +66,7 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
void showSearchResultsTab(LibraryTree tree) { void showSearchResultsTab(LibraryTree tree) {
if (mySearchResultsAdapter == null) { if (mySearchResultsAdapter == null) {
mySearchResultsAdapter = mySearchResultsAdapter =
new LibraryAdapter(createTab("searchResults", R.id.search_results), tree); new LibraryAdapter(createTab("searchResults", R.id.search_results), tree, true);
} else { } else {
mySearchResultsAdapter.resetTree(tree); mySearchResultsAdapter.resetTree(tree);
} }
@ -125,17 +125,24 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
private final class LibraryAdapter extends ZLTreeAdapter { private final class LibraryAdapter extends ZLTreeAdapter {
private final LibraryTree myLibraryTree; private final LibraryTree myLibraryTree;
private final boolean myIsFlat;
LibraryAdapter(ListView view, LibraryTree tree) { LibraryAdapter(ListView view, LibraryTree tree, boolean isFlat) {
super(view, tree); super(view, tree);
myLibraryTree = tree; myLibraryTree = tree;
myIsFlat = isFlat;
} }
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
final View view = (convertView != null) ? convertView : final View view = (convertView != null) ? convertView :
LayoutInflater.from(parent.getContext()).inflate(R.layout.library_tree_item, parent, false); LayoutInflater.from(parent.getContext()).inflate(R.layout.library_tree_item, parent, false);
final LibraryTree tree = (LibraryTree)getItem(position); final LibraryTree tree = (LibraryTree)getItem(position);
setIcon((ImageView)view.findViewById(R.id.library_tree_item_icon), tree); final ImageView iconView = (ImageView)view.findViewById(R.id.library_tree_item_icon);
if (myIsFlat) {
iconView.setVisibility(View.GONE);
} else {
setIcon(iconView, tree);
}
((TextView)view.findViewById(R.id.library_tree_item_name)).setText(tree.getName()); ((TextView)view.findViewById(R.id.library_tree_item_name)).setText(tree.getName());
((TextView)view.findViewById(R.id.library_tree_item_childrenlist)).setText(tree.getSecondString()); ((TextView)view.findViewById(R.id.library_tree_item_childrenlist)).setText(tree.getSecondString());
return view; return view;
@ -147,7 +154,10 @@ public class LibraryTabActivity extends TabActivity implements MenuItem.OnMenuIt
} }
finish(); finish();
final FBReader fbreader = (FBReader)FBReader.Instance(); final FBReader fbreader = (FBReader)FBReader.Instance();
fbreader.openBook(((BookTree)tree).Book, null); final Book book = ((BookTree)tree).Book;
if ((fbreader.Model == null) || (fbreader.Model.Book.getId() != book.getId())) {
fbreader.openBook(book, null);
}
return true; return true;
} }
} }

View file

@ -30,6 +30,8 @@ import android.database.Cursor;
import org.geometerplus.zlibrary.core.filesystem.ZLFile; import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.dialogs.ZLDialogManager; import org.geometerplus.zlibrary.core.dialogs.ZLDialogManager;
import org.geometerplus.zlibrary.core.options.ZLStringOption; import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.zlibrary.core.options.ZLIntegerOption;
import org.geometerplus.zlibrary.core.config.ZLConfig;
import org.geometerplus.zlibrary.text.view.ZLTextPosition; import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication; import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication;
@ -43,6 +45,16 @@ final class SQLiteBooksDatabase extends BooksDatabase {
migrate(); migrate();
} }
protected void executeAsATransaction(Runnable actions) {
myDatabase.beginTransaction();
try {
actions.run();
myDatabase.setTransactionSuccessful();
} finally {
myDatabase.endTransaction();
}
}
private void migrate() { private void migrate() {
final int version = myDatabase.getVersion(); final int version = myDatabase.getVersion();
if (version >= 6) { if (version >= 6) {
@ -77,16 +89,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
}); });
} }
protected void executeAsATransaction(Runnable actions) {
myDatabase.beginTransaction();
try {
actions.run();
myDatabase.setTransactionSuccessful();
} finally {
myDatabase.endTransaction();
}
}
private static void bindString(SQLiteStatement statement, int index, String value) { private static void bindString(SQLiteStatement statement, int index, String value) {
if (value != null) { if (value != null) {
statement.bindString(index, value); statement.bindString(index, value);
@ -484,6 +486,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myDatabase.delete("BookSeries", myBookIdWhereClause, parameters); myDatabase.delete("BookSeries", myBookIdWhereClause, parameters);
myDatabase.delete("BookTag", myBookIdWhereClause, parameters); myDatabase.delete("BookTag", myBookIdWhereClause, parameters);
myDatabase.delete("Bookmarks", myBookIdWhereClause, parameters); myDatabase.delete("Bookmarks", myBookIdWhereClause, parameters);
myDatabase.delete("BookState", myBookIdWhereClause, parameters);
} }
}); });
} }
@ -631,20 +634,21 @@ final class SQLiteBooksDatabase extends BooksDatabase {
protected List<Bookmark> listBookmarks(long bookId) { protected List<Bookmark> listBookmarks(long bookId) {
LinkedList<Bookmark> list = new LinkedList<Bookmark>(); LinkedList<Bookmark> list = new LinkedList<Bookmark>();
Cursor cursor = myDatabase.rawQuery( Cursor cursor = myDatabase.rawQuery(
"SELECT bookmark_id,book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char FROM Bookmarks WHERE book_id = ?", new String[] { "" + bookId } "SELECT Bookmarks.bookmark_id,Bookmarks.book_id,Books.title,Bookmarks.bookmark_text,Bookmarks.creation_time,Bookmarks.modification_time,Bookmarks.access_time,Bookmarks.access_counter,Bookmarks.paragraph,Bookmarks.word,Bookmarks.char FROM Bookmarks INNER JOIN Books ON Books.book_id = Bookmarks.book_id WHERE book_id = ?", new String[] { "" + bookId }
); );
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
list.add(createBookmark( list.add(createBookmark(
cursor.getLong(0), cursor.getLong(0),
cursor.getLong(1), cursor.getLong(1),
cursor.getString(2), cursor.getString(2),
getDate(cursor, 3), cursor.getString(3),
getDate(cursor, 4), getDate(cursor, 4),
getDate(cursor, 5), getDate(cursor, 5),
(int)cursor.getLong(6), getDate(cursor, 6),
(int)cursor.getLong(7), (int)cursor.getLong(7),
(int)cursor.getLong(8), (int)cursor.getLong(8),
(int)cursor.getLong(9) (int)cursor.getLong(9),
(int)cursor.getLong(10)
)); ));
} }
cursor.close(); cursor.close();
@ -653,21 +657,23 @@ final class SQLiteBooksDatabase extends BooksDatabase {
protected List<Bookmark> listAllBookmarks() { protected List<Bookmark> listAllBookmarks() {
LinkedList<Bookmark> list = new LinkedList<Bookmark>(); LinkedList<Bookmark> list = new LinkedList<Bookmark>();
myDatabase.execSQL("DELETE FROM Bookmarks WHERE book_id = -1");
Cursor cursor = myDatabase.rawQuery( Cursor cursor = myDatabase.rawQuery(
"SELECT bookmark_id,book_id,bookmark_text,creation_time,modification_time,access_time,access_counter,paragraph,word,char FROM Bookmarks", null "SELECT Bookmarks.bookmark_id,Bookmarks.book_id,Books.title,Bookmarks.bookmark_text,Bookmarks.creation_time,Bookmarks.modification_time,Bookmarks.access_time,Bookmarks.access_counter,Bookmarks.paragraph,Bookmarks.word,Bookmarks.char FROM Bookmarks INNER JOIN Books ON Books.book_id = Bookmarks.book_id", null
); );
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
list.add(createBookmark( list.add(createBookmark(
cursor.getLong(0), cursor.getLong(0),
cursor.getLong(1), cursor.getLong(1),
cursor.getString(2), cursor.getString(2),
getDate(cursor, 3), cursor.getString(3),
getDate(cursor, 4), getDate(cursor, 4),
getDate(cursor, 5), getDate(cursor, 5),
(int)cursor.getLong(6), getDate(cursor, 6),
(int)cursor.getLong(7), (int)cursor.getLong(7),
(int)cursor.getLong(8), (int)cursor.getLong(8),
(int)cursor.getLong(9) (int)cursor.getLong(9),
(int)cursor.getLong(10)
)); ));
} }
cursor.close(); cursor.close();
@ -726,6 +732,32 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myDeleteBookmarkStatement.execute(); myDeleteBookmarkStatement.execute();
} }
protected ZLTextPosition getStoredPosition(long bookId) {
ZLTextPosition position = null;
Cursor cursor = myDatabase.rawQuery(
"SELECT paragraph,word,char FROM BookState WHERE book_id = " + bookId, null
);
if (cursor.moveToNext()) {
position = new ZLTextPosition((int)cursor.getLong(0), (int)cursor.getLong(1), (int)cursor.getLong(2));
}
cursor.close();
return position;
}
private SQLiteStatement myStorePositionStatement;
protected void storePosition(long bookId, ZLTextPosition position) {
if (myStorePositionStatement == null) {
myStorePositionStatement = myDatabase.compileStatement(
"INSERT OR REPLACE INTO BookState (book_id,paragraph,word,char) VALUES (?,?,?,?)"
);
}
myStorePositionStatement.bindLong(1, bookId);
myStorePositionStatement.bindLong(2, position.ParagraphIndex);
myStorePositionStatement.bindLong(3, position.WordIndex);
myStorePositionStatement.bindLong(4, position.CharIndex);
myStorePositionStatement.execute();
}
private void createTables() { private void createTables() {
myDatabase.execSQL( myDatabase.execSQL(
"CREATE TABLE Books(" + "CREATE TABLE Books(" +
@ -848,6 +880,34 @@ final class SQLiteBooksDatabase extends BooksDatabase {
"paragraph INTEGER NOT NULL," + "paragraph INTEGER NOT NULL," +
"word INTEGER NOT NULL," + "word INTEGER NOT NULL," +
"char INTEGER NOT NULL)"); "char INTEGER NOT NULL)");
myDatabase.execSQL(
"CREATE TABLE BookState(" +
"book_id INTEGER UNIQUE NOT NULL REFERENCES Books(book_id)," +
"paragraph INTEGER NOT NULL," +
"word INTEGER NOT NULL," +
"char INTEGER NOT NULL)");
Cursor cursor = myDatabase.rawQuery(
"SELECT book_id,file_name FROM Books", null
);
final SQLiteStatement statement = myDatabase.compileStatement("INSERT INTO BookState (book_id,paragraph,word,char) VALUES (?,?,?,?)");
while (cursor.moveToNext()) {
final long bookId = cursor.getLong(0);
final String fileName = cursor.getString(1);
final int position = new ZLIntegerOption(fileName, "PositionInBuffer", 0).getValue();
final int paragraph = new ZLIntegerOption(fileName, "Paragraph_" + position, 0).getValue();
final int word = new ZLIntegerOption(fileName, "Word_" + position, 0).getValue();
final int chr = new ZLIntegerOption(fileName, "Char_" + position, 0).getValue();
if ((paragraph != 0) || (word != 0) || (chr != 0)) {
statement.bindLong(1, bookId);
statement.bindLong(2, paragraph);
statement.bindLong(3, word);
statement.bindLong(4, chr);
statement.execute();
}
ZLConfig.Instance().removeGroup(fileName);
}
cursor.close();
} }
private void updateTables6() { private void updateTables6() {

View file

@ -70,23 +70,11 @@ public final class ZLSQLiteConfig extends ZLConfig {
myUnsetValueStatement = myDatabase.compileStatement("DELETE FROM config WHERE groupName = ? AND name = ?"); myUnsetValueStatement = myDatabase.compileStatement("DELETE FROM config WHERE groupName = ? AND name = ?");
myDeleteGroupStatement = myDatabase.compileStatement("DELETE FROM config WHERE groupName = ?"); myDeleteGroupStatement = myDatabase.compileStatement("DELETE FROM config WHERE groupName = ?");
/*
final Cursor cursor = myDatabase.rawQuery("SELECT name FROM config WHERE groupName LIKE ? GROUP BY name", new String[] { "/%" }); final Cursor cursor = myDatabase.rawQuery("SELECT name FROM config WHERE groupName LIKE ? GROUP BY name", new String[] { "/%" });
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
System.err.println(" = " + cursor.getString(0)); System.err.println(" = " + cursor.getString(0));
} }
cursor.close(); cursor.close();
*/
}
synchronized public void executeAsATransaction(Runnable actions) {
myDatabase.beginTransaction();
try {
actions.run();
myDatabase.setTransactionSuccessful();
} finally {
myDatabase.endTransaction();
}
} }
synchronized public void removeGroup(String name) { synchronized public void removeGroup(String name) {

View file

@ -23,6 +23,7 @@ import java.io.*;
import android.app.Application; import android.app.Application;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.AssetFileDescriptor;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@ -97,12 +98,36 @@ public final class ZLAndroidLibrary extends ZLibrary {
} }
} }
@Override
public boolean exists() { public boolean exists() {
return myExists; return myExists;
} }
public InputStream getInputStream() { @Override
return myExists ? myApplication.getResources().openRawResource(myResourceId) : null; public long size() {
try {
AssetFileDescriptor descriptor =
myApplication.getResources().openRawResourceFd(myResourceId);
long length = descriptor.getLength();
descriptor.close();
return length;
} catch (IOException e) {
return 0;
} catch (Resources.NotFoundException e) {
return 0;
}
}
@Override
public InputStream getInputStream() throws IOException {
if (!myExists) {
throw new IOException("No such file: " + getPath());
}
try {
return myApplication.getResources().openRawResource(myResourceId);
} catch (Resources.NotFoundException e) {
throw new IOException(e.getMessage());
}
} }
} }
} }

View file

@ -144,10 +144,10 @@ public final class ZipFile {
return createZipInputStream(header); return createZipInputStream(header);
} }
if (myAllFilesAreRead) { if (myAllFilesAreRead) {
return null; throw new ZipException("Entry " + entryName + " is not found");
} }
} }
// ready to read fileheader // ready to read file header
MyBufferedInputStream baseStream = getBaseStream(); MyBufferedInputStream baseStream = getBaseStream();
baseStream.setPosition(0); baseStream.setPosition(0);
try { try {
@ -165,14 +165,11 @@ public final class ZipFile {
} while (!readFileHeader(baseStream, entryName)); } while (!readFileHeader(baseStream, entryName));
LocalFileHeader header = myFileHeaders.get(entryName); LocalFileHeader header = myFileHeaders.get(entryName);
if (header != null) { if (header != null) {
try {
return createZipInputStream(header); return createZipInputStream(header);
} catch (ZipException e) {
}
} }
} finally { } finally {
storeBaseStream(baseStream); storeBaseStream(baseStream);
} }
return null; throw new ZipException("Entry " + entryName + " is not found");
} }
} }

View file

@ -30,6 +30,18 @@ import org.geometerplus.fbreader.library.Book;
import org.geometerplus.fbreader.formats.*; import org.geometerplus.fbreader.formats.*;
public final class BookModel { public final class BookModel {
public static BookModel createModel(Book book) {
FormatPlugin plugin = PluginCollection.instance().getPlugin(book.File);
if (plugin == null) {
return null;
}
BookModel model = new BookModel(book);
if (plugin.readModel(model)) {
return model;
}
return null;
}
public final Book Book; public final Book Book;
public final ZLTextPlainModel BookTextModel = new ZLTextPlainModel(65536, "/sdcard/Books/.FBReader", "cache"); public final ZLTextPlainModel BookTextModel = new ZLTextPlainModel(65536, "/sdcard/Books/.FBReader", "cache");
public final TOCTree TOCTree = new TOCTree(); public final TOCTree TOCTree = new TOCTree();
@ -49,12 +61,8 @@ public final class BookModel {
} }
} }
public BookModel(final Book book) { private BookModel(Book book) {
Book = book; Book = book;
FormatPlugin plugin = PluginCollection.instance().getPlugin(book.File);
if (plugin != null) {
plugin.readModel(this);
}
} }
ZLTextPlainModel getFootnoteModel(String id) { ZLTextPlainModel getFootnoteModel(String id) {

View file

@ -1,56 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
public class DummyEncodingConverterProvider extends ZLEncodingConverterProvider {
public ZLEncodingConverter createConverter() {
return new DummyEncodingConverter();
}
public ZLEncodingConverter createConverter(String encoding) {
return createConverter();
}
public boolean providesConverter(String encoding) {
final String lowerCasedEncoding = encoding.toLowerCase();
return ("utf-8".equals(lowerCasedEncoding)) || ("us-ascii".equals(lowerCasedEncoding));
}
private static class DummyEncodingConverter extends ZLEncodingConverter {
private DummyEncodingConverter() {}
public boolean fillTable(int[] map) {
for (int i = 0; i < 255; ++i) {
map[i] = i;
}
return true;
}
public void reset() {}
//size=end-start
public String convert(char [] src, int start, int end) {
return new String(src, start, end - start);
}
}
}

View file

@ -1,169 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import org.geometerplus.zlibrary.core.config.ZLConfig;
import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
import org.geometerplus.zlibrary.core.library.ZLibrary;
import org.geometerplus.zlibrary.core.options.ZLBooleanOption;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.xml.ZLXMLReaderAdapter;
public class ZLEncodingCollection {
private static ZLEncodingCollection ourInstance;
private final ArrayList/*<ZLEncodingSet>*/ mySets = new ArrayList();
private final HashMap/*<String,ZLEncodingConverterInfo>*/ myInfosByName = new HashMap();
private final ArrayList/*<ZLEncodingConverterProvider>*/ myProviders = new ArrayList();
private ZLEncodingCollection() {
registerProvider(new DummyEncodingConverterProvider());
// registerProvider(new MyEncodingConverterProvider());
}
public static ZLEncodingCollection instance() {
if (ourInstance == null) {
ourInstance = new ZLEncodingCollection();
}
return ourInstance;
}
public static ZLResourceFile encodingDescriptionFile() {
return ZLResourceFile.createResourceFile("data/encodings/Encodings.xml");
}
public ArrayList<ZLEncodingSet> sets() {
init();
return mySets;
}
public ZLEncodingConverterInfo info(String name) {
init();
String lowerCaseName = name.toLowerCase();
if (lowerCaseName == "iso-8859-1") {
lowerCaseName = "windows-1252";
}
return (ZLEncodingConverterInfo)myInfosByName.get(lowerCaseName);
}
public ZLEncodingConverterInfo info(int code) {
String name = "" + code;
return info(name);
}
public ZLEncodingConverter defaultConverter() {
return new DummyEncodingConverterProvider().createConverter();
}
public void registerProvider(ZLEncodingConverterProvider provider) {
myProviders.add(provider);
}
// private void addInfo(ZLEncodingConverterInfo info) {}
ArrayList/*<ZLEncodingConverterProvider>*/ providers() {
return myProviders;
}
private void init() {
if (mySets.isEmpty()) {
// String prefix = encodingDescriptionPath() + File.separator;
// System.out.println("trying to read " + prefix + "Encodings.xml");
new ZLEncodingCollectionReader(this).read(encodingDescriptionFile());
}
}
private static class ZLEncodingCollectionReader extends ZLXMLReaderAdapter {
private final ZLEncodingCollection myCollection;
private ZLEncodingSet myCurrentSet;
private ZLEncodingConverterInfo myCurrentInfo;
private final ArrayList/*<String>*/ myNames = new ArrayList();
private static final String GROUP = "group";
private static final String ENCODING = "encoding";
private static final String NAME = "name";
private static final String REGION = "region";
private static final String ALIAS = "alias";
private static final String CODE = "code";
private static final String NUMBER = "number";
public ZLEncodingCollectionReader(ZLEncodingCollection collection) {
myCollection = collection;
}
public boolean dontCacheAttributeValues() {
return true;
}
public boolean endElementHandler(String tag) {
if (myCurrentInfo != null && (ENCODING.equals(tag))) {
if (myCurrentInfo.canCreateConverter()) {
myCurrentSet.addInfo(myCurrentInfo);
final int size = myNames.size();
for (int i = 0; i < size; i++) {
myCollection.myInfosByName.put(((String) myNames.get(i)).toLowerCase(), myCurrentInfo);
}
}
myCurrentInfo = null;
myNames.clear();
} else if (myCurrentSet != null && (GROUP.equals(tag))) {
if (!myCurrentSet.infos().isEmpty()) {
myCollection.mySets.add(myCurrentSet);
}
myCurrentSet = null;
}
return false;
}
public boolean startElementHandler(String tag, ZLStringMap attributes) {
if (GROUP.equals(tag)) {
final String name = attributes.getValue(NAME);
if (name != null) {
myCurrentSet = new ZLEncodingSet(name);
}
} else if (myCurrentSet != null) {
if (ENCODING.equals(tag)) {
final String name = attributes.getValue(NAME);
final String region = attributes.getValue(REGION);
if ((name != null) && (region != null)) {
final String sName = name;
myCurrentInfo = new ZLEncodingConverterInfo(sName, region);
myNames.add(sName);
}
} else if (myCurrentInfo != null) {
String name = null;
if (CODE.equals(tag)) {
name = attributes.getValue(NUMBER);
} else if (ALIAS.equals(tag)) {
name = attributes.getValue(NAME);
}
if (name != null) {
final String sName = name;
myCurrentInfo.addAlias(sName);
myNames.add(sName);
}
}
}
return false;
}
}
}

View file

@ -1,33 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
public abstract class ZLEncodingConverter {
protected ZLEncodingConverter() {}
//abstract public void convert(String dst, const char *srcStart, const char *srcEnd);
abstract public String convert(char [] src, int start, int end);
//convert(dst, src.toCharArray(), src.data() + src.length());
public abstract void reset();
public abstract boolean fillTable(int[] map);
//private ZLEncodingConverter(ZLEncodingConverter zl);
//private ZLEncodingConverter &operator=(ZLEncodingConverter zl);
}

View file

@ -1,79 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
import java.util.ArrayList;
import java.util.Iterator;
public class ZLEncodingConverterInfo {
private String myName = "";
private String myVisibleName = "";
private ArrayList/*<String>*/ myAliases = new ArrayList();
public ZLEncodingConverterInfo(String name, String region) {
myName = name;
myVisibleName = region + " (" + name + ")";
addAlias(myName);
}
public void addAlias(String alias) {
myAliases.add(alias);
}
public String name() {
return myName;
}
public String visibleName() {
return myVisibleName;
}
public ZLEncodingConverter createConverter() {
ZLEncodingCollection collection = ZLEncodingCollection.instance();
ArrayList<ZLEncodingConverterProvider> providers = collection.providers();
for (Iterator it = providers.iterator(); it.hasNext(); ) {
for (Iterator jt = myAliases.iterator(); jt.hasNext(); ) {
ZLEncodingConverterProvider itp = (ZLEncodingConverterProvider)it.next();
String str = (String)jt.next();
if (itp.providesConverter(str)) {
return itp.createConverter(str);
}
}
}
return ZLEncodingCollection.instance().defaultConverter();
}
public boolean canCreateConverter() {
ZLEncodingCollection collection = ZLEncodingCollection.instance();
ArrayList<ZLEncodingConverterProvider> providers = collection.providers();
for (Iterator it = providers.iterator(); it.hasNext();) {
final ZLEncodingConverterProvider privider = (ZLEncodingConverterProvider)it.next();
for (Iterator jt = myAliases.iterator(); jt.hasNext(); ) {
if (privider.providesConverter((String)jt.next())) {
return true;
}
}
}
return false;
}
//private ZLEncodingConverterInfo(const ZLEncodingConverterInfo&);
//private ZLEncodingConverterInfo &operator=(const ZLEncodingConverterInfo&);
}

View file

@ -1,28 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
public abstract class ZLEncodingConverterProvider {
protected ZLEncodingConverterProvider() {
}
public abstract boolean providesConverter(String encoding);
public abstract ZLEncodingConverter createConverter(String encoding);
}

View file

@ -1,43 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encoding;
import java.util.ArrayList;
public class ZLEncodingSet {
private String myName = "";
private ArrayList/*<ZLEncodingConverterInfo>*/ myInfos = new ArrayList();
public ZLEncodingSet(String name) {
}
public void addInfo(ZLEncodingConverterInfo info) {
myInfos.add(info);
}
public String name() {
return myName;
}
public ArrayList/*<ZLEncodingConverterInfo>*/ infos() {
return myInfos;
}
}

View file

@ -1,107 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encodingOption;
import java.util.ArrayList;
import java.util.HashMap;
import org.geometerplus.fbreader.encoding.ZLEncodingCollection;
import org.geometerplus.fbreader.encoding.ZLEncodingConverterInfo;
import org.geometerplus.fbreader.encoding.ZLEncodingSet;
import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.zlibrary.core.util.*;
import org.geometerplus.zlibrary.core.dialogs.ZLComboOptionEntry;
public class EncodingEntry extends ZLComboOptionEntry {
private static final String AUTO = "auto";
private static ArrayList/*<String>*/ AUTO_ENCODING;
final ArrayList/*<std::string>*/ mySetNames = new ArrayList();
private final HashMap/*<String, ArrayList<String>>*/ myValues = new HashMap();
private final HashMap/*<String,String>*/ myInitialValues = new HashMap();
private final HashMap/*<String,String>*/ myValueByName = new HashMap();
private ZLStringOption myEncodingOption;
String myInitialSetName = "";
public EncodingEntry(ZLStringOption encodingOption) {
myEncodingOption = encodingOption;
final String value = myEncodingOption.getValue();
if (AUTO.equals(value)) {
myInitialSetName = value;
myInitialValues.put(value, value);
setActive(false);
return;
}
final ArrayList/*<ZLEncodingSet>*/ sets = ZLEncodingCollection.instance().sets();
System.out.println("sets size = " + sets.size());
for (int i = 0; i < sets.size(); i++) {
ZLEncodingSet es = (ZLEncodingSet) sets.get(i);
final ArrayList/*<ZLEncodingConverterInfo>*/ infos = es.infos();
// System.out.println(es.name());
mySetNames.add(es.name());
ArrayList/*<String>*/ names = new ArrayList();
for (int j = 0; j < infos.size(); j++) {
ZLEncodingConverterInfo eci = (ZLEncodingConverterInfo) infos.get(j);
if (eci.name().equals(value)) {
myInitialSetName = es.name();
myInitialValues.put(myInitialSetName, eci.visibleName());
}
names.add(eci.visibleName());
myValueByName.put(eci.visibleName(), eci.name());
}
myValues.put(es.name(), names);
}
//TODO:
if (myInitialSetName.length() == 0 && !mySetNames.isEmpty()) {
myInitialSetName = (String) mySetNames.get(0);
}
}
public ArrayList getValues() {
if (AUTO.equals(initialValue())) {
if (AUTO_ENCODING == null) {
AUTO_ENCODING = new ArrayList();
AUTO_ENCODING.add(AUTO);
}
return AUTO_ENCODING;
}
return (ArrayList) myValues.get(myInitialSetName);
}
public String initialValue() {
if ( myInitialValues.get(myInitialSetName) == null) {
myInitialValues.put(myInitialSetName, ((ArrayList) myValues.get(myInitialSetName)).get(0));
}
return (String) myInitialValues.get(myInitialSetName);
}
public void onAccept(String value) {
if (!AUTO.equals(initialValue())) {
myEncodingOption.setValue((String) myValueByName.get(value));
}
}
public void onValueSelected(int index) {
myInitialValues.put(myInitialSetName, getValues().get(index));
}
}

View file

@ -1,47 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.encodingOption;
import java.util.ArrayList;
import org.geometerplus.zlibrary.core.dialogs.ZLComboOptionEntry;
public class EncodingSetEntry extends ZLComboOptionEntry {
private EncodingEntry myEncodingEntry;
public EncodingSetEntry(EncodingEntry encodingEntry) {
myEncodingEntry = encodingEntry;
}
public ArrayList getValues() {
return myEncodingEntry.mySetNames;
}
public String initialValue() {
return myEncodingEntry.myInitialSetName;
}
public void onAccept(String value) {}
public void onValueSelected(int index) {
myEncodingEntry.myInitialSetName = (String) getValues().get(index);
myEncodingEntry.resetView();
}
}

View file

@ -24,8 +24,6 @@ public interface ActionCode {
String SHOW_OPTIONS = "preferences-old"; String SHOW_OPTIONS = "preferences-old";
String SHOW_PREFERENCES = "preferences"; String SHOW_PREFERENCES = "preferences";
String SHOW_BOOK_INFO = "bookInfo"; String SHOW_BOOK_INFO = "bookInfo";
String UNDO = "undo";
String REDO = "redo";
String SHOW_CONTENTS = "toc"; String SHOW_CONTENTS = "toc";
String SHOW_BOOKMARKS = "bookmarks"; String SHOW_BOOKMARKS = "bookmarks";
String SEARCH = "search"; String SEARCH = "search";

View file

@ -28,6 +28,10 @@ class BookInfoAction extends FBAction {
super(fbreader); super(fbreader);
} }
public boolean isVisible() {
return Reader.Model != null;
}
public void run() { public void run() {
final ZLAndroidDialogManager dialogManager = final ZLAndroidDialogManager dialogManager =
(ZLAndroidDialogManager)ZLAndroidDialogManager.Instance(); (ZLAndroidDialogManager)ZLAndroidDialogManager.Instance();

View file

@ -33,63 +33,10 @@ import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.zlibrary.text.view.impl.*; import org.geometerplus.zlibrary.text.view.impl.*;
public class BookTextView extends FBView { public class BookTextView extends FBView {
private static final String BUFFER_SIZE = "UndoBufferSize";
private static final String POSITION_IN_BUFFER = "PositionInBuffer";
private static final String PARAGRAPH_PREFIX = "Paragraph_";
private static final String WORD_PREFIX = "Word_";
private static final String CHAR_PREFIX = "Char_";
// private static final String MODEL_PREFIX = "Model_";
private static final int MAX_UNDO_STACK_SIZE = 20;
private ZLIntegerOption myParagraphIndexOption;
private ZLIntegerOption myWordIndexOption;
private ZLIntegerOption myCharIndexOption;
private ArrayList<ZLTextPosition> myPositionStack = new ArrayList<ZLTextPosition>();
private int myCurrentPointInStack;
private String myFileName;
BookTextView(ZLPaintContext context) { BookTextView(ZLPaintContext context) {
super(context); super(context);
} }
public void setModel(ZLTextModel model, String fileName) {
super.setModel(model);
myFileName = fileName;
myPositionStack.clear();
final int stackSize = new ZLIntegerRangeOption(fileName, BUFFER_SIZE, 0, MAX_UNDO_STACK_SIZE, 0).getValue();
myCurrentPointInStack = new ZLIntegerRangeOption(fileName, POSITION_IN_BUFFER, 0, (stackSize == 0) ? 0 : (stackSize - 1), 0).getValue();
if (model != null) {
final ZLIntegerOption option = new ZLIntegerOption(fileName, "", 0);
for (int i = 0; i < stackSize; ++i) {
option.changeName(PARAGRAPH_PREFIX + i);
int paragraphIndex = option.getValue();
option.changeName(WORD_PREFIX + i);
final int wordIndex = option.getValue();
option.changeName(CHAR_PREFIX + i);
final int charIndex = option.getValue();
myPositionStack.add(new ZLTextPosition(paragraphIndex, wordIndex, charIndex));
}
if (!myPositionStack.isEmpty()) {
gotoPosition(myPositionStack.get(myCurrentPointInStack));
}
}
}
protected void onPaintInfoPrepared() {
if (myPositionStack.isEmpty()) {
myPositionStack.add(new ZLTextPosition(getStartCursor()));
} else {
myPositionStack.get(myCurrentPointInStack).set(getStartCursor());
}
}
void scrollToHome() { void scrollToHome() {
final ZLTextWordCursor cursor = getStartCursor(); final ZLTextWordCursor cursor = getStartCursor();
if (!cursor.isNull() && cursor.isStartOfParagraph() && cursor.getParagraphCursor().Index == 0) { if (!cursor.isNull() && cursor.isStartOfParagraph() && cursor.getParagraphCursor().Index == 0) {
@ -97,9 +44,8 @@ public class BookTextView extends FBView {
} }
final ZLTextPosition position = new ZLTextPosition(cursor); final ZLTextPosition position = new ZLTextPosition(cursor);
gotoParagraph(0, false); gotoParagraph(0, false);
gotoPosition(0, 0, 0); gotoPosition(new ZLTextPosition(0, 0, 0));
preparePaintInfo(); preparePaintInfo();
savePosition(position, getStartCursor());
ZLApplication.Instance().repaintView(); ZLApplication.Instance().repaintView();
} }
@ -110,7 +56,6 @@ public class BookTextView extends FBView {
final ZLTextPosition position = new ZLTextPosition(cursor); final ZLTextPosition position = new ZLTextPosition(cursor);
gotoParagraph(paragraphIndex, false); gotoParagraph(paragraphIndex, false);
preparePaintInfo(); preparePaintInfo();
savePosition(position, getStartCursor());
} }
} }
@ -159,76 +104,4 @@ public class BookTextView extends FBView {
return super.onStylusPress(x, y); return super.onStylusPress(x, y);
} }
public String getFileName() {
return this.myFileName;
}
protected void savePosition(ZLTextPosition position) {
if (myPositionStack.isEmpty()) {
preparePaintInfo();
}
final ZLTextPosition currentPosition = myPositionStack.get(myCurrentPointInStack);
while (myPositionStack.size() > myCurrentPointInStack) {
myPositionStack.remove(myPositionStack.size() - 1);
}
myPositionStack.add(position);
myPositionStack.add(currentPosition);
while (myPositionStack.size() >= MAX_UNDO_STACK_SIZE) {
myPositionStack.remove(0);
}
myCurrentPointInStack = myPositionStack.size() - 1;
}
void saveState() {
new Thread(new Runnable() {
public void run() {
ZLConfig.Instance().executeAsATransaction(new Runnable() {
public void run() {
saveStateInternal();
}
});
}
}).start();
}
private void saveStateInternal() {
if (getModel() == null) {
return;
}
final String group = getFileName();
new ZLIntegerOption(group, BUFFER_SIZE, 0).setValue(myPositionStack.size());
new ZLIntegerOption(group, POSITION_IN_BUFFER, 0).setValue(myCurrentPointInStack);
final ZLIntegerOption option = new ZLIntegerOption(group, "", 0);
for (int i = 0; i < myPositionStack.size(); ++i) {
final ZLTextPosition position = myPositionStack.get(i);
option.changeName(PARAGRAPH_PREFIX + i);
option.setValue(position.ParagraphIndex);
option.changeName(CHAR_PREFIX + i);
option.setValue(position.CharIndex);
option.changeName(WORD_PREFIX + i);
option.setValue(position.WordIndex);
}
}
boolean canUndoPageMove() {
return myCurrentPointInStack > 0;
}
void undoPageMove() {
gotoPosition(myPositionStack.get(--myCurrentPointInStack));
ZLApplication.Instance().repaintView();
}
boolean canRedoPageMove() {
return myCurrentPointInStack < myPositionStack.size() - 1;
}
void redoPageMove() {
gotoPosition(myPositionStack.get(++myCurrentPointInStack));
ZLApplication.Instance().repaintView();
}
} }

View file

@ -80,9 +80,6 @@ public final class FBReader extends ZLApplication {
addAction(ActionCode.QUIT, new QuitAction(this)); addAction(ActionCode.QUIT, new QuitAction(this));
addAction(ActionCode.ROTATE_SCREEN, new ZLApplication.RotationAction()); addAction(ActionCode.ROTATE_SCREEN, new ZLApplication.RotationAction());
addAction(ActionCode.UNDO, new UndoAction(this));
addAction(ActionCode.REDO, new RedoAction(this));
addAction(ActionCode.INCREASE_FONT, new ChangeFontSizeAction(this, +2)); addAction(ActionCode.INCREASE_FONT, new ChangeFontSizeAction(this, +2));
addAction(ActionCode.DECREASE_FONT, new ChangeFontSizeAction(this, -2)); addAction(ActionCode.DECREASE_FONT, new ChangeFontSizeAction(this, -2));
@ -215,23 +212,25 @@ public final class FBReader extends ZLApplication {
if (book != null) { if (book != null) {
onViewChanged(); onViewChanged();
BookTextView.saveState(); if (Model != null) {
BookTextView.setModel(null, ""); Model.Book.storePosition(new ZLTextPosition(BookTextView.getStartCursor()));
}
BookTextView.setModel(null);
FootnoteView.setModel(null);
Model = null; Model = null;
Model = new BookModel(book); System.gc();
System.gc();
Model = BookModel.createModel(book);
if (Model != null) {
final String fileName = book.File.getPath(); final String fileName = book.File.getPath();
myBookNameOption.setValue(fileName); myBookNameOption.setValue(fileName);
ZLTextHyphenator.Instance().load(book.getLanguage()); ZLTextHyphenator.Instance().load(book.getLanguage());
BookTextView.setModel(Model.BookTextModel, fileName); BookTextView.setModel(Model.BookTextModel);
BookTextView.setCaption(book.getTitle()); BookTextView.gotoPosition((position != null) ? position : book.getStoredPosition());
if (position != null) {
BookTextView.gotoPosition(position);
}
FootnoteView.setModel(null);
FootnoteView.setCaption(book.getTitle());
Library.Instance().addBookToRecentList(book); Library.Instance().addBookToRecentList(book);
} }
}
repaintView(); repaintView();
} }
@ -270,8 +269,8 @@ main:
} }
public void onWindowClosing() { public void onWindowClosing() {
if (BookTextView != null) { if ((Model != null) && (BookTextView != null)) {
BookTextView.saveState(); Model.Book.storePosition(new ZLTextPosition(BookTextView.getStartCursor()));
} }
} }
} }

View file

@ -33,8 +33,6 @@ public abstract class FBView extends ZLTextViewImpl {
private static ZLBooleanOption ourSelectionOption; private static ZLBooleanOption ourSelectionOption;
private String myCaption;
private static ZLIntegerRangeOption createMarginOption(String name, int defaultValue) { private static ZLIntegerRangeOption createMarginOption(String name, int defaultValue) {
return new ZLIntegerRangeOption( return new ZLIntegerRangeOption(
"Options", name, 0, 1000, defaultValue "Options", name, 0, 1000, defaultValue
@ -226,14 +224,6 @@ public abstract class FBView extends ZLTextViewImpl {
return getBottomMarginOption().getValue(); return getBottomMarginOption().getValue();
} }
public String getCaption() {
return myCaption;
}
void setCaption(String caption) {
myCaption = caption;
}
public static ZLBooleanOption selectionOption() { public static ZLBooleanOption selectionOption() {
if (ourSelectionOption == null) { if (ourSelectionOption == null) {
ourSelectionOption = new ZLBooleanOption("Options", "IsSelectionEnabled", true); ourSelectionOption = new ZLBooleanOption("Options", "IsSelectionEnabled", true);

View file

@ -1,38 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.fbreader;
class RedoAction extends FBAction {
RedoAction(FBReader fbreader) {
super(fbreader);
}
public boolean isVisible() {
return Reader.getMode() == FBReader.ViewMode.BOOK_TEXT;
}
public boolean isEnabled() {
return isVisible() && Reader.BookTextView.canRedoPageMove();
}
public void run() {
Reader.BookTextView.redoPageMove();
}
}

View file

@ -26,6 +26,10 @@ class SearchAction extends FBAction {
super(fbreader); super(fbreader);
} }
public boolean isVisible() {
return Reader.Model != null;
}
public void run() { public void run() {
ZLDialogManager.Instance().startSearch(); ZLDialogManager.Instance().startSearch();
} }

View file

@ -1,43 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.fbreader;
class UndoAction extends FBAction {
UndoAction(FBReader fbreader) {
super(fbreader);
}
public boolean isVisible() {
return true;
}
public boolean isEnabled() {
return Reader.getMode() != FBReader.ViewMode.BOOK_TEXT ||
Reader.BookTextView.canUndoPageMove();
}
public void run() {
if (Reader.getMode() == FBReader.ViewMode.BOOK_TEXT) {
Reader.BookTextView.undoPageMove();
} else {
Reader.restorePreviousMode();
}
}
}

View file

@ -1,38 +0,0 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.formats;
import org.geometerplus.fbreader.encoding.ZLEncodingCollection;
import org.geometerplus.fbreader.encoding.ZLEncodingConverter;
import org.geometerplus.fbreader.encoding.ZLEncodingConverterInfo;
public class EncodedTextReader {
private ZLEncodingConverter myConverter;
//?static
public EncodedTextReader(final String encoding) {
ZLEncodingCollection collection = ZLEncodingCollection.instance();
ZLEncodingConverterInfo info = collection.info(encoding);
myConverter = (info != null) ? info.createConverter() : collection.defaultConverter();
}
public ZLEncodingConverter getConverter() {
return myConverter;
}
}

View file

@ -27,7 +27,7 @@ import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.fbreader.formats.fb2.FB2Plugin; import org.geometerplus.fbreader.formats.fb2.FB2Plugin;
import org.geometerplus.fbreader.formats.html.HtmlPlugin; import org.geometerplus.fbreader.formats.html.HtmlPlugin;
import org.geometerplus.fbreader.formats.oeb.OEBPlugin; import org.geometerplus.fbreader.formats.oeb.OEBPlugin;
import org.geometerplus.fbreader.formats.plucker.PluckerPlugin; import org.geometerplus.fbreader.formats.pdb.MobipocketPlugin;
public class PluginCollection { public class PluginCollection {
private static PluginCollection ourInstance; private static PluginCollection ourInstance;
@ -44,13 +44,12 @@ public class PluginCollection {
//ourInstance.myPlugins.add(new PluckerPlugin()); //ourInstance.myPlugins.add(new PluckerPlugin());
//ourInstance->myPlugins.push_back(new DocBookPlugin()); //ourInstance->myPlugins.push_back(new DocBookPlugin());
//ourInstance.myPlugins.add(new HtmlPlugin()); //ourInstance.myPlugins.add(new HtmlPlugin());
/*ourInstance.myPlugins.add(new TxtPlugin()); //ourInstance.myPlugins.add(new TxtPlugin());
ourInstance.myPlugins.add(new PalmDocPlugin()); //ourInstance.myPlugins.add(new PalmDocPlugin());
ourInstance.myPlugins.add(new MobipocketPlugin()); ourInstance.myPlugins.add(new MobipocketPlugin());
ourInstance.myPlugins.add(new ZTXTPlugin()); //ourInstance.myPlugins.add(new ZTXTPlugin());
ourInstance.myPlugins.add(new TcrPlugin()); //ourInstance.myPlugins.add(new TcrPlugin());
ourInstance.myPlugins.add(new CHMPlugin()); //ourInstance.myPlugins.add(new CHMPlugin());
*/
ourInstance.myPlugins.add(new OEBPlugin()); ourInstance.myPlugins.add(new OEBPlugin());
//ourInstance.myPlugins.add(new RtfPlugin()); //ourInstance.myPlugins.add(new RtfPlugin());
//ourInstance.myPlugins.add(new OpenReaderPlugin()); //ourInstance.myPlugins.add(new OpenReaderPlugin());

View file

@ -50,7 +50,6 @@ public abstract class DocDecompressor {
if (stream.read(sourceBuffer, 0, compressedSize) == compressedSize) { if (stream.read(sourceBuffer, 0, compressedSize) == compressedSize) {
byte token; byte token;
int shiftedIndex;
loop: loop:
while ((sourceIndex < compressedSize) && (targetIndex < maxUncompressedSize)) { while ((sourceIndex < compressedSize) && (targetIndex < maxUncompressedSize)) {
@ -79,17 +78,17 @@ loop:
if (sourceIndex + 1 > compressedSize) { if (sourceIndex + 1 > compressedSize) {
break loop; break loop;
} }
int N = 256 * (token & 0xFF) + (sourceBuffer[sourceIndex++] & 0xFF); final int N = ((token & 0xFF) << 16) + (sourceBuffer[sourceIndex++] & 0xFF);
int copyLength = (N & 7) + 3; final int copyLength = (N & 7) + 3;
if (targetIndex + copyLength > maxUncompressedSize) { if (targetIndex + copyLength > maxUncompressedSize) {
break loop; break loop;
} }
shiftedIndex = targetIndex - (N & 0x3fff) / 8; final int srcIndex = targetIndex - (N & 0x3fff) / 8;
if (shiftedIndex >= 0) { if (srcIndex < 0) {
for (int i = 0; i < copyLength; i++) { break;
targetBuffer[targetIndex++] = targetBuffer[shiftedIndex++];
}
} }
System.arraycopy(targetBuffer, srcIndex, targetBuffer, targetIndex, copyLength);
targetIndex += copyLength;
break; break;
} }
} }

View file

@ -0,0 +1,128 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.formats.pdb;
import java.io.*;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.encoding.ZLEncodingCollection;
import org.geometerplus.zlibrary.core.util.ZLLanguageUtil;
import org.geometerplus.fbreader.library.Book;
import org.geometerplus.fbreader.bookmodel.BookModel;
public class MobipocketPlugin extends PdbPlugin {
@Override
public boolean acceptsFile(ZLFile file) {
return super.acceptsFile(file) && (fileType(file) == "BOOKMOBI");
}
@Override
public boolean readMetaInfo(Book book) {
InputStream stream = null;
try {
stream = book.File.getInputStream();
final PdbHeader header = new PdbHeader(stream);
PdbUtil.skip(stream, header.Offsets[0] + 16 - header.length());
if (PdbUtil.readInt(stream) != 0x4D4F4249) /* "MOBI" */ {
return false;
}
final int length = (int)PdbUtil.readInt(stream);
PdbUtil.skip(stream, 4);
final int encodingCode = (int)PdbUtil.readInt(stream);
String encodingName = ZLEncodingCollection.Instance().getEncodingName(encodingCode);
book.setEncoding(encodingName);
if (encodingName == null) {
encodingName = "utf-8";
}
PdbUtil.skip(stream, 52);
final int fullNameOffset = (int)PdbUtil.readInt(stream);
final int fullNameLength = (int)PdbUtil.readInt(stream);
final int languageCode = (int)PdbUtil.readInt(stream);
book.setLanguage(ZLLanguageUtil.languageByCode(languageCode & 0xFF, (languageCode >> 8) & 0xFF));
PdbUtil.skip(stream, 32);
int offset = 132;
if ((PdbUtil.readInt(stream) & 0x40) != 0) {
PdbUtil.skip(stream, length - 116);
offset = length + 20;
if (PdbUtil.readInt(stream) == 0x45585448) /* "EXTH" */ {
PdbUtil.skip(stream, 4);
final int recordsNumber = (int)PdbUtil.readInt(stream);
offset += 8;
for (int i = 0; i < recordsNumber; ++i) {
final int type = (int)PdbUtil.readInt(stream);
final int size = (int)PdbUtil.readInt(stream);
offset += size;
if (size <= 8) {
continue;
}
switch (type) {
default:
PdbUtil.skip(stream, size - 8);
break;
case 100:
{
final byte[] buffer = new byte[size - 8];
stream.read(buffer);
String author = new String(buffer, encodingName);
final int index = author.indexOf(',');
if (index != -1) {
author = author.substring(index + 1).trim() +
' ' +
author.substring(0, index).trim();
} else {
author = author.trim();
}
book.addAuthor(author);
break;
}
case 105:
{
final byte[] buffer = new byte[size - 8];
stream.read(buffer);
book.addTag(new String(buffer, encodingName));
break;
}
}
}
}
}
PdbUtil.skip(stream, fullNameOffset - offset);
final byte[] titleBuffer = new byte[fullNameLength];
stream.read(titleBuffer);
book.setTitle(new String(titleBuffer, encodingName));
return true;
} catch (IOException e) {
return false;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
}
}
}
}
@Override
public boolean readModel(BookModel model) {
return false;
}
}

View file

@ -17,18 +17,37 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
package org.geometerplus.fbreader.encoding; package org.geometerplus.fbreader.formats.pdb;
public class MyEncodingConverterProvider extends ZLEncodingConverterProvider { import java.io.IOException;
public ZLEncodingConverter createConverter(String encoding) { import org.geometerplus.zlibrary.core.filesystem.ZLFile;
// TODO Auto-generated method stub
return null; class MobipocketStream extends PdbStream {
private final long myFileSize;
private final boolean myIsCompressed;
MobipocketStream(ZLFile file) throws IOException {
super(file);
myFileSize = file.size();
final int version = PdbUtil.readShort(myBase);
switch (version) {
case 1:
myIsCompressed = false;
break;
case 2:
myIsCompressed = true;
break;
default:
throw new IOException("Unsupported compression type: " + version);
}
PdbUtil.skip(myBase, 6);
// TODO: implement
} }
public boolean providesConverter(String encoding) { protected boolean fillBuffer() {
// TODO Auto-generated method stub // TODO: implement
return false; return false;
} }
} }

View file

@ -21,7 +21,6 @@ package org.geometerplus.fbreader.formats.pdb;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
public class PdbHeader { public class PdbHeader {
static public String DocName; static public String DocName;
@ -29,41 +28,36 @@ public class PdbHeader {
static public String Id; static public String Id;
static public int[] Offsets; static public int[] Offsets;
public boolean read(InputStream stream) throws IOException { public PdbHeader(InputStream stream) throws IOException {
final byte[] buffer = new byte[32]; final byte[] buffer = new byte[32];
if (stream.read(buffer, 0, 32) != 32) { if (stream.read(buffer, 0, 32) != 32) {
System.err.println("way 0"); throw new IOException("PdbHeader: cannot reader document name");
return false;
} }
DocName = new String(buffer); DocName = new String(buffer);
Flags = PdbUtil.readShort(stream); Flags = PdbUtil.readShort(stream);
stream.skip(26); PdbUtil.skip(stream, 26);
if (stream.read(buffer, 0, 8) != 8) { if (stream.read(buffer, 0, 8) != 8) {
System.err.println("way 1"); throw new IOException("PdbHeader: cannot reader palm id");
return false;
} }
Id = new String(buffer, 0, 8); Id = new String(buffer, 0, 8);
stream.skip(8); PdbUtil.skip(stream, 8);
int numRecords = PdbUtil.readShort(stream); int numRecords = PdbUtil.readShort(stream);
if (numRecords <= 0) { if (numRecords <= 0) {
System.err.println(numRecords); throw new IOException("PdbHeader: record number = " + numRecords);
System.err.println("way 2");
return false;
} }
Offsets = new int[numRecords]; Offsets = new int[numRecords];
for (int i = 0; i < numRecords; ++i) { for (int i = 0; i < numRecords; ++i) {
Offsets[i] = PdbUtil.readInt(stream); Offsets[i] = (int)PdbUtil.readInt(stream);
if (stream.skip(4) != 4) { PdbUtil.skip(stream, 4);
System.err.println("way 3");
return false;
} }
} }
return true; public final int length() {
return 78 + Offsets.length * 8;
} }
} }

View file

@ -22,25 +22,25 @@ package org.geometerplus.fbreader.formats.pdb;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
//import org.geometerplus.fbreader.collection.BookDescriptionUtil;
import org.geometerplus.fbreader.formats.FormatPlugin;
import org.geometerplus.fbreader.formats.plucker.PluckerTextStream;
import org.geometerplus.zlibrary.core.filesystem.ZLFile; import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.options.ZLStringOption; import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.fbreader.formats.FormatPlugin;
public abstract class PdbPlugin extends FormatPlugin { public abstract class PdbPlugin extends FormatPlugin {
protected static String fileType(final ZLFile file) { @Override
final String extension = file.getExtension().toLowerCase().intern(); public boolean acceptsFile(ZLFile file) {
if ((extension != "prc") && (extension != "pdb") && (extension != "mobi")) { final String extension = file.getExtension();
return null; return (extension == "prc") || (extension == "pdb") || (extension == "mobi");
} }
protected static String fileType(final ZLFile file) {
ZLFile baseFile = file.getPhysicalFile(); ZLFile baseFile = file.getPhysicalFile();
boolean upToDate = true;//BookDescriptionUtil.checkInfo(baseFile);
// TODO: use database instead of option (?)
ZLStringOption palmTypeOption = new ZLStringOption(file.getPath(), "PalmType", ""); ZLStringOption palmTypeOption = new ZLStringOption(file.getPath(), "PalmType", "");
String palmType = palmTypeOption.getValue(); String palmType = palmTypeOption.getValue();
if ((palmType.length() != 8) || !upToDate) { if (palmType.length() != 8) {
byte[] id = new byte[8]; byte[] id = new byte[8];
try { try {
final InputStream stream = file.getInputStream(); final InputStream stream = file.getInputStream();
@ -48,18 +48,13 @@ public abstract class PdbPlugin extends FormatPlugin {
return null; return null;
} }
stream.skip(60); stream.skip(60);
stream.read(id, 0, 8); stream.read(id);
stream.close(); stream.close();
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
palmType = new String(id);
if (!upToDate) {
//BookDescriptionUtil.saveInfo(baseFile);
} }
palmType = new String(id).intern();
palmTypeOption.setValue(palmType); palmTypeOption.setValue(palmType);
} }
return palmType; return palmType.intern();
} }
} }

View file

@ -26,22 +26,28 @@ import org.geometerplus.zlibrary.core.filesystem.ZLFile;
public abstract class PdbStream extends InputStream { public abstract class PdbStream extends InputStream {
protected final InputStream myBase; protected final InputStream myBase;
private int myOffset; public PdbHeader myHeader;
public final PdbHeader myHeader = new PdbHeader();
protected byte[] myBuffer; protected byte[] myBuffer;
protected short myBufferLength; protected short myBufferLength;
protected short myBufferOffset; protected short myBufferOffset;
public PdbStream(ZLFile file) { public PdbStream(ZLFile file) throws IOException {
InputStream base; myBase = file.getInputStream();
try {
base = file.getInputStream(); myHeader = new PdbHeader(myBase);
} catch (IOException e) {
e.printStackTrace(); myBase.skip(myHeader.Offsets[0] - myHeader.length());
base = null;
myBufferLength = 0;
myBufferOffset = 0;
} }
myBase = base;
public int read() {
if (!fillBuffer()) {
return -1;
}
return myBuffer[myBufferOffset++];
} }
public int read(byte[] buffer,int offset, int maxSize) { public int read(byte[] buffer,int offset, int maxSize) {
@ -57,45 +63,8 @@ public abstract class PdbStream extends InputStream {
myBufferOffset += size; myBufferOffset += size;
} }
} }
myOffset += realSize;
return realSize; return realSize;
} }
/*public int read(byte[] buffer,int offset, int maxSize) {
int realSize = 0;
while (realSize < maxSize) {
if (!fillBuffer()) {
break;
}
int size = Math.min((maxSize - realSize), (myBufferLength - myBufferOffset));
if (size > 0) {
if (buffer != null) {
for (int i = 0; i < size; i++) {
myBuffer[myBufferOffset+i] = buffer[realSize+i];
}
//memcpy(buffer + realSize, myBuffer + myBufferOffset, size);
}
realSize += size;
myBufferOffset += size;
}
}
myOffset += realSize;
return realSize;
}*/
public boolean open() throws IOException {
if ((myBase == null) || !myHeader.read(myBase)) {
return false;
}
myBase.skip(myHeader.Offsets[0] - 78 - 8 * myHeader.Offsets.length);
myBufferLength = 0;
myBufferOffset = 0;
myOffset = 0;
return true;
}
public void close() throws IOException { public void close() throws IOException {
if (myBase != null) { if (myBase != null) {
@ -109,23 +78,10 @@ public abstract class PdbStream extends InputStream {
public void skip(int offset) throws IOException { public void skip(int offset) throws IOException {
if (offset > 0) { if (offset > 0) {
read(null, 0, offset); read(null, 0, offset);
} else if (offset < 0) { } else {
offset += this.offset(); throw new IOException("Cannot skip: " + offset + " bytes");
open();
if (offset >= 0) {
read(null, 0, offset);
} }
} }
}
public int offset() {
return myOffset;
}
public int sizeOfOpened() {
// TODO: implement
return 0;
}
protected abstract boolean fillBuffer(); protected abstract boolean fillBuffer();
} }

View file

@ -21,31 +21,28 @@ package org.geometerplus.fbreader.formats.pdb;
import java.io.*; import java.io.*;
public class PdbUtil { public abstract class PdbUtil {
public static int readShort(InputStream stream) { public static void skip(InputStream stream, int numBytes) throws IOException {
final byte[] tmp = new byte[2]; numBytes -= stream.skip(numBytes);
try { for (; numBytes > 0; --numBytes) {
stream.read(tmp, 0, 2); if (stream.read() == -1) {
} catch (IOException e) { throw new IOException("Unexpected end of stream");
return -1; }
} }
// int i = ((tmp[1] & 0xFF) + ((tmp[0] & 0xFF) << 8));
// if (i > Short.MAX_VALUE)
// System.out.println("i = " + i);
return ((tmp[1] & 0xFF) + ((tmp[0] & 0xFF) << 8));
} }
//? long public static int readShort(InputStream stream) throws IOException {
public static int readInt(InputStream stream) { final byte[] tmp = new byte[2];
final byte[] tmp = new byte[4]; stream.read(tmp, 0, 2);
try { return (tmp[1] & 0xFF) + ((tmp[0] & 0xFF) << 8);
stream.read(tmp, 0, 4);
} catch (IOException e) {
return -1;
} }
return (tmp[0] << 24) +
((tmp[1] & 0xFF) << 16) + public static long readInt(InputStream stream) throws IOException {
((tmp[2] & 0xFF) << 8) + final byte[] tmp = new byte[4];
(tmp[3] & 0xFF); stream.read(tmp, 0, 4);
return (((long)(tmp[0] & 0xFF)) << 24) +
+ ((tmp[1] & 0xFF) << 16) +
+ ((tmp[2] & 0xFF) << 8) +
+ (tmp[3] & 0xFF);
} }
} }

View file

@ -28,8 +28,6 @@ import org.geometerplus.zlibrary.core.image.*;
import org.geometerplus.zlibrary.text.model.*; import org.geometerplus.zlibrary.text.model.*;
import org.geometerplus.fbreader.bookmodel.*; import org.geometerplus.fbreader.bookmodel.*;
import org.geometerplus.fbreader.encoding.ZLEncodingConverter;
import org.geometerplus.fbreader.formats.EncodedTextReader;
import org.geometerplus.fbreader.formats.pdb.*; import org.geometerplus.fbreader.formats.pdb.*;
public class PluckerBookReader extends BookReader { public class PluckerBookReader extends BookReader {
@ -51,11 +49,9 @@ public class PluckerBookReader extends BookReader {
private ArrayList/*<Integer, Integer>*/ myParagraphVector = new ArrayList(); //<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> private ArrayList/*<Integer, Integer>*/ myParagraphVector = new ArrayList(); //<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private boolean myParagraphStored; private boolean myParagraphStored;
private final ZLEncodingConverter myConverter;
public PluckerBookReader(ZLFile file, BookModel model, String encoding){ public PluckerBookReader(ZLFile file, BookModel model, String encoding){
super(model); super(model);
myConverter = new EncodedTextReader(encoding).getConverter(); //myConverter = new EncodedTextReader(encoding).getConverter();
myFile = file; myFile = file;
//System.out.println(filePath + " " + encoding); //System.out.println(filePath + " " + encoding);
myFont = FontType.FT_REGULAR; myFont = FontType.FT_REGULAR;
@ -63,14 +59,11 @@ public class PluckerBookReader extends BookReader {
myForcedEntry = null; myForcedEntry = null;
} }
public boolean readDocument() throws IOException { public boolean readDocument() {
try {
myStream = new PdbInputStream(myFile); myStream = new PdbInputStream(myFile);
PdbHeader header = new PdbHeader(); PdbHeader header = new PdbHeader(myStream);
if (!header.read(myStream)) {
myStream.close();
return false;
}
setMainTextModel(); setMainTextModel();
myFont = FontType.FT_REGULAR; myFont = FontType.FT_REGULAR;
@ -91,6 +84,9 @@ public class PluckerBookReader extends BookReader {
readRecord(recordSize); readRecord(recordSize);
} }
myStream.close(); myStream.close();
} catch (IOException e) {
return false;
}
for (Iterator it = myReferencedParagraphs.iterator(); it.hasNext();) { for (Iterator it = myReferencedParagraphs.iterator(); it.hasNext();) {
Pair pair = (Pair)it.next(); Pair pair = (Pair)it.next();
@ -285,7 +281,7 @@ public class PluckerBookReader extends BookReader {
if (ptr > textStart) { if (ptr > textStart) {
safeBeginParagraph(); safeBeginParagraph();
// myConvertedTextBuffer = "";//.erase(); // myConvertedTextBuffer = "";//.erase();
myConvertedTextBuffer = myConverter.convert(data, textStart, ptr); myConvertedTextBuffer = "";//myConverter.convert(data, textStart, ptr);
addData(myConvertedTextBuffer.toCharArray()); addData(myConvertedTextBuffer.toCharArray());
myBufferIsEmpty = false; myBufferIsEmpty = false;
} }
@ -315,7 +311,7 @@ public class PluckerBookReader extends BookReader {
if (end > textStart) { if (end > textStart) {
safeBeginParagraph(); safeBeginParagraph();
// myConvertedTextBuffer = "";//erase(); // myConvertedTextBuffer = "";//erase();
myConvertedTextBuffer = myConverter.convert(data, textStart, end); myConvertedTextBuffer = "";//myConverter.convert(data, textStart, end);
addData(myConvertedTextBuffer.toCharArray()); addData(myConvertedTextBuffer.toCharArray());
myBufferIsEmpty = false; myBufferIsEmpty = false;
} }

View file

@ -36,7 +36,7 @@ public class PluckerPlugin extends PdbPlugin {
@Override @Override
public boolean readMetaInfo(Book book) { public boolean readMetaInfo(Book book) {
try { try {
PdbStream stream = new PluckerTextStream(book.File); PluckerTextStream stream = new PluckerTextStream(book.File);
if (stream.open()) { if (stream.open()) {
//detectEncodingAndLanguage(book, stream); //detectEncodingAndLanguage(book, stream);
stream.close(); stream.close();
@ -53,12 +53,6 @@ public class PluckerPlugin extends PdbPlugin {
@Override @Override
public boolean readModel(BookModel model) { public boolean readModel(BookModel model) {
try {
return new PluckerBookReader(model.Book.File, model, model.Book.getEncoding()).readDocument(); return new PluckerBookReader(model.Book.File, model, model.Book.getEncoding()).readDocument();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
} }
} }

View file

@ -30,7 +30,7 @@ public class PluckerTextStream extends PdbStream {
private byte[] myFullBuffer; private byte[] myFullBuffer;
private int myRecordIndex; private int myRecordIndex;
public PluckerTextStream(ZLFile file) { public PluckerTextStream(ZLFile file) throws IOException {
super(file); super(file);
myFullBuffer = null; myFullBuffer = null;
} }
@ -40,9 +40,9 @@ public class PluckerTextStream extends PdbStream {
} }
public boolean open() throws IOException { public boolean open() throws IOException {
if (!super.open()) { //if (!super.open()) {
return false; // return false;
} //}
myCompressionVersion = (short) PdbUtil.readShort(myBase); myCompressionVersion = (short) PdbUtil.readShort(myBase);

View file

@ -24,6 +24,8 @@ import java.util.*;
import org.geometerplus.zlibrary.core.util.ZLMiscUtil; import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
import org.geometerplus.zlibrary.core.filesystem.*; import org.geometerplus.zlibrary.core.filesystem.*;
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.geometerplus.fbreader.formats.*; import org.geometerplus.fbreader.formats.*;
public class Book { public class Book {
@ -77,7 +79,11 @@ public class Book {
if (book == null) { if (book == null) {
book = new Book(bookFile); book = new Book(bookFile);
} }
return book.readMetaInfo() ? book : null; if (book.readMetaInfo()) {
book.save();
return book;
}
return null;
} }
public final ZLFile File; public final ZLFile File;
@ -320,4 +326,14 @@ public class Book {
myIsSaved = true; myIsSaved = true;
return true; return true;
} }
public ZLTextPosition getStoredPosition() {
return BooksDatabase.Instance().getStoredPosition(myId);
}
public void storePosition(ZLTextPosition position) {
if (myId != -1) {
BooksDatabase.Instance().storePosition(myId, position);
}
}
} }

View file

@ -34,7 +34,8 @@ public class Bookmark {
} }
private long myId; private long myId;
private long myBookId; private final long myBookId;
private final String myBookTitle;
private String myText; private String myText;
private final Date myCreationDate; private final Date myCreationDate;
private Date myModificationDate; private Date myModificationDate;
@ -45,9 +46,10 @@ public class Bookmark {
private boolean myIsChanged; private boolean myIsChanged;
Bookmark(long id, long bookId, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCount, int paragraphIndex, int wordIndex, int charIndex) { Bookmark(long id, long bookId, String bookTitle, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCount, int paragraphIndex, int wordIndex, int charIndex) {
myId = id; myId = id;
myBookId = bookId; myBookId = bookId;
myBookTitle = bookTitle;
myText = text; myText = text;
myCreationDate = creationDate; myCreationDate = creationDate;
myModificationDate = modificationDate; myModificationDate = modificationDate;
@ -66,6 +68,7 @@ public class Bookmark {
public Bookmark(Book book, String text, ZLTextPosition position) { public Bookmark(Book book, String text, ZLTextPosition position) {
myId = -1; myId = -1;
myBookId = book.getId(); myBookId = book.getId();
myBookTitle = book.getTitle();
myText = text; myText = text;
myCreationDate = new Date(); myCreationDate = new Date();
myPosition = position; myPosition = position;
@ -84,6 +87,10 @@ public class Bookmark {
return myText; return myText;
} }
public String getBookTitle() {
return myBookTitle;
}
public ZLTextPosition getPosition() { public ZLTextPosition getPosition() {
return myPosition; return myPosition;
} }

View file

@ -23,6 +23,8 @@ import java.util.*;
import org.geometerplus.zlibrary.core.filesystem.ZLFile; import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
public abstract class BooksDatabase { public abstract class BooksDatabase {
private static BooksDatabase ourInstance; private static BooksDatabase ourInstance;
@ -75,12 +77,15 @@ public abstract class BooksDatabase {
protected abstract List<Long> listRecentBookIds(); protected abstract List<Long> listRecentBookIds();
protected abstract void saveRecentBookIds(final List<Long> ids); protected abstract void saveRecentBookIds(final List<Long> ids);
protected Bookmark createBookmark(long id, long bookId, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, int paragraphIndex, int wordIndex, int charIndex) { protected Bookmark createBookmark(long id, long bookId, String bookTitle, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, int paragraphIndex, int wordIndex, int charIndex) {
return new Bookmark(id, bookId, text, creationDate, modificationDate, accessDate, accessCounter, paragraphIndex, wordIndex, charIndex); return new Bookmark(id, bookId, bookTitle, text, creationDate, modificationDate, accessDate, accessCounter, paragraphIndex, wordIndex, charIndex);
} }
protected abstract List<Bookmark> listBookmarks(long bookId); protected abstract List<Bookmark> listBookmarks(long bookId);
protected abstract List<Bookmark> listAllBookmarks(); protected abstract List<Bookmark> listAllBookmarks();
protected abstract long saveBookmark(Bookmark bookmark); protected abstract long saveBookmark(Bookmark bookmark);
protected abstract void deleteBookmark(Bookmark bookmark); protected abstract void deleteBookmark(Bookmark bookmark);
protected abstract ZLTextPosition getStoredPosition(long bookId);
protected abstract void storePosition(long bookId, ZLTextPosition position);
} }

View file

@ -27,8 +27,6 @@ import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.view.ZLViewWidget; import org.geometerplus.zlibrary.core.view.ZLViewWidget;
import org.geometerplus.zlibrary.text.view.style.*; import org.geometerplus.zlibrary.text.view.style.*;
import org.geometerplus.fbreader.encoding.ZLEncodingCollection;
import org.geometerplus.fbreader.encodingOption.*;
import org.geometerplus.fbreader.fbreader.*; import org.geometerplus.fbreader.fbreader.*;
import org.geometerplus.fbreader.formats.PluginCollection; import org.geometerplus.fbreader.formats.PluginCollection;

View file

@ -30,8 +30,6 @@ public abstract class ZLConfig {
ourInstance = this; ourInstance = this;
} }
public abstract void executeAsATransaction(Runnable actions);
public abstract String getValue(String group, String name, String defaultValue); public abstract String getValue(String group, String name, String defaultValue);
public abstract void setValue(String group, String name, String value); public abstract void setValue(String group, String name, String value);
public abstract void unsetValue(String group, String name); public abstract void unsetValue(String group, String name);

View file

@ -0,0 +1,96 @@
/*
* Copyright (C) 2007-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.zlibrary.core.encoding;
import java.util.HashMap;
import org.geometerplus.zlibrary.core.filesystem.ZLResourceFile;
import org.geometerplus.zlibrary.core.library.ZLibrary;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.xml.ZLXMLReaderAdapter;
public final class ZLEncodingCollection {
private static ZLEncodingCollection ourInstance;
public static ZLEncodingCollection Instance() {
if (ourInstance == null) {
ourInstance = new ZLEncodingCollection();
}
return ourInstance;
}
private final HashMap<String,String> myEncodingByAlias = new HashMap<String,String>();
private ZLEncodingCollection() {
new ZLEncodingCollectionReader().read(
ZLResourceFile.createResourceFile("data/encodings/Encodings.xml")
);
}
public String getEncodingName(String alias) {
final String name = myEncodingByAlias.get(alias);
return (name != null) ? name : alias;
}
public String getEncodingName(int code) {
return myEncodingByAlias.get("" + code);
}
private class ZLEncodingCollectionReader extends ZLXMLReaderAdapter {
private String myCurrentEncodingName;
public ZLEncodingCollectionReader() {
}
public boolean dontCacheAttributeValues() {
return true;
}
private static final String ENCODING = "encoding";
private static final String NAME = "name";
private static final String ALIAS = "alias";
private static final String CODE = "code";
private static final String NUMBER = "number";
public boolean startElementHandler(String tag, ZLStringMap attributes) {
if (ENCODING == tag) {
myCurrentEncodingName = attributes.getValue(NAME);
} else if (myCurrentEncodingName != null) {
String alias = null;
if (ALIAS == tag) {
alias = attributes.getValue(NAME);
} else if (CODE == tag) {
alias = attributes.getValue(NUMBER);
}
if (alias != null) {
myEncodingByAlias.put(alias, myCurrentEncodingName);
}
}
return false;
}
public boolean endElementHandler(String tag) {
if (ENCODING == tag) {
myCurrentEncodingName = null;
}
return false;
}
}
}

View file

@ -56,18 +56,22 @@ public abstract class ZLArchiveEntryFile extends ZLFile {
init(); init();
} }
@Override
public boolean exists() { public boolean exists() {
return myParent.exists(); return myParent.exists();
} }
@Override
public boolean isDirectory() { public boolean isDirectory() {
return false; return false;
} }
@Override
public String getPath() { public String getPath() {
return myParent.getPath() + ":" + myName; return myParent.getPath() + ":" + myName;
} }
@Override
public String getNameWithExtension() { public String getNameWithExtension() {
if (myShortName == null) { if (myShortName == null) {
final String name = myName; final String name = myName;
@ -81,10 +85,12 @@ public abstract class ZLArchiveEntryFile extends ZLFile {
return myShortName; return myShortName;
} }
@Override
public ZLFile getParent() { public ZLFile getParent() {
return myParent; return myParent;
} }
@Override
public ZLPhysicalFile getPhysicalFile() { public ZLPhysicalFile getPhysicalFile() {
ZLFile ancestor = myParent; ZLFile ancestor = myParent;
while ((ancestor != null) && !(ancestor instanceof ZLPhysicalFile)) { while ((ancestor != null) && !(ancestor instanceof ZLPhysicalFile)) {

View file

@ -94,6 +94,7 @@ public abstract class ZLFile {
return new ZLPhysicalFile(path); return new ZLPhysicalFile(path);
} }
public abstract long size();
public abstract boolean exists(); public abstract boolean exists();
public abstract boolean isDirectory(); public abstract boolean isDirectory();
public abstract String getPath(); public abstract String getPath();
@ -118,53 +119,6 @@ public abstract class ZLFile {
return myExtension; return myExtension;
} }
/*
public InputStream getInputStream() throws IOException {
InputStream stream = null;
int index = ZLFSUtil.findArchiveFileNameDelimiter(myPath);
if (index == -1) {
stream = ZLibrary.Instance().getInputStream(myPath);
} else {
ZLFile baseFile = new ZLFile(myPath.substring(0, index));
InputStream base = baseFile.getInputStream();
if (base != null) {
if (0 != (baseFile.myArchiveType & ArchiveType.ZIP)) {
ZipFile zf = getZipFile(myPath.substring(0, index));
/*
ZipEntry entry = zf.getEntry(myPath.substring(index+1));
stream = zf.getInputStream(entry);
* /
final String entryName = myPath.substring(index + 1);
stream = zf.getInputStream(entryName);
/*
while (true) {
ZipEntry entry = zipStream.getNextEntry();
if (entry == null) {
break;
} else if (entryName.equals(entry.getName())) {
stream = zipStream;
break;
}
}
* /
} else if (0 != (baseFile.myArchiveType & ArchiveType.TAR)) {
stream = new ZLTarInputStream(base, myPath.substring(index + 1));
}
}
}
if (stream != null) {
if (0 != (myArchiveType & ArchiveType.GZIP)) {
return new java.util.zip.GZIPInputStream(stream, 8192);
}
//if (0 != (myArchiveType & ArchiveType.BZIP2)) {
//return new ZLBzip2InputStream(stream);
//}
}
return stream;
}
*/
protected List<ZLFile> directoryEntries() { protected List<ZLFile> directoryEntries() {
return Collections.emptyList(); return Collections.emptyList();
} }

View file

@ -36,39 +36,46 @@ public final class ZLPhysicalFile extends ZLFile {
init(); init();
} }
@Override
public boolean exists() { public boolean exists() {
return myFile.exists(); return myFile.exists();
} }
@Override
public long size() { public long size() {
return myFile.length(); return myFile.length();
} }
@Override
public boolean isDirectory() { public boolean isDirectory() {
return myFile.isDirectory(); return myFile.isDirectory();
//return myFile.length() == 0;
} }
public boolean remove() { public boolean remove() {
return myFile.delete(); return myFile.delete();
} }
@Override
public String getPath() { public String getPath() {
return myFile.getPath(); return myFile.getPath();
} }
@Override
public String getNameWithExtension() { public String getNameWithExtension() {
return myFile.getName(); return myFile.getName();
} }
@Override
public ZLFile getParent() { public ZLFile getParent() {
return isDirectory() ? null : new ZLPhysicalFile(myFile.getParent()); return isDirectory() ? null : new ZLPhysicalFile(myFile.getParent());
} }
@Override
public ZLPhysicalFile getPhysicalFile() { public ZLPhysicalFile getPhysicalFile() {
return this; return this;
} }
@Override
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
return new FileInputStream(myFile); return new FileInputStream(myFile);
} }

View file

@ -67,6 +67,12 @@ final class ZLZipEntryFile extends ZLArchiveEntryFile {
super(parent, name); super(parent, name);
} }
@Override
public long size() {
throw new RuntimeException("Not implemented yet.");
}
@Override
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
return getZipFile(myParent).getInputStream(myName); return getZipFile(myParent).getInputStream(myName);
} }

View file

@ -56,11 +56,13 @@ public final class ZLTarEntryFile extends ZLArchiveEntryFile {
super(parent, name); super(parent, name);
} }
public InputStream getInputStream() throws IOException { @Override
InputStream base = myParent.getInputStream(); public long size() {
if (base != null) { throw new RuntimeException("Not implemented yet.");
return new ZLTarInputStream(base, myName);
} }
return null;
@Override
public InputStream getInputStream() throws IOException {
return new ZLTarInputStream(myParent.getInputStream(), myName);
} }
} }

View file

@ -29,11 +29,6 @@ public final class ZLIntegerOption extends ZLOption {
myValue = defaultValue; myValue = defaultValue;
} }
public void changeName(String optionName) {
super.changeName(optionName);
myValue = myDefaultValue;
}
public int getValue() { public int getValue() {
if (!myIsSynchronized) { if (!myIsSynchronized) {
String value = getConfigValue(null); String value = getConfigValue(null);

View file

@ -0,0 +1,157 @@
/*
* Copyright (C) 2008-2009 Geometer Plus <contact@geometerplus.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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.zlibrary.core.util;
public abstract class ZLLanguageUtil {
public static String languageByCode(int languageCode, int subLanguageCode) {
switch (languageCode) {
default: return null;
case 0x01: return "ar"; // Arabic
case 0x02: return "bg"; // Bulgarian
case 0x03: return "ca"; // Catalan
case 0x04: return "zh"; // Chinese
case 0x05: return "cs"; // Czech
case 0x06: return "da"; // Danish
case 0x07: return "de"; // German
case 0x08: return "el"; // Greek
case 0x09: return "en"; // English
case 0x0A: return "es"; // Spanish
case 0x0B: return "fi"; // Finnish
case 0x0C: return "fr"; // French
case 0x0D: return "he"; // Hebrew
case 0x0E: return "hu"; // Hungarian
case 0x0F: return "is"; // Icelandic
case 0x10: return "it"; // Italian
case 0x11: return "ja"; // Japanese
case 0x12: return "ko"; // Korean
case 0x13: return "nl"; // Dutch
case 0x14: return "no"; // Norwegian
case 0x15: return "pl"; // Polish
case 0x16: return "pt"; // Portuguese
case 0x17: return "rm"; // Romansh
case 0x18: return "ro"; // Romanian
case 0x19: return "ru"; // Russian
case 0x1A:
switch (subLanguageCode) {
default: return "sr"; // Serbian
case 0x04:
case 0x10: return "hr"; // Croatian
case 0x14:
case 0x20:
case 0x78: return "bs"; // Bosnian
}
case 0x1B: return "sk"; // Slovak
case 0x1C: return "sq"; // Albanian
case 0x1D: return "sv"; // Swedish
case 0x1E: return "th"; // Thai
case 0x1F: return "tr"; // Turkish
case 0x20: return "ur"; // Urdu
case 0x21: return "id"; // Indonesian
case 0x22: return "uk"; // Ukrainian
case 0x23: return "be"; // Belarusian
case 0x24: return "sl"; // Slovenian
case 0x25: return "et"; // Estonian
case 0x26: return "lv"; // Latvian
case 0x27: return "lt"; // Lithuanian
case 0x28: return "tg"; // Tajik
case 0x29: return "fa"; // Persian (Farsi)
case 0x2A: return "vi"; // Vietnamese
case 0x2B: return "hy"; // Armenian
case 0x2C: return "az"; // Azeri
case 0x2D: return "eu"; // Basque
case 0x2E: return (subLanguageCode == 0x08)
? "dsb" // Lower Sorbian
: "wen"; // Upper Sorbian
case 0x2F: return "mk"; // Makedonian
case 0x32: return "tn"; // Setswana/Tswana
case 0x34: return "xh"; // Xhosa/isiXhosa
case 0x35: return "zu"; // Zulu/isiZulu
case 0x36: return "af"; // Afrikaans
case 0x37: return "ka"; // Georgian
case 0x38: return "fo"; // Faeroese
case 0x39: return "hi"; // Hindi
case 0x3A: return "mt"; // Maltese
case 0x3B: return "se"; // Sami
case 0x3C: return "ga"; // Irish
case 0x3E: return "ms"; // Malay
case 0x3F: return "kk"; // Kazak
case 0x40: return "ky"; // Kyrgyz
case 0x41: return "sw"; // Swahili
case 0x42: return "tk"; // Turkmen
case 0x43: return "uz"; // Uzbek
case 0x44: return "tt"; // Tatar
case 0x45: return "bn"; // Bengali
case 0x46: return "pa"; // Punjabi
case 0x47: return "gu"; // Gujaratu
case 0x48: return "or"; // Oriya
case 0x49: return "ta"; // Tamil
case 0x4A: return "te"; // Telugi
case 0x4B: return "kn"; // Kannada
case 0x4C: return "ml"; // Malayalam
case 0x4D: return "as"; // Assamese
case 0x4E: return "mr"; // Marathi
case 0x4F: return "sa"; // Sanskrit
case 0x50: return "mn"; // Mongolian
case 0x51: return "bo"; // Tibetian
case 0x52: return "cy"; // Welsh
case 0x53: return "kh"; // Khmer
case 0x54: return "lo"; // Lao
case 0x56: return "gl"; // Galician
case 0x57: return "kok"; // Konkani
case 0x58: return "mni"; // Manipuri
case 0x59: return "sd"; // Sindhi
case 0x5A: return "syr"; // Syriac
case 0x5B: return "si"; // Sinhala
case 0x5D: return "iu"; // Inuktitut
case 0x5E: return "am"; // Amharic
case 0x5F: return "tzm"; // Tamazight
case 0x60: return "ks"; // Kashmiri
case 0x61: return "ne"; // Nepali
case 0x62: return "fy"; // Frisian
case 0x63: return "ps"; // Pashto
case 0x64: return "fil"; // Filipino
case 0x65: return "dv"; // Divehi
case 0x68: return "ha"; // Hausa
case 0x6A: return "yo"; // Yoruba
case 0x6B: return "quz"; // Quechua
case 0x6C: return "ns"; // Northern Sotho
case 0x6D: return "ba"; // Bashkir
case 0x6E: return "lb"; // Luxemburgish
case 0x6F: return "kl"; // Greenlandic
case 0x70: return "ig"; // Igbo
case 0x73: return "ti"; // Tigrinya
case 0x78: return "yi"; // Yi
case 0x7A: return "arn"; // Mapudungun
case 0x7C: return "moh"; // Mohawk
case 0x7E: return "be"; // Breton
case 0x80: return "ug"; // Uighur
case 0x81: return "mi"; // Maori
case 0x82: return "oc"; // Occitan
case 0x83: return "co"; // Corsican
case 0x84: return "gsw"; // Alsatian
case 0x85: return "sah"; // Yakut
case 0x86: return "qut"; // K'iche
case 0x87: return "rw"; // Kinyarwanda
case 0x88: return "wo"; // Wolof
case 0x8C: return "prs"; // Dari
case 0x8D: return "mg"; // Malagasy
}
}
}

View file

@ -28,8 +28,6 @@ abstract public class ZLView {
Context = context; Context = context;
} }
abstract public String getCaption();
public static final int PAGE_CENTRAL = 0; public static final int PAGE_CENTRAL = 0;
public static final int PAGE_LEFT = 1; public static final int PAGE_LEFT = 1;
public static final int PAGE_RIGHT = 2; public static final int PAGE_RIGHT = 2;

View file

@ -263,24 +263,10 @@ public abstract class ZLTextViewImpl extends ZLTextView {
if (myCurrentPage.StartCursor.isNull()) { if (myCurrentPage.StartCursor.isNull()) {
preparePaintInfo(myCurrentPage); preparePaintInfo(myCurrentPage);
} }
/* if (!position.equalsToCursor(myCurrentPage.StartCursor)) {
savePosition(position);
}
*/
savePosition(position, myCurrentPage.StartCursor);
ZLApplication.Instance().repaintView(); ZLApplication.Instance().repaintView();
} }
} }
protected void savePosition(ZLTextPosition position) {
}
protected final void savePosition(ZLTextPosition position, ZLTextWordCursor cursorToCheck) {
if (!position.equalsToCursor(cursorToCheck)) {
savePosition(position);
}
}
public int search(final String text, boolean ignoreCase, boolean wholeText, boolean backward, boolean thisSectionOnly) { public int search(final String text, boolean ignoreCase, boolean wholeText, boolean backward, boolean thisSectionOnly) {
if (text.length() == 0) { if (text.length() == 0) {
return 0; return 0;
@ -383,9 +369,6 @@ public abstract class ZLTextViewImpl extends ZLTextView {
myNextPage.StartCursor.setCursor(myCurrentPage.EndCursor); myNextPage.StartCursor.setCursor(myCurrentPage.EndCursor);
myNextPage.PaintState = PaintStateEnum.START_IS_KNOWN; myNextPage.PaintState = PaintStateEnum.START_IS_KNOWN;
} }
if (myCurrentPage.PaintState == PaintStateEnum.READY) {
onPaintInfoPrepared();
}
break; break;
} }
case PAGE_RIGHT: case PAGE_RIGHT:
@ -401,9 +384,6 @@ public abstract class ZLTextViewImpl extends ZLTextView {
myCurrentPage.StartCursor.setCursor(myNextPage.EndCursor); myCurrentPage.StartCursor.setCursor(myNextPage.EndCursor);
myCurrentPage.PaintState = PaintStateEnum.START_IS_KNOWN; myCurrentPage.PaintState = PaintStateEnum.START_IS_KNOWN;
} }
if (myCurrentPage.PaintState == PaintStateEnum.READY) {
onPaintInfoPrepared();
}
break; break;
} }
} }
@ -487,14 +467,14 @@ public abstract class ZLTextViewImpl extends ZLTextView {
} }
public final int getScrollbarFullSize() { public final int getScrollbarFullSize() {
if ((myTextSize == null) || (myTextSize.length == 0)) { if ((myModel == null) || (myTextSize == null) || (myTextSize.length == 0)) {
return 1; return 1;
} }
return myTextSize[myTextSize.length - 1]; return myTextSize[myTextSize.length - 1];
} }
public final int getScrollbarThumbPosition(int viewPage) { public final int getScrollbarThumbPosition(int viewPage) {
if ((myTextSize == null) || (myTextSize.length == 0)) { if ((myModel == null) || (myTextSize == null) || (myTextSize.length == 0)) {
return 0; return 0;
} }
ZLTextPage page = getPage(viewPage); ZLTextPage page = getPage(viewPage);
@ -503,7 +483,7 @@ public abstract class ZLTextViewImpl extends ZLTextView {
} }
public final int getScrollbarThumbLength(int viewPage) { public final int getScrollbarThumbLength(int viewPage) {
if ((myTextSize == null) || (myTextSize.length == 0)) { if ((myModel == null) || (myTextSize == null) || (myTextSize.length == 0)) {
return 0; return 0;
} }
ZLTextPage page = getPage(viewPage); ZLTextPage page = getPage(viewPage);
@ -1042,10 +1022,12 @@ public abstract class ZLTextViewImpl extends ZLTextView {
} }
public final void gotoPosition(ZLTextPosition position) { public final void gotoPosition(ZLTextPosition position) {
if (position != null) {
gotoPosition(position.ParagraphIndex, position.WordIndex, position.CharIndex); gotoPosition(position.ParagraphIndex, position.WordIndex, position.CharIndex);
} }
}
public final void gotoPosition(int paragraphIndex, int wordIndex, int charIndex) { private void gotoPosition(int paragraphIndex, int wordIndex, int charIndex) {
final int maxParagraphIndex = myModel.getParagraphsNumber() - 1; final int maxParagraphIndex = myModel.getParagraphsNumber() - 1;
if (paragraphIndex > maxParagraphIndex) { if (paragraphIndex > maxParagraphIndex) {
paragraphIndex = maxParagraphIndex; paragraphIndex = maxParagraphIndex;
@ -1216,13 +1198,9 @@ public abstract class ZLTextViewImpl extends ZLTextView {
if (page == myCurrentPage) { if (page == myCurrentPage) {
myPreviousPage.reset(); myPreviousPage.reset();
myNextPage.reset(); myNextPage.reset();
onPaintInfoPrepared();
} }
} }
protected void onPaintInfoPrepared() {
}
public void clearCaches() { public void clearCaches() {
rebuildPaintInfo(); rebuildPaintInfo();
} }