#!/usr/local/bin/moat

#######################################################
#
# A simple text editor
#
# This is based on the xmeditor that is an example
# program in each Motif release, and is briefly
# described in the Motif Programmers Manual
#
######################################################

global fileSaved
set fileSaved 1

global currentFile
set currentFile ""

########################################################
#
# file menu callbacks
#

# openFileCB

proc openFileCB {} {
    global fileSaved 
    global currentFile

    if {! $fileSaved } {
	if {[saveFileDialog]} {
	    saveFile
	}
    }

    xmFileSelectionDialog .fsd managed
    .fsd.Help unmanageChild
    .fsd okCallback {loadFile %w %value}
    .fsd cancelCallback {[.fsd parent] destroyWidget}
}

# newFileCB

proc newFileCB {} {
    global fileSaved 
    global currentFile

    if {! $fileSaved } {
	if {[saveFileDialog]} {
	    saveFile
	}
    }

    xmPromptDialog .pd managed \
	-selectionLabelString "Enter filename:"
    .pd.Help unmanageChild
    .pd okCallback {newFile %w %value}
    .pd cancelCallback {[.pd parent] destroyWidget}
}

#############################################################
#
# callback to handle "save as..." selection
#
proc saveFileAsCB {} {
    xmFileSelectionDialog .fsd managed
    .fsd.Help unmanageChild
    .fsd okCallback {
	set currentFile %value
	saveFile
	%w destroyWidget
    }
    .fsd cancelCallback {[.fsd parent] destroyWidget}
}

#############################################################
#
# saveFileDialog
#
# modal dialog to check if a file should be saved
# note the globals "answer" and "stillModal". This
# is because the callbacks are executed in global
# context

proc saveFileDialog {} {
    global currentFile
    global answer
    global stillModal

    xmErrorDialog .fileSaveDialog managed \
	-messageString "Save $currentFile?" \
	-dialogStyle dialog_full_application_modal
    .fileSaveDialog okCallback {set stillModal 0; set answer 1}
    .fileSaveDialog cancelCallback {set stillModal 0; set answer 0}
    .fileSaveDialog.Help unmanageChild

    # this dialog has to run modal:
    set stillModal 1
    while {$stillModal} {
        . processEvent
    }
    .fileSaveDialog destroyWidget

    return $answer
}


####################################################
#
# save the text contents to the current file
# put up an error dialog if it can't be written
#
proc saveFile {} {
    global currentFile
    global fileSaved

    if {[catch {set fileID [open $currentFile w]}] > 0} {
	errorDialog "Can't open $currentFile for writing"
	return
    }

    set str [.main.text getString]
    puts $fileID $str
    close $fileID

    set fileSaved 1
}

###################################################################
#
# load a file 
# if not valid, put up an error dialog
#
proc loadFile {w file} {
    global currentFile
    global fileSaved

    [$w parent] destroyWidget

    if {[catch {set fileID [open $file r]}] > 0} {
	errorDialog "Can't open $file for reading"
	return
    }
    set currentFile $file

    .main.text setString ""
    while {[gets $fileID str] >= 0} {
	.main.text insert [.main.text getLastPosition]] "$str\n"
    }
    close $fileID
    set fileSaved 1
}

###############################################################
#
# set new file and clear text contents
#
proc newFile {w file} {
    global currentFile

    [$w parent] destroyWidget
    set currentFile $file
    .main.text setString ""
}

#######################################################
# 
# leave the X world
#
proc quitFileCB {} {
    global fileSaved 
    global currentFile

    if {! $fileSaved } {
	if {[saveFileDialog]} {
	    saveFile
	}
    }
    exit 0
}

##########################################################
#
# show an error dialog for the message
#
proc errorDialog {errMsg} {
    xmErrorDialog .err managed \
	-messageString $errMsg
    .err okCallback {[.err parent] destroyWidget}
    .err.Cancel unmanageChild
    .err.Help unmanageChild
}

#########################################################
#
# help callbacks
#
#########################################################

#########################################################
#
# helpAboutCB
#

proc helpAboutCB {} {
    xmInformationDialog .helpAboutDialog managed \
	-messageAlignment alignment_center \
	-messageString "About xmeditor\n\
Jan Newmarch\n\
Version 1.0\n\
January, 1993"
    .helpAboutDialog okCallback {[%w parent] destroyWidget}
    .helpAboutDialog.Cancel unmanageChild
    .helpAboutDialog.Help unmanageChild
}

#########################################################
#
# X world starts here
#
#########################################################
xtAppInitialize \
	-fallbackResources {
		{*XmText.columns: 80}
		{*XmText.rows: 24}
	}

##########################################################
#
# main window to hold every thing
#
xmMainWindow .main managed

#########################################################
#
# menu system along top
#

# menu bar
xmMenuBar .main.menuBar managed

# file pulldown
xmPulldownMenu .main.filePane
xmCascadeButton .main.menuBar.File managed \
	-subMenuId .main.filePane

xmPushButton .main.filePane.New managed
.main.filePane.New activateCallback newFileCB

xmPushButton .main.filePane.Open managed
.main.filePane.Open activateCallback openFileCB

xmPushButton .main.filePane.Save managed
.main.filePane.Save activateCallback "saveFile"

xmPushButton .main.filePane.SaveAs managed
.main.filePane.SaveAs activateCallback "saveFileAsCB"

xmPushButton .main.filePane.Quit managed
.main.filePane.Quit activateCallback quitFileCB

# edit pulldown
xmPulldownMenu .main.editPane
xmCascadeButton .main.menuBar.Edit managed \
	-subMenuId .main.editPane

xmPushButton .main.editPane.Cut managed
.main.editPane.Cut activateCallback {.main.text cut}

xmPushButton .main.editPane.Copy managed
.main.editPane.Copy activateCallback {.main.text copy}

xmPushButton .main.editPane.Paste managed
.main.editPane.Paste activateCallback {.main.text paste}

xmPushButton .main.editPane.Clear managed
.main.editPane.Clear activateCallback {
	    .main.text getSelectionPosition left right
	    .main.text replace $left $right ""
    	}

#
# help
#
xmPulldownMenu .main.helpPane
xmCascadeButton .main.menuBar.Help managed \
	-subMenuId .main.helpPane
.main.menuBar setValues \
	-menuHelpWidget .main.menuBar.Help

xmPushButton .main.helpPane.about managed \
	-labelString "About..."
.main.helpPane.about activateCallback helpAboutCB

##########################################################
#
# edit window
#
xmScrolledText .main.text managed \
	-editMode Multi_line_edit
.main.text modifyVerifyCallback {set fileSaved 0}


.main setValues -menuBar .main.menuBar \
		-workWindow [.main.text parent]

. realizeWidget
. mainLoop

