dmolony-DiskBrowser/src/com/bytezone/diskbrowser/applefile/ProdosDirectory.java

187 lines
6.6 KiB
Java
Executable File

package com.bytezone.diskbrowser.applefile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Locale;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.prodos.DirectoryHeader;
import com.bytezone.diskbrowser.prodos.ProdosConstants;
import com.bytezone.diskbrowser.prodos.ProdosDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------//
public class ProdosDirectory extends AbstractFile implements ProdosConstants
// -----------------------------------------------------------------------------------//
{
private static Locale US = Locale.US; // to force 3 character months
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy", US);
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
static final String UNDERLINE =
"----------------------------------------------------\n";
private static final String NO_DATE = "<NO DATE>";
private final ProdosDisk parentFD;
private final int totalBlocks;
private final int freeBlocks;
private final int usedBlocks;
// ---------------------------------------------------------------------------------//
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
int totalBlocks, int freeBlocks, int usedBlocks)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
this.parentFD = (ProdosDisk) parent;
this.totalBlocks = totalBlocks;
this.freeBlocks = freeBlocks;
this.usedBlocks = usedBlocks;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
if (showDebugText)
return getDebugText ();
else
return getDirectoryText ();
}
// ---------------------------------------------------------------------------------//
private String getDebugText ()
// ---------------------------------------------------------------------------------//
{
List<DirectoryHeader> directoryHeaders = parentFD.getDirectoryHeaders ();
StringBuilder text = new StringBuilder ();
for (DirectoryHeader directoryHeader : directoryHeaders)
{
text.append (UNDERLINE);
text.append (directoryHeader.getText ());
text.append ("\n");
text.append (UNDERLINE);
directoryHeader.listFileEntries (text);
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String getDirectoryText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
text.append ("File : " + parentFD.getDisplayPath () + "\n\n");
for (int i = 0; i < buffer.length; i += ENTRY_SIZE)
{
int storageType = (buffer[i] & 0xF0) >> 4;
if (storageType == 0)
continue; // break??
int nameLength = buffer[i] & 0x0F;
String filename = HexFormatter.getString (buffer, i + 1, nameLength);
String subType = "";
switch (storageType)
{
case VOLUME_HEADER:
case SUBDIRECTORY_HEADER:
String root = storageType == VOLUME_HEADER ? "/" : "";
text.append (root + filename + "\n\n");
text.append (" NAME TYPE BLOCKS "
+ "MODIFIED CREATED ENDFILE SUBTYPE" + "\n\n");
break;
case FREE:
case SEEDLING:
case SAPLING:
case TREE:
case PASCAL_ON_PROFILE:
case GSOS_EXTENDED_FILE:
case SUBDIRECTORY:
int type = buffer[i + 16] & 0xFF;
int blocks = Utility.getShort (buffer, i + 19);
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
String dateC =
createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
String dateM =
modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
String timeC = createdDate == null ? "" : createdDate.format (tf);
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
int eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
int fileType = buffer[i + 16] & 0xFF;
String locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
int aux = Utility.getShort (buffer, i + 31);
switch (fileType)
{
case FILE_TYPE_TEXT:
subType = String.format ("R=%5d", aux);
break;
case FILE_TYPE_BINARY:
case FILE_TYPE_PNT:
case FILE_TYPE_PIC:
case FILE_TYPE_FOT:
subType = String.format ("A=$%4X", aux);
break;
case FILE_TYPE_AWP:
int flags = Utility.intValue (buffer[i + 32], buffer[i + 31]); // aux backwards!
if (flags != 0)
filename = convert (filename, flags);
break;
default:
subType = "";
}
String forkFlag = storageType == 5 ? "+" : " ";
text.append (
String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s %04X%n",
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks,
dateM, timeM, dateC, timeC, eof, subType, aux));
break;
default:
text.append (" <Unknown strage type : " + storageType + "\n");
}
}
text.append (
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
freeBlocks, usedBlocks, totalBlocks));
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private String convert (String name, int flags)
// ---------------------------------------------------------------------------------//
{
char[] newName = name.toCharArray ();
for (int i = 0, weight = 0x8000; i < newName.length; i++, weight >>>= 1)
{
if ((flags & weight) != 0)
{
if (newName[i] == '.')
newName[i] = ' ';
else if (newName[i] >= 'A' && newName[i] <= 'Z')
newName[i] += 32;
}
}
return new String (newName);
}
}