New menu editor, completely revamped menu system, and more.

This commit is contained in:
mysticbbs 2012-07-23 23:01:52 -04:00
parent b02e43ffea
commit 1e2fb72e90
13 changed files with 1615 additions and 935 deletions

View File

@ -4302,3 +4302,103 @@
+ MakeTheme now only looks at the "mysticbbs" environment variable if + MakeTheme now only looks at the "mysticbbs" environment variable if
mystic.dat is not found in the same directory. mystic.dat is not found in the same directory.
+ The "Transfer of XXX" file prompt has been enhanced to attempt to
always strip the filepath from the file, in case of a strange situation
where it somehow gets into the prompt info code.
+ Display files that are not found in a theme directory now have the option
to "fallback" to the default display file directory, if Theme fallback
is enabled for the theme.
+ Added new ANSI menu editor to replace the old outdated crap. The new
editor has references to all of the menu commands as well as the special
functional hotkeys.
+ Revamped the entire menu system. Menu files must be converted if you are
any version pre 1.10 alpha 15 using the CvtMenus program. Simply copy
this into your folder with all of the *.mnu files are run it one time ONLY
After you are done you will want to review your system because the new
system is not a direct convertion of file format. The method that Mystic
links menu commands has changed. The conversion program does its best to
analyze your menu files and create a menu that functions the same, but
there may be issues - particularly in lightbar grid menus I would guess
since they can be quite complex.
+ Each menu option on a menu now as its own "execution list" of menu
commands. This basically replaces the old "kludge" stacking of commands
to execute back to back with a single hotkey. It is a much more clean
approach this way, and it allows for more options!
+ Each menu command now has the option to redraw the menu or not after its
command list executes.
+ Menus can now be internally generated from 1 to 4 columns (up from 3)
+ Menus now contain a description configurable within the menu flags. A
new MCI code |MD goes along with it, and will display the description
of the current menu.
+ Menus now have an optional "user status" field in the menu flags. If this
is set to a non-blank value, the user's action in node listings will be
updated to this value. If the value is left blank, Mystic will use the
default "Browsing menus" prompt from the theme prompts.
+ Menus now have a "theme fallback" option similar to the recent change to
the display file system. If a menu is not found in its theme menu
directory, then if the option is enabled, Mystic will look for it in the
default menu directory configured in the System Configuration. When
combined with the similar display changes, it makes it very easy to build
additional themes off of the default. In your new themes, the stuff that
you haven't themed can simply fall back to your default theme now.
+ Merged the "Hot Key" and "Long Key" options from the old menu system into
one single hotkey field.
+ Added an "Input char" option to menu flags that defines how the user's
input is echoed back to them at a menu prompt. Valid options are
Uppercase, Lowercase, and hidden.
+ Lightbar menus now allow extended input while the lightbar continues to
function! This works for both standard lightbar and lightbar grid menus.
For example, you can set the hotkey to "OWNAGE" and have full lightbar
menu. Mystic will still recognize and execute the commands linked to
OWNAGE if the user types it. In addition, it has a smart input so that
it only allows valid characters to be entered. Mystic will use the X/Y
location of the cursor after the menu prompt is displayed, so it is best
to set where you might want to see the user's input (if its not hidden)
using the menu footer/prompt.
+ Lightbar grid menus now allow the following events to be handled in
addition to arrow keys:
Page Up
Page Down
Escape
Tab
+ In a lightbar grid menu, each menu command now has the ability to execute
on a grid-specific event. The following are available options:
Selected
Up
Down
Left
Right
Tab
Escape
PgUp
PgDn
+ All displayed menu items now have an option for display type. If it set
to Access it will only be displayed if the user has access. If it is set
to Always, it will always been displayed, and if it is set to Never, it
will never be displayed.
+ Lightbar and Lightbar/Grid menus now display menu header and prompts if
they are not set to a blank value. They were ignored in the past, but
this provides some better flexibility. If you have lightbar menus you
may need to validate that the header/footers in your menu flags are blank
if you do not want this feature.

View File

@ -10,6 +10,7 @@ Uses
Procedure WriteXY (X, Y, A: Byte; S: String); Procedure WriteXY (X, Y, A: Byte; S: String);
Procedure WriteXYPipe (X, Y, A, SZ : Byte; S: String); Procedure WriteXYPipe (X, Y, A, SZ : Byte; S: String);
Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String; Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String;
Function InBox (Header, Text, Def: String; Len, MaxLen: Byte) : String;
Procedure VerticalLine (X, Y1, Y2 : Byte); Procedure VerticalLine (X, Y1, Y2 : Byte);
Function ShowMsgBox (BoxType : Byte; Str : String) : Boolean; Function ShowMsgBox (BoxType : Byte; Str : String) : Boolean;
@ -90,7 +91,8 @@ Uses
m_Strings, m_Strings,
BBS_Core, BBS_Core,
BBS_IO, BBS_IO,
BBS_Common; BBS_Common,
BBS_Ansi_MenuInput;
Procedure WriteXY (X, Y, A: Byte; S: String); Procedure WriteXY (X, Y, A: Byte; S: String);
Begin Begin
@ -152,6 +154,46 @@ Begin
Session.io.BufFlush; Session.io.BufFlush;
End; End;
Function InBox (Header, Text, Def: String; Len, MaxLen: Byte) : String;
Var
Box : TAnsiMenuBox;
Input : TAnsiMenuInput;
Offset : Byte;
Str : String;
WinSize : Byte;
Begin
If Len > Length(Text) Then
Offset := Len
Else
Offset := Length(Text);
WinSize := (80 - Offset + 2) DIV 2;
Box := TAnsiMenuBox.Create;
Input := TAnsiMenuInput.Create;
Box.Header := ' ' + Header + ' ';
//Input.Attr := 15 + 4 * 16;
//Input.FillAttr := 7 + 4 * 16;
Input.LoChars := #13#27;
Box.Open (WinSize, 10, WinSize + Offset + 3, 15);
WriteXY (WinSize + 2, 12, 112, Text);
Str := Input.GetStr(WinSize + 2, 13, Len, MaxLen, 1, Def);
Box.Close;
If Input.ExitCode = #27 Then Str := '';
Input.Free;
Box.Free;
Result := Str;
End;
Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String; Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String;
Begin Begin
Session.io.AnsiGotoXY (X, Y); Session.io.AnsiGotoXY (X, Y);
@ -251,7 +293,7 @@ Begin
BoxAttr2 := 8 + 7 * 16; BoxAttr2 := 8 + 7 * 16;
BoxAttr3 := 15 + 7 * 16; BoxAttr3 := 15 + 7 * 16;
BoxAttr4 := 8 + 7 * 16; BoxAttr4 := 8 + 7 * 16;
HeadAttr := 0 + 7 * 16; HeadAttr := 15 + 1 * 16;
HeadType := 0; HeadType := 0;
HideImage := NIL; HideImage := NIL;
WasOpened := False; WasOpened := False;

View File

@ -44,6 +44,7 @@ Begin
'F' : Configuration_FileBaseEditor; 'F' : Configuration_FileBaseEditor;
'G' : Configuration_GroupEditor(True); 'G' : Configuration_GroupEditor(True);
'L' : Configuration_SecurityEditor(True); 'L' : Configuration_SecurityEditor(True);
'M' : Configuration_MenuEditor;
'P' : Configuration_ProtocolEditor; 'P' : Configuration_ProtocolEditor;
'R' : Configuration_GroupEditor(False); 'R' : Configuration_GroupEditor(False);
'U' : Configuration_UserEditor; 'U' : Configuration_UserEditor;
@ -122,7 +123,6 @@ Var
Session.io.AnsiClear; Session.io.AnsiClear;
Case Mode of Case Mode of
'M' : Menu_Editor;
'E' : Event_Editor; 'E' : Event_Editor;
'V' : Vote_Editor; 'V' : Vote_Editor;
End; End;
@ -288,12 +288,12 @@ Begin
'B' : Configuration_MessageBaseEditor; 'B' : Configuration_MessageBaseEditor;
'F' : Configuration_FileBaseEditor; 'F' : Configuration_FileBaseEditor;
'G' : Configuration_GroupEditor(True); 'G' : Configuration_GroupEditor(True);
'M' : Configuration_MenuEditor;
'P' : Configuration_ProtocolEditor; 'P' : Configuration_ProtocolEditor;
'R' : Configuration_GroupEditor(False); 'R' : Configuration_GroupEditor(False);
'S' : Configuration_SecurityEditor(True); 'S' : Configuration_SecurityEditor(True);
'T' : Configuration_ThemeEditor(False); 'T' : Configuration_ThemeEditor(False);
'U' : Configuration_UserEditor; 'U' : Configuration_UserEditor;
'M',
'E', 'E',
'V' : ExecuteOldConfiguration(Res); 'V' : ExecuteOldConfiguration(Res);
'X' : Break; 'X' : Break;

View File

@ -1,304 +1,706 @@
Unit bbs_cfg_menuedit; Unit bbs_cfg_MenuEdit;
{$I M_OPS.PAS} {$I M_OPS.PAS}
Interface Interface
Uses Procedure Configuration_MenuEditor;
DOS,
m_Strings,
m_FileIO,
bbs_Common,
bbs_Core,
bbs_User,
bbs_Menus;
Procedure Menu_Editor;
Implementation Implementation
Uses
DOS,
m_Types,
m_Output,
m_Strings,
m_QuickSort,
m_FileIO,
bbs_Ansi_MenuBox,
bbs_Ansi_MenuForm,
BBS_Core,
BBS_Common,
BBS_MenuData,
bbs_cfg_Theme,
bbs_cfg_Common;
Type
CmdRec = Record
Name : String[2];
Desc : String[30];
End;
Const
Num_Cmds = 96;
MenuCmds : Array[1..Num_Cmds] of CmdRec = (
// AUTOSIG MENU COMMANDS
( Name: 'AE'; Desc: 'Autosig editor' ),
( Name: 'AT'; Desc: 'Toggle autosig on/off' ),
( Name: 'AV'; Desc: 'View autosig' ),
// BBS LIST MENU COMMANDS
( Name: 'BA'; Desc: 'BBS list add' ),
( Name: 'BL'; Desc: 'BBS list view extended' ),
( Name: 'BS'; Desc: 'BBS list view' ),
// DOOR EXECUTION MENU COMMANDS
( Name: 'D-'; Desc: 'Exec door (no dropfile)' ),
( Name: 'D3'; Desc: 'Exec door (door32.sys)' ),
( Name: 'DC'; Desc: 'Exec door (CHAIN.TXT)' ),
( Name: 'DD'; Desc: 'Exec door (DORINFO1.DEF)' ),
( Name: 'DG'; Desc: 'Exec door (DOOR.SYS)' ),
// FILE BASE MENU COMMANDS
( Name: 'FA'; Desc: 'File area change' ),
( Name: 'FD'; Desc: 'Download file' ),
( Name: 'FF'; Desc: 'Download filelist' ),
( Name: 'FG'; Desc: 'File group change' ),
( Name: 'FL'; Desc: 'List files' ),
( Name: 'FN'; Desc: 'New file scan' ),
( Name: 'FP'; Desc: 'Set new filescan date' ),
( Name: 'FS'; Desc: 'Search for files' ),
( Name: 'FU'; Desc: 'Upload files' ),
( Name: 'FV'; Desc: 'View archive' ),
( Name: 'FZ'; Desc: 'Toggle newscan bases' ),
( Name: 'F1'; Desc: '(SYSOP) Mass upload' ),
( Name: 'F2'; Desc: '(SYSOP) Directory editor' ),
( Name: 'F3'; Desc: 'Send file by location' ),
// GENERAL MENU COMMANDS
( Name: 'G1'; Desc: 'Show BBS history' ),
( Name: 'GA'; Desc: 'ANSI art gallery' ),
( Name: 'GD'; Desc: 'Display a file' ),
( Name: 'GE'; Desc: 'Edit user settings' ),
( Name: 'GH'; Desc: 'Hangup' ),
( Name: 'GI'; Desc: 'Hangup immediately' ),
( Name: 'GL'; Desc: 'Show last callers' ),
( Name: 'GO'; Desc: 'Go to new menu' ),
( Name: 'GN'; Desc: 'Show one-liners' ),
( Name: 'GP'; Desc: 'Page Sysop for chat' ),
( Name: 'GR'; Desc: 'Return from gosub menu' ),
( Name: 'GS'; Desc: 'Gosub to new menu' ),
( Name: 'GT'; Desc: 'Display a line of text' ),
( Name: 'GU'; Desc: 'Display user list' ),
( Name: 'GX'; Desc: 'Execute MPL program' ),
( Name: 'G?'; Desc: 'Open ANSI help browser' ),
// MESSAGE BASE MENU COMMANDS
( Name: 'MA'; Desc: 'Message area change' ),
( Name: 'MC'; Desc: 'Check e-mail' ),
( Name: 'MD'; Desc: 'Set msg newscan date' ),
( Name: 'MG'; Desc: 'Message group change' ),
( Name: 'MM'; Desc: 'Send mass e-mail' ),
( Name: 'MN'; Desc: 'Message new scan' ),
( Name: 'MP'; Desc: 'Post a message' ),
( Name: 'MQ'; Desc: 'Message quick scan' ),
( Name: 'MR'; Desc: 'Read messages' ),
( Name: 'MS'; Desc: 'Global message search' ),
( Name: 'MV'; Desc: 'View sent e-mail' ),
( Name: 'MW'; Desc: 'Send new e-mail' ),
( Name: 'MX'; Desc: 'Post text file to base' ),
( Name: 'MZ'; Desc: 'Toggle new scan bases' ),
// NODE MENU COMMANDS
( Name: 'NA'; Desc: 'Set node action' ),
( Name: 'NC'; Desc: 'Enter teleconference chat' ),
( Name: 'NP'; Desc: 'Page user for private chat' ),
( Name: 'NS'; Desc: 'Send node message' ),
( Name: 'NW'; DEsc: 'Show whos online' ),
// OFFLINE MAIL MENU COMMANDS
( Name: 'OS'; Desc: 'Set QWK scanned bases' ),
( Name: 'OD'; Desc: 'Download QWK packet' ),
( Name: 'OU'; Desc: 'Upload REP packet' ),
// DOWNLOAD QUEUE MENU COMMANDS
( Name: 'QA'; Desc: 'Add file to batch queue' ),
( Name: 'QC'; Desc: 'Clear batch queue' ),
( Name: 'QD'; Desc: 'Delete from batch queue' ),
( Name: 'QL'; Desc: 'List batch queue' ),
// TIME BANK MENU COMMANDS
( Name: 'TD'; Desc: 'Deposit to time bank' ),
( Name: 'TW'; Desc: 'Withdraw from time bank' ),
// VOTING BOOTH MENU COMMANDS
( Name: 'VA'; Desc: 'Create voting poll' ),
( Name: 'VN'; Desc: 'Vote on new polls' ),
( Name: 'VR'; Desc: 'See poll results' ),
( Name: 'VV'; Desc: 'Vote on a poll' ),
// MATRIX LOGIN MENU COMMANDS
( Name: 'XA'; Desc: 'Matrix apply for access' ),
( Name: 'XC'; Desc: 'Matrix check for access' ),
( Name: 'XL'; Desc: 'Matrix login' ),
( Name: 'XP'; Desc: 'Matrix page sysop' ),
// OTHER MENU COMMANDS
( Name: '-D'; Desc: 'Set access flags (set 2)' ),
( Name: '-F'; Desc: 'Set access flags (set 1)' ),
( Name: '-K'; Desc: 'Add keys to input buffer' ),
( Name: '-N'; Desc: 'Ask Yes/No (default No)' ),
( Name: '-P'; Desc: 'Prompt for a password' ),
( Name: '-S'; Desc: 'Add text to Sysop log' ),
( Name: '-Y'; Desc: 'Ask Yes/No (default Yes)' ),
// SYSOP/EDITORS MENU COMMANDS
( Name: '*#'; Desc: '(SYSOP) Menu editor' ),
( Name: '*A'; Desc: '(SYSOP) Archive editor' ),
( Name: '*E'; Desc: '(SYSOP) Event editor' ),
( Name: '*F'; Desc: '(SYSOP) File base editor' ),
( Name: '*G'; Desc: '(SYSOP) Message group editor' ),
( Name: '*L'; Desc: '(SYSOP) Security level editor'),
( Name: '*B'; Desc: '(SYSOP) Message base editor' ),
( Name: '*P'; Desc: '(SYSOP) Protocol editor' ),
( Name: '*R'; Desc: '(SYSOP) File group editor' ),
( Name: '*S'; Desc: '(SYSOP) System configuration' ),
( Name: '*U'; Desc: '(SYSOP) User editor' ),
( Name: '*V'; Desc: '(SYSOP) Voting booth editor' )
); {123456789012345678901234567890}
Var Var
MenuFile : Text; Menu : TMenuData;
MenuName : String;
Changed : Boolean;
Procedure Menu_Editor; Procedure ViewMenu;
Var
Procedure ModifyMenu; OldData : TMenuData;
var a,b{,c} : byte; TmpImage : TConsoleImageRec;
{ tempcmd : menucmdrec;}
Begin Begin
Session.io.OutRaw ('Menu to Edit: '); Screen.GetScreenImage (1, 1, 79, 24, TmpImage);
Session.Menu.MenuName := Session.io.GetInput(mysMaxMenuNameLen, mysMaxMenuNameLen, 11, '');
If Session.Menu.LoadMenu(False, False, False) <> 1 Then Exit; Session.io.OutFull('|07|16|CL');
Session.io.BufFlush;
Repeat OldData := Session.Menu.Data;
Session.io.OutFullLn ('|CL|14Menu Command List|CR|03');
Session.io.OutFullLn ('|15## Hot-Key Cmd Text ## Hot-Key Cmd Text');
Session.io.OutFullLn ('|09-- -------- --- --------------------- -- -------- --- ---------------------|03');
For A := 1 to Session.Menu.CmdNum Do Begin Session.Menu.Data := Menu;
Session.io.OutRaw (strPadR(strI2S(A), 3, ' ') + strPadR(Session.Menu.MenuList[A].HotKey, 9, ' ') +
strPadR(Session.Menu.MenuList[A].Command, 4, ' ') + strPadR(Session.Menu.MenuList[A].Text, 21, ' ') + ' '); Session.Menu.ExecuteMenu(False, False, True, False);
If (A = Session.Menu.CmdNum) or (A Mod 2 = 0) Then Session.io.OutRawLn('');
Session.Menu.Data := OldData;
Session.io.RemoteRestore(TmpImage);
End; End;
Session.io.OutFull ('|CR|09(E)dit, (I)nsert, (D)elete, (F)lags, (V)iew, (Q)uit: '); Function GetCommandDesc (Str: String) : String;
Case Session.io.OneKey('EIDFVQ', True) of Var
'D' : begin Count : Byte;
Session.io.OutRaw('Delete which? '); Begin
a := strS2I(Session.io.GetInput(2, 2, 11, '')); Result := 'Unknown Command';
if (a > 0) and (a <= Session.Menu.CmdNum) then begin For Count := 1 to Num_Cmds Do
for b := a to Session.Menu.CmdNum do If Str = MenuCmds[Count].Name Then Begin
Session.Menu.Menulist[b] := Session.Menu.Menulist[b+1]; Result := MenuCmds[Count].Desc;
dec (Session.Menu.cmdnum);
end;
end;
'I' : if Session.Menu.CmdNum < mysMaxMenuCmds Then Begin
Session.io.OutRaw ('Insert before which (1-' + strI2S(Session.Menu.CmdNum + 1) + '): ');
A := strS2I(Session.io.GetInput(2, 2, 11, ''));
If (A > 0) And (A <= Session.Menu.CmdNum + 1) Then Begin
Inc (Session.Menu.CmdNum);
For B := Session.Menu.CmdNum DownTo A + 1 Do
Session.Menu.MenuList[B] := Session.Menu.MenuList[B - 1];
Session.Menu.MenuList[A].Text := '[XXX] New Command';
Session.Menu.MenuList[A].HotKey := 'XXX';
Session.Menu.MenuList[A].LongKey := 'XXX';
Session.Menu.MenuList[A].Access := '';
Session.Menu.MenuList[A].Command := '';
Session.Menu.MenuList[A].X := 0;
Session.Menu.MenuList[A].Y := 0;
Session.Menu.MenuList[A].Textlo := '';
Session.Menu.MenuList[A].Texthi := '';
End;
End;
'F' : Begin
repeat
Session.io.OutFullLn ('|CL|14Menu Flags (' + Session.Menu.MenuName + ')|CR|03');
Session.io.OutRawLn ('A. Menu Header : ' + strPadR(Session.Menu.Menu.header, 59, ' '));
Session.io.OutRawLn ('B. Menu Prompt : ' + strPadR(Session.Menu.menu.prompt, 59, ' '));
Session.io.OutRawLn ('C. Display Cols : ' + strI2S(Session.Menu.Menu.DispCols));
Session.io.OutRawLn ('D. ACS : ' + Session.Menu.menu.access);
Session.io.OutRawLn ('E. Password : ' + Session.Menu.menu.password);
Session.io.OutRawLn ('F. Display File : ' + Session.Menu.Menu.dispFile);
Session.io.OutRawLn ('G. Fallback Menu : ' + Session.Menu.Menu.Fallback);
Session.io.OutRaw ('H. Menu Type : ');
Case Session.Menu.Menu.MenuType of
0 : Session.io.OutRawLn ('Standard');
1 : Session.io.OutRawLn ('Lightbar');
2 : Session.io.OutRawLn ('Lightbar Grid');
End;
Session.io.OutRawLn ('I. Finish X/Y : ' + strPadR(strI2S(Session.Menu.menu.donex), 3, ' ') + strI2S(Session.Menu.menu.doney));
Session.io.OutRawLn ('J. Use Global MNU: ' + Session.io.OutYN(Session.Menu.Menu.Global=1));
Session.io.OutRaw ('K. Input Type : ');
Case Session.Menu.Menu.InputType of
0 : Session.io.OutRawLn ('User setting');
1 : Session.io.OutRawLn ('Hotkey');
2 : Session.io.OutRawLn ('Longkey');
End;
Session.io.OutFull ('|CR|09(V)iew or (Q)uit: ');
Case Session.io.OneKey('ABCDEFGHIJKQV', True) of
'A' : Session.Menu.Menu.Header := Session.io.InXY(20, 3, 60, 255, 11, Session.Menu.Menu.Header);
'B' : Session.Menu.Menu.Prompt := Session.io.InXY(20, 4, 60, 255, 11, Session.Menu.Menu.Prompt);
'C' : Begin
Session.Menu.Menu.DispCols := strS2I(Session.io.InXY(20, 5, 1, 1, 12, strI2S(Session.Menu.Menu.DispCols)));
If Session.Menu.Menu.DispCols < 1 Then Session.Menu.Menu.DispCols := 1;
If Session.Menu.Menu.DispCols > 3 Then Session.Menu.Menu.DispCols := 3;
End;
'D' : Session.Menu.Menu.AcCeSs := Session.io.InXY(20, 6, 30, 30, 11, Session.Menu.Menu.AcCeSs);
'E' : Session.Menu.Menu.Password := Session.io.InXY(20, 7, 15, 15, 12, Session.Menu.Menu.Password);
'F' : Session.Menu.Menu.dispFile := Session.io.InXY(20, 8, 20, 20, 11, Session.Menu.Menu.dispFile);
'G' : Session.Menu.Menu.Fallback := Session.io.InXY(20, 9, mysMaxMenuNameLen, mysMaxMenuNameLen, 11, Session.Menu.Menu.Fallback);
'H' : If Session.Menu.Menu.MenuType = 2 Then Session.Menu.Menu.MenuType := 0 Else Inc(Session.Menu.Menu.MenuType);
'I' : Begin
Session.Menu.Menu.donex := strS2I(Session.io.InXY(20, 11, 2, 2, 12, strI2S(Session.Menu.Menu.donex)));
Session.Menu.Menu.doney := strS2I(Session.io.InXY(23, 11, 2, 2, 12, strI2S(Session.Menu.Menu.doney)));
End;
'J' : If Session.Menu.Menu.Global = 1 Then dec(Session.Menu.Menu.global) else Session.Menu.Menu.global := 1;
'K' : If Session.Menu.Menu.InputType = 2 Then Session.Menu.Menu.InputType := 0 Else Inc(Session.Menu.Menu.InputType);
'Q' : Break;
'V' : Session.Menu.ExecuteMenu (False, False, True);
End;
Until False;
End;
'E' : Begin
Session.io.OutRaw ('Edit which? ');
a := strS2I(Session.io.GetInput(2, 2, 11, ''));
If (a > 0) and (a <= Session.Menu.CmdNum) then Begin
Repeat
Session.io.OutFullLn ('|CL|14Menu command ' + strI2S(a) + ' of ' + strI2S(Session.Menu.CmdNum) + '|CR|03');
Session.io.OutRawln ('A. Text : ' + Session.Menu.MenuList[A].text);
Session.io.OutRawln ('B. Hot Key : ' + Session.Menu.MenuList[A].HotKey);
Session.io.OutRawLn ('C. Long Key: ' + Session.Menu.MenuList[A].LongKey);
Session.io.OutRawln ('D. ACS : ' + Session.Menu.MenuList[A].access);
Session.io.OutRawln ('E. Command : ' + Session.Menu.MenuList[A].command);
Session.io.OutRawln ('F. Data : ' + Session.Menu.MenuList[A].data);
Session.io.OutFullLn ('|CRG. Lightbar X/Y : ' + strPadR(strI2S(Session.Menu.MenuList[a].x), 3, ' ') + strI2S(Session.Menu.MenuList[a].y));
Session.io.OutRawln ('H. Lightbar Text : ' + Session.Menu.MenuList[a].textlo);
Session.io.OutRawln ('I. Lightbar High : ' + Session.Menu.MenuList[a].texthi);
Session.io.OutRawln ('');
Session.io.OutRawln ('J. Lightbar Up : ' + strI2S(Session.Menu.MenuList[a].cUP));
Session.io.OutRawln ('K. Lightbar Down : ' + strI2S(Session.Menu.MenuList[a].cDOWN));
Session.io.OutRawln ('L. Lightbar Left : ' + strI2S(Session.Menu.MenuList[a].cLEFT));
Session.io.OutRawln ('M. Lightbar Right: ' + strI2S(Session.Menu.MenuList[a].cRIGHT));
Session.io.OutFull ('|CR|09([) Previous, (]) Next, (Q)uit: ');
case session.io.onekey('[]ABCDEFGHIJKLMQ', True) of
'[' : If A > 1 Then Dec(A);
']' : If A < Session.Menu.CmdNum Then Inc(A);
'A' : Session.Menu.MenuList[A].Text := Session.io.InXY(14, 3, 60, 79, 11, Session.Menu.MenuList[A].Text);
'B' : Session.Menu.MenuList[A].HotKey := Session.io.InXY(14, 4, 8, 8, 12, Session.Menu.MenuList[A].HotKey);
'C' : Session.Menu.MenuList[A].LongKey := Session.io.InXY(14, 5, 8, 8, 12, Session.Menu.MenuList[A].LongKey);
'D' : Session.Menu.MenuList[A].Access := Session.io.InXY(14, 6, 30, 30, 11, Session.Menu.MenuList[A].Access);
'E' : Repeat
Session.io.OutFull ('|09Menu Command (?/List): ');
Session.Menu.MenuList[A].command := Session.io.GetInput(2, 2, 12, '');
If Session.Menu.MenuList[A].Command = '?' Then
session.io.OutFile ('menucmds', True, 0)
Else
Break; Break;
Until False;
'F' : Session.Menu.MenuList[A].Data := Session.io.InXY(14, 8, 60, 79, 11, Session.Menu.MenuList[a].data);
'G' : Begin
Session.Menu.MenuList[A].X := strS2I(Session.io.InXY(20, 10, 2, 2, 12, strI2S(Session.Menu.MenuList[A].X)));
Session.Menu.MenuList[A].Y := strS2I(Session.io.InXY(23, 10, 2, 2, 12, strI2S(Session.Menu.MenuList[A].Y)));
End; End;
'H' : Session.Menu.MenuList[A].Textlo := Session.io.InXY(20, 11, 59, 79, 11, Session.Menu.MenuList[A].Textlo);
'I' : Session.Menu.MenuList[A].Texthi := Session.io.InXY(20, 12, 59, 79, 11, Session.Menu.MenuList[A].Texthi);
'J' : Session.Menu.MenuList[A].cUP := strS2I(Session.io.InXY(20, 14, 2, 2, 12, strI2S(Session.Menu.MenuList[A].cUP)));
'K' : Session.Menu.MenuList[A].cDOWN := strS2I(Session.io.InXY(20, 15, 2, 2, 12, strI2S(Session.Menu.MenuList[A].cDOWN)));
'L' : Session.Menu.MenuList[A].cLEFT := strS2I(Session.io.InXY(20, 16, 2, 2, 12, strI2S(Session.Menu.MenuList[A].cLEFT)));
'M' : Session.Menu.MenuList[A].cRIGHT := strS2I(Session.io.InXY(20, 17, 2, 2, 12, strI2S(Session.Menu.MenuList[A].cRIGHT)));
'Q' : Break;
end;
until false;
End;
End;
(*
'P' : begin
Session.io.OutRaw('Move which? ');
a := strS2I(Session.io.GetInput(2, 2, 11, ''));
Session.io.OutRaw('Move before which (1-' + strI2S(Session.Menu.CmdNum+1) + '): ');
b := strS2I(Session.io.GetInput(2, 2, 11, ''));
end;
*)
'Q' : break;
'V' : Session.Menu.ExecuteMenu(False, False, True);
end;
Until false;
Session.io.OutFullLn ('|14Saving...');
assign (menufile, Session.Theme.menupath + Session.Menu.menuname + '.mnu');
rewrite (menufile);
writeln (menufile, Session.Menu.Menu.header);
writeln (menufile, Session.Menu.Menu.prompt);
writeln (menufile, Session.Menu.Menu.dispcols);
writeln (menufile, Session.Menu.Menu.access);
writeln (menufile, Session.Menu.Menu.password);
writeln (menufile, Session.Menu.Menu.dispfile);
WriteLn (MenuFile, Session.Menu.Menu.Fallback);
writeln (menufile, Session.Menu.Menu.MenuType);
WriteLn (MenuFile, Session.Menu.Menu.InputType);
WriteLn (MenuFile, Session.Menu.Menu.DoneX);
WriteLn (MenuFile, Session.Menu.Menu.DoneY);
WriteLn (MenuFile, Session.Menu.Menu.Global);
for a := 1 to Session.Menu.CmdNum do begin
writeln (menufile, Session.Menu.MenuList[a].text);
writeln (menufile, Session.Menu.MenuList[a].HotKey);
WriteLn (MenuFile, Session.Menu.MenuList[A].LongKey);
writeln (menufile, Session.Menu.MenuList[a].access);
writeln (menufile, Session.Menu.MenuList[a].command);
writeln (menufile, Session.Menu.MenuList[a].data);
writeln (menufile, Session.Menu.MenuList[a].x);
writeln (menufile, Session.Menu.MenuList[a].y);
writeln (menufile, Session.Menu.MenuList[a].cUP);
WriteLn (MenuFile, Session.Menu.MenuList[A].cDOWN);
WriteLn (MenuFile, Session.Menu.MenuList[A].cLEFT);
WriteLn (MenuFile, Session.Menu.MenuList[A].cRIGHT);
writeln (menufile, Session.Menu.MenuList[a].textlo);
writeln (menufile, Session.Menu.MenuList[a].texthi);
end;
close (menufile);
End; End;
Function GetCommand (Str: String) : String;
Var Var
Old : String[8]; List : TAnsiMenuList;
OldLang : RecTheme; Count : Byte;
DirInfo: SearchRec;
A : Byte; {format dir output}
Begin Begin
If session.Theme.filename = '' then exit; List := TAnsiMenuList.Create;
Old := Session.Menu.MenuName; For Count := 1 to Num_Cmds Do Begin
OldLang := Session.Theme; List.Add (MenuCmds[Count].Name + ' ' + MenuCmds[Count].Desc, 0);
Session.SystemLog ('*MENU EDITOR*'); If Str = MenuCmds[Count].Name Then
List.Picked := Count;
End;
Session.io.OutFull ('|CL'); List.Open (21, 4, 59, 19);
Session.User.GetLanguage; List.Close;
If List.ExitCode = #13 Then Begin
Changed := Str = MenuCmds[List.Picked].Name;
Str := MenuCmds[List.Picked].Name;
End;
List.Free;
Result := Str;
End;
Procedure GetExtendedKey (Var Key: String);
Var
List : TAnsiMenuList;
Begin
List := TAnsiMenuList.Create;
List.Add ('FIRSTCMD', 0);
List.Add ('EVERY', 0);
List.Add ('AFTER', 0);
List.Add ('LINEFEED', 0);
List.Add ('TIMER', 0);
List.Add ('UP', 0);
List.Add ('DOWN', 0);
List.Add ('LEFT', 0);
List.Add ('RIGHT', 0);
List.Add ('ENTER', 0);
List.Add ('TAB', 0);
List.Add ('ESCAPE', 0);
List.Add ('HOME', 0);
List.Add ('END', 0);
List.Add ('PAGEUP', 0);
List.Add ('PAGEDOWN', 0);
List.Open (35, 4, 46, 21);
List.Close;
If List.ExitCode <> #27 Then Begin
Changed := List.List[List.Picked]^.Name <> Key;
Key := List.List[List.Picked]^.Name;
End;
List.Free;
End;
Procedure EditCommand (Num, CmdNum: Word);
Var
Box : TAnsiMenuBox;
Form : TAnsiMenuForm;
Topic : String;
CmdStr : String;
Begin
Topic := '|03(|09Menu Cmd Editor|03) |01-|09> |15';
Box := TAnsiMenuBox.Create;
Form := TAnsiMenuForm.Create;
Box.Header := ' Menu (' + MenuName + '): Command #' + strI2S(Num) + ' ';
Box.Open (13, 9, 68, 16);
VerticalLine (24, 11, 14);
Form.AddNone ('C', ' Command ', 15, 11, 9, Topic + 'Menu command function');
Form.AddStr ('A', ' Access ' , 16, 12, 26, 12, 8, 30, 30, @Menu.Item[Num]^.CmdData[CmdNum]^.Access, Topic + 'Access level to run this command');
Form.AddStr ('D', ' Data ' , 18, 13, 26, 13, 6, 40, 80, @Menu.Item[Num]^.CmdData[CmdNum]^.Data, Topic + 'Menu command optional data');
Form.AddTog ('G', ' Execute ', 15, 14, 26, 14, 9, 6, 0, 8, 'Selected Up Down Left Right Tab Escape PgUp PgDn', @Menu.Item[Num]^.CmdData[CmdNum]^.JumpID, Topic + '(Grid) Execute command on what Grid event?');
Repeat Repeat
Session.io.OutFullLn ('|CL|14Menu Editor (Language: ' + Session.Theme.Desc + ')|CR'); CmdStr := '(' + Menu.Item[Num]^.CmdData[CmdNum]^.MenuCmd + ') ' + GetCommandDesc(Menu.Item[Num]^.CmdData[CmdNum]^.MenuCmd);
Session.io.OutFullLn ('|08Directory of ' + Session.Theme.MenuPath + '*.MNU|CR|03'); WriteXY (26, 11, 113, strPadR(CmdStr, 40, ' '));
a := 0;
FindFirst (Session.Theme.MenuPath + '*.mnu', Archive, DirInfo);
While DosError = 0 Do Begin
inc (a);
Session.io.OutRaw (strPadR(DirInfo.Name, 25, ' '));
FindNext (DirInfo);
if (a = 3) or (DosError <> 0) then begin
Session.io.OutRawln('');
a := 0
end;
Case Form.Execute of
#27 : Break;
'C' : Begin
Menu.Item[Num]^.CmdData[CmdNum]^.MenuCmd := GetCommand(Menu.Item[Num]^.CmdData[CmdNum]^.MenuCmd);
Changed := True;
End;
End; End;
Session.io.OutFull ('|CR|09(E)dit, (I)nsert, (D)elete, (Q)uit? '); Changed := Changed or Form.Changed;
Case session.io.OneKey('EIDQ', True) of Until False;
'E' : ModifyMenu;
'I' : Begin; Changed := Changed or Form.Changed;
Session.io.OutRaw ('Menu Name: ');
Session.menu.MenuName := Session.io.GetInput(mysMaxMenuNameLen, mysMaxMenuNameLen, 11, ''); Box.Close;
If Session.Menu.MenuName <> '' Then Begin
Assign (MenuFile, Session.Theme.MenuPath + Session.Menu.MenuName + '.mnu'); Box.Free;
{$I-} Reset(MenuFile); {$I+} Form.Free;
If IoResult = 0 Then End;
Session.io.OutRawLn ('Menu already exists')
Else Begin Procedure EditItem (Num: Word);
Rewrite (MenuFile); Const
WriteLn (MenuFile, 'New Menu'); Status1 = '(TAB) to edit menu commands';
WriteLn (MenuFile, 'Command: '); Status2 = '(TAB) Switch (/) Commands';
WriteLn (MenuFile, '2'); Var
WriteLn (MenuFile, ''); Box : TAnsiMenuBox;
WriteLn (MenuFile, ''); List : TAnsiMenuList;
WriteLn (MenuFile, ''); Form : TAnsiMenuForm;
WriteLn (MenuFile, 'main'); Topic : String;
WriteLn (MenuFile, '0');
WriteLn (MenuFile, '0'); Procedure MakeList;
WriteLn (MenuFile, '0'); Var
WriteLn (MenuFile, '0'); Count : Word;
WriteLn (MenuFile, '1'); Begin
Close (MenuFile); List.Clear;
For Count := 1 to Menu.Item[Num]^.Commands Do
With Menu.Item[Num]^.CmdData[Count]^ Do Begin
List.Add(strPadR('(' + MenuCmd + ') ' + GetCommandDesc(MenuCmd), 26, ' ') + ' ' +
strPadR(Access, 12, ' ') + ' ' + Data, 0);
End;
List.Add ('', 0);
End;
Begin
Box := TAnsiMenuBox.Create;
List := TAnsiMenuList.Create;
Form := TAnsiMenuForm.Create;
Form.LoExitChars := #09#12#27;
List.LoChars := #09#13#27#47;
List.LoAttr := 113;
List.NoInput := True;
List.NoWindow := True;
Box.Header := ' Command #' + strI2S(Num) + ' (' + MenuName + ') ';
Topic := '|03(|09Menu Editor|03) |01-|09> |15';
Box.Open (3, 2, 77, 21);
VerticalLine (20, 4, 10);
VerticalLine (71, 3, 11);
WriteXY (5, 12, 112, 'Command Access Data');
WriteXY (5, 13, 112, strRep('Ä', 71));
WriteXY (5, 20, 112, strPadC(Status1, 72, ' '));
WriteXY (5, 19, 112, strRep('Ä', 71));
MakeList;
List.Open (4, 13, 77, 19);
List.Picked := 0;
List.Update;
Form.AddPipe ('D', ' Display Text ' , 6, 4, 22, 4, 14, 40, 160, @Menu.Item[Num]^.Text, Topic + 'Text displayed on generated menus');
Form.AddPipe ('O', ' LightBar Low ' , 6, 5, 22, 5, 14, 40, 160, @Menu.Item[Num]^.TextLo, Topic + 'Normal text in lightbar menu');
Form.AddPipe ('I', ' LightBar High ', 5, 6, 22, 6, 15, 40, 160, @Menu.Item[Num]^.TextHi, Topic + 'Highlighted text in lightbar menu');
Form.AddCaps ('H', ' Hot Key ' , 11, 7, 22, 7, 9, 12, mysMaxMenuInput, @Menu.Item[Num]^.HotKey, Topic + 'Key to run this command (CTRL-L/Extended Key List)');
Form.AddStr ('A', ' Access ' , 12, 8, 22, 8, 8, 30, 30, @Menu.Item[Num]^.Access, Topic + 'ACS level required to access this command');
Form.AddTog ('N', ' Display Type ' , 6, 9, 22, 9, 14, 6, 0, 2, 'Access Always Never', @Menu.Item[Num]^.ShowType, Topic + 'How should this command be displayed?');
Form.AddByte ('X', 'X' , 16, 10, 22, 10, 1, 2, 0, 80, @Menu.Item[Num]^.X, Topic + 'X coordinate of lightbar');
Form.AddByte ('Y', 'Y' , 18, 10, 25, 10, 1, 2, 0, 50, @Menu.Item[Num]^.Y, Topic + 'Y coordinate of lightbar');
Form.AddByte ('U', ' Up ' , 67, 3, 73, 3, 4, 3, 0, 255, @Menu.Item[Num]^.JumpUp, Topic + '(Grid) Item # to jump to when UP is pressed');
Form.AddByte ('D', ' Down ' , 65, 4, 73, 4, 6, 3, 0, 255, @Menu.Item[Num]^.JumpDown, Topic + '(Grid) Item # to jump to when DOWN is pressed');
Form.AddByte ('L', ' Left ' , 65, 5, 73, 5, 6, 3, 0, 255, @Menu.Item[Num]^.JumpLeft, Topic + '(Grid) Item # to jump to when LEFT is pressed');
Form.AddByte ('R', ' Right ' , 64, 6, 73, 6, 7, 3, 0, 255, @Menu.Item[Num]^.JumpRight, Topic + '(Grid) Item # to jump to when RIGHT is pressed');
Form.AddByte ('E', ' Escape ' , 63, 7, 73, 7, 8, 3, 0, 255, @Menu.Item[Num]^.JumpEscape, Topic + '(Grid) Item # to jump to when ESCAPE is pressed');
Form.AddByte ('T', ' Tab ' , 66, 8, 73, 8, 5, 3, 0, 255, @Menu.Item[Num]^.JumpTab, Topic + '(Grid) Item # to jump to when TAB is pressed');
Form.AddByte ('P', ' PageUp ' , 63, 9, 73, 9, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgUp, Topic + '(Grid) Item # to jump to when PGUP is pressed');
Form.AddByte ('G', ' PageDn ' , 63, 10, 73, 10, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgDn, Topic + '(Grid) Item # to jump to when PGDN is pressed');
Form.AddBol ('W', ' Redraw ' , 63, 11, 73, 11, 8, 3, @Menu.Item[Num]^.ReDraw, Topic + 'Redraw menu after running this command?');
Repeat
Case Form.Execute of
#09 : Begin
Repeat
MakeList;
WriteXY (5, 20, 112, strPadC(Status2, 72, ' '));
List.NoInput := False;
List.Open (4, 13, 77, 19);
Case List.ExitCode of
'/' : Case GetCommandOption(10, 'A-Add|D-Delete|') of
'A' : Begin
Menu.InsertCommand(Num, List.Picked);
Changed := True;
End;
'D' : If List.Picked <> List.ListMax Then Begin
Menu.DeleteCommand(Num, List.Picked);
Changed := True;
End; End;
End; End;
#09 : Begin
List.Picked := 0;
List.Update;
Break;
End; End;
'D' : Begin #13 : If List.Picked <> List.ListMax Then EditCommand(Num, List.Picked);
Session.io.OutRaw ('Menu to delete: '); #27 : Break;
Session.Menu.MenuName := Session.io.GetInput(mysMaxMenuNameLen, mysMaxMenuNameLen, 11, '');
FileErase(Session.Theme.MenuPath + Session.Menu.MenuName + '.mnu');
End;
'Q' : Break;
End; End;
Until False; Until False;
Session.Menu.MenuName := Old;
Session.Theme := OldLang; WriteXY (5, 20, 112, strPadC(Status1, 72, ' '));
Close (Session.PromptFile);
Assign (Session.PromptFile, Config.DataPath + Session.Theme.FileName + '.thm'); If List.ExitCode = #27 Then Break;
Reset (Session.PromptFile); End;
#12 : GetExtendedKey(Menu.Item[Num]^.HotKey);
#27 : Break;
End;
Changed := Changed or Form.Changed;
Until False;
Changed := Changed or Form.Changed;
Box.Close;
Form.Free;
List.Free;
Box.Free;
End;
Procedure EditFlags;
Var
Box : TAnsiMenuBox;
Form : TAnsiMenuForm;
Topic : String;
Begin
Box := TAnsiMenuBox.Create;
Form := TAnsiMenuForm.Create;
Box.Header := ' Menu Flags (' + MenuName + ') ';
Topic := '|03(|09Menu Flags|03) |01-|09> |15';;
Box.Open (6, 5, 75, 20);
VerticalLine (22, 7, 19);
Form.AddStr ('D', ' Description ' , 9, 7, 24, 7, 13, 30, 30, @Menu.Info.Description, Topic + 'Description of menu');
Form.AddStr ('A', ' Access ' , 14, 8, 24, 8, 8, 30, 30, @Menu.Info.Access, Topic + 'Security requirements to access this menu');
Form.AddTog ('T', ' Menu Type ' , 11, 9, 24, 9, 11, 13, 0, 2, 'Standard Lightbar Lightbar/Grid', @Menu.Info.MenuType, Topic + 'Type of menu');
Form.AddTog ('I', ' Input Type ' , 10, 10, 24, 10, 12, 12, 0, 2, 'User_Defined HotKey LongKey', @Menu.Info.InputType, Topic + 'Input type for this menu');
Form.AddTog ('C', ' Input Chars ' , 9, 11, 24, 11, 13, 9, 0, 2, 'Uppercase Lowercase Hidden', @Menu.Info.CharType, Topic + 'Input format display');
Form.AddBol ('G', ' Use Global ' , 10, 12, 24, 12, 12, 3, @Menu.Info.Global, Topic + 'Include global menu options in this menu?');
Form.AddStr ('N', ' Node Status ' , 9, 13, 24, 13, 13, 30, 30, @Menu.Info.NodeStatus, Topic + 'Node/User status set when this menu is loaded');
Form.AddStr ('F', ' Display File ', 8, 14, 24, 14, 14, 20, 20, @Menu.Info.DispFile, Topic + 'Display file shown instead of generated menu');
Form.AddTog ('L', ' Display Cols ', 8, 15, 24, 15, 14, 1, 1, 4, '1 2 3 4', @Menu.Info.DispCols, Topic + 'Number of columns in generated menu');
Form.AddPipe ('H', ' Menu Header ' , 9, 16, 24, 16, 13, 50, 160, @Menu.Info.Header, Topic + 'Menu header displayed in generated menu');
Form.AddPipe ('P', ' Menu Prompt ' , 9, 17, 24, 17, 13, 50, 160, @Menu.Info.Footer, Topic + 'Menu prompt displayed in generated menu');
Form.AddByte ('X', ' X ' , 19, 18, 24, 18, 3, 2, 0, 80, @Menu.Info.DoneX, Topic + 'Locate to X coordinate after lightbar menu');
Form.AddByte ('Y', ' Y ' , 19, 19, 24, 19, 3, 2, 0, 50, @Menu.Info.DoneY, Topic + 'Locate to Y coordinate after lightbar menu');
Form.Execute;
Changed := Changed Or Form.Changed;
Box.Close;
Box.Free;
Form.Free;
End;
Procedure EditMenu;
Var
Box : TAnsiMenuBox;
List : TAnsiMenuList;
Count : Word;
CopyItem : Word;
Str : String;
Begin
Menu := TMenuData.Create;
Menu.Load (False, Session.Theme.MenuPath + MenuName + '.mnu');
Box := TAnsiMenuBox.Create;
List := TAnsiMenuList.Create;
List.NoWindow := True;
List.LoChars := #13#27#47;
Box.Header := ' Command list (' + MenuName + ') ';
Box.Open (9, 5, 72, 21);
WriteXY (11, 6, 112, 'Hot Key Text Exec');
WriteXY (11, 7, 112, strRep('Ä', 60));
WriteXY (11, 19, 112, strRep('Ä', 60));
WriteXY (29, 20, 112, cfgCommandList);
CopyItem := 0;
Repeat
List.Clear;
For Count := 1 to Menu.NumItems Do Begin
Str := strStripMCI(Menu.Item[Count]^.Text);
If (Str = '') And (Menu.Item[Count]^.TextLo <> '') Then
Str := strStripMCI(Menu.Item[Count]^.TextLo);
List.Add (strPadR(Menu.Item[Count]^.HotKey, 15, ' ') +
strPadR(Str, 43, ' ') +
strPadL(strI2S(Menu.Item[Count]^.Commands), 2, ' '), 0);
End;
List.Add ('', 0);
List.Open (9, 7, 72, 19);
Case List.ExitCode of
'/' : Case GetCommandOption(10, 'F-Flags|A-Add|D-Delete|C-Copy|P-Paste|V-View|') of
'A' : Begin
Menu.InsertItem(List.Picked);
Changed := True;
End;
'C' : If List.Picked <> List.ListMax Then
CopyItem := List.Picked;
'D' : If List.Picked <> List.ListMax Then Begin
Menu.DeleteItem(List.Picked);
Changed := True;
End;
'F' : EditFlags;
'P' : If (CopyItem > 0) And (CopyItem < List.ListMax) And (Menu.Item[CopyItem] <> NIL) Then Begin
Menu.CopyItem(CopyItem, List.Picked);
Changed := True;
End;
'V' : ViewMenu;
End;
#13 : If List.Picked <> List.ListMax Then
EditItem (List.Picked);
#27 : Break;
End;
Until False;
Box.Close;
List.Free;
Box.Free;
If Changed Then
If ShowMsgBox(1, 'Save changes to ' + MenuName + '?') Then
If Not Menu.Save(Session.Theme.MenuPath + MenuName + '.mnu') Then
ShowMsgBox(0, 'Unable to save menu');
Menu.Free;
End;
Function GetMenuName (OldName: String) : String;
Var
Box : TAnsiMenuBox;
List : TAnsiMenuList;
MF : Text;
Procedure MakeList;
Var
Dir : SearchRec;
Sort : TQuickSort;
Count : Word;
Desc : String;
Begin
Sort := TQuickSort.Create;
FindFirst (Session.Theme.MenuPath + '*.mnu', Archive, Dir);
While DosError = 0 Do Begin
Sort.Add(JustFileName(Dir.Name), 0);
FindNext (Dir);
End;
FindClose(Dir);
Sort.Sort(1, Sort.Total, qAscending);
List.Clear;
For Count := 1 to Sort.Total Do Begin
Assign (MF, Session.Theme.MenuPath + Sort.Data[Count]^.Name + '.mnu');
{$I-} Reset (MF); {$I+}
If IoResult = 0 Then Begin
ReadLn (MF, Desc);
Close (MF);
End Else
Desc := '';
List.Add(strPadR(Sort.Data[Count]^.Name, 22, ' ') + Desc, 0);
If Sort.Data[Count]^.Name = OldName Then
List.Picked := List.ListMax;
End;
Sort.Free;
End;
Procedure CopyMenu (Orig: String);
Var
Str : String;
Begin
Str := InBox('Copy menu', 'New menu name: ', '', 20, 20);
If Str = '' Then Exit;
Str := Session.Theme.MenuPath + Str + '.mnu';
If FileExist(Str) Then
If ShowMsgBox(1, JustFile(Str) + ' already exists. Overwrite?') Then
FileErase(Str);
FileCopy(Session.Theme.MenuPath + Orig + '.mnu', Str);
End;
Procedure InsertMenu;
Var
Str : String;
OK : Boolean;
Begin
Str := InBox('Insert Menu', 'New menu name: ', '', 20, 20);
If Str = '' Then Exit;
OK := Not FileExist(Session.Theme.MenuPath + Str + '.mnu');
If Not OK Then
OK := ShowMsgBox(1, Str + ' already exists. Overwrite?');
If OK Then Begin
Menu := TMenuData.Create;
Menu.CreateNewMenu(Session.Theme.MenuPath + Str + '.mnu');
Menu.Free;
End;
End;
Begin
Result := '';
Box := TAnsiMenuBox.Create;
List := TAnsiMenuList.Create;
List.NoWindow := True;
List.LoChars := #13#27#47;
Box.Header := ' Menu Editor (' + Session.Theme.Desc + ') ';
Box.Open (12, 5, 68, 21);
WriteXY (14, 6, 112, 'Menu Name Description');
WriteXY (14, 7, 112, strRep('Ä', 53));
WriteXY (14, 19, 112, strRep('Ä', 53));
WriteXY (29, 20, 112, cfgCommandList);
Repeat
Changed := False;
MakeList;
List.Open (12, 7, 68, 19);
Case List.ExitCode of
'/' : Case GetCommandOption(10, 'I-Insert|D-Delete|C-Copy|') of
'C' : If List.ListMax > 0 Then
CopyMenu(strWordGet(1, List.List[List.Picked]^.Name, ' '));
'I' : InsertMenu;
'D' : If List.ListMax > 0 Then
If ShowMsgBox(1, 'Delete menu: ' + strWordGet(1, List.List[List.Picked]^.Name, ' ')) Then
FileErase (Session.Theme.MenuPath + strWordGet(1, List.List[List.Picked]^.Name, ' ') + '.mnu');
End;
#13 : Begin
If List.ListMax <> 0 Then
Result := strWordGet(1, List.List[List.Picked]^.Name, ' ');
Break;
End;
#27 : Break;
End;
Until False;
Box.Close;
List.Free;
Box.Free;
End;
Procedure Configuration_MenuEditor;
Var
Saved : String;
Begin
Saved := '';
MenuName := Configuration_ThemeEditor(True);
If MenuName = '' Then Exit;
Repeat
MenuName := GetMenuName(Saved);
Saved := MenuName;
If MenuName = '' Then Exit;
EditMenu;
Until False;
End; End;
End. End.

View File

@ -25,7 +25,7 @@ Type
User : TBBSUser; User : TBBSUser;
Msgs : TMsgBase; Msgs : TMsgBase;
FileBase : TFileBase; FileBase : TFileBase;
Menu : TMenuSystem; Menu : TMenuEngine;
IO : TBBSIO; IO : TBBSIO;
Client : TSocketClass; Client : TSocketClass;
EventFile : File of EventRec; EventFile : File of EventRec;
@ -131,7 +131,7 @@ Begin
IO := TBBSIO.Create(Pointer(Self)); IO := TBBSIO.Create(Pointer(Self));
Msgs := TMsgBase.Create(Pointer(Self)); Msgs := TMsgBase.Create(Pointer(Self));
FileBase := TFileBase.Create(Pointer(Self)); FileBase := TFileBase.Create(Pointer(Self));
Menu := TMenuSystem.Create(Pointer(Self)); Menu := TMenuEngine.Create(Pointer(Self));
End; End;
Destructor TBBSCore.Destroy; Destructor TBBSCore.Destroy;

View File

@ -411,6 +411,8 @@ Begin
Session.io.OutRawLn (''); Session.io.OutRawLn ('');
Session.io.PromptInfo[1] := JustFile(Data);
If dszSearch(JustFile(Data)) Then Begin If dszSearch(JustFile(Data)) Then Begin
Result := True; Result := True;
Session.io.OutFullLn (Session.GetPrompt(385)); Session.io.OutFullLn (Session.GetPrompt(385));
@ -2862,7 +2864,8 @@ Begin
Session.io.OutRawLn (''); Session.io.OutRawLn ('');
For A := 1 to BatchNum Do Begin For A := 1 to BatchNum Do Begin
Session.io.PromptInfo[1] := Batch[A].FileName; Session.io.PromptInfo[1] := JustFile(Batch[A].FileName);
If dszSearch (Batch[A].FileName) Then Begin If dszSearch (Batch[A].FileName) Then Begin
Session.SystemLog ('Download: ' + Batch[A].FileName); Session.SystemLog ('Download: ' + Batch[A].FileName);

View File

@ -84,7 +84,7 @@ Type
Procedure OutBS (Num : Byte; Del: Boolean); Procedure OutBS (Num : Byte; Del: Boolean);
Procedure OutFull (Str : String); Procedure OutFull (Str : String);
Procedure OutFullLn (Str : String); Procedure OutFullLn (Str : String);
Procedure OutFile (FName : String; DoPause: Boolean; Speed: Byte); Function OutFile (FName : String; DoPause: Boolean; Speed: Byte) : Boolean;
Function OutYN (Y : Boolean) : String; Function OutYN (Y : Boolean) : String;
Function OutON (O : Boolean) : String; Function OutON (O : Boolean) : String;
Procedure PauseScreen; Procedure PauseScreen;
@ -192,16 +192,9 @@ Var
Begin Begin
{$IFDEF WINDOWS} {$IFDEF WINDOWS}
If OutBufPos > 0 Then Begin If OutBufPos > 0 Then Begin
If Not TBBSCore(Core).LocalMode Then Begin If Not TBBSCore(Core).LocalMode Then
Res := TBBSCore(Core).Client.WriteBuf(OutBuffer, OutBufPos); Res := TBBSCore(Core).Client.WriteBuf(OutBuffer, OutBufPos);
(* Moved to m_sockets_class 1.10a14
While (Res = -1) and (WSAGetLastError = EWOULDBLOCK) Do Begin
WaitMS(10);
Res := TBBSCore(Core).Client.WriteBuf(OutBuffer, OutBufPos);
End;*)
End;
OutBufPos := 0; OutBufPos := 0;
End; End;
{$ENDIF} {$ENDIF}
@ -533,6 +526,10 @@ Begin
End; End;
'M' : Case Code[2] of 'M' : Case Code[2] of
'B' : LastMCIValue := TBBSCore(Core).Msgs.MBase.Name; 'B' : LastMCIValue := TBBSCore(Core).Msgs.MBase.Name;
'D' : If Session.Menu.Data <> NIL Then
LastMCIValue := Session.Menu.Data.Info.Description
Else
LastMCIValue := '';
'E' : LastMCIValue := strI2S(TBBSCore(Core).User.ThisUser.Emails); 'E' : LastMCIValue := strI2S(TBBSCore(Core).User.ThisUser.Emails);
'G' : LastMCIValue := TBBSCore(Core).Msgs.Group.Name; 'G' : LastMCIValue := TBBSCore(Core).Msgs.Group.Name;
'L' : LastMCIValue := OutON(TBBSCore(Core).User.ThisUser.UseLBIndex); 'L' : LastMCIValue := OutON(TBBSCore(Core).User.ThisUser.UseLBIndex);
@ -694,9 +691,6 @@ Procedure TBBSIO.OutFull (Str : String);
Var Var
A : Byte; A : Byte;
B : Byte; B : Byte;
D : DirStr;
N : NameStr;
E : ExtStr;
Begin Begin
A := 1; A := 1;
@ -720,8 +714,7 @@ Begin
While (Str[B] <> ' ') and (Str[B] <> '|') and (B <= Length(Str)) Do While (Str[B] <> ' ') and (Str[B] <> '|') and (B <= Length(Str)) Do
Inc (B); Inc (B);
FSplit (strStripLOW(Copy(Str, A + 1, B - A - 1)), D, N, E); OutFile (JustFile(strStripLOW(Copy(Str, A + 1, B - A - 1))), True, 0);
OutFile (TBBSCore(Core).Theme.TextPath + N + E, True, 0);
A := B; A := B;
@ -919,7 +912,7 @@ Begin
If O Then OutON := 'On' Else OutON := 'Off'; {++lang} If O Then OutON := 'On' Else OutON := 'Off'; {++lang}
End; End;
Procedure TBBSIO.OutFile (FName : String; DoPause: Boolean; Speed: Byte); Function TBBSIO.OutFile (FName : String; DoPause: Boolean; Speed: Byte) : Boolean;
Var Var
Buffer : Array[1..4096] of Char; Buffer : Array[1..4096] of Char;
BufPos : LongInt; BufPos : LongInt;
@ -932,6 +925,25 @@ Var
Ch : Char; Ch : Char;
Done : Boolean; Done : Boolean;
Function CheckFileInPath (Path: String) : Boolean;
Var
Temp : String;
Begin
Result := False;
Temp := Path + FName;
If (Graphics = 1) and (FileExist(Temp + '.ans')) Then Begin
Ext := '.ans';
FName := Temp;
Result := True;
End Else
If FileExist(Temp + '.asc') Then Begin
Ext := '.asc';
FName := Temp;
Result := True;
End;
End;
Function GetChar : Char; Function GetChar : Char;
Begin Begin
If BufPos = BufSize Then Begin If BufPos = BufSize Then Begin
@ -951,37 +963,42 @@ Var
End; End;
Begin Begin
If Pos(PathChar, FName) = 0 Then Result := False;
FName := TBBSCore(Core).Theme.TextPath + FName; NoFile := True;
If Pos('.', FName) > 0 Then If (Pos(PathSep, FName) > 0) or (Pos('.', FName) > 0) Then Begin
Ext := '' If Not FileExist(FName) Then
Else If Not CheckFileInPath('') Then Exit;
If (Graphics = 1) and (FileExist(FName + '.ans')) Then End Else Begin
Ext := '.ans' If Not CheckFileInPath(Session.Theme.TextPath) Then
Else If Session.Theme.Flags AND thmFallBack <> 0 Then Begin
Ext := '.asc'; If Not CheckFileInPath(Config.TextPath) Then Exit;
End Else
Exit;
If FileExist(FName + Copy(Ext, 1, 3) + '1') Then Begin If FileExist(FName + Copy(Ext, 1, 3) + '1') Then Begin
Repeat Repeat
BufPos := Random(9); BufPos := Random(9);
If BufPos = 0 Then If BufPos = 0 Then
Code := Ext[Length(Ext)] Code := Ext[Length(Ext)]
Else Else
Code := strI2S(BufPos); Code := strI2S(BufPos);
Until FileExist(FName + Copy(Ext, 1, 3) + Code); Until FileExist(FName + Copy(Ext, 1, 3) + Code);
Ext := Copy(Ext, 1, 3) + Code; Ext := Copy(Ext, 1, 3) + Code;
End; End;
Assign (dFile, FName + Ext);
{$I-} Reset(dFile, 1); {$I+}
If IoResult <> 0 Then Begin
NoFile := True;
Exit;
End; End;
Assign (dFile, FName + Ext);
{$I-} Reset(dFile, 1); {$I+}
If IoResult <> 0 Then Exit;
NoFile := False; NoFile := False;
Result := True;
Old := AllowPause; Old := AllowPause;
AllowPause := DoPause; AllowPause := DoPause;
PausePtr := 1; PausePtr := 1;
@ -1032,7 +1049,7 @@ Begin
Str := Str + GetChar; Str := Str + GetChar;
End; End;
OutFile (TBBSCore(Core).Theme.TextPath + strStripLOW(Str), True, 0); OutFile (JustFile(strStripLOW(Str)), True, 0);
Continue; Continue;
End; End;

File diff suppressed because it is too large Load Diff

View File

@ -951,7 +951,7 @@ Begin
Session.Menu.MenuName := 'newinfo'; Session.Menu.MenuName := 'newinfo';
Session.Menu.ExecuteMenu (False, False, False); Session.Menu.ExecuteMenu (False, False, False, True);
Session.io.OutFullLn (Session.GetPrompt(21)); Session.io.OutFullLn (Session.GetPrompt(21));
@ -1227,7 +1227,7 @@ Begin
If Config.UseMatrix Then Begin If Config.UseMatrix Then Begin
Repeat Repeat
Session.Menu.MenuName := Config.MatrixMenu; Session.Menu.MenuName := Config.MatrixMenu;
Session.Menu.ExecuteMenu (True, False, False); Session.Menu.ExecuteMenu (True, False, False, True);
Until MatrixOK or Session.ShutDown; Until MatrixOK or Session.ShutDown;
End; End;

View File

@ -619,10 +619,7 @@ Var
Box : TMenuBox; Box : TMenuBox;
InKey : TMenuInput; InKey : TMenuInput;
Str : String; Str : String;
Save : Boolean;
Begin Begin
Save := True;
Box := TMenuBox.Create(Console); Box := TMenuBox.Create(Console);
InKey := TMenuInput.Create(Console); InKey := TMenuInput.Create(Console);

View File

@ -787,7 +787,6 @@ End;
Function TParserEngine.ParseElement (VN: Word; TypeCheck: Boolean; VT: TIdentTypes) : TIdentTypes; Function TParserEngine.ParseElement (VN: Word; TypeCheck: Boolean; VT: TIdentTypes) : TIdentTypes;
Var Var
Element : String; Element : String;
RecNum : Word;
Count : Word; Count : Word;
Found : Boolean; Found : Boolean;
Offset : LongInt; Offset : LongInt;
@ -1659,8 +1658,6 @@ Function TParserEngine.ParseVariableInfo (Param: Boolean; IsRec: Boolean; Var In
End; End;
Procedure ParseVarType; Procedure ParseVarType;
Var
Count : LongInt;
Begin Begin
GetIdent(False); GetIdent(False);

View File

@ -461,6 +461,6 @@ Begin
Session.Menu.MenuName := Config.DefStartMenu; Session.Menu.MenuName := Config.DefStartMenu;
Repeat Repeat
Session.Menu.ExecuteMenu (True, True, False); Session.Menu.ExecuteMenu (True, True, False, True);
Until False; Until False;
End. End.

View File

@ -46,7 +46,10 @@ Const
mysMaxBatchQueue = 50; // max files per queue mysMaxBatchQueue = 50; // max files per queue
mysMaxVoteQuestion = 20; // Max number of voting questions mysMaxVoteQuestion = 20; // Max number of voting questions
mysMaxMenuNameLen = 20; // menu name size mysMaxMenuNameLen = 20; // menu name size
mysMaxMenuCmds = 75; // Maximum menu commands per menu mysMaxMenuItems = 75; // Maximum menu items per menu
mysMaxMenuCmds = 20; // Max menu commands per item
mysMaxMenuInput = 12;
mysMaxMenuStack = 8;
mysMaxThemeText = 493; // Total prompts in theme file mysMaxThemeText = 493; // Total prompts in theme file
fn_SemFileEcho = 'echomail.now'; fn_SemFileEcho = 'echomail.now';
@ -512,43 +515,55 @@ Type
Hidden : Boolean; Hidden : Boolean;
End; End;
(* Mystic BBS stores it's menu files as text files. They *) PtrMenuCmd = ^RecMenuCmd;
(* have been stored this way to make it possible to edit them with a text *) RecMenuCmd = Packed Record
(* editor (which is sometimes easier then using the menu editor). The *) MenuCmd : String[2];
(* following records do not need to be used, but provide one way of *) Access : String[mysMaxAcsSize];
(* reading a menu into a record. *) Data : String[80];
JumpID : Byte;
RecMenuFlags = Record
Header : String[255];
Prompt : String[255];
DispCols : Byte;
Access : String[30];
Password : String[15];
DispFile : String[20];
FallBack : String[20];
MenuType : Byte; { 0 = standard, 1 = lightbar, 2 = lightbar grid }
InputType : Byte; { 0 = user setting, 1 = longkey, 2 = hotkey }
DoneX : Byte;
DoneY : Byte;
Global : Byte; { 0 = no, 1 = yes }
End; End;
PtrMenuCommand = ^RecMenuCommand; PtrMenuItem = ^RecMenuItem;
RecMenuCommand = Record RecMenuItem = Packed Record
Text : String[79]; Text : String[160];
TextLo : String[79]; TextLo : String[160];
TextHi : String[79]; TextHi : String[160];
HotKey : String[8]; HotKey : String[mysMaxMenuInput];
LongKey : String[8]; Access : String[mysMaxAcsSize];
Access : string[30]; ShowType : Byte;
Command : String[2]; ReDraw : Byte;
Data : String[79]; JumpUp : Byte;
JumpDown : Byte;
JumpLeft : Byte;
JumpRight : Byte;
JumpEscape : Byte;
JumpTab : Byte;
JumpPgUp : Byte;
JumpPgDn : Byte;
JumpHome : Byte;
JumpEnd : Byte;
CmdData : Array[1..mysMaxMenuCmds] of PtrMenuCmd;
Commands : Byte;
X : Byte; X : Byte;
Y : Byte; Y : Byte;
cUp : Byte; Timer : Word;
cDown : Byte; End;
cLeft : Byte;
cRight : Byte; RecMenuInfo = Packed Record
Description : String[30];
Access : String[mysMaxAcsSize];
DispFile : String[20];
Password : String[20];
NodeStatus : String[30];
Header : String[160];
Footer : String[160];
DoneX : Byte;
DoneY : Byte;
MenuType : Byte;
InputType : Byte;
CharType : Byte;
DispCols : Byte;
Global : Boolean;
End; End;
RecPercent = Record RecPercent = Record