mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2025-01-22 00:32:08 +00:00
Implement Gutenberg disk translation
This commit is contained in:
parent
1a46ae1126
commit
2eb1437326
@ -34,6 +34,7 @@ import com.webcodepro.applecommander.storage.os.cpm.CpmFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.dos33.DosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.dos33.OzDosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.dos33.UniDosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.gutenberg.GutenbergFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.pascal.PascalFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.os.rdos.RdosFormatDisk;
|
||||
@ -191,7 +192,7 @@ public class Disk {
|
||||
if (isProdosOrder()) {
|
||||
imageOrder = new ProdosOrder(diskImageManager);
|
||||
} else if (isDosOrder()) {
|
||||
imageOrder = new DosOrder(diskImageManager);
|
||||
imageOrder = new DosOrder(diskImageManager);
|
||||
} else if (isNibbleOrder()) {
|
||||
imageOrder = new NibbleOrder(diskImageManager);
|
||||
}
|
||||
@ -256,10 +257,13 @@ public class Disk {
|
||||
} else if (isCpmFormat()) {
|
||||
return new FormattedDisk[]
|
||||
{ new CpmFormatDisk(filename, imageOrder) };
|
||||
} else if (isWPFormat()) {
|
||||
return new FormattedDisk[]
|
||||
{ new GutenbergFormatDisk(filename, imageOrder) };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the diskImage.
|
||||
* @return byte[]
|
||||
@ -556,6 +560,20 @@ public class Disk {
|
||||
return "RDOS".equals(id); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the disk format to see if this is a WP formatted
|
||||
* disk.
|
||||
*/
|
||||
public boolean isWPFormat() {
|
||||
if (!is140KbDisk()) return false;
|
||||
byte[] vtoc = readSector(17, 7);
|
||||
return (imageOrder.isSizeApprox(APPLE_140KB_DISK)
|
||||
|| imageOrder.isSizeApprox(APPLE_140KB_NIBBLE_DISK))
|
||||
&& vtoc[0x00] == 17 // expect catalog to start on track 17
|
||||
&& vtoc[0x01] == 7 // expect catalog to start on sector 7
|
||||
&& vtoc[0x0f] == -115; // expect 0x8d's every 16 bytes
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the disk has changed. Triggered when data is
|
||||
* written and cleared when data is saved.
|
||||
|
@ -23,6 +23,7 @@ DiskNameN={0} (Disk {1})
|
||||
Dos33=DOS 3.3
|
||||
LockedQ=Locked?
|
||||
DirectoryCreationNotSupported=Unable to create directories.
|
||||
Gutenberg=Gutenberg
|
||||
|
||||
##### FIX #####
|
||||
###############
|
||||
@ -155,6 +156,9 @@ DosFormatDisk.InvalidTrackAndSectorCombinationError=Invalid track ({0}), sector
|
||||
DosFileEntry.DosFileEntryLengthError=A DOS 3.3 file entry must be {0} bytes long\!
|
||||
DosFileEntry.UnableToSetAddressError=Unable to set address for DosFileEntry [{0}]
|
||||
|
||||
# GutenbergFileEntry
|
||||
GutenbergFileEntry.GutenbergFileEntryLengthError=A Gutenberg file entry must be {0} bytes long\!
|
||||
|
||||
# CpmFormatDisk
|
||||
CpmFormatDisk.DiskName=CP/M Volume
|
||||
CpmFormatDisk.Cpm=CP/M
|
||||
|
@ -0,0 +1,553 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2002, 2008 by Robert Greene
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage.filters;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.webcodepro.applecommander.storage.FileEntry;
|
||||
import com.webcodepro.applecommander.storage.FileFilter;
|
||||
import com.webcodepro.applecommander.ui.AppleCommander;
|
||||
import com.webcodepro.applecommander.util.AppleUtil;
|
||||
|
||||
/**
|
||||
* Extract the contents of an ancient word processor file (might be Word
|
||||
* Perfect) and convert to a text format. Currently supported formats are plain
|
||||
* text, HTML, or RTF. These are not exact duplicates, but they are close
|
||||
* approximations. RTF format is suitable for conversion to other word
|
||||
* processors.
|
||||
* <p>
|
||||
* To choose export format, use the appropriately named select method.
|
||||
* <p>
|
||||
* Date created: Dec 18, 2008 9:09:21 AM
|
||||
*
|
||||
* @author David Schmidt
|
||||
*/
|
||||
public class GutenbergFileFilter implements FileFilter {
|
||||
/*
|
||||
* This list identifies the various rendering options. As the internal
|
||||
* format may change in the future, the internal representation is hidden
|
||||
* and the developer should use the appropriate select method.
|
||||
*/
|
||||
private static final int RENDER_AS_TEXT = 0;
|
||||
private static final int RENDER_AS_HTML = 1;
|
||||
private static final int RENDER_AS_RTF = 2;
|
||||
private int rendering = RENDER_AS_HTML;
|
||||
/**
|
||||
* Constructor for GutenbergFileFilter.
|
||||
*/
|
||||
public GutenbergFileFilter() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given FileEntry and return a byte array with filtered data.
|
||||
*
|
||||
* @see com.webcodepro.applecommander.storage.FileFilter#filter(FileEntry)
|
||||
*/
|
||||
public byte[] filter(FileEntry fileEntry) {
|
||||
byte[] fileData = fileEntry.getFileData();
|
||||
int offset = 0;
|
||||
ByteArrayOutputStream byteArray = new ByteArrayOutputStream(
|
||||
fileData.length);
|
||||
PrintWriter printWriter = new PrintWriter(byteArray, true);
|
||||
while (offset < fileData.length) {
|
||||
fileData[offset] = (byte) (fileData[offset++] & 0x7f);
|
||||
}
|
||||
String preprocess = new String(fileData).trim();
|
||||
handleTranslation(preprocess, printWriter, rendering);
|
||||
printWriter.flush();
|
||||
return byteArray.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform text into desired destination format
|
||||
*/
|
||||
protected void handleTranslation(String raw, PrintWriter output, int rendering) {
|
||||
boolean ignoreBr = false;
|
||||
boolean inHeader = false;
|
||||
boolean inItalics = false;
|
||||
boolean inBold = false;
|
||||
boolean inCenter = false;
|
||||
boolean inUnderline = false;
|
||||
boolean inSuperscript = false;
|
||||
String cooked = raw.replaceAll("\\x00", ""); //$NON-NLS-1$ $NON-NLS-2$ Remove nulls
|
||||
cooked=cooked.replaceAll("<[a|A]1>", ""); //$NON-NLS-1$ $NON-NLS-2$ File start
|
||||
cooked=cooked.replaceAll("<e9>", ""); //$NON-NLS-1$ $NON-NLS-2$ End of file
|
||||
cooked=cooked.replaceAll("<d1>", ""); //$NON-NLS-1$ $NON-NLS-2$ File start
|
||||
cooked=cooked.replaceAll("<s1>", ""); //$NON-NLS-1$ $NON-NLS-2$ File start
|
||||
cooked=cooked.replaceAll("<2>", ""); //$NON-NLS-1$ $NON-NLS-2$ Dunno what this is
|
||||
cooked=cooked.replaceAll("<f9>", ""); //$NON-NLS-1$ $NON-NLS-2$ Dunno what this is
|
||||
cooked=cooked.replaceAll("<i>", ""); //$NON-NLS-1$ $NON-NLS-2$ Dunno what this is
|
||||
cooked=cooked.replaceAll("<i1>", ""); //$NON-NLS-1$ $NON-NLS-2$ Dunno what this is
|
||||
cooked=cooked.replaceAll("<[h|H]1>(.*)", "<h1>$1</h1>"); //$NON-NLS-1$ $NON-NLS-2$ Bound a h1 heading
|
||||
cooked=cooked.replaceAll("<[h|H]2>(.*)", "<h2>$1</h2>"); //$NON-NLS-1$ $NON-NLS-2$ Bound a h2 heading
|
||||
cooked=cooked.replaceAll("<[h|H]3>(.*)", "<h3>$1</h3>"); //$NON-NLS-1$ $NON-NLS-2$ Bound a h3 heading
|
||||
cooked=cooked.replaceAll("<[h|H]4>(.*)", "<h4>$1</h4>"); //$NON-NLS-1$ $NON-NLS-2$ Bound a h4 heading
|
||||
cooked=cooked.replaceAll("<[n|N]1>(.*)", "<h1>$1</h1>"); //$NON-NLS-1$ $NON-NLS-2$ Another kind of heading? Give it boundaries
|
||||
cooked=cooked.replaceAll("<[n|N]2>(.*)", "<h2>$1</h2>"); //$NON-NLS-1$ $NON-NLS-2$ Another kind of heading? Give it boundaries
|
||||
cooked=cooked.replaceAll("<[n|N]3>(.*)", "<h3>$1</h3>"); //$NON-NLS-1$ $NON-NLS-2$ Another kind of heading? Give it boundaries
|
||||
cooked=cooked.replaceAll("<[t|T]1>", "<p>"); //$NON-NLS-1$ $NON-NLS-2$ Tab level 1
|
||||
cooked=cooked.replaceAll("<[t|T]2>(.*)", "<blockquote>$1</blockquote>"); //$NON-NLS-1$ $NON-NLS-2$ Tab level 2
|
||||
cooked=cooked.replaceAll("<[t|T]3>(.*)", "<blockquote><blockquote>$1</blockquote></blockquote>"); //$NON-NLS-1$ $NON-NLS-2$ Tab level 3
|
||||
cooked=cooked.replaceAll("\\x0f", "</i>"); //$NON-NLS-1$ $NON-NLS-2$ Italics off
|
||||
cooked=cooked.replaceAll("\\x01(.*)", " <i>$1</i>"); //$NON-NLS-1$ $NON-NLS-2$ Italics on
|
||||
cooked=cooked.replaceAll("\\x02(.*)", " <i>$1</i>"); //$NON-NLS-1$ $NON-NLS-2$ Italics on
|
||||
cooked=cooked.replaceAll("~", "\""); //$NON-NLS-1$ $NON-NLS-2$ Leading quote
|
||||
cooked=cooked.replaceAll("_", "-"); //$NON-NLS-1$ $NON-NLS-2$
|
||||
StringTokenizer newlines = new StringTokenizer(cooked, "\r", false); //$NON-NLS-1$
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.println("<body><html>");
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.print("{\\rtf1"); //$NON-NLS-1$
|
||||
output.print("{\\fonttbl{\\f0\\fmodern\\fprq1;}}"); //$NON-NLS-1$
|
||||
output.print("{\\*\\generator AppleCommander "); //$NON-NLS-1$
|
||||
output.print(AppleCommander.VERSION);
|
||||
output.println(";}"); //$NON-NLS-1$
|
||||
output.print("\\f0 "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while (newlines.hasMoreTokens())
|
||||
{
|
||||
int mode = 0;
|
||||
String line = newlines.nextToken();
|
||||
StringTokenizer commands = new StringTokenizer(line,"<>",true);
|
||||
while (commands.hasMoreTokens())
|
||||
{
|
||||
String t = commands.nextToken();
|
||||
if (t.equals("<")) //$NON-NLS-1$
|
||||
mode = 1;
|
||||
else if (t.equals(">")) //$NON-NLS-1$
|
||||
mode = 0;
|
||||
else if (mode == 1) {
|
||||
if (t.startsWith("NF")) //$NON-NLS-1$
|
||||
{
|
||||
// do nothing... consume it
|
||||
}
|
||||
else if (t.equalsIgnoreCase("i") && (!inItalics)) //$NON-NLS-1$
|
||||
{
|
||||
// Italics on
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<i>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\i "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inItalics = true;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("/i")) //$NON-NLS-1$
|
||||
{
|
||||
// Italics off
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</i>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\i0 "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inItalics = false;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("p") || t.startsWith("j") || t.startsWith("J")) //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$
|
||||
{
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<p>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\par "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ignoreBr = true;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("UL") && (!inUnderline)) //$NON-NLS-1$
|
||||
{
|
||||
switch (rendering)
|
||||
{
|
||||
// Underline on
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<u>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\ul "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inUnderline = true;
|
||||
}
|
||||
else if ((t.equalsIgnoreCase("KU") || t.equalsIgnoreCase("KL") || t.equalsIgnoreCase("UK")) && (inUnderline)) //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$
|
||||
{
|
||||
// Underline off
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</u>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\ulnone "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inUnderline = false;
|
||||
}
|
||||
else if ((t.equalsIgnoreCase("BO") || t.equalsIgnoreCase("b1")) && (!inBold)) //$NON-NLS-1$ $NON-NLS-2$
|
||||
{
|
||||
// Bold on
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<b>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\b "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inBold = true;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("KB")) //$NON-NLS-1$
|
||||
{
|
||||
// Bold off
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</b>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\b0 "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inUnderline = false;
|
||||
}
|
||||
else if ((t.equalsIgnoreCase("UFA") || t.equalsIgnoreCase("UFP") || t.equals("UFY") || t.equalsIgnoreCase("f1")) && (inSuperscript == false)) //$NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ $NON-NLS-4$
|
||||
{
|
||||
// Superscript on
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<sup>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\super "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inSuperscript = true;
|
||||
}
|
||||
else if ((t.equalsIgnoreCase("UFM") || t.equalsIgnoreCase("f2")) && (inSuperscript == true)) //$NON-NLS-1$ $NON-NLS-2$
|
||||
{
|
||||
// Superscript off
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</sup>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\nosupersub"); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inSuperscript = false;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("co") && (inCenter == false)) //$NON-NLS-1$
|
||||
{
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<center>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\pard\\qc "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inCenter = true;
|
||||
ignoreBr = true;
|
||||
}
|
||||
else if (t.equalsIgnoreCase("h8") && (inCenter == true)) //$NON-NLS-1$
|
||||
{
|
||||
// Center off
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</center>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("\\par \\pard "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inCenter = false;
|
||||
ignoreBr = true;
|
||||
}
|
||||
else if (t.startsWith("h") && (!inHeader)) //$NON-NLS-1$
|
||||
{
|
||||
ignoreBr = true;
|
||||
inHeader = true;
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
if (t.equalsIgnoreCase("h1")) //$NON-NLS-1$
|
||||
output.print("<h1>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h2")) //$NON-NLS-1$
|
||||
output.print("<h2>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h3")) //$NON-NLS-1$
|
||||
output.print("<h3>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h4")) //$NON-NLS-1$
|
||||
output.print("<h4>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
if (t.equalsIgnoreCase("h1")) //$NON-NLS-1$
|
||||
output.print("\\pard\\s1\\b\\fs48 "); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h2")) //$NON-NLS-1$
|
||||
output.print("\\pard\\s2\\b\\fs36 "); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h3")) //$NON-NLS-1$
|
||||
output.print("\\pard\\s3\\b\\fs27 "); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("h4")) //$NON-NLS-1$
|
||||
output.print("\\pard\\s4\\b\\fs24 "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
output.println();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((t.startsWith("/h")) && (inHeader))
|
||||
{
|
||||
ignoreBr = true;
|
||||
inHeader = false;
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
if (t.equalsIgnoreCase("/h1")) //$NON-NLS-1$
|
||||
output.print("</h1>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("/h2")) //$NON-NLS-1$
|
||||
output.print("</h2>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("/h3")) //$NON-NLS-1$
|
||||
output.print("</h3>"); //$NON-NLS-1$
|
||||
else if (t.equalsIgnoreCase("/h4")) //$NON-NLS-1$
|
||||
output.print("</h4>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.print("\\b0\\par\\fs24 "); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
output.println();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (t.startsWith("blockquote")) // Indent $NON-NLS-1$
|
||||
{
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("<blockquote>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println(""); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
output.print(" "); //$NON-NLS-1$
|
||||
break;
|
||||
}
|
||||
ignoreBr = true;
|
||||
}
|
||||
else if (t.startsWith("/blockquote")) // Outdent $NON-NLS-1$
|
||||
{
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.print("</blockquote>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println(""); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ignoreBr = true;
|
||||
}
|
||||
// else
|
||||
// System.err.println("Ignored command: <"+t+">");
|
||||
}
|
||||
else
|
||||
{
|
||||
// System.out.println("Data: ["+t+"]");
|
||||
output.print(t);
|
||||
}
|
||||
}
|
||||
if (!ignoreBr)
|
||||
handleReturn(output);
|
||||
ignoreBr = false;
|
||||
|
||||
switch (rendering)
|
||||
{
|
||||
// turn off many types of formatting stuff at the end of lines
|
||||
case RENDER_AS_HTML:
|
||||
if (inItalics)
|
||||
output.print("</i>"); //$NON-NLS-1$
|
||||
if (inBold)
|
||||
output.print("</b>"); //$NON-NLS-1$
|
||||
if (inUnderline)
|
||||
output.print("</u>"); //$NON-NLS-1$
|
||||
if (inSuperscript)
|
||||
output.print("</sup>"); //$NON-NLS-1$
|
||||
case RENDER_AS_RTF:
|
||||
if (inItalics)
|
||||
output.print("\\i0 "); //$NON-NLS-1$
|
||||
if (inBold)
|
||||
output.print("\\b0 "); //$NON-NLS-1$
|
||||
if (inUnderline)
|
||||
output.print("\\ulnone"); //$NON-NLS-1$
|
||||
if (inSuperscript)
|
||||
output.print("\\nosupersub"); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
inItalics = false;
|
||||
inBold = false;
|
||||
inUnderline = false;
|
||||
inSuperscript = false;
|
||||
inHeader = false;
|
||||
}
|
||||
// Put the finishing touches on the document
|
||||
switch (rendering)
|
||||
{
|
||||
case RENDER_AS_HTML:
|
||||
output.println("</body></html>"); //$NON-NLS-1$
|
||||
break;
|
||||
case RENDER_AS_RTF:
|
||||
output.println("}"); //$NON-NLS-1$
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with carriage-return.
|
||||
*/
|
||||
protected void handleReturn(PrintWriter printWriter) {
|
||||
if (isHtmlRendering())
|
||||
printWriter.println("<br>"); //$NON-NLS-1$
|
||||
else if (isRtfRendering())
|
||||
printWriter.println("\\par"); //$NON-NLS-1$
|
||||
else
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Give suggested file name.
|
||||
*
|
||||
* @see com.webcodepro.applecommander.storage.FileFilter#getSuggestedFileName(FileEntry)
|
||||
*/
|
||||
public String getSuggestedFileName(FileEntry fileEntry) {
|
||||
String fileName = fileEntry.getFilename().trim();
|
||||
String extension = ".txt"; //$NON-NLS-1$
|
||||
if (isHtmlRendering())
|
||||
extension = ".html"; //$NON-NLS-1$
|
||||
else if (isRtfRendering())
|
||||
extension = ".rtf"; //$NON-NLS-1$
|
||||
|
||||
if (!fileName.toLowerCase().endsWith(extension)) {
|
||||
fileName = fileName + extension;
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rendering method.
|
||||
*/
|
||||
protected void setRendering(int rendering) {
|
||||
this.rendering = rendering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a text rendering.
|
||||
*/
|
||||
public boolean isTextRendering() {
|
||||
return rendering == RENDER_AS_TEXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is an HTML rendering.
|
||||
*/
|
||||
public boolean isHtmlRendering() {
|
||||
return rendering == RENDER_AS_HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is an RTF rendering.
|
||||
*/
|
||||
public boolean isRtfRendering() {
|
||||
return rendering == RENDER_AS_RTF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the text rendering engine.
|
||||
*/
|
||||
public void selectTextRendering() {
|
||||
rendering = RENDER_AS_TEXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the HTML rendering engine.
|
||||
*/
|
||||
public void selectHtmlRendering() {
|
||||
rendering = RENDER_AS_HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the RTF rendering engine.
|
||||
*/
|
||||
public void selectRtfRendering() {
|
||||
rendering = RENDER_AS_RTF;
|
||||
}
|
||||
}
|
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2002 by Robert Greene
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage.os.gutenberg;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.webcodepro.applecommander.storage.Disk;
|
||||
import com.webcodepro.applecommander.storage.DiskFullException;
|
||||
import com.webcodepro.applecommander.storage.FileEntry;
|
||||
import com.webcodepro.applecommander.storage.FileFilter;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.StorageBundle;
|
||||
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
|
||||
import com.webcodepro.applecommander.util.AppleUtil;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
|
||||
/**
|
||||
* Represents a DOS file entry on disk.
|
||||
* <p>
|
||||
* Date created: Oct 4, 2002 5:15:25 PM
|
||||
* @author Rob Greene
|
||||
*/
|
||||
public class GutenbergFileEntry implements FileEntry {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* Indicates the length in bytes of the DOS file entry field.
|
||||
*/
|
||||
public static final int FILE_DESCRIPTIVE_ENTRY_LENGTH = 16;
|
||||
/**
|
||||
* Holds the disk the FileEntry is attached to.
|
||||
*/
|
||||
private GutenbergFormatDisk disk;
|
||||
/**
|
||||
* Track of the FileEntry location.
|
||||
*/
|
||||
private int track;
|
||||
/**
|
||||
* Sector of the FileEntry location.
|
||||
*/
|
||||
private int sector;
|
||||
/**
|
||||
* Offset into sector of FileEntry location.
|
||||
*/
|
||||
private int offset;
|
||||
|
||||
/**
|
||||
* Constructor for GutenbergFileEntry.
|
||||
*/
|
||||
public GutenbergFileEntry(GutenbergFormatDisk disk, int track, int sector, int offset) {
|
||||
super();
|
||||
this.disk = disk;
|
||||
this.track = track;
|
||||
this.sector = sector;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the FileEntry from the disk image.
|
||||
*/
|
||||
protected byte[] readFileEntry() {
|
||||
byte[] sectorData = disk.readSector(track, sector);
|
||||
byte[] fileEntry = new byte[FILE_DESCRIPTIVE_ENTRY_LENGTH];
|
||||
System.arraycopy(sectorData, offset, fileEntry, 0, fileEntry.length);
|
||||
return fileEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the FileEntry to the disk image.
|
||||
*/
|
||||
protected void writeFileEntry(byte[] fileEntry) {
|
||||
if (fileEntry.length != FILE_DESCRIPTIVE_ENTRY_LENGTH) {
|
||||
throw new IllegalArgumentException(textBundle.
|
||||
format("GutenbergFileEntry.GutenbergFileEntryLengthError", //$NON-NLS-1$
|
||||
FILE_DESCRIPTIVE_ENTRY_LENGTH));
|
||||
}
|
||||
byte[] sectorData = disk.readSector(track, sector);
|
||||
System.arraycopy(fileEntry, 0, sectorData, offset, fileEntry.length);
|
||||
disk.writeSector(track, sector, sectorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum filename length.
|
||||
*/
|
||||
public int getMaximumFilenameLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of this file.
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#getFilename()
|
||||
*/
|
||||
public String getFilename() {
|
||||
return AppleUtil.getString(readFileEntry(), 0, getMaximumFilenameLength()).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of this file.
|
||||
*/
|
||||
public void setFilename(String filename) {
|
||||
byte[] data = readFileEntry();
|
||||
AppleUtil.setString(data, 0, filename.toUpperCase(), getMaximumFilenameLength());
|
||||
writeFileEntry(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filetype of this file.
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#getFiletype()
|
||||
*/
|
||||
public String getFiletype() {
|
||||
return "T"; // Only one file type... text //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filetype (typeless - unused)
|
||||
*/
|
||||
public void setFiletype(String filetype) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if this file is locked.
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#isLocked()
|
||||
*/
|
||||
public boolean isLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lock indicator (unused)
|
||||
*/
|
||||
public void setLocked(boolean lock) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the size of this file (in bytes).
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
// Nothing special, just compute from number of sectors
|
||||
int size = getSectorsUsed() * Disk.SECTOR_SIZE;
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of sectors used.
|
||||
*/
|
||||
public int getSectorsUsed() {
|
||||
// Follow the chain of sectors to find the end.
|
||||
int track = getTrack();
|
||||
int sector = getSector();
|
||||
int sectors = 0;
|
||||
while (track < 128) {
|
||||
byte[] sectorData = disk.readSector(track, sector);
|
||||
track = AppleUtil.getUnsignedByte(sectorData[0x04]);
|
||||
sector = AppleUtil.getUnsignedByte(sectorData[0x05]);
|
||||
sectors++;
|
||||
}
|
||||
return sectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of sectors used.
|
||||
*/
|
||||
public void setSectorsUsed(int sectorsUsed) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if this is a directory file.
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#isDirectory()
|
||||
*/
|
||||
public boolean isDirectory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if this file has been deleted.
|
||||
* @see com.webcodepro.applecommander.storage.FileEntry#isDeleted()
|
||||
*/
|
||||
public boolean isDeleted() {
|
||||
return AppleUtil.getUnsignedByte(readFileEntry()[0x0d]) == 0x40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this file.
|
||||
*/
|
||||
public void delete() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the standard file column header information.
|
||||
* This default implementation is intended only for standard mode.
|
||||
* displayMode is specified in FormattedDisk.
|
||||
*/
|
||||
public List getFileColumnData(int displayMode) {
|
||||
NumberFormat numberFormat = NumberFormat.getNumberInstance();
|
||||
List list = new ArrayList();
|
||||
switch (displayMode) {
|
||||
case FormattedDisk.FILE_DISPLAY_NATIVE:
|
||||
list.add(isLocked() ? "*" : " "); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
list.add(getFiletype());
|
||||
numberFormat.setMinimumIntegerDigits(3);
|
||||
list.add(numberFormat.format(getSectorsUsed()));
|
||||
list.add(getFilename());
|
||||
break;
|
||||
case FormattedDisk.FILE_DISPLAY_DETAIL:
|
||||
list.add(isLocked() ? "*" : " "); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
list.add(getFiletype());
|
||||
list.add(getFilename());
|
||||
list.add(numberFormat.format(getSize()));
|
||||
numberFormat.setMinimumIntegerDigits(3);
|
||||
list.add(numberFormat.format(getSectorsUsed()));
|
||||
list.add(isDeleted() ? textBundle.get("Deleted") : ""); //$NON-NLS-1$//$NON-NLS-2$
|
||||
list.add("T" + getTrack() + " S" + getSector()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
break;
|
||||
default: // FILE_DISPLAY_STANDARD
|
||||
list.add(getFilename());
|
||||
list.add(getFiletype());
|
||||
list.add(numberFormat.format(getSize()));
|
||||
list.add(isLocked() ? textBundle.get("Locked") : ""); //$NON-NLS-1$//$NON-NLS-2$
|
||||
break;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the track of first track/sector list sector.
|
||||
*/
|
||||
public int getTrack() {
|
||||
return AppleUtil.getUnsignedByte(readFileEntry()[0x0c]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the track of the first track/sector list sector.
|
||||
*/
|
||||
public void setTrack(int track) {
|
||||
byte[] data = readFileEntry();
|
||||
data[0x0c] = (byte) track;
|
||||
writeFileEntry(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sector of first track/sector list sector.
|
||||
*/
|
||||
public int getSector() {
|
||||
return AppleUtil.getUnsignedByte(readFileEntry()[0x0d]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sector of the first track/sector list sector.
|
||||
*/
|
||||
public void setSector(int sector) {
|
||||
byte[] data = readFileEntry();
|
||||
data[0x0d] = (byte) sector;
|
||||
writeFileEntry(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file data. This handles any operating-system specific issues.
|
||||
*/
|
||||
public byte[] getFileData() {
|
||||
return disk.getFileData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file data.
|
||||
*
|
||||
* Note: The address can be set before the data is saved or
|
||||
* after the data is saved. This is an attempt to make the
|
||||
* API more easily usable.
|
||||
*
|
||||
* Empirically, the data must be set before the address is set.
|
||||
*/
|
||||
public void setFileData(byte[] data) throws DiskFullException {
|
||||
disk.setFileData(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the suggested FileFilter. This appears to be operating system
|
||||
* specific, so each operating system needs to implement some manner
|
||||
* of guessing the appropriate filter.
|
||||
* FIXME - this code should be a helper class for DOS and RDOS!
|
||||
*/
|
||||
public FileFilter getSuggestedFilter() {
|
||||
return new GutenbergFileFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this is an assembly source code file.
|
||||
*/
|
||||
public boolean isAssemblySourceFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FormattedDisk associated with this FileEntry.
|
||||
* This is useful to interfaces that need to retrieve the associated
|
||||
* disk.
|
||||
*/
|
||||
public FormattedDisk getFormattedDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this filetype requires an address component.
|
||||
* Note that the FormattedDisk also has this method - normally,
|
||||
* this will defer to the method on FormattedDisk, as it will be
|
||||
* more generic.
|
||||
*/
|
||||
public boolean needsAddress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address that this file loads at.
|
||||
*/
|
||||
public void setAddress(int address) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this filetype can be compiled.
|
||||
*/
|
||||
public boolean canCompile() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,718 @@
|
||||
/*
|
||||
* AppleCommander - An Apple ][ image utility.
|
||||
* Copyright (C) 2002, 2008 by Robert Greene
|
||||
* robgreene at users.sourceforge.net
|
||||
*
|
||||
* 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.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
package com.webcodepro.applecommander.storage.os.gutenberg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.webcodepro.applecommander.storage.DirectoryEntry;
|
||||
import com.webcodepro.applecommander.storage.DiskFullException;
|
||||
import com.webcodepro.applecommander.storage.FileEntry;
|
||||
import com.webcodepro.applecommander.storage.FormattedDisk;
|
||||
import com.webcodepro.applecommander.storage.StorageBundle;
|
||||
import com.webcodepro.applecommander.storage.physical.ImageOrder;
|
||||
import com.webcodepro.applecommander.util.AppleUtil;
|
||||
import com.webcodepro.applecommander.util.TextBundle;
|
||||
|
||||
/**
|
||||
* Manages a disk that is in Gutenberg Word Processor format.
|
||||
* <p>
|
||||
* Date created: Dec 17, 2008 04:29:23 PM
|
||||
* @author David Schmidt
|
||||
*/
|
||||
public class GutenbergFormatDisk extends FormattedDisk {
|
||||
private TextBundle textBundle = StorageBundle.getInstance();
|
||||
/**
|
||||
* Indicates the index of the track in the location array.
|
||||
*/
|
||||
public static final int TRACK_LOCATION_INDEX = 0;
|
||||
/**
|
||||
* Indicates the index of the sector in the location array.
|
||||
*/
|
||||
public static final int SECTOR_LOCATION_INDEX = 1;
|
||||
/**
|
||||
* The catalog track.
|
||||
*/
|
||||
public static final int CATALOG_TRACK = 17;
|
||||
/**
|
||||
* The VTOC sector.
|
||||
*/
|
||||
public static final int VTOC_SECTOR = 7;
|
||||
/**
|
||||
* The standard track/sector pairs in a track/sector list.
|
||||
*/
|
||||
public static final int TRACK_SECTOR_PAIRS = 122;
|
||||
/**
|
||||
* The list of filetypes available.
|
||||
*/
|
||||
private static final String[] filetypes = {
|
||||
"T" //$NON-NLS-1$
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this inner interface for managing the disk usage data.
|
||||
* This offloads format-specific implementation to the implementing class.
|
||||
*/
|
||||
private class WPDiskUsage implements DiskUsage {
|
||||
private int[] location = null;
|
||||
public boolean hasNext() {
|
||||
return location == null
|
||||
|| (location[TRACK_LOCATION_INDEX] < getTracks()
|
||||
&& location[SECTOR_LOCATION_INDEX] < getSectors());
|
||||
}
|
||||
public void next() {
|
||||
if (location == null) {
|
||||
location = new int[2];
|
||||
} else {
|
||||
location[SECTOR_LOCATION_INDEX]++;
|
||||
if (location[SECTOR_LOCATION_INDEX] >= getSectors()) {
|
||||
location[SECTOR_LOCATION_INDEX] = 0;
|
||||
location[TRACK_LOCATION_INDEX]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the free setting for the bitmap at the current location.
|
||||
* I don't think there is a map stored on disk, however.
|
||||
*/
|
||||
public boolean isFree() {
|
||||
if (location == null || location.length != 2) {
|
||||
throw new IllegalArgumentException(StorageBundle.getInstance()
|
||||
.get("DosFormatDisk.InvalidDimensionError")); //$NON-NLS-1$
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isUsed() {
|
||||
return !isFree();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for GutenbergFormatDisk.
|
||||
*/
|
||||
public GutenbergFormatDisk(String filename, ImageOrder imageOrder) {
|
||||
super(filename, imageOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a GutenbergFormatDisk. All DOS disk images are expected to
|
||||
* be 140K in size.
|
||||
*/
|
||||
public static GutenbergFormatDisk[] create(String filename, ImageOrder imageOrder) {
|
||||
GutenbergFormatDisk disk = new GutenbergFormatDisk(filename, imageOrder);
|
||||
disk.format();
|
||||
return new GutenbergFormatDisk[] { disk };
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the operating system format of this disk as Gutenberg.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getFormat()
|
||||
*/
|
||||
public String getFormat() {
|
||||
return textBundle.get("Gutenberg"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of files.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getFiles()
|
||||
*/
|
||||
public List getFiles() {
|
||||
List list = new ArrayList();
|
||||
int track = CATALOG_TRACK;
|
||||
int sector = VTOC_SECTOR;
|
||||
while (track < 40) { // iterate through all catalog sectors
|
||||
byte[] catalogSector = readSector(track, sector);
|
||||
int offset = 0x20; // First entry is 0x20 deep
|
||||
while (offset < 0xff) { // iterate through all entries
|
||||
if (catalogSector[offset] != -96) {
|
||||
list.add(new GutenbergFileEntry(this, track, sector, offset));
|
||||
}
|
||||
offset+= GutenbergFileEntry.FILE_DESCRIPTIVE_ENTRY_LENGTH;
|
||||
}
|
||||
track = AppleUtil.getUnsignedByte(catalogSector[4]); // Pull in the next catalog sector
|
||||
sector = AppleUtil.getUnsignedByte(catalogSector[5]);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FileEntry.
|
||||
*/
|
||||
public FileEntry createFile() throws DiskFullException {
|
||||
byte[] vtoc = readVtoc();
|
||||
int track = AppleUtil.getUnsignedByte(vtoc[1]);
|
||||
int sector = AppleUtil.getUnsignedByte(vtoc[2]);
|
||||
while (sector != 0) { // bug fix: iterate through all catalog _sectors_
|
||||
byte[] catalogSector = readSector(track, sector);
|
||||
int offset = 0x0b;
|
||||
while (offset < 0xff) { // iterate through all entries
|
||||
int value = AppleUtil.getUnsignedByte(catalogSector[offset]);
|
||||
if (value == 0 || value == 0xff) {
|
||||
return new GutenbergFileEntry(this, track, sector, offset);
|
||||
}
|
||||
offset+= GutenbergFileEntry.FILE_DESCRIPTIVE_ENTRY_LENGTH;
|
||||
}
|
||||
track = catalogSector[1];
|
||||
sector = catalogSector[2];
|
||||
}
|
||||
throw new DiskFullException(textBundle.get("DosFormatDisk.NoMoreSpaceError")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if additional directories can be created. This
|
||||
* may indicate that directories are not available to this
|
||||
* operating system or simply that the disk image is "locked"
|
||||
* to writing.
|
||||
*/
|
||||
public boolean canCreateDirectories() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this disk image can create a file.
|
||||
* If not, the reason may be as simple as it has not beem implemented
|
||||
* to something specific about the disk.
|
||||
*/
|
||||
public boolean canCreateFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the amount of freespace available on the disk.
|
||||
* This algorithm completely ignores tracks and sectors by
|
||||
* running through the entire bitmap stored on the VTOC.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getFreeSpace()
|
||||
*/
|
||||
public int getFreeSpace() {
|
||||
return getFreeSectors() * SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comput the number of free sectors available on the disk.
|
||||
*/
|
||||
public int getFreeSectors() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the amount of used space in bytes.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getUsedSpace()
|
||||
*/
|
||||
public int getUsedSpace() {
|
||||
return APPLE_140KB_DISK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of used sectors on the disk.
|
||||
*/
|
||||
public int getUsedSectors() {
|
||||
return getTotalSectors() - getFreeSectors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the total number of sectors available on the disk.
|
||||
*/
|
||||
public int getTotalSectors() {
|
||||
int tracks = getTracks();
|
||||
int sectors = getSectors();
|
||||
return tracks * sectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the WP disk name.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getDiskName()
|
||||
*/
|
||||
public String getDiskName() {
|
||||
// Pull the disk name out...
|
||||
return AppleUtil.getString(readVtoc(), 6, 9).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the VTOC (Volume Table Of Contents).
|
||||
*/
|
||||
protected byte[] readVtoc() {
|
||||
return readSector(CATALOG_TRACK, VTOC_SECTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the VTOC (Volume Table Of Contents) to disk.
|
||||
*/
|
||||
protected void writeVtoc(byte[] vtoc) {
|
||||
writeSector(CATALOG_TRACK, VTOC_SECTOR, vtoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the disk usage iterator.
|
||||
*/
|
||||
public DiskUsage getDiskUsage() {
|
||||
return new WPDiskUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of tracks on this disk.
|
||||
*/
|
||||
public int getTracks() {
|
||||
byte[] vtoc = readVtoc();
|
||||
return AppleUtil.getUnsignedByte(vtoc[0x34]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of sectors on this disk.
|
||||
*/
|
||||
public int getSectors() {
|
||||
byte[] vtoc = readVtoc();
|
||||
return AppleUtil.getUnsignedByte(vtoc[0x35]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get suggested dimensions for display of bitmap. For DOS 3.3, that information
|
||||
* is stored in the VTOC, and that information is fairly important.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#getBitmapDimensions()
|
||||
*/
|
||||
public int[] getBitmapDimensions() {
|
||||
int tracks = getTracks();
|
||||
int sectors = getSectors();
|
||||
return new int[] { tracks, sectors };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of the bitmap.
|
||||
*/
|
||||
public int getBitmapLength() {
|
||||
return getTotalSectors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the labels to use in the bitmap.
|
||||
*/
|
||||
public String[] getBitmapLabels() {
|
||||
return new String[] { textBundle.get("DosFormatDisk.Track"), textBundle.get("DosFormatDisk.Sector") }; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
/**
|
||||
* Get WP-specific disk information.
|
||||
*/
|
||||
public List getDiskInformation() {
|
||||
List list = super.getDiskInformation();
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the standard file column header information.
|
||||
* This default implementation is intended only for standard mode.
|
||||
*/
|
||||
public List getFileColumnHeaders(int displayMode) {
|
||||
List list = new ArrayList();
|
||||
switch (displayMode) {
|
||||
case FILE_DISPLAY_NATIVE:
|
||||
list.add(new FileColumnHeader(" ", 1, FileColumnHeader.ALIGN_CENTER)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("DosFormatDisk.Type"), 1, FileColumnHeader.ALIGN_CENTER)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("DosFormatDisk.SizeInSectors"), 3, FileColumnHeader.ALIGN_RIGHT)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("Name"), 30, //$NON-NLS-1$
|
||||
FileColumnHeader.ALIGN_LEFT));
|
||||
break;
|
||||
case FILE_DISPLAY_DETAIL:
|
||||
list.add(new FileColumnHeader(" ", 1, FileColumnHeader.ALIGN_CENTER)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("DosFormatDisk.Type"), 1, FileColumnHeader.ALIGN_CENTER)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("Name"), 30, //$NON-NLS-1$
|
||||
FileColumnHeader.ALIGN_LEFT));
|
||||
list.add(new FileColumnHeader(textBundle.get("SizeInBytes"), 6, //$NON-NLS-1$
|
||||
FileColumnHeader.ALIGN_RIGHT));
|
||||
list.add(new FileColumnHeader(textBundle.get("DosFormatDisk.SizeInSectors"), 3, FileColumnHeader.ALIGN_RIGHT)); //$NON-NLS-1$
|
||||
list.add(new FileColumnHeader(textBundle.get("DeletedQ"), 7, //$NON-NLS-1$
|
||||
FileColumnHeader.ALIGN_CENTER));
|
||||
list.add(new FileColumnHeader(textBundle.get("DosFormatDisk.TrackAndSectorList"), 7, FileColumnHeader.ALIGN_CENTER)); //$NON-NLS-1$
|
||||
break;
|
||||
default: // FILE_DISPLAY_STANDARD
|
||||
list.addAll(super.getFileColumnHeaders(displayMode));
|
||||
break;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this disk format supports "deleted" files.
|
||||
*/
|
||||
public boolean supportsDeletedFiles() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this disk image can read data from a file.
|
||||
*/
|
||||
public boolean canReadFileData() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this disk image can write data to a file.
|
||||
*/
|
||||
public boolean canWriteFileData() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify if this disk format as not capable of having directories.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#canHaveDirectories()
|
||||
*/
|
||||
public boolean canHaveDirectories() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this disk image can delete a file.
|
||||
*/
|
||||
public boolean canDeleteFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data associated with the specified FileEntry.
|
||||
*/
|
||||
public byte[] getFileData(FileEntry fileEntry) {
|
||||
if ( !(fileEntry instanceof GutenbergFileEntry)) {
|
||||
throw new IllegalArgumentException(textBundle.get("DosFormatDisk.InvalidFileEntryError")); //$NON-NLS-1$
|
||||
}
|
||||
GutenbergFileEntry wpEntry = (GutenbergFileEntry) fileEntry;
|
||||
// Size is calculated by sectors used - not actual size - as size varies
|
||||
// on filetype, etc.
|
||||
int filesize = wpEntry.getSectorsUsed();
|
||||
byte[] fileData = null;
|
||||
if (filesize > 0) {
|
||||
fileData = new byte[(wpEntry.getSectorsUsed()) * SECTOR_SIZE];
|
||||
} else {
|
||||
fileData = new byte[0];
|
||||
// don't need to load it - also bypass potential issues
|
||||
return fileData;
|
||||
}
|
||||
int track = wpEntry.getTrack();
|
||||
int sector = wpEntry.getSector();
|
||||
int offset = 0;
|
||||
while (track < 128) {
|
||||
byte[] sectorData = readSector(track,sector);
|
||||
track = AppleUtil.getUnsignedByte(sectorData[0x04]);
|
||||
sector = AppleUtil.getUnsignedByte(sectorData[0x05]);
|
||||
System.arraycopy(sectorData, 6, fileData, offset, sectorData.length-6);
|
||||
offset+= sectorData.length-6;
|
||||
}
|
||||
return fileData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the raw bytes into the file. This bypasses any special formatting
|
||||
* of the data (such as prepending the data with a length and/or an address).
|
||||
* Typically, the FileEntry.setFileData method should be used.
|
||||
*/
|
||||
public void setFileData(FileEntry fileEntry, byte[] fileData) throws DiskFullException {
|
||||
setFileData((GutenbergFileEntry)fileEntry, fileData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data associated with the specified GutenbergFileEntry into sectors
|
||||
* on the disk.
|
||||
*/
|
||||
protected void setFileData(GutenbergFileEntry fileEntry, byte[] data) throws DiskFullException {
|
||||
// compute free space and see if the data will fit!
|
||||
int numberOfDataSectors = (data.length + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
int numberOfSectors = numberOfDataSectors +
|
||||
(numberOfDataSectors + TRACK_SECTOR_PAIRS - 1) / TRACK_SECTOR_PAIRS;
|
||||
if (numberOfSectors > getFreeSectors() + fileEntry.getSectorsUsed()) {
|
||||
throw new DiskFullException(
|
||||
textBundle.format("DosFormatDisk.NotEnoughSectorsError", //$NON-NLS-1$
|
||||
numberOfSectors, getFreeSectors()));
|
||||
}
|
||||
// free "old" data and just rewrite stuff...
|
||||
// freeSectors(fileEntry); (not going to work...)
|
||||
byte[] vtoc = readVtoc();
|
||||
int track = fileEntry.getTrack();
|
||||
int sector = fileEntry.getSector();
|
||||
if (track == 0 || track == 255) {
|
||||
track = 1;
|
||||
sector = 0;
|
||||
while (true) {
|
||||
if (isSectorFree(track,sector,vtoc)) {
|
||||
break;
|
||||
}
|
||||
sector++;
|
||||
if (sector >= getSectors()) {
|
||||
track++;
|
||||
sector = 0;
|
||||
}
|
||||
}
|
||||
fileEntry.setTrack(track);
|
||||
fileEntry.setSector(sector);
|
||||
}
|
||||
setSectorUsed(track, sector, vtoc);
|
||||
byte[] trackSectorList = new byte[SECTOR_SIZE];
|
||||
int offset = 0;
|
||||
int trackSectorOffset = 0x0c;
|
||||
int totalSectors = 0;
|
||||
int t=1; // initial search for space
|
||||
int s=0;
|
||||
while (offset < data.length) {
|
||||
// locate next free sector
|
||||
while (true) {
|
||||
if (isSectorFree(t,s,vtoc)) {
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
if (s >= getSectors()) {
|
||||
t++;
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
setSectorUsed(t,s,vtoc);
|
||||
if (trackSectorOffset >= 0x100) {
|
||||
// filled up the first track/sector list - save it
|
||||
trackSectorList[0x01] = (byte) t;
|
||||
trackSectorList[0x02] = (byte) s;
|
||||
writeSector(track, sector, trackSectorList);
|
||||
trackSectorList = new byte[SECTOR_SIZE];
|
||||
trackSectorOffset = 0x0c;
|
||||
track = t;
|
||||
sector = s;
|
||||
} else {
|
||||
// write out a data sector
|
||||
trackSectorList[trackSectorOffset] = (byte) t;
|
||||
trackSectorList[trackSectorOffset+1] = (byte) s;
|
||||
trackSectorOffset+= 2;
|
||||
byte[] sectorData = new byte[SECTOR_SIZE];
|
||||
int length = Math.min(SECTOR_SIZE, data.length - offset);
|
||||
System.arraycopy(data, offset, sectorData, 0, length);
|
||||
writeSector(t,s,sectorData);
|
||||
offset+= SECTOR_SIZE;
|
||||
}
|
||||
totalSectors++;
|
||||
}
|
||||
writeSector(track, sector, trackSectorList); // last T/S list
|
||||
totalSectors++;
|
||||
fileEntry.setSectorsUsed(totalSectors);
|
||||
writeVtoc(vtoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free sectors used by a GutenbergFileEntry.
|
||||
*/
|
||||
/*
|
||||
protected void freeSectors(GutenbergFileEntry GutenbergFileEntry) {
|
||||
byte[] vtoc = readVtoc();
|
||||
int track = GutenbergFileEntry.getTrack();
|
||||
if (track == 255) return;
|
||||
int sector = GutenbergFileEntry.getSector();
|
||||
while (track != 0) {
|
||||
setSectorFree(track,sector,vtoc);
|
||||
byte[] trackSectorList = readSector(track, sector);
|
||||
track = AppleUtil.getUnsignedByte(trackSectorList[0x01]);
|
||||
sector = AppleUtil.getUnsignedByte(trackSectorList[0x02]);
|
||||
for (int i=0x0c; i<0x100; i+=2) {
|
||||
int t = AppleUtil.getUnsignedByte(trackSectorList[i]);
|
||||
if (t == 0) break;
|
||||
int s = AppleUtil.getUnsignedByte(trackSectorList[i+1]);
|
||||
setSectorFree(t,s,vtoc);
|
||||
}
|
||||
}
|
||||
writeVtoc(vtoc);
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Format the disk as DOS 3.3.
|
||||
* @see com.webcodepro.applecommander.storage.FormattedDisk#format()
|
||||
*/
|
||||
public void format() {
|
||||
getImageOrder().format();
|
||||
format(15, 35, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the disk as DOS 3.3 given the dymanic parameters.
|
||||
* (Used for UniDOS and OzDOS.)
|
||||
*/
|
||||
protected void format(int firstCatalogSector, int tracksPerDisk,
|
||||
int sectorsPerTrack) {
|
||||
|
||||
writeBootCode();
|
||||
// create catalog sectors
|
||||
byte[] data = new byte[SECTOR_SIZE];
|
||||
for (int sector=firstCatalogSector; sector > 0; sector--) {
|
||||
if (sector > 1) {
|
||||
data[0x01] = CATALOG_TRACK;
|
||||
data[0x02] = (byte)(sector-1);
|
||||
} else {
|
||||
data[0x01] = 0;
|
||||
data[0x02] = 0;
|
||||
}
|
||||
writeSector(CATALOG_TRACK, sector, data);
|
||||
}
|
||||
// create VTOC
|
||||
data[0x01] = CATALOG_TRACK; // track# of first catalog sector
|
||||
data[0x02] = (byte)firstCatalogSector; // sector# of first catalog sector
|
||||
data[0x03] = 3; // DOS 3.3 formatted
|
||||
data[0x06] = (byte)254; // DISK VOLUME#
|
||||
data[0x27] = TRACK_SECTOR_PAIRS;// maximum # of T/S pairs in a sector
|
||||
data[0x30] = CATALOG_TRACK+1; // last track where sectors allocated
|
||||
data[0x31] = 1; // direction of allocation
|
||||
data[0x34] = (byte)tracksPerDisk; // tracks per disk
|
||||
data[0x35] = (byte)sectorsPerTrack;// sectors per track
|
||||
data[0x37] = 1; // 36/37 are # of bytes per sector
|
||||
for (int track=0; track<tracksPerDisk; track++) {
|
||||
for (int sector=0; sector<sectorsPerTrack; sector++) {
|
||||
if (track == 0 || track == CATALOG_TRACK) {
|
||||
setSectorUsed(track, sector, data);
|
||||
} else {
|
||||
setSectorFree(track, sector, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
writeVtoc(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a specific track/sector is free.
|
||||
*/
|
||||
public boolean isSectorFree(int track, int sector, byte[] vtoc) {
|
||||
checkRange(track, sector);
|
||||
byte byt = vtoc[getFreeMapByte(track, sector)];
|
||||
return AppleUtil.isBitSet(byt, getFreeMapBit(sector));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if a specific track/sector is used.
|
||||
*/
|
||||
public boolean isSectorUsed(int track, int sector, byte[] vtoc) {
|
||||
return !isSectorFree(track, sector, vtoc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the track/sector indicator to free.
|
||||
*/
|
||||
public void setSectorFree(int track, int sector, byte[] vtoc) {
|
||||
checkRange(track, sector);
|
||||
int offset = getFreeMapByte(track, sector);
|
||||
byte byt = vtoc[offset];
|
||||
byt = AppleUtil.setBit(byt, getFreeMapBit(sector));
|
||||
vtoc[offset] = byt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the track/sector indicator to used.
|
||||
*/
|
||||
public void setSectorUsed(int track, int sector, byte[] vtoc) {
|
||||
checkRange(track, sector);
|
||||
int offset = getFreeMapByte(track, sector);
|
||||
byte byt = vtoc[offset];
|
||||
byt = AppleUtil.clearBit(byt, getFreeMapBit(sector));
|
||||
vtoc[offset] = byt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the VTOC byte for the T/S map.
|
||||
*/
|
||||
protected int getFreeMapByte(int track, int sector) {
|
||||
int trackOffset = track * 4;
|
||||
int sectorOffset = 1 - ((sector & 0x8) >> 3);
|
||||
return 0x38 + trackOffset + sectorOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the VTOC bit for the T/S map.
|
||||
*/
|
||||
protected int getFreeMapBit(int sector) {
|
||||
int bit = sector & 0x7;
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate track/sector range. This just validates the
|
||||
* maximum values allowable for track and sector.
|
||||
*/
|
||||
protected void checkRange(int track, int sector) {
|
||||
if (track > 50 || sector > 32) {
|
||||
throw new IllegalArgumentException(
|
||||
textBundle.format("DosFormatDisk.InvalidTrackAndSectorCombinationError", //$NON-NLS-1$
|
||||
track, sector));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the logical disk number. Returns a 0 to indicate no numbering.
|
||||
*/
|
||||
public int getLogicalDiskNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid filename for the given filename.
|
||||
*/
|
||||
public String getSuggestedFilename(String filename) {
|
||||
int len = Math.min(filename.length(), 12);
|
||||
return filename.toUpperCase().substring(0, len).trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a valid filetype for the given filename. The most simple
|
||||
* format will just assume a filetype of binary. This method is
|
||||
* available for the interface to make an intelligent first guess
|
||||
* as to the filetype.
|
||||
*/
|
||||
public String getSuggestedFiletype(String filename) {
|
||||
return "T"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of possible file types. Since the filetype is
|
||||
* specific to each operating system, a simple String is used.
|
||||
*/
|
||||
public String[] getFiletypes() {
|
||||
return filetypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this filetype requires an address component.
|
||||
* For DOS, only the Binary type needs an address.
|
||||
*/
|
||||
public boolean needsAddress(String filetype) {
|
||||
return "B".equals(filetype); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this FormattedDisk supports a disk map.
|
||||
*/
|
||||
public boolean supportsDiskMap() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change to a different ImageOrder. Remains in DOS 3.3 format but
|
||||
* the underlying order can chage.
|
||||
* @see ImageOrder
|
||||
*/
|
||||
public void changeImageOrder(ImageOrder imageOrder) {
|
||||
AppleUtil.changeImageOrderByTrackAndSector(getImageOrder(), imageOrder);
|
||||
setImageOrder(imageOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new DirectoryEntry.
|
||||
* @see com.webcodepro.applecommander.storage.DirectoryEntry#createDirectory()
|
||||
*/
|
||||
public DirectoryEntry createDirectory() throws DiskFullException {
|
||||
throw new UnsupportedOperationException(textBundle.get("DirectoryCreationNotSupported")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ WordProcessorRenderingMenuItem=Rendering
|
||||
WordProcessorRenderAsTextMenuItem=Text
|
||||
WordProcessorRenderAsHtmlMenuItem=HTML
|
||||
WordProcessorRenderAsRtfMenuItem=RTF
|
||||
GutenbergRenderingMenuItem=Gutenberg File Rendered as...
|
||||
ExportAsGraphicsMenuItem=Graphics...
|
||||
ExportGraphicsModeMenuItem=Mode
|
||||
ExportGraphicsAsHiresBlackAndWhiteMenuItem=Hi-Res B&W
|
||||
|
@ -87,6 +87,7 @@ import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosDiskSizeDoesNotMatchException;
|
||||
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
|
||||
import com.webcodepro.applecommander.storage.physical.ByteArrayImageLayout;
|
||||
@ -153,6 +154,7 @@ public class DiskExplorerTab {
|
||||
private FileFilter fileFilter;
|
||||
private GraphicsFileFilter graphicsFilter = new GraphicsFileFilter();
|
||||
private AppleWorksWordProcessorFileFilter awpFilter = new AppleWorksWordProcessorFileFilter();
|
||||
private GutenbergFileFilter wpFilter = new GutenbergFileFilter();
|
||||
|
||||
private int currentFormat = FormattedDisk.FILE_DISPLAY_STANDARD;
|
||||
private boolean formatChanged;
|
||||
@ -612,6 +614,62 @@ public class DiskExplorerTab {
|
||||
|
||||
item = new MenuItem(menu, SWT.SEPARATOR);
|
||||
|
||||
item = new MenuItem(menu, SWT.CASCADE);
|
||||
item.setText(textBundle.get("GutenbergRenderingMenuItem")); //$NON-NLS-1$
|
||||
Menu subMenu2 = new Menu(shell, SWT.DROP_DOWN);
|
||||
item.setMenu(subMenu2);
|
||||
subMenu.addMenuListener(new MenuAdapter() {
|
||||
/**
|
||||
* Toggle all sub-menu MenuItems to the proper state to reflect
|
||||
* the current file extension chosen.
|
||||
*/
|
||||
public void menuShown(MenuEvent event) {
|
||||
Menu theMenu = (Menu) event.getSource();
|
||||
MenuItem[] subItems = theMenu.getItems();
|
||||
subItems[0].setSelection(getWPFilter().isTextRendering());
|
||||
subItems[1].setSelection(getWPFilter().isHtmlRendering());
|
||||
subItems[2].setSelection(getWPFilter().isRtfRendering());
|
||||
}
|
||||
});
|
||||
item = new MenuItem(subMenu2, SWT.RADIO);
|
||||
item.setText(textBundle.get("WordProcessorRenderAsTextMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
/**
|
||||
* Set the appropriate rendering style.
|
||||
*/
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
getWPFilter().selectTextRendering();
|
||||
setFileFilter(getWPFilter());
|
||||
exportFile(null);
|
||||
}
|
||||
});
|
||||
item = new MenuItem(subMenu2, SWT.RADIO);
|
||||
item.setText(textBundle.get("WordProcessorRenderAsHtmlMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
/**
|
||||
* Set the appropriate rendering style.
|
||||
*/
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
getWPFilter().selectHtmlRendering();
|
||||
setFileFilter(getWPFilter());
|
||||
exportFile(null);
|
||||
}
|
||||
});
|
||||
item = new MenuItem(subMenu2, SWT.RADIO);
|
||||
item.setText(textBundle.get("WordProcessorRenderAsRtfMenuItem")); //$NON-NLS-1$
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
/**
|
||||
* Set the appropriate rendering style.
|
||||
*/
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
getWPFilter().selectRtfRendering();
|
||||
setFileFilter(getWPFilter());
|
||||
exportFile(null);
|
||||
}
|
||||
});
|
||||
|
||||
item = new MenuItem(menu, SWT.SEPARATOR);
|
||||
|
||||
item = new MenuItem(menu, SWT.NONE);
|
||||
item.setText(textBundle.get("ExportAsGraphicsMenuItem")); //$NON-NLS-1$
|
||||
item.setEnabled(GraphicsFileFilter.isCodecAvailable());
|
||||
@ -953,6 +1011,7 @@ public class DiskExplorerTab {
|
||||
outputStream.write(data);
|
||||
outputStream.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
String errorMessage = ex.getMessage();
|
||||
if (errorMessage == null) {
|
||||
errorMessage = ex.getClass().getName();
|
||||
@ -1596,6 +1655,7 @@ public class DiskExplorerTab {
|
||||
}
|
||||
}
|
||||
} else { // No CTRL key
|
||||
if ((event.stateMask & SWT.ALT) != SWT.ALT) { // Ignore ALT key combinations like alt-F4!
|
||||
switch (event.keyCode) {
|
||||
case SWT.F2: // Standard file display
|
||||
changeCurrentFormat(FormattedDisk.FILE_DISPLAY_STANDARD);
|
||||
@ -1611,6 +1671,7 @@ public class DiskExplorerTab {
|
||||
getShowDeletedFilesToolItem().setSelection(isShowDeletedFiles());
|
||||
fillFileTable(getCurrentFileList());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1939,6 +2000,10 @@ public class DiskExplorerTab {
|
||||
return awpFilter;
|
||||
}
|
||||
|
||||
protected GutenbergFileFilter getWPFilter() {
|
||||
return wpFilter;
|
||||
}
|
||||
|
||||
protected GraphicsFileFilter getGraphicsFilter() {
|
||||
return graphicsFilter;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
|
||||
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
|
||||
import com.webcodepro.applecommander.ui.UiBundle;
|
||||
import com.webcodepro.applecommander.ui.swt.filteradapter.ApplesoftFilterAdapter;
|
||||
import com.webcodepro.applecommander.ui.swt.filteradapter.BusinessBASICFilterAdapter;
|
||||
@ -187,10 +188,15 @@ public class FileViewerWindow {
|
||||
imageManager.get(ImageManager.ICON_VIEW_AS_SPREADSHEET)
|
||||
));
|
||||
nativeFilterAdapterMap.put(AppleWorksWordProcessorFileFilter.class,
|
||||
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.WordprocessorButton"), //$NON-NLS-1$
|
||||
textBundle.get("FileViewerWindow.WordprocessorTooltip"), //$NON-NLS-1$
|
||||
imageManager.get(ImageManager.ICON_VIEW_AS_WORDPROCESSOR)
|
||||
));
|
||||
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.WordprocessorButton"), //$NON-NLS-1$
|
||||
textBundle.get("FileViewerWindow.WordprocessorTooltip"), //$NON-NLS-1$
|
||||
imageManager.get(ImageManager.ICON_VIEW_AS_WORDPROCESSOR)
|
||||
));
|
||||
nativeFilterAdapterMap.put(GutenbergFileFilter.class,
|
||||
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.WordprocessorButton"), //$NON-NLS-1$
|
||||
textBundle.get("FileViewerWindow.WordprocessorTooltip"), //$NON-NLS-1$
|
||||
imageManager.get(ImageManager.ICON_VIEW_AS_WORDPROCESSOR)
|
||||
));
|
||||
nativeFilterAdapterMap.put(AssemblySourceFileFilter.class,
|
||||
new TextFilterAdapter(this, textBundle.get("FileViewerWindow.AssemblyButton"), //$NON-NLS-1$
|
||||
textBundle.get("FileViewerWindow.AssemblyTooltip"), //$NON-NLS-1$
|
||||
|
Loading…
x
Reference in New Issue
Block a user