From da3177feea6966b3ac1a3ffccded7e9c0a6e8b43 Mon Sep 17 00:00:00 2001 From: Robert Greene Date: Thu, 17 Jun 2004 02:59:42 +0000 Subject: [PATCH] Supports Pascal ".text" file formats. --- .../storage/filters/PascalTextFileFilter.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/com/webcodepro/applecommander/storage/filters/PascalTextFileFilter.java diff --git a/src/com/webcodepro/applecommander/storage/filters/PascalTextFileFilter.java b/src/com/webcodepro/applecommander/storage/filters/PascalTextFileFilter.java new file mode 100644 index 0000000..099d338 --- /dev/null +++ b/src/com/webcodepro/applecommander/storage/filters/PascalTextFileFilter.java @@ -0,0 +1,122 @@ +/* + * AppleCommander - An Apple ][ image utility. + * Copyright (C) 2004 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 com.webcodepro.applecommander.storage.FileEntry; +import com.webcodepro.applecommander.storage.FileFilter; + +/** + * Filter the given file as a Pascal ".text" file. + *

+ * From the Apple Pascal v1.2 Operating System Reference manual: + * + * Text files in Apple Pascal + *


+ * At the beginning of each textfile is a 1024-byte (two blocks on + * diskette) header page, which contains information for the texteditor. + * This space is reserved for use by the text editor, and is respected + * by all portions of the system. When a user program opens a text file, + * and REWRITEs or RESETs it with a title ending in .TEXT, the I/O + * subsystem will create and skip over the initial header page. This is + * done to faciliatie users editing their input and/or output data. The + * file-handler wil transfer the header page only on a disk-to-disk + * transfer, and will omit it on a transfer to a serial device (thus + * transfers to PRINTER: abd CONSOLE: will omit the header page). + *

+ * Following the initial header page, the text itself appears in + * subsequent 1024-byte text pages (two block each, on diskette), + * where a text page is defined:
+ *

+ *     [DLE] [indent] [text] [cr] [dle] [indent] [text] [CR] .. [nulls]
+ * 
+ * DLE's (Data Link Escapes) are followed by an indent-code, which is a + * byte containing the value 32+(number to indent). The nulls at the + * end of the page follow a [CR} in all cases, and are a pad to the end + * of a 1024-byte page (because the compiler wants integral numbers of + * lines on a page). The Data Link Escape and corresponding indentation + * code are optional. In a given text file, some lines will have the + * codes, and some won't. + * + * (Thanks to Hans Otten for sending in this information.) + * + * @author: Rob Greene + */ +public class PascalTextFileFilter implements FileFilter { + private static final char NUL = 0x00; + private static final char CR = 0x0d; + private static final char DLE = 0x10; + private static final int HEADER_SIZE = 1024; + private static final int INDENT_BASE_VALUE = 0x20; + + /** + * Constructor for PascalTextFileFilter. + */ + public PascalTextFileFilter() { + super(); + } + + /** + * Process the given FileEntry and return a byte array + * with filtered data; use PrintWriter to get platform + * agnostic line endings. + */ + public byte[] filter(FileEntry fileEntry) { + byte[] fileData = fileEntry.getFileData(); + int offset = HEADER_SIZE; + ByteArrayOutputStream byteArray = new + ByteArrayOutputStream(fileData.length); + PrintWriter printWriter = new PrintWriter(byteArray, true); + while (offset < fileData.length) { + char c = (char)(fileData[offset] & 0x7f); // Will the bitwise AND be a problem?? + switch (c) { + case NUL: break; // ignore + case CR: printWriter.println(); + break; + case DLE: if (offset+1 < fileData.length) { + offset++; + int indent = fileData[offset] - INDENT_BASE_VALUE; + while (indent-- > 0) { + printWriter.print(' '); + } + } + break; + default: printWriter.print(c); + break; + } + offset++; + } + return byteArray.toByteArray(); + } + + + /** + * Give suggested file name. + */ + public String getSuggestedFileName(FileEntry fileEntry) { + String fileName = fileEntry.getFilename().trim(); + if (!fileName.toLowerCase().endsWith(".txt")) { + fileName = fileName + ".txt"; + } + return fileName; + } +}