/* * [JDisplayMacro.java] * * Summary: implements JDisplay macro to display colourised listing three different ways. * * Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.1 2005-11-11 */ package com.mindprod.jdisplayaux; import com.mindprod.common18.Build; import com.mindprod.common18.EIO; import com.mindprod.htmlmacros.macro.Global; import com.mindprod.htmlmacros.macro.Macro; import com.mindprod.jdisplay.Footprint; import com.mindprod.jdisplay.Geometry; import com.mindprod.jtokens.Token; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.PrintWriter; import static com.mindprod.jdisplayaux.WaysToRender.bestFit; import static java.lang.System.*; /** * implements JDisplay macro to display colourised listing three different ways. *

* Decides which technique to use based on the size of the listing - * inline for very short, iframe for short and Applet for long. * * @author Roedy Green, Canadian Mind Products * @version 1.3 2007-06-03 * @see WaysToRender * @since 2005 */ public class JDisplayMacro extends Macro { /** * true if want extra debugging output */ private static final boolean DEBUGGING = false; /** * how to use the macro */ private static final String USAGE = "\nJDisplay macro needs snippetname [maxwidth] [maxheight]"; private static String sourceDirName; /** * stays open for whole session to log which snippets actually used. */ private static PrintWriter usedSnippets = null; /** * @param snippetName snippetName name f the snippet relative to its document, e.g. asnip.javafrag, no lead * /snippet/ser or trailing .ser. * @param maxWidth max width to allow for an Applet display * @param maxHeight max height to allow for an Applet display * * @return expanded macro HTML */ private String expand( String snippetName, int maxWidth, int maxHeight ) { try { // O P E N // have snippetName relative to master document. final File f = new File( fileBeingProcessed.getParentFile(), "snippet/ser/" + snippetName + ".ser" ); if ( !f.exists() ) { throw new IllegalArgumentException( "missing JDisplay " + EIO.getCanOrAbsPath( f ) ); } // insist that snippet match case perfectly // compare just the file part, no dir. if ( !f.getCanonicalFile().getName().equals( f.getName() ) ) { throw new IllegalArgumentException( "case mismatch JDisplay " + EIO.getCanOrAbsPath( f ) ); } final ObjectInputStream ois = EIO.getObjectInputStream( f, 4 * 1024, true ); // R E A D, footprintversion, footprint, tokens final long expectedVersion = Footprint.serialVersionUID; final long fileVersion = ( Long ) ois.readObject(); if ( fileVersion != expectedVersion ) { throw new IllegalArgumentException( "Stale " + EIO.getCanOrAbsPath( f ) + " Version " + fileVersion + " should be " + expectedVersion ); } Footprint footprint = ( Footprint ) ois.readObject(); if ( DEBUGGING ) { out.println( "\nFootprint for " + snippetName ); out.println( footprint ); } /* * We don't need to read the tokens unless we decide to expand * inline. We don't need to recompute with our font metrics. Let * WaysToRender figure out best way to render given the amount of * space we have. */ footprint = bestFit( footprint, maxWidth, maxHeight ); if ( footprint == null || footprint.viewportWidth == 0 ) { throw new IllegalArgumentException( "failed to find a pattern to render JDisplay " + snippetName ); } if ( DEBUGGING ) { out.println( "Footprint best match:" ); out.println( footprint ); } // collect list of used snippets to detect orphans // strip lead E:\mindprod\ final String uDirWhereSnippetDisplays = fileBeingProcessed.getParent() .substring( Build.MINDPROD_WEBROOT.length() + 1 ).replace( '\\', '/' ); final String uSnippetName = uDirWhereSnippetDisplays + "/snippet/" + snippetName; if ( DEBUGGING ) { out.println( uSnippetName + " for " + EIO.getCanOrAbsPath( fileBeingProcessed ) ); } usedSnippets.println( uSnippetName ); // webrootrelative / name of the raw snippet with ext switch ( footprint.rendering ) { case INLINE: // for small snippets, generate inline Token[] tokens = ( Token[] ) ois.readObject(); // C L O S E ois.close(); // generate inline return RenderInline.expand( tokens ); case APPLET: /* * let Applet read the ser file * generate code like this */ return RenderWithApplet.expand( footprint, snippetName, fileBeingProcessed ); case IFRAME: return RenderAsIframe.expand( footprint, snippetName ); default: throw new IllegalArgumentException( "invalid enum " + footprint.rendering ); } } catch ( ClassNotFoundException e ) { throw new IllegalArgumentException( "corrupt JDisplay " + snippetName + " object stream " + e.getMessage() ); } catch ( IOException e ) { throw new IllegalArgumentException( "problem getting JDisplay source for " + snippetName + e.getMessage() ); } } // end expand public static void fireup() { try { // combine dirsWithMacros and dirsWithIncludes into dirsToProcess; sourceDirName = Global.configuration.getSourceDirWithSlashes(); usedSnippets = EIO.getPrintWriter( new File( sourceDirName + "/jdisplayorphans/usedsnippets.log" ), 64 * 1024, EIO.UTF8 ); } catch ( FileNotFoundException e ) { err.println( e.getMessage() ); System.exit( 1 ); } } public static void shutdown() { usedSnippets.close(); } /** * Generate a JDisplay file widthInPixel maxHeightInPixels. If would render bigger than this Applet scrolls in * window. Making these smaller than usual forces use of Applet. Making these bigger than usual forces use of * inline * HTML expansion. expands takes filename relative to enclosing * document, e.g. use snippet/... max size optional * * @param parms parameters from macro * @param quiet true if want to suppress optional output. * @param verbose true if want extra status information. * * @return expanded macro HTML */ public String expandMacro( String[] parms, final boolean quiet, final boolean verbose ) { if ( parms.length < 1 ) { throw new IllegalArgumentException( USAGE ); } // fix in cased used \. // without snippet/ or snippet/ser String snippetName = parms[ 0 ].replace( File.separatorChar, '/' ); if ( snippetName.startsWith( "snippet/" ) ) { snippetName = snippetName.substring( "snippet/".length() ); } // temporarily crank these up if you want JDisplay Applet to never be // used, // so will display HTML inline al the elapsedTime. int maxWidth = Geometry.DEFAULT_MAX_WIDTH_PX; int maxHeight = Geometry.DEFAULT_MAX_HEIGHT_PX; if ( parms.length >= 3 ) { maxWidth = Integer.parseInt( parms[ 1 ] ); maxHeight = Integer.parseInt( parms[ 2 ] ); } return expand( snippetName, maxWidth, maxHeight ); } }