~ubuntu-branches/ubuntu/saucy/lazarus/saucy

« back to all changes in this revision

Viewing changes to ide/codemacroprompt.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Bart Martens, Paul Gevers
  • Date: 2013-06-08 14:12:17 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130608141217-7k0cy9id8ifcnutc
Tags: 1.0.8+dfsg-1
[ Abou Al Montacir ]
* New upstream major release and multiple maintenace release offering many
  fixes and new features marking a new milestone for the Lazarus development
  and its stability level.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_fixes_branch
* LCL changes:
  - LCL is now a normal package.
      + Platform independent parts of the LCL are now in the package LCLBase
      + LCL is automatically recompiled when switching the target platform,
        unless pre-compiled binaries for this target are already installed.
      + No impact on existing projects.
      + Linker options needed by LCL are no more added to projects that do
        not use the LCL package.
  - Minor changes in LCL basic classes behaviour
      + TCustomForm.Create raises an exception if a form resource is not
        found.
      + TNotebook and TPage: a new implementation of these classes was added.
      + TDBNavigator: It is now possible to have focusable buttons by setting
        Options = [navFocusableButtons] and TabStop = True, useful for
        accessibility and for devices with neither mouse nor touch screen.
      + Names of TControlBorderSpacing.GetSideSpace and GetSpace were swapped
        and are now consistent. GetSideSpace = Around + GetSpace.
      + TForm.WindowState=wsFullscreen was added
      + TCanvas.TextFitInfo was added to calculate how many characters will
        fit into a specified Width. Useful for word-wrapping calculations.
      + TControl.GetColorResolvingParent and
        TControl.GetRGBColorResolvingParent were added, simplifying the work
        to obtain the final color of the control while resolving clDefault
        and the ParentColor.
      + LCLIntf.GetTextExtentExPoint now has a good default implementation
        which works in any platform not providing a specific implementation.
        However, Widgetset specific implementation is better, when available.
      + TTabControl was reorganized. Now it has the correct class hierarchy
        and inherits from TCustomTabControl as it should.
  - New unit in the LCL:
      + lazdialogs.pas: adds non-native versions of various native dialogs,
        for example TLazOpenDialog, TLazSaveDialog, TLazSelectDirectoryDialog.
        It is used by widgetsets which either do not have a native dialog, or
        do not wish to use it because it is limited. These dialogs can also be
        used by user applications directly.
      + lazdeviceapis.pas: offers an interface to more hardware devices such
        as the accelerometer, GPS, etc. See LazDeviceAPIs
      + lazcanvas.pas: provides a TFPImageCanvas descendent implementing
        drawing in a LCL-compatible way, but 100% in Pascal.
      + lazregions.pas. LazRegions is a wholly Pascal implementation of
        regions for canvas clipping, event clipping, finding in which control
        of a region tree one an event should reach, for drawing polygons, etc.
      + customdrawncontrols.pas, customdrawndrawers.pas,
        customdrawn_common.pas, customdrawn_android.pas and
        customdrawn_winxp.pas: are the Lazarus Custom Drawn Controls -controls
        which imitate the standard LCL ones, but with the difference that they
        are non-native and support skinning.
  - New APIs added to the LCL to improve support of accessibility software
    such as screen readers.
* IDE changes:
  - Many improvments.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/New_IDE_features_since#v1.0_.282012-08-29.29
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes#IDE_Changes
* Debugger / Editor changes:
  - Added pascal sources and breakpoints to the disassembler
  - Added threads dialog.
* Components changes:
  - TAChart: many fixes and new features
  - CodeTool: support Delphi style generics and new syntax extensions.
  - AggPas: removed to honor free licencing. (Closes: Bug#708695)
[Bart Martens]
* New debian/watch file fixing issues with upstream RC release.
[Abou Al Montacir]
* Avoid changing files in .pc hidden directory, these are used by quilt for
  internal purpose and could lead to surprises during build.
[Paul Gevers]
* Updated get-orig-source target and it compinion script orig-tar.sh so that they
  repack the source file, allowing bug 708695 to be fixed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
uses
34
34
  Classes, SysUtils, LCLProc, Forms, Controls, Graphics, Dialogs,
 
35
  BasicCodeTools,
35
36
  SynEditAutoComplete, SynPluginTemplateEdit, SynPluginSyncronizedEditBase, SynEdit,
36
37
  MacroIntf, LazIDEIntf, SrcEditorIntf;
37
38
 
64
65
    FEditCellList: TSynPluginSyncronizedEditList;
65
66
    FEnableMacros: Boolean;
66
67
    FIndent: String;
 
68
    FKeepSubIndent: Boolean;
67
69
    FSrcTemplate: String;
68
70
    FDestTemplate: String;
69
71
    FSrcPosition: Integer;
72
74
    FDestPosY: Integer;
73
75
    FLevel: Integer;
74
76
    FSrcEdit: TSourceEditorInterface;
 
77
    FSubIndent: integer;
75
78
  protected
76
79
    // nested macros, get the X pos of the outer macro
77
80
    function GetSrcPosition: Integer; override;
92
95
    procedure TrimEOTChar(eot: Char);
93
96
 
94
97
    property EnableMacros: Boolean read FEnableMacros write FEnableMacros;
 
98
    property KeepSubIndent: Boolean read FKeepSubIndent write FKeepSubIndent;
95
99
    property Indent: String read FIndent write FIndent;
 
100
    property SubIndent: integer read FSubIndent write FSubIndent;
96
101
    property DestCaret: TPoint read FCaret;
97
102
 
98
103
    property EditCellList: TSynPluginSyncronizedEditList read FEditCellList;
202
207
end;
203
208
 
204
209
function TLazTemplateParser.SubstituteMacros(var Template: String): boolean;
 
210
const
 
211
  TemplateTabWidth = 8;
 
212
var
 
213
  IndentLevel: Integer;
 
214
  LastLineIndent: Integer;
 
215
  IsLineStart: boolean;
205
216
 
206
217
  procedure AppentToDest(S: String);
207
218
  var
208
 
    i, i2: Integer;
 
219
    i, LastCopy: Integer;
 
220
    CurLineIndent: LongInt;
 
221
    SpaceStart: LongInt;
209
222
  begin
210
223
    i := 1;
211
 
    i2 := 1;
 
224
    LastCopy := 1;
 
225
    //debugln(['AppentToDest START S="',dbgstr(S),'" Indent="',dbgstr(Indent),'"']);
212
226
    while i <= length(S) do begin
213
227
      case s[i] of
214
228
        #10, #13:
216
230
            inc(i);
217
231
            if (i <= length(S)) and (s[i] in [#10,#13]) and (s[i] <> s[i-1]) then
218
232
              inc(i);
219
 
            if (FDestTemplate <> '') and (i > i2) and
220
 
               (FDestTemplate[length(FDestTemplate)] in [#10, #13])
221
 
            then
222
 
              FDestTemplate := FDestTemplate + FIndent;
223
 
            FDestTemplate := FDestTemplate + copy(s, i2, i - i2);
224
 
            i2 := i;
 
233
            FDestTemplate := FDestTemplate + copy(s, LastCopy, i - LastCopy) + FIndent;
 
234
            LastCopy := i;
225
235
            FDestPosX := 1 + length(FIndent);
 
236
            IsLineStart:=true;
226
237
            inc(FDestPosY);
227
238
          end;
228
 
        else
 
239
        else // case else
229
240
          begin
230
 
            if (s[i] = '|') and (FCaret.y < 0) then begin
 
241
            if (s[i] in [' ',#9])
 
242
              and (not KeepSubIndent)
 
243
              and ((FDestTemplate<>'') and IsLineStart)
 
244
            then begin
 
245
              // space at start of template line (not first line)
 
246
              FDestTemplate:=FDestTemplate+copy(S,LastCopy,i-LastCopy);
 
247
              LastCopy:=i;
 
248
              SpaceStart:=i;
 
249
              while (i<=length(S)) and (S[i] in [' ',#9]) do inc(i);
 
250
              // compare the indentation of the current and the last line of the template
 
251
              CurLineIndent:=GetLineIndentWithTabs(S,SpaceStart,TemplateTabWidth);
 
252
              if CurLineIndent>LastLineIndent then
 
253
                inc(IndentLevel)
 
254
              else if (IndentLevel>0) and (CurLineIndent<LastLineIndent) then
 
255
                dec(IndentLevel);
 
256
              LastLineIndent:=CurLineIndent;
 
257
              // append space
 
258
              CurLineIndent:=IndentLevel*SubIndent;
 
259
              //debugln(['AppentToDest CurLineIndent=',CurLineIndent,' ',IndentLevel,'*',SubIndent]);
 
260
              FDestTemplate:=FDestTemplate+StringOfChar(' ',CurLineIndent);
 
261
              LastCopy:=i;
 
262
              inc(FDestPosX,CurLineIndent);
 
263
            end else if (s[i] = '|') and (FCaret.y < 0) then
 
264
            begin
 
265
              // place cursor
231
266
              System.Delete(s, i, 1);
232
267
              FCaret.y := FDestPosY;
233
268
              FCaret.x := FDestPosX;
236
271
              inc(i);
237
272
              inc(FDestPosX);
238
273
            end;
239
 
        end;
 
274
            IsLineStart:=false;
 
275
          end;
240
276
      end;
241
277
    end;
242
 
    if (FDestTemplate <> '') and (i > i2) and
 
278
    if (FDestTemplate <> '') and (i > LastCopy) and
243
279
       (FDestTemplate[length(FDestTemplate)] in [#10, #13])
244
280
    then
245
281
      FDestTemplate := FDestTemplate + FIndent;
246
 
    FDestTemplate := FDestTemplate + copy(s, i2, i - i2);
 
282
    FDestTemplate := FDestTemplate + copy(s, LastCopy, i - LastCopy);
247
283
    FDestPosition := length(FDestTemplate);
 
284
    //debugln(['AppentToDest END FDestTemplate=',dbgstr(FDestTemplate)]);
248
285
  end;
249
286
 
250
287
var
266
303
  p:=1;
267
304
  SrcCopiedPos := 1;
268
305
  len:=length(Template);
 
306
  IndentLevel:=0;
 
307
  LastLineIndent:=0;
 
308
  IsLineStart:=false;
269
309
  while p <= len do begin
270
310
    case Template[p] of
271
311
      '$':
371
411
    System.Delete(FDestTemplate, length(FDestTemplate), 1);
372
412
end;
373
413
 
374
 
 
375
414
function ExecuteCodeTemplate(SrcEdit: TSourceEditorInterface;
376
415
  const TemplateName, TemplateValue, TemplateComment,
377
416
  EndOfTokenChr: string; Attributes: TStrings;
378
417
  IndentToTokenStart: boolean): boolean;
379
418
var
380
 
  AEditor: TCustomSynEdit;
 
419
  AEditor: TSynEdit;
381
420
  p: TPoint;
382
421
  TokenStartX: LongInt;
383
422
  s: string;
384
 
  IndentLen: Integer;
 
423
  BaseIndent: Integer;
385
424
  i: Integer;
386
425
  j: LongInt;
387
426
  Pattern: String;
390
429
begin
391
430
  Result:=false;
392
431
  //debugln('ExecuteCodeTemplate ',dbgsName(SrcEdit),' ',dbgsName(SrcEdit.EditorControl));
393
 
  AEditor:=SrcEdit.EditorControl as TCustomSynEdit;
 
432
  AEditor:=SrcEdit.EditorControl as TSynEdit;
394
433
  Pattern:=TemplateValue;
395
434
 
396
435
  Parser := TLazTemplateParser.Create(Pattern);
397
436
  AEditor.BeginUpdate;
398
437
  try
 
438
    Parser.SubIndent:=AEditor.BlockIndent;
399
439
    p := AEditor.LogicalCaretXY;
400
440
    TokenStartX:=p.x;
401
441
    if IndentToTokenStart then begin
402
 
      IndentLen := TokenStartX - 1;
 
442
      BaseIndent := TokenStartX - 1;
403
443
    end else begin
404
444
      // indent the same as the first line
405
 
      IndentLen:=1;
 
445
      BaseIndent:=1;
406
446
      if (p.y>0) and (p.y<=AEditor.Lines.Count) then begin
407
447
        s:=AEditor.Lines[p.y-1];
408
 
        while (IndentLen<p.x)
409
 
        and ((IndentLen>length(s)) or (s[IndentLen] in [#9,' '])) do
410
 
          inc(IndentLen);
 
448
        while (BaseIndent<p.x)
 
449
        and ((BaseIndent>length(s)) or (s[BaseIndent] in [#9,' '])) do
 
450
          inc(BaseIndent);
411
451
      end;
412
 
      IndentLen:=AEditor.LogicalToPhysicalCol(s, p.y - 1, IndentLen);// consider tabs
413
 
      dec(IndentLen);
 
452
      BaseIndent:=AEditor.LogicalToPhysicalCol(s, p.y - 1, BaseIndent);// consider tabs
 
453
      dec(BaseIndent);
414
454
    end;
415
455
 
416
456
    Parser.EnableMacros := Attributes.IndexOfName(CodeTemplateEnableMacros)>=0;
417
 
    Parser.Indent := StringOfChar(' ', IndentLen);
 
457
    Parser.KeepSubIndent := Attributes.IndexOfName(CodeTemplateKeepSubIndent)>=0;
 
458
    Parser.Indent := StringOfChar(' ', BaseIndent);
418
459
    LazarusIDE.SaveSourceEditorChangesToCodeCache(nil);
419
460
    if not Parser.SubstituteCodeMacros(SrcEdit) then exit;
420
461
 
431
472
 
432
473
    // New Caret
433
474
    p := Parser.DestCaret ;
434
 
    if p.y < 0 then
435
 
      p := AEditor.CaretXY
436
 
    else begin
 
475
    if p.y >= 0 then begin
437
476
      if p.y = 1 then
438
477
        p.x := p.x + TokenStartX - 1;
439
478
      p.y := p.y + AEditor.BlockBegin.y - 1; // Todo: logicalToPhysical
451
490
        Parser.TrimEOTChar(EndOfTokenChr[i]);
452
491
    end;
453
492
 
454
 
    i := AEditor.PluginCount - 1;
 
493
    if Parser.EditCellList.Count > 0 then
 
494
      i := AEditor.PluginCount - 1
 
495
    else
 
496
      i := -1;
455
497
    while i >= 0 do begin
456
498
      if AEditor.Plugin[i] is TSynPluginTemplateEdit then begin
 
499
        if p.y < 1 then
 
500
          p := AEditor.CaretXY;
457
501
        TSynPluginTemplateEdit(AEditor.Plugin[i]).CellParserEnabled := False;
458
502
        TSynPluginTemplateEdit(AEditor.Plugin[i]).SetTemplate(Parser.DestTemplate, p);
459
503
        TSynPluginTemplateEdit(AEditor.Plugin[i]).AddEditCells(Parser.EditCellList);
463
507
    end;
464
508
    if i < 0 then begin
465
509
      // replace the selected text and position the caret
466
 
      AEditor.SelText := Parser.DestTemplate;
467
 
      AEditor.MoveCaretIgnoreEOL(p);
 
510
      AEditor.SetTextBetweenPoints(AEditor.BlockBegin, AEditor.BlockEnd, Parser.DestTemplate, [], scamEnd);
 
511
      if p.y > 0 then
 
512
        AEditor.MoveCaretIgnoreEOL(p);
468
513
    end;
469
514
  finally
470
515
    AEditor.EndUpdate;