--- /dev/null
+/*
+ * 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());
+ }
+ }
+ }
+ }
+}