home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR8
/
FOLD11.ZIP
/
FOLD.S
< prev
next >
Wrap
Text File
|
1993-08-06
|
18KB
|
609 lines
/* IF THIS MAKRO IS USED UNCHANGED, THE CLOSED FOLDS CAN BE OPENED WITH
CTRL-F12 AND CLOSED WITH CTRL-F11 */
//{{{ Title
//
// FOLD.S
//
// Version: 1.1 english / 06.08.1993
//
// Macro for TSE as folding editor
//
// Copyright (C) 1993 by Dirk Wissmann
//
// Bugfixes / Additional help:
//
// David Mayerovitch (file-status-bug)
// E-Mail: david.mayerovitch@canrem.com
//
//}}}
//{{{ Introduction
//
// This Sourcefile ist at the same time an example for WHAT using
// folds is able to do. The structure becomes somehow obvious...
//
// Closed folds are marked by three POINTS followed by a brief
// description. Opening them is done by the procedure OpenFold.
// Open folds are marked by user-defined character-strings.
//
// HINT: Please don't use the character "." (Ascii 46) inside the
// description of any fold - it only causes much much trouble.
//
//}}}
//{{{ Known Bugs
//
// Known Bugs in version 1.1:
//
// If you load a new file, where one or more folds have the identical
// description as in an already loaded file, the contents of the fold
// of the already loaded file are completely lost without a chance of
// restoring. Until now, I don't have any idea how to prevent this.
//
// OpenAllClosedFolds doesn't work correct, when a fold is placed in
// the topmost column (column 1 thus). There is no data lost, but it
// is possible, that this fold is placed at a random place inside the
// text.
//
// There is no protection for the folding-lines, thus if someone changes
// the Line starting with the <closedfold> characters, he should know, that
// TSE is perhaps not in state to find the internal buffer. The reason is,
// that the description of the fold is taken as reference-name for this
// internal system buffer. Overwriting lines starting with <startfold>
// characters is not so harmful, but I advise you, NOT to do this.
// ("Enter at your own risk" - B.Simpson)
//
// Nested folds are not possible yet. It would be too complex for me at the
// moment to implement this feature. But if you absolutely want it, there
// could be a dirty workaround, but I'm not sure, if it really works
// (especially while initial closing or final opening of all folds for
// saving the file): create one fold with a name, let's say "louie". Then,
// WITHIN this fold create some empty lines, and then create another fold
// with another name, let's say "foo". When you finished your work in
// "foo", close this fold, and after finishing work in "louie", close this
// fold too. Opening now must happen in reverse order: first open "louie",
// then open "foo" - voilà, it should have worked. But I recommend you,
// better NOT to do such things - leaving the editor would DEFINITELY
// destroy "foo", I think.
//
//}}}
//{{{ Improvements and new versions
//
// Improvements, new versions:
//
// If I find the time, I'm surely interested in improving my macro. I
// think, in one of the next versions, the menu-driven configuration will
// be implemented. I also will _try_ to implement nested folds, but that's
// really complex, so this will take some time. Finally, in one of the next
// versions, there will be a function to DEactivate the macro.
//
// If someone has suggestions or has done changes in sourcecode - please
// send them to me (see below for my email-addresses).
//
// Improvements done so far:
//
// ---------------------------- Version 1.1 -----------------------
// * David Mayerovitch has fixed the problem, that even if there were
// no changes at all, the editor always thought, there WERE some
// changes (caused by the use of system-buffers).
//
// * I slightly changed the key-assignment and added some keys.
// New: keys to open or close all folds with one keystroke, and
// a key to deactivate the macro (see below)
//
// * I added a function to deactivate the macro now. Before it is
// deactivated, all folds are opened, so there should be no loss
// of data.
//
//}}}
//{{{ Copyright
//
// For those, who didn's open the fold "Title" in this source:
// this macro is Copyrighted. For more details see the file
// READ.ME, which should be found in this archive.
//
//}}}
//{{{ Global variables
string closedfold[6] = " ..." // Alt-255 followed by 3 dots
string startfold[6] = "{{{"
string endfold[6] = "}}}"
string startcomment[6] = "%"
string endcomment[6] = ""
integer create_history_num = 1
//}}}
//{{{ Function IsClosedFold
// IsClosedFold determines, if the current Cursorline could be
// a closed fold. Returns 1, if yes, else 0.
integer proc IsClosedFold()
string foldline[6] = ""
integer result = 0
foldline = GetText(1,Length(closedfold))
result = (foldline == closedfold)
return(result)
end IsClosedFold
//}}}
//{{{ Function IsOpenFold
// IsOpenFold determines, if the current Cursorline could be
// an opened fold. Returns 1, if yes, else 0.
integer proc IsOpenFold()
string foldline[12] = ""
integer result = 0
string openfold[12] = ""
openfold = startcomment + startfold
foldline = GetText(1,Length(openfold))
result = (foldline == openfold)
return(result)
end IsOpenFold
//}}}
//{{{ Fucktion GetFoldDescription
// GetFoldDescription gets the description of a fold
// (I never would have guessed THAT ;-)
string proc GetFoldDescription()
string result[100] = ""
string foldsign_start[100] = ""
integer desc_start, desc_end
integer noclose = 0
if NOT IsClosedFold()
foldsign_start = startcomment + startfold
noclose = 1
else
foldsign_start = closedfold
noclose = 0
endif
desc_start = Length(foldsign_start) + 2 // BEHIND the space, we start!
PushPosition()
EndLine()
if noclose
desc_end = CurrPos() - Length(endcomment) - desc_start
else
desc_end = CurrPos() - desc_start
endif
PopPosition()
result = GetText(desc_start,desc_end)
return(result)
end GetFoldDescription
//}}}
//{{{ Procedure MarkFold
// MarkFold marks a complete fold. Does'nt work yet for nested folds
proc MarkFold()
string findstr[18] = ""
findstr = startcomment + endfold + endcomment
PushPosition()
UnmarkBlock()
MarkLine()
BegLine()
// Endmarks only may appear in column 1
while (lFind(findstr,"")) and (CurrCol()>1)
Right()
endwhile
MarkLine()
PopPosition()
end MarkFold
//}}}
//{{{ Procedure OpenFold
// OpenFold opens a closed fold (no, say...). Doesn't work yet
// for nested folds.
// File status is not affected now.
proc OpenFold()
string description[80] = ""
integer fold_id = 0
integer SaveClipboardId = 0
integer fileChanged = 0
PushBlock()
if IsClosedFold()
description = GetFoldDescription()
SaveClipboardId = GetClipBoardId() // save actual Clipboard
fold_id = GetBufferId(description)
if fold_id <> 0
fileChanged = IsChanged() // SAVE CURRENT FILE STATUS
DelLine()
Up() // Necessary because of DelLine
SetClipBoardId(fold_id)
Paste()
ForceChanged(fileChanged) // RESTORE FILE STATUS
SetClipBoardId(SaveClipBoardId)
Down() // and back
else
warn("FATAL: Buffer with this line not more available :-(")
endif
else
warn("WARNING: Line isn't a closed fold!")
endif
PopBlock()
end OpenFold
//}}}
//{{{ Procedure CloseFold
// CloseFold closes an open fold (hey, this guy knows what he says ;-) )
// Doesn't work yet for nested folds.
// File status is not affected now.
proc CloseFold()
string description[80] = ""
string cl_fold[80] = ""
integer fold_id = 0
integer SaveClipboardId = 0
integer curr_id = 0
integer fileChanged = 0
if IsOpenFold()
description = GetFoldDescription()
PushBlock()
MarkFold()
SaveClipboardId = GetClipBoardId() // save actual Clipboard
fold_id = GetBufferId(description)
if fold_id == 0
curr_id = GetBufferId()
fold_id = CreateBuffer(description,_SYSTEM_)
GotoBufferId(curr_id)
endif
if fold_id <> 0 // put away this fold
SetClipBoardId(fold_id)
fileChanged = IsChanged() // SAVE CURRENT FILE STATUS
Cut()
SetClipBoardId(SaveClipboardId)
cl_fold = closedfold + " " + description
InsertLine(cl_fold)
ForceChanged(fileChanged) // RESTORE FILE STATUS
else
Warn("FATAL: fold could not be saved internally!")
endif
PopBlock()
else
Warn("WARNING: I don't like THIS as fold...")
endif
end CloseFold
//}}}
//{{{ Procedure CreateFold
// CreateFold... guess yourself :-) It also creates the description
// and all necessary informations.
proc CreateFold()
string foldsign_start[100] = ""
string foldsign_end[18] = ""
string description[80] = ""
foldsign_end = startcomment + endfold + endcomment
Ask("Description for this fold: ", description, create_history_num)
foldsign_start = startcomment + startfold + " " + description + endcomment
AddLine(foldsign_start)
AddLine(foldsign_end)
end CreateFold
//}}}
//{{{ Function ContainsFileFold
// ContainsFileFold determines, whether a loaded file contains a fold
// or not. (YIKES)
integer proc ContainsFileFold()
integer result = 0
integer lastline = 0
BegFile()
while (not result) and (not lastline)
result = IsOpenFold()
lastline = not Down()
endwhile
return(result)
end ContainsFileFold
//}}}
//{{{ Function ContainsFileClosedFold
// ContainsFileClosedFold determines, if in the actual file, there
// is any closed fold. The marking of these folds MUST appear
// at the beginning of the line.
integer proc ContainsFileClosedFold()
integer result = 0
integer lastline = 0
BegFile()
while (not result) and (not lastline)
result = IsClosedFold()
lastline = not Down()
endwhile
return(result)
end ContainsFileClosedFold
//}}}
//{{{ Function FindNextClosedFold
// FindNextClosedFold searches from within the cursorline down
// to the next closed fold. Attention: if such a fold is found,
// the following Down() must be omitted, else the cursor would be
// on line too far down for opening this fold. Therefor the if-
// construction marked with (1), also in the next procedure!
integer proc FindNextClosedFold()
integer result = 0
integer lastline = 0
while (not result) and (not lastline)
result = IsClosedFold()
if not result // (1)
lastline = not Down()
endif
endwhile
return(result)
end FindNextClosedFold
//}}}
//{{{ Function FindNextOpenFold
// FindNextOpenFold searches from within the cursorline until the next
// open fold. For (1), see FindNextClosedFold.
integer proc FindNextOpenFold()
integer result = 0
integer lastline = 0
while (not result) and (not lastline)
result = IsOpenFold()
if not result // (1)
lastline = not Down()
endif
endwhile
return(result)
end FindNextOpenFold
//}}}
//{{{ Procedure OpenAllClosedFolds
// OpenAllClosedFolds opens all closed folds, so that the file is
// ready to be saved. MUST be done, because all folds are stored
// in system-buffers, which are NOT saved automatically!
proc OpenAllClosedFolds()
BegFile()
while FindNextClosedFold()
OpenFold()
endwhile
end OpenAllClosedFolds
//}}}
//{{{ Procedure CloseAllOpenFolds
// CloseAllOpenFolds is called upon first time loading a file:
// contained folds are closed, so that the user directly sees the
// structure of the file.
proc CloseAllOpenFolds()
BegFile()
while FindNextOpenFold()
CloseFold()
endwhile
end CloseAllOpenFolds
//}}}
//{{{ Procedure mExitAndSave
// mExitAndSave is an extended Exit-procedure, because there could
// be closed folds in the system-buffers. They must be opened before
// saving, otherwise you would have massive Date-loss.
proc mExitAndSave()
if ContainsFileClosedFold()
Message("One moment please...")
OpenAllClosedFolds()
endif
Exit()
end mExitAndSave
//}}}
//{{{ Procedure mQuitFile
// mQuitFile replaces QuitFile, because this procedure works only
// for the part you SEE on screen. This can naturally cause heavy
// loss of data, which I hope will be prevented by this procedure here.
proc mQuitFile()
if ContainsFileClosedFold()
Message("One moment please...")
OpenAllClosedFolds()
endif
QuitFile()
end mQuitFile
//}}}
//{{{ Prozedur mSaveFile
// mSaveFile replaces SaveFile, because this procedure works only
// for the part you SEE on screen. This can naturally cause heavy
// loss of data, which I hope will be prevented by this procedure here.
proc mSaveFile()
if ContainsFileClosedFold()
Message("One moment please...")
OpenAllClosedFolds()
endif
SaveFile()
end mSaveFile
//}}}
//{{{ Prozedur mSaveAndQuitFile
// mSaveAndQuitFile replaces SaveAndQuitFile, because this procedure
// works only for the part you SEE on screen. This can naturally cause
// heavy loss of data, which I hope will be prevented by this
// procedure here.
proc mSaveAndQuitFile()
if ContainsFileClosedFold()
Message("One moment please...")
OpenAllClosedFolds()
endif
SaveAndQuitFile()
end mSaveAndQuitFile
//}}}
//{{{ Procedure PrepareLoadedFile
// PrepareLoadedFile checks, if a loaded file contains folds. If yes,
// all folds are closed, so that the structure of the file can be seen.
// Using hooking-technique, this procedure is called every time you
// load a new file.
proc PrepareLoadedFile()
if ContainsFileFold()
CloseAllOpenFolds()
else
Message("INFO: File doesn't contain folds yet!")
endif
end PrepareLoadedFile
//}}}
//{{{ Procedure ReadConfigFile
// ReadConfigFile reads an eventually existing Configurationfile.
// What you can see here: normally, the use of macro-instructions
// for reading DOS-Files is not necessary, you can get everything
// as shown here.
// ReadConfigFile is called automatically upon start of macro.
// The configurationfile MUST be named FOLD.CFG.
proc ReadConfigFile()
EditFile("fold.cfg")
BegFile()
lfind("startfold=","")
startfold = GetText(11,6)
BegFile()
lfind("endfold=","")
endfold = GetText(9,6)
BegFile()
lfind("startcomment=","")
startcomment = GetText(14,6)
BegFile()
lfind("endcomment=","")
endcomment = GetText(12,6)
BegFile()
lfind("closedfold=","")
closedfold = GetText(12,6)
AbandonFile()
end ReadConfigFile
//}}}
//{{{ Procedure SaveConfigFile
// SaveConfigFile writes a configurationfile to disk (not used yet).
// You could apply this procedure to a special key. In a later version,
// this procedure will be used from within an interactive menu.
// Interesting: the file is built like a LIFO-buffer. This is caused
// by the InsertLine-command.
proc SaveConfigFile()
integer id
id = CreateBuffer("fold.cfg")
if id
InsertLine("closedfold="+closedfold)
InsertLine("endcomment="+endcomment)
InsertLine("startcomment="+startcomment)
InsertLine("endfold="+endfold)
InsertLine("startfold="+startfold)
EraseDiskFile("fold.cfg")
SaveAs("fold.cfg")
AbandonFile()
else
Warn("WARNING: Couldn't create configuration-file in memory!")
endif
end SaveConfigFile
//}}}
//{{{ Startup Macro WhenLoaded
// Executed upon start of TSE, but before the commandline is completely
// evaluated and before any file is loaded.
proc WhenLoaded()
if FileExists("fold.cfg") // Read configuration, if existing
ReadConfigFile()
endif
Set(Break,ON)
Hook(_ON_FIRST_EDIT_,PrepareLoadedFile)
end WhenLoaded
//}}}
//{{{ Procedure DeactivateMacro
// With DeactivateMacro, the macro fold is fully disabled. But before
// doing this, all folds are opened, so that there is no loss of data.
proc DeactivateMacro()
Message("The folding macro finishes his work. Live long and prosper!")
OpenAllClosedFolds()
PurgeMacro("fold")
end DeactivateMacro
//}}}
//{{{ Startup Macro Main
// Main is executed upon start of macro, but AFTER a file named in the
// command-line is loaded.
proc Main()
UpdateDisplay()
BegFile()
if (ContainsFileFold())
PrepareLoadedFile()
endif
Message("TSE is now configured as folding editor! (c) dw 93")
end Main
//}}}
//{{{ Keydefinitions
// Keydefinitions for testing purposes.
// Please change them following your own wishes.
// I recommend the redefinition of Alt-x, and perhaps the new definition
// of Ctrl F11 und Ctrl F12.
<Ctrl F3> CloseAllOpenFolds()
<Ctrl F4> OpenAllClosedFolds()
<Ctrl F6> SaveConfigFile()
<Ctrl F8> ReadConfigFile()
<Alt x> mExitAndSave()
<Ctrl F10> CreateFold()
<Ctrl F11> CloseFold()
<Ctrl F12> OpenFold()
<Shift F12> DeactivateMacro()
// necessary new assignments
<Ctrl k><q> mQuitFile() CloseWindow()
<Ctrl k><d> mQuitFile() CloseWindow()
<Ctrl k><s> mSaveFile()
<Ctrl k><x> mSaveAndQuitFile()
//}}}