1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2014 TextEditor.mcc Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 TextEditor class Support Site: http://www.sf.net/projects/texteditor-mcc
21 ***************************************************************************/
25 #include <libraries/iffparse.h>
27 #include <clib/alib_protos.h>
28 #include <proto/utility.h>
29 #include <proto/exec.h>
30 #include <proto/iffparse.h>
36 void RedrawArea(struct InstData
*data
, LONG startx
, struct line_node
*startline
, LONG stopx
, struct line_node
*stopline
)
45 line_nr1
= LineToVisual(data
, startline
) - 1;
46 line_nr2
= LineToVisual(data
, stopline
) - 1;
48 OffsetToLines(data
, startx
, startline
, &pos1
);
50 if(stopx
>= stopline
->line
.Length
)
51 stopx
= stopline
->line
.Length
-1;
53 OffsetToLines(data
, stopx
, stopline
, &pos2
);
55 line_nr1
+= pos1
.lines
-1;
59 line_nr2
+= pos2
.lines
-1;
60 if(line_nr2
>= data
->maxlines
)
61 line_nr2
= data
->maxlines
-1;
62 if(line_nr1
<= line_nr2
)
64 DumpText(data
, data
->visual_y
+line_nr1
, line_nr1
, line_nr2
+1, TRUE
);
72 void MarkAllBlock(struct InstData
*data
, struct marking
*block
)
76 block
->startline
= GetFirstLine(&data
->linelist
);
78 block
->stopline
= GetLastLine(&data
->linelist
);
79 block
->stopx
= block
->stopline
->line
.Length
-1;
80 block
->enabled
= TRUE
;
87 STRPTR
GetBlock(struct InstData
*data
, struct marking
*block
)
91 struct line_node
*startline
;
92 struct line_node
*stopline
;
93 struct line_node
*act
;
95 struct ExportMessage emsg
;
99 startx
= block
->startx
;
100 stopx
= block
->stopx
;
101 startline
= block
->startline
;
102 stopline
= block
->stopline
;
104 data
->CPos_X
= startx
;
105 data
->actualline
= startline
;
107 // clear the export message
108 memset(&emsg
, 0, sizeof(struct ExportMessage
));
110 // fill it afterwards
111 emsg
.UserData
= NULL
;
115 emsg
.failure
= FALSE
;
117 if(startline
!= stopline
)
119 // Create a firstline look-a-like if it contains any text
120 D(DBF_BLOCK
, "exporting first line with length %ld, starting at %ld", startline
->line
.Length
-startx
, startx
);
121 if(emsg
.failure
== FALSE
&& startline
->line
.Length
-startx
> 0 && (emsg
.Contents
= AllocVecPooled(data
->mypool
, startline
->line
.Length
-startx
+1)) != NULL
)
123 if(startline
->line
.Styles
!= NULL
&& startline
->line
.Styles
[0].column
!= EOS
)
125 struct Grow styleGrow
;
126 UWORD startstyle
= GetStyle(startx
, startline
);
127 struct LineStyle
*oldstyles
= startline
->line
.Styles
;
129 D(DBF_BLOCK
, "export styles");
131 InitGrow(&styleGrow
, data
->mypool
, sizeof(struct LineStyle
));
133 // apply any active style
134 if(isFlagSet(startstyle
, BOLD
))
136 struct LineStyle newStyle
;
139 newStyle
.style
= BOLD
;
140 AddToGrow(&styleGrow
, &newStyle
);
142 if(isFlagSet(startstyle
, ITALIC
))
144 struct LineStyle newStyle
;
147 newStyle
.style
= ITALIC
;
148 AddToGrow(&styleGrow
, &newStyle
);
150 if(isFlagSet(startstyle
, UNDERLINE
))
152 struct LineStyle newStyle
;
155 newStyle
.style
= UNDERLINE
;
156 AddToGrow(&styleGrow
, &newStyle
);
159 // skip all styles until the block starts
160 while(oldstyles
->column
<= startx
)
163 // copy all styles until the end of the line
164 while(oldstyles
->column
!= EOS
)
166 struct LineStyle newStyle
;
168 newStyle
.column
= oldstyles
->column
- startx
;
169 newStyle
.style
= oldstyles
->style
;
170 AddToGrow(&styleGrow
, &newStyle
);
175 // terminate the style array
176 if(styleGrow
.itemCount
> 0)
178 struct LineStyle terminator
;
180 terminator
.column
= EOC
;
181 terminator
.style
= 0;
182 AddToGrow(&styleGrow
, &terminator
);
185 emsg
.Styles
= (struct LineStyle
*)styleGrow
.array
;
190 if(startline
->line
.Colors
!= NULL
&& startline
->line
.Colors
[0].column
!= EOC
)
192 struct Grow colorGrow
;
193 UWORD lastcolor
= GetColor(startx
, startline
);
194 struct LineColor
*oldcolors
= startline
->line
.Colors
;
196 D(DBF_BLOCK
, "export colors");
198 InitGrow(&colorGrow
, data
->mypool
, sizeof(struct LineColor
));
200 // apply the active color
203 struct LineColor newColor
;
206 newColor
.color
= lastcolor
;
207 AddToGrow(&colorGrow
, &newColor
);
210 // skip all colors until the block starts
211 while(oldcolors
->column
<= startx
)
214 // copy all colors until the end of the line
215 while(oldcolors
->column
!= EOC
)
217 // apply real color changes only
218 if(oldcolors
->color
!= lastcolor
)
220 struct LineColor newColor
;
222 newColor
.column
= oldcolors
->column
- startx
;
223 newColor
.color
= oldcolors
->color
;
224 AddToGrow(&colorGrow
, &newColor
);
226 // remember this color change
227 lastcolor
= oldcolors
->color
;
232 // unapply the last active color
235 struct LineColor newColor
;
237 newColor
.column
= strlen(startline
->line
.Contents
)-startx
+1;
239 AddToGrow(&colorGrow
, &newColor
);
242 // terminate the color array
243 if(colorGrow
.itemCount
> 0)
245 struct LineColor terminator
;
247 terminator
.column
= EOC
;
248 terminator
.color
= 0;
249 AddToGrow(&colorGrow
, &terminator
);
252 emsg
.Colors
= (struct LineColor
*)colorGrow
.array
;
257 strlcpy(emsg
.Contents
, &startline
->line
.Contents
[startx
], startline
->line
.Length
-startx
+1);
258 emsg
.Length
= startline
->line
.Length
- startx
;
259 emsg
.Flow
= startline
->line
.Flow
;
260 emsg
.Separator
= startline
->line
.Separator
;
261 emsg
.Highlight
= startline
->line
.Highlight
;
262 emsg
.UserData
= (APTR
)CallHookA(&ExportHookPlain
, NULL
, &emsg
);
264 FreeVecPooled(data
->mypool
, emsg
.Contents
);
266 if(emsg
.Styles
!= NULL
)
268 FreeVecPooled(data
->mypool
, emsg
.Styles
);
271 if(emsg
.Colors
!= NULL
)
273 FreeVecPooled(data
->mypool
, emsg
.Colors
);
278 // Start iterating...
279 act
= GetNextLine(startline
);
280 while(emsg
.failure
== FALSE
&& act
!= stopline
)
282 D(DBF_BLOCK
, "exporting line with length %ld", act
->line
.Length
);
283 emsg
.Contents
= act
->line
.Contents
;
284 emsg
.Length
= act
->line
.Length
;
285 emsg
.Styles
= act
->line
.Styles
;
286 emsg
.Colors
= act
->line
.Colors
;
287 emsg
.Flow
= act
->line
.Flow
;
288 emsg
.Separator
= act
->line
.Separator
;
289 emsg
.Highlight
= act
->line
.Highlight
;
290 emsg
.UserData
= (APTR
)CallHookA(&ExportHookPlain
, NULL
, &emsg
);
291 act
= GetNextLine(act
);
294 // Create a Lastline look-a-like if it contains any text
295 D(DBF_BLOCK
, "exporting last line, stopping at %ld", stopx
);
296 if(emsg
.failure
== FALSE
&& stopx
> 0 && (emsg
.Contents
= AllocVecPooled(data
->mypool
, stopx
+1)) != NULL
)
298 D(DBF_BLOCK
, "export styles");
300 if(stopline
->line
.Styles
!= NULL
&& stopline
->line
.Styles
[0].column
!= EOS
)
302 struct Grow styleGrow
;
303 UWORD stopstyle
= GetStyle(stopx
, stopline
);
304 struct LineStyle
*oldstyles
= stopline
->line
.Styles
;
306 InitGrow(&styleGrow
, data
->mypool
, sizeof(struct LineStyle
));
308 // copy all styles until the end of the block
309 while(oldstyles
->column
<= stopx
)
311 AddToGrow(&styleGrow
, oldstyles
);
315 // unapply any still active styles
316 if(isFlagSet(stopstyle
, BOLD
))
318 struct LineStyle newStyle
;
320 newStyle
.column
= stopx
+ 1;
321 newStyle
.style
= ~BOLD
;
322 AddToGrow(&styleGrow
, &newStyle
);
324 if(isFlagSet(stopstyle
, ITALIC
))
326 struct LineStyle newStyle
;
328 newStyle
.column
= stopx
+ 1;
329 newStyle
.style
= ~ITALIC
;
330 AddToGrow(&styleGrow
, &newStyle
);
332 if(isFlagSet(stopstyle
, UNDERLINE
))
334 struct LineStyle newStyle
;
336 newStyle
.column
= stopx
+ 1;
337 newStyle
.style
= ~UNDERLINE
;
338 AddToGrow(&styleGrow
, &newStyle
);
341 // terminate the style array
342 if(styleGrow
.itemCount
> 0)
344 struct LineStyle terminator
;
346 terminator
.column
= EOC
;
347 terminator
.style
= 0;
348 AddToGrow(&styleGrow
, &terminator
);
351 emsg
.Styles
= (struct LineStyle
*)styleGrow
.array
;
356 if(stopline
->line
.Colors
!= NULL
&& stopline
->line
.Colors
[0].column
!= EOC
)
358 struct Grow colorGrow
;
360 struct LineColor
*oldcolors
= stopline
->line
.Colors
;
362 D(DBF_BLOCK
, "export colors");
364 InitGrow(&colorGrow
, data
->mypool
, sizeof(struct LineColor
));
366 // copy all colors until the end of the block
367 while(oldcolors
->column
<= stopx
)
369 // apply real color changes only
370 if(oldcolors
->color
!= lastcolor
)
372 AddToGrow(&colorGrow
, oldcolors
);
373 // remember this color change
374 lastcolor
= oldcolors
->color
;
379 // unapply the last active color
382 struct LineColor newColor
;
384 newColor
.column
= stopx
+ 1;
386 AddToGrow(&colorGrow
, &newColor
);
389 // terminate the color array
390 if(colorGrow
.itemCount
> 0)
392 struct LineColor terminator
;
394 terminator
.column
= EOC
;
395 terminator
.color
= 0;
396 AddToGrow(&colorGrow
, &terminator
);
399 emsg
.Colors
= (struct LineColor
*)colorGrow
.array
;
404 strlcpy(emsg
.Contents
, stopline
->line
.Contents
, stopx
+1);
406 emsg
.Flow
= stopline
->line
.Flow
;
407 emsg
.Separator
= stopline
->line
.Separator
;
408 emsg
.Highlight
= stopline
->line
.Highlight
;
410 text
= (STRPTR
)CallHookA(&ExportHookPlain
, NULL
, &emsg
);
412 FreeVecPooled(data
->mypool
, emsg
.Contents
);
414 if(emsg
.Styles
!= NULL
)
416 FreeVecPooled(data
->mypool
, emsg
.Styles
);
419 if(emsg
.Colors
!= NULL
)
421 FreeVecPooled(data
->mypool
, emsg
.Colors
);
425 // clear the state pointer
426 emsg
.UserData
= NULL
;
431 // Create a single line
432 D(DBF_BLOCK
, "exporting single line, starting at %ld, stopping at %ld", startx
, stopx
);
433 if(emsg
.failure
== FALSE
&& stopx
-startx
> 0 && (emsg
.Contents
= AllocVecPooled(data
->mypool
, stopx
-startx
+1)) != NULL
)
435 if(startline
->line
.Styles
!= NULL
&& startline
->line
.Styles
->column
!= EOS
)
437 struct Grow styleGrow
;
438 UWORD startstyle
= GetStyle(startx
, startline
);
439 UWORD stopstyle
= GetStyle(stopx
, stopline
);
440 struct LineStyle
*oldstyles
= startline
->line
.Styles
;
442 InitGrow(&styleGrow
, data
->mypool
, sizeof(struct LineStyle
));
444 // apply any active style
445 if(isFlagSet(startstyle
, BOLD
))
447 struct LineStyle newStyle
;
450 newStyle
.style
= BOLD
;
451 AddToGrow(&styleGrow
, &newStyle
);
453 if(isFlagSet(startstyle
, ITALIC
))
455 struct LineStyle newStyle
;
458 newStyle
.style
= ITALIC
;
459 AddToGrow(&styleGrow
, &newStyle
);
461 if(isFlagSet(startstyle
, UNDERLINE
))
463 struct LineStyle newStyle
;
466 newStyle
.style
= UNDERLINE
;
467 AddToGrow(&styleGrow
, &newStyle
);
470 // skip all styles until the block starts
471 while(oldstyles
->column
<= startx
)
474 // copy all styles until the end of the block
475 while(oldstyles
->column
<= stopx
)
477 struct LineStyle newStyle
;
479 newStyle
.column
= oldstyles
->column
- startx
;
480 newStyle
.style
= oldstyles
->style
;
481 AddToGrow(&styleGrow
, &newStyle
);
486 // unapply any still active styles
487 if(isFlagSet(stopstyle
, BOLD
))
489 struct LineStyle newStyle
;
491 newStyle
.column
= stopx
- startx
+ 1;
492 newStyle
.style
= ~BOLD
;
493 AddToGrow(&styleGrow
, &newStyle
);
495 if(isFlagSet(stopstyle
, ITALIC
))
497 struct LineStyle newStyle
;
499 newStyle
.column
= stopx
- startx
+ 1;
500 newStyle
.style
= ~ITALIC
;
501 AddToGrow(&styleGrow
, &newStyle
);
503 if(isFlagSet(stopstyle
, UNDERLINE
))
505 struct LineStyle newStyle
;
507 newStyle
.column
= stopx
- startx
+ 1;
508 newStyle
.style
= ~UNDERLINE
;
509 AddToGrow(&styleGrow
, &newStyle
);
512 // terminate the style array
513 if(styleGrow
.itemCount
> 0)
515 struct LineStyle terminator
;
517 terminator
.column
= EOC
;
518 terminator
.style
= 0;
519 AddToGrow(&styleGrow
, &terminator
);
522 emsg
.Styles
= (struct LineStyle
*)styleGrow
.array
;
527 if(startline
->line
.Colors
!= NULL
&& startline
->line
.Colors
[0].column
!= EOC
)
529 struct Grow colorGrow
;
530 UWORD lastcolor
= GetColor(startx
, startline
);
531 struct LineColor
*oldcolors
= startline
->line
.Colors
;
533 InitGrow(&colorGrow
, data
->mypool
, sizeof(struct LineColor
));
535 // apply the active color
538 struct LineColor newColor
;
541 newColor
.color
= lastcolor
;
542 AddToGrow(&colorGrow
, &newColor
);
545 // skip all colors until the block starts
546 while(oldcolors
->column
<= startx
)
549 // copy all colors until the end of the block
550 while(oldcolors
->column
<= stopx
)
552 // apply real color changes only
553 if(oldcolors
->color
!= lastcolor
)
555 struct LineColor newColor
;
557 newColor
.column
= oldcolors
->column
- startx
;
558 newColor
.color
= oldcolors
->color
;
559 AddToGrow(&colorGrow
, &newColor
);
561 // remember this color change
562 lastcolor
= oldcolors
->color
;
567 // unapply the last active color
570 struct LineColor newColor
;
572 newColor
.column
= stopx
- startx
+ 1;
574 AddToGrow(&colorGrow
, &newColor
);
577 // terminate the color array
578 if(colorGrow
.itemCount
> 0)
580 struct LineColor terminator
;
582 terminator
.column
= EOC
;
583 terminator
.color
= 0;
584 AddToGrow(&colorGrow
, &terminator
);
587 emsg
.Colors
= (struct LineColor
*)colorGrow
.array
;
592 strlcpy(emsg
.Contents
, &startline
->line
.Contents
[startx
], stopx
-startx
+1);
593 emsg
.Length
= stopx
-startx
;
594 emsg
.Flow
= startline
->line
.Flow
;
595 emsg
.Separator
= startline
->line
.Separator
;
596 emsg
.Highlight
= startline
->line
.Highlight
;
598 text
= (STRPTR
)CallHookA(&ExportHookPlain
, NULL
, &emsg
);
600 FreeVecPooled(data
->mypool
, emsg
.Contents
);
602 if(emsg
.Styles
!= NULL
)
604 FreeVecPooled(data
->mypool
, emsg
.Styles
);
607 if(emsg
.Colors
!= NULL
)
609 FreeVecPooled(data
->mypool
, emsg
.Colors
);
613 // clear the state pointer
614 emsg
.UserData
= NULL
;
618 if(emsg
.UserData
!= NULL
)
620 SHOWVALUE(DBF_BLOCK
, emsg
.failure
);
621 // clear the state pointer if that didn't happen before
622 // and get the final exported text
623 emsg
.Contents
= (STRPTR
)"\n";
627 emsg
.Flow
= MUIV_TextEditor_Flow_Left
;
628 emsg
.Separator
= LNSF_None
;
629 emsg
.Highlight
= FALSE
;
631 // clear the failure signal, otherwise the hook will do nothing
632 emsg
.failure
= FALSE
;
633 text
= (STRPTR
)CallHookA(&ExportHookPlain
, NULL
, &emsg
);
642 void NiceBlock(struct marking
*realblock
, struct marking
*newblock
)
644 LONG startx
= realblock
->startx
;
645 LONG stopx
= realblock
->stopx
;
646 struct line_node
*startline
= realblock
->startline
;
647 struct line_node
*stopline
= realblock
->stopline
;
651 if(startline
== stopline
)
653 // swap start end position if the block is marked backwards
664 struct line_node
*c_startline
= startline
;
665 struct line_node
*c_stopline
= stopline
;
667 // ensure that the start and and stop line pointers really point to
668 // the first and last line respectively
669 while(c_startline
!= stopline
&& c_stopline
!= startline
)
671 if(HasNextLine(c_startline
) == TRUE
)
672 c_startline
= GetNextLine(c_startline
);
673 if(HasNextLine(c_stopline
) == TRUE
)
674 c_stopline
= GetNextLine(c_stopline
);
677 // swap start end position if the block is marked backwards
678 if(c_stopline
== startline
)
685 c_startline
= startline
;
686 startline
= stopline
;
687 stopline
= c_startline
;
691 // reuse the original block if this is requested
693 newblock
= realblock
;
695 newblock
->startx
= startx
;
696 newblock
->stopx
= stopx
;
697 newblock
->startline
= startline
;
698 newblock
->stopline
= stopline
;
705 LONG
CutBlock(struct InstData
*data
, ULONG flags
)
707 struct marking newblock
;
712 //D(DBF_STARTUP, "CutBlock: %08lx", flags);
714 NiceBlock(&data
->blockinfo
, &newblock
);
715 if(isFlagSet(flags
, CUTF_CUT
))
716 AddToUndoBuffer(data
, ET_DELETEBLOCK
, &newblock
);
718 result
= CutBlock2(data
, flags
, &newblock
);
726 LONG
CutBlock2(struct InstData
*data
, ULONG flags
, struct marking
*newblock
)
732 struct line_node
*startline
;
733 struct line_node
*stopline
;
734 IPTR clipSession
= (IPTR
)NULL
;
738 startx
= newblock
->startx
;
739 stopx
= newblock
->stopx
;
740 startline
= newblock
->startline
;
741 stopline
= newblock
->stopline
;
743 //D(DBF_STARTUP, "CutBlock2: %ld-%ld %lx-%lx %08lx", startx, stopx, startline, stopline, flags);
745 if(startline
!= stopline
)
747 struct line_node
*c_startline
= GetNextLine(startline
);
749 data
->update
= FALSE
;
751 if(isFlagSet(flags
, CUTF_CLIPBOARD
))
753 // write the block to the clipboard
754 if((clipSession
= ClientStartSession(IFFF_WRITE
)) != (IPTR
)NULL
)
756 ClientWriteChars(clipSession
, startline
, startx
, startline
->line
.Length
-startx
);
760 // clipboard access failed, don't do further clipboard accesses
761 clearFlag(flags
, CUTF_CLIPBOARD
);
765 while(c_startline
!= stopline
)
767 if(isFlagSet(flags
, CUTF_CLIPBOARD
))
769 ClientWriteLine(clipSession
, c_startline
);
772 if(isFlagSet(flags
, CUTF_CUT
))
774 struct line_node
*cc_startline
= GetNextLine(c_startline
);
776 FreeVecPooled(data
->mypool
, c_startline
->line
.Contents
);
777 if(c_startline
->line
.Styles
!= NULL
)
778 FreeVecPooled(data
->mypool
, c_startline
->line
.Styles
);
779 if(c_startline
->line
.Colors
!= NULL
)
780 FreeVecPooled(data
->mypool
, c_startline
->line
.Colors
);
781 data
->totallines
-= c_startline
->visual
;
783 //D(DBF_STARTUP, "FreeLine %08lx", cc_startline);
785 // check for possible references first
786 CheckBlock(data
, c_startline
);
787 // now remove and free the line
788 RemLine(c_startline
);
789 FreeVecPooled(data
->mypool
, c_startline
);
791 c_startline
= cc_startline
;
794 c_startline
= GetNextLine(c_startline
);
797 if(isFlagSet(flags
, CUTF_CLIPBOARD
))
800 ClientWriteChars(clipSession
, stopline
, 0, stopx
);
802 ClientEndSession(clipSession
);
805 if(isFlagSet(flags
, CUTF_CUT
))
807 //D(DBF_STARTUP, "RemoveChars: %ld %ld %08lx %ld", startx, stopx, startline, startline->line.Length);
809 if(startline
->line
.Length
-startx
-1 > 0)
810 RemoveChars(data
, startx
, startline
, startline
->line
.Length
-startx
-1);
813 RemoveChars(data
, 0, stopline
, stopx
);
815 data
->CPos_X
= startx
;
816 data
->actualline
= startline
;
817 MergeLines(data
, startline
);
822 if(isFlagSet(flags
, CUTF_CLIPBOARD
))
824 if((clipSession
= ClientStartSession(IFFF_WRITE
)) != (IPTR
)NULL
)
826 ClientWriteChars(clipSession
, startline
, startx
, stopx
-startx
);
827 ClientEndSession(clipSession
);
830 if(isFlagSet(flags
, CUTF_UPDATE
) && isFlagClear(flags
, CUTF_CUT
))
832 MarkText(data
, data
->blockinfo
.startx
, data
->blockinfo
.startline
, data
->blockinfo
.stopx
, data
->blockinfo
.stopline
);
837 if(isFlagSet(flags
, CUTF_CUT
))
839 data
->CPos_X
= startx
;
840 RemoveChars(data
, startx
, startline
, stopx
-startx
);
841 if(isFlagSet(flags
, CUTF_UPDATE
))
846 tvisual_y
= LineToVisual(data
, startline
)-1;
847 if(tvisual_y
< 0 || tvisual_y
> data
->maxlines
)
849 //D(DBF_STARTUP, "ScrollIntoDisplay");
850 ScrollIntoDisplay(data
);
854 if(isFlagSet(flags
, CUTF_UPDATE
))
856 //D(DBF_STARTUP, "DumpText! %ld %ld %ld", data->visual_y, tvisual_y, data->maxlines);
858 DumpText(data
, data
->visual_y
+tvisual_y
, tvisual_y
, data
->maxlines
, TRUE
);
870 // check if the global block structure references the given line and
871 // adjust the block structure accordingly
872 void CheckBlock(struct InstData
*data
, struct line_node
*line
)
874 // we make sure the line is not referenced by other
875 // structures as well such as the global blockinfo structure.
876 if(data
->blockinfo
.startline
== line
)
878 data
->blockinfo
.startline
= GetNextLine(line
);
879 if(data
->blockinfo
.startline
== NULL
)
881 data
->blockinfo
.enabled
= FALSE
;
885 if(data
->blockinfo
.stopline
== line
)
887 data
->blockinfo
.stopline
= GetPrevLine(line
);
888 if(data
->blockinfo
.stopline
== NULL
)
890 data
->blockinfo
.enabled
= FALSE
;