1:   // MiscKeys.cs 
2:   // Copyright (C) 2000 Mike Krueger
3:   //
4:   // with contributions from :
5:   //      Andrea Paatz
6:   //      Jeppe Cramon
7:   //
8:   // This program is free software; you can redistribute it and/or modify
9:   // it under the terms of the GNU General Public License as published by
10:   // the Free Software Foundation; either version 2 of the License, or
11:   // (at your option) any later version.
12:   //
13:   // This program is distributed in the hope that it will be useful,
14:   // but WITHOUT ANY WARRANTY; without even the implied warranty of
15:   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16:   // GNU General Public License for more details.
17:   //
18:   // You should have received a copy of the GNU General Public License
19:   // along with this program; if not, write to the Free Software
20:   // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21:  
22:   using System.Drawing;
23:   using System.Windows.Forms;
24:   using System;
25:  
26:   using Core.Properties;
27:   using SharpDevelop.Gui;
28:   using SharpDevelop.DefaultEditor.Gui.Editor;
29:   using SharpDevelop.DefaultEditor.Text;
30:  
31:   namespace SharpDevelop.DefaultEditor.Actions {
32:  
33:       public class Tab : AbstractEditAction
34:       {
35:           void InsertTabs(IDocument documentITextSelection selectionint y1int y2)
36:           {
37:               int  redocounter 0;
38:               for (int y2>= y1; --i) {
39:                   LineSegment line document.GetLineSegment(i);
40:                   if (== y2 && line.Offset == selection.Offset selection.Length) {
41:                       continue;
42:                   }
43:                   
44:                   document.Insert(line.Offset"\t");
45:                   ++redocounter;
46:               }
47:               
48:               if (redocounter 0) {
49:                   document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
50:               }
51:           }
52:           
53:           public override void Execute(IEditActionServices services)
54:           {
55:               if (services.HasSomethingSelected) {
56:                   foreach (ITextSelection selection in services.Document.TextSelectionCollection) {
57:                       int startLine selection.StartLine;
58:                       int endLine   selection.EndLine;
59:                       services.BeginUpdate();
60:                       InsertTabs(services.DocumentselectionstartLineendLine);
61:                       services.EndUpdate();
62:                       services.UpdateLines(startLineendLine);
63:                   }
64:                   services.AutoClearSelection false;
65:               else {
66:                   services.BeginUpdate();
67:                   services.Document.Insert(services.Document.Caret.Offset"\t");
68:                   ++services.Document.Caret.Offset;
69:                   services.Document.SetDesiredColumn();
70:                   services.EndUpdate();
71:                   
72:                   int curLineNr services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
73:                   services.UpdateLineToEnd(curLineNrservices.Document.Caret.Offset services.Document.GetLineOffset(curLineNr));
74:               }
75:           }
76:       }
77:       
78:       public class ShiftTab : AbstractEditAction
79:       {
80:           void RemoveTabs(IDocument documentITextSelection selectionint y1int y2
81:           {
82:               int  redocounter 0;
83:               for (int y2>= y1; --i) {
84:                   LineSegment line document.GetLineSegment(i);
85:                   if (== y2 && line.Offset == selection.Offset selection.Length) {
86:                       continue;
87:                   }
88:                   if (line.Length && document.GetCharAt(line.Offset) == '\t') {
89:                       document.Remove(line.Offset1);
90:                       ++redocounter;
91:                   }
92:               }
93:               
94:               if (redocounter 0) {
95:                   document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
96:               }
97:           }
98:           
99:           public override void Execute(IEditActionServices services)
100:           {
101:               if (services.HasSomethingSelected) {
102:                   foreach (ITextSelection selection in services.Document.TextSelectionCollection) {
103:                       int startLine selection.StartLine;
104:                       int endLine   selection.EndLine;
105:                       services.BeginUpdate();
106:                       RemoveTabs(services.DocumentselectionstartLineendLine);
107:                       services.EndUpdate();
108:                       services.UpdateLines(startLineendLine);
109:                   }
110:                   services.AutoClearSelection false;
111:               else {
112:                   services.Document.Caret.Offset -= services.Document.Properties.GetProperty("TabIndent"4);
113:                   services.Document.SetDesiredColumn();
114:               }
115:           }
116:       }
117:       
118:       public class ToggleComment : AbstractEditAction
119:       {
120:           int firstLine;
121:           int lastLine;
122:           
123:           void InsertComment(IDocument documentITextSelection selectionint y1int y2)
124:           {
125:               int  redocounter 0;
126:               int  addCounter    0;
127:               int  removeCounter 0;
128:               firstLine y1;
129:               lastLine  y2;
130:               
131:               for (int y2>= y1; --i) {
132:                   LineSegment line document.GetLineSegment(i);
133:                   if (selection != null && i == y2 && line.Offset == selection.Offset selection.Length) {
134:                       --lastLine;
135:                       continue;
136:                   }
137:                   
138:                   string lineText document.GetText(line.Offsetline.Length);
139:                   if (lineText.Trim().StartsWith("//")) {
140:                       document.Remove(line.Offset lineText.IndexOf("//"), 2);
141:                       ++removeCounter;
142:                   else {
143:                       document.Insert(line.Offset"//");
144:                       ++addCounter;
145:                   }
146:                   ++redocounter;
147:               }
148:               
149:               if (redocounter 0) {
150:                   document.UndoStack.UndoLast(redocounter); // redo the whole operation (not the single deletes)
151:               }
152:           }
153:           
154:           public override void Execute(IEditActionServices services)
155:           {
156:               if (services.HasSomethingSelected) {
157:                   foreach (ITextSelection selection in services.Document.TextSelectionCollection) {
158:                       services.BeginUpdate();
159:                       InsertComment(services.Documentselectionselection.StartLineselection.EndLine);
160:                       services.EndUpdate();
161:                       services.UpdateLines(firstLinelastLine);
162:                   }
163:                   services.AutoClearSelection false;
164:               else {
165:                   int caretLine services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
166:                   InsertComment(services.DocumentnullcaretLinecaretLine);
167:               }
168:           }
169:       }
170:       
171:       
172:   /*    
173:       public class ReloadBuffer : AbstractEditAction
174:       {
175:           public override void Execute(IEditActionServices services)
176:           {
177:               services.TextArea.ReloadFile();
178:               services.TextArea.Refresh();
179:           }
180:       }
181:           
182:       public class IndentSelection : AbstractEditAction
183:       {
184:           public override void Execute(IEditActionServices services)
185:           {
186:               if (services.TextArea.Buffer.ReadOnly) 
187:                   return;
188:               if (services.TextArea.Selection.HasSomethingSelected) {
189:                   int y1 = services.TextArea.Selection.RealStart.Y;
190:                   int y2 = services.TextArea.Selection.RealEnd.Y;
191:                   Indent.IndentLines(services.TextArea.Buffer, y1, y2, services.TextArea.Options.IndentStyle);
192:                   services.TextArea.Refresh(); // TODO : LineUpdate
193:               }
194:           }
195:       }
196:       
197:       public class TextAreaOptions : AbstractEditAction
198:       {
199:           public override void Execute(IEditActionServices services)
200:           {
201:               new SharpDevelop.Gui.Dialogs.OptionsDialog("Buffer Options", services.TextArea.Options).ShowDialog();
202:               services.TextArea.Refresh();
203:           }
204:       }
205:                   
206:       public class Fold : AbstractEditAction
207:       {
208:           
209:           
210:           public override void Execute(IEditActionServices services)
211:           {
212:               services.TextArea.Buffer.Foldings.FoldPos(services.TextArea.Caret.CaretPos);
213:               services.TextArea.Refresh();
214:           }
215:       }
216:       
217:       public class UnFold : AbstractEditAction
218:       {
219:           public override void Execute(IEditActionServices services)
220:           {
221:               services.TextArea.Buffer.Foldings.UnFold(services.TextArea.Caret.CaretPos.Y + 1);
222:               services.TextArea.Refresh();
223:           }
224:       }
225:       */
226:       
227:       public class Backspace : AbstractEditAction
228:       {
229:           public override void Execute(IEditActionServices services)
230:           {
231:               if (services.HasSomethingSelected) {
232:                   services.RemoveSelectedText();
233:                   services.ScrollToCaret();
234:               else {
235:                   if (services.Document.Caret.Offset 0) {
236:                       services.BeginUpdate();
237:                       int curLineNr     services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
238:                       int curLineOffset services.Document.GetLineOffset(curLineNr);
239:                       
240:                       if (curLineOffset == services.Document.Caret.Offset) {
241:                           LineSegment line services.Document.GetLineSegment(curLineNr 1);
242:                           
243:                           bool lastLine curLineNr == services.Document.TotalNumberOfLines;
244:                           int lineEndOffset line.Offset line.Length;
245:                           services.Document.Remove(lineEndOffsetcurLineOffset lineEndOffset);
246:                           services.Document.Caret.Offset lineEndOffset;                    
247:                           services.EndUpdate();
248:                           services.UpdateToEnd(curLineNr 1);
249:                       else {
250:                           --services.Document.Caret.Offset;
251:                           services.Document.Remove(services.Document.Caret.Offset1);
252:                           services.EndUpdate();
253:                           services.UpdateLineToEnd(curLineNrservices.Document.Caret.Offset services.Document.GetLineOffset(curLineNr));
254:                       }
255:                   }
256:               }
257:           }
258:       }
259:       
260:       public class Delete : AbstractEditAction
261:       {
262:           public override void Execute(IEditActionServices services)
263:           {
264:               if (services.HasSomethingSelected) {
265:                   services.RemoveSelectedText();
266:                   services.ScrollToCaret();
267:               else {
268:               
269:                   if (services.Document.Caret.Offset services.Document.TextLength) {
270:                       services.BeginUpdate();
271:                       int curLineNr   services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
272:                       LineSegment curLine services.Document.GetLineSegment(curLineNr);
273:                       
274:                       if (curLine.Offset curLine.Length == services.Document.Caret.Offset) {
275:                           if (curLineNr services.Document.TotalNumberOfLines) {
276:                               LineSegment nextLine services.Document.GetLineSegment(curLineNr 1);
277:                               
278:                               services.Document.Remove(services.Document.Caret.OffsetnextLine.Offset services.Document.Caret.Offset);
279:                               services.EndUpdate();
280:                               services.UpdateToEnd(curLineNr);
281:                           }
282:                       else {
283:                           services.Document.Remove(services.Document.Caret.Offset1);
284:                           services.EndUpdate();
285:                           services.UpdateLineToEnd(curLineNrservices.Document.Caret.Offset services.Document.GetLineOffset(curLineNr));
286:                       }
287:                   }
288:               }
289:           }
290:       }
291:       
292:       public class MovePageDown : AbstractEditAction
293:       {
294:           public override void Execute(IEditActionServices services)
295:           {
296:               int curLineNr     services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
297:               int requestedLineNumber Math.Min(curLineNr services.MaxVisibleLineservices.Document.TotalNumberOfLines 1);
298:               
299:               if (curLineNr != requestedLineNumber) {
300:                   LineSegment line services.Document.GetLineSegment(requestedLineNumber);
301:                   services.Document.Caret.Offset line.Offset Math.Min(line.Lengthservices.Document.Caret.DesiredColumn);
302:               }
303:           }
304:       }
305:       
306:       public class MovePageUp : AbstractEditAction
307:       {
308:           public override void Execute(IEditActionServices services)
309:           {
310:               int curLineNr     services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
311:               int requestedLineNumber Math.Max(curLineNr services.MaxVisibleLine0);
312:               
313:               if (curLineNr != requestedLineNumber) {
314:                   LineSegment line services.Document.GetLineSegment(requestedLineNumber);
315:                   services.Document.Caret.Offset line.Offset Math.Min(line.Lengthservices.Document.Caret.DesiredColumn);
316:               }
317:           }
318:       }
319:       
320:       public class Return : AbstractEditAction
321:       {    
322:           public override void Execute(IEditActionServices services)
323:           {
324:               services.BeginUpdate();
325:               int curLineNr     services.Document.GetLineNumberOfOffset(services.Document.Caret.Offset);
326:               services.Document.Insert(services.Document.Caret.Offset"\n");
327:               ++services.Document.Caret.Offset;
328:               services.Document.Caret.Offset += services.Document.FormatingStrategy.FormatLine(curLineNr 1services.Document.Caret.Offset);
329:               services.Document.SetDesiredColumn();
330:               
331:               services.EndUpdate();
332:               services.UpdateToEnd(curLineNr 1);
333:           }
334:       }
335:       
336:       public class ToggleEditMode : AbstractEditAction
337:       {
338:           public override void Execute(IEditActionServices services)
339:           {
340:               services.Document.Caret.InsertMode = !services.Document.Caret.InsertMode;
341:           }
342:       }
343:       
344:       public class Undo : AbstractEditAction
345:       {
346:           public override void Execute(IEditActionServices services)
347:           {
348:               if (services.Document.UndoStack.CanUndo) {
349:                   
350:             &n