/***************************************************************************
* $Id$
**
* Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
**
* This file is part of an example program for Qt.  This example
* program may be used, distributed and modified without limitation.
**
****************************************************************************/

import org.trinitydesktop.qt.*;
import java.util.ArrayList;

class Editor extends TQWidget
{
private   TQMenuBar 	   m;
private   TQMultiLineEdit e;
private   TQPrinter        printer = new TQPrinter();
private   TQPopupMenu	   save_as;
private   TQPopupMenu	   open_as;
private   boolean changed;


private   boolean no_writing = false;

static ArrayList codecList = null;

static final int Uni = 0;
static final int MBug = 1;
static final int Lat1 = 2;
static final int Local = 3;
static final int Guess = 4;
static final int Codec = 5;


Editor( )
{
	this(null, null);
}

Editor( TQWidget  parent , String  name )
{
    super( parent, name, WDestructiveClose );
    m = new TQMenuBar( this, "menu" );

    TQPopupMenu  file = new TQPopupMenu(this);
    m.insertItem( "&File", file );

    file.insertItem( "&New",   this, SLOT("newDoc()"),   new TQKeySequence(ALT+Key_N) );
    file.insertItem( "&Open...",  this, SLOT("load()"),     new TQKeySequence(ALT+Key_O) );
    file.insertItem( "&Save...",  this, SLOT("save()"),     new TQKeySequence(ALT+Key_S) );
    file.insertSeparator();
    open_as = new TQPopupMenu(file);
    file.insertItem( "Open &As",  open_as );
    save_as = new TQPopupMenu(file);
    file.insertItem( "Sa&ve As",  save_as );
    file.insertItem( "Add &Encoding", this, SLOT("addEncoding()") );    
    file.insertSeparator();
    file.insertItem( "&Print...", this, SLOT("print()"),    new TQKeySequence(ALT+Key_P) );
    file.insertSeparator();
    file.insertItem( "&Close", this, SLOT("close()"),new TQKeySequence(ALT+Key_W) );
    file.insertItem( "&Quit",  tqApp(), SLOT("closeAllWindows()"),     new TQKeySequence(ALT+Key_Q) );

    connect( save_as, SIGNAL("activated(int)"), this, SLOT("saveAsEncoding(int)") );
    connect( open_as, SIGNAL("activated(int)"), this, SLOT("openAsEncoding(int)") );
    rebuildCodecList();

    TQPopupMenu  edit = new TQPopupMenu(m);
    m.insertItem( "&Edit", edit );

    edit.insertItem( "To &Uppercase",   this, SLOT("toUpper()"),   new TQKeySequence(ALT+Key_U) );
    edit.insertItem( "To &Lowercase",   this, SLOT("toLower()"),   new TQKeySequence(ALT+Key_L) );
    edit.insertSeparator();
    edit.insertItem( "&Select Font" ,	 this, SLOT("getFont()"),     new TQKeySequence(ALT+Key_F) );
    changed = false;
    e = new TQMultiLineEdit( this, "editor" );
    connect( e, SIGNAL(" textChanged()"), this, SLOT(" textChanged()") );

    // We use Unifont - if you have it installed you'll see all
    // Unicode character glyphs.
    //
    // Unifont only comes in one pixel size, so we cannot let
    // it change pixel size as the display DPI changes.
    //
    TQFont unifont = new TQFont("unifont",16,50); unifont.setPixelSize(16);
    e.setFont( unifont );

    e.setFocus();
}


public void getFont()
{
    boolean[] ok = { true };
    TQFont f = TQFontDialog.getFont( ok, e.font() );
    if ( ok[0] ) {
        e.setFont( f );
    }
}



void rebuildCodecList()
{
    codecList = new ArrayList();
    TQTextCodec codec = null;
    int i;
    for (i = 0; (codec = TQTextCodec.codecForIndex(i)) != null; i++)
	codecList.add( codec );
    int n = codecList.size();
    for (int pm=0; pm<2; pm++) {
	TQPopupMenu menu = pm != 0 ? open_as : save_as;
	menu.clear();
	String local = "Local (";
	local += TQTextCodec.codecForLocale().name();
	local += ")";
	menu.insertItem( local, Local );
	menu.insertItem( "Unicode", Uni );
	menu.insertItem( "Latin1", Lat1 );
	menu.insertItem( "Microsoft Unicode", MBug );
	if ( pm != 0 )
	    menu.insertItem( "[guess]", Guess );
	for ( i = 0; i < n; i++ )
	    menu.insertItem( ((TQTextCodec) codecList.get(i)).name(), Codec + i );
    }
}

void newDoc()
{
    Editor ed = new Editor();
    if ( tqApp().desktop().size().width() < 450
	 || tqApp().desktop().size().height() < 450 ) {
	ed.showMaximized();
    } else {
	ed.resize( 400, 400 );
	ed.show();
    }
}


void load()
{
    String fn = TQFileDialog.getOpenFileName( "", "", this );
    if ( fn != null )
	load( fn, -1 );
}

void load( String fileName )
{
	load(fileName, -1);
}

void load( String fileName, int code )
{
    TQFile f = new TQFile( fileName );
    if ( !f.open( TQIODevice.IO_ReadOnly ) )
	return;

    e.setAutoUpdate( false );

    TQTextStream t = new TQTextStream(f);
    if ( code >= Codec )
	t.setCodec( (TQTextCodec) codecList.get(code-Codec) );
    else if ( code == Uni )
	t.setEncoding( TQTextStream.Unicode );
    else if ( code == MBug )
	t.setEncoding( TQTextStream.UnicodeReverse );
    else if ( code == Lat1 )
	t.setEncoding( TQTextStream.Latin1 );
    else if ( code == Guess ) {
	f = new TQFile(fileName);
	f.open(TQIODevice.IO_ReadOnly);
	StringBuffer buffer = new StringBuffer();
	int l = 256;
	l=(int)f.readBlock(buffer,l);
	TQTextCodec codec = TQTextCodec.codecForContent(buffer.toString(), l);
	if ( codec != null ) {
	    TQMessageBox.information(this,"Encoding","Codec: "+codec.name());
	    t.setCodec( codec );
	}
    }
    e.setText( t.read() );
    f.close();

    e.setAutoUpdate( true );
    e.repaint();
    setCaption( fileName );

    changed = false;
}

void openAsEncoding( int code )
{
    //storing filename (proper save) is left as an exercise...
    String fn = TQFileDialog.getOpenFileName( "", "", this );
    if ( !fn.equals("") )
	load( fn, code );
}

boolean save()
{
    //storing filename (proper save) is left as an exercise...
    String fn = TQFileDialog.getSaveFileName( "", "", this );
    if ( !fn.equals("") )
	return saveAs( fn );
    return false;
}

void saveAsEncoding( int code )
{
    //storing filename (proper save) is left as an exercise...
    String fn = TQFileDialog.getSaveFileName( "", "", this );
    if ( !fn.equals("") )
	saveAs( fn, code );
}

void addEncoding()
{
    String fn = TQFileDialog.getOpenFileName( "", "*.map", this );
    if ( !fn.equals("") ) {
	TQFile f = new TQFile(fn);
	if (f.open(TQIODevice.IO_ReadOnly)) {
	    if (TQTextCodec.loadCharmap(f) != null) {
		rebuildCodecList();
	    } else {
		TQMessageBox.warning(null,"Charmap error",
		    "The file did not contain a valid charmap.\n\n"
		    + "A charmap file should look like this:\n"
		       + "  <code_set_name> thename\n"
		       + "  <escape_char> /\n"
		       + "  % alias thealias\n"
		       + "  CHARMAP\n"
		       + "  <tokenname> /x12 <U3456>\n"
		       + "  <tokenname> /xAB/x12 <U0023>\n"
		       + "  ...\n"
		       + "  END CHARMAP\n"
		);
	    }
	}
    }
}


boolean saveAs( String fileName )
{
	return saveAs(fileName, -1);
}

boolean saveAs( String fileName, int code )
{
    TQFile f = new TQFile( fileName );
    if ( no_writing || !f.open( TQIODevice.IO_WriteOnly ) ) {
	TQMessageBox.warning(this,"I/O Error",
		    "The file could not be opened.\n\n"
			+fileName);
	return false;
    }
    TQTextStream t = new TQTextStream(f);
    if ( code >= Codec )
	t.setCodec( (TQTextCodec) codecList.get(code-Codec) );
    else if ( code == Uni )
	t.setEncoding( TQTextStream.Unicode );
    else if ( code == MBug )
	t.setEncoding( TQTextStream.UnicodeReverse );
    else if ( code == Lat1 )
	t.setEncoding( TQTextStream.Latin1 );
	t.writeRawBytes(e.text(), e.text().length());
    f.close();
    setCaption( fileName );
    changed = false;
    return true;
}

void print()
{
    if ( printer.setup(this) ) {		// opens printer dialog
	printer.setFullPage(true);		// we'll set our own margins
	TQPainter p = new TQPainter();
	p.begin( printer );			// paint on printer
	p.setFont( e.font() );
	TQFontMetrics fm = p.fontMetrics();
	TQPaintDeviceMetrics metrics = new TQPaintDeviceMetrics( printer ); // need width/height
						 // of printer surface
	int MARGIN = metrics.logicalDpiX() / 2; // half-inch margin
	int yPos        = MARGIN;		// y position for each line

	for( int i = 0 ; i < e.numLines() ; i++ ) {
	    if ( printer.aborted() )
		break;
	    if ( yPos + fm.lineSpacing() > metrics.height() - MARGIN ) {
		// no more room on this page
		if ( !printer.newPage() )          // start new page
		    break;                           // some error
		yPos = MARGIN;			 // back to top of page
	    }
	    p.drawText( MARGIN, yPos, metrics.width() - 2*MARGIN,
			fm.lineSpacing(), ExpandTabs, e.textLine( i ) );
	    yPos += fm.lineSpacing();
	}
	p.end();				// send job to printer
    }
}

protected void resizeEvent( TQResizeEvent event )
{
    if ( e != null && m != null )
	e.setGeometry( 0, m.height(), width(), height() - m.height() );
}

protected void closeEvent( TQCloseEvent event )
{
    event.accept();

    if ( changed ) { // the text has been changed
	switch ( TQMessageBox.warning( this, "Qwerty",
					"Save changes to Document?",
					tr("&Yes"),
					tr("&No"),
					tr("Cancel"),
					0, 2) ) {
	case 0: // yes
	    if ( save() )
		event.accept();
	    else
		event.ignore();
	    break;
	case 1: // no
	    event.accept();
	    break;
	default: // cancel
	    event.ignore();
	    break;
	}
    }
}

void toUpper()
{
    e.setText(e.text().toUpperCase());
}

void toLower()
{
    e.setText(e.text().toLowerCase());
}

void textChanged()
{
    changed = true;
}
}
