OSDN Git Service

Change directory structure.
[dvibrowser/dvi2epub.git] / src / main / java / jp / sourceforge / dvibrowser / dvicore / special / SourceSpecialParser.java
diff --git a/src/main/java/jp/sourceforge/dvibrowser/dvicore/special/SourceSpecialParser.java b/src/main/java/jp/sourceforge/dvibrowser/dvicore/special/SourceSpecialParser.java
new file mode 100644 (file)
index 0000000..2e0c0bb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009, Takeyuki Nagao
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ * 
+ *  * Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer in the documentation and/or other
+ *    materials provided with the distribution.
+ *    
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+package jp.sourceforge.dvibrowser.dvicore.special;
+
+import java.util.Stack;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jp.sourceforge.dvibrowser.dvicore.DviException;
+import jp.sourceforge.dvibrowser.dvicore.DviObject;
+import jp.sourceforge.dvibrowser.dvicore.api.DviContextSupport;
+import jp.sourceforge.dvibrowser.dvicore.api.DviDocument;
+
+
+public class SourceSpecialParser
+extends DviObject
+{
+  private static final Logger LOGGER = Logger.getLogger(SourceSpecialParser.class.getName());
+  private final AnchorSet anchorSet = new AnchorSet();
+  private final PrivateExecuter exe;
+
+  public SourceSpecialParser(DviContextSupport dcs)
+  {
+    super(dcs);
+    exe = new PrivateExecuter(dcs, anchorSet);
+  }
+
+  private static final Pattern srcPat
+    = Pattern.compile(
+      "\\s*src:\\s*([-0-9]*)\\s\\s*(.*)\\s*",
+      Pattern.CASE_INSENSITIVE
+    );
+  
+  public void execute(DviDocument doc)
+  throws DviException
+  {
+    for (int p=0; p<doc.getTotalPages(); p++) {
+      exe.execute(doc.getPage(p));
+    }
+  }
+
+  public AnchorSet getAnchorSet()
+  {
+    return anchorSet;
+  }
+
+  private static class PrivateExecuter
+  extends AbstractDviSpecialExecutor
+  {
+    private final AnchorSet anchorSet;
+    public PrivateExecuter(DviContextSupport dcs, AnchorSet anchorSet) {
+      super(dcs);
+      this.anchorSet = anchorSet;
+    }
+
+    private static class StackItem
+    {
+      private final long start;
+      private final String tag;
+      private final String data;
+      private final int lineNumber;
+      public StackItem(long start, String tag, String data, int lineNumber) {
+        this.start = start;
+        this.tag = tag;
+        this.data = data;
+        this.lineNumber = lineNumber;
+      }
+    }
+
+    private final Stack<StackItem> stack
+      = new Stack<StackItem>();
+    
+    @Override
+    public void end() throws DviException {
+      flushStack();
+      super.end();
+    }
+    
+    private void flushStack()
+    {
+      if (!stack.empty()) {
+        StackItem it = stack.pop();
+        DviExecutorContextImpl ctx = getExecutorContext();
+        Anchor a = null;
+        if ("src".equals(it.tag)) {
+          a = new Anchor.Source(
+            it.start,
+            ctx.getCommandRange().end(),
+            it.data,
+            it.lineNumber
+          );
+        }
+        anchorSet.add(a);
+      }
+    }
+
+    @Override
+    public void doSpecial(byte [] _xxx)
+    throws DviException
+    {
+      String xxx = new String(_xxx);
+      Matcher mat;
+      DviExecutorContextImpl ctx = getExecutorContext();
+      if ((mat = srcPat.matcher(xxx)).matches()) {
+        flushStack();
+        try {
+          stack.push(
+            new StackItem(
+              ctx.getCommandRange().begin(),
+              "src",
+              mat.group(2), // filename
+              Integer.parseInt(mat.group(1)) // linenumber
+            )
+          );
+        } catch (NumberFormatException e) {
+          LOGGER.warning(e.getMessage());
+        }
+      }
+    }
+  }
+}