diff --git a/mystic/HISTORY.txt b/mystic/HISTORY.txt index 928956d..4283084 100644 --- a/mystic/HISTORY.txt +++ b/mystic/HISTORY.txt @@ -4313,7 +4313,8 @@ + 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. + functional hotkeys. It still maintains the ability to "simulate" menus + as well. + 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 @@ -4336,7 +4337,9 @@ 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. + command list executes. This defaults to on to mimic previous menu system + however for some advanced stuff, like TIMER, you may will to turn them + off. + Menus can now be internally generated from 1 to 4 columns (up from 3) @@ -4423,10 +4426,21 @@ counter used to fire off TIMER commands. It represents the number of seconds that have passed since the menu was loaded. + + TIMER commands also have 3 types, configurable per each menu option: + + Interval - Always execute at the configured timed interval + OnlyOnce - Execute at interval ONLY ONCE per menu being loaded + PerRedraw - Execute after each menu redraw as per timer interval + + When using hotkey-style menu input, extended hotkeys are no longer required to have a / first. You can make a hotkey command named QUIT for example, and it will execute immediately when QUIT is entered. + Keep in mind it is still a hot-key styled input. So you cannot have + one hotkey named QUIT and one named QUITNOW. The QUIT command will + always get the hotkey. If you need functionality like that, hotkeys + can be disabled on the menu. + + Similar to the display file and menu systems, the MPL scripts directory will now also fallback from the theme scripts path to the default scripts directory if the feature is enabled in the selected theme. diff --git a/mystic/bbs_cfg_menuedit.pas b/mystic/bbs_cfg_menuedit.pas index f852a27..642dd89 100644 --- a/mystic/bbs_cfg_menuedit.pas +++ b/mystic/bbs_cfg_menuedit.pas @@ -307,6 +307,7 @@ Procedure EditItem (Num: Word); Const Status1 = ' (TAB) to edit menu commands '; Status2 = ' (TAB) Switch (/) Commands '; + Grid = '(Grid) Item # to jump to on keypress '; Var Box : TAnsiMenuBox; List : TAnsiMenuList; @@ -357,30 +358,30 @@ Begin List.Picked := 0; List.Update; - Form.AddPipe ('D', ' Display Text ' , 4, 6, 20, 6, 14, 58, 160, @Menu.Item[Num]^.Text, Topic + 'Text displayed on generated menus'); - Form.AddPipe ('O', ' LightBar Low ' , 4, 7, 20, 7, 14, 58, 160, @Menu.Item[Num]^.TextLo, Topic + 'Normal text in lightbar menu'); - Form.AddPipe ('I', ' LightBar High ', 3, 8, 20, 8, 15, 58, 160, @Menu.Item[Num]^.TextHi, Topic + 'Highlighted text in lightbar menu'); - Form.AddCaps ('H', ' Hot Key ' , 9, 9, 20, 9, 9, 12, mysMaxMenuInput, @Menu.Item[Num]^.HotKey, Topic + 'Key to run this command (CTRL-L/Extended Key List)'); - Form.AddStr ('A', ' Access ' , 10, 10, 20, 10, 8, 30, 30, @Menu.Item[Num]^.Access, Topic + 'ACS level required to access this command'); - Form.AddTog ('S', ' Display Type ' , 4, 11, 20, 11, 14, 6, 0, 2, 'Access Always Never', @Menu.Item[Num]^.ShowType, Topic + 'How should this command be displayed?'); + Form.AddPipe ('D', ' Display Text' , 4, 6, 20, 6, 14, 58, 160, @Menu.Item[Num]^.Text, Topic + 'Text displayed on generated menus'); + Form.AddPipe ('O', ' LightBar Low' , 4, 7, 20, 7, 14, 58, 160, @Menu.Item[Num]^.TextLo, Topic + 'Normal text in lightbar menu'); + Form.AddPipe ('I', ' LightBar High' , 3, 8, 20, 8, 15, 58, 160, @Menu.Item[Num]^.TextHi, Topic + 'Highlighted text in lightbar menu'); + Form.AddCaps ('H', ' Hot Key' , 9, 9, 20, 9, 9, 12, mysMaxMenuInput, @Menu.Item[Num]^.HotKey, Topic + 'Key to run this command (CTRL-L/Extended Key List)'); + Form.AddStr ('A', ' Access' , 10, 10, 20, 10, 8, 30, 30, @Menu.Item[Num]^.Access, Topic + 'ACS level required to access this command'); + Form.AddTog ('S', ' Display Type' , 4, 11, 20, 11, 14, 6, 0, 2, 'Access Always Never', @Menu.Item[Num]^.ShowType, Topic + 'How should this command be displayed?'); Form.AddByte ('X', 'X' , 14, 12, 20, 12, 1, 2, 0, 80, @Menu.Item[Num]^.X, Topic + 'X coordinate of lightbar'); Form.AddByte ('Y', 'Y' , 16, 12, 23, 12, 1, 2, 0, 50, @Menu.Item[Num]^.Y, Topic + 'Y coordinate of lightbar'); - Form.AddWord ('M', ' Timer ' , 11, 13, 20, 13, 7, 5, 0, 65535, @Menu.Item[Num]^.Timer, Topic + 'Timer interval (seconds)'); - Form.AddTog ('X', ' Exec Type' , 7, 14, 20, 14, 11, 9, 0, 2, 'Interval OnlyOnce PerRedraw', @Menu.Item[Num]^.TimerType, Topic + 'TIMER event execution type'); + Form.AddWord ('M', ' Timer' , 11, 13, 20, 13, 7, 5, 0, 65535, @Menu.Item[Num]^.Timer, Topic + 'Timer interval (seconds)'); + Form.AddTog ('X', ' Timer Type' , 6, 14, 20, 14, 12, 9, 0, 2, 'Interval OnlyOnce PerRedraw', @Menu.Item[Num]^.TimerType, Topic + 'TIMER event execution type'); - Form.AddBol ('W', ' Redraw ' , 33, 14, 43, 14, 8, 3, @Menu.Item[Num]^.ReDraw, Topic + 'Redraw menu after running this command?'); + Form.AddBol ('W', ' Redraw' , 33, 14, 43, 14, 8, 3, @Menu.Item[Num]^.ReDraw, Topic + 'Redraw menu after running this command?'); - Form.AddByte ('U', ' Up ' , 56, 10, 62, 10, 4, 3, 0, 255, @Menu.Item[Num]^.JumpUp, Topic + '(Grid) Item # to jump to when UP is pressed'); - Form.AddByte ('D', ' Down ' , 54, 11, 62, 11, 6, 3, 0, 255, @Menu.Item[Num]^.JumpDown, Topic + '(Grid) Item # to jump to when DOWN is pressed'); - Form.AddByte ('L', ' Left ' , 54, 12, 62, 12, 6, 3, 0, 255, @Menu.Item[Num]^.JumpLeft, Topic + '(Grid) Item # to jump to when LEFT is pressed'); - Form.AddByte ('R', ' Right ' , 53, 13, 62, 13, 7, 3, 0, 255, @Menu.Item[Num]^.JumpRight, Topic + '(Grid) Item # to jump to when RIGHT is pressed'); - Form.AddByte ('E', ' Home ' , 54, 14, 62, 14, 6, 3, 0, 255, @Menu.Item[Num]^.JumpHome, Topic + '(Grid) Item # to jump to when HOME is pressed'); + Form.AddByte ('U', ' Up' , 56, 10, 62, 10, 4, 3, 0, 255, @Menu.Item[Num]^.JumpUp, Topic + Grid + 'UP'); + Form.AddByte ('D', ' Down' , 54, 11, 62, 11, 6, 3, 0, 255, @Menu.Item[Num]^.JumpDown, Topic + Grid + 'DOWN'); + Form.AddByte ('L', ' Left' , 54, 12, 62, 12, 6, 3, 0, 255, @Menu.Item[Num]^.JumpLeft, Topic + Grid + 'LEFT'); + Form.AddByte ('R', ' Right' , 53, 13, 62, 13, 7, 3, 0, 255, @Menu.Item[Num]^.JumpRight, Topic + Grid + 'RIGHT'); + Form.AddByte ('E', ' Home' , 54, 14, 62, 14, 6, 3, 0, 255, @Menu.Item[Num]^.JumpHome, Topic + Grid + 'HOME'); - Form.AddByte ('C', ' Escape ' , 65, 10, 75, 10, 8, 3, 0, 255, @Menu.Item[Num]^.JumpEscape, Topic + '(Grid) Item # to jump to when ESCAPE is pressed'); - Form.AddByte ('T', ' Tab ' , 68, 11, 75, 11, 5, 3, 0, 255, @Menu.Item[Num]^.JumpTab, Topic + '(Grid) Item # to jump to when TAB is pressed'); - Form.AddByte ('P', ' PageUp ' , 65, 12, 75, 12, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgUp, Topic + '(Grid) Item # to jump to when PGUP is pressed'); - Form.AddByte ('G', ' PageDn ' , 65, 13, 75, 13, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgDn, Topic + '(Grid) Item # to jump to when PGDN is pressed'); - Form.AddByte ('N', ' End ' , 68, 14, 75, 14, 5, 3, 0, 255, @Menu.Item[Num]^.JumpEnd, Topic + '(Grid) Item # to jump to when END is pressed'); + Form.AddByte ('C', ' Escape' , 65, 10, 75, 10, 8, 3, 0, 255, @Menu.Item[Num]^.JumpEscape, Topic + Grid + 'ESCAPE'); + Form.AddByte ('T', ' Tab' , 68, 11, 75, 11, 5, 3, 0, 255, @Menu.Item[Num]^.JumpTab, Topic + Grid + 'TAB'); + Form.AddByte ('P', ' PageUp' , 65, 12, 75, 12, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgUp, Topic + Grid + 'PGUP'); + Form.AddByte ('G', ' PageDn' , 65, 13, 75, 13, 8, 3, 0, 255, @Menu.Item[Num]^.JumpPgDn, Topic + Grid + 'PGDN'); + Form.AddByte ('N', ' End' , 68, 14, 75, 14, 5, 3, 0, 255, @Menu.Item[Num]^.JumpEnd, Topic + Grid + 'END'); WriteXY (26, 21, 120, Status1); @@ -453,19 +454,19 @@ Begin 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.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; diff --git a/mystic/bbs_io.pas b/mystic/bbs_io.pas index 723a7e6..80bca71 100644 --- a/mystic/bbs_io.pas +++ b/mystic/bbs_io.pas @@ -95,6 +95,7 @@ Type Function InXY (X, Y, Field, Max, Mode: Byte; Default: String) : String; Function InKey (Wait: LongInt) : Char; Function GetYNL (Str: String; Yes: Boolean) : Boolean; + Function DoInputEvents (Var Ch: Char) : Boolean; Function GetKey : Char; Function GetYN (Str: String; Yes: Boolean) : Boolean; Function GetPW (Str : String; BadStr : String; PW : String) : Boolean; @@ -1258,9 +1259,76 @@ Begin End; {$ENDIF} -Function TBBSIO.GetKey : Char; +Function TBBSIO.DoInputEvents (Var Ch: Char) : Boolean; Var TimeCount : LongInt; +Begin + Result := False; + + If InMacro Then + If InMacroPos <= Length(InMacroStr) Then Begin + Ch := InMacroStr[InMacroPos]; + Result := True; + + Inc (InMacroPos); + Exit; + End Else + InMacro := False; + + If TBBSCore(Core).CheckTimeOut Then + If TimerSeconds - TBBSCore(Core).TimeOut >= Config.Inactivity Then Begin + TBBSCore(Core).SystemLog('Inactivity timeout'); + OutFullLn (TBBSCore(Core).GetPrompt(136)); + Halt(0); + End; + + If Session.AllowMessages And Not Session.InMessage Then Begin + Dec (Session.MessageCheck); + + If Session.MessageCheck = 0 Then Begin + CheckNodeMessages; + + Session.MessageCheck := mysMessageThreshold; + End; + End; + + TimeCount := TBBSCore(Core).TimeLeft; + + If TimeCount <> Session.LastTimeLeft Then Begin + Session.LastTimeLeft := TimeCount; + + {$IFNDEF UNIX} + UpdateStatusLine(StatusPtr, ''); + {$ENDIF} + + If TBBSCore(Core).TimerOn Then Begin + If TimeCount = 5 Then Begin + If Not TBBSCore(Core).TimeChecked Then Begin + TBBSCore(Core).TimeChecked := True; + OutFullLn (TBBSCore(Core).GetPrompt(134)); + End; + End Else + If TimeCount < 1 Then Begin + If Not TBBSCore(Core).TimeChecked Then Begin + TBBSCore(Core).TimeChecked := True; + OutFullLn (TBBSCore(Core).GetPrompt(135)); + TBBSCore(Core).SystemLog ('User ran out of time'); + Halt(0); + End; + End Else + TBBSCore(Core).TimeChecked := False; + End; + + If TBBSCore(Core).NextEvent.Active Then + If (TBBSCore(Core).MinutesUntilEvent(TBBSCore(Core).NextEvent.ExecTime) = TBBSCore(Core).NextEvent.Warning) And + (Not TBBSCore(Core).EventWarn) And (TBBSCore(Core).NextEvent.Forced) Then Begin + TBBSCore(Core).EventWarn := True; + OutFullLn (TBBSCore(Core).GetPrompt(133)); + End; + End; +End; + +Function TBBSIO.GetKey : Char; Begin Result := #255; @@ -1270,7 +1338,6 @@ Begin Repeat If LastSecond <> TimerSeconds Then Begin - LastSecond := TimerSeconds; If Assigned(GetKeyCallBack) Then @@ -1279,65 +1346,7 @@ Begin Exit; End; - If InMacro Then - If InMacroPos <= Length(InMacroStr) Then Begin - Result := InMacroStr[InMacroPos]; - Inc (InMacroPos); - Exit; - End Else - InMacro := False; - - If TBBSCore(Core).CheckTimeOut Then - If TimerSeconds - TBBSCore(Core).TimeOut >= Config.Inactivity Then Begin - TBBSCore(Core).SystemLog('Inactivity timeout'); - OutFullLn (TBBSCore(Core).GetPrompt(136)); - Halt(0); - End; - - If Session.AllowMessages And Not Session.InMessage Then Begin - Dec (Session.MessageCheck); - - If Session.MessageCheck = 0 Then Begin - CheckNodeMessages; - - Session.MessageCheck := mysMessageThreshold; - End; - End; - - TimeCount := TBBSCore(Core).TimeLeft; - - If TimeCount <> Session.LastTimeLeft Then Begin - Session.LastTimeLeft := TimeCount; - - {$IFNDEF UNIX} - UpdateStatusLine(StatusPtr, ''); - {$ENDIF} - - If TBBSCore(Core).TimerOn Then Begin - If TimeCount = 5 Then Begin - If Not TBBSCore(Core).TimeChecked Then Begin - TBBSCore(Core).TimeChecked := True; - OutFullLn (TBBSCore(Core).GetPrompt(134)); - End; - End Else - If TimeCount < 1 Then Begin - If Not TBBSCore(Core).TimeChecked Then Begin - TBBSCore(Core).TimeChecked := True; - OutFullLn (TBBSCore(Core).GetPrompt(135)); - TBBSCore(Core).SystemLog ('User ran out of time'); - Halt(0); - End; - End Else - TBBSCore(Core).TimeChecked := False; - End; - - If TBBSCore(Core).NextEvent.Active Then - If (TBBSCore(Core).MinutesUntilEvent(TBBSCore(Core).NextEvent.ExecTime) = TBBSCore(Core).NextEvent.Warning) And - (Not TBBSCore(Core).EventWarn) And (TBBSCore(Core).NextEvent.Forced) Then Begin - TBBSCore(Core).EventWarn := True; - OutFullLn (TBBSCore(Core).GetPrompt(133)); - End; - End; + If DoInputEvents(Result) Then Exit; End; Result := InKey(1000); diff --git a/mystic/bbs_menus.pas b/mystic/bbs_menus.pas index 0ee1fe0..9bacf38 100644 --- a/mystic/bbs_menus.pas +++ b/mystic/bbs_menus.pas @@ -237,7 +237,10 @@ Begin MenuName := CmdData; Result := True; End; - 'T' : Session.io.OutFull (CmdData); + 'T' : Begin + Session.io.OutFull (CmdData); + Session.io.BufFlush; + End; 'U' : ShowUserList (strUpper(CmdData)); 'X' : Result := ExecuteMPL(NIL, CmdData) = 2; '?' : Begin @@ -625,9 +628,10 @@ End; Function TMenuEngine.MenuGetKey : Char; Var - Current : LongInt; LastSec : LongInt; Begin + Session.io.BufFlush; + LastSec := TimerSeconds; While Not TBBSCore(Owner).ShutDown Do Begin @@ -635,24 +639,28 @@ Begin If TBBSCore(Owner).ShutDown Then Exit; - If UseTimer And (TimerSeconds <> LastSec) Then Begin + If TimerSeconds <> LastSec Then Begin LastSec := TimerSeconds; - Inc (TimerCount); + If Session.io.DoInputEvents(Result) Then Exit; - Case ExecuteByHotkey('TIMER', TimerCount) of - 1 : If ReDraw Then Begin - Result := #02; - Exit; - End; - 2 : Begin - TimerReload := True; - Result := #02; - Exit; - End; + If UseTimer Then Begin + Inc (TimerCount); + + Case ExecuteByHotkey('TIMER', TimerCount) of + 1 : If ReDraw Then Begin + Result := #02; + Exit; + End; + 2 : Begin + TimerReload := True; + Result := #02; + Exit; + End; + End; + + If TimerCount = 1000000000 Then TimerCount := 0; End; - - If TimerCount = 1000000000 Then TimerCount := 0; End; If Result <> #255 Then Break;