common parent for text files

This commit is contained in:
Denis Molony 2020-09-14 19:51:14 +10:00
parent 5c66c39478
commit 8c07de944d
8 changed files with 235 additions and 220 deletions

View File

@ -0,0 +1,216 @@
package com.bytezone.diskbrowser.applefile;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class BasicTextFile extends TextFile
// -----------------------------------------------------------------------------------//
{
private int recordLength; // prodos aux
private List<TextBuffer> buffers; // only used if it is a Prodos text file
private int eof;
private boolean prodosFile;
// ---------------------------------------------------------------------------------//
public BasicTextFile (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
}
// ---------------------------------------------------------------------------------//
public BasicTextFile (String name, byte[] buffer, int auxType, int eof)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
this.eof = eof;
recordLength = auxType;
prodosFile = true;
}
// ---------------------------------------------------------------------------------//
public BasicTextFile (String name, List<TextBuffer> buffers, int auxType, int eof)
// ---------------------------------------------------------------------------------//
{
super (name, null);
this.buffers = buffers;
this.eof = eof;
recordLength = auxType;
prodosFile = true;
}
// ---------------------------------------------------------------------------------//
@Override
public String getHexDump ()
// ---------------------------------------------------------------------------------//
{
if (buffers == null)
return (super.getHexDump ());
StringBuilder text = new StringBuilder ();
for (TextBuffer tb : buffers)
{
for (int i = 0, rec = 0; i < tb.buffer.length; i += tb.reclen, rec++)
{
text.append ("\nRecord #" + (tb.firstRecNo + rec) + "\n");
text.append (HexFormatter.format (tb.buffer, i, tb.reclen) + "\n");
}
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
if (textPreferences.showHeader)
{
text.append ("Name : " + name + "\n");
if (prodosFile)
{
text.append (String.format ("Record length : %,8d%n", recordLength));
text.append (String.format ("End of file : %,8d%n", eof));
}
else
text.append (String.format ("End of file : %,8d%n", buffer.length));
text.append ("\n");
}
// check whether file is spread over multiple buffers
if (buffers != null)
return treeFileText (text); // calls knownLength()
// check whether the record length is known
if (recordLength == 0)
return unknownLength (text);
text.append ("Offset Record# Text values\n");
text.append (
"------ ------- -------------------------------------------------------\n");
return knownLength (text, 0).toString ();
}
// ---------------------------------------------------------------------------------//
private String treeFileText (StringBuilder text)
// ---------------------------------------------------------------------------------//
{
text.append (" Offset Record# Text values\n");
text.append (
"---------- ------- -------------------------------------------------------\n");
for (TextBuffer tb : buffers)
{
buffer = tb.buffer;
text = knownLength (text, tb.firstRecNo);
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private StringBuilder knownLength (StringBuilder text, int recNo)
// ---------------------------------------------------------------------------------//
{
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
{
if (buffer[ptr] == 0)
{
recNo++;
continue;
}
int len = buffer.length - ptr;
int bytes = len < recordLength ? len : recordLength;
while (buffer[ptr + bytes - 1] == 0)
bytes--;
if ((buffer[ptr + bytes - 1] & 0x7F) == 0x0D) // ignore CR
bytes--;
String line = HexFormatter.getString (buffer, ptr, bytes);
line = line.replaceAll ("\\n", "\n ");
text.append (
String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo++, line));
}
return text;
}
// ---------------------------------------------------------------------------------//
private String unknownLength (StringBuilder text)
// ---------------------------------------------------------------------------------//
{
int nulls = 0;
int ptr = 0;
int size = buffer.length;
int lastVal = 0;
// boolean showAllOffsets = true;
if (textPreferences.showTextOffsets)
{
text.append (" Offset Text values\n");
text.append ("---------- -------------------------------------------------------"
+ "-------------------\n");
}
else
{
text.append (" Text values\n");
text.append ("-------------------------------------------------------"
+ "-------------------------------\n");
}
if (buffer.length == 0)
return text.toString ();
if (buffer[0] != 0 && textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr));
int gcd = 0;
while (ptr < size)
{
int val = buffer[ptr++] & 0x7F; // strip hi-order bit
if (val == 0)
++nulls;
else if (val == 0x0D) // carriage return
text.append ("\n");
else
{
if (nulls > 0)
{
if (textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr - 1));
nulls = 0;
gcd = gcd == 0 ? ptr - 1 : gcd (gcd, ptr - 1);
}
else if (lastVal == 0x0D && textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr - 1));
text.append ((char) val);
}
lastVal = val;
}
if (gcd > 0)
text.append (String.format ("%nGCD: %,d", gcd));
else if (text.length () > 0 && text.charAt (text.length () - 1) == '\n')
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private int gcd (int a, int b)
// ---------------------------------------------------------------------------------//
{
return a == 0 ? b : gcd (b % a, a);
}
}

View File

@ -1,7 +1,7 @@
package com.bytezone.diskbrowser.applefile;
// -----------------------------------------------------------------------------------//
public class CPMTextFile extends AbstractFile
public class CPMTextFile extends TextFile
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//
@ -18,7 +18,8 @@ public class CPMTextFile extends AbstractFile
{
StringBuilder text = new StringBuilder ();
text.append ("Name : " + name + "\n\n");
if (textPreferences.showHeader)
text.append ("Name : " + name + "\n\n");
int ptr = 0;
while (ptr < buffer.length && buffer[ptr] != (byte) 0x1A)

View File

@ -1,7 +1,7 @@
package com.bytezone.diskbrowser.applefile;
// -----------------------------------------------------------------------------------//
public class PascalText extends AbstractFile
public class PascalText extends TextFile
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//

210
src/com/bytezone/diskbrowser/applefile/TextFile.java Executable file → Normal file
View File

@ -1,28 +1,11 @@
package com.bytezone.diskbrowser.applefile;
import java.util.List;
import com.bytezone.diskbrowser.gui.TextPreferences;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class TextFile extends AbstractFile
// -----------------------------------------------------------------------------------//
public abstract class TextFile extends AbstractFile
{
static TextPreferences textPreferences; // set by MenuHandler
private int recordLength; // prodos aux
private List<TextBuffer> buffers; // only used if it is a Prodos text file
private int eof;
private boolean prodosFile;
// ---------------------------------------------------------------------------------//
public static void setTextPreferences (TextPreferences textPreferences)
// ---------------------------------------------------------------------------------//
{
TextFile.textPreferences = textPreferences;
}
// ---------------------------------------------------------------------------------//
public TextFile (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
@ -31,194 +14,9 @@ public class TextFile extends AbstractFile
}
// ---------------------------------------------------------------------------------//
public TextFile (String name, byte[] buffer, int auxType, int eof)
public static void setTextPreferences (TextPreferences textPreferences)
// ---------------------------------------------------------------------------------//
{
this (name, buffer);
this.eof = eof;
recordLength = auxType;
prodosFile = true;
TextFile.textPreferences = textPreferences;
}
// ---------------------------------------------------------------------------------//
public TextFile (String name, List<TextBuffer> buffers, int auxType, int eof)
// ---------------------------------------------------------------------------------//
{
super (name, null);
this.buffers = buffers;
this.eof = eof;
recordLength = auxType;
prodosFile = true;
}
// ---------------------------------------------------------------------------------//
@Override
public String getHexDump ()
// ---------------------------------------------------------------------------------//
{
if (buffers == null)
return (super.getHexDump ());
StringBuilder text = new StringBuilder ();
for (TextBuffer tb : buffers)
{
for (int i = 0, rec = 0; i < tb.buffer.length; i += tb.reclen, rec++)
{
text.append ("\nRecord #" + (tb.firstRecNo + rec) + "\n");
text.append (HexFormatter.format (tb.buffer, i, tb.reclen) + "\n");
}
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
if (textPreferences.showHeader)
{
text.append ("Name : " + name + "\n");
if (prodosFile)
{
text.append (String.format ("Record length : %,8d%n", recordLength));
text.append (String.format ("End of file : %,8d%n", eof));
}
else
text.append (String.format ("End of file : %,8d%n", buffer.length));
text.append ("\n");
}
// check whether file is spread over multiple buffers
if (buffers != null)
return treeFileText (text); // calls knownLength()
// check whether the record length is known
if (recordLength == 0)
return unknownLength (text);
text.append ("Offset Record# Text values\n");
text.append (
"------ ------- -------------------------------------------------------\n");
return knownLength (text, 0).toString ();
}
// ---------------------------------------------------------------------------------//
private String treeFileText (StringBuilder text)
// ---------------------------------------------------------------------------------//
{
text.append (" Offset Record# Text values\n");
text.append (
"---------- ------- -------------------------------------------------------\n");
for (TextBuffer tb : buffers)
{
buffer = tb.buffer;
text = knownLength (text, tb.firstRecNo);
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private StringBuilder knownLength (StringBuilder text, int recNo)
// ---------------------------------------------------------------------------------//
{
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
{
if (buffer[ptr] == 0)
{
recNo++;
continue;
}
int len = buffer.length - ptr;
int bytes = len < recordLength ? len : recordLength;
while (buffer[ptr + bytes - 1] == 0)
bytes--;
if ((buffer[ptr + bytes - 1] & 0x7F) == 0x0D) // ignore CR
bytes--;
String line = HexFormatter.getString (buffer, ptr, bytes);
line = line.replaceAll ("\\n", "\n ");
text.append (
String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo++, line));
}
return text;
}
// ---------------------------------------------------------------------------------//
private String unknownLength (StringBuilder text)
// ---------------------------------------------------------------------------------//
{
int nulls = 0;
int ptr = 0;
int size = buffer.length;
int lastVal = 0;
// boolean showAllOffsets = true;
if (textPreferences.showTextOffsets)
{
text.append (" Offset Text values\n");
text.append ("---------- -------------------------------------------------------"
+ "-------------------\n");
}
else
{
text.append (" Text values\n");
text.append ("-------------------------------------------------------"
+ "-------------------------------\n");
}
if (buffer.length == 0)
return text.toString ();
if (buffer[0] != 0 && textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr));
int gcd = 0;
while (ptr < size)
{
int val = buffer[ptr++] & 0x7F; // strip hi-order bit
if (val == 0)
++nulls;
else if (val == 0x0D) // carriage return
text.append ("\n");
else
{
if (nulls > 0)
{
if (textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr - 1));
nulls = 0;
gcd = gcd == 0 ? ptr - 1 : gcd (gcd, ptr - 1);
}
else if (lastVal == 0x0D && textPreferences.showTextOffsets)
text.append (String.format ("%,10d ", ptr - 1));
text.append ((char) val);
}
lastVal = val;
}
if (gcd > 0)
text.append (String.format ("%nGCD: %,d", gcd));
else if (text.length () > 0 && text.charAt (text.length () - 1) == '\n')
text.deleteCharAt (text.length () - 1);
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private int gcd (int a, int b)
// ---------------------------------------------------------------------------------//
{
return a == 0 ? b : gcd (b % a, a);
}
}
}

View File

@ -18,7 +18,7 @@ import com.bytezone.diskbrowser.applefile.OriginalHiResImage;
import com.bytezone.diskbrowser.applefile.PrintShopGraphic;
import com.bytezone.diskbrowser.applefile.ShapeTable;
import com.bytezone.diskbrowser.applefile.SimpleText2;
import com.bytezone.diskbrowser.applefile.TextFile;
import com.bytezone.diskbrowser.applefile.BasicTextFile;
import com.bytezone.diskbrowser.applefile.VisicalcFile;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress;
@ -197,7 +197,7 @@ abstract class AbstractCatalogEntry implements AppleFileSource
if (VisicalcFile.isVisicalcFile (buffer))
appleFile = new VisicalcFile (name, buffer);
else
appleFile = new TextFile (name, buffer);
appleFile = new BasicTextFile (name, buffer);
break;
case IntegerBasic:

View File

@ -32,7 +32,7 @@ import com.bytezone.diskbrowser.applefile.Palette;
import com.bytezone.diskbrowser.applefile.PaletteFactory.CycleDirection;
import com.bytezone.diskbrowser.applefile.QuickDrawFont;
import com.bytezone.diskbrowser.applefile.SHRPictureFile2;
import com.bytezone.diskbrowser.applefile.TextFile;
import com.bytezone.diskbrowser.applefile.BasicTextFile;
import com.bytezone.diskbrowser.applefile.VisicalcFile;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.SectorList;
@ -558,7 +558,7 @@ public class DataPanel extends JTabbedPane
public void setTextPreferences (TextPreferences textPreferences)
// ---------------------------------------------------------------------------------//
{
if (currentDataSource instanceof TextFile)
if (currentDataSource instanceof BasicTextFile)
setDataSource (currentDataSource);
}

View File

@ -22,7 +22,7 @@ import com.bytezone.diskbrowser.applefile.BasicProgram;
import com.bytezone.diskbrowser.applefile.HiResImage;
import com.bytezone.diskbrowser.applefile.Palette;
import com.bytezone.diskbrowser.applefile.PaletteFactory;
import com.bytezone.diskbrowser.applefile.TextFile;
import com.bytezone.diskbrowser.applefile.BasicTextFile;
import com.bytezone.diskbrowser.applefile.VisicalcFile;
import com.bytezone.diskbrowser.disk.DataDisk;
import com.bytezone.diskbrowser.disk.FormattedDisk;
@ -409,7 +409,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
{
textPreferences.showTextOffsets = showTextOffsetsItem.isSelected ();
textPreferences.showHeader = showTextHeaderItem.isSelected ();
TextFile.setTextPreferences (textPreferences);
BasicTextFile.setTextPreferences (textPreferences);
}
// ---------------------------------------------------------------------------------//

View File

@ -35,7 +35,7 @@ import com.bytezone.diskbrowser.applefile.ShapeTable;
import com.bytezone.diskbrowser.applefile.SimpleText;
import com.bytezone.diskbrowser.applefile.StoredVariables;
import com.bytezone.diskbrowser.applefile.TextBuffer;
import com.bytezone.diskbrowser.applefile.TextFile;
import com.bytezone.diskbrowser.applefile.BasicTextFile;
import com.bytezone.diskbrowser.appleworks.AppleworksADBFile;
import com.bytezone.diskbrowser.appleworks.AppleworksSSFile;
import com.bytezone.diskbrowser.appleworks.AppleworksWPFile;
@ -380,7 +380,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
else if (name.endsWith (".GIF") && HiResImage.isGif (exactBuffer))
file = new OriginalHiResImage (name, exactBuffer, auxType);
else
file = new TextFile (name, exactBuffer, auxType, endOfFile);
file = new BasicTextFile (name, exactBuffer, auxType, endOfFile);
break;
case FILE_TYPE_APPLESOFT_BASIC:
@ -608,7 +608,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
if (buffers.size () == 1 && name.endsWith (".S"))
return new MerlinSource (name, buffers.get (0).buffer, auxType, endOfFile);
return new TextFile (name, buffers, auxType, endOfFile);
return new BasicTextFile (name, buffers, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//
@ -622,7 +622,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
if (buffers.size () == 1 && name.endsWith (".S"))
return new MerlinSource (name, buffers.get (0).buffer, auxType, endOfFile);
return new TextFile (name, buffers, auxType, endOfFile);
return new BasicTextFile (name, buffers, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//
@ -640,7 +640,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
if (name.endsWith (".S"))
return new MerlinSource (name, buffer, auxType, endOfFile);
return new TextFile (name, buffer, auxType, endOfFile);
return new BasicTextFile (name, buffer, auxType, endOfFile);
}
// ---------------------------------------------------------------------------------//