1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * ident "%Z%%M% %I% %E% SMI" 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * Copyright (c) 1999-2000 by Sun Microsystems, Inc. 26*0Sstevel@tonic-gate * All rights reserved. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate import java.awt.*; 29*0Sstevel@tonic-gate import java.awt.event.*; 30*0Sstevel@tonic-gate import java.io.*; 31*0Sstevel@tonic-gate import java.util.ResourceBundle; 32*0Sstevel@tonic-gate import java.util.MissingResourceException; 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate public class PrintUtil { 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate // For I18N 37*0Sstevel@tonic-gate private static ResourceBundle rb = 38*0Sstevel@tonic-gate ResourceBundle.getBundle("GuiResource" /* NOI18N */); 39*0Sstevel@tonic-gate private static ResourceBundle hrb = 40*0Sstevel@tonic-gate ResourceBundle.getBundle("HelpData" /* NOI18N */); 41*0Sstevel@tonic-gate /** 42*0Sstevel@tonic-gate * Prints an object to either file or printer. Uses the toString() 43*0Sstevel@tonic-gate * method of the object to obtain a string representation for it. 44*0Sstevel@tonic-gate * @param obj the Object that is to be printed 45*0Sstevel@tonic-gate */ dump(Frame parent, Object obj)46*0Sstevel@tonic-gate public static void dump(Frame parent, Object obj) { 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate boolean usePrinter; 49*0Sstevel@tonic-gate String stringRep = obj.toString(); 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate Frame printFrame = new PrintFrame(parent, stringRep); 52*0Sstevel@tonic-gate printFrame.setVisible(true); 53*0Sstevel@tonic-gate } 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /** 56*0Sstevel@tonic-gate * Call rb.getString(), but catch exception and return English 57*0Sstevel@tonic-gate * key so that small spelling errors don't cripple the GUI 58*0Sstevel@tonic-gate * 59*0Sstevel@tonic-gate */ getString(String key)60*0Sstevel@tonic-gate private static final String getString(String key) { 61*0Sstevel@tonic-gate return (getString(rb, key)); 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate getString(ResourceBundle rb, String key)64*0Sstevel@tonic-gate private static final String getString(ResourceBundle rb, String key) { 65*0Sstevel@tonic-gate try { 66*0Sstevel@tonic-gate String res = rb.getString(key); 67*0Sstevel@tonic-gate return res; 68*0Sstevel@tonic-gate } catch (MissingResourceException e) { 69*0Sstevel@tonic-gate System.out.println("Missing resource "+key+", using English."); 70*0Sstevel@tonic-gate return key; 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate } 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /** 75*0Sstevel@tonic-gate * Forgets the command and filename that was last entered. 76*0Sstevel@tonic-gate */ reinitialize()77*0Sstevel@tonic-gate public static final void reinitialize() { 78*0Sstevel@tonic-gate PrintFrame.command = PrintFrame.fileName = null; 79*0Sstevel@tonic-gate } 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate /* 82*0Sstevel@tonic-gate ************************************************************ 83*0Sstevel@tonic-gate * I N N E R C L A S S E S F O L L O W 84*0Sstevel@tonic-gate ************************************************************ 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate /** 88*0Sstevel@tonic-gate * This class will show a Frame to determine whether the user wants 89*0Sstevel@tonic-gate * to print to a file and which file, if so, or to the printer 90*0Sstevel@tonic-gate * directly. Finally it will print to the appropriate destinaition. 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate private static class PrintFrame extends Frame { 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate private String text; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate static TextField command = null; 97*0Sstevel@tonic-gate static TextField fileName = null; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate private CheckboxGroup options; 100*0Sstevel@tonic-gate private Checkbox printer; 101*0Sstevel@tonic-gate private Checkbox file; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate private Frame parent; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate private static String defaultFileName = 106*0Sstevel@tonic-gate "/tmp/.SEAM_temp.txt" /* NO18N */; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /** 109*0Sstevel@tonic-gate * Constructor for PrintFrame. 110*0Sstevel@tonic-gate */ PrintFrame(Frame parent, String text)111*0Sstevel@tonic-gate public PrintFrame(Frame parent, String text) { 112*0Sstevel@tonic-gate super(rb.getString("SEAM Print Helper")); 113*0Sstevel@tonic-gate this.text = text; 114*0Sstevel@tonic-gate this.parent = parent; 115*0Sstevel@tonic-gate setLayout(new GridBagLayout()); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate addLabelsAndFields(); 118*0Sstevel@tonic-gate addCheckboxGroup(); 119*0Sstevel@tonic-gate addButtons(); 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate setBackground(parent.getBackground()); 122*0Sstevel@tonic-gate setForeground(parent.getForeground()); 123*0Sstevel@tonic-gate setSize(340, 160); 124*0Sstevel@tonic-gate setResizable(false); 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate printer.setState(true); 127*0Sstevel@tonic-gate command.setEditable(true); 128*0Sstevel@tonic-gate fileName.setEditable(false); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate addLabelsAndFields()131*0Sstevel@tonic-gate private void addLabelsAndFields() { 132*0Sstevel@tonic-gate GridBagConstraints gbc = new GridBagConstraints(); 133*0Sstevel@tonic-gate gbc.weightx = gbc.weighty = 1; 134*0Sstevel@tonic-gate gbc.gridwidth = 2; 135*0Sstevel@tonic-gate gbc.fill = GridBagConstraints.HORIZONTAL; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate gbc.gridx = 1; 138*0Sstevel@tonic-gate gbc.gridy = 0; 139*0Sstevel@tonic-gate add(new Label(getString("Print Command")), gbc); 140*0Sstevel@tonic-gate if (command == null) 141*0Sstevel@tonic-gate command = new TextField("lp" /* NO18N */, 10); 142*0Sstevel@tonic-gate gbc.gridx = 3; 143*0Sstevel@tonic-gate add(command, gbc); 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate gbc.gridx = 1; 146*0Sstevel@tonic-gate gbc.gridy = 1; 147*0Sstevel@tonic-gate add(new Label(getString("File Name")), gbc); 148*0Sstevel@tonic-gate if (fileName == null) 149*0Sstevel@tonic-gate fileName = new TextField("" /* NO18N */, 10); 150*0Sstevel@tonic-gate gbc.gridx = 3; 151*0Sstevel@tonic-gate add(fileName, gbc); 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate ActionListener al = new StartPrintingListener(); 154*0Sstevel@tonic-gate command.addActionListener(al); 155*0Sstevel@tonic-gate fileName.addActionListener(al); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate addCheckboxGroup()158*0Sstevel@tonic-gate private void addCheckboxGroup() { 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate GridBagConstraints gbc = new GridBagConstraints(); 161*0Sstevel@tonic-gate gbc.weightx = gbc.weighty = 1; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate options = new CheckboxGroup(); 164*0Sstevel@tonic-gate printer = new Checkbox(); 165*0Sstevel@tonic-gate file = new Checkbox(); 166*0Sstevel@tonic-gate printer.setCheckboxGroup(options); 167*0Sstevel@tonic-gate file.setCheckboxGroup(options); 168*0Sstevel@tonic-gate options.setSelectedCheckbox(printer); 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate printer.addItemListener(new PrintSelectedListener()); 171*0Sstevel@tonic-gate file.addItemListener(new FileSelectedListener()); 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate gbc.gridx = 0; 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate gbc.gridy = 0; 176*0Sstevel@tonic-gate add(printer, gbc); 177*0Sstevel@tonic-gate gbc.gridy = 1; 178*0Sstevel@tonic-gate add(file, gbc); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate addButtons()181*0Sstevel@tonic-gate private void addButtons() { 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate Button fileMore = new Button("..." /* NO18N */); 184*0Sstevel@tonic-gate Button print = new Button(getString("Print")); 185*0Sstevel@tonic-gate Button cancel = new Button(getString("Cancel")); 186*0Sstevel@tonic-gate Button help = new Button(getString("Help")); 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate GridBagConstraints gbc = new GridBagConstraints(); 189*0Sstevel@tonic-gate gbc.weightx = gbc.weighty = 1; 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate gbc.gridx = 5; 192*0Sstevel@tonic-gate gbc.gridy = 1; 193*0Sstevel@tonic-gate add(fileMore, gbc); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate gbc.gridx = 0; 197*0Sstevel@tonic-gate // gbc.gridy = 2; 198*0Sstevel@tonic-gate gbc.gridwidth = GridBagConstraints.REMAINDER; 199*0Sstevel@tonic-gate gbc.fill = GridBagConstraints.BOTH; 200*0Sstevel@tonic-gate // gbc.insets = new Insets(0, 10, 0, 10); 201*0Sstevel@tonic-gate // gbc.weighty = .1; 202*0Sstevel@tonic-gate // add(new LineSeparator(), gbc); 203*0Sstevel@tonic-gate // gbc.weighty = 1; 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate Panel p = new Panel(); 206*0Sstevel@tonic-gate gbc.insets = new Insets(0, 10, 0, 10); 207*0Sstevel@tonic-gate gbc.gridy = 2; 208*0Sstevel@tonic-gate add(p, gbc); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate p.setLayout(new GridBagLayout()); 211*0Sstevel@tonic-gate gbc = new GridBagConstraints(); 212*0Sstevel@tonic-gate gbc.fill = GridBagConstraints.HORIZONTAL; 213*0Sstevel@tonic-gate gbc.weightx = gbc.weighty = 1; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate p.add(print, gbc); 216*0Sstevel@tonic-gate p.add(cancel, gbc); 217*0Sstevel@tonic-gate p.add(help, gbc); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate print.addActionListener(new StartPrintingListener()); 220*0Sstevel@tonic-gate cancel.addActionListener(new CancelButtonListener()); 221*0Sstevel@tonic-gate help.addActionListener(new HelpButtonListener()); 222*0Sstevel@tonic-gate fileMore.addActionListener(new FileMoreButtonListener()); 223*0Sstevel@tonic-gate addWindowListener(new WindowCloseListener()); 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate /** 228*0Sstevel@tonic-gate * Called when the print frame has to be closed. IT may be closed 229*0Sstevel@tonic-gate * as a result of the user choosing any one of "print", "cancel" or 230*0Sstevel@tonic-gate * just the window close (which also cancels the printing). 231*0Sstevel@tonic-gate * @param doIt true if the printing should be carried out, false 232*0Sstevel@tonic-gate * if it is to be cancelled. 233*0Sstevel@tonic-gate */ close(boolean doIt)234*0Sstevel@tonic-gate private void close(boolean doIt) { 235*0Sstevel@tonic-gate if (doIt) { 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate Checkbox cb = options.getSelectedCheckbox(); 238*0Sstevel@tonic-gate String dest = null; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate try { 241*0Sstevel@tonic-gate if (cb == printer) { 242*0Sstevel@tonic-gate dest = command.getText().trim(); 243*0Sstevel@tonic-gate if (dest.length() == 0) 244*0Sstevel@tonic-gate return; 245*0Sstevel@tonic-gate else 246*0Sstevel@tonic-gate print(dest); 247*0Sstevel@tonic-gate } else { 248*0Sstevel@tonic-gate dest = fileName.getText().trim(); 249*0Sstevel@tonic-gate if (dest.length() == 0) 250*0Sstevel@tonic-gate return; 251*0Sstevel@tonic-gate else 252*0Sstevel@tonic-gate saveToFile(dest); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate } catch (IOException e) { 255*0Sstevel@tonic-gate // System.out.println(e); XXX 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate } // end of doIt 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate dispose(); 260*0Sstevel@tonic-gate }// end of close 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /** 263*0Sstevel@tonic-gate * Prints the string to a file and then send the file's contents 264*0Sstevel@tonic-gate * to the printer. It then deletes the file. 265*0Sstevel@tonic-gate * @param command the print comman to be used 266*0Sstevel@tonic-gate */ print(String command)267*0Sstevel@tonic-gate private void print(String command) throws IOException { 268*0Sstevel@tonic-gate Thread printThread = new PrintThread(command); 269*0Sstevel@tonic-gate printThread.start(); 270*0Sstevel@tonic-gate saveToFile(defaultFileName); 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /** 274*0Sstevel@tonic-gate * Saves the string onto the file. 275*0Sstevel@tonic-gate * @param fileName the file to which the string must be written 276*0Sstevel@tonic-gate */ saveToFile(String fileName)277*0Sstevel@tonic-gate private void saveToFile(String fileName) throws IOException { 278*0Sstevel@tonic-gate PrintWriter outFile = null; 279*0Sstevel@tonic-gate outFile = new PrintWriter(new BufferedWriter(new 280*0Sstevel@tonic-gate FileWriter(fileName))); 281*0Sstevel@tonic-gate outFile.print(text); 282*0Sstevel@tonic-gate outFile.flush(); 283*0Sstevel@tonic-gate outFile.close(); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate // Listeners for the gui components: 287*0Sstevel@tonic-gate // javac in current makefile will not compile if these are anonymous. 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate private class PrintSelectedListener implements ItemListener { itemStateChanged(ItemEvent e)290*0Sstevel@tonic-gate public void itemStateChanged(ItemEvent e) { 291*0Sstevel@tonic-gate command.setEditable(true); 292*0Sstevel@tonic-gate fileName.setEditable(false); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate private class FileSelectedListener implements ItemListener { itemStateChanged(ItemEvent e)297*0Sstevel@tonic-gate public void itemStateChanged(ItemEvent e) { 298*0Sstevel@tonic-gate command.setEditable(false); 299*0Sstevel@tonic-gate fileName.setEditable(true); 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate private class StartPrintingListener implements ActionListener { actionPerformed(ActionEvent e)304*0Sstevel@tonic-gate public void actionPerformed(ActionEvent e) { 305*0Sstevel@tonic-gate close(true); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate private class CancelButtonListener implements ActionListener { actionPerformed(ActionEvent e)310*0Sstevel@tonic-gate public void actionPerformed(ActionEvent e) { 311*0Sstevel@tonic-gate close(false); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate } 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate private class HelpButtonListener implements ActionListener { actionPerformed(ActionEvent e)316*0Sstevel@tonic-gate public void actionPerformed(ActionEvent e) { 317*0Sstevel@tonic-gate HelpDialog hd = new HelpDialog(PrintFrame.this, 318*0Sstevel@tonic-gate getString("Help for Date/Time Helper"), false); 319*0Sstevel@tonic-gate hd.setVisible(true); 320*0Sstevel@tonic-gate hd.setText(getString(hrb, "PrintUtilHelp")); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate private class FileMoreButtonListener implements 325*0Sstevel@tonic-gate ActionListener { 326*0Sstevel@tonic-gate actionPerformed(ActionEvent e)327*0Sstevel@tonic-gate public void actionPerformed(ActionEvent e) { 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate // Turn off print "command" and enable output "file name" 330*0Sstevel@tonic-gate options.setSelectedCheckbox(file); 331*0Sstevel@tonic-gate command.setEditable(false); 332*0Sstevel@tonic-gate fileName.setEditable(true); 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate FileDialog fd = new FileDialog(PrintFrame.this, 335*0Sstevel@tonic-gate getString("SEAM File Helper"), 336*0Sstevel@tonic-gate FileDialog.SAVE); 337*0Sstevel@tonic-gate fd.setDirectory(System.getProperty("user.dir" /* NO18N */)); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate // Use what's in the fileName field already to initialize the 340*0Sstevel@tonic-gate // FileDialog 341*0Sstevel@tonic-gate String fileNameText = fileName.getText(); 342*0Sstevel@tonic-gate if (fileNameText != null) { 343*0Sstevel@tonic-gate File file = new File(fileNameText); 344*0Sstevel@tonic-gate if (file.isDirectory()) 345*0Sstevel@tonic-gate fd.setDirectory(fileNameText); 346*0Sstevel@tonic-gate else { 347*0Sstevel@tonic-gate fd.setFile(fileNameText); 348*0Sstevel@tonic-gate String parent = file.getParent(); 349*0Sstevel@tonic-gate if (parent != null) 350*0Sstevel@tonic-gate fd.setDirectory(parent); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate fd.setVisible(true); 355*0Sstevel@tonic-gate if (fd.getFile() != null && fd.getFile().length() > 0) 356*0Sstevel@tonic-gate fileName.setText(fd.getDirectory() + fd.getFile()); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /** 361*0Sstevel@tonic-gate * This class prints out to a temporary file defaultFileName, send 362*0Sstevel@tonic-gate * that to the printer, and then deletes the file after TIME_OUT 363*0Sstevel@tonic-gate * milliseconds. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate private class PrintThread extends Thread { 366*0Sstevel@tonic-gate private String command; 367*0Sstevel@tonic-gate private long TIME_OUT = 30000; // milliseconds 368*0Sstevel@tonic-gate PrintThread(String command)369*0Sstevel@tonic-gate public PrintThread(String command) { 370*0Sstevel@tonic-gate this.command = command; 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate run()373*0Sstevel@tonic-gate public void run() { 374*0Sstevel@tonic-gate try { 375*0Sstevel@tonic-gate Process printProcess = Runtime.getRuntime() 376*0Sstevel@tonic-gate .exec(command + " " /* NO18N */ + defaultFileName); 377*0Sstevel@tonic-gate try { 378*0Sstevel@tonic-gate sleep(TIME_OUT); 379*0Sstevel@tonic-gate } catch (InterruptedException e) {} 380*0Sstevel@tonic-gate printProcess.destroy(); 381*0Sstevel@tonic-gate File tempFile = new File(PrintFrame.this.defaultFileName); 382*0Sstevel@tonic-gate tempFile.delete(); 383*0Sstevel@tonic-gate } catch (IOException e) { 384*0Sstevel@tonic-gate // System.err.println(e); XXX 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate } 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate private class WindowCloseListener extends WindowAdapter { windowClosing(WindowEvent e)390*0Sstevel@tonic-gate public void windowClosing(WindowEvent e) { 391*0Sstevel@tonic-gate close(false); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate } // class PrintFrame 395*0Sstevel@tonic-gate } 396