sda4: commit the Glaze developer hard-drive dump

Un-ignored: the dev drive is the ground truth the restoration and
emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer
source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio
content). Kept in-repo for the pod-owner community.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-04 19:41:15 -05:00
co-authored by Claude Fable 5
parent 504aef88d4
commit db7745fcd0
19993 changed files with 1983033 additions and 0 deletions
Binary file not shown.
Binary file not shown.
+33
View File
@@ -0,0 +1,33 @@
PROMPT $p$g
rem C:\386MAX\386Cache /m- /s:768 /l:512
rem C:\386MAX\386Cache /m- /s:512 /EM
C:\386MAX\386Cache /m- /s:512
c:\tools\numb
C:\QUICKEN4\BILLMIND C:\QUICKEN4
rem --------start of unattended backup installation
rem cd \TAPE
rem autoback C:\TAPE
rem cd \
rem --------end of unattended backup installation
SET NU=C:\NORTON
@C:\NORTON\IMAGE
set bpath=;c:\brief\macros
set bhelp=c:\brief\help
set bfile=c:\brief\state.rst
set bbackup=c:\backup
set bcc="!cl -c %%s.c"
set bcasm="!masm %%s.asm\;"
set bpackages=c:t 0 0 0 0;asm:r
rem set bpackages=c:t 1 1 1 0;asm:r ***** FOR VWEI
set bflags=-i120k4M117z -mCPB -mrestore -Dega
set path=c:\dos;c:\windows;c:\tools;c:\brief;c:\norton;c:\word;c:\c600\bin;c:\c600\binb;\dpaint;\pads;
SET LIB=C:\C600\LIB
SET HELPFILES=C:\C600\HELP\*.HLP;C:\MASM\HELP\*.HLP;
SET INCLUDE=C:\C600\INCLUDE
SET INIT=C:\C600\INIT
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
echo off
prompt $p$g
rem VERIFY=OFF
path C:\utils\zip;c:\dos;c:\brief;c:\doomsw;
rem set bpath=c:\brief\macros
rem set bhelp=c:\brief\help
rem set bfile=state.rst
rem set bbackup=editback\
rem set bcc="cl -c %%s.c"
rem set bpackages=doc-txt,h-c,default,c,txt,odl,asm,658,pas,68k,34,34h,hdr,z80:r
rem set bflags=-i160Mu300 -mGC -mrestore -msavehist -mscrapper -Dega -D101key
c:\bin\msmouse7
prompt $p$g
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+136
View File
@@ -0,0 +1,136 @@
ÚÄÂÄ¿ÉÍËÍ»ÖÄÒÄ·ÕÍÑ͸ÜÜÜ
³ ³ ³º º ºº º º³ ³ ³Ý Þ
ÃÄÅÄ´ÌÍÎ͹ÇÄ×ĶÆÍØÍµßßß
³ ³ ³º º ºº º º³ ³ ³°±²Ûþùúð
ÀÄÁÄÙÈÍÊͼÓÄÐĽÔÍÏ;
LSN -->
0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
       
        
               
     
2³ ! " # $ % & ' ( ) * + , - . / 2³         
3³0 1 2 3 4 5 6 7 8 9 : ; < = > ? 3³  ! " # $ % & '
4³@ A B C D E F G H I J K L M N O 4³( ) * + , - . / 0 1
5³P Q R S T U V W X Y Z [ \ ] ^ _ 5³2 3 4 5 6 7 8 9 : ;
6³` a b c d e f g h i j k l m n o 6³< = > ? @ A B C D E
7³p q r s t u v w x y z „ | } ~  7³F G H I J K L M N O
8³€ ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž 8³P Q R S T U V W X Y
‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ 9³Z [ \ ] ^ _ ` a b c
A³  ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ 10³d e f g h i j k l m
B³° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ 11³n o p q r s t u v w
C³À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï 12³x y z „ | } ~ 
D³Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß 13³‚ ƒ „ … † ‡ ˆ ‰ Š ‹
E³à á â ã ä å æ ç è é ê ë ì í î ï 14³Œ Ž ‘ ’ “ ” •
F³ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ 15³– — ˜ ™ š › œ ž Ÿ
16³  ¡ ¢ £ ¤ ¥ ¦ § ¨ ©
17³ª « ¬ ­ ® ¯ ° ± ² ³
18³´ µ ¶ · ¸ ¹ º » ¼ ½
19³¾ ¿ À Á Â Ã Ä Å Æ Ç
20³È É Ê Ë Ì Í Î Ï Ð Ñ
21³Ò Ó Ô Õ Ö × Ø Ù Ú Û
22³Ü Ý Þ ß à á â ã ä å
23³æ ç è é ê ë ì í î ï
24³ð ñ ò ó ô õ ö ÷ ø ù
25³ú û ü ý þ
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
³ (c) 1992 innoMATION, all rights reserved ³
ÃÄÄÄÄÄÄÄÄÄÂÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ History ³þþþ³þþ-þþ-þþ³started ³
ÀÄÄÄÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ Description ³ ³
ÆÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵
³ Enter ³(void) ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ Exit ³(void) ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ Side effects³**UNKNOWN** ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ Comments ³(none) ³
ÆÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÑÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵
³ History ³þþþ³þþ-þþ-þþ³first written ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
/*ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
º º
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
º Description ³ º
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
º Enter ³(void) º
ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º Exit ³(void) º
ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º Side effects³**UNKNOWN** º
ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
º Comments ³(none) º
ÌÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÑÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
º History ³þþþ³þþ-þþ-þþ³first written º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÏÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ ³
;³ Incredible Technologies, Inc. ³
;ÃÄÄÄÄÄÄÄÄÄÂÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³ History ³þþþ³þþ-þþ-þþ³started ³
;ÀÄÄÄÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³ Description ³ ³
;ÆÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵
;³ Enter ³(void) ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³ Exit ³(void) ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³ Side effects³**UNKNOWN** ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³ Comments ³(none) ³
;ÆÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÑÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͵
;³ History ³þþþ³þþ-þþ-þþ³first written ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
;º º
;ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
;º Description ³ º
;ÌÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
;º Enter ³(void) º
;ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
;º Exit ³(void) º
;ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
;º Side effects³**UNKNOWN** º
;ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ
;º Comments ³(none) º
;ÌÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÑÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹
;º History ³þþþ³þþ-þþ-þþ³first written º
;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÏÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
+28
View File
@@ -0,0 +1,28 @@
echo off
rem Very basic macro to make the compile/correct task easier. Uses the error
rem macro to locate errors after an unsucessful compile, then attempts to
rem compile again. Note the invocation of brief with the -m option.
if .%1 == . goto usage
:loop
if .%1 == . goto exit
if not exist %1.c goto again
if exist %1 goto usage
cc1 -i %1 >%1.err
if errorlevel 1 goto error
cc2 %1 >%1.err
if errorlevel 1 goto error
cc3 %1 >%1.err
if errorlevel 1 goto error
cc4 %1 >%1.err
if errorlevel 1 goto error
del %1.err
goto again
:error
b %1.c -mnext_error
goto loop
:again
shift
goto loop
:usage
echo Usage: c86cc filenames... (no .c)
:exit
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
echo off
rem Very basic macro to make the compile/correct task easier. Uses the errorfix
rem macro to locate errors after an unsucessful compile, then attempts to
rem compile again. Note the invocation of brief with the -m option.
if .%1 == . goto usage
:loop
if .%1 == . goto exit
if not exist %1.m goto again
if exist %1 goto usage
cm %1 >%1.err
if errorlevel 1 goto error
del %1.err
goto again
:error
b %1.m -mnext_error
goto loop
:again
shift
goto loop
:usage
echo Usage: cmac filenames... (no .m)
:exit
+22
View File
@@ -0,0 +1,22 @@
echo off
rem Very basic macro to make the compile/correct task easier. Uses the errorfix
rem macro to locate errors after an unsucessful compile, then attempts to
rem compile again. Note the invocation of brief with the -m option.
if .%1 == . goto usage
:loop
if .%1 == . goto exit
if not exist %1.asm goto again
if exist %1 goto usage
masm %1.asm; >%1.err
if errorlevel 1 goto error
del %1.err
goto again
:error
b %1.asm -mnext_error
goto loop
:again
shift
goto loop
:usage
echo Usage: cmasm filenames... (no .asm)
:exit
+7
View File
@@ -0,0 +1,7 @@
buffers = 20
files = 20
device = dmdrvr.bin
device = mouse.sys /2
device = ramdrive.sys 380/e
shell = c:\command.com c:\ /p /e:800

+10
View File
@@ -0,0 +1,10 @@
FILES=40
DOS=HIGH
buffers=20
device=c:\386max\386max.sys pro=c:\386max\386max.pro
rem device=c:\386max\386load.sys size=6144 flexframe prog=c:\386max\386disk.sys 400 128 32
device=c:\dos\setver.exe
device=c:\386max\386load.sys size=2912 prgreg=3 prog=c:\386max\386cache.win
device=c:\386max\386load.sys size=17168 prog=c:\mouse\mouse.sys /c2
shell =c:\command.com c:\ /p /e:800
+556
View File
@@ -0,0 +1,556 @@
HOW TO USE THE BRIEF DIALOG MANAGER PACKAGE
WHAT IS THE DIALOG MANAGER?
The BRIEF dialog manager is a macro package containing tools for
generating pop-up menus and dialog boxes. Menus allow a user to perform
complicated tasks by choosing from lists of possible actions. Dialog
boxes allow a user to answer questions and fill in forms, while possibly
restricting the set of valid answers.
Many of BRIEF's standard macros (Help, for example) use the dialog
manager. You can use the dialog manager in your own macros, too.
WHERE IS THE DIALOG MANAGER?
Source code for the package is located in the files dialog.m and
dialog.h; the compiled version is in dialog.cm.
WHY USE THE DIALOG MANAGER?
The BRIEF dialog manager provides a standard user interface for macros.
If you write a macro that uses this interface properly, it will have the
look and feel of the standard commands that are shipped with BRIEF, and
any BRIEF user will be able to use it with minimal effort.
Using the dialog manager conserves memory and avoids reinventing the
wheel. Suppose you frequently use Help and three other macro packages
with separate user interfaces. That's a lot of macros to load at once;
BRIEF may spend a fair amount of time re-reading the disk. The macros
will take up far less memory if they reuse the same code.
WHAT CAPABILITIES ARE PROVIDED?
The dialog manager is essentially just two macro calls, one to create
and process a menu, and one to create and process a dialog box.
Although the dialog manager contains dozens of other macros (as well as
several global variables,) you should seldom need to deal with them.
(Consult the source code for more information.)
Menus are pop-up windows, within which one line ("button") is always
highlighted. Pressing Enter ("picking") causes an action associated
with the highlighted button to be executed. The up and down arrow keys
move the highlight up or down. Windows scroll vertically as needed.
Menus offer a choice of several actions. These actions may invoke other
menus or dialog boxes. In Help, for example, picking some buttons
causes a window of help information on a particular topic to appear;
picking others causes another menu (more detailed) to appear.
Dialog boxes are the other half of the dialog manager. Dialog boxes are
pop-up windows that contain descriptive text and any of several kinds of
input fields. A user may move between fields and change the contents of
any field. These changes can be saved or cancelled as a group.
The kinds of input fields are:
Filenames
Lists
Integers
Nonblank strings
Strings
LISTS
Lists, like menus, are multiple-choice situations; however, lists are
choices of values, not actions, and the values are usually mutually
exclusive. One very common list has two choices: Yes and No.
Lists appear on the screen on a single line, with items separated by
whitespace. A highlight is used to mark the currently selected item
while the user's cursor is on the field; when he or she leaves, the
highlight changes to a pair of parentheses.
A list can be paired with a text string, which is usually a question:
Do you want to save your changes? (Yes)No
Line drawing style: Single(Double)Mixed None
FILENAMES, INTEGERS, NONBLANK STRINGS, AND STRINGS
The number of possible answers to a question is often so great that a
list is awkward or impossible. In such situations, it's best to let the
user to type in his or her answer, then check it for validity. The user
can be asked to re-enter an invalid answer.
Filenames, Integers, Nonblank strings, and Strings behave identically
except that they use different validation criteria. Strings are not
checked at all. Nonblank strings may not be blank. Integer fields must
contain an integer value, and Filename fields must contain a
syntactically legal path name.
Fields are one line deep and may extend from their beginning to the
right edge of the window. The entire field is highlighted when the
user's cursor enters it; the highlight disappears as soon as anything
happens. When the user's cursor leaves, the field contents are
validated.
KEY ASSIGNMENTS
The key assignments for moving around and between menus and dialog boxes
are standardized. You should not change these key assignments, although
you may add your own to the list.
These key assignments are uniform throughout the dialog manager:
Esc Exit all levels Keypad minus Exit 1 level
Ctrl-Home Top of window Ctrl-End End of window
Within menus, the additional assignments are:
Enter Pick from menu
Up arrow Previous item Down arrow Next item
Backspace Previous item Space Next item
Home First item End Last item
PgUp Previous page PgDn Next page
Alphanumeric character Next item beginning with character
Within any dialog box field, the following keys are defined:
Enter Next field, or save if on last field (== Ctrl-m)
F10 Save dialog box and exit
Up arrow Previous field Down arrow Next field
Shift-Tab Previous field Tab Previous field
Within lists only, additional assignments are:
Left arrow Previous item Right arrow Next item
Backspace Previous item Space Next item
Home First item End Last item
Alphanumeric character Next item beginning with character
Within fields (excepting lists), additional key assignments are:
Left arrow Left Right arrow Right
Backspace Backspace Space Space
Home Beginning of field End End of field
Del Delete character Alt-k Delete to end
Ins, Alt-i Toggle insert mode Alt-d Delete field
When a field is highlighted, typing causes the contents of the field to
be replaced by the new characters.
MENUS
HOW TO CREATE A MENU
There are 3 steps involved in creating a menu.
1. Create a data file containing the names of the menu buttons and the
actions you want the buttons to invoke.
2. Write a macro that calls the dialog manager package.
3. Write the action macros that will handle everything the user does in
the menu.
CREATING THE MENU DATA FILE
Menu data files are usually given a .mnu extension and kept in the same
directory as the help files (specified by BHELP).
A menu file contains one line for each line of the menu. Each line
consists of a button name and optional additional information. When
the menu is displayed, the additional information should be invisible
(just past the right edge of the window). The menu button is normally
centered in the visible part of the line.
For fastest operation, each line is normally pre-formatted; in this
example (taken from help.mnu), spaces are used to center the buttons in
the visible part of the window, which is delimited by the semicolons.
Everything to the right of the semicolons is considered "additional
information":
Help on Help ;display_help "help"
Quick Reference ;display_help "keyboard layout"
Key-Specific Help ;key_specific_help
You can also have the menu automatically formatted. If you do, you
must use a semicolon as the delimiter, and leading/trailing whitespace
around the buttons will be ignored:
Help on Help;display_help "help"
Quick Reference;display_help "keyboard layout"
Key-Specific Help;key_specific_help
Action macros, described below, are free to do whatever they want with
the additional information. In this case, the information is a macro
call (complete with a string parameter), and it is passed to
execute_macro.
CALLING UP THE MENU
The call to create and process a menu is as follows:
(_process_menu lx by rx ty title msg filename buf_id action fast)
Parameters 0 through 3 are integers, the coordinates of the left (lx),
bottom (by), right (rx), and top (ty) edges of the window. These are
absolute screen coordinates; the top left corner of a 25x80 screen is
(0, 0) and the lower right is (24, 79). If lx equals rx or ty equals
by, the menu is positioned at (lx, ty) and the size will be computed
automatically based on the number of lines on the menu and the column
position of the first semicolon. (Be careful not to position menus
so close to the bottom and left edges of the screen so that there's
no room for automatic formatting.)
Parameter 4 is the title of the menu, a string to be displayed in the
top edge of the window. It may be at most 12 characters long.
Parameter 5 is a string, a message to be displayed in the bottom edge of
the window. Make sure it is shorter than the edge itself.
You should supply either, but not both, of parameters 6 and 7. Supply
NULL in the place of whichever parameter you omit. Parameter 6 is the
filename of a menu data file (in the BHELP directory), while parameter 7
is the identifier of a buffer containing a menu data file. Use
parameter 7 if you have a .mnu file already in memory and want to keep
it there; otherwise, use parameter 6 and the dialog manager will delete
the buffer when you're done with it. (If you use parameter 7, then the
title you passed in parameter 4 will be ignored, and the buffer name
already in existence will be used.)
Note that parameter 6 is assumed to be the name of a file in the
BHELP directory unless an absolute path name is supplied. The dialog
manager assumes that any name containing the characters /, \, or : is
an absolute path.
Parameter 8 is a string containing the name of your main action macro,
described below.
Parameter 9 may be omitted. If it is passed and TRUE, your menu file
is not formatted in any way, saving oodles of time when it pops up.
If you use this parameter, make sure to pre-format your .mnu file.
The dialog manager assumes the values you pass it are correct, so be
careful.
When the call to _process_menu is encountered, the menu will pop up and
processing of the user's keystrokes will begin immediately. Processing
will stop when the user presses Esc (or the keypad minus key), and
control will return to your macro, just after the _process_menu call.
_process_menu returns TRUE if it was able to create and process a menu,
FALSE if an error occurred.
EVENTS
We have written the dialog manager to be as flexible as possible.
Hence, the system leaves a lot of decisions and a lot of work up to your
action macro. The dialog manager is event-driven; it quietly goes about
its business until an "event" of significance occurs, at which point it
taps your macro on the shoulder, informs it of the situation, and waits
for a response before continuing.
Here's a list of all significant events, for both menus and dialog
boxes. Matching #define statements are contained in the file
"dialog.h". You should #include this file in any macro file you write
that calls the dialog manager, so that you can refer to the event types
by symbolic name rather than by number.
DIALOG_INIT The dialog manager has just been invoked
DIALOG_TERM The dialog manager is exiting
DIALOG_ENTER_FIELD The cursor has just entered a non-list field
DIALOG_EXIT_FIELD The cursor has just left a non-list field
DIALOG_ENTER_LIST The cursor has just entered a list
DIALOG_EXIT_LIST The cursor has just left a list
DIALOG_ALTER_LIST The current item in a list has just been changed
DIALOG_ALTER_MENU The current item in a menu has just been changed
DIALOG_MOVE_MENU (Same as DIALOG_ALTER_MENU)
DIALOG_PICK_MENU The user has just selected a menu button with Enter
DIALOG_ESCAPE The user has just pressed Esc to exit all levels
DIALOG_F10 The user has just pressed F10 to save a dialog box
DIALOG_GREY_MINUS The user has just pressed the keypad minus key
DIALOG_CREATE_MENU A menu buffer has just been made current
DIALOG_CREATE_DBOX A dialog box data buffer "
HOW TO WRITE THE MENU ACTION MACROS
When you're working with menus, only the invoke/exit events, the
Esc/keypad minus events, and the events for changing or selecting menu
items can happen. Your job is to provide a single macro that responds
to these events; the name of this macro is parameter 8 in the call to
_process_menu, and the macro is called by _process_menu whenever one of
these events occurs.
Suppose you call your action macro "action". When called, action will
be passed three parameters:
(action event_type line text)
The first parameter is an integer matching one of the above #defines.
The second is the number of the current line in the menu (note that this
is also the number a user will see as Line: in the BRIEF message area).
The third is the text of the entire button, including the delimiter and
additional information (if any).
In the BRIEF macro language, parameters in the calling function are only
evaluated when the called function explicitly requests the parameter.
This means that, for best performance, your action macro should never
get a parameter it does not need.
The normal strategy for processing events within a menu action macro is
as follows:
1. Get the event type parameter.
2. If the event type is DIALOG_PICK_MENU, then get the line number or
text parameters and process them as desired. Note that the dialog
manager does NOT execute an action associated with a button
automatically. Your action macro must parse the button text and execute
the command.
Commonly, a pick event will cause the action macro to pop up a window
of text (such as help) and enter a process under the user's control.
The window will remain visible until the user presses Esc or Keypad
minus to signal he's done. If the user pressed Esc, the action macro
should push the Esc back into the keyboard buffer so that a DIALOG_ESC
event is generated as soon as the action macro returns.
3. If the event type is DIALOG_CREATE_MENU, the unformatted menu
is the current buffer, and its name is the text parameter. You can
use this event to add buttons to the menu.
(If the event type is anything else, you usually don't need to do any
more. However, if you want to add key assignments to the normal menu
keymap, you can use DIALOG_INIT as a signal to add them, and DIALOG_TERM
as a signal to remove them. And if you want to preclude the user from
moving to a particular line of the menu (for example, a heading) then
you can use DIALOG_MOVE_MENU.)
3. Return TRUE. The only time you should return FALSE is if the event
was DIALOG_MOVE_MENU, and the line number or text was such that you
don't want the cursor to be allowed to move to it (other lines will be
tried until EOF or until DIALOG_MOVE_MENU succeeds).
ACTION MACRO EXAMPLE
The following macro, when called by the dialog manager, will handle two
types of events. First, the user will not be allowed to move to line 1
or line 4. Second, when the user picks a button, this macro will use
the additional information present in the .mnu file to call another macro.
(macro action
(
(int event_type
line_no
retval
)
(string button_text)
(get_parm 0 event_type)
(= retval TRUE)
(switch event_type
DIALOG_MOVE_MENU
(
(get_parm 1 line_no)
(if (|| (== line_no 1) (== line_no 4))
(= retval FALSE)
)
)
DIALOG_PICK_MENU
(
(get_parm 2 button_text)
;** Trim the button name and treat the additional
;** information as a command that can be executed.
(execute_macro (substr button_text
(+ (index button_text ";") 1)))
)
)
(returns retval)
)
)
DIALOG BOXES
HOW TO CREATE A DIALOG BOX
As with menus, there are 3 steps to creating a dialog box: creating a
data file, writing a macro that calls the dialog manager, and writing
action macros.
DATA FILES FOR DIALOG BOXES
Dialog box data files must be kept in the BHELP directory. Like menu
files, they contain one line for each item displayed. Each line
contains the type of the input field, the row and column coordinates
(relative to the window's origin) at which the field should be placed,
and the field's initial contents. The number of fields is unlimited
because dialog boxes, like menus, can scroll vertically.
The row and column coordinates must be surrounded by parentheses and
separated by a comma. The initial contents must be surrounded by double
quotes. Whitespace may go just about anywhere, and you can have
comments. The following example shows a number of legal ways of
defining fields, and descriptive text, in a dialog box:
;** Get the speed using a 3-item list.
Text at (1, 1) is "Speed:"
List ( 1, 8 ) = "(Slow)Medium Fast"
;** Get the user's name. Make sure they enter one.
text (3,1) "Name:"
nonblank(3,9) "Your name goes here"
;** Prompt for user's age. Make sure it's numeric.
T (5, 1) "Age:"
I(5,9)"24"
The first non-whitespace character on a line defines the type of the
field. A 'T' means that this line is a descriptive text string that can
be displayed only. The letters F, L, I, N, and S denote Filenames,
Lists, Integers, Nonblank strings, and Strings.
All fields, even lists and integers, are really strings. Hence, you
should format the initial contents of every field as a quoted string, as
in the example above.
List strings have a special format. Items must be separated by single
tab characters (since spaces are allowed in item names). The item that
is to be initially highlighted should be surrounded by parentheses
instead of tabs.
Position lists as you would any other field. If a list begins with
a (, the dialog manager will compensate for you.
If you omit the current item in a list, or if you supply a field that's
too wide for the window, the invalid field will not be displayed and an
error message will.
The dialog manager does not check to see if any fields overlap. Hence,
only one input field is allowed per line. Text can be placed anywhere
except to the right of an input field.
HOW TO CALL UP A DIALOG BOX
The call to create and process a dialog box is nearly identical to the
call to create a menu, except that the macro name is _process_dialog_box:
(_process_dialog_box lx by rx ty title msg filename buf_id action)
All parameters have the same meaning as for _process_menu, except:
1. There is no automatic sizing for dialog boxes, so lx must not equal
rx, and by must not equal ty.
2. Parameter 4, the title, is always used, even when a buffer ID is passed
for parameter 7.
3. There is no parameter 9 for quick dialog box creation.
This call may return when the user presses F10, Esc, or the keypad minus
key. _process_dialog_box returns TRUE if it was successful, FALSE if an
error occurred.
HOW TO WRITE THE ACTION MACROS
The first two parameters passed to your action function are the event
type and line number. The third parameter is either (for lists) the
text of the current list item, not counting separator characters, or
(for other field types) the full text of the field, not counting the
newline at the end.
Any event may occur in a dialog box except DIALOG_ALTER_MENU or
DIALOG_PICK_MENU. However, the only events you normally have to worry
about are DIALOG_EXIT_FIELD, DIALOG_EXIT_LIST, and DIALOG_F10.
You can perform additional validation on the contents of a field when
the user wants to move to another field (DIALOG_EXIT_FIELD). After the
dialog manager has performed its built-in type checking on the field,
your action macro will be called. If your action macro returns FALSE
for any reason, the user will not be allowed to leave the field. You
can use a String field coupled with your own validation function to
check for almost any value. Lists are not validated, since all the
possible answers are known in advance.
When the user leaves a field or a list (DIALOG_EXIT_FIELD or
DIALOG_EXIT_LIST), keep track of the value of that input field. There
is no way to determine the value of an input field at any other time.
We recommend you use a separate buffer, where each line represents the
contents of one input field, for dialog boxes containing more than three
or four input fields; otherwise, use string variables to store the
current values.
Treat DIALOG_F10 as a signal that the user is satisfied with his or her
changes and wishes to save them. The current list or field will be
exited before DIALOG_F10 occurs. When it does, process the values you
have saved in your macro. (DIALOG_ESC and DIALOG_GREY_MINUS should just
ignore the saved values.)
EXAMPLE
This data file ("example") defines a dialog box containing two lists.
Text (1, 3) = "Do you want case-sensitive search?"
List (1, 38) = "(Yes)No"
Text (3, 3) = "Do you want regular expressions?"
List (3, 38) = "(Yes)No"
This macro puts up a dialog box containing the above information, and
defines two string variables which are used by the action macro. Both
variables are set to Yes, since the data file's defaults are Yes.
(macro put_up_box
(
(string case_sens
reg_exp
)
(global case_sens
reg_exp
)
(= case_sens "Yes")
(= reg_exp "Yes")
(_process_dialog_box 10 15 60 10 "Search" "Set search parameters"
"example" NULL "action")
)
)
The following macro will process the dialog box, and save the current
values when F10 is pressed:
(macro action
(
(int event_type
line_no
)
(string button_text)
(get_parm 0 event_type)
(switch event_type
DIALOG_EXIT_LIST
(
(get_parm 1 line_no)
(get_parm 2 button_text)
(if (== line_no 1)
(= case_sens button_text)
;else
(= reg_exp button_text)
)
)
DIALOG_F10
(
(search_case (if (== case_sens "Yes") 0 1))
(toggle_re (if (== reg_exp "Yes") 1 0))
)
)
(returns TRUE)
)
)
A more sophisticated macro could keep the data file in a buffer and
continuously alter it to make sure the correct values of case
sensitivity and regular expressions were always displayed.
That's all you need to know to design menus and dialog boxes in the
BRIEF macro language. Enjoy.
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
echo off
rem Very basic macro to make the compile/correct task easier. Uses the errorfix
rem macro to locate errors after an unsucessful compile, then attempts to
rem compile again. Note the invocation of brief with the -m option.
if .%1 == . goto usage
:loop
if .%1 == . goto exit
if not exist %1.c goto again
if exist %1 goto usage
cc -c %1.c >%1.err
if errorlevel 1 goto error
del %1.err
goto again
:error
b %1.c -mnext_error
goto loop
:again
shift
goto loop
:usage
echo Usage: gencc filenames... (no .c)
:exit
+13
View File
@@ -0,0 +1,13 @@
Overview ;display_help "basic concepts"
Insert/Overstrike Mode ;display_help "insert_mode"
Typing Keys ;display_help "self_insert"
File Name Completion ;display_help "completion"
History ;display_help "history"
Undo and Escape ;display_help "undo"
Quote a Key ;display_help "quote"
Tabs ;display_help "tabs"
New Lines ;display_help "newlines"
Delete ;display_help "deleting"
Delete Word ;display_help "delete_previous_word"
Delete/Join Line ;display_help "deleting lines"
Delete to End of Line ;display_help "delete_to_eol"
+10
View File
@@ -0,0 +1,10 @@
Block Concepts ;display_help "blocks"
Mark ;display_help "marking"
Delete and Cut ;display_help "cut"
Copy ;display_help "copy"
Paste ;display_help "paste"
Write ;display_help "writing"
Print ;display_help "printing"
Search ;display_help "searching blocks"
Indent ;display_help "indenting blocks"
Change Case ;display_help "case conversion"
+10
View File
@@ -0,0 +1,10 @@
Buffer Concepts ;display_help "buffers"
Editing ;display_help "editing"
Reading ;display_help "reading"
Naming ;display_help "file names"
Buffer List ;display_help "buffer list"
Change Buffer ;display_help "change buffer"
Writing ;display_help "writing"
Backup Files ;display_help "backups"
Delete Buffer ;display_help "delete buffer"
Delete File ;display_help "delete file"
+109
View File
@@ -0,0 +1,109 @@
Back Tab ;back_tab
Backspace ;backspace
Backup File Toggle ;set_backup
Beginning of Line ;_home
Block Search Toggle ;block_search
Borders Toggle ;borders
Brace Check ;brace
Buffer List ;buf_list
Case Sensitivity Toggle ;search_case
Center Line Horizontally ;center
Center Line in Window ;center_line
Change Directory ;cd
Change Output File ;output_file
Change Window ;change_window
Color ;color
Column Mark ;mark 2
Comment Block ;comment_block
Compile Buffer ;compile_it
Copy to Scrap ;copy
Create Key Assignment ;assign_to_key
Create Window ;create_edge
Cut to Scrap ;cut
Delete ;delete_char
Delete Current Buffer ;delete_curr_buffer
Delete File ;del
Delete Line ;delete_line
Delete Macro File ;delete_macro
Delete Next Word ;delete_next_word
Delete Previous Word ;delete_previous_word
Delete to End of Line ;delete_to_eol
Delete Window ;delete_edge
Display File Name ;display_file_name
Display Version ID ;version
Down ;down
Drop Bookmark ;drop_bookmark
Edit File ;edit_file
End of Buffer ;end_of_buffer
End of Line ;_end
End of Window ;end_of_window
Execute Command ;execute_macro
Exit ;exit
Go to Line ;goto_line
Go to Routine ;routines
Help ;help
Incremental Search ;i_search
Indent Block ;slide_in
Insert/Overstrike Toggle ;insert_mode
Insert Key Code ;key
Jump to Bookmark ;goto_bookmark
Keys ;keys
Left ;left
Left Side of Window ;left_side
Line Mark ;mark 3
Line to Bottom of Window ;to_bottom
Line to Top of Window ;to_top
Load Keystroke Macro ;load_keystroke_macro
Load Macro File ;load_macro
Lowercase Block ;tolower
Margin ;margin
Mark ;mark
Next Buffer ;edit_next_buffer
Next Character ;next_char
Next Error ;next_error
Next Word ;next_word
Noninclusive Mark ;mark 4
Open Line ;open_line
Outdent Block ;slide_out
Page Down ;page_down
Page Up ;page_up
Paste from Scrap ;paste
Pause on Error ;pause_on_error
Playback ;playback
Pop-Up Error Window ;next_error 1
Previous Buffer ;edit_prev_buffer
Previous Character ;prev_char
Previous Word ;previous_word
Print Block ;print
Quote ;quote
Read File into Buffer ;read_file
Reformat Paragraph ;reform
Regular Expression Toggle ;toggle_re
Remember ;remember
Repeat ;repeat
Resize Window ;move_edge
Right ;right
Right Side of Window ;right_side
Save Keystroke Macro ;save_keystroke_macro
Scroll Buffer Down in Window ;screen_down
Scroll Buffer Up in Window ;screen_up
Search Again ;search_again
Search Backward ;search_back
Search Forward ;search_fwd
Suspend BRIEF ;dos
Swap Cursor and Mark ;swap_anchor
Tab Stops ;tabs
Top of Buffer ;top_of_buffer
Top of Window ;top_of_window
Translate Again ;translate_again
Translate Backward ;translate_back
Translate Forward ;translate
Uncomment Block ;uncomment_block
Undo ;undo
Up ;up
Uppercase Block ;toupper
Use Tab Characters ;use_tab_char
Warnings Toggle ;warnings_only
Write ;write_buffer
Write Files and Exit ;write_and_exit
Zoom Window ;zoom_window
+9
View File
@@ -0,0 +1,9 @@
Character Movement ;display_help "character movement"
Word Movement ;display_help "word movement"
Line Movement ;display_help "line movement"
Window Movement ;display_help "window movement"
Buffer Movement ;display_help "buffer movement"
Scroll by Line ;display_help "scrolling by line"
Scroll by Page ;display_help "scrolling by page"
Drop Bookmark ;display_help "drop_bookmark"
Go to Bookmark ;display_help "goto_bookmark"
+13
View File
@@ -0,0 +1,13 @@
Help on Help ;display_help "help"
Quick Reference ;display_help "keyboard layout"
Key-Specific Help ;key_specific_help
Basic Concepts ;process_help_menu "Basic" "basic.mnu"
Blocks ;process_help_menu "Blocks" "block.mnu"
Buffers ;process_help_menu "Buffers" "buffers.mnu"
Cursor Movement ;process_help_menu "Movement" "cursor.mnu"
Keys and Commands ;process_help_menu "Keys" "keys.mnu"
Mouse ;process_help_menu "Mouse" "mouse.mnu"
Miscellaneous ;process_help_menu "Misc" "misc.mnu"
Packages ;process_help_menu "Packages" "packages.mnu"
Search/Translate ;process_help_menu "Search" "search.mnu"
Windows ;process_help_menu "Windows" "windows.mnu"
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
Overview ;display_help "keys and commands"
Responding to Prompts ;display_help "file name completion"
Execute Command ;display_help "execute"
Remember ;display_help "remember"
Playback ;display_help "playback"
Load Keystroke Macro ;display_help "load_keystroke_macro"
Save Keystroke Macro ;display_help "save_keystroke_macro"
Repeat ;display_help "repeat"
Keys ;display_help "keys"
Change Key Assignment ;display_help "assign_to_key"
Insert Key Code ;display_help "key codes"
Load Macro File ;display_help "load_macro"
Delete Macro File ;display_help "delete_macro"
Debugging Macros ;display_help "macro_debugger"
+5
View File
@@ -0,0 +1,5 @@
Load Macro File ;display_help "load_macro"
Delete Macro File ;display_help "delete_macro"
Language Packages ;display_help "languages"
Compiling ;display_help "compiling"
Word Processing ;display_help "word processing"
+9
View File
@@ -0,0 +1,9 @@
Automatic File Save ;display_help "autosave"
Change Drive/Directory ;display_help "change directory"
Cursor Shape ;display_help "cursor shapes"
Exit BRIEF ;display_help "exit"
File Name Completion ;display_help "completion"
History ;display_help "history"
Pause Error Messages ;display_help "pausing errors"
Run DOS Commands ;display_help "suspend"
Undo and Escape ;display_help "undo"
+7
View File
@@ -0,0 +1,7 @@
Basic Concepts ;display_help "mouse basic"
Button Assignments;display_help "mouse buttons"
Cursor Positioning;display_help "mouse cursor"
Marking ;display_help "mouse marking"
Pop-Up Menu ;display_help "mouse popup menu"
Scrolling ;display_help "mouse scrolling"
Windows ;display_help "mouse windows"
+6
View File
@@ -0,0 +1,6 @@
Language Packages ;display_help "languages"
Brace Checking ;display_help "brace matching"
Compiling ;display_help "compiling"
Error Location ;display_help "error location"
Procedure Location ;display_help "routines"
Word Processing ;display_help "word processing"
+10
View File
@@ -0,0 +1,10 @@
Copy ;copy
Cut ;cut
Paste ;paste
Buffers ;buf_list 1
Copy & Append ;copy 1
Cut & Append ;cut 1
Delete ;delete_char
Help ;help
QuickHelp ;qh
Routines ;routines
+10
View File
@@ -0,0 +1,10 @@
Copy ;copy
Cut ;cut
Paste ;paste
Buffers ;buf_list 1
Copy & Append ;copy 1
Cut & Append ;cut 1
Delete ;delete_char
Help ;help
QuickHelp ;qh
Routines ;routines
+7
View File
@@ -0,0 +1,7 @@
Search Concepts ;display_help "searching"
Regular Expressions ;display_help "regular expressions"
Case Sensitivity ;display_help "case sensitivity"
Search ;display_help "search"
Translate ;display_help "translate"
Repeat ;display_help "searching again"
Incremental Search ;display_help "incremental search"
+26
View File
@@ -0,0 +1,26 @@
[edit-]
screen=80 50
toggles=1 1 0 1 0 0
srch=
src=
rpl=
file=c:\brief\help\help.mnu 1 1 25 5
[brief]
file=c:\brief\help\help.mnu 1 1 25 5 1 47 78 1 c=0
file=c:\brief\help\keys.mnu 1 1 1 1
file=c:\brief\help\macros.mnu 1 1 1 1
file=c:\brief\help\misc.mnu 1 1 1 1
file=c:\brief\help\mouse.mnu 1 1 1 1
file=c:\brief\help\packages.mnu 1 1 1 1
file=c:\brief\help\popup.mnu 1 1 1 3
file=c:\brief\help\search.mnu 1 1 1 1
file=c:\brief\help\snmk0.mnu 1 1 1 1
file=c:\brief\help\windows.mnu 1 1 1 1
file=c:\brief\help\basic.mnu 1 1 1 1
file=c:\brief\help\block.mnu 1 1 1 1
file=c:\brief\help\buffers.mnu 1 1 1 1
file=c:\brief\help\commands.mnu 1 1 1 1
file=c:\brief\help\cursor.mnu 1 1 1 1
[shared-]
pmark=c:\brief\help\help.mnu 25 5

+8
View File
@@ -0,0 +1,8 @@
Window Concepts ;display_help "windows"
Create ;display_help "splitting"
Resize ;display_help "resizing"
Change ;display_help "switching"
Delete ;display_help "removing"
Zoom ;display_help "zoom_window"
Borders ;display_help "borders"
Colors ;display_help "color"
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
echo off
rem Very basic macro to make the compile/correct task easier. Uses the errorfix
rem macro to locate errors after an unsucessful compile, then attempts to
rem compile again. Note the invocation of brief with the -m option.
if .%1 == . goto usage
:loop
if .%1 == . goto exit
if not exist %1.c goto again
if exist %1 goto usage
lc1 %1 >%1.err
if errorlevel 1 goto error
lc2 %1 >%1.err
if errorlevel 1 goto error
del %1.err
goto again
:error
b %1.c -mnext_error
goto loop
:again
shift
goto loop
:usage
echo Usage: lcc filenames... (no .c)
:exit
+14
View File
@@ -0,0 +1,14 @@
Rye bread
Corned beef
Sauerkraut
Swiss cheese
Mustard
Bandersnatch repellent
beef tea
The Dancing Beef Tearoom
Mini-Eggs
Stoned wheat thins
Orangina
Lion bars
Mocha chip ice cream
More lion bars
+884
View File
@@ -0,0 +1,884 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
**
** History:
** 12/10/90 Jim Rodriquez - move assign_to_keys from _init macro
** to smart_first macro to conserve
** memory.
*/
/*
**
** ada.cb:
**
** Smart indenting and template editing for ADA. This package
** works for files with the extensions .ada. Other languages
** extensions can be supported by SETUP or manual extension
** equivalence.
*/
#define FALSE 0
#define TRUE 1
#define MIN_ABBREV 1
#define ADA_SKIP_PAT "{{--*\n}|{\\<\\<[~<>\n]@\\>\\>}|[ \xc\t\n]}@"
/*
** Note: the "!" found after the two letter abbreviations (i.e. AG, DR,
** DG, etc) is an internal convention in order to ensure that the
** abbreviation's length is less than the completion length. Thus,
** the user does NOT have to type in the "!" to ensure the two letter
** abbreviations' expansions.
*/
#define ABBR_LIST_1 "~ACCEPT~ABORT~BEGIN~CASE~ELSE~ELSIF~EI!~ENTRY~EXCEPTION~EXIT~EXIT WHEN~EW!~FUNCTION~FOR~IF~LOOP~OR~PROCEDURE~"
#define ABBR_LIST_2 "~PACKAGE~PACKAGE BODY~PB!~PACKAGE IS NEW~PN!~RETURN~RECORD~SUBTYPE~SELECT~TYPE~TASK~TASK BODY~TB!~TERMINATE~"
#define ABBR_LIST_3 "~USE~WITH~WHEN~WHEN OTHERS~WO!~WHILE~"
#define KW_LIST "~ACCEPT~BEGIN~CASE~ELSE~ELSIF~FOR~FUNCTION~IF~LOOP~OR~PACKAGE~PROCEDURE~RECORD~SELECT~TASK~WHEN~WHILE~"
#define KW_LOWER 0
#define KW_UPPER 1
#define KW_MIXED 2
#define MAX_COL 20736
#define NEG_MAX_COL -20736
/*
** Function Prototypes
*/
extern void slide_in ();
extern void open_line ();
extern void back_tab ();
extern int .c_previous_word ();
extern int .c_next_word ();
string .ada_smart_first ();
string .ada_template_first (~int, ~int);
int .ada_indent_level (~int);
void .ada_indent (int);
void .ada_abbrev ();
void .ada_first_nonwhite ();
string .ada_keyword_cvt (string);
void .ada_reindent (string, int);
void .ada_expand_block (string);
void .ada_expand_pair (string);
void .ada_expand_full (string, string);
int .ada_next_word ();
int .ada_previous_word ();
/*
** Allocate the global variables and set up the keymaps.
*/
int _ada_smart,
_ada_template,
_ada_alt_template,
_ada_keyword_case,
_ada_min_abbrev;
/*
** Turn on smart indenting for ADA. This macro is designed to
** be run the first time a file is edited, but may also be run from
** the command line.
*/
string .ada_smart_first ()
{
if (first_time())
{
keyboard_push ();
assign_to_key ("<Enter>", ".ada_indent");
assign_to_key ("<Tab>", "slide_in");
assign_to_key ("<Shift-Tab>", "slide_out");
_ada_smart = inq_keyboard ();
keyboard_pop (1);
}
use_local_keyboard (_ada_smart);
returns ("");
}
/*
** Turn on template editing for ADA. This macro is designed to
** be run the first time a file is edited, but may also be run from
** the command line.
**
** Parameters:
** 0 -- the minimum length of abbreviations that should be expanded.
** If this is 0, abbreviations are only expanded when <Tab>
** is pressed. If it is 1, b<Space> will expand to a BEGIN/END
** block; if it is 2, you would need to type be<Space> in order
** to expand the template.
** 1 -- controls case of expanded keywords. If this is 0, r<Space>
** expands to "return"; if 1, it expands to "RETURN"; and if 2,
** it expands to "Return".
**
** Defaults: 1 0
*/
string .ada_template_first (~int, ~int)
{
_ada_min_abbrev = MIN_ABBREV;
_ada_keyword_case = KW_LOWER;
get_parm (0, _ada_min_abbrev);
get_parm (1, _ada_keyword_case);
if (first_time())
{
keyboard_push ();
assign_to_key ("<Enter>", ".ada_indent");
assign_to_key ("<Tab>", ".ada_abbrev");
assign_to_key ("<Shift-Tab>", "slide_out");
assign_to_key ("<Ctrl-s>", "just_space");
_ada_alt_template = inq_keyboard ();
keyboard_pop (1);
keyboard_push ();
assign_to_key ("<Enter>", ".ada_indent");
assign_to_key ("<Tab>", "slide_in");
assign_to_key ("<Shift-Tab>", "slide_out");
assign_to_key ("<Space>", ".ada_abbrev");
assign_to_key ("<Ctrl-s>", "just_space");
_ada_template = inq_keyboard ();
keyboard_pop (1);
}
if (_ada_min_abbrev == 0)
{
use_local_keyboard (_ada_alt_template);
_ada_min_abbrev = MIN_ABBREV;
}
else
use_local_keyboard (_ada_template);
returns ("");
}
/*
** These definitions are used as Ada "language sensitive" word patterns
*/
int .ada_next_word ()
{
returns (.c_next_word ());
}
int .ada_previous_word ()
{
returns (.c_previous_word ());
}
/*
** Maps between indent levels (in tab stops) and column positions in a
** file. Column 1 to just before the first tab stop is level 0; from
** the first to just before the second tab stop is level 1; etc.
**
** If a parameter is passed, we treat it as an indent level, and we
** calculate the column corresponding to it. Otherwise, we calculate
** the indent level corresponding to the current column.
*/
int .ada_indent_level (~int)
{
int curr_col,
lev_to_col,
level;
save_position ();
curr_col = 1;
if (get_parm (0, lev_to_col))
{
beginning_of_line ();
while (level < lev_to_col)
{
move_abs (0, curr_col += distance_to_tab ());
++level;
}
level = curr_col;
}
else
{
inq_position (NULL, lev_to_col);
beginning_of_line ();
while ((curr_col += distance_to_tab ()) <= lev_to_col)
{
move_abs (0, curr_col);
++level;
}
}
restore_position ();
returns (level);
}
/*
** .ada_indent:
**
** This macro does syntax-sensitive indenting ("smart indenting") for
** ADA language files.
**
** Parameters:
** 0 -- if TRUE, the line is reindented if necessary, but the line
** is never split, no newline is inserted, and the cursor is left
** at the end of the line.
*/
void .ada_indent (int scratch)
{
int curr_line, // Line cursor is on when called.
code_line, // Line where last code char is found.
code_indent_level, // Current indent level, in tab stops.
prev_indent_level, // Indent level of previous line.
code_trail, // The last code character.
prev_trail; // Last code char before code_line.
string following_string, // Remainder of line being split.
code_text, // Trimmed text of code line.
token, // Tokenized version of line.
prev_text, // Trimmed text of previous line.
prev_token; // First token on previous line.
/*
** Initialize.
*/
inq_position (curr_line, NULL);
code_trail = prev_trail = '\;';
/*
** If we're in overstrike mode, we act as if we were at the
** end of the line when the command was invoked.
**
** If we're in insert mode, we may have to split the line.
*/
if (!inq_mode ())
end_of_line ();
/*
** If line is being split, cut text to following_string.
** Leave all trailing whitespace except the newline.
*/
else if (read (1) != "\n")
{
following_string = ltrim (read ());
following_string = substr (following_string, 1, strlen (following_string) - 1);
delete_to_eol ();
}
/*
** Find the last "code" character; skip back over whitespace and
** comments until we get something different. The cursor will be
** left on the next character from the "different" one; we do a
** (prev_char) to get to the code character. (If it fails, we're
** at the top of the buffer.)
*/
search_back (ADA_SKIP_PAT, -2);
/*
** Remember which line we found the code character on. Classify
** the code character by looking it up in a string, and save
** a "tokenized" version of the whole line.
*/
if (prev_char ())
{
/*
** We save the identity of the last code character on
** the "code line".
*/
inq_position (code_line);
code_trail = atoi (read (1), 0);
/*
** Find the first non-white character on the line, so
** we may determine its indenting level. Save the
** text of the line for later parsing.
*/
.ada_first_nonwhite ();
code_indent_level = .ada_indent_level ();
code_text = trim (read ());
/*
** Find the last code line before this, as well as its
** last code character and whether or not it contains
** ADA keywords that affect indenting.
*/
if (up ())
{
end_of_line ();
if (search_back (ADA_SKIP_PAT, -2) && prev_char ())
{
prev_trail = atoi (read (1), 0);
.ada_first_nonwhite ();
prev_indent_level = .ada_indent_level ();
prev_text = trim (read ());
/*
** Get the first token on the previous line.
*/
prev_token = upper (substr (prev_text, 1, index (prev_text + " ", " ") - 1));
}
}
/*
** Get the first token on the code line. This assumes
** that tokens are separated by spaces.
*/
token = upper (substr (code_text, 1, index (code_text + " ", " ") - 1));
}
/*
** Move to the beginning of the line the cursor was originally on.
** Occasionally, we have to adjust its indent level. However,
** if the line contains no code, we don't need to worry about it.
*/
move_abs (curr_line, 1);
if (code_line == curr_line)
{
code_line = prev_indent_level;
switch (token)
{
/*
** If the last token on the previous line was IS, we align
** a BEGIN with that line. If not, we outdent the BEGIN
** one level.
*/
case "BEGIN":
if ("IS" != upper (substr (prev_text, rindex (" " + prev_text, " "))))
--code_line;
/*
** ELSE should be outdented one level from the
** previous line, unless the last line was a clause
** like "IF x THEN y;".
*/
case "ELSE":
case "ELSIF":
if (!((prev_token == "IF" || prev_token == "ELSIF") && prev_trail == ';'))
--code_line;
/*
** END should usually be outdented one level from the
** previous line. Exceptions are at the end of a CASE
** statement, when we have to outdent two levels,
** and at the end of any block with no intervening
** indented text, when we want to stay put. (We guess
** that a line beginning with any of certain keywords
** and ending with a semicolon is a block of the form
** "IF x THEN y;").
*/
case "END;":
case "END":
{
if (!(index (KW_LIST, "~" + (prev_token + "~")) && prev_trail == ';'))
if (index (upper (substr (code_text, 5)), "CASE") && prev_token != "WHEN")
code_line -= 2;
else
--code_line;
code_trail = '\;';
}
/*
** If the previous line began with CASE or EXCEPTION,
** we indent the code line one level from it. If the
** previous line began with WHEN, we align the lines.
** Otherwise, we outdent the code line one level.
*/
case "WHEN":
switch (prev_token)
{
case "CASE":
case "EXCEPTION":
++code_line;
case "WHEN":
nothing ();
default:
--code_line;
}
/*
** OR should always be outdented. Maybe EXCEPTION should as well.
*/
case "OR":
case "EXCEPTION":
--code_line;
default:
code_line = code_indent_level;
}
/*
** Reindent only when necessary.
*/
if (code_indent_level != code_line)
.ada_reindent (code_text, code_indent_level = code_line);
}
/*
** Check the parameter. If it's TRUE, we put the line back
** together and return.
*/
if (scratch)
{
end_of_line ();
if (following_string != "")
insert (following_string);
return;
}
/*
** Move to the next line, inserting a new line below the current
** one if in insert mode.
*/
if (inq_mode ())
{
end_of_line ();
insert ("\n");
}
else
down ();
if (code_indent_level < 0)
code_indent_level = 0;
/*
** We indent the cursor unless the code line ended in a semicolon.
*/
if (code_trail != '\;')
++code_indent_level;
/*
** Move to the new position.
**
** If we cut characters from the previous line, reinsert them.
*/
move_abs (0, .ada_indent_level (code_indent_level));
if (following_string != "")
{
save_position ();
insert (following_string);
restore_position ();
}
}
/*
** .ada_abbrev:
**
** This macro performs template expansion for ADA. When it is
** invoked, the characters before the cursor are checked to see if
** they are the start of a ADA keyword, preceded by a space or a
** tab, and followed only by whitespace. If a match is found, the
** remainder of the statement is filled in automatically.
**
** Expansion is only done when we're at or past the end of the
** line, and when the line is less than 10 characters long. This
** makes expansion faster and avoids unwanted expansion.
*/
void .ada_abbrev ()
{
int done; // index into keywords lists
/*
** Expand only when we're at the end of the line.
*/
if (read (1) == "\n")
{
int loc;
string line,
which_abbrev;
/*
** Get a trimmed representation of the line into a string.
*/
save_position ();
beginning_of_line ();
loc = strlen (line = (upper (trim (ltrim (read ())))));
/*
** Only do template expansion if the trimmed version
** of the line is at least _ada_min_abbrev characters long,
** at most 10 characters long, matches an expansion in
** one of the ABBR_LISTs, and is shorter than that token.
** We do all comparisons in upper case.
**
*/
if (done = index (ABBR_LIST_1, "~" + line))
which_abbrev = ABBR_LIST_1;
else if (done = index (ABBR_LIST_2, "~" + line))
which_abbrev = ABBR_LIST_2;
else if (done = index (ABBR_LIST_3, "~" + line))
which_abbrev = ABBR_LIST_3;
if ((loc <= 10) && (loc >= _ada_min_abbrev) && loc && done)
{
string completion;
/*
** Extract the full, expanded keyword from the
** abbreviation list, and make sure it's longer
** than the abbreviation.
*/
completion = substr (which_abbrev, ++done);
completion = substr (completion, 1, index (completion, "~") - 1);
if (loc < strlen (completion))
{
/*
** Delete the abbreviation from the buffer, and
** replace it with the expanded version.
*/
.ada_first_nonwhite ();
delete_to_eol ();
/*
** Insert necessary context for each keyword.
*/
switch (completion)
{
case "ABORT":
case "EXIT":
case "TERMINATE":
{
insert (.ada_keyword_cvt (completion));
insert (";");
}
case "RETURN":
case "USE":
case "WITH":
{
insert (.ada_keyword_cvt (completion));
insert (" ;");
}
case "ACCEPT":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_full ("END ;", "DO");
}
case "BEGIN":
case "EXCEPTION":
{
insert (.ada_keyword_cvt (completion));
open_line ();
}
case "CASE":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_full ("END CASE;", "IS");
}
case "ELSE":
case "OR":
{
insert (.ada_keyword_cvt (completion));
.ada_indent (1);
open_line ();
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "WHEN OTHERS":
case "WO!":
{
insert (.ada_keyword_cvt ("WHEN OTHERS =>"));
.ada_indent (1);
open_line ();
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "EI!":
case "ELSIF":
{
insert (.ada_keyword_cvt ("ELSIF"));
.ada_indent (1);
.ada_expand_pair ("THEN");
}
case "FOR":
case "WHILE":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_full ("END LOOP;", "LOOP");
}
case "FUNCTION":
case "PROCEDURE":
{
insert (.ada_keyword_cvt (completion));
save_position ();
.ada_expand_block ("END ;");
back_tab ();
insert (.ada_keyword_cvt ("BEGIN"));
restore_position ();
.ada_expand_pair ("IS");
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "TASK BODY":
case "TB!":
{
insert (.ada_keyword_cvt ("TASK BODY"));
save_position ();
.ada_expand_block ("END ;");
back_tab ();
insert (.ada_keyword_cvt ("BEGIN"));
restore_position ();
.ada_expand_pair ("IS");
}
case "IF":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_full ("END IF;", "THEN");
}
case "LOOP":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_block ("END LOOP;");
}
case "PACKAGE":
case "TASK":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_full ("END ;", "IS");
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "PACKAGE BODY":
case "PB!":
{
insert (.ada_keyword_cvt ("PACKAGE BODY"));
.ada_expand_full ("END ;", "IS");
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "PACKAGE IS NEW":
case "PN!":
{
insert (.ada_keyword_cvt ("PACKAGE IS NEW ;"));
prev_char (9);
}
case "RECORD":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_block ("END RECORD;");
}
case "SELECT":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_block ("END SELECT;");
}
case "SUBTYPE":
case "TYPE":
{
insert (.ada_keyword_cvt (completion));
.ada_expand_pair ("IS");
}
case "WHEN":
{
insert (.ada_keyword_cvt (completion));
.ada_indent (1);
.ada_expand_pair ("=>");
}
/*
** Note: the "!" is an internal convention to ensure
** that the abbreviation length is less than the
** completion length.
*/
case "EW!":
{
insert (.ada_keyword_cvt ("EXIT WHEN"));
insert (" ");
}
default:
{
insert (.ada_keyword_cvt (completion));
insert (" ");
}
}
done = strlen (completion);
}
else
done = FALSE;
}
else
done = FALSE;
restore_position (!done);
}
/*
** If we couldn't expand an abbreviation, we perform the
** normal task associated with the key that called us: insert
** a space, or shift a marked block.
*/
if (!done)
if (inq_local_keyboard () == _ada_alt_template)
slide_in ();
else
self_insert ();
}
/*
** Moves the cursor to the first character on the current line that
** is not a space or a tab.
*/
void .ada_first_nonwhite ()
{
beginning_of_line ();
next_char (strlen (read ()) - strlen (ltrim (read ())));
}
/*
** Converts keywords into the user-specified preferred case. If the
** case is MIXED, the first separate letter of each "word" in the
** keyword string is converted to upper case, and the others are
** converted to lower case.
*/
string .ada_keyword_cvt (string keyword)
{
switch (_ada_keyword_case)
{
case KW_UPPER:
returns (upper (keyword));
case KW_LOWER:
returns (lower (keyword));
case KW_MIXED:
{
int space;
string retval;
keyword = lower (keyword);
while (space = index (keyword, " "))
{
retval += upper (substr (keyword, 1, 1));
retval += substr (keyword, 2, space - 1);
keyword = substr (keyword, ++space);
}
retval += upper (substr (keyword, 1, 1));
returns (retval += substr (keyword, 2));
}
}
}
/*
** Repositions a line at a specified indent level.
**
** Parameters:
** 0 -- the text of the line to reindent.
** 1 -- the new indent level.
*/
void .ada_reindent (string text, int curr_indent_level)
{
beginning_of_line ();
delete_to_eol ();
move_abs (0, .ada_indent_level (curr_indent_level));
insert (text);
}
/*
** Adds a matching keyword below the expanded template, at the same
** indent level; then inserts a line between the pair and leaves the
** cursor on it. Since inserting a line may reindent the current
** line, it does this in a strange order.
*/
void .ada_expand_block (string keyword)
{
int column;
open_line ();
save_position ();
move_rel (-1, NEG_MAX_COL);
.ada_first_nonwhite ();
inq_position (NULL, column);
move_rel (1, NEG_MAX_COL);
insert ("\n");
move_abs (0, column);
insert (.ada_keyword_cvt (keyword));
restore_position ();
}
/*
** Expands a keyword pair, positioning the cursor between the two
** keywords.
*/
void .ada_expand_pair (string keyword)
{
save_position ();
insert (" " + .ada_keyword_cvt (keyword));
restore_position ();
right ();
}
/*
** Expands a keyword block with a paired keyword on the first line.
*/
void .ada_expand_full (string keyword1, string keyword2)
{
save_position ();
.ada_expand_block (keyword1);
delete_line ();
restore_position ();
.ada_expand_pair (keyword2);
}

Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
;** External macro declarations
(extern autosave
toggle_re
)
;** Initials Macro
(macro AG
(
(color 0 7 15 7 15) ;** Set the screen colors
(autosave) ;** Automatic file save when idle
)
)
;** File Extension Macros
(macro default
(
(tabs 9 17)
)
)
Binary file not shown.
+64
View File
@@ -0,0 +1,64 @@
;** _init macro.
;** Do not change this macro (always overwritten by Setup).
(macro _init
(
(extern autosave ;** External macro declarations
toggle_re
)
(color 1 14 12 10 13 0x80) ;** Set the screen colors
(autosave) ;** Automatic file save when idle
(set_mouse_type 3 0) ;** Set number of mouse buttons, button one location
(set_ctrl_state 0 1) ;** Enable close button
(set_ctrl_state 1 1) ;** Enable zoom button
(set_ctrl_state 2 1) ;** Enable vertical scroll bar
(set_ctrl_state 3 1) ;** Enable horizontal scroll bar
(set_mouse_action "_mouse_action") ;** Set mouse action macro
(set_btn2_action 1) ;** Set default action for mouse button two
)
)
;** Initials Macro
;** Initials macro.
;** Use this macro for additional customization.
(macro AG
(
;** Put your changes here.
(return)
)
)
;** File Extension Macros, etc.
;** Macros marked "Overwritable" may be overwritten by SETUP.
;** File Extension Macros
;** Overwritable by Setup
(macro default
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .asm
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .c
(
(tabs 4 7)
)
)
;** Overwritable by Setup
(macro .pds
(
(tabs 9 17)
)
)
+20
View File
@@ -0,0 +1,20 @@
;** External macro declarations
(extern autosave
toggle_re
)
;** Initials Macro
(macro AG
(
(color 0 7 15 7 15) ;** Set the screen colors
(autosave) ;** Automatic file save when idle
)
)
;** File Extension Macros
(macro default
(
(tabs 9 17)
)
)
+19
View File
@@ -0,0 +1,19 @@
;** External macro declarations
(extern autosave
toggle_re
)
;** Initials Macro
(macro AG
(
(color 0 7 15 7 15) ;** Set the screen colors
)
)
;** File Extension Macros
(macro default
(
(tabs 9 17)
)
)
+20
View File
@@ -0,0 +1,20 @@
;** External macro declarations
(extern autosave
toggle_re
)
;** Initials Macro
(macro AG
(
(color 0 7 15 7 15) ;** Set the screen colors
(autosave) ;** Automatic file save when idle
)
)
;** File Extension Macros
(macro default
(
(tabs 9 17)
)
)
+312
View File
@@ -0,0 +1,312 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** autosave.cb:
**
** This macro implements a simple autosave feature using the BRIEF
** idle action registered macro facility. Every time the user is idle
** for the amount of time specified by -i<num>, the buffer list is checked
** and modified files are automatically written to disk as "filename.asv"
** (stands for AutoSaVe).
**
** Autosaving can be forced after a number of minutes by passing the
** number of minutes between forced autosaves to the autosave macro. Note
** that this type of autosave can not be interrupted, and could become quite
** annoying if the value is too low.
*/
string escape_re (string original, ~string);
int force_autosave, // Whether or not we should save unmodified files.
save_buf, // Buffer that stores saved names.
last_idle_save, // Last idle time we saved.
last_save_time, // Last real time we saved.
last_save_day; // Last day we saved (to deal with rollover).
void autosave (~int)
{
int hours,
minutes;
register_macro (4, "save_files");
get_parm (0, force_autosave);
date (NULL, NULL, last_save_day);
time (hours, minutes);
last_save_time = minutes + (hours * 60);
}
/*
** save_files:
**
** This macro loops through the buffer list, writing all of the modified
** buffers. Note that a special buffer is created to keep track of the
** autosaved files.
*/
void save_files ()
{
int curr_buf,
old_buf,
saved,
do_autosave,
force_save,
hours,
minutes,
day;
date (NULL, NULL, day);
time (hours, minutes);
force_save = force_autosave && (minutes + ((hours + (day != last_save_day ? 24 : 0)) * 60)) - last_save_time >= force_autosave;
if (inq_idle_time () < last_idle_save)
last_idle_save = 0;
if (force_save || inq_idle_time () > inq_idle_default () && last_idle_save == 0)
{
last_idle_save = inq_idle_time ();
curr_buf = inq_buffer ();
/*
** This loop goes through the buffer list, and stops when
** all non-system buffers have been checked.
**
** Note that if this is an idle save and the user starts
** typing, the loop stops. This prevents the autosave from
** continuing when the user has made the transition from an
** idle to a non-idle state.
**
** If this is a forced save, all buffers are saved before
** stopping.
*/
while (!(curr_buf == old_buf || !force_save && inq_kbd_char ()))
{
if (!old_buf)
old_buf = curr_buf;
if (inq_modified () && !inq_system ())
{
/*
** If the current buffer is modified, and is not a system
** buffer, we have to write it to disk.
*/
string full_name,
just_name,
extension;
inq_names (full_name, extension, just_name);
if (strlen (extension))
full_name = substr (full_name, 1, rindex (full_name, "." + extension) - 1);
save_position ();
top_of_buffer ();
drop_anchor (3);
if (!save_buf)
{
set_buffer (save_buf = create_buffer ("Autosaves", NULL, 1));
delete_line ();
register_macro (5, "save_exit");
}
else
set_buffer (save_buf);
top_of_buffer ();
/*
** If the file has been autosaved already, we
** have some additional work to do.
*/
if (search_fwd (escape_re (full_name) + ".as[v0-9]\xff" + escape_re (extension) + "\n"))
{
full_name = read ();
full_name = substr (full_name, 1, index (full_name, "\xff") - 1);
/*
** If this is a forced save, we do it
** whether the files are the same or not.
*/
if (force_save)
{
del (full_name);
++do_autosave;
}
else
{
int comp_buf,
done;
string line_1,
line_2;
/*
** At this point, we know the file has
** been saved once before. Here, we check
** to see if the file has actually been
** modified since the last autosave. This
** is done by performing a line-by-line
** comparison of the two files. Note that
** this comparison (and the entire autosave)
** is aborted if the users starts typing.
*/
if (comp_buf = create_buffer ("Save Comp", full_name, 1))
{
while (!(inq_kbd_char () || done))
{
set_buffer (curr_buf);
/*
** If we're past the end of the
** file, we use the null string rather
** than the newline character that read
** usually returns. If this wasn't
** done, files with newline characters
** at their ends would match files
** that were essentially the same but
** shorter.
*/
if (inq_position ())
line_1 = "";
else
{
line_1 = read ();
move_rel (1, 0);
}
set_buffer (comp_buf);
if (inq_position ())
line_2 = "";
else
{
line_2 = read ();
move_rel (1, 0);
}
done += line_1 != line_2 || line_1 == "";
}
set_buffer (curr_buf);
delete_buffer (comp_buf);
/*
** We want to actually perform the save
** if the users hasn't typed anything and
** the last lines compared didn't match.
*/
if (!inq_kbd_char () && line_1 != line_2)
{
++do_autosave;
/*
** We delete the previously saved
** file at this point. If we didn't,
** a backup file could be created.
*/
del (full_name);
}
}
}
}
else
{
/*
** To avoid problems with buffers that have the same base name
** but multiple extensions, we check to see if we've already saved
** a buffer with the intended autosave filename. If so, we construct
** a new extension using a number as the last character. This
** method handles up to ten different files in the same directory
** with the same base name, which will, hopefully, be plenty.
*/
int save_pass;
do
{
top_of_buffer ();
}
while (search_fwd (full_name + ".as" + substr ("v1234567890", ++save_pass, 1) + "\xff", 0));
full_name += ".as" + substr ("v1234567890", save_pass, 1);
insert (full_name + "\xff" + extension + "\n");
++do_autosave;
}
if (do_autosave)
{
++saved;
set_buffer (curr_buf);
message ("Autosaving %s...", just_name);
end_of_buffer ();
if (write_block (full_name) <= 0)
raise_anchor ();
--do_autosave;
}
else
raise_anchor ();
restore_position ();
}
/*
** When we go to the next buffer, we ask next buffer for
** all of the buffers, not just non-system. This way, if we
** started with a system buffer, we don't infinite loop.
*/
set_buffer (curr_buf = next_buffer (1));
}
if (old_buf)
set_buffer (old_buf);
if (force_save || saved)
{
if (force_save || !inq_kbd_char ())
{
last_save_day = day;
last_save_time = minutes + hours * 60;
}
if (saved)
message ("Autosave complete.");
}
}
}
/*
** save_exit:
**
** This routine is called just before BRIEF is going to exit for real.
** At that time, all of the autosaved files are deleted from the disk
** since they are no longer needed.
*/
void save_exit (void)
{
if (save_buf)
{
string name;
int old_buf = set_buffer (save_buf);
top_of_buffer ();
while (!inq_position ())
{
name = read ();
del (substr (name, 1, index (name, "\xff") - 1));
down ();
}
set_buffer (old_buf);
}
unregister_macro (4, "save_files");
}
Binary file not shown.
+315
View File
@@ -0,0 +1,315 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;**
;** autosave.m:
;**
;** This macro implements a simple autosave feature using the BRIEF
;** idle action registered macro facility. Every time the user is idle
;** for the amount of time specified by -i<num>, the buffer list is checked
;** and modified files are automatically written to disk as "filename.asv"
;** (stands for AutoSaVe).
;**
;** Autosaving can be forced after a number of minutes by passing the
;** number of minutes between forced autosaves to the autosave macro. Note
;** that this type of autosave can not be interrupted, and could become quite
;** annoying if the value is too low.
;**
;** Revision history:
;** -----------------
;**
(macro autosave
(
(int force_autosave
save_buf
last_idle_save
last_save_time
last_save_day
hours
minutes
)
(global force_autosave
save_buf
last_idle_save
last_save_time
last_save_day
)
(register_macro 4 "save_files")
(register_macro 5 "save_exit")
(get_parm 0 force_autosave)
(date NULL NULL last_save_day)
(time hours minutes)
(= last_save_time (+ minutes (* hours 60)))
)
)
;**
;** save_files:
;**
;** This macro loops through the buffer list, writing all of the modified
;** buffers. Note that a special buffer is created to keep track of the
;** autosaved files.
;**
(macro save_files
(
(int curr_buf
old_buf
saved
do_autosave
force_save
hours
minutes
day
)
(date NULL NULL day)
(time hours minutes)
(= force_save (&& force_autosave (>= (- (+ minutes (* (+ hours (if (!= day last_save_day) 24 0)) 60)) last_save_time) force_autosave)))
(if (< (inq_idle_time) last_idle_save)
(= last_idle_save 0)
)
(if (|| force_save (&& (> (inq_idle_time) (inq_idle_default)) (== last_idle_save 0)))
(
(= last_idle_save (inq_idle_time))
(= curr_buf (inq_buffer))
;**
;** This loop goes through the buffer list, and stops when
;** all non-system buffers have been checked.
;**
;** Note that if this is an idle save and the users starts
;** typing, the loop stops. This prevents the autosave from
;** continuing when the user has made the transition from an
;** idle to a non-idle state.
;**
;** If this is a forced save, all buffers are saved before
;** stopping.
;**
(while (! (|| (== curr_buf old_buf) (&& (! force_save) (inq_kbd_char))))
(
(if (! old_buf)
(= old_buf curr_buf)
)
(if (&& (inq_modified) (! (inq_system)))
(
;**
;** If the current buffer is modified, and is not a system
;** buffer, we have to write it to disk.
;**
(string name
extension
)
(inq_names name extension)
(if (strlen extension)
(= name (substr name 1 (- (rindex name (+ "." extension)) 1)))
)
(+= name ".asv")
(inq_names NULL NULL extension)
(save_position)
(top_of_buffer)
(drop_anchor 3)
(if (! save_buf)
(= save_buf (create_buffer "Autosaves" NULL 1))
)
(set_buffer save_buf)
(top_of_buffer)
;**
;** If the file has been autosaved already, we
;** have some additional work to do.
;**
(if (search_fwd name 0)
(
;**
;** If this is a forced save, we do it
;** whether the files are the same or not.
;**
(if force_save
(
(del name)
(++ do_autosave)
)
;else
(
(int comp_buf
done
)
(string line_1
line_2
)
;**
;** At this point, we know the file has
;** been saved once before. Here, we check
;** to see if the file has actually been
;** modified since the last autosave. This
;** is done by performing a line-by-line
;** comparison of the two files. Note that
;** this comparison (and the entire autosave)
;** is aborted if the users starts typing.
;**
(if (= comp_buf (create_buffer "Save Comp" name 1))
(
(while (! (|| (inq_kbd_char) done))
(
(set_buffer curr_buf)
;**
;** If we're past the end of the
;** file, we use the null string rather
;** than the newline character that read
;** usually returns. If this wasn't
;** done, files with newline characters
;** at their ends would match files
;** that were essentially the same but
;** shorter.
;**
(if (inq_position)
(= line_1 "")
;else
(
(= line_1 (read))
(move_rel 1 0)
)
)
(set_buffer comp_buf)
(if (inq_position)
(= line_2 "")
;else
(
(= line_2 (read))
(move_rel 1 0)
)
)
(+= done (|| (!= line_1 line_2) (== line_1 "")))
)
)
(set_buffer curr_buf)
(delete_buffer comp_buf)
;**
;** We want to actually perform the save
;** if the users hasn't typed anything and
;** the last lines compared didn't match.
;**
(if (&& (! (inq_kbd_char)) (!= line_1 line_2))
(
(++ do_autosave)
;**
;** We delete the previously saved
;** file at this point. If we didn't,
;** a backup file could be created.
;**
(del name)
)
)
)
)
)
)
)
;else
(
(insert (+ name "\n"))
(++ do_autosave)
)
)
(if do_autosave
(
(++ saved)
(set_buffer curr_buf)
(message "Autosaving %s..." extension)
(end_of_buffer)
(if (< (write_block name) 0)
(raise_anchor)
)
(-- do_autosave)
)
;else
(raise_anchor)
)
(restore_position)
)
)
;**
;** When we go to the next buffer, we ask next buffer for
;** all of the buffers, not just non-system. This way, if we
;** started with a system buffer, we don't infinite loop.
;**
(= curr_buf (set_buffer (next_buffer 1)))
)
)
(if old_buf
(set_buffer old_buf)
)
(if (|| force_save saved)
(
(if (|| force_save (! (inq_kbd_char)))
(
(= last_save_day day)
(= last_save_time (+ minutes (* hours 60)))
)
)
(if saved
(message "Autosave complete.")
)
)
)
)
)
)
)
;**
;** save_exit:
;**
;** This routine is called just before BRIEF is going to exit for real.
;** At that time, all of the autosaved files are deleted from the disk
;** since they are no longer needed.
;**
(macro save_exit
(
(string name)
(int old_buf)
(if save_buf
(
(= old_buf (inq_buffer))
(set_buffer save_buf)
(top_of_buffer)
(while (! (inq_position))
(
(= name (read))
(del (substr name 1 (- (strlen name) 1)))
(move_rel 1 0)
)
)
(set_buffer old_buf)
)
)
)
)
+849
View File
@@ -0,0 +1,849 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
**
** History:
** 12/10/90 Jim Rodriquez - move assign_to_keys from _init macro
** to smart_first macro to conserve
** memory.
*/
/*
**
** basic.cb:
**
** Smart indenting and template editing for BASIC.
**
*/
#define FALSE 0
#define TRUE 1
#define MIN_ABBREV 1
/*
** This pattern treats REM statements as code for efficiency, since they
** tend to be at the same indenting level as the surrounding code.
** However, comments beginning with a single quote are skipped over
** in figuring the indenting level, as are line identifiers.
*/
#define BAS_SKIP_PAT "{{<[ \xc\t]@{[A-Z0-9!#$%]+[ \t]@:}|{[0-9]+}}|{'[~\"\n]@}|[ \xc\t\n]}@"
#define ABBR_LIST "~CASE~DEF FN~ELSE~EI~ELSEIF~EXIT~FOR~FUNCTION~IF~ON~ON ERROR GOTO~RETURN~SELECT CASE~SUB~WHILE~"
#define KW_LOWER 0
#define KW_UPPER 1
#define KW_MIXED 2
#define MAX_COL 20736
#define NEG_MAX_COL -20736
extern void slide_in ();
extern void open_line ();
extern int .c_previous_word ();
extern int .c_next_word ();
/*
** Function Prototypes
*/
string .bas_smart_first (~int, ~int, ~int);
string .bas_template_first (~int, ~int, ~int, ~int);
int .bas_indent_level (~int);
void .bas_first_nonwhite ();
int .bas_outdent_to_match (string, int, string);
void .bas_indent (~int);
void .bas_abbrev ();
void .bas_reindent (int);
void .bas_expand_block (string, int);
void .bas_expand_pair (string);
void .bas_expand_full (string, string);
string .bas_keyword_cvt (string);
int .bas_next_word ();
int .bas_previous_word ();
/*
** Allocate the global variables and set up the keymaps.
*/
int _bas_smart,
_bas_template,
_bas_alt_template,
_bas_keyword_case,
_bas_indent_block,
_bas_indent_close,
_bas_indent_first,
_bas_min_abbrev;
/*
** Turn on smart indenting for BASIC. This macro is designed to
** be run the first time a file is edited, but may also be run from
** the command line.
**
** Parameters:
** 0 -- TRUE if the body of a procedure should be indented.
** 1 -- TRUE if the END of a block (but not a procedure, module,
** or RECORD) should be indented.
** 2 -- TRUE if the outermost BEGIN/END of a procedure, and the
** declarations associated with a procedure, should be indented.
**
** Defaults: 1 0 0
*/
string .bas_smart_first (~int, ~int, ~int)
{
if (first_time())
{
keyboard_push ();
assign_to_key ("<Enter>", ".bas_indent");
assign_to_key ("<Tab>", "slide_in");
assign_to_key ("<Shift-Tab>", "slide_out");
_bas_smart = inq_keyboard ();
keyboard_pop (1);
}
use_local_keyboard (_bas_smart);
_bas_indent_block = TRUE;
_bas_indent_close = FALSE;
_bas_indent_first = FALSE;
get_parm (0, _bas_indent_block);
get_parm (1, _bas_indent_close);
get_parm (2, _bas_indent_first);
returns ("");
}
/*
** Turn on template editing for BASIC. This macro is designed to
** be run the first time a file is edited, but may also be run from
** the command line.
**
** Parameters:
** 0 - 2 are the same as for smart indenting.
** 3 -- the minimum length of abbreviations that should be expanded.
** For example, if this is 2, wh<Space> will expand to a WHILE
** loop, and wi<Space> will expand to a WITH block, but w<Space>
** will be left alone. Set this parameter to 0 if you want
** to selectively expand templates by pressing <Tab>.
** 4 -- controls case of expanded keywords. If this is 0, w<Space>
** expands to "while"; if 1, it expands to "WHILE"; and if 2,
** it expands to "While".
***
** Defaults: 1 0 0 1 1
*/
string .bas_template_first (~int, ~int, ~int, ~int)
{
_bas_indent_block = TRUE;
_bas_indent_close = FALSE;
_bas_indent_first = FALSE;
_bas_min_abbrev = MIN_ABBREV;
_bas_keyword_case = KW_UPPER;
get_parm (0, _bas_indent_block);
get_parm (1, _bas_indent_close);
get_parm (2, _bas_indent_first);
get_parm (3, _bas_min_abbrev);
get_parm (4, _bas_keyword_case);
if (first_time())
{
keyboard_push ();
assign_to_key ("<Enter>", ".bas_indent");
assign_to_key ("<Tab>", ".bas_abbrev");
assign_to_key ("<Shift-Tab>", "slide_out");
assign_to_key ("<Ctrl-s>", "just_space");
_bas_alt_template = inq_keyboard ();
keyboard_pop (1);
keyboard_push ();
assign_to_key ("<Enter>", ".bas_indent");
assign_to_key ("<Tab>", "slide_in");
assign_to_key ("<Shift-Tab>", "slide_out");
assign_to_key ("<Space>", ".bas_abbrev");
assign_to_key ("<Ctrl-s>", "just_space");
_bas_template = inq_keyboard ();
keyboard_pop (1);
}
if (_bas_min_abbrev == 0)
{
use_local_keyboard (_bas_alt_template);
_bas_min_abbrev = MIN_ABBREV;
}
else
use_local_keyboard (_bas_template);
returns ("");
}
/*
** These definitions are used as Basic "language sensitive" word patterns
*/
int .bas_next_word ()
{
returns (.c_next_word ());
}
int .bas_previous_word ()
{
returns (.c_previous_word ());
}
/*
** Maps between indent levels (in tab stops) and column positions in a
** file. Column 1 to just before the first tab stop is level 0; from
** the first to just before the second tab stop is level 1; etc.
**
** If a parameter is passed, we treat it as an indent level, and we
** calculate the column corresponding to it. Otherwise, we calculate
** the indent level corresponding to the current column.
*/
int .bas_indent_level (~int)
{
int curr_col,
level,
lev_to_col;
save_position ();
curr_col = 1;
if (get_parm (0, lev_to_col))
{
beginning_of_line ();
while (level < lev_to_col)
{
move_abs (0, curr_col += distance_to_tab ());
++level;
}
level = curr_col;
}
else
{
inq_position (NULL, lev_to_col);
beginning_of_line ();
while ((curr_col += distance_to_tab ()) <= lev_to_col)
{
move_abs (0, curr_col);
++level;
}
}
restore_position ();
returns (level);
}
/*
** Moves the cursor to the first character on the current line that
** is not a space or a tab, or a line number.
*/
void .bas_first_nonwhite ()
{
string line;
beginning_of_line ();
/*
** If the line begins with a number, it may be a line number.
** In that case, we do a complicated (and relatively slow)
** search to get us to the first character after the line number.
** Then we skip over whitespace to get to the real line beginning.
**
** Since there is no quick way to detect an alphanumeric line
** label, we assume they only appear by themselves on lines.
** We can't look for a colon to find potentially labeled lines,
** because colons are too common, and searching would be too
** inefficient in this context.
*/
if (atoi (line = read ()))
{
int length;
if (search_string ("<[ \xc\t]@[0-9]+", line, length, -1, 1))
{
next_char (length);
line = read ();
}
}
next_char (strlen (line) - strlen (ltrim (line)));
}
/*
** Outdents a line until it pairs up with another keyword.
**
** Parameters:
** 0 -- the search pattern.
** 1 -- the current indenting level.
** 2 -- if passed, a keyword that increments the nesting level
** when we find it. If not passed, it defaults to END.
**
** Puts the new indenting level, if it changes, back into parameter 1.
*/
int .bas_outdent_to_match (string match_pattern, int curr_indent_level, ~string)
{
int nesting;
string end_keyword;
save_position ();
end_keyword = get_parm (2, end_keyword) ? upper (substr (end_keyword, 1, 3)) : "END";
nesting = 1;
/*
** Repeat until nesting is zero, or until we can't find another
** keyword. END and UNTIL increase the nesting level; other
** keywords decrease it.
*/
while (nesting)
{
move_abs (0, MAX_COL);
if (!(up () && search_back (match_pattern, 1, 0)))
{
restore_position ();
return (FALSE);
}
if (upper (substr (ltrim (read ()), 1, 3)) == end_keyword)
++nesting;
else
--nesting;
}
/*
** We have found the matching line.
*/
.bas_first_nonwhite ();
nesting = .bas_indent_level ();
restore_position ();
if (nesting != curr_indent_level)
{
.bas_reindent (nesting);
put_parm (1, nesting);
}
}
/*
** .bas_indent:
**
** This macro does syntax-sensitive indenting ("smart indenting") for
** BASIC language files. It handles most common constructs, except
** for nested comments.
**
** Parameters:
** 0 -- If FALSE, forces split mode (see below). If TRUE, forces
** non-split mode. If the parameter is omitted, split mode
** depends on whether or not BRIEF is in insert mode.
*/
void .bas_indent (~int)
{
int curr_line, // Line cursor is on when called.
code_line, // Line where last code char is found.
code_indent_level, // Current indent level, in tab stops.
prev_indent_level, // Indent level of previous line.
split_mode, // Should we insert a newline?
scratch; // Temporary integer.
string following_string, // Remainder of line being split.
code_text, // Trimmed text of code line.
token, // Tokenized version of line.
prev_text; // Trimmed text of previous line.
/*
** Initialize.
*/
inq_position (curr_line, NULL);
/*
** .bas_indent has two modes.
**
** Both modes will reindent the current line if necessary and
** position the cursor correctly on the following line.
**
** When BRIEF is in insert mode, or this macro is called from
** open_line, .bas_indent will add a new line to the buffer. The
** contents depend on the cursor position when .bas_indent is
** called: if the cursor is at the end of the line, the new line
** will be blank, but if not, the old line will be split in two.
**
** When BRIEF is in overstrike mode and the macro was not called
** by open_line, BRIEF does not add a new line. Note that open_line
** doesn't call the macro directly, but calls it via key assignment,
** which makes life difficult for us.
**
** You can pass an integer parameter to .bas_indent to force
** it into either mode. If the parameter is FALSE, .bas_indent
** will split; if it's TRUE, it won't.
*/
split_mode = inq_mode () || inq_command () == "open_line";
if (get_parm (0, scratch))
split_mode = !scratch;
/*
** If we're splitting, and not at the end of the line, we save
** the end of the line (minus its newline) and delete it.
*/
if (split_mode && read (1) != "\n")
{
following_string = read ();
following_string = substr (following_string, 1, strlen (following_string) - 1);
delete_to_eol ();
}
else
end_of_line ();
/*
** Find the last "code" character; skip back over whitespace, labels
** and comments until we get something different. The cursor will
** be left on the next character from the "different" one; we do a
** (prev_char) to get to the code character.
*/
search_back (BAS_SKIP_PAT, -2, 0);
/*
** Remember which line we found the code character on, the code
** portion of the line, and the indent level.
*/
if (prev_char ())
{
inq_position (code_line);
/*
** Find the first non-white character on the line, so
** we may determine its indenting level. Skip over any
** leading line identifier.
*/
.bas_first_nonwhite ();
code_indent_level = .bas_indent_level ();
code_text = upper (trim (read ()));
/*
** Find the last code line before this, and read information
** about it.
*/
beginning_of_line ();
if (prev_char ())
{
search_back (BAS_SKIP_PAT, -2, 0);
if (prev_char ())
{
.bas_first_nonwhite ();
prev_indent_level = .bas_indent_level ();
prev_text = upper (trim (read ()));
}
}
/*
** Get the first token on the code line. This assumes
** that tokens are separated by spaces.
*/
token = substr (code_text, 1, index (code_text + " ", " ") - 1);
}
/*
** Move to the beginning of the line the cursor was originally on.
** Occasionally, we have to adjust its indent level. However,
** if the line contains no code, we don't need to worry about it.
*/
move_abs (curr_line, 1);
if (code_line == curr_line)
switch (token)
{
/*
** Outdent an END so it's flush with its matching keyword.
** For END DEF and END SUB, we search for the last matching
** keyword; for END IF, we search for other IF statements
** as well as END IF (since nesting is permitted). We take
** care not to match on the single-line forms of IF and
** DEF FN.
*/
case "END":
{
switch (substr (ltrim (substr (code_text, 4)), 1, 2))
{
case "DE":
.bas_outdent_to_match ("<[ \t]@DEF FN[A-Z][~=]@>", code_indent_level);
case "IF":
.bas_outdent_to_match ("<[ \t]@{IF[ \t (]*THEN{[ \t]|{'*}}@>}|{END IF}", code_indent_level);
/*
** Currently, if you have a line identifier
** on the same line as one of these keywords,
** the matcher won't work correctly.
*/
case "SU":
.bas_outdent_to_match ("<[ \t]@SUB[ \t\n (']", code_indent_level);
}
}
case "ELSE":
case "ELSEIF":
.bas_outdent_to_match ("<[ \t]@{IF[ \t (]*THEN{[ \t]|{'*}}@>}|{END IF}", code_indent_level);
case "NEXT":
.bas_outdent_to_match ("<[ \t]@{FOR}|{NEXT}[ \t\n (']", code_indent_level, "NEXT");
case "WEND":
.bas_outdent_to_match ("<[ \t]@{WHILE}|{WEND}[ \t\n (']", code_indent_level, "WEND");
/*
** Outdent function and subroutine definitions to column 1.
*/
case "FUNCTION":
case "SUB":
if (code_indent_level)
.bas_reindent (code_indent_level = 0);
case "DEF":
if (substr (code_text, 5, 2) == "FN" && code_indent_level)
.bas_reindent (code_indent_level = 0);
}
/*
** Don't let the indenting level go negative.
*/
if (code_indent_level < 0)
code_indent_level = 0;
/*
** Move to the next line, splitting if necessary.
*/
if (split_mode)
{
end_of_line ();
insert ("\n");
}
else
move_rel (1, NEG_MAX_COL);
/*
** Now we calculate where to put the cursor on the next line.
** The actual algorithm for the default indenting style is:
**
** Indent after a line that began with DEF FN, FOR, WHILE, SUB
** (but not for a one-line DEF FN). Indent after a line that ended
** with THEN or ELSE
**
** Otherwise leave the line alone. Note: if we allow choices
** of indenting style, may have to work differently, even outdent
** cursor in some circumstances. May want to indent if line
** ended in _.
*/
switch (token)
{
case "DEF":
if (substr (code_text, 5, 2) == "FN" && !index (code_text, "="))
++code_indent_level;
case "FOR":
case "SUB":
case "WHILE":
case "FUNCTION":
case "SELECT":
++code_indent_level;
default:
{
token = substr (code_text, rindex (" " + code_text, " "));
if (token == "ELSE" || token == "THEN")
++code_indent_level;
}
}
/*
** Move to the new position.
**
** If we cut characters from the previous line, reinsert them.
*/
move_abs (0, .bas_indent_level (code_indent_level));
if (following_string != "")
{
save_position ();
insert (ltrim (following_string));
restore_position ();
}
}
/*
** .bas_abbrev:
**
** This macro performs template expansion for BASIC. When it is
** invoked, the characters before the cursor are checked to see if
** they are the start of a BASIC keyword, preceded by a space or a
** tab, and followed only by whitespace. If a match is found, the
** remainder of the statement is filled in automatically.
**
** Expansion is only done when we're at or past the end of the
** line, and when the line is less than 8 characters long. This
** makes expansion faster and avoids unwanted expansion.
*/
void .bas_abbrev ()
{
int done;
/*
** Expand only when we're at the end of the line.
*/
if (read (1) == "\n")
{
int loc;
string line;
/*
** Get a trimmed representation of the line into a string.
*/
save_position ();
beginning_of_line ();
loc = strlen (line = upper ((trim (ltrim (read ())))));
/*
** Only do template expansion if the trimmed version
** of the line is at least _bas_min_abbrev characters long,
** at most 8 characters long, matches an expansion in
** ABBR_LIST, and is shorter than that token.
*/
if ((loc <= 8 && loc >= _bas_min_abbrev) && (done = index (ABBR_LIST, "~" + line)))
{
string completion;
/*
** Extract the full, expanded keyword from the
** abbreviation list, and make sure it's longer
** than the abbreviation.
*/
completion = substr (ABBR_LIST, ++done);
completion = substr (completion, 1, index (completion, "~") - 1);
switch (completion)
{
case "DF":
completion = "DEF FN";
case "EI":
completion = "ELSEIF";
}
if (loc < strlen (completion))
{
/*
** Delete the abbreviation from the buffer, and
** replace it with the expanded version.
*/
.bas_first_nonwhite ();
delete_to_eol ();
insert (.bas_keyword_cvt (completion));
/*
** Insert necessary context for each keyword.
*/
switch (completion)
{
case "DEF FN":
.bas_expand_block ("END DEF", TRUE);
case "FUNCTION":
.bas_expand_block ("END FUNCTION", TRUE);
case "ELSE":
open_line ();
case "ELSEIF":
{
.bas_indent (TRUE);
move_rel (-1, NEG_MAX_COL);
end_of_line ();
.bas_expand_pair ("THEN");
}
case "FOR":
.bas_expand_full ("NEXT", "= ");
case "IF":
.bas_expand_full ("END IF", "THEN");
case "ON":
.bas_expand_pair ("GOSUB ");
case "SUB":
.bas_expand_block ("END SUB", TRUE);
case "WHILE":
.bas_expand_block ("WEND", TRUE);
case "SELECT CASE":
.bas_expand_block ("END SELECT", TRUE);
/*
** Don't want to insert a space after RETURN.
** Thus, make a special case for return to
** prevent it from going into default.
*/
case "RETURN":
nothing ();
default:
insert (" ");
}
}
else
done = FALSE;
}
restore_position (!done);
}
/*
** If we couldn't expand an abbreviation, we perform the
** normal task associated with the key that called us: insert
** a space, or shift a marked block.
*/
if (!done)
if (inq_local_keyboard () == _bas_alt_template)
slide_in ();
else
self_insert ();
}
/*
** Converts keywords into the user-specified preferred case.
*/
string .bas_keyword_cvt (string keyword)
{
int space;
string ret_string,
current_word;
switch (_bas_keyword_case)
{
case (KW_UPPER):
returns (upper (keyword));
case (KW_LOWER):
returns (lower (keyword));
case (KW_MIXED):
{
while (space = index (keyword, " "))
{
current_word = substr (keyword, 1, space);
ret_string = ret_string + upper (substr (current_word, 1, 1)) +
lower (substr (current_word, 2));
keyword = substr (keyword, space + 1);
}
ret_string = ret_string + upper (substr (keyword, 1, 1)) +
lower (substr (keyword, 2));
returns (ret_string);
}
}
}
/*
** Repositions a line at a specified indent level.
**
** Parameters:
** 0 -- the new indent level.
*/
void .bas_reindent (int curr_indent_level)
{
string temp;
save_position ();
.bas_first_nonwhite ();
if (.bas_indent_level () != curr_indent_level)
{
temp = trim (read ());
beginning_of_line ();
delete_to_eol ();
move_abs (0, .bas_indent_level (curr_indent_level));
insert (temp);
}
restore_position ();
}
/*
** Adds a matching keyword below the expanded template, at the same
** column.
*/
void .bas_expand_block (string keyword, int insert_space)
{
end_of_line ();
.bas_indent (FALSE);
move_rel (-1, NEG_MAX_COL);
.bas_first_nonwhite ();
down ();
insert (.bas_keyword_cvt (keyword));
move_rel (-1, NEG_MAX_COL);
end_of_line ();
if (insert_space)
insert (" ");
}
/*
** Expands a keyword pair, positioning the cursor between the two
** keywords.
*/
void .bas_expand_pair (string keyword)
{
save_position ();
insert (" " + (.bas_keyword_cvt (keyword)));
restore_position ();
right ();
}
void .bas_expand_full (string keyword1, string keyword2)
{
.bas_expand_block (keyword1, FALSE);
.bas_expand_pair (keyword2);
}

Binary file not shown.
Binary file not shown.
+97
View File
@@ -0,0 +1,97 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/* brace.cb:
**
** This macro is an attempt at a "locate the unmatched brace" utility.
** Although it attempts to be fairly smart about things, it has an IQ of
** 4 or 5, so be careful before taking its word for something.
**
** It DOES NOT WORK if there are braces inside quotes, apostrophes, or
** comments. The macro can, however, be modified to ignore everything
** inside these structures (and check for the appropriate mismatches).
*/
#define TRUE 1
#define BACK 1
#define DONE 2
int char_search (int backward);
void brace ()
{
int tot_count,
start_line,
start_col,
mismatch,
char_we_got,
backward;
string msg_pattern = "Checking braces, %d unmatched {s.",
msg_text;
inq_position (start_line, start_col);
top_of_buffer ();
while (backward < DONE)
{
while (char_search (backward) && !mismatch)
{
sprintf (msg_text, msg_pattern, tot_count);
message (msg_text);
if (backward)
char_we_got = index ("}{", read (1));
else
char_we_got = index ("{}", read (1));
if (char_we_got == 1)
++tot_count;
else if (char_we_got == 2)
if (tot_count)
--tot_count;
else
{
if (backward)
message ("Mismatched opening brace.");
else
message ("Mismatched closing brace.");
mismatch = TRUE;
}
if (!mismatch)
if (backward)
prev_char ();
else
next_char ();
}
if (!mismatch)
if (tot_count)
{
end_of_buffer ();
tot_count = 0;
backward = BACK;
msg_pattern = "Locating mismatch, %d unmatched }s.";
}
else
backward = DONE;
else
backward = DONE;
}
if (!mismatch)
{
message ("All braces match.");
move_abs (start_line, start_col);
}
}
int char_search (int backward)
{
if (backward)
returns (search_back ("[\\{\\}]"));
else
returns (search_fwd ("[\\{\\}]"));
}
Binary file not shown.
+118
View File
@@ -0,0 +1,118 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;** brace.m:
;**
;** This macro is an attempt at a "locate the unmatched brace" utility.
;** Although it attempts to be fairly smart about things, it has an IQ of
;** 4 or 5, so be careful before taking its word for something.
;**
;** It DOES NOT WORK if there are braces inside quotes, apostrophes, or
;** comments. The macro can, however, be modified to ignore everything
;** inside these structures (and check for the appropriate mismatches).
;**
;** Revision history:
;** -----------------
#define TRUE 1
#define BACK 1
#define DONE 2
(macro brace
(
(int tot_count
start_line
start_col
mismatch
char_we_got
backward
)
(string msg_pattern
msg_text)
(= msg_pattern "Checking braces, %d unmatched {s.")
(inq_position start_line start_col)
(top_of_buffer)
(while (< backward DONE)
(
(while (&& (char_search backward) (! mismatch))
(
(sprintf msg_text msg_pattern tot_count)
(message msg_text)
(if backward
(= char_we_got (index "}{" (read 1)))
;else
(= char_we_got (index "{}" (read 1)))
)
(if (== char_we_got 1)
(++ tot_count)
;else
(if (== char_we_got 2)
(if tot_count
(-- tot_count)
;else
(
(if backward
(message "Mismatched opening brace.")
;else
(message "Mismatched closing brace.")
)
(= mismatch TRUE)
)
)
)
)
(if (! mismatch)
(
(if backward
(prev_char)
;else
(next_char)
)
)
)
)
)
(if (! mismatch)
(if tot_count
(
(end_of_buffer)
(= tot_count 0)
(= backward BACK)
(= msg_pattern "Locating mismatch, %d unmatched }s.")
)
;else
(= backward DONE)
)
;else
(= backward DONE)
)
)
)
(if (! mismatch)
(
(message "All braces match.")
(move_abs start_line start_col)
)
)
)
)
(macro char_search
(
(int backward)
(get_parm 0 backward)
(if backward
(returns (search_back "[\\{\\}]"))
;else
(returns (search_fwd "[\\{\\}]"))
)
)
)
+990
View File
@@ -0,0 +1,990 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
#include "dialog.h"
#include "win_ctrl.h"
/*
** buffers.cb:
**
** This file contains all of the standard BRIEF macros for buffer
** manipulation.
*/
/*
** buf_list:
**
** This macro provides the user with a list of buffers that can be
** manipulated and scrolled through. It is of interest because it
** simulates an array of buffer ids using a system buffer. Macro
** programmers interested in using arrays should examine this code
** carefully before implementing an array system of their own.
*/
#define SYSTEM 1 // The value to use for system buffers.
#define NEW_FILE 1 // The value to use for new file attachments.
#define NUM_ENTRIES_DISPLAYED 6 // The number of non-expert entries displayed
void display_file_name ();
int _buf_write ();
string _bookmark_menu ();
void mouse_buf_list();
void _buf_position( int );
void buf_list (~int)
{
global int _buf_list, // Buffer that contains visible list.
_buf_array, // Buffer that simulates an array.
_end_buf, // The buffer to be attached on exit.
_expert; // Are we in expert mode?
int num_bufs, // The number of buffers in the list.
start_buf, // The buffer we started on.
curr_buf, // The buffer we're on (in the loop).
modified; // Is the current buffer modified?
string file_name, // The file name of the buffer.
buffer_name; // The buffer name.
if (get_parm (0, _expert))
_expert = !!_expert;
else
_expert = 0;
/*
** First, we create the array and list buffers, making sure that they
** have the "system" attributes. We use non-file buffers because this is
** temporary information.
**
** The "_buf_list" buffer contains a textual list of all of the non
** system buffers currently in memory. "_buf_array" contains a list of the
** corresponding buffer pointers. Note that the buffer pointers are not
** inserted into the buffer as is -- they are converted to string integers
** first. This prevents inserting bad characters like tab, return and EOF.
*/
message ("Creating buffer list...");
/* First, we get the ID of the current buffer -- we have to
** restore it at the end of the macro. After that, we create the
** array buffer and put it aside for the moment. Note that the
** array buffer is a non-file buffer -- this prevents disk accesses
** since the file is held completely in memory.
*/
start_buf = _end_buf = inq_buffer ();
/* Make sure we start off with a non-system buffer
*/
if (inq_system(start_buf))
start_buf = _end_buf = next_buffer ();
if (inq_system(start_buf))
{
error ("No buffers found.");
}
_buf_array = create_buffer ("Buffer Array", NULL, SYSTEM);
/* Now, we create the buffer that the user will actually see on
** the screen, set it to be the current buffer, and set the tabs to
** the values we want (tabs default to every column).
*/
set_buffer (_buf_list = create_buffer ("Buffer List", NULL, SYSTEM));
tabs (5);
/* This loop creates both buffer lists: the non-system buffers
** are looped through and information about them are culled and added
** to the list.
*/
while (start_buf != curr_buf)
{
if (!curr_buf)
curr_buf = start_buf;
else
{
set_buffer (_buf_list);
insert ("\n");
set_buffer (_buf_array);
insert ("\n");
}
++num_bufs;
message ("Creating buffer list [#%d]...", num_bufs);
set_buffer (curr_buf);
inq_names (file_name, NULL, buffer_name);
modified = inq_modified ();
set_buffer (_buf_list);
if (!_expert)
insert ("%d)\tBuffer \"%s\" has %sbeen modified.\n\tFile: ", num_bufs, buffer_name, modified ? "" : "not ");
else
insert ("%d)\t", num_bufs);
insert (file_name + (modified ? "*" : ""));
set_buffer (_buf_array);
insert ("%d", curr_buf);
set_buffer (curr_buf);
curr_buf = next_buffer ();
}
message ("List created.");
/*
** At this point, the array buffer and list buffer have been created
** and filled in. We create a window to display the list in, initialize
** the marked area, set up a keymap, and call process. Process handles
** the mainline loop -- we need only provide action routines.
*/
set_ctrl_state( ZOOM_BTN, HIDE_CTRL); // hide the zoom button for this window
set_ctrl_state( HORZ_SCROLL, HIDE_CTRL); // hide the horz scroll bar for this window
create_window (5, 4+NUM_ENTRIES_DISPLAYED*2+1, 74, 4,
" or  to select, E to edit, D to delete, W to write, ESC to exit.");
set_ctrl_state( ZOOM_BTN, SHOW_CTRL); // show the zoom button
set_ctrl_state( HORZ_SCROLL, SHOW_CTRL); // show the horz scroll bar
attach_buffer (_buf_list);
keyboard_push ();
assign_to_key ("<Down>", "_buf_down");
assign_to_key ("<Up>", "_buf_up");
assign_to_key ("<PgUp>", "_buf_pgup");
assign_to_key ("<PgDn>", "_buf_pgdn");
assign_to_key ("<Home>", "_buf_home");
assign_to_key ("<End>", "_buf_end");
assign_to_key ("<Ctrl-PgUp>", "_buf_home");
assign_to_key ("<Ctrl-PgDn>", "_buf_end");
assign_to_key ("d", "_buf_delete");
assign_to_key ("D", "_buf_delete");
assign_to_key ("<Ctrl-minus>", "_buf_delete");
assign_to_key ("e", "_buf_edit");
assign_to_key ("E", "_buf_edit");
assign_to_key ("<Alt-e>", "_buf_edit");
assign_to_key ("W", "_buf_write");
assign_to_key ("w", "_buf_write");
assign_to_key ("<Alt-w>", "_buf_write");
assign_to_key ("<Enter>", "_buf_edit");
assign_to_key ("<Esc>", "exit");
/*
** specify the function to handle mouse events and save the
** previous mouse handler to allow for sub-classing of events
*/
set_mouse_action( "mouse_buf_list" );
move_abs (2 - _expert, 100);
drop_anchor (3);
move_abs (1, 1);
set_buffer (_buf_array);
move_abs (1, 1);
set_buffer (_buf_list);
refresh ();
process ();
/* Now that we're back from the processing, we pop the keymap that
** we created, raise the assorted anchors, and delete the temporary
** window and the buffers.
*/
keyboard_pop ();
raise_anchor ();
delete_window ();
delete_buffer (_buf_list);
delete_buffer (_buf_array);
/* If we end with a different buffer than we started with, we
** attach it to the current window and display its file name.
** Otherwise, we set the current buffer back, and call NEW_FILE
** to make sure its defaults are reset.
*/
set_buffer (_end_buf);
inq_names (file_name);
edit_file (file_name);
}
/*
** _buf_down:
**
** This routine is called whenever the user presses a down arrow.
** It moves the array buffer and list buffer's current lines, ensuring
** the user does not go past the end of the buffer.
*/
int _buf_down ()
{
int line;
inq_position (line);
if (!_expert && line % 2 == 0)
{
swap_anchor();
refresh();
}
move_rel (3 - _expert * 2, 0);
if (inq_position ())
{
move_rel (-3 + _expert * 2, 0);
return (0);
}
else
{
raise_anchor ();
drop_anchor (3);
move_rel (-1 + _expert, 0);
set_buffer (_buf_array);
down ();
set_buffer (_buf_list);
returns (1);
}
}
/*
** _buf_up:
**
** This macro is called whenever the user presses the up arrow. It
** moves up in the list and array buffers, not going past the top of the
** buffer.
*/
int _buf_up ()
{
int line;
inq_position (line);
if (!_expert && line % 2 == 0)
{
swap_anchor();
refresh();
}
if (!up ())
return (0);
else
{
raise_anchor ();
drop_anchor (3);
move_rel (-1 + _expert, 0);
set_buffer (_buf_array);
move_rel (-1, 0);
set_buffer (_buf_list);
returns (1);
}
}
/*
** _buf_pgup:
**
** This macro is called whenever the user presses PgUp. It moves up
** one screen in the list and array buffers, not going past the top of the
** buffer.
*/
void _buf_pgup ()
{
int num_lines = NUM_ENTRIES_DISPLAYED * (_expert + 1);
while (num_lines--)
_buf_up ();
}
void _buf_home ()
{
while (_buf_up ());
}
/*
** _buf_pgdn:
**
** This macro is called whenever the user presses PgDn. It moves
** down one page/screen in the buffer list and the array.
*/
void _buf_pgdn ()
{
int num_lines = NUM_ENTRIES_DISPLAYED * (_expert + 1);
while (num_lines--)
_buf_down ();
}
void _buf_end ()
{
while (_buf_down ());
}
/*
** _buf_delete:
**
** This routine is called when the user wants to delete a buffer.
** It makes sure the buffer is not in a window, and prompts the user
** if the buffer has been modified.
*/
void _buf_delete ()
{
int buf_to_delete;
string misc_str = "y";
set_buffer (_buf_array);
buf_to_delete = atoi (read ());
set_buffer (buf_to_delete);
if (!inq_views ())
{
if (inq_modified ())
{
keyboard_flush ();
if (!get_parm (NULL, misc_str, "This buffer has not been saved. Delete [ynw]? ", 1))
misc_str = "n";
}
if (index ("yY", misc_str) || index ("wW", misc_str) && _buf_write () > 0)
{
int line;
set_buffer (_buf_list);
inq_position (line);
if (!_expert && line % 2 == 0)
{
swap_anchor();
refresh();
}
delete_line ();
if (!_expert)
delete_line ();
set_buffer (_buf_array);
delete_line ();
delete_buffer (buf_to_delete);
set_buffer (_buf_list);
if (inq_position ())
_buf_up ();
else
{
raise_anchor ();
move_rel (1 - _expert, 0);
drop_anchor (3);
move_rel (-1 + _expert, 0);
}
}
else if (!index ("wW", misc_str))
message ("Buffer not deleted.");
}
else
error ("You can't delete a viewed buffer.");
set_buffer (_buf_list);
}
/* _buf_edit:
**
** This routine is called when the user is on a buffer that he wants
** to edit. It sets the global "_end_buf" variable to the current
** line's buffer, and calls exit so no further processing takes place.
*/
void _buf_edit ()
{
set_buffer (_buf_array);
_end_buf = atoi (read ());
set_buffer (_buf_list);
exit ();
}
/*
** _buf_write:
**
** This routine is called when the user wants to write a modified
** buffer. It makes sure the buffer is modified -- if so, it's written
** and the information in the window is updated.
*/
int _buf_write ()
{
int old_msg_level,
ret_code;
set_buffer (_buf_array);
set_buffer (atoi (read ()));
if (inq_modified ())
{
old_msg_level = inq_msg_level ();
set_msg_level (0);
if ((ret_code = write_buffer ()) > 0)
{
set_msg_level (old_msg_level);
set_buffer (_buf_list);
if (!_expert)
{
search_fwd ("has \\c");
insert ("not ");
down ();
}
end_of_line ();
backspace ();
move_rel (-1 + _expert, -100);
}
else
set_msg_level (old_msg_level);
}
else
error ("Buffer not modified.");
set_buffer (_buf_list);
returns (ret_code);
}
/*
** edit_file:
**
** This macro replaces the built-in edit_file function: it displays
** the file name of the edited file if the edit operation was successful.
*/
replacement int edit_file (~string)
{
int ret_code,
old_msg_level;
old_msg_level = inq_msg_level ();
if (inq_called () == "")
set_msg_level (0);
ret_code = edit_file ();
set_msg_level (old_msg_level);
if (ret_code == 1)
display_file_name ();
returns (ret_code);
}
/*
** _multifile_edit_file:
**
** This macro is called by the file completion functions when more then
** one file is selected from the completion menu.
*/
void _multifile_edit_file (int completion_buf_id, string path)
{
int old_buf_id = set_buffer (completion_buf_id);
string file_name;
top_of_buffer ();
while (!inq_position () && (file_name = trim (ltrim (read ()))) != "")
{
edit_file (path + file_name);
set_buffer (completion_buf_id);
down ();
}
set_buffer (old_buf_id);
}
/*
** edit_next_buffer:
**
** Edits the next buffer in the buffer list in the current window. If
** there are no other buffers, an error message is displayed.
*/
void edit_next_buffer ()
{
string file_name;
int new_buffer = next_buffer ();
if (new_buffer != inq_buffer ())
{
set_buffer (new_buffer);
inq_names (file_name);
edit_file (file_name);
}
else
error ("No other buffers.");
}
/*
** edit_prev_buffer:
**
** Edits the previous buffer in the buffer list.
*/
void edit_prev_buffer ()
{
string file_name;
int old_buffer = inq_buffer ();
while (next_buffer () != old_buffer)
set_buffer (next_buffer ());
if (inq_buffer () != old_buffer)
{
inq_names (file_name);
edit_file (file_name);
}
else
error ("No other buffers.");
}
/*
** delete_curr_buffer:
**
** This function deletes the current buffer, if it is unmodified,
** there is another buffer in the list to replace it, and it is only
** visible in one window.
**
** If the buffer is modified, the user is asked if he really wants to
** delete the buffer. If he answers yes, the deletion is performed.
**
** If there are no other buffers, or the buffer is in an overlapping
** window and any other window, the deletion is not performed.
*/
int delete_curr_buffer ()
{
int old_buf_id = inq_buffer (),
new_buf_id = next_buffer (),
window_buf_id,
orig_window_id,
curr_window_id;
string reply,
file_name;
if (old_buf_id == new_buf_id)
{
error ("Can't delete: no other buffers.");
return (0);
}
orig_window_id = inq_window ();
if (inq_window_info () == 1)
{
curr_window_id = next_window ();
while (orig_window_id != curr_window_id)
{
inq_window_info (curr_window_id, window_buf_id);
if (window_buf_id == old_buf_id)
{
error ("Can't delete: buffer's windows overlap.");
return (0);
}
curr_window_id = next_window (curr_window_id);
}
}
if (inq_modified ())
{
keyboard_flush ();
if (!get_parm (NULL, reply, "This buffer has not been saved. Delete [ynw]? ", 1))
return (0);
else if (!strlen (reply) || !index ("yYwW", reply))
{
message ("Buffer not deleted.");
return (0);
}
if (index ("wW", reply))
{
int old_msg_level = inq_msg_level (),
ret_code;
set_msg_level (0);
ret_code = write_buffer ();
set_msg_level (old_msg_level);
if (ret_code <= 0)
return (0);
}
}
set_buffer (new_buf_id);
inq_names (file_name, NULL);
set_buffer (old_buf_id);
edit_file (file_name);
if (inq_views (old_buf_id) != 0)
{
curr_window_id = next_window ();
while (orig_window_id != curr_window_id)
{
inq_window_info (curr_window_id, window_buf_id);
if (old_buf_id == window_buf_id)
{
set_window (curr_window_id);
edit_file (file_name);
}
curr_window_id = next_window (curr_window_id);
}
if (inq_window () != orig_window_id)
set_window (orig_window_id);
}
delete_buffer (old_buf_id);
returns (1);
}
/*
** _bad_key:
**
** This routine adds menus to some prompts.
*/
replacement _bad_key ()
{
int key_pressed = read_char ();
if (inq_command () == "goto_bookmark" && key_pressed == key_to_int ("<Tab>"))
return (_bookmark_menu ());
push_back (key_pressed);
return (_bad_key ());
}
/*
** _bookmark_menu:
**
** This routine actually handles the "invalid keystroke" event
** when in the bookmark prompt.
*/
string _bookmark_menu ()
{
global int _bookmark;
int menu_buf,
old_buf,
curr_buf,
line,
col,
i,
num_bookmarks;
string bookmark,
file_name;
while (i < 10)
{
if (goto_bookmark (i, curr_buf, line, col))
++num_bookmarks;
++i;
}
if (num_bookmarks == 0)
beep ();
else
{
int num_lines,
num_cols,
lx,
by,
rx,
ty;
old_buf = inq_buffer ();
sprintf (bookmark, "%d bookmark%s", num_bookmarks, num_bookmarks == 1 ? "" : "s");
set_buffer (menu_buf = create_buffer (bookmark, NULL, SYSTEM));
num_bookmarks = 0;
i = 1;
tabs (2, 13, 19, 25, 80);
while (i <= 10)
{
if (goto_bookmark (i, curr_buf, line, col))
{
if (++num_bookmarks == 1)
insert ("\n\tBookmark\tLine\tCol\tFile\n\t--------\t----\t---\t----");
insert ("\n");
set_buffer (curr_buf);
inq_names (file_name);
set_buffer (menu_buf);
insert ("\t%d\t%d\t%d\t%s\t;%d", i, line, col, file_name, i);
}
++i;
}
set_buffer (old_buf);
_bookmark = -1;
inq_screen_size (num_lines, num_cols);
num_lines /= 2;
num_cols /= 2;
lx = num_cols - 36;
rx = num_cols + 36;
ty = num_lines - (4 + (num_bookmarks + 4) / 2);
by = ty + (num_bookmarks + 5);
_process_menu (lx, by, rx, ty, NULL, " or  to move, <Enter> to select, <Esc> to exit", NULL, menu_buf, "_bookmark_action", TRUE);
if (_bookmark >= 0)
{
sprintf (bookmark, "%d", _bookmark);
push_back (key_to_int ("<Enter>"));
return (bookmark);
}
}
returns (inq_cmd_line ());
}
/*
** _bookmark_action:
**
** This is the action routine for the dialog manager.
*/
int _bookmark_action (int event_type, ~string)
{
string button_text;
switch (event_type)
{
case DIALOG_MOVE_MENU:
{
get_parm (2, button_text);
if (index (button_text, ";"))
returns (TRUE);
else
returns (FALSE);
}
case DIALOG_PICK_MENU:
case DIALOG_F10:
{
get_parm (2, button_text);
_bookmark = atoi (substr (button_text, rindex (button_text, ";") + 1));
_dialog_esc ();
returns (TRUE);
}
}
}
/*
** mouse_buf_list
**
** Handle all the mouse events of interest for the buffer list
**
** Mouse assignments:
** btn1 down, up, click - position to an entry in the list
** btn1 dblclk - edit the file
** btn2 click - write the file
** btn2 click + ctrl - delete the file
** btn1 click outside the list - close the list
** btn1 click on close button - close the list
*/
void mouse_buf_list (int event, // the event code
int modifier, // modifier keys
int parm2, // line or scroll bar code
int parm3 ) // column or thumb position
{
/* handle the events of interest */
switch ( event ){
case BTN2_CLICK: // delete / write the file
case BTN1_DOWN: // position to a file
case BTN1_UP: // position to a file
case BTN1_MOVE: // position to a file
case BTN1_CLICK: // position to a file
case BTN1_DBLCLK:{ // edit the file
int lines;
save_position(); // get number of lines in buffer
end_of_buffer();
inq_position( lines );
restore_position();
if ( 0 < parm2 && parm2 <= lines ) {
/* if two lines per entry and an even line clicked on
switch to corresponding odd line */
if ( !_expert && !(parm2%2) ) parm2--;
_buf_position( parm2 ); // goto selected position
switch ( event ){
case BTN1_DBLCLK: // edit the file
_buf_edit();
case BTN2_CLICK:
switch ( modifier ){
case 0: // write the file
_buf_write();
case KB_CTRL: // delete the file
_buf_delete();
}
}
}
}
case SET_WIN: // click outside list closes it
if ( parm2 != inq_window() ) exit();
case CLOSE_WIN:
exit(); // close the buffer list
case VSCROLL: // vertical scroll bar event
switch ( parm2 ){
case SB_BOTTOM: // end of the list
_buf_end();
case SB_TOP: // beginning of the list
_buf_home();
case SB_PAGEDOWN: // page down request
_buf_pgdn();
case SB_PAGEUP: // page up request
_buf_pgup();
case SB_LINEDOWN: // line down request
_buf_down();
case SB_LINEUP: // line up request
_buf_up();
case SB_THUMBTRACK:{ // scroll while tracking the thumb
int new_line;
save_position();
/* Move the thumb to the desired position. We do this
** to find out what the target line is.
*/
set_ctrl_state(VERT_THUMB, parm3);
/* Get the target line
*/
inq_position(new_line);
restore_position();
/* Now let _buf_position really move to the new
** selection. This is done so that the buffer containing
** buffer info is updated correctly.
*/
_buf_position( new_line ); // goto the entry
}
}
}
}
/*
** _buf_position
**
** Position to an entry in the list and highlite the entry.
**
*/
void _buf_position(int new_line) // target line to goto
{
int curr_line,
top_left,
line,
moved_up = 0,
extra;
/* If we're not in expert mode, we may need to position the cursor
** on the second line of an entry to get the thumb to position
** correctly.
*/
if (!_expert && new_line % 2 == 0)
extra = 1;
else
extra = 0;
inq_position( line ); // get current position
/* If we are currently on the second line of an entry,
** reposition by swapping the anchor.
*/
if (!_expert && line % 2 == 0)
{
swap_anchor();
inq_position( line ); // get current position
}
/* target line is below current line */
if ( line < new_line )
{
while ( inq_position(line) == 0 && line < new_line)
{
if (extra && line + 1 == new_line)
{
swap_anchor();
move_abs(0, 1);
break;
}
if (!_buf_down())
break;
}
}
/* target line is above current line */
else if ( line > new_line )
{
moved_up = 1;
while (line + extra > new_line)
{
_buf_up();
inq_position( line );
if (extra && (line + 1 == new_line))
{
swap_anchor();
break;
}
}
}
refresh();
/* Now make sure an entry is not split by the window.
*/
inq_position(curr_line);
inq_top_left(top_left);
if (top_left % 2 == 0)
{
if (moved_up)
set_top_left(top_left - 1, 1);
else
set_top_left(top_left + 1, 1);
}
}
Binary file not shown.
+766
View File
@@ -0,0 +1,766 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
#include "dialog.h"
;**
;** buffers.m:
;**
;** This file contains all of the standard BRIEF macros for buffer
;** manipulation.
;**
;** Revision history:
;** -----------------
;**
;** buf_list:
;**
;** This macro provides the user with a list of buffers that can be
;** manipulated and scrolled through. It is of interest because it
;** simulates an array of buffer ids using a system buffer. Macro
;** programmers interested in using arrays should examine this code
;** carefully before implementing an array system of their own.
;**
#define SYSTEM 1 ;** The value to use for system buffers.
#define NEW_FILE 1 ;** The value to use for new file attachments.
(extern display_file_name
_bad_key
)
(macro buf_list
(
(int _buf_list ;** Buffer that contains visible list.
_buf_array ;** Buffer that simulates an array.
_end_buf ;** The buffer to be attached on exit.
num_bufs ;** The number of buffers in the list.
start_buf ;** The buffer we started on.
curr_buf ;** The buffer we're on (in the loop).
modified ;** Is the current buffer modified?
_expert ;** Are we in expert mode?
)
(string file_name ;** The file name of the buffer.
buffer_name ;** The buffer name.
file_line ;** Buffer for line to insert.
)
(global _buf_list
_buf_array
_end_buf
_expert
)
(if (get_parm 0 _expert)
(= _expert (! (! _expert)))
;else
(= _expert 0)
)
;**
;** First, we create the array and list buffers, making sure that they
;** have the "system" attributes. We use non-file buffers because this is
;** temporary information.
;**
;** The "_buf_list" buffer contains a textual list of all of the non
;** system buffers currently in memory. "_buf_array" contains a list of the
;** corresponding buffer pointers. Note that the buffer pointers are not
;** inserted into the buffer as is -- they are converted to string integers
;** first. This prevents inserting bad characters like tab, return and EOF.
;**
(message "Creating buffer list...")
;** First, we get the ID of the current buffer -- we have to
;** restore it at the end of the macro. After that, we create the
;** array buffer and put it aside for the moment. Note that the
;** array buffer is a non-file buffer -- this prevents disk accesses
;** since the file is held completely in memory.
(= start_buf (= _end_buf (inq_buffer)))
(= _buf_array (create_buffer "Buffer Array" NULL SYSTEM))
;** Now, we create the buffer that the user will actually see on
;** the screen, set it to be the current buffer, and set the tabs to
;** the values we want (tabs default to every column).
(= _buf_list (create_buffer "Buffer List" NULL SYSTEM))
(set_buffer _buf_list)
(tabs 5)
;** This loop creates both buffer lists: the non-system buffers
;** are looped through and information about them are culled and added
;** to the list.
(while (!= start_buf curr_buf)
(
(if (! curr_buf)
(= curr_buf start_buf)
;else
(
(set_buffer _buf_list)
(insert "\n")
(set_buffer _buf_array)
(insert "\n")
)
)
(++ num_bufs)
(message "Creating buffer list [#%d]..." num_bufs)
(set_buffer curr_buf)
(inq_names file_name NULL buffer_name)
(= modified (inq_modified))
(set_buffer _buf_list)
(if (! _expert)
(
(sprintf file_line "%d)\tBuffer \"%s\" has " num_bufs buffer_name)
(insert file_line)
(sprintf file_line "%sbeen modified.\n\tFile: " (if modified "" "not "))
(insert file_line)
)
;else
(
(sprintf file_line "%d)\t" num_bufs)
(insert file_line)
)
)
(insert file_name)
(if modified
(insert "*")
)
(set_buffer _buf_array)
(sprintf file_line "%d" curr_buf)
(insert file_line)
(set_buffer curr_buf)
(= curr_buf (next_buffer))
)
)
(message "List created.")
;**
;** At this point, the array buffer and list buffer have been created
;** and filled in. We create a window to display the list in, initialize
;** the marked area, set up a keymap, and call process. Process handles
;** the mainline loop -- we need only provide action routines.
;**
(create_window 5 17 74 4 " or  to select, E to edit, D to delete, W to write, ESC to exit.")
(attach_buffer _buf_list)
(keyboard_push)
(assign_to_key "<Down-Arrow>" "_buf_down")
(assign_to_key "<Up-Arrow>" "_buf_up")
(assign_to_key "<PgUp>" "_buf_pgup")
(assign_to_key "<PgDn>" "_buf_pgdn")
(assign_to_key "<Home>" "_buf_home")
(assign_to_key "<End>" "_buf_end")
(assign_to_key "<Ctrl-PgUp>" "_buf_home")
(assign_to_key "<Ctrl-PgDn>" "_buf_end")
(assign_to_key "d" "_buf_delete")
(assign_to_key "D" "_buf_delete")
(assign_to_key "<Ctrl-minus>" "_buf_delete")
(assign_to_key "e" "_buf_edit")
(assign_to_key "E" "_buf_edit")
(assign_to_key "<Alt-e>" "_buf_edit")
(assign_to_key "W" "_buf_write")
(assign_to_key "w" "_buf_write")
(assign_to_key "<Alt-w>" "_buf_write")
(assign_to_key "<Enter>" "_buf_edit")
(assign_to_key "<Esc>" "exit")
(move_abs (- 2 _expert) 100)
(drop_anchor)
(move_abs 1 1)
(set_buffer _buf_array)
(move_abs 1 1)
(set_buffer _buf_list)
(refresh)
(process)
;** Now that we're back from the processing, we pop the keymap that
;** we created, raise the assorted anchors, and delete the temporary
;** window and the buffers.
(keyboard_pop)
(raise_anchor)
(delete_window)
(delete_buffer _buf_list)
(delete_buffer _buf_array)
;** If we end with a different buffer than we started with, we
;** attach it to the current window and display its file name.
;** Otherwise, we set the current buffer back, and call NEW_FILE
;** to make sure its defaults are reset.
(set_buffer _end_buf)
(inq_names file_name)
(edit_file file_name)
)
)
;**
;** _buf_down:
;**
;** This routine is called whenever the user presses a down arrow.
;** It moves the array buffer and list buffer's current lines, ensuring
;** the user does not go past the end of the buffer.
;**
(macro _buf_down
(
(move_rel (- 3 (* _expert 2)) 0)
(if (inq_position)
(
(move_rel (+ -3 (* _expert 2)) 0)
(return 0)
)
;else
(
(raise_anchor)
(drop_anchor 3)
(move_rel (+ -1 _expert) 0)
(set_buffer _buf_array)
(down)
(set_buffer _buf_list)
(return 1)
)
)
)
)
;**
;** _buf_up:
;**
;** This macro is called whenever the user presses the up arrow. It
;** moves up in the list and array buffers, not going past the top of the
;** buffer.
;**
(macro _buf_up
(
(int line)
(inq_position line)
(if (! (up))
(return 0)
;else
(
(raise_anchor)
(drop_anchor 3)
(move_rel (+ -1 _expert) 0)
(set_buffer _buf_array)
(move_rel -1 0)
(set_buffer _buf_list)
(return 1)
)
)
)
)
;**
;** _buf_pgup:
;**
;** This macro is called whenever the user presses PgUp. It moves up
;** one screen in the list and array buffers, not going past the top of the
;** buffer.
;**
(macro _buf_pgup
(
(int num_lines)
(= num_lines (* 6 (+ _expert 1)))
(while num_lines
(
(_buf_up)
(-- num_lines)
)
)
)
)
(macro _buf_home
(while (_buf_up))
)
;**
;** _buf_pgdn:
;**
;** This macro is called whenever the user presses PgDn. It moves
;** down one page/screen in the buffer list and the array.
;**
(macro _buf_pgdn
(
(int num_lines)
(= num_lines (* 6 (+ _expert 1)))
(while num_lines
(
(_buf_down)
(-- num_lines)
)
)
)
)
(macro _buf_end
(while (_buf_down))
)
;**
;** _buf_delete:
;**
;** This routine is called when the user wants to delete a buffer.
;** It makes sure the buffer is not in a window, and prompts the user
;** if the buffer has been modified.
;**
(macro _buf_delete
(
(int buf_to_delete
ret_code
)
(string misc_str)
(set_buffer _buf_array)
(= buf_to_delete (atoi (read)))
(set_buffer buf_to_delete)
(= misc_str "y")
(if (! (inq_views))
(
(if (inq_modified)
(
(keyboard_flush)
(if (! (get_parm NULL misc_str "This buffer has not been saved. Delete [ynw]? " 1))
(= misc_str "n")
)
)
)
(if (|| (index "yY" misc_str) (&& (index "wW" misc_str) (> (_buf_write) 0)))
(
(set_buffer _buf_list)
(delete_line)
(if (! _expert)
(delete_line)
)
(set_buffer _buf_array)
(delete_line)
(delete_buffer buf_to_delete)
(set_buffer _buf_list)
(if (inq_position)
(_buf_up)
;else
(
(raise_anchor)
(move_rel (- 1 _expert) 0)
(drop_anchor 3)
(move_rel (+ -1 _expert) 0)
)
)
)
;else
(if (! (index "wW" misc_str))
(message "Buffer not deleted.")
)
)
)
;else
(error "You can't delete a viewed buffer.")
)
(set_buffer _buf_list)
)
)
;** _buf_edit:
;**
;** This routine is called when the user is on a buffer that he wants
;** to edit. It sets the global "_end_buf" variable to the current
;** line's buffer, and calls exit so no further processing takes place.
;**
(macro _buf_edit
(
(set_buffer _buf_array)
(= _end_buf (atoi (read)))
(set_buffer _buf_list)
(exit)
)
)
;**
;** _buf_write:
;**
;** This routine is called when the user wants to write a modified
;** buffer. It makes sure the buffer is modified -- if so, it's written
;** and the information in the window is updated.
;**
(macro _buf_write
(
(int old_msg_level
ret_code
)
(set_buffer _buf_array)
(set_buffer (atoi (read)))
(if (inq_modified)
(
(= old_msg_level (inq_msg_level))
(set_msg_level 0)
(if (> (= ret_code (write_buffer)) 0)
(
(set_msg_level old_msg_level)
(set_buffer _buf_list)
(if (! _expert)
(
(search_fwd "has \\c")
(insert "not ")
(down)
)
)
(end_of_line)
(backspace)
(move_rel (+ -1 _expert) -100)
)
;else
(set_msg_level old_msg_level)
)
)
;else
(error "Buffer not modified.")
)
(set_buffer _buf_list)
(returns ret_code)
)
)
;**
;** edit_file:
;**
;** This macro replaces the built-in edit_file function: it displays
;** the file name of the edited file if the edit operation was successful.
;**
(replacement edit_file
(
(int ret_code
old_msg_level
)
(= old_msg_level (inq_msg_level))
(if (== (inq_called) "")
(set_msg_level 0)
)
(= ret_code (edit_file))
(set_msg_level old_msg_level)
(if (== ret_code 1)
(display_file_name)
)
(return ret_code)
)
)
;**
;** edit_next_buffer:
;**
;** Edits the next buffer in the buffer list in the current window. If
;** there are no other buffers, an error message is displayed.
;**
(macro edit_next_buffer
(
(string file_name)
(int new_buffer)
(= new_buffer (next_buffer))
(if (!= new_buffer (inq_buffer))
(
(set_buffer new_buffer)
(inq_names file_name)
(edit_file file_name)
)
;else
(error "No other buffers.")
)
)
)
;**
;** edit_prev_buffer:
;**
;** Edits the previous buffer in the buffer list.
;**
(macro edit_prev_buffer
(
(string file_name)
(int old_buffer)
(= old_buffer (inq_buffer))
(while (!= (next_buffer) old_buffer)
(set_buffer (next_buffer))
)
(if (!= (inq_buffer) old_buffer)
(
(inq_names file_name)
(edit_file file_name)
)
;else
(error "No other buffers.")
)
)
)
;**
;** delete_curr_buffer:
;**
;** This function deletes the current buffer, if it is unmodified,
;** there is another buffer in the list to replace it, and it is only
;** visible in one window.
;**
;** If the buffer is modified, the user is asked if he really wants to
;** delete the buffer. If he answers yes, the deletion is performed.
;**
;** If there are no other buffers, or the buffer is in more than one
;** window, the deletion is not performed.
;**
(macro delete_curr_buffer
(
(int old_buf_id
new_buf_id
)
(string reply
file_name
)
(= old_buf_id (inq_buffer))
(= new_buf_id (next_buffer))
(if (== old_buf_id new_buf_id)
(
(error "Can't delete: no other buffers.")
(return 0)
)
)
(if (!= (inq_views) 1)
(
(message "Can't delete: buffer is in multiple windows.")
(return 0)
)
)
(if (inq_modified)
(
(keyboard_flush)
(if (! (get_parm NULL reply "This buffer has not been saved. Delete [ynw]? " 1))
(return 0)
;else
(if (|| (! (strlen reply)) (! (index "yYwW" reply)))
(
(message "Buffer not deleted.")
(return 0)
)
)
)
(if (index "wW" reply)
(
(int old_msg_level
ret_code
)
(= old_msg_level (inq_msg_level))
(set_msg_level 0)
(= ret_code (write_buffer))
(set_msg_level old_msg_level)
(if (<= ret_code 0)
(return 0)
)
)
)
)
)
(set_buffer new_buf_id)
(inq_names file_name NULL)
(set_buffer old_buf_id)
(edit_file file_name)
(delete_buffer old_buf_id)
(return 1)
)
)
;**
;** _bad_key:
;**
;** This routine adds menus to some prompts.
;**
(replacement _bad_key
(
(int key_pressed)
(= key_pressed (read_char))
(if (&& (== (inq_command) "goto_bookmark") (== key_pressed (key_to_int "<Tab>")))
(return (_bookmark_menu))
)
(push_back key_pressed)
(return (_bad_key))
)
)
;**
;** _bookmark_menu:
;**
;** This routine actually handles the "invalid keystroke" event
;** when in the bookmark prompt.
;**
(macro _bookmark_menu
(
(int menu_buf
old_buf
curr_buf
line
col
i
num_bookmarks
_bookmark
)
(string bookmark
file_name
)
(global _bookmark)
(while (< i 10)
(
(if (goto_bookmark i curr_buf line col)
(++ num_bookmarks)
)
(++ i)
)
)
(if (== num_bookmarks 0)
(beep)
;else
(
(int num_lines
num_cols
lx
by
rx
ty
)
(= old_buf (inq_buffer))
(sprintf bookmark "%d bookmark%s" num_bookmarks (if (== num_bookmarks 1) "" "s"))
(set_buffer (= menu_buf (create_buffer bookmark NULL SYSTEM)))
(= num_bookmarks 0)
(= i 1)
(tabs 2 13 19 25 80)
(while (<= i 10)
(
(if (goto_bookmark i curr_buf line col)
(
(if (== (++ num_bookmarks) 1)
(insert "\n\tBookmark\tLine\tCol\tFile\n\t--------\t----\t---\t----")
)
(insert "\n")
(set_buffer curr_buf)
(inq_names file_name)
(sprintf bookmark "\t%d\t%d\t%d\t%s\t;" i line col file_name)
(sprintf bookmark "%s%d" bookmark i)
(set_buffer menu_buf)
(insert bookmark)
)
)
(++ i)
)
)
(set_buffer old_buf)
(= _bookmark -1)
(inq_screen_size num_lines num_cols)
(/= num_lines 2)
(/= num_cols 2)
(= lx (- num_cols 36))
(= rx (+ num_cols 36))
(= ty (- num_lines (+ 4 (/ (+ num_bookmarks 4) 2))))
(= by (+ ty (+ num_bookmarks 5)))
(_process_menu lx by rx ty NULL
" or  to move, <Enter> to select, <Esc> to exit"
NULL menu_buf "_bookmark_action" TRUE)
(if (>= _bookmark 0)
(
(sprintf bookmark "%d" _bookmark)
(push_back (key_to_int "<Enter>"))
(return bookmark)
)
)
)
)
(returns (inq_cmd_line))
)
)
;**
;** _bookmark_action:
;**
;** This is the action routine for the dialog manager.
;**
(macro _bookmark_action
(
(int event_type)
(string button_text)
(get_parm 0 event_type)
(switch event_type
DIALOG_MOVE_MENU
(
(get_parm 2 button_text)
(if (index button_text ";")
(returns TRUE)
;else
(returns FALSE)
)
)
DIALOG_PICK_MENU
NULL
DIALOG_F10
(
(get_parm 2 button_text)
(= _bookmark (atoi (substr button_text (+ (rindex button_text ";") 1))))
(_dialog_esc)
(returns TRUE)
)
)
)
)
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+167
View File
@@ -0,0 +1,167 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** column.cb:
**
** This file contains a set of macros that let perform block operations
** columns of text. These macros are called by the standard replacement
** macros; this makes sure that the column functions aren't pulled in unless
** they're needed.
*/
#define REG_MARK 1
#define COL_MARK 2
#define LINE_MARK 3
#define NI_MARK 4
#define NOTHING 0
#define REPLACE 1
#define REMOVE 2
void gen_block (string function_name, string message);
void _complete_col (int append);
/*
** _col_copy, _do_col_copy:
**
** This macro copies a marked area to another buffer. It uses the
** generic block operation routine to loop through the marked lines.
** It then inserts these lines into a special buffer. Once all the
** lines have been copied, this special buffer is copied to the scrap.
*/
void _col_copy (~int append)
{
global int col_buf = create_buffer ("Column", NULL, 1);
gen_block ("_do_col_copy", "Copying columns to scrap");
_complete_col (append);
raise_anchor ();
message ("Columns copied to scrap.");
}
int _do_col_copy (string line)
{
int old_buf = set_buffer (col_buf);
if (!index (line, "\n"))
line += "\n";
insert (line);
set_buffer (old_buf);
returns (NOTHING);
}
/*
** _col_cut, _do_col_cut:
**
** This macro cuts a marked area to another buffer. It uses the
** generic block operation routine to loop through the marked lines.
** It then inserts these lines into a special buffer. Once all the
** lines have been cut, this special buffer is copied to the scrap.
*/
void _col_cut (~int append)
{
int start_col;
col_buf = create_buffer ("Column", NULL, 1);
inq_marked (NULL, start_col);
gen_block ("_do_col_cut", "Deleting columns to scrap");
_complete_col (append);
raise_anchor ();
move_abs (0, start_col);
message ("Columns deleted to scrap.");
}
int _do_col_cut (string line)
{
int old_buf = set_buffer (col_buf);
if (!index (line, "\n"))
line += "\n";
insert (line);
set_buffer (old_buf);
returns (REMOVE);
}
/*
** _complete_col:
**
** This routine puts the column scrap buffer onto the regular scrap
** and then deletes it. If the append parameter is specified, it is passed
** through to copy.
*/
void _complete_col (int append)
{
int old_buf = set_buffer (col_buf);
top_of_buffer ();
drop_anchor (COL_MARK);
end_of_buffer ();
prev_char ();
copy (append);
set_buffer (old_buf);
delete_buffer (col_buf);
}
/*
** _col_paste, _do_col_paste:
**
** This routine pastes the standard scrap as columnar information.
*/
void _col_paste ()
{
col_buf = set_buffer (inq_scrap ());
top_of_buffer ();
drop_anchor (LINE_MARK);
end_of_buffer ();
gen_block ("_do_col_paste", "Inserting columns");
raise_anchor ();
set_buffer (col_buf);
message ("Columns inserted.");
}
int _do_col_paste (string line)
{
int scrap_buf = set_buffer (col_buf),
curr_col;
line = substr (line, 1, strlen (line) - 1);
inq_position (NULL, curr_col);
insert (line);
move_rel (1, 0);
move_abs (0, curr_col);
set_buffer (scrap_buf);
returns (NOTHING);
}
/*
** _col_delete, _do_col_delete:
**
** This macro deletes a marked columnar area. It uses the generic
** block operation routine to loop through the marked lines. It then
** simply tells the routine to remove the information.
*/
void _col_delete ()
{
int start_col;
inq_marked (NULL, start_col);
gen_block ("_do_col_delete", "Deleting columns");
raise_anchor ();
move_abs (0, start_col);
message ("Columns deleted.");
}
_do_col_delete (...)
{
returns (REMOVE);
}
Binary file not shown.
+204
View File
@@ -0,0 +1,204 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;**
;** column.m:
;**
;** This file contains a set of macros that let perform block operations
;** columns of text. These macros are called by the standard replacement
;** macros; this makes sure that the column functions aren't pulled in unless
;** they're needed.
;**
;** Revision history:
;** -----------------
#define REG_MARK 1
#define COL_MARK 2
#define LINE_MARK 3
#define NI_MARK 4
#define NOTHING 0
#define REPLACE 1
#define REMOVE 2
(extern gen_block)
;**
;** _col_copy, _do_col_copy:
;**
;** This macro copies a marked area to another buffer. It uses the
;** generic block operation routine to loop through the marked lines.
;** It then inserts these lines into a special buffer. Once all the
;** lines have been copied, this special buffer is copied to the scrap.
;**
(macro _col_copy
(
(int col_buf
append
)
(global col_buf)
(get_parm 0 append)
(= col_buf (create_buffer "Column" NULL 1))
(gen_block "_do_col_copy" "Copying columns to scrap")
(_complete_col append)
(raise_anchor)
(message "Columns copied to scrap.")
)
)
(macro _do_col_copy
(
(int old_buf)
(string line)
(get_parm 0 line)
(= old_buf (inq_buffer))
(set_buffer col_buf)
(if (! (index line "\n"))
(+= line "\n")
)
(insert line)
(set_buffer old_buf)
(returns NOTHING)
)
)
;**
;** _col_cut, _do_col_cut:
;**
;** This macro cuts a marked area to another buffer. It uses the
;** generic block operation routine to loop through the marked lines.
;** It then inserts these lines into a special buffer. Once all the
;** lines have been cut, this special buffer is copied to the scrap.
;**
(macro _col_cut
(
(int start_col
append
)
(get_parm 0 append)
(inq_marked NULL start_col)
(= col_buf (create_buffer "Column" NULL 1))
(gen_block "_do_col_cut" "Deleting columns to scrap")
(_complete_col append)
(raise_anchor)
(move_abs 0 start_col)
(message "Columns deleted to scrap.")
)
)
(macro _do_col_cut
(
(int old_buf)
(string line)
(get_parm 0 line)
(= old_buf (inq_buffer))
(set_buffer col_buf)
(if (! (index line "\n"))
(+= line "\n")
)
(insert line)
(set_buffer old_buf)
(returns REMOVE)
)
)
;**
;** _complete_col:
;**
;** This routine puts the column scrap buffer onto the regular scrap
;** and then deletes it. If the append parameter is specified, it is passed
;** through to copy.
;**
(macro _complete_col
(
(int old_buf
append
)
(get_parm 0 append)
(= old_buf (inq_buffer))
(set_buffer col_buf)
(top_of_buffer)
(drop_anchor COL_MARK)
(end_of_buffer)
(prev_char)
(copy append)
(set_buffer old_buf)
(delete_buffer col_buf)
)
)
;**
;** _col_paste, _do_col_paste:
;**
;** This routine pastes the standard scrap as columnar information.
;**
(macro _col_paste
(
(= col_buf (inq_buffer))
(set_buffer (inq_scrap))
(top_of_buffer)
(drop_anchor LINE_MARK)
(end_of_buffer)
(gen_block "_do_col_paste" "Inserting columns")
(raise_anchor)
(set_buffer col_buf)
(message "Columns inserted.")
)
)
(macro _do_col_paste
(
(int scrap_buf
curr_col
)
(string line)
(= scrap_buf (inq_buffer))
(get_parm 0 line)
(= line (substr line 1 (- (strlen line) 1)))
(set_buffer col_buf)
(inq_position NULL curr_col)
(insert line)
(move_rel 1 0)
(move_abs 0 curr_col)
(set_buffer scrap_buf)
(returns NOTHING)
)
)
;**
;** _col_delete, _do_col_delete:
;**
;** This macro deletes a marked columnar area. It uses the generic
;** block operation routine to loop through the marked lines. It then
;** simply tells the routine to remove the information.
;**
(macro _col_delete
(
(int start_col)
(inq_marked NULL start_col)
(gen_block "_do_col_delete" "Deleting columns")
(raise_anchor)
(move_abs 0 start_col)
(message "Columns deleted.")
)
)
(macro _do_col_delete
(returns REMOVE)
)
Binary file not shown.
+555
View File
@@ -0,0 +1,555 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** compile.cb:
**
** This file contains all of the standard BRIEF macros for compiling
** files.
*/
string add_to_path (string path, string name);
string escape_re (string original, ~string);
int next_error (~int action);
int cc (string pass_string, ~string legal_extension, ~int check_warnings, ~int background, ~int continuation);
void _cc_complete (int ret_code, string full_name, int check_warnings, string pass_string);
int cm (...);
int cb (...);
extern int _check_warnings, // Check for warnings in the compiler output?
_background; // Run the compiler in the background?
/*
** compile_it:
**
** This function automatically compiles the file in the current
** buffer. It uses the "BC<extension>" environment variable to
** determine what to do with any given file. If no "BC<extension>"
** environment variable exists for the specific file extension being
** compiled, compile_it checks to see if it's ".c", ".m" or ".asm". If
** it's a macro file the "cm" macro is executed; if it's a C file, a
** generic "cc" command is used, and if it's an ASM file, the Macro
** Assembler is invoked.
**
** Other compilers can be supported very easily. Simply set a
** "BC<extension>" environment variable to the "pass string" you
** want to use. For example, if you wanted to call the (fictitious)
** UnderWare C compiler, which has two passes called "under" and "ware",
** you'd use the command:
**
** set bcc="under %s;ware %s"
**
** You must place the pass string in quotes. If you don't, compile_it
** calls a macro named whatever is in the pass string. So, for example,
** if you accidently set your pass string using the command:
**
** set bcc=under %s;ware %s
**
** compile_it would call a macro named "under %s;ware %s". This probably
** isn't what you want -- but this feature can be useful if you want to
** run some sort of custom macro for the file extension (compile_it does
** this when compiling cm files).
**
** Also note that DOS requires you to double any % characters that
** appear in a batch file. So if you were setting the BCC variable in
** your autoexec, you would use the line:
**
** set bcc="under %%s;ware %%s"
**
** Each pass begins with the name of the executable program that does
** that compilation pass. That is followed by the a space, the special
** string "%s", which is replaced by the filename (with NO extension),
** and the multiple pass separation character ";". If you want to put
** a ";" in your pass string, use "\;".
**
** These special characters are very important -- don't forget them!
** Remember that the special "%s" string is only replaced by the filename,
** not the filename and the extension. Up to seven of these can be specified
** in any given pass. If your compiler requires the extension as well,
** place it after this string (e.g. "cc -c %s.c").
**
** If you want to pass options to your compiler, you can place them
** either before or after the "%s". Placing them before puts the option
** before the filename, and vice versa.
**
** If your compiler doesn't return an error code, put an exclamation
** point in front of the first pass string (either inside or outside the
** quotes); this will override the current warnings_only setting and
** automatically check for errors in the compiler output.
*/
int compile_it (void)
{
string extension, // File extension of the current file.
command; // Command to be used to compile file.
inq_names (NULL, extension);
command = trim (ltrim (inq_environment ("BC" + upper (extension))));
if (command != "")
{
if (index (command, "\""))
{
int loc,
background;
background = _background;
while (loc = index (command, "\""))
command = substr (command, 1, loc - 1) + substr (command, loc + 1);
if (substr (command, strlen (command), 1) == "&")
{
background = 1;
command = trim (substr (command, 1, strlen (command) - 1));
}
if ("!" == substr (command, 1, 1))
returns (cc (substr (command, 2), extension, 1, background));
else
returns (cc (command, extension, NULL, background));
}
else
{
int check_warnings = _check_warnings;
if (substr (command, 1, 1) == "!")
{
check_warnings = 1;
command = substr (command, 2);
}
returns (execute_macro (command, command, check_warnings));
}
}
else
switch (extension)
{
case "m":
returns (cm (_check_warnings));
case "asm":
returns (cc ("masm %s\\;", extension));
case "c":
returns (cc ("cc -c %s.c", extension));
case "cb":
returns (cb (_check_warnings));
default:
{
error ("Can't compile: no BC%s environment variable.", upper (extension));
returns (-1);
}
}
}
/*
** warnings_only:
**
** This macro toggles whether or not errors are searched for when a
** compile is done and the compiler returns "no errors". Note that its
** value is saved in the state file.
*/
int warnings_only (~int)
{
int ret_code,
previous_value;
previous_value = _check_warnings;
if (!(ret_code = get_parm (0, _check_warnings)))
_check_warnings = !_check_warnings;
if (!ret_code || inq_called () == "")
message ("Compile warning detection %s.", _check_warnings ? "on" : "off");
returns (previous_value);
}
/*
** bgd_compilation:
**
** This macro toggles whether or not compilation is done in the
** background under operating systems that support it. Note that this
** value is saved in the state file.
*/
int bgd_compilation (~int)
{
int ret_code,
previous_value;
previous_value = _background;
if (!(ret_code = get_parm (0, _background)))
_background = !_background;
if (!ret_code || inq_called () == "")
message ("Background compilation %s.", _background ? "on" : "off");
returns (previous_value);
}
/*
** cc:
**
** This routine compiles the file in the current buffer using the
** passed "pass string" and the BRIEF DOS command. It needs a lot
** of memory to run -- either turn swapping on or start with at least
** 256K and -M20. Of course, this may vary depending with the size
** and memory requirements of the specific compiler you're using.
**
** The "pass string" passed should be of the form:
**
** pass_1 %s;pass_2 %s;...pass_n %s
**
** The optional second parameter is an extended file type -- this is
** used by the "cm" and "cb" macros, and to compile other types of files
** (e.g. .asm).
**
** If no pass string is specified, it defaults to a generic "cc"
** command. If no extension is specified, it defaults to "c".
*/
int cc (string pass_string, ~string, ~int, ~int, ~int continuation)
{
string file_name, // The name of the file we're compiling.
legal_extension, // The extension of files we can compile.
path, // The path of the file we're compiling.
extension, // The extension of the file we're compiling.
command_line, // The compile command line.
old_path, // The original path we were on.
error_file; // The file to put error information in.
int loc, // Generic index place holder.
length, // Generic length place holder.
ret_code = 1, // Return code from DOS.
buffer_id, // Buffer ID of error buffer.
check_warnings, // Examine result of compile for errors?
background; // Do compilation in background?
/*
** We get the name of the file from inq_names and check to see
** if it's a legal extension.
*/
if (!get_parm (1, legal_extension))
legal_extension = "c";
inq_names (path, extension, file_name);
if (extension != legal_extension)
error ("Current buffer is not a .%s file.", legal_extension);
else
{
/*
** If the file has been modified, we want to make sure the
** current version gets compiled, so we write it to disk.
**
** Note that if the user does not specify a pass string, it
** defaults to a generic "cc" command.
*/
if (pass_string == "")
pass_string = "cc -c %s.c";
if (!get_parm (2, check_warnings))
check_warnings = _check_warnings;
if (!get_parm (3, background))
background = _background;
version (old_path);
if (old_path != "OS/2")
background = 0;
if (!continuation && inq_modified ())
{
int old_msg_level;
old_msg_level = inq_msg_level ();
set_msg_level (0);
ret_code = write_buffer ();
set_msg_level (old_msg_level);
}
if (ret_code > 0)
{
/*
** Now we parse the filename off the path string,
** making sure to handle the possible presence of forward
** and backward slash characters. We then replace the
** file_name's ".c" with ".err" for redirection purposes.
*/
path = substr (path, 1, rindex (path, substr (path, 3, 1)));
if (strlen (path) > 3)
path = substr (path, 1, strlen (path) - 1);
file_name = substr (file_name, 1, index (file_name, ".") - 1);
error_file = file_name + ".err";
ret_code = 0;
/*
** We want the .obj file to end up in the file's
** directory, so we change to the directory where the
** file is, saving the current directory. We also make
** the file's drive the default drive.
*/
getwd ("", command_line);
getwd (path, old_path);
old_path = substr (command_line, 1, 1) + substr (old_path, 2);
cd (path);
cd (substr (path, 1, 2));
/*
** This loop goes through each pass of the compiler,
** checks to see if the return code was OK, and, if so,
** continues along. If an error occurs, the loop exits
** immediately.
*/
while (!ret_code && strlen (pass_string))
{
if (loc = search_string ("[~\\\\];", pass_string))
{
command_line = substr (pass_string, 1, loc);
pass_string = substr (pass_string, loc + 2);
}
else
{
command_line = pass_string;
pass_string = "";
}
command_line += " >&" + error_file;
while (loc = index (command_line, "\\;"))
command_line = substr (command_line, 1, loc - 1) + substr (command_line, loc + 1);
/*
** Since environment variables don't allow "=" characters to
** appear in them, we use "--" as an alias.
*/
while (loc = index (command_line, "--"))
command_line = substr (command_line, 1, loc - 1) + "=" + substr (command_line, loc + 2);
sprintf (command_line, command_line, file_name, file_name, file_name, file_name, file_name, file_name, file_name);
message ("%s", background ? command_line + " &" : command_line);
if (background)
{
string completion_rtn;
inq_names (file_name);
sprintf (completion_rtn, "_cc_complete \"%s\" %d \"%s\"", file_name, check_warnings, escape_re (pass_string, "\""));
dos (command_line, 0, completion_rtn);
break;
}
else if ((ret_code = dos (command_line, 0)) > 0)
next_error ();
else if (ret_code == 0 && check_warnings)
ret_code = next_error (2);
}
/*
** Finally, we restore the old directory. If the
** compilation did not succeed, the next_error macro
** was called to place the cursor under the error.
**
** Otherwise, the temporary file is deleted and a
** message is printed.
*/
if (!background && ret_code <= 0)
{
del (error_file);
if (ret_code == 0)
message ("Compilation successful.");
}
cd (substr (old_path, 3));
cd (substr (old_path, 1, 2));
}
}
returns (ret_code);
}
/*
** _cc_complete:
**
** This is the completion routine for background compilation.
*/
void _cc_complete (int ret_code, string full_name, int check_warnings, string pass_string)
{
int in_memory,
old_buf_id = inq_buffer (),
buf_id,
loc;
string file_name,
extension;
/*
** First, we check to see if the buffer being compiled
** is in the buffer list.
*/
in_memory = (inq_buffer (full_name) != 0);
/*
** If in_memory is true then the current buffer is set
** to the buffer we're compiling. Otherwise, we have to
** read it into memory to prepare for a possible next_error.
*/
loc = strlen (full_name);
while (!index ("/\\", substr (full_name, loc, 1)))
--loc;
file_name = substr (full_name, loc + 1);
if (!in_memory)
if (buf_id = create_buffer (file_name, full_name))
set_buffer (buf_id);
else
error ("_cc_complete: fatal error, can't edit %s.", file_name);
inq_names (NULL, extension);
if (!ret_code)
{
if (check_warnings)
ret_code = next_error (3);
if (!ret_code)
if (pass_string == "")
{
message ("Compilation of %s successful.", file_name);
del (substr (full_name, 1, rindex (full_name, ".")) + "err");
}
else
cc (pass_string, extension, check_warnings, 1, 1);
}
/*
** At this point, we know we can clean up. First, we set
** the current buffer to the one we started with. Then, if we
** temporarily edited the buffer we were compiling, we delete
** it.
*/
set_buffer (old_buf_id);
if (!in_memory)
delete_buffer (buf_id);
if (ret_code)
{
beep ();
if (buf_id == 0 || old_buf_id == buf_id)
error ("Error compiling %s; press %s.", file_name, inq_assignment ("next_error", 1));
else
error ("Error compiling %s.", file_name, inq_assignment ("next_error", 1));
}
}
/*
** cm:
**
** This macro compiles the macro in the current buffer (if there is one).
** If the compilation was successful, the macro is re-loaded (or loaded, as
** the case may be). If the compilation failed, the errorfix macro
** is used to locate the problem in the .m file.
**
** Note that the "cc" macro is used to do most of the work. This macro
** merely calls "cc" with the parameters required for compilation of a
** macro file, then loads the file if the compilation was successful.
*/
int cm (...)
{
int check_warnings,
curr_parm,
ret_code;
string command_line = "cm";
for (curr_parm = 1 ; curr_parm >= 0 && !get_parm (curr_parm, check_warnings) ; curr_parm--);
if (curr_parm > 0)
get_parm (0, command_line);
command_line += " %s";
if (!(ret_code = cc (command_line, "m", check_warnings, 0)))
{
int old_msg_level;
string name;
inq_names (name);
name = substr (name, 1, rindex (name, ".") - 1);
old_msg_level = inq_msg_level ();
set_msg_level (3);
delete_macro (name);
set_msg_level (old_msg_level);
load_macro (name);
message ("Macro compiled and loaded.");
}
returns (ret_code);
}
/*
** cb:
**
** This macro compiles the CBRIEF macro in the current buffer (if
** there is one). If the compilation was successful, the macro is
** re-loaded (or loaded, as the case may be). If the compilation failed,
** the errorfix macro is used to locate the problem in the .m file.
**
** Note that the "cc" macro is used to do most of the work. This macro
** merely calls "cc" with the parameters required for compilation of a
** CBRIEF file, then loads the file if the compilation was successful.
*/
int cb (...)
{
int check_warnings,
curr_parm,
ret_code;
string command_line = "cb";
for (curr_parm = 1 ; curr_parm >= 0 && !get_parm (curr_parm, check_warnings) ; curr_parm--);
if (curr_parm > 0)
get_parm (0, command_line);
command_line += " %s";
if (!(ret_code = cc (command_line, "cb", check_warnings, 0)))
{
int old_msg_level;
string name;
inq_names (name);
name = substr (name, 1, rindex (name, ".") - 1);
old_msg_level = inq_msg_level ();
set_msg_level (3);
delete_macro (name);
set_msg_level (old_msg_level);
load_macro (name);
message ("Macro compiled and loaded.");
}
returns (ret_code);
}
Binary file not shown.
+397
View File
@@ -0,0 +1,397 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;**
;** compile.m:
;**
;** This file contains all of the standard BRIEF macros for compiling
;** files.
;**
;** Revision history:
;** -----------------
(extern add_to_path
next_error
_check_warnings
)
;**
;** compile_it:
;**
;** This function automatically compiles the file in the current
;** buffer. It uses the "BC<extension>" environment variable to
;** determine what to do with any given file. If no "BC<extension>"
;** environment variable exists for the specific file extension being
;** compiled, compile_it checks to see if it's ".c", ".m" or ".asm". If
;** it's a macro file the "cm" macro is executed; if it's a C file, a
;** generic "cc" command is used, and if it's an ASM file, the Macro
;** Assembler is invoked.
;**
;** Other compilers can be supported very easily. Simply set a
;** "BC<extension>" environment variable to the "pass string" you
;** want to use. For example, if you wanted to call the (fictitious)
;** UnderWare C compiler, which has two passes called "under" and "ware",
;** you'd use the command:
;**
;** set bcc="under %s;ware %s"
;**
;** You must place the pass string in quotes. If you don't, compile_it
;** calls a macro named whatever is in the pass string. So, for example,
;** if you accidently set your pass string using the command:
;**
;** set bcc=under %s;ware %s
;**
;** compile_it would call a macro named "under %s;ware %s". This probably
;** isn't what you want -- but this feature can be useful if you want to
;** run some sort of custom macro for the file extension (compile_it does
;** this when compiling cm files).
;**
;** Also note that DOS requires you to double any % characters that
;** appear in a batch file. So if you were setting the BCC variable in
;** your autoexec, you would use the line:
;**
;** set bcc="under %%s;ware %%s"
;**
;** Each pass begins with the name of the executable program that does
;** that compilation pass. That is followed by the a space, the special
;** string "%s", which is replaced by the filename (with NO extension),
;** and the multiple pass separation character ";". If you want to put
;** a ";" in your pass string, use "\;".
;**
;** These special characters are very important -- don't forget them!
;** Remember that the special "%s" string is only replaced by the filename,
;** not the filename and the extension. Up to two of these can be specified
;** in any given pass. If your compiler requires the extension as well,
;** place it after this string (e.g. "cc -c %s.c").
;**
;** If you want to pass options to your compiler, you can place them
;** either before or after the "%s". Placing them before puts the option
;** before the filename, and vice versa.
;**
;** If you compiler doesn't return an error code, put an exclamation
;** point in front of the first pass string (either inside or outside the
;** quotes); this will override the current warnings_only setting and
;** automatically check for errors in the compiler output.
;**
(macro compile_it
(
(string extension
command
)
(inq_names NULL extension)
(= command (trim (ltrim (inq_environment (+ "BC" (upper extension))))))
(if (!= command "")
(
(if (index command "\"")
(
(int loc)
(while (= loc (index command "\""))
(= command (+ (substr command 1 (- loc 1)) (substr command (+ loc 1))))
)
(if (== "!" (substr command 1 1))
(returns (cc (substr command 2) extension 1))
;else
(returns (cc command extension))
)
)
;else
(if (== "!" (substr command 1 1))
(returns (execute_macro (substr command 2) 1))
;else
(returns (execute_macro command _check_warnings))
)
)
)
;else
(
(if (== extension "m")
(returns (cm))
;else
(if (== extension "asm")
(returns (cc "masm %s\\;" extension))
;else
(if (== extension "c")
(returns (cc "cc -c %s.c" extension))
;else
(
(error "Can't compile: no BC%s environment variable." (upper extension))
(returns -1)
)
)
)
)
)
)
)
)
;**
;** warnings_only:
;**
;** This macro toggles whether or not errors are searched for when a
;** compile is done and the compiler returns "no errors". Note that its
;** value is saved in the state file.
;**
(macro warnings_only
(
(int ret_code
previous_value
)
(= previous_value _check_warnings)
(if (! (= ret_code (get_parm 0 _check_warnings)))
(= _check_warnings (! _check_warnings))
)
(if (|| (! ret_code) (== (inq_called) ""))
(message "Compile warning detection %s." (if _check_warnings "on" "off"))
)
(returns previous_value)
)
)
;**
;** cc:
;**
;** This routine compiles the file in the current buffer using the
;** passed "pass string" and the BRIEF DOS command. It needs a lot
;** of memory to run (you should have at least 256K and start with -M20)
;** so be careful!
;**
;** The "pass string" passed should be of the form:
;**
;** pass_1 %s;pass_2 %s;...pass_n %s
;**
;** The optional second parameter is an extended file type -- this is
;** used by the "cm" macro, and to compile other types of files (e.g.
;** .asm).
;**
;** If no pass string is specified, it defaults to a generic "cc"
;** command. If no extension is specified, it defaults to "c".
;**
(macro cc
(
(string file_name ;** The name of the file we're compiling.
command_line ;** The compile command line.
path ;** The path of the file we're compiling.
old_path ;** The original path we were on.
passes ;** The names of the passes.
error_file ;** The file to put error information in.
)
(int loc ;** Generic index place holder.
ret_code ;** Return code from DOS.
buffer_id ;** Buffer ID of error buffer.
check_warnings ;** Examine resule of compile for errors?
)
;**
;** We get the name of the file from inq_names (the extension is
;** put in the command_line variable so we don't have to declare too
;** many strings) and check to see if it is a C file.
;**
(if (! (get_parm 1 passes))
(= passes "c")
)
(if (! (get_parm 2 check_warnings))
(= check_warnings _check_warnings)
)
(inq_names path command_line file_name)
(= ret_code 1)
(if (== command_line passes)
(
;**
;** If the file has been modified, we want to make sure the
;** current version gets compiled, so we write it to disk.
;**
;** Note that if the user does not specify a pass string, it
;** defaults to a generic "cc" command, which works with the
;** Wizard C compiler (and a few others).
;**
(if (! (get_parm 0 passes))
(= passes "cc -c %s.c")
)
(if (inq_modified)
(
(int old_msg_level)
(= old_msg_level (inq_msg_level))
(set_msg_level 0)
(= ret_code (write_buffer))
(set_msg_level old_msg_level)
)
)
(if (>= ret_code 0)
(
;**
;** Now we parse the filename off the path string,
;** making sure to handle the possible presence of forward
;** and backward slash characters. We then replace the
;** file_name's ".c" with ".err" for redirection purposes.
;**
(= path (substr path 1 (rindex path (substr path 3 1))))
(if (> (strlen path) 3)
(= path (substr path 1 (- (strlen path) 1)))
)
(= file_name (substr file_name 1 (- (index file_name ".") 1)))
(= error_file (+ file_name ".err"))
(= ret_code 0)
;**
;** We want the .obj file to end up in the file's
;** directory, so we change to the directory where the
;** file is, saving the current directory. We also make
;** the file's drive the default drive.
;**
(getwd "" command_line)
(getwd path old_path)
(= old_path (+ (substr command_line 1 1) (substr old_path 2)))
(cd path)
(cd (substr path 1 2))
;**
;** If there is already a buffer for the error file, we
;** "create" it (create_buffer returns the ID of a buffer
;** that already existed) and then delete it immediately.
;** Note that under some very obscure circumstances, the
;** create_buffer call could fail. If it does, it'll
;** return 0, which is an invalid buffer id. We check for
;** this case since delete_buffer does not.
;**
(if (= buffer_id (create_buffer "Error File" error_file 1))
(delete_buffer buffer_id)
)
;**
;** This loop goes through each pass of the compiler,
;** checks to see if the return code was OK, and, if so,
;** continues along. If an error occurs, the loop exits
;** immediately.
;**
(while (&& (! ret_code) (strlen passes))
(
(if (= loc (search_string "[~\\\\]\\c;" passes))
(
(= command_line (substr passes 1 (- loc 1)))
(= passes (substr passes (+ loc 1)))
)
;else
(
(= command_line passes)
(= passes "")
)
)
(+= command_line (+ " >&" error_file))
(while (= loc (search_string "\\\\;" command_line))
(= command_line (+ (substr command_line 1 (- loc 1)) (substr command_line (+ loc 1))))
)
(sprintf command_line command_line file_name file_name file_name file_name file_name file_name file_name)
(message command_line)
(if (> (= ret_code (dos command_line 0)) 0)
(next_error)
;else
(if (&& (== ret_code 0) check_warnings)
(= ret_code (next_error 2))
)
)
)
)
;**
;** Finally, we restore the old directory. If the
;** compilation did not succeed, the next_error macro
;** was called to place the cursor under the error.
;**
;** Otherwise, the temporary file is deleted and a
;** message is printed.
;**
(if (<= ret_code 0)
(
(del error_file)
(if (== ret_code 0)
(message "Compilation successful.")
)
)
)
(cd (substr old_path 3))
(cd (substr old_path 1 2))
)
)
)
;else
(error "Current buffer is not a .%s file." passes)
)
(returns ret_code)
)
)
;**
;** cm:
;**
;** This macro compiles the macro in the current buffer (if there is one).
;** If the compilation was successful, the macro is re-loaded (or loaded, as
;** the case may be). If the compilation failed, the errorfix macro
;** is used to locate the problem in the .m file.
;**
;** Note that the "cc" macro is used to do most of the work. This macro
;** merely calls "cc" with the parameters required for compilation of a
;** macro file, then loads the file if the compilation was successful.
;**
(macro cm
(
(int check_warnings
curr_parm
)
(string command_line)
(= curr_parm 10)
(while (&& (> curr_parm 0) (! (get_parm curr_parm check_warnings)))
(-- curr_parm)
)
(if (> curr_parm 0)
(
(get_parm 0 command_line)
(if (strlen (= command_line (trim (ltrim command_line))))
(= command_line (+ " " command_line))
)
)
)
(= command_line (+ (+ "cm" command_line) " %s"))
(if (! (cc command_line "m" check_warnings))
(
(int old_msg_level)
(string name)
(inq_names name)
(= name (substr name 1 (- (strlen name) 2)))
(= old_msg_level (inq_msg_level))
(set_msg_level 3)
(delete_macro name)
(set_msg_level old_msg_level)
(load_macro name)
(message "Macro compiled and loaded.")
)
)
)
)
+17
View File
@@ -0,0 +1,17 @@
void copyrite ()
/*
Insert a copyright notice at the beginning of the current line.
After the copyright notice is inserted the cursor is positioned
at the beginning of the line following "All rights reserved."
You can assign this macro to a key using:
(assign_to_key "<Ctrl-F1>" "copyrite" )
This should be placed in your initials macro along with a command to
load the copyrite macro. The command is :
(load_macro "copyrite" )
*/
{
beginning_of_line();
insert ( " Copyright 1990 SDC Partners II L.P.\n" );
insert ( " All rights reserved.\n" );
}
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+566
View File
@@ -0,0 +1,566 @@
HOW TO USE THE BRIEF DIALOG MANAGER PACKAGE
WHAT IS THE DIALOG MANAGER?
The BRIEF dialog manager is a macro package containing tools for
generating pop-up menus and dialog boxes. Menus allow a user to perform
complicated tasks by choosing from lists of possible actions. Dialog
boxes allow a user to answer questions and fill in forms, while possibly
restricting the set of valid answers.
Many of BRIEF's standard macros (Help, for example) use the dialog
manager. You can use the dialog manager in your own macros, too.
WHERE IS THE DIALOG MANAGER?
Source code for the package is located in the files dialog.m and
dialog.h; the compiled version is in dialog.cm.
WHY USE THE DIALOG MANAGER?
The BRIEF dialog manager provides a standard user interface for macros.
If you write a macro that uses this interface properly, it will have the
look and feel of the standard commands that are shipped with BRIEF, and
any BRIEF user will be able to use it with minimal effort.
Using the dialog manager conserves memory and avoids reinventing the
wheel. Suppose you frequently use Help and three other macro packages
with separate user interfaces. That's a lot of macros to load at once;
BRIEF may spend a fair amount of time re-reading the disk. The macros
will take up far less memory if they reuse the same code.
WHAT CAPABILITIES ARE PROVIDED?
The dialog manager is essentially just two macro calls, one to create
and process a menu, and one to create and process a dialog box.
Although the dialog manager contains dozens of other macros (as well as
several global variables,) you should seldom need to deal with them.
(Consult the source code for more information.)
Menus are pop-up windows, within which one line ("button") is always
highlighted. Pressing Enter ("picking") causes an action associated
with the highlighted button to be executed. The up and down arrow keys
move the highlight up or down. Windows scroll vertically as needed.
Menus offer a choice of several actions. These actions may invoke other
menus or dialog boxes. In Help, for example, picking some buttons
causes a window of help information on a particular topic to appear;
picking others causes another menu (more detailed) to appear.
Dialog boxes are the other half of the dialog manager. Dialog boxes are
pop-up windows that contain descriptive text and any of several kinds of
input fields. A user may move between fields and change the contents of
any field. These changes can be saved or cancelled as a group.
The kinds of input fields are:
Filenames
Lists
Integers
Nonblank strings
Strings
LISTS
Lists, like menus, are multiple-choice situations; however, lists are
choices of values, not actions, and the values are usually mutually
exclusive. One very common list has two choices: Yes and No.
Lists appear on the screen on a single line, with items separated by
whitespace. A highlight is used to mark the currently selected item
while the user's cursor is on the field; when he or she leaves, the
highlight changes to a pair of parentheses.
A list can be paired with a text string, which is usually a question:
Do you want to save your changes? (Yes)No
Line drawing style: Single(Double)Mixed None
FILENAMES, INTEGERS, NONBLANK STRINGS, AND STRINGS
The number of possible answers to a question is often so great that a
list is awkward or impossible. In such situations, it's best to let the
user to type in his or her answer, then check it for validity. The user
can be asked to re-enter an invalid answer.
Filenames, Integers, Nonblank strings, and Strings behave identically
except that they use different validation criteria. Strings are not
checked at all. Nonblank strings may not be blank. Integer fields must
contain an integer value, and Filename fields must contain a
syntactically legal path name.
Fields are one line deep and may extend from their beginning to the
right edge of the window. The entire field is highlighted when the
user's cursor enters it; the highlight disappears as soon as anything
happens. When the user's cursor leaves, the field contents are
validated.
KEY ASSIGNMENTS
The key assignments for moving around and between menus and dialog boxes
are standardized. You should not change these key assignments, although
you may add your own to the list.
These key assignments are uniform throughout the dialog manager:
Esc Exit all levels Keypad minus Exit 1 level
Ctrl-Home Top of window Ctrl-End End of window
Within menus, the additional assignments are:
Enter Pick from menu
Up arrow Previous item Down arrow Next item
Backspace Previous item Space Next item
Home First item End Last item
PgUp Previous page PgDn Next page
Alphanumeric character sequence Next item beginning with characters
Within any dialog box field, the following keys are defined:
Enter Next field, or save if on last field (== Ctrl-m)
F10 Save dialog box and exit
Up arrow Previous field Down arrow Next field
Shift-Tab Previous field Tab Previous field
Within lists only, additional assignments are:
Left arrow Previous item Right arrow Next item
Backspace Previous item Space Next item
Home First item End Last item
Alphanumeric character Next item beginning with character
Within fields (excepting lists), additional key assignments are:
Left arrow Left Right arrow Right
Backspace Backspace Space Space
Home Beginning of field End End of field
Del Delete character Alt-k Delete to end
Ins, Alt-i Toggle insert mode Alt-d Delete field
When a field is highlighted, typing causes the contents of the field to
be replaced by the new characters.
MENUS
HOW TO CREATE A MENU
There are 3 steps involved in creating a menu.
1. Create a data file containing the names of the menu buttons and the
actions you want the buttons to invoke.
2. Write a macro that calls the dialog manager package.
3. Write the action macros that will handle everything the user does in
the menu.
CREATING THE MENU DATA FILE
Menu data files are usually given a .mnu extension and kept in the same
directory as the help files (specified by BHELP).
A menu file contains one line for each line of the menu. Each line
consists of a button name and optional additional information. When
the menu is displayed, the additional information should be invisible
(just past the right edge of the window). The menu button is normally
centered in the visible part of the line.
For fastest operation, each line is normally pre-formatted; in this
example (taken from help.mnu), spaces are used to center the buttons in
the visible part of the window, which is delimited by the semicolons.
Everything to the right of the semicolons is considered "additional
information":
Help on Help ;display_help "help"
Quick Reference ;display_help "keyboard layout"
Key-Specific Help ;key_specific_help
You can also have the menu automatically formatted. If you do, you
must use a semicolon as the delimiter, and leading/trailing whitespace
around the buttons will be ignored:
Help on Help;display_help "help"
Quick Reference;display_help "keyboard layout"
Key-Specific Help;key_specific_help
Action macros, described below, are free to do whatever they want with
the additional information. In this case, the information is a macro
call (complete with a string parameter), and it is passed to
execute_macro.
CALLING UP THE MENU
The call to create and process a menu is as follows:
(_process_menu lx by rx ty title msg filename buf_id action fast
picked_line picked_text)
Parameters 0 through 3 are integers, the coordinates of the left (lx),
bottom (by), right (rx), and top (ty) edges of the window. These are
absolute screen coordinates; the top left corner of a 25x80 screen is
(0, 0) and the lower right is (24, 79). If lx equals rx or ty equals
by, the menu is positioned at (lx, ty) and the size will be computed
automatically based on the number of lines on the menu and the column
position of the first semicolon. (Be careful not to position menus
so close to the bottom and left edges of the screen so that there's
no room for automatic formatting.)
Parameter 4 is the title of the menu, a string to be displayed in the
top edge of the window. It may be at most 12 characters long.
Parameter 5 is a string, a message to be displayed in the bottom edge of
the window. Make sure it is shorter than the edge itself.
You should supply either, but not both, of parameters 6 and 7. Supply
NULL in the place of whichever parameter you omit. Parameter 6 is the
filename of a menu data file (in the BHELP directory), while parameter 7
is the identifier of a buffer containing a menu data file. Use
parameter 7 if you have a .mnu file already in memory and want to keep
it there; otherwise, use parameter 6 and the dialog manager will delete
the buffer when you're done with it. (If you use parameter 7, then the
title you passed in parameter 4 will be ignored, and the buffer name
already in existence will be used.)
Note that parameter 6 is assumed to be the name of a file in the
BHELP directory unless an absolute path name is supplied. The dialog
manager assumes that any name containing the characters /, \, or : is
an absolute path.
Parameter 8 is a string containing the name of your main action macro,
described below.
Parameter 9 may be omitted. If it is passed and TRUE, your menu file
is not formatted in any way, saving oodles of time when it pops up.
If you use this parameter, make sure to pre-format your .mnu file.
Parameter 10 is an optional integer variable which will be set to the
number of the menu button that the user picks. It is only valid when
the call to _process_menu returns TRUE. If the user presses <Esc> or
<Keypad minus> to escape from a menu, this parameter will be zero.
Parameter 11 is an optional string variable which will be set to the
text of the menu button that the user picks. It is only valud when
the call to _process_menu returns TRUE and parameter 10 is nonzero.
The dialog manager assumes the values you pass it are correct, so be
careful.
When the call to _process_menu is encountered, the menu will pop up and
processing of the user's keystrokes will begin immediately. Processing
will stop when the user presses Esc (or the keypad minus key), and
control will return to your macro, just after the _process_menu call.
_process_menu returns TRUE if it was able to create and process a menu,
FALSE if an error occurred.
EVENTS
We have written the dialog manager to be as flexible as possible.
Hence, the system leaves a lot of decisions and a lot of work up to your
action macro. The dialog manager is event-driven; it quietly goes about
its business until an "event" of significance occurs, at which point it
taps your macro on the shoulder, informs it of the situation, and waits
for a response before continuing.
Here's a list of all significant events, for both menus and dialog
boxes. Matching #define statements are contained in the file
"dialog.h". You should #include this file in any macro file you write
that calls the dialog manager, so that you can refer to the event types
by symbolic name rather than by number.
DIALOG_INIT The dialog manager has just been invoked
DIALOG_TERM The dialog manager is exiting
DIALOG_ENTER_FIELD The cursor has just entered a non-list field
DIALOG_EXIT_FIELD The cursor has just left a non-list field
DIALOG_ENTER_LIST The cursor has just entered a list
DIALOG_EXIT_LIST The cursor has just left a list
DIALOG_ALTER_LIST The current item in a list has just been changed
DIALOG_ALTER_MENU The current item in a menu has just been changed
DIALOG_MOVE_MENU (Same as DIALOG_ALTER_MENU)
DIALOG_PICK_MENU The user has just selected a menu button with Enter
DIALOG_ESCAPE The user has just pressed Esc to exit all levels
DIALOG_F10 The user has just pressed F10 to save a dialog box
DIALOG_GREY_MINUS The user has just pressed the keypad minus key
DIALOG_CREATE_MENU A menu buffer has just been made current
DIALOG_CREATE_DBOX A dialog box data buffer "
HOW TO WRITE THE MENU ACTION MACROS
When you're working with menus, only the invoke/exit events, the
Esc/keypad minus events, and the events for changing or selecting menu
items can happen. Your job is to provide a single macro that responds
to these events; the name of this macro is parameter 8 in the call to
_process_menu, and the macro is called by _process_menu whenever one of
these events occurs.
Suppose you call your action macro "action". When called, action will
be passed three parameters:
(action event_type line text)
The first parameter is an integer matching one of the above #defines.
The second is the number of the current line in the menu (note that this
is also the number a user will see as Line: in the BRIEF message area).
The third is the text of the entire button, including the delimiter and
additional information (if any).
In the BRIEF macro language, parameters in the calling function are only
evaluated when the called function explicitly requests the parameter.
This means that, for best performance, your action macro should never
get a parameter it does not need.
The normal strategy for processing events within a menu action macro is
as follows:
1. Get the event type parameter.
2. If the event type is DIALOG_PICK_MENU, then get the line number or
text parameters and process them as desired. Note that the dialog
manager does NOT execute an action associated with a button
automatically. Your action macro must parse the button text and execute
the command.
Commonly, a pick event will cause the action macro to pop up a window
of text (such as help) and enter a process under the user's control.
The window will remain visible until the user presses Esc or Keypad
minus to signal he's done. If the user pressed Esc, the action macro
should push the Esc back into the keyboard buffer so that a DIALOG_ESC
event is generated as soon as the action macro returns.
3. If the event type is DIALOG_CREATE_MENU, the unformatted menu
is the current buffer, and its name is the text parameter. You can
use this event to add buttons to the menu.
(If the event type is anything else, you usually don't need to do any
more. However, if you want to add key assignments to the normal menu
keymap, you can use DIALOG_INIT as a signal to add them, and DIALOG_TERM
as a signal to remove them. And if you want to preclude the user from
moving to a particular line of the menu (for example, a heading) then
you can use DIALOG_MOVE_MENU.)
3. Return TRUE. The only time you should return FALSE is if the event
was DIALOG_MOVE_MENU, and the line number or text was such that you
don't want the cursor to be allowed to move to it (other lines will be
tried until EOF or until DIALOG_MOVE_MENU succeeds).
ACTION MACRO EXAMPLE
The following macro, when called by the dialog manager, will handle two
types of events. First, the user will not be allowed to move to line 1
or line 4. Second, when the user picks a button, this macro will use
the additional information present in the .mnu file to call another macro.
(macro action
(
(int event_type
line_no
retval
)
(string button_text)
(get_parm 0 event_type)
(= retval TRUE)
(switch event_type
DIALOG_MOVE_MENU
(
(get_parm 1 line_no)
(if (|| (== line_no 1) (== line_no 4))
(= retval FALSE)
)
)
DIALOG_PICK_MENU
(
(get_parm 2 button_text)
;** Trim the button name and treat the additional
;** information as a command that can be executed.
(execute_macro (substr button_text
(+ (index button_text ";") 1)))
)
)
(returns retval)
)
)
DIALOG BOXES
HOW TO CREATE A DIALOG BOX
As with menus, there are 3 steps to creating a dialog box: creating a
data file, writing a macro that calls the dialog manager, and writing
action macros.
DATA FILES FOR DIALOG BOXES
Dialog box data files must be kept in the BHELP directory. Like menu
files, they contain one line for each item displayed. Each line
contains the type of the input field, the row and column coordinates
(relative to the window's origin) at which the field should be placed,
and the field's initial contents. The number of fields is unlimited
because dialog boxes, like menus, can scroll vertically.
The row and column coordinates must be surrounded by parentheses and
separated by a comma. The initial contents must be surrounded by double
quotes. Whitespace may go just about anywhere, and you can have
comments. The following example shows a number of legal ways of
defining fields, and descriptive text, in a dialog box:
;** Get the speed using a 3-item list.
Text at (1, 1) is "Speed:"
List ( 1, 8 ) = "(Slow)Medium Fast"
;** Get the user's name. Make sure they enter one.
text (3,1) "Name:"
nonblank(3,9) "Your name goes here"
;** Prompt for user's age. Make sure it's numeric.
T (5, 1) "Age:"
I(5,9)"24"
The first non-whitespace character on a line defines the type of the
field. A 'T' means that this line is a descriptive text string that can
be displayed only. The letters F, L, I, N, and S denote Filenames,
Lists, Integers, Nonblank strings, and Strings.
All fields, even lists and integers, are really strings. Hence, you
should format the initial contents of every field as a quoted string, as
in the example above.
List strings have a special format. Items must be separated by single
tab characters (since spaces are allowed in item names). The item that
is to be initially highlighted should be surrounded by parentheses
instead of tabs.
Position lists as you would any other field. If a list begins with
a (, the dialog manager will compensate for you.
If you omit the current item in a list, or if you supply a field that's
too wide for the window, the invalid field will not be displayed and an
error message will.
The dialog manager does not check to see if any fields overlap. Hence,
only one input field is allowed per line. Text can be placed anywhere
except to the right of an input field.
HOW TO CALL UP A DIALOG BOX
The call to create and process a dialog box is nearly identical to the
call to create a menu, except that the macro name is _process_dialog_box:
(_process_dialog_box lx by rx ty title msg filename buf_id action)
All parameters have the same meaning as for _process_menu, except:
1. There is no automatic sizing for dialog boxes, so lx must not equal
rx, and by must not equal ty.
2. Parameter 4, the title, is always used, even when a buffer ID is passed
for parameter 7.
3. There are no parameters 9, 10, or 11.
This call may return when the user presses F10, Esc, or the keypad minus
key. _process_dialog_box returns TRUE if it was successful, FALSE if an
error occurred.
HOW TO WRITE THE ACTION MACROS
The first two parameters passed to your action function are the event
type and line number. The third parameter is either (for lists) the
text of the current list item, not counting separator characters, or
(for other field types) the full text of the field, not counting the
newline at the end.
Any event may occur in a dialog box except DIALOG_ALTER_MENU or
DIALOG_PICK_MENU. However, the only events you normally have to worry
about are DIALOG_EXIT_FIELD, DIALOG_EXIT_LIST, and DIALOG_F10.
You can perform additional validation on the contents of a field when
the user wants to move to another field (DIALOG_EXIT_FIELD). After the
dialog manager has performed its built-in type checking on the field,
your action macro will be called. If your action macro returns FALSE
for any reason, the user will not be allowed to leave the field. You
can use a String field coupled with your own validation function to
check for almost any value. Lists are not validated, since all the
possible answers are known in advance.
When the user leaves a field or a list (DIALOG_EXIT_FIELD or
DIALOG_EXIT_LIST), keep track of the value of that input field. There
is no way to determine the value of an input field at any other time.
We recommend you use a separate buffer, where each line represents the
contents of one input field, for dialog boxes containing more than three
or four input fields; otherwise, use string variables to store the
current values.
Treat DIALOG_F10 as a signal that the user is satisfied with his or her
changes and wishes to save them. The current list or field will be
exited before DIALOG_F10 occurs. When it does, process the values you
have saved in your macro. (DIALOG_ESC and DIALOG_GREY_MINUS should just
ignore the saved values.)
EXAMPLE
This data file ("example") defines a dialog box containing two lists.
Text (1, 3) = "Do you want case-sensitive search?"
List (1, 38) = "(Yes)No"
Text (3, 3) = "Do you want regular expressions?"
List (3, 38) = "(Yes)No"
This macro puts up a dialog box containing the above information, and
defines two string variables which are used by the action macro. Both
variables are set to Yes, since the data file's defaults are Yes.
(macro put_up_box
(
(string case_sens
reg_exp
)
(global case_sens
reg_exp
)
(= case_sens "Yes")
(= reg_exp "Yes")
(_process_dialog_box 10 15 60 10 "Search" "Set search parameters"
"example" NULL "action")
)
)
The following macro will process the dialog box, and save the current
values when F10 is pressed:
(macro action
(
(int event_type
line_no
)
(string button_text)
(get_parm 0 event_type)
(switch event_type
DIALOG_EXIT_LIST
(
(get_parm 1 line_no)
(get_parm 2 button_text)
(if (== line_no 1)
(= case_sens button_text)
;else
(= reg_exp button_text)
)
)
DIALOG_F10
(
(search_case (if (== case_sens "Yes") 0 1))
(toggle_re (if (== reg_exp "Yes") 1 0))
)
)
(returns TRUE)
)
)
A more sophisticated macro could keep the data file in a buffer and
continuously alter it to make sure the correct values of case
sensitivity and regular expressions were always displayed.
That's all you need to know to design menus and dialog boxes in the
BRIEF macro language. Enjoy.
+93
View File
@@ -0,0 +1,93 @@
/*
** Symbolic constants
*/
#define TRUE 1
#define FALSE 0
/*
** Dialog manager modes
*/
#define DIALOG_MENU_MODE 1
#define DIALOG_DBOX_MODE 2
/*
** Field types (use the mnemonic "FLINTSCRP")
*/
#define FILENAME 1
#define LIST 2
#define INTEGER 3
#define NONBLANK 4
#define TEXT 5
#define STRING 6
#define CHECK 7
#define RADIO 8
#define PUSH 9
#define GROUP 10
#define ENDGROUP 11
/*
** Event types for both dialog boxes and menus
*/
#define DIALOG_INIT -1
#define DIALOG_ENTER_FIELD -2
#define DIALOG_ENTER_LIST -3
#define DIALOG_ALTER_LIST -4
#define DIALOG_ALTER_MENU -5
#define DIALOG_MOVE_MENU -5
#define DIALOG_PICK_MENU -6
#define DIALOG_EXIT_FIELD -7
#define DIALOG_EXIT_LIST -8
#define DIALOG_TERM -9
#define DIALOG_ESCAPE -10
#define DIALOG_F10 -11
#define DIALOG_GREY_MINUS -12
#define DIALOG_CREATE_MENU -13
#define DIALOG_CREATE_DBOX -14
#define DIALOG_ENTER_CHECK -15
#define DIALOG_PICK_CHECK -16
#define DIALOG_EXIT_CHECK -17
#define DIALOG_ENTER_RADIO -18
#define DIALOG_PICK_RADIO -19
#define DIALOG_EXIT_RADIO -20
#define DIALOG_ENTER_PUSH -21
#define DIALOG_PICK_PUSH -22
#define DIALOG_EXIT_PUSH -23
/*
#define DIALOG_ENTER_GROUP ???
#define DIALOG_EXIT_GROUP ???
*/
/*
** External macro and global variable declarations
*/
int _process_menu (int lx, int by, int rx, int ty, string title,
string msg, ~string filename, ~int buf_id,
string action, ~int fast, ~int picked_line,
~string picked_text);
int _process_dialog_box (int lx, int by, int rx, int ty, string title,
string msg, ~string filename, ~int buf_id,
string action);
void _dialog_esc (void);
void _dialog_grey_minus (void);
void _dialog_f10 (void);
void _dialog_check_button (string button, int check);
int _dialog_is_checked (string button);
void _dialog_check_radio (string button, ~string group);
string _dialog_radio_checked (~string group);
#ifndef DIALOG_MAIN
extern string _dialog_dir;
extern int _dialog_level,
_dialog_type,
_dialog_row,
_dialog_col,
_dialog_mode;
#endif
File diff suppressed because it is too large Load Diff
+147
View File
@@ -0,0 +1,147 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg.h:
**
** This file contains the #defines used by the dialog manager, function
** prototypes for all of the dialog manager's support functions and the
** names of the dialog manager's 'private' global variables.
*/
#define CONTROL_TYPES "FLINTSCRPGE"
#define FIND_CONTROL "<[ \t]@\\c[FLINSCRP]"
#define FIND_ANY "<[ \t]@\\c[FLINTSCRPGE]"
#define FIND_RADIO "<[ \t]@\\c[RE]"
#define FIND_NEXT "<[ \t]@\\c[FLINSCPG]"
#define FIND_PREV "<[ \t]@\\c[FLINSCPE]"
/*
** The following are for searching in the Radiobutton management file.
*/
#define FIND_RADIO_POS "<*\"*\"(%d,%d)"
#define FIND_RADIO_LBL "<%s\"%s\"*%c>"
#define FIND_RADIO_GRP "<%s\"*\x07>"
#define RADIO_ON 0x07 // Radio-button "On" character
#define RADIO_OFF 0x20 // Radio-button "Off" character
#define RADIO_BTN "(%c) %s" // Radio-button graphic template
#define RADIO_ON_STR "" // Radio-button "on: character - string version
#define RADIO_OFF_STR " " // Radio-button "off" character - string version
#define RADIO_RIGHT ")" // right delimiter for a radio button
#define CHECK_BOX "[ ]"
#define CHECK_RGT_SRCH "]"
#define CHECK_LFT_SRCH "[" // Unused?
#define CHECKMARK "û"
#define NOCHECKMARK " "
#define PUSH_SRCH "[<®]?*[¯>]"
#define PUSH_RGT_SRCH "[¯>]"
#define PUSH_SEL_LFT "®" // Unused?
#define PUSH_SEL_RGT "¯" // Unused?
#define PUSH_NML_LFT "<" // Unused?
#define PUSH_NML_RGT ">" // Unused?
#define PUSH_BUTTON "< %s >"
#define PUSH_BUTTON_DEF "® %s ¯"
#define BTN_SRCH_STRN "<[\t ]@%c*(\\c[\t 0-9]+,[\t 0-9]+)*\"%s\"*%s"
int _dialog_exit ();
int _dialog_menu_down ();
int _dialog_menu_up ();
int _dialog_validate (string value);
int _dlg_goto_btn (int btn_type, string button_label, ~string group);
int _menu_highlight ();
int at_eol ();
int is_filename (string name);
replacement void _invalid_key ();
string _dialog_set_globals ();
string _dlg_check_btn ();
string _dlg_push_btn ();
string _dlg_radio_btn ();
string _dlg_radio_grp (void);
string _field_contents ();
string _list_button ();
string _menu_button ();
void _dialog_end ();
void _dialog_enter ();
void _dialog_home ();
void _dialog_menu_end ();
void _dialog_menu_home ();
void _dialog_menu_pgdn ();
void _dialog_menu_pgup ();
void _dialog_menu_pick ();
void _dialog_next ();
void _dialog_next_and_save ();
void _dialog_prev ();
void _dlg_beep (void);
void _dlg_btn_next (void);
void _dlg_btn_prev (void);
void _dlg_btn_tab_next (void);
void _dlg_btn_tab_prev (void);
void _dlg_goto_radio_ctrl (void);
void _dlg_pick_btn (void);
void _dlg_select_push (string button_label, int select);
void _field_bksp ();
void _field_del ();
void _field_del_line (void);
void _field_delete_to_eol (void);
void _field_end ();
void _field_home ();
void _field_insert (int key);
void _field_left ();
void _field_right ();
void _format_dialog ();
void _format_menu ();
void _list_end ();
void _list_go (int key);
void _list_highlight ();
void _list_home ();
void _list_next ();
void _list_prev ();
void _menu_go (int key);
void _remove_dialog_manager (void);
void mou_dlg_mnu_init ();
void mou_mnu_goto ();
void mou_dlg_goto (int ctrl_line);
void mou_mnu_dwn ();
void mou_mnu_up ();
void mou_dlg_exit ();
/*
** External functions.
*/
extern mouse_dialog_init ();
extern void wait ();
extern void _exit ();
extern string search_path (string path, string filename);
extern void to_bottom (void);
extern void center_line (void);
#ifndef DIALOG_MAIN
extern int _dialog_field_keymap;
extern int _dialog_list_keymap;
extern int _dialog_menu_keymap;
extern int _dialog_button_keymap;
extern int _dialog_size;
extern int _dialog_data_buf;
extern int _dialog_disp_buf;
extern int _dialog_radio_buf;
extern int _dialog_menu_time;
extern int _dialog_picked;
extern int _dialog_pb_state;
extern string _dialog_action_func;
extern string _dialog_menu_prefix;
extern string _dialog_default_pb;
#endif
+557
View File
@@ -0,0 +1,557 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_btn.cb:
**
** This file contains all BRIEF macros for managing dialog box buttons.
*/
#include "dialog.h"
#include "dlg.h"
/*
** _dialog_check_button:
**
** Places or removes a checkmark from the button specified
** by button label. If check is nonzero a check mark will be
** placed in the check box, otherwise a space will be placed in
** the check box.
**
** This is a user-accessible function.
*/
void _dialog_check_button (string button_label, int check)
{
int row, col;
save_position ();
if (_dlg_goto_btn ('C', button_label))
{
delete_char ();
insert (check ? CHECKMARK : NOCHECKMARK);
}
restore_position ();
}
/*
** _dialog_is_checked:
**
** Determines whether the control specified by button_label
** has a checkmark next to it. Returns TRUE if a check mark is
** present, FALSE otherwise.
**
** This is a user-accessible function.
*/
int _dialog_is_checked (string button_label)
{
int rval;
if (_dlg_goto_btn ('C', button_label))
{
if (read (1) == CHECKMARK)
rval = TRUE;
}
returns (rval);
}
/*
** _dialog_check_radio:
**
** Places a check by the specified radio button and removes the check
** from all other radio buttons within the specified group. The group label
** is not required if the dialog box has only one group of radio buttons.
**
** This is a user-accessible function.
*/
void _dialog_check_radio (string button, ~string group)
{
int curr_buf = inq_buffer ();
string label;
set_buffer (_dialog_radio_buf);
save_position ();
top_of_buffer ();
sprintf (label, FIND_RADIO_GRP, group);
if (search_fwd (label, TRUE, TRUE) >= 1)
{
int offset;
string ctrl = read ();
offset = index (ctrl, "\"") + 1;
label = substr (ctrl, offset, rindex (ctrl, "\"") - offset);
/*
** Only do real work when we absolutely have to ...
**
** If the specified button and the current 'ON' button are not the
** same, then turn the current 'ON' button off and the specified
** button 'ON'. Update the radio button control file first, then the
** display buffer.
*/
if (label != button)
{
int row_off = atoi (substr (ctrl, rindex (ctrl, "(") + 1)),
col_off = atoi (substr (ctrl, rindex (ctrl, ",") + 1)),
row_on,
col_on;
move_rel (0, strlen (ctrl) - 2);
delete_char ();
insert ("%c", RADIO_OFF);
top_of_buffer ();
sprintf (label, FIND_RADIO_LBL, group, button, RADIO_OFF);
if (search_fwd (label, TRUE, TRUE) >= 1)
{
ctrl = read ();
row_on = atoi (substr (ctrl, rindex (ctrl, "(") + 1));
col_on = atoi (substr (ctrl, rindex (ctrl, ",") + 1));
move_rel (0, strlen (ctrl) - 2);
delete_char ();
insert ("%c", RADIO_ON);
/*
** Update the display buffer.
*/
set_buffer (_dialog_disp_buf);
save_position ();
move_abs (row_off, col_off + 1);
delete_char ();
insert ("%c", RADIO_OFF);
move_abs (row_on, col_on + 1);
delete_char ();
insert ("%c", RADIO_ON);
restore_position ();
set_buffer (_dialog_radio_buf);
}
else
{
error ("Unable to locate 'OFF' Radio button in control file.");
beep ();
}
}
}
else
{
error ("Unable to locate 'ON' Radio button in control file.");
beep ();
}
restore_position ();
set_buffer (curr_buf);
}
/*
** _dialog_radio_checked:
**
** Determines which radio button of the specified group is on. Returns
** the label of the 'on' button. The group lable is not required if the
** dialog box has only one group of radio buttons.
**
** This is a user-accessible function.
*/
string _dialog_radio_checked (~string group)
{
int curr_buf = inq_buffer ();
string label;
/*
** Search the radio button control buffer for the specified button.
** If we find it, return its label. Otherwise, return an empty string.
*/
set_buffer (_dialog_radio_buf);
save_position ();
top_of_buffer ();
sprintf (label, FIND_RADIO_GRP, group);
if (search_fwd (label, TRUE, TRUE) >= 1)
{
int offset;
label = read ();
offset = index (label, "\"") + 1;
label = substr (label, offset, rindex (label, "\"") - offset);
}
else
label = "";
restore_position ();
set_buffer (curr_buf);
returns (label);
}
/*
** _dlg_goto_btn:
**
** Positions the cursor at the second character of the control text
** in the display buffer. If the control is a checkbox, the cursor will
** be below the check area. If the control is a push button, the cursor
** will be below the white space before the push button label. This function
** set the current buffer to the display buffer at exit.
*/
int _dlg_goto_btn (int btn_type, string button_label, ~string group)
{
string line;
int row, col,
rval;
set_buffer (_dialog_data_buf);
save_position ();
top_of_buffer ();
sprintf (line, BTN_SRCH_STRN, btn_type, button_label, group);
if (search_fwd (line, TRUE, FALSE))
{
row = atoi (line = read ());
col = atoi (substr (line, index (line, ",") + 1)) + 1;
rval = TRUE;
}
restore_position ();
set_buffer (_dialog_disp_buf);
if (rval)
move_abs (row, col);
returns (rval);
}
/*
** _dlg_check_btn, _dlg_push_btn, _dlg_radio_btn:
**
** Returns the label of the current check, push or radio button.
** Assumes that the current buffer is the display buffer.
*/
string _dlg_check_btn ()
{
string line;
line = read ();
line = trim (substr (line, index (line, CHECK_RGT_SRCH) + 2));
line = substr (line, 1, search_string ("[\t\n]", line) - 1);
returns (line);
}
string _dlg_push_btn ()
{
string line;
line = read ();
line = trim (substr (line, 2, search_string (PUSH_RGT_SRCH, line) - 2));
returns (line);
}
string _dlg_radio_btn ()
{
int offset;
string label;
set_buffer (_dialog_radio_buf);
top_of_buffer ();
sprintf (label, FIND_RADIO_POS, _dialog_row, _dialog_col - 1);
if (search_fwd (label, TRUE, TRUE) >= 1)
{
label = read ();
offset = index (label, "\"") + 1;
label = substr (label, offset, rindex (label, "\"") - offset);
}
else
{
error ("Unable to locate Radiobutton in control file.");
beep ();
}
set_buffer (_dialog_disp_buf);
returns (label);
}
/*
** _dlg_radio_group:
**
** Returns the current radio button's group label. Returns NULL if the
** the current button is not a radio button.
*/
string _dlg_radio_grp (void)
{
string group;
if (_dialog_type == RADIO)
{
set_buffer (_dialog_radio_buf);
top_of_buffer ();
sprintf (group, FIND_RADIO_POS, _dialog_row, _dialog_col - 1);
if (search_fwd (group, TRUE, TRUE) >= 1)
{
group = read ();
group = substr (group, 1, index (group, "\"") - 1);
}
else
{
error ("Unable to locate current Radiobutton in control file.");
beep ();
}
set_buffer (_dialog_disp_buf);
}
returns (group);
}
/*
** _dlg_pick_btn:
**
** Generates the event for a pick button. Passes the row number and
** the button label to the user.
*/
void _dlg_pick_btn (void)
{
switch (_dialog_type)
{
case CHECK:
execute_macro (_dialog_action_func, DIALOG_PICK_CHECK, _dialog_row, _dlg_check_btn ());
case PUSH:
execute_macro (_dialog_action_func, DIALOG_PICK_PUSH, _dialog_row, _dlg_push_btn ());
case RADIO:
execute_macro (_dialog_action_func, DIALOG_PICK_RADIO, _dialog_row, _dlg_radio_btn (), _dlg_radio_grp ());
}
}
/*
** _dlg_select_push:
**
** Selects or deselects the push button specified by button label.
** If select is nonzero, the push button is selected, otherwise it is
** deselected.
*/
void _dlg_select_push (string button_label, int select)
{
int len;
if (button_label != "")
{
if (button_label == _dialog_default_pb)
_dialog_pb_state = select;
if (_dlg_goto_btn ('P', button_label))
{
/* position over the left delimiter of the push button */
move_rel( 0,-1 );
delete_char (len = (strlen (button_label) + 4));
if (select)
insert (PUSH_BUTTON_DEF, button_label);
else
insert (PUSH_BUTTON, button_label);
move_rel (0, -(len - 1));
}
}
}
/*
** _dlg_btn_tab_next, _dlg_btn_tab_prev, _dlg_btn_next, _dlg_btn_prev:
**
** Moves the cursor from button control to button control. Check and
** push buttons work just like other controls. Radio buttons are different.
**
** Pressing the Tab or Shift-Tab key when a radio button has the focus
** will move the focus to the next control not in that radio button's group.
**
** The cursor keys also work a little differently for radio buttons. If
** the current control is a radio button, pressing Up/Left or Right/Down
** moves the focus to the next radio button in the same group of radio
** buttons. When the current radio button is the first or last button in
** the group, the cursor will 'wrap-around' to the last or first button in
** the group.
*/
void _dlg_btn_tab_next (void)
{
if (_dialog_type == RADIO)
{
if (_dialog_exit ())
{
/*
** Find next radio button group or other control. If the next
** control found is another set of radio buttons, make the first
** button of the group the current control.
*/
set_buffer (_dialog_data_buf);
next_char ();
if (search_fwd (FIND_NEXT, TRUE, FALSE))
{
if (upper (read (1)) == "G")
search_fwd ("<[ \t]@\\cR", TRUE, FALSE);
}
else
prev_char ();
_dialog_enter ();
}
}
else
_dialog_next ();
}
void _dlg_btn_tab_prev (void)
{
if (_dialog_type == RADIO)
{
if (_dialog_exit ())
{
set_buffer (_dialog_data_buf);
/*
** Find previous radio button group or other control. If the
** previous control found is another set of radio buttons, make the
** last button of the group the current control.
*/
if (prev_char ())
{
if (search_back (FIND_PREV, TRUE, FALSE))
{
if (upper (read (1)) == "E")
search_back ("<[ \t]@\\cR", TRUE, FALSE);
}
else
next_char ();
}
_dialog_enter ();
}
}
else
_dialog_prev ();
}
void _dlg_btn_next (void)
{
if (_dialog_type == RADIO)
{
if (_dialog_exit ())
{
set_buffer (_dialog_data_buf);
search_fwd ("<[ \t]@\\c[RE]", TRUE, FALSE);
if (read (1) == "E")
{
search_back ("<[ \t]@\\cG", TRUE, FALSE);
search_fwd ("<[ \t]@\\cR", TRUE, FALSE);
}
_dialog_enter ();
}
}
else
_dialog_next ();
}
void _dlg_btn_prev (void)
{
if (_dialog_type == RADIO)
{
if (_dialog_exit ())
{
set_buffer (_dialog_data_buf);
up ();
search_back ("<[ \t]@\\c[RG]", TRUE, FALSE);
if (read (1) == "G")
{
search_fwd ("<[ \t]@\\cE", TRUE, FALSE);
search_back ("<[ \t]@\\cR", TRUE, FALSE);
}
_dialog_enter ();
}
}
else
_dialog_prev ();
}
/*
** _is_push_button
**
** Search the current line of the dialog display buffer
** and determine if the user clicked on a push button.
**
** Input:
** Current buffer equal _dialog_disp_buf
** col - the column position of the click
**
** Returns
** the position of the left delimiter of the push button
** if a push button was clicked in; otherwise zero. On
** exit the current position in _dialog_disp_buf is the
** position of the click.
**
*/
int _is_push_button( int col )
{
int i, btn_left, btn_right, len;
string temp;
i = 0; // adjustment for position on original line
beginning_of_line();
temp = read(); // get the whole line
/*
** Look thru the whole line finding each push button on the line
** and checking if the given column position is inside that button
*/
btn_left = search_string( PUSH_SRCH, temp, len); // look for a push button
while ( btn_left && col > btn_right ) {
btn_left = btn_left + i;
btn_right = btn_left + len - 1;
/* was the click on this push button?? */
if ( btn_left <= col && col <= btn_right ) {
break;
} else {
/* No - check for the next push button */
i = btn_right++; // look for another push button
temp = substr( temp, btn_right );
btn_left = search_string( PUSH_SRCH, temp, len); // look for the btn_right delimiter
}
}
move_abs( 0, col ); // return to original position
return( btn_left );
}
Binary file not shown.
+248
View File
@@ -0,0 +1,248 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_fld.cb:
**
** This file contains all BRIEF macros for managing dialog box fields.
*/
#include <dialog.h>
#include <dlg.h>
/*
** _field_insert:
**
** Makes sure that there's still room left in the window; if not,
** removes the last key inserted, beeps and prints an error message.
** Handles both insert and overstrike mode.
*/
void _field_insert (int key)
{
int last_col;
if (inq_marked ())
{
raise_anchor ();
delete_to_eol ();
}
save_position ();
if (inq_mode ())
end_of_line ();
inq_position (NULL, last_col);
restore_position ();
if (last_col < _dialog_size)
self_insert (key);
else
{
error ("Field is full.");
beep ();
}
}
/*
** _field_bksp:
**
** Backs the cursor up in a typed field (if it's not already at
** the beginning of the field) and deletes it. In overstrike
** mode, this function replaces the deleted character with a space.
*/
void _field_bksp ()
{
int cur_col;
inq_position (NULL, cur_col);
if (inq_marked ())
{
raise_anchor ();
delete_to_eol ();
}
if (cur_col > _dialog_col)
{
left ();
if (!at_eol ())
{
delete_char ();
if (!inq_mode ())
{
insert (" ");
prev_char ();
}
}
}
}
/*
** _field_left, _field_right:
**
** Moves the cursor to the left or to the right in the field, if
** possible. If the field is marked (which implies that the cursor
** is still at the beginning of the field), the highlight is removed.
*/
void _field_left ()
{
int cur_col;
raise_anchor ();
inq_position (NULL, cur_col);
if (cur_col > _dialog_col)
left ();
}
void _field_right ()
{
int cur_col;
raise_anchor ();
inq_position (NULL, cur_col);
if (cur_col < _dialog_size - 1)
right ();
}
/*
** _field_del:
**
** Deletes a character, as long as it's not a newline. Works the
** same way in both insert and overstrike modes. If the field is still
** marked, deletes the whole thing.
*/
void _field_del ()
{
if (!at_eol ())
if (inq_marked ())
{
raise_anchor ();
delete_to_eol ();
}
else
delete_char ();
}
/*
** _field_end, _field_home:
**
** Removes the mark if there is one, then positions the cursor
** at the end or beginning of the field.
*/
void _field_end ()
{
raise_anchor ();
end_of_line ();
}
void _field_home ()
{
raise_anchor ();
move_abs (0, _dialog_col);
}
/*
** _field_del_line, _field_delete_to_eol:
**
** Deletes either the entire field or the field contents after the
** cursor position, removing any mark first.
*/
void _field_del_line (void)
{
move_abs (0, _dialog_col);
_field_delete_to_eol ();
}
void _field_delete_to_eol (void)
{
raise_anchor ();
delete_to_eol ();
}
/*
** _dialog_validate:
**
** Determines if the current field meets predefined criteria for
** being a nonblank string, integer, or file name. (Used for all typed
** fields.) Returns TRUE if the string satisfied the criteria for
** the current type, _dialog_type, or if the current type was not
** a nonblank string, integer, or file name type.
*/
int _dialog_validate (string value)
{
int retval = TRUE;
switch (_dialog_type)
{
case FILENAME:
if (!(retval = is_filename (value)))
error ("This field must be a filename.");
case INTEGER:
if (!(retval = search_string ("<[ \\t]@{[\\-+][0-9]+}|{[0-9]+}[ \t]@\n", value + "\n", NULL, TRUE)))
error ("This field must be an integer.");
case NONBLANK:
if (!(retval = search_string ("[~ \\t\\n]", value, NULL, TRUE)))
error ("This field may not be blank.");
}
if (!retval)
beep ();
returns (retval);
}
/*
** is_filename:
**
** Returns TRUE if a string contains a syntactically correct
** filename. Note: this regular expression will catch most, but
** not all, incorrect file names. Among the cases that it will not
** catch are two drive specifiers, extra or misplaced periods, omitted
** filename (just extension), and name or extension too long.
*/
int is_filename (string name)
{
returns (search_string ("<{[a-z]:}@[\\\\/]@{[~- \"%*-,/:-?\\[-\\]|]+[\\\\/]}@[~- \"%*-,/:-?\\[-\\]|]+>", name + "\n", NULL, TRUE, FALSE));
}
/*
** at_eol:
**
** Returns TRUE if the current position is at the end of a line,
** FALSE otherwise.
*/
int at_eol ()
{
returns (read (1) == "\n");
}
/*
** _field_contents:
**
** Returns the contents of the current field, not including the
** newline, and regardless of the cursor position.
*/
string _field_contents ()
{
string field;
save_position ();
move_abs (0, _dialog_col);
field = read ();
restore_position ();
returns (substr (field, 1, strlen (field) - 1));
}
Binary file not shown.
+219
View File
@@ -0,0 +1,219 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_list.cb:
**
** This file contains all BRIEF macros for managing dialog box lists.
*/
#include <dialog.h>
#include <dlg.h>
/*
** _list_next, _list_prev:
**
** Moves the mark from one button to the next or previous button
** on a list. Lists do not wrap.
*/
void _list_next ()
{
raise_anchor ();
save_position ();
search_fwd ("{\\t\\c[~\\t]}|\\n", TRUE);
restore_position (at_eol ());
_list_highlight ();
}
void _list_prev ()
{
int col,
len;
raise_anchor ();
inq_position (NULL, col);
/*
** If we move past the beginning of the list when we move two
** columns left, there is no previous button. If we are still
** in the list, we are at the end of the previous button.
** All we have to do is move one past the previous tab character.
** This we do in 2 steps because we have to read, starting at
** the beginning of the list.
*/
if ((len = (col -= 2) - _dialog_col) > 0)
{
move_abs (0, _dialog_col);
move_rel (0, rindex (read (len), "\t"));
}
_list_highlight ();
}
/*
** _list_highlight:
**
** Highlights the list button where the cursor is. Also, since
** this function is called by all the functions that change the value
** of a list, calls the action function with that code.
*/
void _list_highlight ()
{
string value;
int len = index (value = read (), "\t") - 2;
move_rel (0, len);
drop_anchor ();
move_rel (0, 0 - len);
execute_macro (_dialog_action_func, DIALOG_ALTER_LIST, _dialog_row, substr (value, 1, len+1));
}
/*
** _list_home, _list_end:
**
** Moves the highlight to the first or last button on a list.
*/
void _list_home ()
{
move_abs (0, _dialog_col);
_list_next ();
}
void _list_end ()
{
end_of_line ();
_list_prev ();
}
/*
** _list_go:
**
** Reads a character (that was just inserted; _list_go is
** called as a type 0 registered macro) from the buffer and deletes
** it, then looks for a matching button before the end of the list.
** If there is none, looks for one starting with the first item.
** If there is still none, stays put. (If a button is found,
** _list_go moves to it and highlights it.)
**
** Note that alphabetic keys pressed will only find buttons
** beginning with the upper case versions of the letters.
*/
void _list_go (int key)
{
int col,
offset;
string pattern;
raise_anchor ();
sprintf (pattern, "%c", key);
pattern = "\t" + upper (pattern);
if (offset = index (read (), pattern))
move_rel (0, offset);
else
{
save_position ();
move_abs (0, _dialog_col);
if (offset = index (read (), pattern))
move_rel (0, offset);
else
beep ();
restore_position (!offset);
}
_list_highlight ();
}
/*
** _list_button:
**
** Returns the text of the current list button, excluding any
** surrounding parentheses or tabs.
*/
string _list_button ()
{
string button = read ();
returns (substr (button, 1, index (button, "\t") - 1));
}
/*
** _is_list_
**
** Determine if the given line and column position is in
** a dialog manager list. Called by mouse_dialog to determin
** if the user clicked in a list.
**
** Input:
** Current buffer equal _dialog_disp_buf
** buf_line - the line position of a click.
** buf_col - the column position of the click
**
** Returns
** TRUE if a list entry was clicked on. Returns FALSE
** if a list was not clicked on OR if a tab in a list was
** clicked on OR if the () in a list was clicked on. Returns
** with the current buffer equal to _dialog_disp_buf. In
** _dialog_data_buf the position is the beginning of the line
** of the line containing the list control that was clicked on.
**
*/
int _is_list( int buf_line, int buf_col )
{
int list_left, len;
string ctrl_string, temp, list_text;
/* Are there any lists specified for the line that the user clicked on?? */
set_buffer (_dialog_data_buf); // switch to the data buffer
top_of_buffer();
sprintf( ctrl_string,
"list[ \t]@([ \t]@%d[ \t]@,[ \t]@[0-9]*[ \t]@)", buf_line );
while ( search_fwd( ctrl_string, TRUE, FALSE ) ) {
/*
** Yes - there are list(s) specified for this line.
** See if the position was in this one
*/
temp = read(); // get the control spec for the list
/*
** Extract the text of the list. Compute the length of
** text without any leading or trailing ().
** Note: The first entry in the
** list is placed at the list's starting position.
*/
list_text = substr( temp,index( temp, "\"")+1);
len = strlen( list_text ) - 2; // dont include trailing " and \n
if ( rindex( list_text, ")") == len ) len--;
if ( index( list_text, "(") == 1 ) {
len--;
list_text = substr( list_text, 2 ); // delete leading (
}
list_left = atoi( substr( temp, (index(temp,",")+1) ) );
if ( list_left <= buf_col && buf_col <= (list_left+len-1) ) {
beginning_of_line(); // beginning of line of the control spec
/*
** Found the clicked on list, make sure an entry and not
** a tab was clicked on. If a () was clicked on just ignore it
*/
set_buffer( _dialog_disp_buf );
temp = read(1); // get the char under the mouse cursor.
if ( temp != "\t" &&
temp != "(" && temp != ")" ) {
return( TRUE );
}
break; // exit the search
}
move_rel( 1,0); // move to next entry in the information buffer
}
set_buffer( _dialog_disp_buf );
return( FALSE );
}
Binary file not shown.
+426
View File
@@ -0,0 +1,426 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_menu.cb:
**
** This file contains all BRIEF macros for managing menus provided
** by the dialog manager.
*/
#include "dialog.h"
#include "dlg.h"
#include "win_ctrl.h"
/*
** mouse_menu
**
** Handle all the mouse events of interest for menus
**
** Mouse assignments
** BTN1 DOWN, UP, MOVE - highlight a menu entry
** BTN1_CLICK - pick a menu choice
** BTN2_CLICK - close the menu
*/
void mouse_menu ( int event, // the event code
int modifier, // modifier keys
int parm2, // line or scroll bar code
int parm3 ) // column or thumb position
{
/* handle the events of interest */
switch ( event ){
/*
** Note: the double click is ignored because the CLICK message
** comes thru before the double click message so the click causes
** the menu selection.
*/
case BTN1_DOWN: // highlite a menu entry
case BTN1_UP: // highlite a menu entry
case BTN1_MOVE: // highlite a menu entry
case BTN1_CLICK: { // pick a menu choice
int lines;
if ( modifier == 0 ) { // make sure no modifiers present
/* determine the number of lines in the buffer */
save_position();
end_of_buffer(); // position to the end of the buffer
inq_position( lines );
restore_position();
if ( 0 < parm2 && parm2 <= lines ) {
inq_position( lines );
if ( lines != parm2 ) { // did the mouse move to a new entry?
raise_anchor(); // erase current highlight
move_abs( parm2, 0 ); // position to choice that was clicked on
_menu_highlight(); // highlight the menu choice
}
if ( event == BTN1_CLICK ) _dialog_menu_pick();
}
}
}
/*
** Close the menu if the user clicks in the status area.
** If you would like a click in the status area, when a
** menu is up to mean shut down the menu and bring up
** a command prompt, then remove the test for BTN1_CLICK
** and just exit. Then the BTN1_DOWN message will cause
** the menu to exit and the BTN1_CLICK will pass thru to
** the default handler which will bring up the command prompt
*/
case STATUS_AREA:
switch ( parm2 ) {
case BTN1_CLICK:
exit();
}
/* close the menu if the close button clicked on this menu */
case CLOSE_WIN:
if ( inq_window() == parm2 ) exit(); // close this menu
/* close the menu if the user clicked outside of it */
case SET_WIN:
if ( inq_window() != parm2 ) exit(); // close this menu
case VSCROLL: // vertical scroll bar event
switch ( parm2 ){
case SB_BOTTOM: // end of menu request
_dialog_menu_end();
case SB_TOP: // top of menu request
_dialog_menu_home();
case SB_PAGEDOWN: // page down request
_dialog_menu_pgdn();
case SB_PAGEUP: // page up request
_dialog_menu_pgup();
case SB_LINEDOWN: // line down request
_dialog_menu_down();
case SB_LINEUP: // line up request
_dialog_menu_up();
case SB_THUMBTRACK:{ // scroll while tracking the thumb
raise_anchor(); // erase current highlight
/* set the thumb position */
set_ctrl_state(VERT_THUMB, parm3);
/* make sure we're at the left col */
move_abs(0, 1);
_menu_highlight(); // highlight the menu choice
}
}
}
}
/*
** _menu_highlight:
**
** Calls the menu alter event. If it succeeds, highlights the
** current menu line using a line mark.
*/
int _menu_highlight ()
{
int line;
inq_position (line);
if (execute_macro (_dialog_action_func, DIALOG_MOVE_MENU, line, _menu_button ()))
{
raise_anchor ();
drop_anchor (3);
returns (TRUE);
}
else
returns (FALSE);
}
/*
** _dialog_menu_home:
**
** Moves the selection to the first selectable item on the menu.
** Calls the action function with the new line number and menu button
** text.
*/
void _dialog_menu_home ()
{
top_of_buffer ();
while (!_menu_highlight ())
down ();
}
/*
** _dialog_menu_end:
**
** Moves to the last selectable item on the menu. Calls the
** action function with the new line number and menu button text.
*/
void _dialog_menu_end ()
{
end_of_buffer ();
beginning_of_line ();
to_bottom ();
while (!_menu_highlight ())
up ();
}
/*
** _dialog_menu_pgup, _dialog_menu_pgdn:
**
** Pages up or down in a menu.
*/
void _dialog_menu_pgup ()
{
page_up ();
if (!(_menu_highlight () || _dialog_menu_up ()))
_dialog_menu_down ();
}
void _dialog_menu_pgdn ()
{
page_down ();
while (inq_position ())
up ();
if (!(_menu_highlight () || _dialog_menu_down ()))
_dialog_menu_up ();
}
/*
** _dialog_menu_down:
**
** Moves the current selection down, stopping at next selectable
** item; if the bottom of the menu is encountered, returns to the
** previous position. Returns whether or not it succeeded in moving.
** Calls the action function with the new line number and menu
** button text as parameters.
*/
int _dialog_menu_down ()
{
int failed;
save_position ();
while (TRUE)
{
down ();
if (inq_position ())
{
failed++;
break;
}
else if (_menu_highlight ())
break;
}
restore_position (failed);
returns (!failed);
}
/*
** _dialog_menu_up:
**
** Moves the current selection up to the previous selectable
** item, if there are any. Returns TRUE if it succeeded.
*/
int _dialog_menu_up ()
{
int moved;
save_position ();
while (up ())
if (_menu_highlight ())
{
moved++;
break;
}
if (!moved)
set_top_left (1, 1);
restore_position (!moved);
returns (moved);
}
/*
** _menu_go:
**
** Reads a character (that was just inserted; _menu_go is
** called by a type 0 registered macro) from the buffer and deletes
** it, then looks for a matching button before the end of the menu.
** If there is none, looks for one starting with the first item.
** If there is still none, stays put. (If a selectable button is found,
** _menu_go moves to it and highlights it.)
*/
void _menu_go (int key)
{
string pattern;
int end_line,
after_line,
start_line,
start_col,
failed;
/*
** Figure out the time when the key was pressed. This is a
** relative number, measured in tenths of a second, and it is
** used to figure out when a user is typing a multi-key
** sequence.
*/
time (NULL, start_line, start_col, end_line);
end_line = (start_line * 60 + start_col) * 10 + end_line / 10;
after_line = end_line - _dialog_menu_time;
_dialog_menu_time = end_line;
while (after_line < 0)
after_line += 32768;
/*
** If .8 seconds or more elapsed since we last pressed a key in
** this menu, we clear the remembered prefix.
*/
if (after_line >= 8)
_dialog_menu_prefix = "";
/*
** Figure out what key was pressed.
*/
sprintf (pattern, "%c", key);
/*
** If the character is a regular expression character, we make
** sure to put a backslash in front of it.
*/
if (index ("?*@+|\\<>%${}[]~-", pattern))
pattern = "\\" + pattern;
pattern = "<[ \\t]@" + (_dialog_menu_prefix += pattern);
/*
** Find the last line of the window; if the search takes us
** outside it, we want to center the line in the window.
*/
inq_position (start_line, start_col);
end_of_window ();
inq_position (end_line);
move_abs (start_line, start_col);
/*
** If we are searching for a one-character button prefix, we
** search the current line last, not first.
*/
if (strlen (_dialog_menu_prefix) == 1)
down ();
/*
** Search from the current position to EOF, breaking if
** a selectable line is found. If the pattern is not found,
** start searching from the top of the file down.
*/
while (!failed)
{
if (search_fwd (pattern, TRUE, FALSE) <= 0)
{
move_abs (start_line, start_col);
drop_anchor (3);
top_of_buffer ();
while (!failed)
{
if (search_fwd (pattern, TRUE, FALSE, TRUE) <= 0)
++failed;
else if (_menu_highlight ())
{
inq_position (after_line);
if (after_line > end_line)
center_line ();
return;
}
else
down ();
}
/*
** If we can't find the current multi-character prefix in the
** menu, but the last two characters were the same, we throw
** away the second of those and look for the next prefix that
** matches.
*/
if ((failed = strlen (_dialog_menu_prefix)) > 1 && substr (_dialog_menu_prefix, failed, 1) == substr (_dialog_menu_prefix, failed - 1, 1))
{
_dialog_menu_prefix = substr (_dialog_menu_prefix, 1, failed - 1);
pattern = "<[ \\t]@" + _dialog_menu_prefix;
move_abs (start_line, start_col);
down ();
failed = FALSE;
}
else
failed = TRUE;
raise_anchor ();
}
else if (_menu_highlight ())
{
inq_position (after_line);
if (after_line > end_line)
center_line ();
return;
}
else
down ();
}
move_abs (start_line, start_col);
}
/*
** _dialog_menu_pick:
**
** Processes the menu line that is selected when the user presses
** Enter.
*/
void _dialog_menu_pick ()
{
int line;
inq_position (line);
if (execute_macro (_dialog_action_func, DIALOG_PICK_MENU, line, _menu_button ()))
_dialog_picked = line;
}
/*
** _menu_button:
**
** Returns the text of the current menu button, with leading and
** trailing white space removed.
*/
string _menu_button ()
{
returns (trim (ltrim (read ())));
}
Binary file not shown.
+241
View File
@@ -0,0 +1,241 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
** dlg_mous.cb:
**
** This file contains all macros for the Dialog Manager's Mouse Interface.
*/
#include "dialog.h"
#include "dlg.h"
#include "win_ctrl.h"
int _is_push_button( int col );
int _is_list( int buf_line, int buf_col );
extern void begin_word();
extern int _dialog_mouse_buf;
int mouse_choice_type,
new_focus,
focus_y,
focus_x1,
focus_x2;
/*
** mouse_dialog
**
** Handle all the mouse events of interest for dialog boxes
**
*/
void mouse_dialog (int event, int modifier, int parm2, int parm3 )
{
/* handle the events of interest */
switch ( event )
{
case BTN1_DOWN:
{
string str;
int curr_buf,
line,
col,
lx,
rx;
/* Save current buffer */
curr_buf = inq_buffer();
inq_position(line, col);
/* The _dialog_mouse_buf is a mirror image of the display
** buffer except instead of contols, the buffer contains control
** codes. For example if a radio button in the display buffer
** looks like XXXX ( ), in the mouse info buffer it looks
** like 88888888.
*/
set_buffer(_dialog_mouse_buf);
/* By positioning in the mouse buffer, we can determine
** what the current focus is.
*/
move_abs(line, col);
/* Find the left and right edges of this control
*/
search_back("\t|<| ", TRUE);
inq_position(NULL, lx);
/* Find out where the control ends */
move_rel(0, 1);
search_fwd("\t|>| ", TRUE);
inq_position(NULL, rx);
/* If this is the first time here, set the current focus.
*/
if (first_time())
{
focus_y = line;
focus_x1 = lx + 1;
focus_x2 = rx - 1;
}
/* Now, check to see if the focus has changed, if so,
** set the new_focus flag
*/
if (line != parm2 || parm3 < lx + 1 || parm3 > rx - 1)
{
/* Move to new position and read in one character.
** That character is the control code (or 0 if not over
** a control.
*/
move_abs(parm2, parm3);
str = read(1);
mouse_choice_type = atoi(str);
/* If the mouse down was over a control we have a new_focus */
if (mouse_choice_type != 0)
{
/* Find the left edge of the control
*/
search_back("\t|<| ", TRUE);
inq_position(focus_y, focus_x1);
move_rel(0, 1);
search_fwd("\t|>| ", TRUE);
inq_position(NULL, focus_x2);
focus_x1 ++;
focus_x2 --;
new_focus = 1;
}
}
/* If the focus has not changed and the last mouse_choice is
** 0 (becuase of a click outside of any control, need to reset
** the mouse_choice_type
*/
else if (mouse_choice_type == 0)
{
move_abs(parm2, parm3);
str = read(1);
mouse_choice_type = atoi(str);
}
set_buffer(curr_buf);
}
case BTN1_CLICK:
{
/* If we are still in focus and we have a valid mouse_choice_type */
if (parm2 == focus_y && parm3 >= focus_x1 && parm3 <= focus_x2 &&
mouse_choice_type)
{
/* if the fcous has not changed */
if (!new_focus)
{
/* Send a button pick.
*/
if (mouse_choice_type == CHECK ||
mouse_choice_type == RADIO ||
mouse_choice_type == PUSH)
_dlg_pick_btn();
/* Send an alter list
*/
else if (mouse_choice_type == LIST)
{
raise_anchor ();
move_abs(parm2, parm3);
begin_word();
_list_highlight ();
}
/* Must be a field, so just position the cursor
*/
else
{
raise_anchor();
move_abs(parm2, parm3);
}
}
else if (_dialog_exit())
{
string temp;
raise_anchor();
set_buffer (_dialog_data_buf);
top_of_buffer();
/* locate the line in the control file where the control is defined */
sprintf( temp, "( @%d @, @%d @)", focus_y, focus_x1);
search_fwd( temp, TRUE, TRUE );
beginning_of_line();
/* send the enter event */
_dialog_enter();
if (mouse_choice_type == CHECK ||
mouse_choice_type == RADIO ||
mouse_choice_type == PUSH)
_dlg_pick_btn();
else if (mouse_choice_type == LIST)
{
int x1, x2;
inq_marked(NULL, x1, NULL, x2);
/* If not in a marked are, we must be selecting
** a new list entry
*/
if (parm3 < x1 || parm3 > x2)
{
raise_anchor();
move_abs(parm2, parm3);
begin_word();
_list_highlight ();
}
}
/* This must be a field, so position the cursor.
*/
else
{
raise_anchor();
move_abs(parm2, parm3);
}
}
new_focus = 0;
}
}
/* For close and set window, just want to exit the dialog manager.
*/
case CLOSE_WIN:
case SET_WIN:
_dialog_f10();
}
}
Binary file not shown.
Binary file not shown.
+129
View File
@@ -0,0 +1,129 @@
;** _init macro.
;** Do not change this macro (always overwritten by Setup).
(macro _init
(
(extern autosave ;** External macro declarations
toggle_re
)
(color 0 7 15 7 15 0x80) ;** Set the screen colors
(set_mouse_type 2 0) ;** Set number of mouse buttons, button one location
(set_ctrl_state 0 1) ;** Enable close button
(set_ctrl_state 1 1) ;** Enable zoom button
(set_ctrl_state 2 1) ;** Enable vertical scroll bar
(set_ctrl_state 3 1) ;** Enable horizontal scroll bar
(set_mouse_action "_mouse_action") ;** Set mouse action macro
(set_btn2_action 1) ;** Set default action for mouse button two
)
)
;** Initials macro.
;** Use this macro for additional customization.
(macro DM
(
;** Put your changes here.
(return)
)
)
;** File Extension Macros, etc.
;** Macros marked "Overwritable" may be overwritten by SETUP.
;** Overwritable by Setup
(macro default
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .doc
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .h
(
(tabs 4 7)
)
)
;** Overwritable by Setup
(macro .c
(
(tabs 4 7)
)
)
;** Overwritable by Setup
(macro .txt
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .odl
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .asm
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .658
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .pas
(
(tabs 4 7)
)
)
;** Overwritable by Setup
(macro .68k
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .34
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .34h
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .hdr
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .z80
(
(tabs 9 17)
)
)
+2
View File
@@ -0,0 +1,2 @@
cb -d snasm

+158
View File
@@ -0,0 +1,158 @@
;** _init macro.
;** Do not change this macro (always overwritten by Setup).
(macro _init
(
(extern autosave ;** External macro declarations
toggle_re
)
(color 0 10 15 11 15 0x80) ;** Set the screen colors
(search_case 1) ;** Case insensitive search
(autosave) ;** Automatic file save when idle
(set_mouse_type 3 0) ;** Set number of mouse buttons, button one location
(set_ctrl_state 0 1) ;** Enable close button
(set_ctrl_state 1 1) ;** Enable zoom button
(set_ctrl_state 2 1) ;** Enable vertical scroll bar
(set_ctrl_state 3 1) ;** Enable horizontal scroll bar
(set_mouse_action "_mouse_action") ;** Set mouse action macro
(set_btn2_action 1) ;** Set default action for mouse button two
)
)
;** Initials macro.
;** Use this macro for additional customization.
(macro GC
(
(return)
)
)
;** File Extension Macros, etc.
;** Macros marked "Overwritable" may be overwritten by SETUP.
;** Overwritable by Setup
(macro default
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .doc
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .txt
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .odl
(
(tabs 9 17)
)
)
;** Overwritable by Setup
(macro .asm
(
(tabs 15 23 40 44)
)
)
;** Overwritable by Setup
(macro .658
(
(tabs 15 23 40 44)
)
)
;** Overwritable by Setup
(macro .pas
(
(tabs 4 8)
)
)
;** Overwritable by Setup
(macro .68k
(
(tabs 15 23 40 44)
)
)
(macro .34
(
(tabs 15 23 40 44)
)
)
(macro .34h
(
(tabs 15 23 40 44)
)
)
(macro .hdr
(
(tabs 15 23 40 44)
)
)
;** Overwritable by Setup
(macro .h
(
(tabs 15 23 40 44)
)
)
;** Overwritable by Setup
(macro .z80
(
(tabs 15 23 40 44)
)
)
;** Overwritable by Setup
(macro .pas_next_error
(returns (search_fwd "<*.[a-zA-Z]+(\\c[0-9]+): Error" 1 1))
)
;** Overwritable by Setup
(macro .pas_prev_error
(returns (search_back "<*.[a-zA-Z]+(\\c[0-9]+): Error" 1 1))
)
;** Overwritable by Setup
(macro .pas_error_info
(
(string error_text)
(int line
ret_val
)
(string buf_name
error_msg
file_name
base_name
)
(extern _error_info)
(get_parm 0 buf_name)
(get_parm 5 base_name)
(= ret_val (_error_info buf_name line NULL error_msg file_name base_name))
(put_parm 1 line)
(put_parm 4 file_name)
(put_parm 3 error_msg)
(put_parm 2 0)
(returns ret_val)
)
)

+936
View File
@@ -0,0 +1,936 @@
/*
** BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
** Written by Dave Nanian and Michael Strickman.
*/
/*
** errorfix.cb:
**
** This file contains the main driver and support macros for BRIEF's
** error location facility.
*/
#include "win_ctrl.h"
#define TRUE 1
#define FALSE 0
#define WARNING 1
#define ERROR 2
#define DISPLAY_NEXT_ERROR 0
#define POP_UP_ERROR_WINDOW 1
#define PROBE_AND_DISPLAY 2
#define JUST_PROBE 3
string add_to_path (string path, string file_name);
string escape_re (string original, ~string);
void center_line (void);
void _exit ();
int get_error_file (string full_name);
int find_error_file (string full_name);
int delete_error_file (string full_name, int delete_buffer_too);
void add_error_file (string full_name);
int next_error (~int action);
int _call_next (string error_extension, string file_name);
int _call_prev (string error_extension, string file_name);
int _next_error (~string extension);
int _prev_error (~string extension);
int _error_info (string error_file, int, int, string, string file_name);
int _error_buf_id, // Holds the error buffer.
_cancel_errorfix; // Flag to show whether or not Cancel done from menu.
string prev_mouse_action; // the previous mouse event function
/*
** _init:
**
** This macro gets run when the macro is loaded. It creates the
** error buffer, and sets _error_buf_id to the error buffer id.
*/
void _init (void)
{
_error_buf_id = create_buffer ("Error Stack", NULL, 1);
}
/*
** compile_it
**
** This is a replacement compile macro. It first deletes the error
** file, if one exists. The file name is also removed from the error
** stack, and then the actual compilation is executed.
**
** Returns:
**
** Result of the original compile macro.
*/
replacement compile_it ()
{
string file_name; // Name of the file that's being compiled.
inq_names (file_name);
/*
** Before compiling the file, we ensure that its error file
** has been removed from the error stack and the buffer has been
** deleted from memory. This ensures the file can be written
** by the compiler, and is up to date.
*/
delete_error_file (file_name, TRUE);
returns (compile_it ());
}
/*
** get_error_file:
**
** This routine obtains the most recent error file name, which is
** located at the top of the error stack file. It returns the name
** in the passed parameter.
**
** Returns:
**
** TRUE if a file was obtained from the error stack
** FALSE if a file could not be obtained from the error stack
*/
int get_error_file (string full_name)
{
int old_buf_id = set_buffer (_error_buf_id),
loc;
string line;
move_abs (1, 1);
if ((full_name = read ()) != "\n")
{
/*
** Trim is used to remove the newline.
*/
full_name = trim (full_name);
}
else
full_name = "";
put_parm (0, full_name);
set_buffer (old_buf_id);
returns (full_name != "");
}
/*
** find_error_file:
**
** This routine finds the location of the given file and path
** in the error stack file. The current line in the error stack
** is left at the found line.
**
**
** Returns:
**
** 0 if the file name and path are not found.
** Otherwise, the line number of the file path in the error stack file.
*/
int find_error_file (string full_name)
{
int old_buf_id = set_buffer (_error_buf_id),
error_file_line;
top_of_buffer ();
/*
** Since the full_name includes the drive letter, we don't need
** to worry about embedded paths (i.e., accidentally finding
** "\foo\foo\foo.c" instead of "\foo\foo.c").
*/
if (search_fwd (full_name + "\n", 0))
inq_position (error_file_line);
set_buffer (old_buf_id);
returns (error_file_line);
}
/*
** delete_error_file:
**
** This routine finds and if found, deletes, the given file and path
** from the error stack file.
*/
int delete_error_file (string full_name, int delete_buffer_too)
{
int ret_code,
old_buf_id = set_buffer (_error_buf_id),
buffer_id,
loc;
if (ret_code = find_error_file (full_name))
delete_line ();
/*
** If there is already a buffer for the error file, we
** "create" it (create_buffer returns the ID of a buffer
** that already existed) and then delete it immediately.
** Note that under some very obscure circumstances, the
** create_buffer call could fail. If it does, it'll
** return 0, which is an invalid buffer id. We check for
** this case since delete_buffer does not.
*/
loc = rindex (full_name, substr (full_name, 3, 1));
if (rindex (substr (full_name, loc + 1), "."))
full_name = substr (full_name, 1, rindex (full_name, ".")) + "err";
else
full_name += ".err";
if (delete_buffer_too
&& (buffer_id = create_buffer ("Error File", full_name, 1))
&& !inq_views (buffer_id))
delete_buffer (buffer_id);
set_buffer (old_buf_id);
returns (ret_code);
}
/*
** add_error_file:
**
** This routine adds an error file to the error stack file.
** The given file name (and its path) is inserted at the top of the
** error stack file. A call is made to delete_error_file, to find
** and delete a previous occurrence of this file name in the error
** stack file (if it exists).
*/
void add_error_file (string full_name)
{
int old_buf_id = set_buffer (_error_buf_id);
delete_error_file (full_name, FALSE);
top_of_buffer ();
insert (full_name + "\n");
set_buffer (old_buf_id);
}
/*
** fix_error_name:
**
** This routine constructs the necessary names from the given file_name,
** and checks to see if we've already attached the error file to another
** file. If so, we return that file's name rather than the name passed.
** This ensures that, when you've got an include file and a source file with
** the same name, you keep the error file attached to the source.
**
*/
void fix_error_name (string file_name, string error_file, string error_extension)
{
int loc,
old_buf_id = set_buffer (_error_buf_id);
/*
** This loop'll go through once for an unaliased error file, and twice
** if we find it attached to another buffer. In essence, it's only a
** loop to save having to repeat the parsing code.
*/
for (;;)
{
top_of_buffer ();
loc = rindex (file_name, substr (file_name, 3, 1));
if (rindex (substr (file_name, loc + 1), "."))
{
error_extension = substr (file_name, loc = rindex (file_name, "."));
error_file = substr (file_name, 1, loc - 1);
}
else
{
error_file = file_name;
error_extension = ".";
}
/*
** First, we check for the explicit file name. If that's not found,
** we check for only the base (no extension).
*/
if (!search_fwd (file_name + "\n", 0) && search_fwd ("<" + escape_re (error_file) + "{.[~/\\\\\n]@}@>"))
file_name = trim (read ());
else
break;
}
put_parm (0, file_name);
put_parm (1, error_file + ".err");
put_parm (2, error_extension);
}
/*
** next_error:
**
** This routine is the engine for BRIEF's error location facility. It
** reads in the error file and calls the appropriate routines to display
** either an individual error message or a window full of error message
** information.
**
** If no parameter (or zero) is passed to next_error, the error file is
** read into a buffer and searched for error messages. If the buffer is
** empty, the message "No errors." is displayed and the error buffer is
** removed. If the buffer is not empty, and a message can be located, the
** text of the message is displayed on the message line, the cursor is placed
** on the first non-blank character of the line containing the error, and that
** line is centered in the window. If no messages can be located, the error
** file is presented in a pop-up window.
**
** If a "1" is passed to next_error, the error information is displayed in
** a window, with the current message highlighted. If no messages could be
** recognised, the highlight is not displayed, and the cursor can be moved
** anywhere within the file.
**
** If a "2" is passed to next_error, the error file is tested to see if
** any messages can be recognised. If so, the same action is taken as with
** next_error 0. If not, no message is displayed and the error file buffer
** is deleted.
**
** If a "3" is passed, a test is done and a return code is returned, but
** no message is displayed in either case.
**
** In all cases, next_error returns 0 if no error was found, and non-zero
** if there was an error.
**
** If an error file is not found for the current file, then the error
** stack is accessed to obtain the error file accessed most recently.
*/
int next_error (~int action)
{
int error_buf,
old_buf_id = inq_buffer (),
line,
col,
loc,
attempts,
error_type,
more_errors,
prev_errors,
errors_exist,
total_error_lines,
windowed;
string error_msg,
error_file,
error_file_name,
curr_file_name,
buf_name,
parms,
error_extension;
_cancel_errorfix = FALSE;
inq_names (error_file_name, NULL, buf_name);
curr_file_name = error_file_name;
/*
** Find the error file for the current buffer. If one does
** not exist, then get the most recently accessed error file
** from the error stack.
*/
while (TRUE)
{
/*
** From the current error_file_name, construct the error_file and
** error_extension (which is either the error_file_name's extension
** or "." if there is no extension). If there's a similar file
** already in the error list, use it instead.
*/
fix_error_name (error_file_name, error_file, error_extension);
if (!(error_buf = create_buffer ("Error File", error_file, TRUE)))
{
/*
** Note that we could have gone through this list a number
** of times before this failure happens, so we must ensure the
** current buffer is reset.
*/
set_buffer (old_buf_id);
return (FALSE);
}
set_buffer (error_buf);
/*
** errors_exist is set to TRUE if there is data in the file.
** We assume that an empty file means no file, and that a file
** with data in it is worth looking into.
*/
save_position ();
top_of_buffer ();
errors_exist = end_of_buffer ();
inq_position (total_error_lines);
restore_position ();
if (!errors_exist)
{
/*
** If there aren't any errors in the file, we need to pop the
** buffer off the error stack (if it's there), and check the one
** at the top of the stack. If there isn't one, we're done.
**
** The attempts variable basically keeps track of the number
** of buffers we've examined that were actually on the error
** stack. This lets us distinguish between the "No errors"
** and the "No more errors" cases.
*/
attempts += delete_error_file (error_file_name, TRUE);
/*
** If we're just supposed to check whether or not there are
** errors in the current file, we stop here.
*/
if (action >= PROBE_AND_DISPLAY)
break;
}
else
{
/*
** Now that we know the file isn't empty, we check to
** see if there are "real" errors in the file. This is done
** with the next/prev error routine appropriate to the file's
** extension. We set the more_errors and prev_errors variables
** based on this test, and reset the errors_exist variable based
** on both of them.
*/
add_error_file (error_file_name);
parms = error_extension + " " + buf_name;
windowed = (action == POP_UP_ERROR_WINDOW);
save_position ();
more_errors = execute_macro ("_call_next " + parms);
if (more_errors && windowed)
execute_macro ("_call_prev " + parms);
else
{
down ();
save_position ();
prev_errors = execute_macro ("_call_prev " + parms);
restore_position ();
}
restore_position ();
errors_exist = (more_errors || prev_errors);
break;
}
/*
** If there are any more error files on the error stack, we check
** them out the same way.
*/
if (!get_error_file (error_file_name))
{
if (attempts == 0)
{
set_buffer (old_buf_id);
message ("No errors.");
return (0);
}
break;
}
more_errors = prev_errors = FALSE;
}
/*
** If we're supposed to pop up a window, or if the file isn't
** empty and we don't recognize any error messages, we pop up an
** error window. In the latter case, we do it so the user can
** see what's going on.
*/
if (windowed = (action < PROBE_AND_DISPLAY && (windowed || !errors_exist)))
{
int lines,
cols;
/* save the current mouse event routine */
prev_mouse_action = inq_mouse_action();
keyboard_push ();
assign_to_key ("<Enter>", "_exit");
assign_to_key ("<Esc>", "_error_cancel");
assign_to_key ("<Left>", "left");
assign_to_key ("<Right>", "right");
assign_to_key ("<Home>", "beginning_of_line");
assign_to_key ("<End>", "end_of_line");
/*
** If there are recognizable errors in the file, we assign the
** up and down keys to the error search functions. Otherwise, we
** just move up and down normally. This allows the user to browse
** the file even though we don't know what's going on.
*/
if (errors_exist)
{
save_position ();
drop_anchor (3);
assign_to_key ("<Up>", "_call_prev " + parms);
assign_to_key ("<Down>", "_call_next " + parms);
}
else
{
assign_to_key ("<Up>", "up");
assign_to_key ("<Down>", "down");
}
beginning_of_line ();
inq_screen_size (lines, cols);
set_ctrl_state( ZOOM_BTN, HIDE_CTRL ); // dont display a zoom button
create_window (5, lines - 4, cols - 5, 3, " or  to move, <Enter> to select, <Esc> to exit");
set_ctrl_state( ZOOM_BTN, SHOW_CTRL ); // display a zoom button
attach_buffer (error_buf);
refresh ();
/* establish the mouse action handler for errorfix */
set_mouse_action( "mouse_errorfix" );
process ();
if (errors_exist)
{
restore_position ();
raise_anchor ();
}
delete_window ();
/*
** Note that we set the current buffer back before doing the
** keyboard_pop: this ensures that the local keyboard (if any)
** is restored properly.
*/
set_buffer (old_buf_id);
keyboard_pop ();
set_buffer (error_buf);
}
/*
** At this point the cursor is pointing at the requested error
** message. If the user didn't cancel, we display the chosen message
** and move the cursor to the appropriate line.
*/
if (!_cancel_errorfix && action != JUST_PROBE)
{
string macro_to_call = error_extension + "_error_info";
if (!inq_macro (macro_to_call))
macro_to_call = "_error_info";
if ((windowed && errors_exist || more_errors)
&& (error_type = execute_macro (macro_to_call, buf_name, line, col, error_msg, curr_file_name, error_file_name)))
{
int error_file_buf = inq_buffer (curr_file_name);
if (error_file_buf != old_buf_id)
{
set_buffer (old_buf_id);
/*
** If the buffer is in the system, and it's being viewed in
** a window, we switch to it. Otherwise, we use edit_file to
** read it in (if necessary) and attach it to the current window.
*/
if (error_file_buf != 0 && inq_views (error_file_buf))
{
int curr_window = inq_window (),
window_buf_id;
do
{
curr_window = next_window (curr_window);
inq_window_info (curr_window, window_buf_id);
}
while (window_buf_id != error_file_buf);
set_window (curr_window);
old_buf_id = error_file_buf;
}
else if (edit_file (curr_file_name) > 0)
old_buf_id = inq_buffer ();
}
else
set_buffer (old_buf_id);
if (error_type < 0)
error_type = -error_type;
if (error_type >= 3)
goto_line (line);
else
goto_old_line (line);
center_line ();
if (col)
move_abs (0, col);
else
{
beginning_of_line ();
next_char (strlen (trim (read ())) - strlen (ltrim (trim (read ()))));
}
if (error_type == ERROR || error_type == -ERROR)
error (error_msg);
else
message (error_msg);
}
else if (windowed)
message (trim (ltrim (read ())));
else
{
if (errors_exist)
message ("No more errors.");
delete_error_file (error_file_name, TRUE);
}
}
else if (action == JUST_PROBE)
delete_error_file (error_file_name, TRUE);
else
message ("");
set_buffer (old_buf_id);
returns (more_errors);
}
/*
** mouse_errorfix
**
** Handle all the mouse events of interest for the errorfix text window
** Mouse assignments
** BTN1 DOWN, UP, MOVE - highlight an entry
** BTN1_CLICK - pick an error entry from the error file window
** BTN2_CLICK - close the error file window
** BTN1_CLICK outside error file window - close error file window
*/
void mouse_errorfix( int event, // the event code
int modifier, // modifier keys
int parm2, // line or scroll bar code
int parm3 ) // column or thumb position
{
/* handle the events of interest */
switch ( event ){
case BTN1_DOWN:
case BTN1_UP:
case BTN1_MOVE:
case BTN1_CLICK:
{
int old_line, lines, i, count;
string cmd;
inq_position( old_line ); // get current position
raise_anchor(); // unhighlight the current line
end_of_buffer(); // position to end of the buffer
inq_position( lines ); // get number of lines in buffer
move_abs( old_line ); // position back to original line
if ( 0 < parm2 && parm2 <= lines ) { // did the user click on a valid line?
/* get the command assigned to Up or Down */
if ( parm2 < old_line ) {
cmd = inq_assignment( "<Up>" );
count = old_line - parm2;
} else {
cmd = inq_assignment( "<Down>" );
count = parm2 - old_line;
}
/* move to the designated error line */
for ( i=0; i<count; i++) execute_macro( cmd );
if( event == BTN1_CLICK ) exit();// close the error text window
}
drop_anchor(3);
}
case BTN2_CLICK:
case CLOSE_WIN:
exit(); // close the error text window
case SET_WIN: // close the error text window
if ( parm2 != inq_window() ) exit();
case VSCROLL: // vertical scroll bar event
switch ( parm2 ){
case SB_BOTTOM: // end of error text window
case SB_TOP: // top of error text window
case SB_PAGEDOWN:{ // page down request
int size, i, status;
inq_window_size( size );
/* move to the designated error line */
status = 1;
for ( i=0; i<size, status; i++) {
status = execute_macro( inq_assignment( "<Down>" ) );
}
drop_anchor(3);
}
case SB_PAGEUP:{ // page up request
int size, i, status;
inq_window_size( size );
/* move to the designated error line */
status = 1;
for ( i=0; i<size, status; i++) {
status = execute_macro( inq_assignment( "<Up>" ) );
}
drop_anchor(3);
}
case SB_LINEDOWN: // next error down
execute_macro( inq_assignment( "<Down>" ) );
case SB_LINEUP: // next error up
execute_macro( inq_assignment( "<Up>" ) );
}
case HSCROLL: // horizontial scroll bar event
execute_macro( prev_mouse_action, event, modifier, parm2, parm3 );
}
}
/*
** _call_next:
**
** This macro is used to call the _next_error function. It checks to
** see if there is a file extension specific function first. If not, it
** calls the generic function.
*/
int _call_next (string error_extension, string file_name)
{
string macro_name = "_next_error";
int ret_code,
mark_type,
col;
if (mark_type = inq_marked ())
raise_anchor ();
if (inq_macro (error_extension + macro_name))
macro_name = error_extension + macro_name;
inq_position (NULL, col);
restore_position ();
ret_code = execute_macro (macro_name + " " + error_extension + " " + file_name);
save_position ();
move_abs (0, col);
if (mark_type)
drop_anchor (mark_type);
returns (ret_code);
}
/*
** _call_prev:
**
** This macro is used to call the _prev_error function. It checks to
** see if there is a file extension specific function first. If not, it
** calls the generic function.
*/
int _call_prev (string error_extension, string file_name)
{
string macro_name = "_prev_error";
int ret_code,
mark_type,
col;
if (mark_type = inq_marked ())
raise_anchor ();
inq_position (NULL, col);
restore_position ();
save_position ();
if (up ())
end_of_line ();
if (inq_macro (error_extension + macro_name))
macro_name = error_extension + macro_name;
restore_position (!(ret_code = execute_macro (macro_name + " " + error_extension + " " + file_name)));
save_position ();
move_abs (0, col);
if (mark_type)
drop_anchor (mark_type);
returns (ret_code);
}
void _error_cancel ()
{
_cancel_errorfix = 1;
_exit ();
}
/*
** _next_error, _prev_error, _error_info:
**
** These routines are the default routines for locating error
** information. They can be enhanced with file extension specific
** error location functions that are written for a specific compiler.
**
** The _next_error and _prev_error macros move the cursor to the
** next and previous error message, respectively. They return TRUE
** if another error message is found, and FALSE otherwise.
**
** _error_info takes a given line in the error buffer (located by
** the _next and _previous error routines) and returns the information
** needed by BRIEF to locate the error message. It returns 0 if there
** is no error message, 1 if the error is a warning, and 2 if it's an
** error. It also returns the line and column in the file the error
** corresponds to, as well as the message that should be displayed at
** the bottom of the window.
*/
/*
** _next_error, _prev_error:
**
** Both of these routines are passed the extension of the file that
** has been compiled and the full file name. Although the generic
** routines don't make use of this information, extension-specific
** routines could.
*/
int _next_error (~string)
{
returns (search_fwd ("<*.[a-zA-Z][~ \t\n]@[ \t,(:][ \t]@{line }@\\c[0-9]", 1, 0));
}
int _prev_error (~string)
{
returns (search_back ("<*.[a-zA-Z][~ \t\n]@[ \t,(:][ \t]@{line }@\\c[0-9]", 1, 0));
}
/*
** _error_info:
**
** This routine parses a given error line and returns information
** about it. It is passed the following parameters:
**
** Parameter Description
** --------- -----------
** 0 The name of the file the error was in.
**
** The following are write-only parameters passed back to the calling
** function:
**
** Parameter Description
** --------- -----------
** 1 The line of the file the error was on.
** 2 The column of the file the error was on.
** If 0 is passed back, the first non-blank
** character is assumed.
** 3 The actual error message, minus any useless
** information.
**
** Finally, this last parameter is the buffer identifier of the source
** buffer.
**
** Parameter Description
** --------- -----------
** 4 The full file name of the file the errors are
** in. This macro may reset this name if the
** errors are found in a different buffer.
**
** 5 The file that "owns" the errors -- could be
** different than parameter 4 if we're in an
** include file, and the error file is owned
** by a source file.
**
** _error_info returns an integer corresponding to the level of the
** error encountered.
**
** Error Code Meaning
** ---------- -------
** 0 No error
** 1 Warning error in source file
** -1 Warning error in another file
** 2 "Normal" error in source file
** -2 "Normal" error in another file
** 3 Actual line (not original) error in source file.
** -3 Actual line (not original) error in another file.
** 4 Actual line (not original) warning in source file.
** -4 Actual line (not original) warning in another file.
**
** This information is used by the next_error driver to determine
** how to display the message.
*/
int _error_info (string error_file, int, int, string, string file_name, string base_name)
{
int length,
position,
error_level,
error_line;
string error_text;
if (!(error_line = atoi (read (10))))
if (read (1) == "0")
error_line = 1;
else
return (FALSE);
save_position ();
beginning_of_line ();
error_text = trim (ltrim (read ()));
restore_position ();
error_level = WARNING + !index (lower (error_text), "warning");
/*
** If the error file name isn't found in the error text, we have to do
** more work...
*/
if (!index (lower (error_text), lower (error_file)))
{
position = search_string ("<*\\c[~ \t\"()'`]+.[a-zA-Z][~ \t\n\"()'`]@[ \t,\"()'`:]", error_text, length);
error_file = substr (error_text, position, length - 1);
if (!index ("/\\", substr (error_file, 1, 1)) && substr (error_file, 2, 1) != ":")
file_name = add_to_path (substr (base_name, 1, rindex (base_name, substr (base_name, 3, 1)) - 1), error_file);
else
file_name = error_file;
error_level *= -1;
}
error_text = trim (ltrim (read ()));
error_text = substr (error_text, search_string ("['`\"a-zA-Z]", error_text));
put_parm (1, error_line);
put_parm (2, 0);
put_parm (3, error_text);
put_parm (4, file_name);
returns (error_level);
}

Binary file not shown.
+447
View File
@@ -0,0 +1,447 @@
;**
;** BRIEF -- Basic Reconfigurable Interactive Editing Facility
;**
;** Written by Dave Nanian and Michael Strickman.
;**
;** errorfix.m
;**
;** This file contains the main driver and support macros for BRIEF's
;** error location facility.
;**
#define TRUE 1
#define FALSE 0
#define WARNING 1
#define ERROR 2
(extern add_to_path
center_line
_exit
)
;**
;** next_error:
;**
;** This routine is the engine for BRIEF's error location facility. It
;** reads in the error file and calls the appropriate routines to display
;** either an individual error message or a window full of error message
;** information.
;**
;** If no parameter (or zero) is passed to next_error, the error file is
;** read into a buffer and searched for error messages. If the buffer is
;** empty, the message "No errors." is displayed and the error buffer is
;** removed. If the buffer is not empty, and a message can be located, the
;** text of the message is displayed on the message line, the cursor is placed
;** on the first non-blank character of the line containing the error, and that
;** line is centered in the window. If no messages can be located, the error
;** file is presented in a pop-up window.
;**
;** If a "1" is passed to next_error, the error information is displayed in
;** a window, with the current message highlighted. If no messages could be
;** recognised, the highlight is not displayed, and the cursor can be moved
;** anywhere within the file.
;**
;** If a "2" is passed to next_error, the error file is tested to see if
;** any messages can be recognised. If so, the same action is taken as with
;** next_error 0. If not, no message is displayed and the error file buffer
;** is deleted.
;**
;** In all cases, next_error returns 0 if no error was found, and non-zero
;** if there was an error.
;**
(macro next_error
(
(int error_buf
curr_buf
line
col
error_type
more_errors
prev_errors
errors_exist
action
windowed
_cancel_errorfix
)
(string error_msg
error_file
buf_name
parms
error_extension
)
(global _cancel_errorfix)
(inq_names error_file error_extension buf_name)
(= curr_buf (inq_buffer))
(= _cancel_errorfix FALSE)
(if (strlen error_extension)
(= error_file (substr error_file 1 (- (rindex error_file ".") 1)))
)
(+= error_file ".err")
(= error_extension (+ "." error_extension))
(= parms (+ (+ error_extension " ") buf_name))
(if (! (= error_buf (create_buffer "Error File" error_file TRUE)))
(return FALSE)
)
(set_buffer error_buf)
(save_position)
(top_of_buffer)
(= errors_exist (end_of_buffer))
(restore_position)
(get_parm 0 action)
(if (! errors_exist)
(
(if (!= action 2)
(message "No errors.")
)
)
;else
(
(= windowed (== action 1))
(save_position)
(= more_errors (execute_macro (+ "_call_next " parms)))
(if (&& more_errors windowed)
(execute_macro (+ "_call_prev " parms))
;else
(
(down)
(save_position)
(= prev_errors (execute_macro (+ "_call_prev " parms)))
(restore_position)
(restore_position)
(save_position)
)
)
(= errors_exist (|| more_errors prev_errors))
(if (= windowed (&& (!= action 2) (|| windowed (! errors_exist))))
(
(int lines
cols
)
(keyboard_push)
(assign_to_key "<Enter>" "_exit")
(assign_to_key "<Esc>" "_error_cancel")
(assign_to_key "<Left>" "left")
(assign_to_key "<Right>" "right")
(assign_to_key "<Home>" "beginning_of_line")
(assign_to_key "<End>" "end_of_line")
(if errors_exist
(
(drop_anchor 3)
(assign_to_key "<Up>" (+ "_call_prev " parms))
(assign_to_key "<Down>" (+ "_call_next " parms))
)
;else
(
(assign_to_key "<Up>" "up")
(assign_to_key "<Down>" "down")
)
)
(beginning_of_line)
(inq_screen_size lines cols)
(create_window 5 (- lines 4) (- cols 5) 3 " or  to move, <Enter> to select, <Esc> to exit")
(attach_buffer error_buf)
(refresh)
(process)
(if errors_exist
(raise_anchor)
)
(delete_window)
(set_buffer curr_buf)
(keyboard_pop)
(set_buffer error_buf)
)
)
;**
;** At this point the cursor is pointing at the requested error
;** message. If the user didn't cancel, we display the chosen message
;** and move the cursor to the appropriate line.
;**
(restore_position errors_exist)
(if (! _cancel_errorfix)
(
(if (! (inq_macro (+= error_extension "_error_info")))
(= error_extension "_error_info")
)
(if
(&&
(|| (&& windowed errors_exist) more_errors)
(= error_type (execute_macro error_extension buf_name line col error_msg curr_buf))
)
(
(set_buffer curr_buf)
(if (> error_type 0)
(
(goto_old_line line)
(center_line)
(if col
(move_abs 0 col)
;else
(
(beginning_of_line)
(next_char (- (strlen (trim (read))) (strlen (ltrim (trim (read))))))
)
)
)
)
(if (|| (== error_type ERROR) (== (* error_type -1) ERROR))
(error error_msg)
;else
(message error_msg)
)
)
;else
(
(if windowed
(message (trim (ltrim (read))))
;else
(if errors_exist
(message "No more errors.")
)
)
)
)
)
)
)
)
(set_buffer curr_buf)
(if (&& (! (inq_views error_buf)) (&& (! more_errors) (! windowed)))
(delete_buffer error_buf)
)
(if _cancel_errorfix
(message "")
)
(returns more_errors)
)
)
;**
;** _call_next:
;**
;** This macro is used to call the _next_error function. It checks to
;** see if there is a file extension specific function first. If not, it
;** calls the generic function.
;**
(macro _call_next
(
(string error_extension
file_name
macro_name
)
(int ret_code
mark_type
col
)
(if (= mark_type (inq_marked))
(raise_anchor)
)
(get_parm 0 error_extension)
(get_parm 1 file_name)
(= macro_name "_next_error")
(if (inq_macro (+ error_extension macro_name))
(= macro_name (+ error_extension macro_name))
)
(inq_position NULL col)
(restore_position)
(= ret_code (execute_macro (+ macro_name (+ " " (+ error_extension (+ " " file_name))))))
(save_position)
(move_abs 0 col)
(if mark_type
(drop_anchor mark_type)
)
(returns ret_code)
)
)
;**
;** _call_prev:
;**
;** This macro is used to call the _prev_error function. It checks to
;** see if there is a file extension specific function first. If not, it
;** calls the generic function.
;**
(macro _call_prev
(
(string error_extension
file_name
macro_name
)
(int ret_code
mark_type
col
)
(if (= mark_type (inq_marked))
(raise_anchor)
)
(inq_position NULL col)
(restore_position)
(save_position)
(if (up)
(end_of_line)
)
(get_parm 0 error_extension)
(get_parm 1 file_name)
(= macro_name "_prev_error")
(if (inq_macro (+ error_extension macro_name))
(= macro_name (+ error_extension macro_name))
)
(restore_position (! (= ret_code (execute_macro (+ macro_name (+ " " (+ error_extension (+ " " file_name))))))))
(save_position)
(move_abs 0 col)
(if mark_type
(drop_anchor mark_type)
)
(returns ret_code)
)
)
(macro _error_cancel
(
(= _cancel_errorfix 1)
(_exit)
)
)
;**
;** _next_error, _prev_error, _error_info:
;**
;** These routines are the default routines for locating error
;** information. They can be enhanced with file extension specific
;** error location functions that are written for a specific compiler.
;**
;** The _next_error and _prev_error macros move the cursor to the
;** next and previous error message, respectively. They return TRUE
;** if another error message is found, and FALSE otherwise.
;**
;** _error_info takes a given line in the error buffer (located by
;** the _next and _previous error routines) and returns the information
;** needed by BRIEF to locate the error message. It returns 0 if there
;** is no error message, 1 if the error is a warning, and 2 if it's an
;** error. It also returns the line and column in the file the error
;** corresponds to, as well as the message that should be displayed at
;** the bottom of the window.
;**
;**
;** _next_error, _prev_error:
;**
;** Both of these routines are passed the extension of the file that
;** has been compiled and the full file name. Although the generic
;** routines don't make use of this information, extension-specific
;** routines could.
;**
(macro _next_error
(returns (search_fwd "<*.[a-zA-Z][~ \t\n]@[ \t,(:][ \t]@{line }@\\c[0-9]" 1 0))
)
(macro _prev_error
(returns (search_back "<*.[a-zA-Z][~ \t\n]@[ \t,(:][ \t]@{line }@\\c[0-9]" 1 0))
)
;**
;** _error_info:
;**
;** This routine parses a given error line and returns information
;** about it. It is passed the following parameters:
;**
;** Parameter Description
;** --------- -----------
;** 0 The name of the file the error was in.
;**
;** The following are write-only parameters passed back to the calling
;** function:
;**
;** Parameter Description
;** --------- -----------
;** 1 The line of the file the error was on.
;** 2 The column of the file the error was on.
;** If 0 is passed back, the first non-blank
;** character is assumed.
;** 3 The actual error message, minus any useless
;** information.
;**
;** Finally, this last parameter is the buffer identifier of the source
;** buffer.
;**
;** Parameter Description
;** --------- -----------
;** 4 The buffer identifier of the source buffer.
;**
;** _error_info returns an integer corresponding to the level of the
;** error encountered.
;**
;** Error Code Meaning
;** ---------- -------
;** 0 No error
;** 1 Warning error in source file
;** -1 Warning error in another file
;** 2 "Normal" error in source file
;** -2 "Normal" error in another file
;**
;** This information is used by the next_error driver to determine
;** how to display the message.
;**
(macro _error_info
(
(int error_level
error_line
)
(string error_text
error_file
)
(get_parm 0 error_file)
(if (! (= error_line (atoi (read 10))))
(if (== "0" (read 1))
(= error_line 1)
;else
(return FALSE)
)
)
(save_position)
(beginning_of_line)
(= error_text (trim (ltrim (read))))
(restore_position)
(= error_level (+ WARNING (! (index (lower error_text) "warning"))))
(if (index (lower error_text) error_file)
(
(= error_text (trim (ltrim (read))))
(= error_text (substr error_text (search_string "['`\"a-zA-Z]" error_text)))
)
;else
(*= error_level -1)
)
(put_parm 1 error_line)
(put_parm 2 0)
(put_parm 3 error_text)
(returns error_level)
)
)
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
;** External macro declarations
(extern autosave
toggle_re
)
;** Initials Macro
(macro AG
(
(color 0 7 15 7 15) ;** Set the screen colors
(autosave) ;** Automatic file save when idle
)
)
;** File Extension Macros
(macro default
(
(tabs 9 17)
)
)

Some files were not shown because too many files have changed in this diff Show More