#!/usr/bin/env ruby
require 'fox16'
require 'fox16/responder'
require 'fox16/undolist'
require_relative 'prefdialog'
require_relative 'helpwindow'
require_relative 'commands'
include Fox
class TextWindow < FXMainWindow
include Responder
MAXUNDOSIZE, KEEPUNDOSIZE = 1000000, 500000
# Define message identifiers recognized by this class
ID_ABOUT,
ID_FILEFILTER,
ID_OPEN,
ID_OPEN_SELECTED,
ID_REOPEN,
ID_SAVE,
ID_SAVEAS,
ID_NEW,
ID_TITLE,
ID_FONT,
ID_QUIT,
ID_PRINT,
ID_TREELIST,
ID_TEXT_BACK,
ID_TEXT_FORE,
ID_TEXT_SELBACK,
ID_TEXT_SELFORE,
ID_TEXT_CURSOR,
ID_DIR_BACK,
ID_DIR_FORE,
ID_DIR_SELBACK,
ID_DIR_SELFORE,
ID_DIR_LINES,
ID_RECENTFILE,
ID_TOGGLE_WRAP,
ID_FIXED_WRAP,
ID_SAVE_SETTINGS,
ID_TEXT,
ID_STRIP_CR,
ID_STRIP_SP,
ID_INCLUDE_PATH,
ID_SHOW_HELP,
ID_OVERSTRIKE,
ID_READONLY,
ID_FILETIME,
ID_PREFERENCES,
ID_TABCOLUMNS,
ID_WRAPCOLUMNS,
ID_DELIMITERS,
ID_INSERTTABS,
ID_AUTOINDENT,
ID_BRACEMATCH,
ID_NUMCHARS,
ID_INSERT_FILE,
ID_EXTRACT_FILE,
ID_WHEELADJUST,
ID_LAST = enum(FXMainWindow::ID_LAST, 47)
# Load the named icon from a file
def loadIcon(filename)
begin
filename = File.join("..", "icons", filename)
icon = nil
File.open(filename, "rb") { |f|
icon = FXPNGIcon.new(getApp(), f.read)
}
icon
rescue
raise RuntimeError, "Couldn't load icon: #{filename}"
end
end
def initialize(app)
# Call base class initialize first
super(app, "FOX Text Editor: - untitled", nil, nil, DECOR_ALL,
0, 0, 850, 600, 0, 0)
# Set up the message map for this class
FXMAPFUNC(SEL_TIMEOUT, ID_FILETIME, :onCheckFile)
FXMAPFUNC(SEL_COMMAND, ID_ABOUT, :onCmdAbout)
FXMAPFUNC(SEL_COMMAND, ID_REOPEN, :onCmdReopen)
FXMAPFUNC(SEL_UPDATE, ID_REOPEN, :onUpdReopen)
FXMAPFUNC(SEL_COMMAND, ID_OPEN, :onCmdOpen)
FXMAPFUNC(SEL_COMMAND, ID_OPEN_SELECTED, :onCmdOpenSelected)
FXMAPFUNC(SEL_COMMAND, ID_SAVE, :onCmdSave)
FXMAPFUNC(SEL_UPDATE, ID_SAVE, :onUpdSave)
FXMAPFUNC(SEL_COMMAND, ID_SAVEAS, :onCmdSaveAs)
FXMAPFUNC(SEL_COMMAND, ID_NEW, :onCmdNew)
FXMAPFUNC(SEL_UPDATE, ID_TITLE, :onUpdTitle)
FXMAPFUNC(SEL_COMMAND, ID_FONT, :onCmdFont)
FXMAPFUNC(SEL_COMMAND, ID_QUIT, :onCmdQuit)
FXMAPFUNC(SEL_SIGNAL, ID_QUIT, :onCmdQuit)
FXMAPFUNC(SEL_CLOSE, ID_TITLE, :onCmdQuit)
FXMAPFUNC(SEL_COMMAND, ID_PRINT, :onCmdPrint)
FXMAPFUNC(SEL_COMMAND, ID_TREELIST, :onCmdTreeList)
FXMAPFUNC(SEL_COMMAND, ID_TEXT_BACK, :onCmdTextBackColor)
FXMAPFUNC(SEL_CHANGED, ID_TEXT_BACK, :onCmdTextBackColor)
FXMAPFUNC(SEL_UPDATE, ID_TEXT_BACK, :onUpdTextBackColor)
FXMAPFUNC(SEL_COMMAND, ID_TEXT_SELBACK, :onCmdTextSelBackColor)
FXMAPFUNC(SEL_CHANGED, ID_TEXT_SELBACK, :onCmdTextSelBackColor)
FXMAPFUNC(SEL_UPDATE, ID_TEXT_SELBACK, :onUpdTextSelBackColor)
FXMAPFUNC(SEL_COMMAND, ID_TEXT_FORE, :onCmdTextForeColor)
FXMAPFUNC(SEL_CHANGED, ID_TEXT_FORE, :onCmdTextForeColor)
FXMAPFUNC(SEL_UPDATE, ID_TEXT_FORE, :onUpdTextForeColor)
FXMAPFUNC(SEL_COMMAND, ID_TEXT_SELFORE, :onCmdTextSelForeColor)
FXMAPFUNC(SEL_CHANGED, ID_TEXT_SELFORE, :onCmdTextSelForeColor)
FXMAPFUNC(SEL_UPDATE, ID_TEXT_SELFORE, :onUpdTextSelForeColor)
FXMAPFUNC(SEL_COMMAND, ID_TEXT_CURSOR, :onCmdTextCursorColor)
FXMAPFUNC(SEL_CHANGED, ID_TEXT_CURSOR, :onCmdTextCursorColor)
FXMAPFUNC(SEL_UPDATE, ID_TEXT_CURSOR, :onUpdTextCursorColor)
FXMAPFUNC(SEL_COMMAND, ID_DIR_BACK, :onCmdDirBackColor)
FXMAPFUNC(SEL_CHANGED, ID_DIR_BACK, :onCmdDirBackColor)
FXMAPFUNC(SEL_UPDATE, ID_DIR_BACK, :onUpdDirBackColor)
FXMAPFUNC(SEL_COMMAND, ID_DIR_FORE, :onCmdDirForeColor)
FXMAPFUNC(SEL_CHANGED, ID_DIR_FORE, :onCmdDirForeColor)
FXMAPFUNC(SEL_UPDATE, ID_DIR_FORE, :onUpdDirForeColor)
FXMAPFUNC(SEL_COMMAND, ID_DIR_SELBACK, :onCmdDirSelBackColor)
FXMAPFUNC(SEL_CHANGED, ID_DIR_SELBACK, :onCmdDirSelBackColor)
FXMAPFUNC(SEL_UPDATE, ID_DIR_SELBACK, :onUpdDirSelBackColor)
FXMAPFUNC(SEL_COMMAND, ID_DIR_SELFORE, :onCmdDirSelForeColor)
FXMAPFUNC(SEL_CHANGED, ID_DIR_SELFORE, :onCmdDirSelForeColor)
FXMAPFUNC(SEL_UPDATE, ID_DIR_SELFORE, :onUpdDirSelForeColor)
FXMAPFUNC(SEL_COMMAND, ID_DIR_LINES, :onCmdDirLineColor)
FXMAPFUNC(SEL_CHANGED, ID_DIR_LINES, :onCmdDirLineColor)
FXMAPFUNC(SEL_UPDATE, ID_DIR_LINES, :onUpdDirLineColor)
FXMAPFUNC(SEL_COMMAND, ID_RECENTFILE, :onCmdRecentFile)
FXMAPFUNC(SEL_UPDATE, ID_TOGGLE_WRAP, :onUpdWrap)
FXMAPFUNC(SEL_COMMAND, ID_TOGGLE_WRAP, :onCmdWrap)
FXMAPFUNC(SEL_COMMAND, ID_SAVE_SETTINGS, :onCmdSaveSettings)
FXMAPFUNC(SEL_INSERTED, ID_TEXT, :onTextInserted)
FXMAPFUNC(SEL_REPLACED, ID_TEXT, :onTextReplaced)
FXMAPFUNC(SEL_DELETED, ID_TEXT, :onTextDeleted)
FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, ID_TEXT, :onTextRightMouse)
FXMAPFUNC(SEL_UPDATE, ID_FIXED_WRAP, :onUpdWrapFixed)
FXMAPFUNC(SEL_COMMAND, ID_FIXED_WRAP, :onCmdWrapFixed)
FXMAPFUNC(SEL_DND_MOTION, ID_TEXT, :onEditDNDMotion)
FXMAPFUNC(SEL_DND_DROP, ID_TEXT, :onEditDNDDrop)
FXMAPFUNC(SEL_UPDATE, ID_STRIP_CR, :onUpdStripReturns)
FXMAPFUNC(SEL_COMMAND, ID_STRIP_CR, :onCmdStripReturns)
FXMAPFUNC(SEL_UPDATE, ID_STRIP_SP, :onUpdStripSpaces)
FXMAPFUNC(SEL_COMMAND, ID_STRIP_SP, :onCmdStripSpaces)
FXMAPFUNC(SEL_COMMAND, ID_INCLUDE_PATH, :onCmdIncludePaths)
FXMAPFUNC(SEL_COMMAND, ID_SHOW_HELP, :onCmdShowHelp)
FXMAPFUNC(SEL_COMMAND, ID_FILEFILTER, :onCmdFilter)
FXMAPFUNC(SEL_UPDATE, ID_OVERSTRIKE, :onUpdOverstrike)
FXMAPFUNC(SEL_UPDATE, ID_READONLY, :onUpdReadOnly)
FXMAPFUNC(SEL_UPDATE, ID_NUMCHARS, :onUpdNumChars)
FXMAPFUNC(SEL_COMMAND, ID_PREFERENCES, :onCmdPreferences)
FXMAPFUNC(SEL_COMMAND, ID_TABCOLUMNS, :onCmdTabColumns)
FXMAPFUNC(SEL_UPDATE, ID_TABCOLUMNS, :onUpdTabColumns)
FXMAPFUNC(SEL_COMMAND, ID_DELIMITERS, :onCmdDelimiters)
FXMAPFUNC(SEL_UPDATE, ID_DELIMITERS, :onUpdDelimiters)
FXMAPFUNC(SEL_COMMAND, ID_WRAPCOLUMNS, :onCmdWrapColumns)
FXMAPFUNC(SEL_UPDATE, ID_WRAPCOLUMNS, :onUpdWrapColumns)
FXMAPFUNC(SEL_COMMAND, ID_AUTOINDENT, :onCmdAutoIndent)
FXMAPFUNC(SEL_UPDATE, ID_AUTOINDENT, :onUpdAutoIndent)
FXMAPFUNC(SEL_COMMAND, ID_INSERTTABS, :onCmdInsertTabs)
FXMAPFUNC(SEL_UPDATE, ID_INSERTTABS, :onUpdInsertTabs)
FXMAPFUNC(SEL_COMMAND, ID_BRACEMATCH, :onCmdBraceMatch)
FXMAPFUNC(SEL_UPDATE, ID_BRACEMATCH, :onUpdBraceMatch)
FXMAPFUNC(SEL_UPDATE, ID_INSERT_FILE, :onUpdInsertFile)
FXMAPFUNC(SEL_COMMAND, ID_INSERT_FILE, :onCmdInsertFile)
FXMAPFUNC(SEL_UPDATE, ID_EXTRACT_FILE, :onUpdExtractFile)
FXMAPFUNC(SEL_COMMAND, ID_EXTRACT_FILE, :onCmdExtractFile)
FXMAPFUNC(SEL_UPDATE, ID_WHEELADJUST, :onUpdWheelAdjust)
FXMAPFUNC(SEL_COMMAND, ID_WHEELADJUST, :onCmdWheelAdjust)
# Undoable commands
@undolist = FXUndoList.new
# Default font
@font = nil
# Make some icons
@bigicon = loadIcon("big.png")
@smallicon = loadIcon("small.png")
@newicon = loadIcon("filenew.png")
@openicon = loadIcon("fileopen.png")
@saveicon = loadIcon("filesave.png")
@saveasicon = FXPNGIcon.new(getApp(), File.open(File.join("..", "icons", "saveas.png"), "rb").read(),
0, IMAGE_ALPHAGUESS)
@printicon = loadIcon("printicon.png")
@cuticon = loadIcon("cut.png")
@copyicon = loadIcon("copy.png")
@pasteicon = loadIcon("paste.png")
@deleteicon = loadIcon("kill.png")
@undoicon = loadIcon("undo.png")
@redoicon = loadIcon("redo.png")
@fontsicon = loadIcon("fonts.png")
@helpicon = loadIcon("help.png")
# Application icons
setIcon(@bigicon)
setMiniIcon(@smallicon)
# Make main window; set myself as the target
setTarget(self)
setSelector(ID_TITLE)
# Help window
@helpwindow = HelpWindow.new(self)
# Make menu bar
dragshell1 = FXToolBarShell.new(self, FRAME_RAISED|FRAME_THICK)
menubar = FXMenuBar.new(self, dragshell1, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
FXToolBarGrip.new(menubar, menubar, FXMenuBar::ID_TOOLBARGRIP,
TOOLBARGRIP_DOUBLE)
# Tool bar
dragshell2 = FXToolBarShell.new(self, FRAME_RAISED|FRAME_THICK)
toolbar = FXToolBar.new(self, dragshell2,
LAYOUT_SIDE_TOP|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH|PACK_UNIFORM_HEIGHT)
FXToolBarGrip.new(toolbar, toolbar, FXToolBar::ID_TOOLBARGRIP,
TOOLBARGRIP_DOUBLE)
# Status bar
statusbar = FXStatusBar.new(self,
LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
# Info about the editor
FXButton.new(statusbar, "\tThe FOX Text Editor\tAbout the FOX Text Editor.",
@smallicon, self, ID_ABOUT, LAYOUT_FILL_Y|LAYOUT_RIGHT)
# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
# Edit Menu
editmenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&Edit", nil, editmenu)
# Goto Menu
gotomenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&Goto", nil, gotomenu)
# Search Menu
searchmenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&Search", nil, searchmenu)
# Options Menu
optionmenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&Options", nil, optionmenu)
# View menu
viewmenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&View", nil, viewmenu)
# Help menu
helpmenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&Help", nil, helpmenu, LAYOUT_RIGHT)
# Splitter
splitter = FXSplitter.new(self,
LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_TRACKING)
# Sunken border for tree
@treebox = FXVerticalFrame.new(splitter, LAYOUT_FILL_X|LAYOUT_FILL_Y,
0, 0, 0, 0, 0, 0, 0, 0)
# Make tree
treeframe = FXHorizontalFrame.new(@treebox,
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,
0, 0, 0, 0, 0, 0, 0, 0)
@dirlist = FXDirList.new(treeframe, self, ID_TREELIST,
(DIRLIST_SHOWFILES|TREELIST_BROWSESELECT|TREELIST_SHOWS_LINES|
TREELIST_SHOWS_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y))
filterframe = FXHorizontalFrame.new(@treebox, LAYOUT_FILL_X)
FXLabel.new(filterframe, "Filter:")
@filter = FXComboBox.new(filterframe, 25, self, ID_FILEFILTER,
COMBOBOX_STATIC|LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK)
@filter.numVisible = 4
# Sunken border for text widget
textbox = FXHorizontalFrame.new(splitter,
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0)
# Make editor window
@editor = FXText.new(textbox, self, ID_TEXT, LAYOUT_FILL_X|LAYOUT_FILL_Y)
@editor.hiliteMatchTime = 300000
# Show readonly state in status bar
readonly = FXLabel.new(statusbar, nil, nil, FRAME_SUNKEN|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
readonly.padLeft = 2
readonly.padRight = 2
readonly.padTop = 1
readonly.padBottom = 1
readonly.setTarget(self)
readonly.setSelector(ID_READONLY)
# Show insert mode in status bar
overstrike = FXLabel.new(statusbar, nil, nil, FRAME_SUNKEN|LAYOUT_RIGHT|LAYOUT_CENTER_Y)
overstrike.padLeft = 2
overstrike.padRight = 2
overstrike.padTop = 1
overstrike.padBottom = 1
overstrike.setTarget(self)
overstrike.setSelector(ID_OVERSTRIKE)
# Show size of text in status bar
numchars = FXTextField.new(statusbar, 6, self, ID_NUMCHARS,
FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,
0, 0, 0, 0, 2, 2, 1, 1)
numchars.backColor = statusbar.backColor
# Caption before number
FXLabel.new(statusbar, " Size:", nil, LAYOUT_RIGHT|LAYOUT_CENTER_Y)
# Show column number in status bar
columnno = FXTextField.new(statusbar, 4, @editor, FXText::ID_CURSOR_COLUMN,
FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,
0, 0, 0, 0, 2, 2, 1, 1)
columnno.backColor = statusbar.backColor
# Caption before number
FXLabel.new(statusbar, " Col:", nil, LAYOUT_RIGHT|LAYOUT_CENTER_Y)
# Show line number in status bar
rowno = FXTextField.new(statusbar, 4, @editor, FXText::ID_CURSOR_ROW,
FRAME_SUNKEN|JUSTIFY_RIGHT|LAYOUT_RIGHT|LAYOUT_CENTER_Y,
0, 0, 0, 0, 2, 2, 1, 1)
rowno.backColor = statusbar.backColor
# Caption before number
FXLabel.new(statusbar, " Line:", nil, LAYOUT_RIGHT|LAYOUT_CENTER_Y)
# Toobar buttons: File manipulation
FXButton.new(toolbar, "New\tNew\tCreate new document.", @newicon,
self, ID_NEW, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|
LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Open\tOpen\tOpen document file.", @openicon,
self, ID_OPEN, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|
LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Save\tSave\tSave document.", @saveicon,
self, ID_SAVE, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|
LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Save as\tSave As\tSave document to another file.",
@saveasicon, self, ID_SAVEAS, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
# Toobar buttons: Print
FXFrame.new(toolbar,
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 5, 5)
FXButton.new(toolbar, "Print\tPrint\tPrint document.", @printicon,
self, ID_PRINT, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|
LAYOUT_TOP|LAYOUT_LEFT))
# Toobar buttons: Editing
FXFrame.new(toolbar,
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 5, 5)
FXButton.new(toolbar, "Cut\tCut\tCut selection to clipboard.", @cuticon,
@editor, FXText::ID_CUT_SEL, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Copy\tCopy\tCopy selection to clipboard.", @copyicon,
@editor, FXText::ID_COPY_SEL, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Paste\tPaste\tPaste clipboard.", @pasteicon,
@editor, FXText::ID_PASTE_SEL, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Undo\tUndo\tUndo last change.", @undoicon,
@undolist, FXUndoList::ID_UNDO, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Redo\tRedo\tRedo last undo.", @redoicon,
@undolist, FXUndoList::ID_REDO, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_LEFT))
# Color
FXFrame.new(toolbar,
LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 5, 5)
FXButton.new(toolbar, "Fonts\tFonts\tDisplay font dialog.", @fontsicon,
self, ID_FONT, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|FRAME_RAISED|
LAYOUT_TOP|LAYOUT_LEFT))
FXButton.new(toolbar, "Help\tHelp on editor\tDisplay help information.",
@helpicon, self, ID_SHOW_HELP, (ICON_ABOVE_TEXT|BUTTON_TOOLBAR|
FRAME_RAISED|LAYOUT_TOP|LAYOUT_RIGHT))
# File Menu entries
FXMenuCommand.new(filemenu, "&Open... \tCtl-O\tOpen document file.",
@openicon, self, ID_OPEN)
FXMenuCommand.new(filemenu,
"Open Selected... \tCtl-E\tOpen highlighted document file.", nil,
self, ID_OPEN_SELECTED)
FXMenuCommand.new(filemenu, "&Reopen...\t\tReopen file.", nil,
self, ID_REOPEN)
FXMenuCommand.new(filemenu, "&New...\tCtl-N\tCreate new document.",
@newicon, self, ID_NEW)
FXMenuCommand.new(filemenu, "&Save\tCtl-S\tSave changes to file.",
@saveicon, self, ID_SAVE)
FXMenuCommand.new(filemenu, "Save &As...\t\tSave document to another file.",
@saveasicon, self, ID_SAVEAS)
FXMenuSeparator.new(filemenu)
FXMenuCommand.new(filemenu, "Insert from file...\t\tInsert text from file.",
nil, self, ID_INSERT_FILE)
FXMenuCommand.new(filemenu, "Extract to file...\t\tExtract text to file.",
nil, self, ID_EXTRACT_FILE)
FXMenuCommand.new(filemenu, "&Print...\tCtl-P\tPrint document.", @printicon,
self, ID_PRINT)
FXMenuCommand.new(filemenu, "&Editable\t\tDocument editable.", nil,
@editor, FXText::ID_TOGGLE_EDITABLE)
iconifyCmd = FXMenuCommand.new(filemenu, "&Iconify...\t\tIconify editor.")
iconifyCmd.connect(SEL_COMMAND) { self.minimize }
# Recent file menu; this automatically hides if there are no files
sep1 = FXMenuSeparator.new(filemenu)
sep1.setTarget(@mrufiles)
sep1.setSelector(FXRecentFiles::ID_ANYFILES)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_1)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_2)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_3)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_4)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_5)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_6)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_7)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_8)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_9)
FXMenuCommand.new(filemenu, nil, nil, @mrufiles, FXRecentFiles::ID_FILE_10)
FXMenuCommand.new(filemenu, "&Clear Recent Files", nil,
@mrufiles, FXRecentFiles::ID_CLEAR)
sep2 = FXMenuSeparator.new(filemenu)
sep2.setTarget(@mrufiles)
sep2.setSelector(FXRecentFiles::ID_ANYFILES)
FXMenuCommand.new(filemenu, "&Quit\tCtl-Q", nil, self, ID_QUIT)
# Edit Menu entries
FXMenuCommand.new(editmenu, "&Undo\tCtl-Z\tUndo last change.", @undoicon,
@undolist, FXUndoList::ID_UNDO)
FXMenuCommand.new(editmenu, "&Redo\tCtl-Y\tRedo last undo.", @redoicon,
@undolist, FXUndoList::ID_REDO)
FXMenuCommand.new(editmenu, "&Undo all\t\tUndo all.", nil,
@undolist, FXUndoList::ID_UNDO_ALL)
FXMenuCommand.new(editmenu, "&Redo all\t\tRedo all.", nil,
@undolist, FXUndoList::ID_REDO_ALL)
FXMenuCommand.new(editmenu, "&Revert to saved\t\tRevert to saved.", nil,
@undolist, FXUndoList::ID_REVERT)
FXMenuSeparator.new(editmenu)
FXMenuCommand.new(editmenu, "&Copy\tCtl-C\tCopy selection to clipboard.",
@copyicon, @editor, FXText::ID_COPY_SEL)
FXMenuCommand.new(editmenu, "Cu&t\tCtl-X\tCut selection to clipboard.",
@cuticon, @editor, FXText::ID_CUT_SEL)
FXMenuCommand.new(editmenu, "&Paste\tCtl-V\tPaste from clipboard.",
@pasteicon, @editor, FXText::ID_PASTE_SEL)
FXMenuCommand.new(editmenu, "&Delete\t\tDelete selection.", @deleteicon,
@editor, FXText::ID_DELETE_SEL)
FXMenuSeparator.new(editmenu)
FXMenuCommand.new(editmenu, "Lo&wer-case\tCtl-6\tChange to lower case.",
nil, @editor, FXText::ID_LOWER_CASE)
FXMenuCommand.new(editmenu,
"Upp&er-case\tShift-Ctl-^\tChange to upper case.", nil,
@editor, FXText::ID_UPPER_CASE)
FXMenuCommand.new(editmenu,
"Clean indent\t\tClean indentation to either all tabs or all spaces.",
nil, @editor, FXText::ID_CLEAN_INDENT)
FXMenuCommand.new(editmenu, "Shift left\tCtl-9\tShift text left.", nil,
@editor, FXText::ID_SHIFT_LEFT)
FXMenuCommand.new(editmenu, "Shift right\tCtl-0\tShift text right.", nil,
@editor, FXText::ID_SHIFT_RIGHT)
FXMenuCommand.new(editmenu,
"Shift tab left\t\tShift text left one tab position.", nil,
@editor, FXText::ID_SHIFT_TABLEFT)
FXMenuCommand.new(editmenu,
"Shift tab right\t\tShift text right one tab position.", nil,
@editor, FXText::ID_SHIFT_TABRIGHT)
# Goto Menu entries
FXMenuCommand.new(gotomenu,
"&Goto...\tCtl-G\tGoto line number.", nil,
@editor, FXText::ID_GOTO_LINE)
FXMenuCommand.new(gotomenu,
"Goto selected...\tCtl-L\tGoto selected line number.", nil,
@editor, FXText::ID_GOTO_SELECTED)
FXMenuSeparator.new(gotomenu)
FXMenuCommand.new(gotomenu,
"Goto {..\tShift-Ctl-{\tGoto start of enclosing block.", nil,
@editor, FXText::ID_LEFT_BRACE)
FXMenuCommand.new(gotomenu,
"Goto ..}\tShift-Ctl-}\tGoto end of enclosing block.", nil,
@editor, FXText::ID_RIGHT_BRACE)
FXMenuCommand.new(gotomenu,
"Goto (..\tShift-Ctl-(\tGoto start of enclosing expression.", nil,
@editor, FXText::ID_LEFT_PAREN)
FXMenuCommand.new(gotomenu,
"Goto ..)\tShift-Ctl-)\tGoto end of enclosing expression.", nil,
@editor, FXText::ID_RIGHT_PAREN)
FXMenuSeparator.new(gotomenu)
FXMenuCommand.new(searchmenu,
"Goto matching (..)\tCtl-M\tGoto matching brace or parenthesis.", nil,
@editor, FXText::ID_GOTO_MATCHING)
# Search Menu entries
FXMenuCommand.new(searchmenu,
"Select matching (..)\tShift-Ctl-M\tSelect matching brace or parenthesis.", nil,
@editor, FXText::ID_SELECT_MATCHING)
FXMenuCommand.new(searchmenu,
"Select block {..}\tShift-Alt-{\tSelect enclosing block.", nil,
@editor, FXText::ID_SELECT_BRACE)
FXMenuCommand.new(searchmenu,
"Select block {..}\tShift-Alt-}\tSelect enclosing block.", nil,
@editor, FXText::ID_SELECT_BRACE)
FXMenuCommand.new(searchmenu,
"Select expression (..)\tShift-Alt-(\tSelect enclosing parentheses.", nil,
@editor, FXText::ID_SELECT_PAREN)
FXMenuCommand.new(searchmenu,
"Select expression (..)\tShift-Alt-)\tSelect enclosing parentheses.", nil,
@editor, FXText::ID_SELECT_PAREN)
FXMenuSeparator.new(searchmenu)
FXMenuCommand.new(searchmenu,
"&Search sel. fwd\tCtl-H\tSearch for selection.", nil,
@editor, FXText::ID_SEARCH_FORW_SEL)
FXMenuCommand.new(searchmenu,
"&Search sel. bck\tShift-Ctl-H\tSearch for selection.", nil,
@editor, FXText::ID_SEARCH_BACK_SEL)
FXMenuCommand.new(searchmenu,
"&Search...\tCtl-F\tSearch for a string.", nil,
@editor, FXText::ID_SEARCH)
FXMenuCommand.new(searchmenu,
"R&eplace...\tCtl-R\tSearch for a string.", nil,
@editor, FXText::ID_REPLACE)
# Options menu
FXMenuCommand.new(optionmenu,
"Preferences...\t\tChange preferences.", nil,
self, TextWindow::ID_PREFERENCES)
FXMenuCommand.new(optionmenu,
"Font...\t\tChange text font.", @fontsicon, self, ID_FONT)
FXMenuCommand.new(optionmenu,
"Overstrike\t\tToggle overstrike mode.", nil,
@editor, FXText::ID_TOGGLE_OVERSTRIKE)
FXMenuCommand.new(optionmenu,
"Include path...\t\tDirectories to search for include files.", nil,
self, TextWindow::ID_INCLUDE_PATH)
FXMenuCommand.new(optionmenu,
"Save Settings...\t\tSave settings now.", nil,
self, TextWindow::ID_SAVE_SETTINGS)
# View Menu entries
FXMenuCommand.new(viewmenu,
"Hidden files\t\tShow hidden files and directories.", nil,
@dirlist, FXDirList::ID_TOGGLE_HIDDEN)
FXMenuCommand.new(viewmenu,
"File Browser\t\tDisplay file list.", nil,
@treebox,FXWindow::ID_TOGGLESHOWN)
FXMenuCommand.new(viewmenu, "Toolbar\t\tDisplay toolbar.", nil,
toolbar, FXWindow::ID_TOGGLESHOWN)
FXMenuCommand.new(viewmenu, "Status line\t\tDisplay status line.", nil,
statusbar, FXWindow::ID_TOGGLESHOWN)
# Help Menu entries
FXMenuCommand.new(helpmenu, "&Help...\t\tDisplay help information.",
@helpicon, self, ID_SHOW_HELP, 0)
FXMenuSeparator.new(helpmenu)
FXMenuCommand.new(helpmenu, "&About TextEdit...\t\tDisplay about panel.",
@smallicon, self, ID_ABOUT, 0)
# Make a tool tip
FXToolTip.new(getApp(), 0)
# Recent files
@mrufiles = FXRecentFiles.new
@mrufiles.setTarget(self)
@mrufiles.setSelector(ID_RECENTFILE)
# Add some alternative accelerators
if getAccelTable()
getAccelTable().addAccel(MKUINT(KEY_Z, CONTROLMASK|SHIFTMASK),
@undolist,
MKUINT(FXUndoList::ID_REDO, SEL_COMMAND))
end
# Initialize file name
@filename = "untitled"
@filetime = nil
@filenameset = false
# Initialize other stuff
@searchpath = "/usr/include"
setPatterns(["All Files (*)"])
setCurrentPattern(0)
@timer = nil
@stripcr = true
@stripsp = false
@undolist.mark
end
# Load file
def loadFile(file)
begin
getApp().beginWaitCursor()
text = File.open(file, "r").read
text.gsub!('\r', '') if @stripcr
@editor.text = text
ensure
getApp().endWaitCursor()
end
# Set stuff
@editor.modified = false
@editor.editable = File.stat(file).writable?
@dirlist.currentFile = file
@mrufiles.appendFile(file)
@filetime = File.mtime(file)
@filename = file
@filenameset = true
@undolist.clear
@undolist.mark
end
# Insert file
def insertFile(file)
begin
getApp().beginWaitCursor()
text = File.open(file, "r").read
text.gsub!('\r', '') if @stripcr
@editor.insertText(@editor.cursorPos, text, n, true)
@editor.modified = true
ensure
getApp().endWaitCursor()
end
end
# Save file
def saveFile(file)
# Set wait cursor
getApp().beginWaitCursor()
# Get text from editor
text = @editor.text
# Strip trailing spaces
if @stripsp
lines = text.split('\n')
lines.each { |line|
line.sub!(/ *$/, "")
}
text = lines.join('\n')
end
# Write the file
File.open(file, "w").write(text)
# Kill wait cursor
getApp().endWaitCursor()
# Set stuff
@editor.modified = false
@editor.editable = true
@dirlist.currentFile = file
@mrufiles.appendFile(file)
@filetime = File.mtime(file)
@filename = file
@filenameset = true
@undolist.mark
end
# Extract file
def extractFile(file)
# Set wait cursor
getApp().beginWaitCursor()
# Get text from editor
size = @editor.selEndPos - @editor.selStartPos
text = @editor.extractText(@editor.selStartPos, size)
# Strip trailing spaces
if @stripsp
lines = text.split('\n')
lines.each { |line|
line.sub!(/ *$/, "")
}
text = lines.join('\n')
end
# Write the file
File.open(file, "w").write(text)
# Kill wait cursor
getApp().endWaitCursor()
end
# Read settings from registry
def readRegistry
# Text colors
textback = getApp().reg().readColorEntry("SETTINGS", "textbackground", @editor.backColor)
textfore = getApp().reg().readColorEntry("SETTINGS", "textforeground", @editor.textColor)
textselback = getApp().reg().readColorEntry("SETTINGS", "textselbackground", @editor.selBackColor)
textselfore = getApp().reg().readColorEntry("SETTINGS", "textselforeground", @editor.selTextColor)
textcursor = getApp().reg().readColorEntry("SETTINGS", "textcursor", @editor.cursorColor)
# Directory colors
dirback = getApp().reg().readColorEntry("SETTINGS", "browserbackground", @dirlist.backColor)
dirfore = getApp().reg().readColorEntry("SETTINGS", "browserforeground", @dirlist.textColor)
dirselback = getApp().reg().readColorEntry("SETTINGS", "browserselbackground", @dirlist.selBackColor)
dirselfore = getApp().reg().readColorEntry("SETTINGS", "browserselforeground", @dirlist.selTextColor)
dirlines = getApp().reg().readColorEntry("SETTINGS", "browserlines", @dirlist.lineColor)
# Delimiters
delimiters = getApp().reg().readStringEntry("SETTINGS", "delimiters", '~.,/\\`\'!@#$%^&*()-=+{}|[]":;<>?')
# Font
fontspec = getApp().reg().readStringEntry("SETTINGS", "font", "")
if fontspec != ""
font = FXFont.new(getApp(), fontspec)
@editor.font = font
end
# Get size
xx = getApp().reg().readIntEntry("SETTINGS", "x", 5)
yy = getApp().reg().readIntEntry("SETTINGS", "y", 5)
ww = getApp().reg().readIntEntry("SETTINGS", "width", 600)
hh = getApp().reg().readIntEntry("SETTINGS", "height", 400)
# Hidden files shown
hiddenfiles = getApp().reg().readIntEntry("SETTINGS", "showhiddenfiles", 0)
@dirlist.hiddenFilesShown = (hiddenfiles != 0) ? true : false
# Showing the tree?
hidetree = getApp().reg().readIntEntry("SETTINGS", "hidetree", 1)
# Width of tree
treewidth = getApp().reg().readIntEntry("SETTINGS", "treewidth", 100)
# Word wrapping
wrapping = getApp().reg().readIntEntry("SETTINGS", "wordwrap", 0)
wrapcols = getApp().reg().readIntEntry("SETTINGS", "wrapcols", 80)
fixedwrap = getApp().reg().readIntEntry("SETTINGS", "fixedwrap", 1)
# Tab settings, autoindent
autoindent = getApp().reg().readIntEntry("SETTINGS", "autoindent", 0)
hardtabs = getApp().reg().readIntEntry("SETTINGS", "hardtabs", 1)
tabcols = getApp().reg().readIntEntry("SETTINGS", "tabcols", 8)
# Strip returns
@stripcr = getApp().reg().readIntEntry("SETTINGS", "stripreturn", 0)
@stripcr = (@stripcr != 0) ? true : false
@stripsp = getApp().reg().readIntEntry("SETTINGS", "stripspaces", 0)
@stripsp = (@stripsp != 0) ? true : false
# File patterns
patterns = getApp().reg().readStringEntry("SETTINGS", "filepatterns", "All Files (*)")
setPatterns(patterns.split("\n"))
setCurrentPattern(getApp().reg().readIntEntry("SETTINGS", "filepatternno", 0))
# Search path
searchpath = getApp().reg().readStringEntry("SETTINGS", "searchpath", "/usr/include")
# Change the colors
@editor.textColor = textfore
@editor.backColor = textback
@editor.selBackColor = textselback
@editor.selTextColor = textselfore
@editor.cursorColor = textcursor
@dirlist.textColor = dirfore
@dirlist.backColor = dirback
@dirlist.selBackColor = dirselback
@dirlist.selTextColor = dirselfore
@dirlist.lineColor = dirlines
# Change delimiters
@editor.delimiters = delimiters
# Hide tree if asked for
@treebox.hide if hidetree
# Set tree width
@treebox.width = treewidth
# Open toward file
@dirlist.currentFile = @filename
# Wrap mode
if wrapping
@editor.textStyle |= TEXT_WORDWRAP
else
@editor.textStyle &= ~TEXT_WORDWRAP
end
# Wrap fixed mode
if fixedwrap
@editor.textStyle |= TEXT_FIXEDWRAP
else
@editor.textStyle &= ~TEXT_FIXEDWRAP
end
# Autoindent
if autoindent
@editor.textStyle |= TEXT_AUTOINDENT
else
@editor.textStyle &= ~TEXT_AUTOINDENT
end
# Hard tabs
if hardtabs
@editor.textStyle &= ~TEXT_NO_TABS
else
@editor.textStyle |= TEXT_NO_TABS
end
# Wrap and tab columns
@editor.wrapColumns = wrapcols
@editor.tabColumns = tabcols
# Reposition window
position(xx, yy, ww, hh)
end
# Save settings to registry
def writeRegistry
# Colors of text
getApp().reg().writeColorEntry("SETTINGS", "textbackground", @editor.backColor)
getApp().reg().writeColorEntry("SETTINGS", "textforeground", @editor.textColor)
getApp().reg().writeColorEntry("SETTINGS", "textselbackground", @editor.selBackColor)
getApp().reg().writeColorEntry("SETTINGS", "textselforeground", @editor.selTextColor)
getApp().reg().writeColorEntry("SETTINGS", "textcursor", @editor.cursorColor)
# Colors of directory
getApp().reg().writeColorEntry("SETTINGS", "browserbackground", @dirlist.backColor)
getApp().reg().writeColorEntry("SETTINGS", "browserforeground", @dirlist.textColor)
getApp().reg().writeColorEntry("SETTINGS", "browserselbackground", @dirlist.selBackColor)
getApp().reg().writeColorEntry("SETTINGS", "browserselforeground", @dirlist.selTextColor)
getApp().reg().writeColorEntry("SETTINGS", "browserlines", @dirlist.lineColor)
# Delimiters
getApp().reg().writeStringEntry("SETTINGS", "delimiters", @editor.delimiters)
# Write new window size back to registry
getApp().reg().writeIntEntry("SETTINGS", "x", getX())
getApp().reg().writeIntEntry("SETTINGS", "y", getY())
getApp().reg().writeIntEntry("SETTINGS", "width", getWidth())
getApp().reg().writeIntEntry("SETTINGS", "height", getHeight())
# Were showing hidden files
getApp().reg().writeIntEntry("SETTINGS", "showhiddenfiles", @dirlist.hiddenFilesShown? ? 1 : 0)
# Was tree shown?
getApp().reg().writeIntEntry("SETTINGS", "hidetree", @treebox.shown() ? 0 : 1)
# Width of tree
getApp().reg().writeIntEntry("SETTINGS", "treewidth", @treebox.getWidth())
# Wrap mode
getApp().reg().writeIntEntry("SETTINGS", "wordwrap", (@editor.textStyle & TEXT_WORDWRAP) != 0 ? 1 : 0)
getApp().reg().writeIntEntry("SETTINGS", "fixedwrap", (@editor.textStyle & TEXT_FIXEDWRAP) != 0 ? 1 : 0)
getApp().reg().writeIntEntry("SETTINGS", "wrapcols", @editor.getWrapColumns())
# Tab settings, autoindent
getApp().reg().writeIntEntry("SETTINGS", "autoindent", (@editor.textStyle & TEXT_AUTOINDENT) != 0 ? 1 : 0)
getApp().reg().writeIntEntry("SETTINGS", "hardtabs", (@editor.textStyle & TEXT_NO_TABS) == 0 ? 1 : 0)
getApp().reg().writeIntEntry("SETTINGS", "tabcols", @editor.getTabColumns())
# Strip returns
getApp().reg().writeIntEntry("SETTINGS", "stripreturn", @stripcr ? 1 : 0)
getApp().reg().writeIntEntry("SETTINGS", "stripspaces", @stripsp ? 1 : 0)
# File patterns
getApp().reg().writeIntEntry("SETTINGS", "filepatternno", getCurrentPattern())
patterns = getPatterns().join("\n")
getApp().reg().writeStringEntry("SETTINGS", "filepatterns", patterns)
# Search path
getApp().reg().writeStringEntry("SETTINGS", "searchpath", @searchpath)
# Font
getApp().reg().writeStringEntry("SETTINGS", "font", @editor.font.font)
end
# About box
def onCmdAbout(sender, sel, ptr)
about = FXMessageBox.new(self, "FOX Text Editor",
"The FOX Text Editor\n\nUsing FOX Library Version #{fxversion[0]}.#{fxversion[1]}.#{fxversion[2]}\n\nCopyright (C) 2000,2001 Jeroen van der Zijp ([email protected])", @bigicon, MBOX_OK|DECOR_TITLE|DECOR_BORDER)
about.execute
return 1
end
# Change font
def onCmdFont(sender, sel, ptr)
fontdlg = FXFontDialog.new(self, "Change Font", DECOR_BORDER|DECOR_TITLE)
fontdesc = @editor.font.fontDesc
fontdlg.fontSelection = fontdesc
if fontdlg.execute() != 0
fontdesc = fontdlg.fontSelection
font = FXFont.new(getApp(), fontdesc)
font.create
@editor.font = font
@editor.update
end
return 1
end
# Save settings
def onCmdSaveSettings(sender, sel, ptr)
writeRegistry();
getApp().reg().write
return 1
end
# Toggle wrap mode
def onCmdWrap(sender, sel, ptr)
@editor.textStyle ^= TEXT_WORDWRAP
return 1
end
# Update toggle wrap mode
def onUpdWrap(sender, sel, ptr)
if (@editor.textStyle & TEXT_WORDWRAP) != 0
sender.handle(self, MKUINT(ID_CHECK, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_UNCHECK, SEL_COMMAND), nil)
end
return 1
end
# Toggle fixed wrap mode
def onCmdWrapFixed(sender, sel, ptr)
@editor.textStyle ^= TEXT_FIXEDWRAP
return 1
end
# Update toggle fixed wrap mode
def onUpdWrapFixed(sender, sel, ptr)
if (@editor.textStyle & TEXT_FIXEDWRAP) != 0
sender.handle(self, MKUINT(ID_CHECK, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_UNCHECK, SEL_COMMAND), nil)
end
return 1
end
# Toggle strip returns mode
def onCmdStripReturns(sender, sel, ptr)
@stripcr = !@stripcr
return 1
end
# Update toggle strip returns mode
def onUpdStripReturns(sender, sel, ptr)
if @stripcr
sender.handle(self, MKUINT(ID_CHECK, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_UNCHECK, SEL_COMMAND), nil)
end
return 1
end
# Toggle strip spaces mode
def onCmdStripSpaces(sender, sel, ptr)
@stripsp = !@stripsp
return 1
end
# Update toggle strip spaces mode
def onUpdStripSpaces(sender, sel, ptr)
if @stripsp
sender.handle(self, MKUINT(ID_CHECK, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_UNCHECK, SEL_COMMAND), nil)
end
return 1
end
# Reopen file
def onCmdReopen(sender, sel, ptr)
if !@undolist.marked?
if FXMessageBox.question(self, MBOX_YES_NO, "Document was changed",
"Discard changes to this document?") == MBOX_CLICKED_NO
return 1
end
end
loadFile(@filename)
return 1
end
# Update reopen file
def onUpdReopen(sender, sel, ptr)
if @filenameset
sender.handle(self, MKUINT(ID_ENABLE, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_DISABLE, SEL_COMMAND), nil)
end
return 1
end
# Save changes, prompt for new filename
def saveChanges
if !@undolist.marked?
answer = FXMessageBox.question(self, MBOX_YES_NO_CANCEL,
"Unsaved Document", "Save current document to file?")
return false if (answer == MBOX_CLICKED_CANCEL)
if answer == MBOX_CLICKED_YES
file = @filename
if !@filenameset
savedialog = FXFileDialog.new(self, "Save Document")
savedialog.selectMode = SELECTFILE_ANY
savedialog.patternList = getPatterns()
savedialog.currentPattern = getCurrentPattern()
savedialog.filename = file
return false if (savedialog.execute == 0)
setCurrentPattern(savedialog.currentPattern)
file = savedialog.filename
if File.exist?(file)
if MBOX_CLICKED_NO == FXMessageBox.question(self, MBOX_YES_NO,
"Overwrite Document", "Overwrite existing document: #{file}?")
return false
end
end
end
file = savedialog.filename
saveFile(file)
end
end
true
end
# Open
def onCmdOpen(sender, sel, ptr)
return 1 if !saveChanges()
opendialog = FXFileDialog.new(self, "Open Document")
opendialog.selectMode = SELECTFILE_EXISTING
opendialog.patternList = getPatterns()
opendialog.currentPattern = getCurrentPattern()
opendialog.filename = @filename
if opendialog.execute != 0
setCurrentPattern(opendialog.currentPattern)
loadFile(opendialog.filename)
end
return 1
end
# Insert file into buffer
def onCmdInsertFile(sender, sel, ptr)
opendialog = FXFileDialog.new(self, "Open Document")
opendialog.selectMode = SELECTFILE_EXISTING
opendialog.patternList = getPatterns()
opendialog.currentPattern = getCurrentPattern()
if opendialog.execute != 0
setCurrentPattern(opendialog.currentPattern)
insertFile(opendialog.filename)
end
return 1
end
# Update insert file
def onUpdInsertFile(sender, sel, ptr)
if @editor.editable?
sender.handle(self, MKUINT(ID_ENABLE, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_DISABLE, SEL_COMMAND), nil)
end
return 1
end
# Extract selection to file
def onCmdExtractFile(sender, sel, ptr)
savedialog = FXFileDialog.new(self, "Save Document")
file = "untitled"
savedialog.selectMode = SELECTFILE_ANY
savedialog.patternList = getPatterns()
savedialog.currentPattern = getCurrentPattern()
savedialog.filename = file
if savedialog.execute != 0
setCurrentPattern(savedialog.currentPattern)
file = savedialog.filename
if File.exist?(file)
if MBOX_CLICKED_NO == FXMessageBox.question(self, MBOX_YES_NO,
"Overwrite Document", "Overwrite existing document: #{file}?")
return 1
end
end
extractFile(file)
end
return 1
end
# Update extract file
def onUpdExtractFile(sender, sel, ptr)
if @editor.hasSelection()
sender.handle(self, MKUINT(ID_ENABLE, SEL_COMMAND), nil)
else
sender.handle(self, MKUINT(ID_DISABLE, SEL_COMMAND), nil)
end
return 1
end
# Open Selected
def onCmdOpenSelected(sender, sel, ptr)
string = getDNDData(FROM_SELECTION, stringType)
return 1 if !string
if string.length < 1024
# Where to look for this file?
if @filename.empty?
dir = Dir.getwd
else
dir = File.dirname(@filename) unless @filename.empty?
end
# Strip leading and trailing spaces
string.strip!
# Attempt to extract the file name from various forms
if string =~ /#include \".*\"/
file = File.expand_path(name, dir)
if !File.exist?(file)
Find.find(@searchpath) { |f| file = f if (f == name) }
end
elsif string =~ /#include <.*>/
file = File.expand_path(name, dir)
if !File.exist?(file)
Find.find(@searchpath) { |f| file = f if (f == name) }
end
elsif string =~ /.*:.*:.*/
file = File.expand_path(name, dir)
if !File.exist?(file)
Find.find(@searchpath) { |f| file = f if (f == name) }
end
else
file = File.expand_path(string, dir)
end
if File.exist?(file)
# Different from current file?
if file != @filename
# Save old file first
return 1 if !saveChanges()
# Open the new file
loadFile(file)
end
# Switch line number only
if lineno != 0
pos = @editor.nextLine(0, lineno - 1)
@editor.cursorPos = pos
@editor.centerLine = pos
end
return 1
end
else
getApp().beep # string is too long to be a file name
end
return 1
end
# Open recent file
def onCmdRecentFile(sender, sel, filename)
return 1 if !saveChanges()
loadFile(filename)
return 1
end
# Save
def onCmdSave(sender, sel, ptr)
if !@filenameset
return onCmdSaveAs(sender, sel, ptr)
end
saveFile(@filename)
return 1
end
# Save Update
def onUpdSave(sender, sel, ptr)
msg = (!@undolist.marked?) ? FXWindow::ID_ENABLE : FXWindow::ID_DISABLE
sender.handle(self, MKUINT(msg, SEL_COMMAND), nil)
return 1
end
# Save As
def onCmdSaveAs(sender, sel, ptr)
savedialog = FXFileDialog.new(self, "Save Document")
file = @filename
savedialog.selectMode = SELECTFILE_ANY
savedialog.patternList = getPatterns()
savedialog.currentPattern = getCurrentPattern()
savedialog.filename = file
if savedialog.execute != 0
setCurrentPattern(savedialog.currentPattern)
file = savedialog.filename
if File.exist?(file)
if MBOX_CLICKED_NO == FXMessageBox.question(self, MBOX_YES_NO,
"Overwrite Document", "Overwrite existing document: #{file}?")
return 1
end
end
saveFile(file)
end
return 1
end
# New
def onCmdNew(sender, sel, ptr)
return 1 if !saveChanges()
@filename = "untitled"
@filetime = nil
@filenameset = false
@editor.text = nil
@editor.modified = false
@editor.editable = true
@undolist.clear
@undolist.mark
return 1
end
# Quit
def onCmdQuit(sender, sel, ptr)
return 1 if !saveChanges()
writeRegistry()
getApp().exit(0)
return 1
end
# Update title
def onUpdTitle(sender, sel, ptr)
title = "FOX Text Editor:- " + @filename
title += "*" if !@undolist.marked?
sender.handle(self, MKUINT(FXWindow::ID_SETSTRINGVALUE, SEL_COMMAND), title)
return 1
end
# Print the text
def onCmdPrint(sender, sel, ptr)
dlg = FXPrintDialog.new(self, "Print File")
if dlg.execute != 0
printer = dlg.printer
end
return 1
end
# Command from the tree list
def onCmdTreeList(sender, sel, item)
if !item || !@dirlist.isItemFile(item)
return 1
end
if !saveChanges()
return 1
end
file = @dirlist.getItemPathname(item)
loadFile(file)
return 1
end
# See if we can get it as a filename
def onEditDNDDrop(sender, sel, ptr)
urilist = getDNDData(FROM_DRAGNDROP, FXWindow.urilistType)
if urilist
file = FXURL.fileFromURL(urilist.before('\r'))
return 1 if (file == "")
return 1 if !saveChanges()
loadFile(file)
return 1
end
return 0
end
# See if a filename is being dragged over the window
def onEditDNDMotion(sender, sel, ptr)
if offeredDNDType(FROM_DRAGNDROP, FXWindow.urilistType)
acceptDrop(DRAG_COPY)
return 1
end
return 0
end
# Change both text background color
def onCmdTextBackColor(sender, sel, color)
@editor.backColor = color
return 1
end
# Update background color
def onUpdTextBackColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.backColor)
return 1
end
# Change both text selected background color
def onCmdTextSelBackColor(sender, sel, color)
@editor.selBackColor = color
return 1
end
# Update selected background color
def onUpdTextSelBackColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.selBackColor)
return 1
end
# Change both text and tree text color
def onCmdTextForeColor(sender, sel, color)
@editor.textColor = color
return 1
end
# Forward GUI update to text widget
def onUpdTextForeColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.textColor)
return 1
end
# Change both text and tree text color
def onCmdTextSelForeColor(sender, sel, color)
@editor.selTextColor = color
return 1
end
# Forward GUI update to text widget
def onUpdTextSelForeColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.selTextColor)
return 1
end
# Change cursor color
def onCmdTextCursorColor(sender, sel, color)
@editor.cursorColor = color
return 1
end
# Update cursor color
def onUpdTextCursorColor(sender, sel, ptr)
sender.handle(self, MKUINT(FXWindow::ID_SETINTVALUE, SEL_COMMAND), @editor.cursorColor)
return 1
end
# Change both tree background color
def onCmdDirBackColor(sender, sel, color)
@dirlist.backColor = color
return 1
end
# Update background color
def onUpdDirBackColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @dirlist.backColor)
return 1
end
# Change both text and tree selected background color
def onCmdDirSelBackColor(sender, sel, color)
@dirlist.selBackColor = color
return 1
end
# Update selected background color
def onUpdDirSelBackColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @dirlist.selBackColor)
return 1
end
# Change both text and tree text color
def onCmdDirForeColor(sender, sel, color)
@dirlist.textColor = color
return 1
end
# Forward GUI update to text widget
def onUpdDirForeColor(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @dirlist.textColor)
return 1
end
# Change both text and tree
def onCmdDirSelForeColor(sender, sel, color)
@dirlist.selTextColor = color
return 1
end
# Forward GUI update to text widget
def onUpdDirSelForeColor(sender, sel, ptr)
sender.handle(sender, MKUINT(FXWindow::ID_SETINTVALUE, SEL_COMMAND), @dirlist.selTextColor)
return 1
end
# Change both text and tree
def onCmdDirLineColor(sender, sel, color)
@dirlist.lineColor = color
return 1
end
# Forward GUI update to text widget
def onUpdDirLineColor(sender, sel, ptr)
sender.handle(sender, MKUINT(FXWindow::ID_SETINTVALUE, SEL_COMMAND), @dirlist.lineColor)
return 1
end
# Text inserted
def onTextInserted(sender, sel, change)
@undolist.add(FXTextInsert.new(@editor, change.pos))
# Keep the undo list in check by trimming it down to KEEPUNDOSIZE
# whenever the amount of undo buffering exceeds MAXUNDOSIZE.
@undolist.trimSize(KEEPUNDOSIZE) if (@undolist.undoSize() > MAXUNDOSIZE)
return 1
end
# Text deleted
def onTextDeleted(sender, sel, change)
@undolist.add(FXTextDelete.new(@editor, change))
# Keep the undo list in check by trimming it down to KEEPUNDOSIZE
# whenever the amount of undo buffering exceeds MAXUNDOSIZE.
@undolist.trimSize(KEEPUNDOSIZE) if (@undolist.undoSize() > MAXUNDOSIZE)
return 1
end
# Text replaced
def onTextReplaced(sender, sel, change)
@undolist.add(FXTextReplace.new(@editor, change))
# Keep the undo list in check by trimming it down to KEEPUNDOSIZE
# whenever the amount of undo buffering exceeds MAXUNDOSIZE.
@undolist.trimSize(KEEPUNDOSIZE) if (@undolist.undoSize() > MAXUNDOSIZE)
return 1
end
# Released right button
def onTextRightMouse(sender, sel, event)
if !event.moved
pane = FXMenuPane.new(self)
FXMenuCommand.new(pane, "Undo", @undoicon, @undolist, FXUndoList::ID_UNDO)
FXMenuCommand.new(pane, "Redo", @redoicon, @undolist, FXUndoList::ID_REDO)
FXMenuSeparator.new(pane)
FXMenuCommand.new(pane, "Cut", @cuticon, @editor, FXText::ID_CUT_SEL)
FXMenuCommand.new(pane, "Copy", @copyicon, @editor, FXText::ID_COPY_SEL)
FXMenuCommand.new(pane, "Paste", @pasteicon, @editor, FXText::ID_PASTE_SEL)
FXMenuCommand.new(pane, "Select All", nil, @editor, FXText::ID_SELECT_ALL)
pane.create
pane.popup(nil, event.root_x, event.root_y)
getApp().runModalWhileShown(pane)
end
return 1
end
# Set TextWindow path
def onCmdIncludePaths(sender, sel, ptr)
searchpath = FXInputDialog::getString(@searchpath, self,
"Change include file search path",
"Specify a list of directories separated by a `#{File::PATH_SEPARATOR}'" +
" where include files are to be found.\nFor example:\n\n" +
" /usr/include#{File::PATH_SEPARATOR}/usr/local/include\n\n" +
"This list will be used to locate the selected file name.")
@searchpath = searchpath if searchpath != nil
return 1
end
# Change patterns
def setPatterns(patterns)
@filter.clearItems
patterns.each { |pat| @filter.appendItem(pat) }
if @filter.numItems == 0
@filter.appendItem("All Files (*)")
end
setCurrentPattern(0)
end
# Return array of pattern strings
def getPatterns()
patterns = []
@filter.each { |itemText, itemData| patterns.push(itemText) }
patterns
end
# Strip pattern from text if present
def patternFromText(pattern)
if pattern =~ /\(.*\)/
$&[1..2]
else
pattern
end
end
# Set current pattern
def setCurrentPattern(n)
n = [[0, n].max, @filter.getNumItems() - 1].min
@filter.currentItem = n
@dirlist.pattern = patternFromText(@filter.getItemText(n))
end
# Return current pattern
def getCurrentPattern()
@filter.currentItem
end
# Change the pattern
def onCmdFilter(sender, sel, ptr)
@dirlist.pattern = patternFromText(ptr)
return 1
end
# Show help window
def onCmdShowHelp(sender, sel, ptr)
@helpwindow.show(PLACEMENT_CURSOR)
return 1
end
# Show preferences dialog
def onCmdPreferences(sender, sel, ptr)
preferences = PrefDialog.new(self)
preferences.setPatterns(getPatterns())
if preferences.execute != 0
setPatterns(preferences.getPatterns())
end
return 1
end
# Change tab columns
def onCmdTabColumns(sender, sel, ptr)
@editor.tabColumns = sender.text.to_i # sender is an FXTextField
return 1
end
# Update tab columns
def onUpdTabColumns(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.tabColumns)
return 1
end
# Change wrap columns
def onCmdWrapColumns(sender, sel, ptr)
@editor.wrapColumns sender.text.to_i # sender is an FXTextField
return 1
end
# Update wrap columns
def onUpdWrapColumns(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.wrapColumns)
return 1
end
# Toggle insertion of tabs
def onCmdInsertTabs(sender, sel, ptr)
@editor.textStyle ^= TEXT_NO_TABS
return 1
end
# Update insertion of tabs
def onUpdInsertTabs(sender, sel, ptr)
sender.handle(self, ((@editor.textStyle & TEXT_NO_TABS) != 0) ?
MKUINT(ID_UNCHECK, SEL_COMMAND) : MKUINT(ID_CHECK, SEL_COMMAND), nil)
return 1
end
# Toggle autoindent
def onCmdAutoIndent(sender, sel, ptr)
@editor.textStyle ^= TEXT_AUTOINDENT
return 1
end
# Update autoindent
def onUpdAutoIndent(sender, sel, ptr)
sender.handle(self, ((@editor.textStyle & TEXT_AUTOINDENT) != 0) ?
MKUINT(ID_CHECK, SEL_COMMAND) : MKUINT(ID_UNCHECK, SEL_COMMAND), nil)
return 1
end
# Set brace match time
def onCmdBraceMatch(sender, sel, ptr)
@editor.hiliteMatchTime = sender.text.to_i # sender is an FXTextField
return 1
end
# Update brace match time
def onUpdBraceMatch(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.hiliteMatchTime)
return 1
end
# Change word delimiters
def onCmdDelimiters(sender, sel, ptr)
@editor.delimiters = sender.text # sender is an FXTextField
return 1
end
# Update word delimiters
def onUpdDelimiters(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETSTRINGVALUE, SEL_COMMAND), @editor.delimiters)
return 1
end
# Update box for overstrike mode display
def onUpdOverstrike(sender, sel, ptr)
mode = ((@editor.textStyle & TEXT_OVERSTRIKE) != 0) ? "OVR" : "INS"
sender.handle(self, MKUINT(ID_SETSTRINGVALUE, SEL_COMMAND), mode)
return 1
end
# Update box for readonly display
def onUpdReadOnly(sender, sel, ptr)
rw = ((@editor.textStyle & TEXT_READONLY) != 0) ? "RO" : "RW"
sender.handle(self, MKUINT(ID_SETSTRINGVALUE, SEL_COMMAND), rw)
return 1
end
# Update box for size display
def onUpdNumChars(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), @editor.length)
return 1
end
# Update box for readonly display
def onCheckFile(sender, sel, ptr)
mtime = File.exist?(@filename) ? File.mtime(@filename) : nil
if @filetime && mtime && mtime != @filetime
@filetime = mtime
if MBOX_CLICKED_OK == FXMessageBox.warning(self, MBOX_OK_CANCEL,
"File Was Changed",
"The file was changed by another program\nReload this file from disk?")
loadFile(@filename)
end
end
@timer = getApp().addTimeout(1000, self, ID_FILETIME)
return 1
end
# Set scroll wheel lines
def onCmdWheelAdjust(sender, sel, ptr)
getApp().wheelLines = sender.value # sender is an FXSpinner
return 1;
end
# Update wheel adjustment time
def onUpdWheelAdjust(sender, sel, ptr)
sender.handle(self, MKUINT(ID_SETINTVALUE, SEL_COMMAND), getApp().wheelLines)
return 1
end
# Start the ball rolling
def start(args)
if args.length > 0
loadFile(File.expand_path(args[1]))
end
end
# Create and show window
def create
@urilistType = getApp().registerDragType(FXWindow.urilistTypeName) unless @urilistType
readRegistry
super
show
@timer = getApp().addTimeout(1000, self, ID_FILETIME)
end
end
# Start the whole thing
if __FILE__ == $0
# Make application
application = FXApp.new("TextEdit", "FoxTest")
application.threadsEnabled = false
# Open display
application.init(ARGV)
# Make window
window = TextWindow.new(application)
# Handle interrupt to save stuff nicely
application.addSignal("SIGINT", window, TextWindow::ID_QUIT)
# Create it
application.create
# Start
window.start(ARGV)
# Run
application.run
end