working on script editor

This commit is contained in:
codeimp 2008-11-03 16:11:00 +00:00
parent 4a2bf61c1c
commit fe2fa46d9c
5 changed files with 163 additions and 33 deletions

View file

@ -56,7 +56,9 @@ namespace CodeImp.DoomBuilder.Config
// Collections
private Dictionary<string, string> keywords;
private Dictionary<string, string> lowerkeywords;
private List<string> constants;
private Dictionary<string, string> lowerconstants;
#endregion
@ -92,6 +94,8 @@ namespace CodeImp.DoomBuilder.Config
this.cfg = cfg;
this.keywords = new Dictionary<string,string>();
this.constants = new List<string>();
this.lowerkeywords = new Dictionary<string, string>();
this.lowerconstants = new Dictionary<string, string>();
// Read settings
compilername = cfg.ReadSetting("compiler", "");
@ -105,12 +109,18 @@ namespace CodeImp.DoomBuilder.Config
// Load keywords
dic = cfg.ReadSetting("keywords", new Hashtable());
foreach(DictionaryEntry de in dic)
{
keywords.Add(de.Key.ToString(), de.Value.ToString());
lowerkeywords.Add(de.Key.ToString().ToLowerInvariant(), de.Key.ToString());
}
// Load constants
dic = cfg.ReadSetting("constants", new Hashtable());
foreach(DictionaryEntry de in dic)
{
constants.Add(de.Key.ToString());
lowerconstants.Add(de.Key.ToString().ToLowerInvariant(), de.Key.ToString());
}
// Compiler specified?
if(compilername.Length > 0)
@ -136,6 +146,38 @@ namespace CodeImp.DoomBuilder.Config
#region ================== Methods
// This returns the correct case for a keyword
// Returns the same keyword as the input when it cannot be found
public string GetKeywordCase(string keyword)
{
if(lowerkeywords.ContainsKey(keyword.ToLowerInvariant()))
return lowerkeywords[keyword.ToLowerInvariant()];
else
return keyword;
}
// This returns the correct case for a constant
// Returns the same constant as the input when it cannot be found
public string GetConstantCase(string constant)
{
if(lowerconstants.ContainsKey(constant.ToLowerInvariant()))
return lowerconstants[constant.ToLowerInvariant()];
else
return constant;
}
// This returns true when the given word is a keyword
public bool IsKeyword(string keyword)
{
return lowerkeywords.ContainsKey(keyword.ToLowerInvariant());
}
// This returns true when the given word is a contant
public bool IsConstant(string constant)
{
return lowerconstants.ContainsKey(constant.ToLowerInvariant());
}
#endregion
}
}

View file

@ -47,6 +47,7 @@ namespace CodeImp.DoomBuilder.Controls
this.functionslist.Name = "functionslist";
this.functionslist.Size = new System.Drawing.Size(474, 21);
this.functionslist.TabIndex = 1;
this.functionslist.TabStop = false;
//
// scriptedit
//
@ -124,6 +125,7 @@ namespace CodeImp.DoomBuilder.Controls
this.scriptedit.WrapVisualFlagsLocation = 0;
this.scriptedit.XOffset = 0;
this.scriptedit.ZoomLevel = 0;
this.scriptedit.KeyDown += new System.Windows.Forms.KeyEventHandler(this.scriptedit_KeyDown);
//
// scriptpanel
//

View file

@ -30,6 +30,7 @@ using System.Reflection;
using CodeImp.DoomBuilder.IO;
using System.Collections;
using System.Globalization;
using CodeImp.DoomBuilder.Rendering;
#endregion
@ -53,7 +54,10 @@ namespace CodeImp.DoomBuilder.Controls
#endregion
#region ================== Variables
// List of keywords and constants, sorted as uppercase
private string autocompletestring;
#endregion
#region ================== Contructor / Disposer
@ -63,31 +67,43 @@ namespace CodeImp.DoomBuilder.Controls
{
// Initialize
InitializeComponent();
// Script editor properties
// Unfortunately, these cannot be set using the designer
// because the control is not really loaded in design mode
scriptedit.AutoCMaximumHeight = 8;
scriptedit.AutoCSeparator = ' ';
scriptedit.AutoCTypeSeparator = ',';
scriptedit.CaretWidth = 2;
scriptedit.EndAtLastLine = 1;
scriptedit.EndOfLineMode = ScriptEndOfLine.CRLF;
scriptedit.IsAutoCGetChooseSingle = true;
scriptedit.IsAutoCGetIgnoreCase = true;
scriptedit.IsBackSpaceUnIndents = true;
scriptedit.IsBufferedDraw = true;
scriptedit.SetFoldFlags((int)ScriptFoldFlag.Box);
scriptedit.IsUseTabs = true;
scriptedit.IsViewEOL = false;
scriptedit.IsVScrollBar = true;
scriptedit.IsHScrollBar = true;
scriptedit.IsCaretLineVisible = false;
scriptedit.IsHScrollBar = true;
scriptedit.IsIndentationGuides = true;
scriptedit.IsMouseDownCaptures = true;
scriptedit.IsTabIndents = true;
scriptedit.IsUndoCollection = true;
scriptedit.EndOfLineMode = ScriptEndOfLine.CRLF;
scriptedit.EndAtLastLine = 1;
scriptedit.SetMarginWidthN(0, 16);
scriptedit.IsUseTabs = true;
scriptedit.IsViewEOL = false;
scriptedit.IsVScrollBar = true;
scriptedit.SetFoldFlags((int)ScriptFoldFlag.Box);
scriptedit.SetMarginTypeN(0, (int)ScriptMarginType.Symbol);
scriptedit.SetMarginWidthN(1, 42);
scriptedit.SetMarginTypeN(1, (int)ScriptMarginType.Number);
scriptedit.CaretWidth = 2;
scriptedit.SetMarginTypeN(2, (int)ScriptMarginType.Symbol);
scriptedit.SetMarginWidthN(0, 16);
scriptedit.SetMarginWidthN(1, 40);
scriptedit.SetMarginWidthN(2, 5);
//scriptedit.AddIgnoredKey(Keys.ControlKey, Keys.None);
//scriptedit.AddIgnoredKey(Keys.Space, Keys.None);
//scriptedit.AddIgnoredKey(Keys.Space, Keys.Control);
}
#endregion
#region ================== Methods
// This sets up the script editor with a script configuration
@ -96,6 +112,7 @@ namespace CodeImp.DoomBuilder.Controls
Stream lexersdata;
StreamReader lexersreader;
Configuration lexercfg = new Configuration();
List<string> autocompletelist = new List<string>();
string[] resnames;
// Find a resource named Actions.cfg
@ -135,10 +152,20 @@ namespace CodeImp.DoomBuilder.Controls
scriptedit.CaretPeriod = SystemInformation.CaretBlinkTime;
scriptedit.CaretFore = General.Colors.ScriptBackground.Inverse().ToColorRef();
scriptedit.StyleBits = 7;
// This applies the default style to all styles
scriptedit.StyleClearAll();
// Set the default to something normal (this is used by the autocomplete list)
scriptedit.StyleSetFont(DEFAULT_STYLE, this.Font.Name);
scriptedit.StyleSetBold(DEFAULT_STYLE, this.Font.Bold);
scriptedit.StyleSetItalic(DEFAULT_STYLE, this.Font.Italic);
scriptedit.StyleSetUnderline(DEFAULT_STYLE, this.Font.Underline);
scriptedit.StyleSetSize(DEFAULT_STYLE, (int)Math.Round(this.Font.SizeInPoints));
// Set style for linenumbers and margins
scriptedit.StyleSetBack((int)ScriptStylesCommon.LineNumber, General.Colors.ScriptBackground.ToColorRef());
// Clear all keywords
for(int i = 0; i < 9; i++) scriptedit.KeyWords(i, null);
@ -166,6 +193,7 @@ namespace CodeImp.DoomBuilder.Controls
{
if(keywordslist.Length > 0) keywordslist.Append(" ");
keywordslist.Append(k);
autocompletelist.Add(k);
}
string words = keywordslist.ToString();
scriptedit.KeyWords(keywordsindex, words.ToLowerInvariant());
@ -180,16 +208,39 @@ namespace CodeImp.DoomBuilder.Controls
{
if(constantslist.Length > 0) constantslist.Append(" ");
constantslist.Append(c);
autocompletelist.Add(c);
}
string words = constantslist.ToString();
scriptedit.KeyWords(constantsindex, words.ToLowerInvariant());
}
// Sort the autocomplete list
autocompletelist.Sort(StringComparer.CurrentCultureIgnoreCase);
autocompletestring = string.Join(" ", autocompletelist.ToArray());
}
#endregion
#region ================== Events
// Key pressed down
private void scriptedit_KeyDown(object sender, KeyEventArgs e)
{
// CTRL+Space to autocomplete
if((e.KeyCode == Keys.Space) && (e.Modifiers == Keys.Control))
{
// Hide call tip if any
scriptedit.CallTipCancel();
// Show autocomplete
int currentpos = scriptedit.CurrentPos;
int wordstartpos = scriptedit.WordStartPosition(currentpos, true);
scriptedit.AutoCShow(currentpos - wordstartpos, autocompletestring);
e.Handled = true;
}
}
#endregion
}
}

View file

@ -56,6 +56,7 @@ namespace CodeImp.DoomBuilder.Controls
private const uint WS_TABSTOP = (uint)0x00010000L;
private const int WM_NOTIFY = 0x004E;
private const int WM_KEYDOWN = 0x0100;
private const int WM_KEYUP = 0x0101;
#endregion
@ -301,6 +302,38 @@ namespace CodeImp.DoomBuilder.Controls
}
}
/// <summary>
/// Width of the the auto-completion list
/// </summary>
public int AutoCMaximumWidth
{
get
{
return (int)FastPerform(2209, 0, 0);
}
set
{
FastPerform(2208, (uint)value, 0);
}
}
/// <summary>
/// Height of the the auto-completion list
/// </summary>
public int AutoCMaximumHeight
{
get
{
return (int)FastPerform(2211, 0, 0);
}
set
{
FastPerform(2210, (uint)value, 0);
}
}
/// <summary>
/// Returns the number of characters in the document.
///
@ -2194,7 +2227,7 @@ namespace CodeImp.DoomBuilder.Controls
#endregion
#region ================== Events
// When resized
protected override void OnResize(EventArgs e)
{
@ -2205,6 +2238,20 @@ namespace CodeImp.DoomBuilder.Controls
General.SetWindowPos(controlptr, 0, 0, 0, base.Width, base.Height, 0);
}
// When a windows message is pre-processed
public override bool PreProcessMessage(ref Message m)
{
switch(m.Msg)
{
case WM_KEYUP:
case WM_KEYDOWN:
// Why do I have to call this for my events work properly?
// I should be able to call base.PreProcessMessage, but that doesn't raise my events!
return base.ProcessKeyEventArgs(ref m);
}
return false;
}
#endregion
#region ================== Methods
@ -2241,7 +2288,7 @@ namespace CodeImp.DoomBuilder.Controls
this.ignoredkeys.Add(key, key);
}
private void AddIgnoredKey(System.Windows.Forms.Keys key, System.Windows.Forms.Keys modifier)
public void AddIgnoredKey(System.Windows.Forms.Keys key, System.Windows.Forms.Keys modifier)
{
this.ignoredkeys.Add((int)key + (int)modifier, (int)key + (int)modifier);
}
@ -2265,18 +2312,6 @@ namespace CodeImp.DoomBuilder.Controls
}
}
public override bool PreProcessMessage(ref Message m)
{
switch(m.Msg)
{
case WM_KEYDOWN:
if(ignoredkeys.ContainsKey((int)Control.ModifierKeys + (int)m.WParam))
return base.PreProcessMessage(ref m);
break;
}
return false;
}
/// <summary>
/// Convert all line endings in the document to one mode.
/// </summary>

View file

@ -417,10 +417,10 @@ namespace CodeImp.DoomBuilder
}
}
}
catch(Exception)
catch(Exception e)
{
// Unable to load configuration
ShowErrorMessage("Unable to load the script configuration file \"" + Path.GetFileName(filepath) + "\".", MessageBoxButtons.OK);
ShowErrorMessage("Unable to load the script configuration file \"" + Path.GetFileName(filepath) + "\". Error: " + e.Message, MessageBoxButtons.OK);
}
}
}