OSDN Git Service

a627d877d335664dafc8a8a9b07ce7bb611e03e7
[radegast/radegast.git] / Radegast / GUI / Consoles / Assets / ScriptEditor.cs
1 // 
2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, Radegast Development Team
4 // All rights reserved.
5 // 
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 
9 //     * Redistributions of source code must retain the above copyright notice,
10 //       this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //     * Neither the name of the application "Radegast", nor the names of its
15 //       contributors may be used to endorse or promote products derived from
16 //       this software without specific prior written permission.
17 // 
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // $Id$
30 //
31 using System;
32 using System.Collections.Generic;
33 using System.Drawing;
34 using System.Text.RegularExpressions;
35 using System.IO;
36 using System.Windows.Forms;
37 using OpenMetaverse;
38 using OpenMetaverse.Assets;
39
40 namespace Radegast
41 {
42
43     public partial class ScriptEditor : UserControl
44     {
45         private RadegastInstance instance;
46         private GridClient client { get { return instance.Client; } }
47         private InventoryLSL script;
48         private string scriptName;
49         private string fileName;
50         private Primitive prim;
51
52         public ScriptEditor(RadegastInstance instance)
53             : this(instance, null, null)
54         {
55             scriptName = "New Script";
56         }
57
58         public ScriptEditor(RadegastInstance instance, InventoryLSL script)
59             : this(instance, script, null)
60         {
61         }
62
63         public ScriptEditor(RadegastInstance instance, InventoryLSL script, Primitive prim)
64         {
65             InitializeComponent();
66             Disposed += new EventHandler(SscriptEditor_Disposed);
67
68             this.instance = instance;
69             this.script = script;
70             this.prim = prim;
71             rtb.SyntaxHighlightEnabled = instance.GlobalSettings["script_syntax_highlight"].AsBoolean();
72             lblScripStatus.Text = string.Empty;
73             lblScripStatus.TextChanged += (object sender, EventArgs e) =>
74                 instance.TabConsole.DisplayNotificationInChat(lblScripStatus.Text, ChatBufferTextStyle.Invisible);
75             Dock = DockStyle.Fill;
76             this.TabStop = false;
77
78             if (prim == null)
79             {
80                 cbRunning.Visible = false;
81             }
82
83             // Download script
84             if (script != null)
85             {
86                 scriptName = script.Name;
87                 if (prim != null)
88                 {
89                     client.Assets.RequestInventoryAsset(script.AssetUUID, script.UUID, prim.ID, prim.OwnerID, script.AssetType, true, Assets_OnAssetReceived);
90                     client.Inventory.RequestGetScriptRunning(prim.ID, script.UUID);
91                     client.Inventory.ScriptRunningReply += OnScriptRunningReplyReceived;
92                 }
93                 else
94                 {
95                     client.Assets.RequestInventoryAsset(script, true, Assets_OnAssetReceived);
96                 }
97                 rtb.Text = lblScripStatus.Text = "Loading script...";
98             }
99             else
100             {
101                 rtb.Text = " "; //bugs in control grrrr
102                 rtb.SelectionStart = 0;
103             }
104         }
105
106         void SscriptEditor_Disposed(object sender, EventArgs e)
107         {
108             client.Inventory.ScriptRunningReply -= OnScriptRunningReplyReceived;
109         }
110
111         void OnScriptRunningReplyReceived(object sender, ScriptRunningReplyEventArgs e)
112         {
113             if (InvokeRequired)
114             {
115                 if (!instance.MonoRuntime || IsHandleCreated)
116                     BeginInvoke(new MethodInvoker(() => OnScriptRunningReplyReceived(sender, e)));
117                 return;
118             }
119
120             cbRunning.Checked = e.IsRunning;
121             cbMono.Checked = e.IsMono;
122         }
123
124         void Assets_OnAssetReceived(AssetDownload transfer, Asset asset)
125         {
126             if (InvokeRequired)
127             {
128                 if (!instance.MonoRuntime || IsHandleCreated)
129                     BeginInvoke(new MethodInvoker(() => Assets_OnAssetReceived(transfer, asset)));
130                 return;
131             }
132
133             if (!transfer.Success || asset.AssetType != AssetType.LSLText)
134             {
135                 lblScripStatus.Text = rtb.Text = "Failed to download.";
136                 return;
137             }
138             else
139                 lblScripStatus.Text = rtb.Text = "OK";
140
141             asset.Decode();
142             rtb.Text = ((AssetScriptText)asset).Source;
143             lineNubersForRtb.Invalidate();
144             SetTitle();
145         }
146
147         private void SetTitle()
148         {
149             if (detached)
150             {
151                 FindForm().Text = scriptName + " - " + Properties.Resources.ProgramName + " script editor";
152             }
153         }
154
155         #region Detach/Attach
156         private Control originalParent;
157         private Form detachedForm;
158         private bool detached = false;
159
160         public bool Detached
161         {
162             get
163             {
164                 return detached;
165             }
166
167             set
168             {
169                 if (detached == value) return; // no change
170
171                 detached = value;
172
173                 if (detached)
174                 {
175                     Detach();
176                 }
177                 else
178                 {
179                     Retach();
180                 }
181             }
182         }
183
184         public void ShowDetached()
185         {
186             Detached = true;
187         }
188
189         private void Detach()
190         {
191             detached = true;
192
193             if (detachedForm != null)
194             {
195                 detachedForm.Dispose();
196             }
197
198             detachedForm = new Form();
199             originalParent = Parent;
200             Parent = detachedForm;
201             detachedForm.ClientSize = new Size(873, 580);
202             SetTitle();
203             detachedForm.ActiveControl = this;
204             detachedForm.Show();
205             detachedForm.FormClosing += new FormClosingEventHandler(detachedForm_FormClosing);
206
207             if (originalParent != null)
208             {
209                 originalParent.ControlAdded += new ControlEventHandler(originalParent_ControlAdded);
210             }
211             else
212             {
213                 tbtnAttach.Visible = false;
214             }
215
216             tbtnAttach.Text = "Retach";
217
218             if (originalParent == null)
219             {
220                 tSeparator1.Visible = true;
221                 tbtnExit.Visible = true;
222             }
223             else
224             {
225                 tSeparator1.Visible = false;
226                 tbtnExit.Visible = false;
227             }
228         }
229
230         void originalParent_ControlAdded(object sender, ControlEventArgs e)
231         {
232             if (detachedForm != null)
233             {
234                 detachedForm.FormClosing -= new FormClosingEventHandler(detachedForm_FormClosing);
235             }
236             originalParent.ControlAdded -= new ControlEventHandler(originalParent_ControlAdded);
237             tbtnAttach.Visible = false;
238         }
239
240         void detachedForm_FormClosing(object sender, FormClosingEventArgs e)
241         {
242             Retach();
243         }
244
245         private void Retach()
246         {
247             detached = false;
248
249             if (originalParent != null)
250             {
251                 originalParent.ControlAdded -= new ControlEventHandler(originalParent_ControlAdded);
252                 Parent = originalParent;
253             }
254
255             if (detachedForm != null)
256             {
257                 detachedForm.Dispose();
258                 detachedForm = null;
259             }
260
261             tbtnAttach.Text = "Detach";
262
263             if (originalParent == null)
264             {
265                 Dispose();
266             }
267         }
268
269         private void tbtnAttach_Click(object sender, EventArgs e)
270         {
271             if (detached)
272             {
273                 Retach();
274             }
275             else
276             {
277                 Detach();
278             }
279         }
280         #endregion
281
282
283         #region File I/O
284         private void tbtbSaveToDisk_Click_1(object sender, EventArgs e)
285         {
286             if (string.IsNullOrEmpty(fileName))
287             {
288                 tbtbSaveToDisk_Click(sender, e);
289                 return;
290             }
291             File.WriteAllText(fileName, rtb.Text);
292         }
293
294         private void tbtbSaveToDisk_Click(object sender, EventArgs e)
295         {
296             SaveFileDialog dlg = new SaveFileDialog();
297             dlg.Title = "Save script";
298             dlg.Filter = "LSL script file (*.lsl)|*.lsl|Plain text file (*.txt)|*.txt";
299             dlg.FileName = RadegastMisc.SafeFileName(scriptName);
300             DialogResult res = dlg.ShowDialog();
301
302             if (res == DialogResult.OK)
303             {
304                 fileName = dlg.FileName;
305                 scriptName = Path.GetFileName(fileName);
306                 SetTitle();
307                 File.WriteAllText(fileName, rtb.Text);
308             }
309
310         }
311
312         private void tbtbLoadFromDisk_Click(object sender, EventArgs e)
313         {
314             OpenFileDialog dlg = new OpenFileDialog();
315             dlg.Title = "Open script";
316             dlg.Filter = "LSL script files (*.lsl)|*.lsl|Plain text files (*.txt)|*.txt|All files (*.*)|*.*";
317             dlg.Multiselect = false;
318             DialogResult res = dlg.ShowDialog();
319
320             if (res == DialogResult.OK)
321             {
322                 fileName = dlg.FileName;
323                 scriptName = Path.GetFileName(fileName);
324                 SetTitle();
325                 rtb.Text = File.ReadAllText(fileName);
326                 lineNubersForRtb.Invalidate();
327             }
328         }
329         #endregion
330
331         private void tbtnExit_Click(object sender, EventArgs e)
332         {
333             FindForm().Close();
334         }
335
336         private void rtb_SelectionChanged(object sender, EventArgs e)
337         {
338             RRichTextBox.CursorLocation c = rtb.CursorPosition;
339             lblLine.Text = string.Format("Ln {0}", c.Line + 1);
340             lblCol.Text = string.Format("Col {0}", c.Column + 1);
341         }
342
343         private bool spaceOrTab(char c)
344         {
345             return c == ' ' || c == '\t';
346         }
347
348         private int lastPos(string s, char c)
349         {
350             s = s.TrimEnd();
351
352             if (s == string.Empty)
353                 return -1;
354
355             if (s[s.Length - 1] == c)
356             {
357                 return s.LastIndexOf(c);
358             }
359             return -1;
360         }
361
362         //private RRichTextBox.CursorLocation prevCursor;
363
364         private void rtb_KeyDown(object sender, KeyEventArgs e)
365         {
366             if (e.KeyCode == Keys.S && e.Control && !e.Shift)
367             {
368                 tbtbSave_Click(this, EventArgs.Empty);
369                 e.Handled = e.SuppressKeyPress = true;
370                 return;
371             }
372
373             if (e.KeyCode == Keys.L && e.Control && !e.Shift)
374             {
375                 ReadCursorPosition();
376                 e.Handled = e.SuppressKeyPress = true;
377                 return;
378             }
379
380             if (e.Modifiers == Keys.Control && e.KeyCode == Keys.F)
381             {
382                 findToolStripMenuItem_Click(null, null);
383             }
384             if (e.KeyCode == Keys.Tab)
385             {
386                 rtb.SelectedText = "    ";
387                 e.Handled = true;
388             }
389             /*
390             else if (e.KeyCode == Keys.Enter)
391             {
392                 e.Handled = true;
393                 e.SuppressKeyPress = true;
394
395                 // RRichTextBox.CursorLocation cl = prevCursor;
396                 RRichTextBox.CursorLocation cl = rtb.CursorPosition;
397                 string prevLine = rtb.Lines[cl.Line];
398                 string addIndent = "\n";
399                 int pos;
400
401                 for (int spaces = 0;
402                     spaces < prevLine.Length && spaceOrTab(prevLine[spaces]);
403                     addIndent += prevLine[spaces++]) ;
404
405                 System.Console.WriteLine("In identer");
406                 if ((pos = lastPos(prevLine.Substring(0, cl.Column), '{')) != -1)
407                 {
408                     addIndent += "    ";
409                 }
410
411                 rtb.SelectedText = addIndent;
412                 int eat = 0;
413                 for (eat = 0; (eat + rtb.SelectionStart) < rtb.Text.Length && rtb.Text[rtb.SelectionStart + eat] == ' '; eat++) ;
414                 rtb.SelectionLength = eat;
415                 rtb.SelectedText = "";
416             }
417             */
418
419         }
420
421
422         private void rtb_KeyPress(object sender, KeyPressEventArgs e)
423         {/*
424             if (rtb.Lines.Length > 0)
425             {
426                 if (e.KeyChar == '}')
427                 {
428                     string li = rtb.Lines[rtb.GetLineFromCharIndex(rtb.SelectionStart)];
429
430                     if (li.Trim() == "")
431                     {
432                         rtb.BeginUpdate();
433                         int toDelete = li.Length;
434
435                         if (toDelete > 4)
436                         {
437                             toDelete = 4;
438                         }
439
440                         rtb.SelectionStart -= toDelete;
441                         rtb.SelectionLength = toDelete;
442                         rtb.SelectedText = "";
443                         rtb.EndUpdate();
444                     }
445                 }
446             }
447           */
448         }
449
450         #region Edit menu handlers
451         private void undoToolStripMenuItem_Click(object sender, EventArgs e)
452         {
453             rtb.Undo();
454         }
455
456         private void redoToolStripMenuItem_Click(object sender, EventArgs e)
457         {
458             rtb.Redo();
459         }
460
461         private void cutToolStripMenuItem_Click(object sender, EventArgs e)
462         {
463             rtb.Cut();
464         }
465
466         private void copyToolStripMenuItem_Click(object sender, EventArgs e)
467         {
468             rtb.Copy();
469         }
470
471         private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
472         {
473             rtb.Paste();
474         }
475
476         private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
477         {
478             rtb.SelectedText = string.Empty;
479         }
480
481         private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
482         {
483             rtb.SelectionStart = 0;
484             rtb.SelectionLength = rtb.Text.Length;
485         }
486
487         private void findToolStripMenuItem_Click(object sender, EventArgs e)
488         {
489             tsFindReplace.Show();
490             tfindFindText.Focus();
491         }
492         #endregion
493
494         private void tfindClose_Click(object sender, EventArgs e)
495         {
496             tsFindReplace.Hide();
497         }
498
499         private class FindHistoryItem
500         {
501             public FindHistoryItem(string term, int ss, int sl)
502             {
503                 Term = term;
504                 SelStart = ss;
505                 SelLength = sl;
506             }
507
508             public string Term;
509             public int SelStart;
510             public int SelLength;
511
512             public override string ToString()
513             {
514                 return Term;
515             }
516         }
517
518         Dictionary<string, FindHistoryItem> FindHistory = new Dictionary<string, FindHistoryItem>();
519         FindHistoryItem startPos;
520         int searchFrom = 0;
521
522         private void tfindFindText_TextChanged(object sender, EventArgs e)
523         {
524             string st = tfindFindText.Text;
525
526             if (startPos == null)
527             {
528                 startPos = new FindHistoryItem(string.Empty, rtb.SelectionStart, rtb.SelectionLength);
529                 FindHistory[startPos.Term] = startPos;
530             }
531
532             StringComparison type;
533
534             if (tfindMatchCase.Checked)
535             {
536                 type = StringComparison.Ordinal;
537             }
538             else
539             {
540                 type = StringComparison.OrdinalIgnoreCase;
541             }
542
543             if (FindHistory.ContainsKey(st))
544             {
545                 tfindFindText.BackColor = Color.FromKnownColor(KnownColor.Window);
546                 FindHistoryItem h = FindHistory[st];
547                 rtb.BeginUpdate();
548                 rtb.Select(h.SelStart, h.SelLength);
549                 rtb.ScrollToCaret();
550                 rtb.EndUpdate();
551                 searchFrom = h.SelStart;
552
553                 if (st == string.Empty)
554                 {
555                     FindHistory.Clear();
556                     tfindFindText.BackColor = Color.FromKnownColor(KnownColor.Window);
557                 }
558
559                 return;
560             }
561
562             if (st == string.Empty)
563             {
564                 FindHistory.Clear();
565                 tfindFindText.BackColor = Color.FromKnownColor(KnownColor.Window);
566                 return;
567             }
568
569             int pos = rtb.Text.IndexOf(st, searchFrom, type);
570
571             if (pos != -1)
572             {
573                 tfindFindText.BackColor = Color.FromKnownColor(KnownColor.Window);
574                 FindHistory[st] = new FindHistoryItem(st, pos, st.Length);
575                 rtb.BeginUpdate();
576                 rtb.Select(pos, st.Length);
577                 rtb.ScrollToCaret();
578                 rtb.EndUpdate();
579                 searchFrom = pos;
580             }
581             else
582             {
583                 searchFrom = 0;
584                 tfindFindText.BackColor = Color.FromArgb(200, 0, 0);
585             }
586         }
587
588         private void tfindFindText_KeyDown(object sender, KeyEventArgs e)
589         {
590             if (e.KeyCode == Keys.Enter)
591             {
592                 e.SuppressKeyPress = true;
593             }
594         }
595
596         private void tfindFindText_KeyUp(object sender, KeyEventArgs e)
597         {
598             switch (e.KeyCode)
599             {
600                 case Keys.Enter:
601                     tfindDoFind_Click(null, null);
602                     e.Handled = true;
603                     e.SuppressKeyPress = true;
604                     break;
605             }
606         }
607
608         private void tfindDoFind_Click(object sender, EventArgs e)
609         {
610             FindHistory.Clear();
611             searchFrom += rtb.SelectionLength;
612             tfindFindText_TextChanged(sender, e);
613         }
614
615         private void tfindFindText_Leave(object sender, EventArgs e)
616         {
617             startPos = null;
618             FindHistory.Clear();
619         }
620
621         private void tfindFindText_Enter(object sender, EventArgs e)
622         {
623             searchFrom = rtb.SelectionStart;
624         }
625
626
627         private void tfindFindNextReplace_Click(object sender, EventArgs e)
628         {
629             tfindDoFind_Click(null, null);
630         }
631
632         private void tfindReplace_Click(object sender, EventArgs e)
633         {
634             if (tfindFindText.Text.Length > 0 && rtb.SelectionLength > 0)
635             {
636                 rtb.SelectedText = tfindReplaceText.Text;
637                 tfindDoFind_Click(null, null);
638             }
639         }
640
641         private static string ReplaceEx(string original, string pattern, string replacement)
642         {
643             int count, position0, position1;
644             count = position0 = position1 = 0;
645             string upperString = original.ToUpper();
646             string upperPattern = pattern.ToUpper();
647             int inc = (original.Length / pattern.Length) * (replacement.Length - pattern.Length);
648             char[] chars = new char[original.Length + Math.Max(0, inc)];
649             while ((position1 = upperString.IndexOf(upperPattern, position0)) != -1)
650             {
651                 for (int i = position0; i < position1; ++i)
652                     chars[count++] = original[i];
653                 for (int i = 0; i < replacement.Length; ++i)
654                     chars[count++] = replacement[i];
655                 position0 = position1 + pattern.Length;
656             }
657             if (position0 == 0) return original;
658             for (int i = position0; i < original.Length; ++i)
659                 chars[count++] = original[i];
660             return new string(chars, 0, count);
661         }
662
663         private void tfindReplaceAll_Click(object sender, EventArgs e)
664         {
665             if (tfindFindText.Text.Length > 0)
666             {
667                 if (tfindMatchCase.Checked)
668                 {
669                     rtb.Text.Replace(tfindFindText.Text, tfindReplaceText.Text);
670                 }
671                 else
672                 {
673                     rtb.Text = ReplaceEx(rtb.Text, tfindFindText.Text, tfindReplaceText.Text);
674                 }
675             }
676         }
677
678         private void syntaxHiglightingToolStripMenuItem_Click(object sender, EventArgs e)
679         {
680             if (rtb.SyntaxHighlightEnabled == true)
681             {
682                 rtb.SyntaxHighlightEnabled = false;
683             }
684             else
685             {
686                 rtb.SyntaxHighlightEnabled = true;
687             }
688             syntaxHiglightingToolStripMenuItem.Checked = rtb.SyntaxHighlightEnabled;
689         }
690
691         private void ReadCursorPosition()
692         {
693             instance.TabConsole.DisplayNotificationInChat(
694                 string.Format("Cursor at line {0}, column {1}", rtb.CursorPosition.Line + 1, rtb.CursorPosition.Column + 1),
695                 ChatBufferTextStyle.Invisible);
696         }
697
698         private void tbtbSave_Click(object sender, EventArgs e)
699         {
700             InventoryManager.ScriptUpdatedCallback handler = (bool uploadSuccess, string uploadStatus, bool compileSuccess, List<string> compileMessages, UUID itemID, UUID assetID) =>
701             {
702                 if (!IsHandleCreated && instance.MonoRuntime) return;
703
704                 BeginInvoke(new MethodInvoker(() =>
705                 {
706                     if (uploadSuccess && compileSuccess)
707                     {
708                         lblScripStatus.Text = "Saved OK";
709                     }
710                     else
711                     {
712                         if (!compileSuccess)
713                         {
714                             lblScripStatus.Text = "Compilation failed";
715                             if (compileMessages != null)
716                             {
717                                 txtStatus.Show();
718                                 txtStatus.Text = string.Empty;
719                                 for (int i = 0; i < compileMessages.Count; i++)
720                                 {
721                                     Match m = Regex.Match(compileMessages[i], @"\((?<line>\d+),\s*(?<column>\d+)\s*\)\s*:\s*(?<kind>\w+)\s*:\s*(?<msg>.*)", RegexOptions.IgnoreCase);
722
723                                     if (m.Success)
724                                     {
725                                         int line = 1 + int.Parse(m.Groups["line"].Value, Utils.EnUsCulture);
726                                         int column = 1 + int.Parse(m.Groups["column"].Value, Utils.EnUsCulture);
727                                         string kind = m.Groups["kind"].Value;
728                                         string msg = m.Groups["msg"].Value;
729                                         instance.TabConsole.DisplayNotificationInChat(
730                                             string.Format("{0} on line {1}, column {2}: {3}", kind, line, column, msg),
731                                             ChatBufferTextStyle.Invisible);
732                                         txtStatus.Text += string.Format("{0} (Ln {1}, Col {2}): {3}", kind, line, column, msg);
733
734                                         if (i == 0)
735                                         {
736                                             rtb.CursorPosition = new RRichTextBox.CursorLocation(line - 1, column - 1);
737                                             ReadCursorPosition();
738                                             rtb.Focus();
739                                         }
740                                     }
741                                     else
742                                     {
743                                         txtStatus.Text += compileMessages[i] + Environment.NewLine;
744                                         instance.TabConsole.DisplayNotificationInChat(compileMessages[i]);
745                                     }
746                                 }
747                             }
748                         }
749                         else
750                         {
751                             lblScripStatus.Text = rtb.Text = "Failed to download.";
752                         }
753
754                     }
755                 }
756                 ));
757             };
758
759
760             lblScripStatus.Text = "Saving...";
761             txtStatus.Hide();
762             txtStatus.Text = string.Empty;
763
764             AssetScriptText n = new AssetScriptText();
765             n.Source = rtb.Text;
766             n.Encode();
767
768             if (prim != null)
769             {
770                 client.Inventory.RequestUpdateScriptTask(n.AssetData, script.UUID, prim.ID, cbMono.Checked, cbRunning.Checked, handler);
771             }
772             else
773             {
774                 client.Inventory.RequestUpdateScriptAgentInventory(n.AssetData, script.UUID, cbMono.Checked, handler);
775             }
776         }
777
778     }
779 }