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:
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
||||
0³
|
||||
0³
|
||||
1³ 1³
|
||||
|
||||
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³� ‘ ’ “ ” • – — ˜ ™ š › œ � ž Ÿ 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 º
|
||||
;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÏÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
|
||||
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
|
||||
;³ ³
|
||||
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
@@ -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
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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.
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
@@ -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.
@@ -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)
|
||||
)
|
||||
)
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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.
@@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -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.
@@ -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.
@@ -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 "[\\{\\}]"))
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -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.
@@ -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.
@@ -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.
@@ -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.
@@ -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.
@@ -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.")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -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.
@@ -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.
|
||||
@@ -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
@@ -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
|
||||
@@ -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.
@@ -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.
@@ -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.
@@ -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.
@@ -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.
@@ -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)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
cb -d snasm
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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.
@@ -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.
@@ -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
Reference in New Issue
Block a user