1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2009 by 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 <devices/clipboard.h>
26 #include <libraries/iffparse.h>
28 #include <clib/alib_protos.h>
29 #include <proto/graphics.h>
30 #include <proto/layers.h>
31 #include <proto/exec.h>
32 #include <proto/iffparse.h>
33 #include <proto/intuition.h>
38 BOOL
InitClipboard(struct InstData
*data
, ULONG flags
);
39 void EndClipSession(struct InstData
*data
);
41 #if defined(__MORPHOS__)
42 #include <proto/keymap.h>
43 #include <proto/locale.h>
45 static char *utf8_to_ansi(struct InstData
*data
, STRPTR src
)
47 static struct KeyMap
*keymap
;
50 ULONG octets
, strlength
;
54 keymap
= AskKeyMapDefault();
64 ptr
+= (octets
= UTF8_Decode(ptr
, &wc
));
65 c
= ToANSI(wc
, keymap
);
69 /* ToANSI() returns '?' if there is not matching code point in the current keymap */
70 if (c
== '?' && wc
!= '?')
72 /* If direct conversion fails try compatibility decomposition (but without recursion) */
73 CONST_WSTRPTR p
= UCS4_Decompose(wc
);
87 dst
= MyAllocPooled(data
->mypool
, strlength
);
100 ptr
+= (octets
= UTF8_Decode(ptr
, &wc
));
101 c
= ToANSI(wc
, keymap
);
105 if (c
== '?' && wc
!= '?')
107 CONST_WSTRPTR p
= UCS4_Decompose(wc
);
115 *bufptr
++ = ToANSI(*p
, keymap
);
123 MyFreePooled(data
->mypool
, src
); // Free original buffer
134 /*----------------------*
135 * Paste from Clipboard *
136 *----------------------*/
137 BOOL
PasteClip (LONG x
, struct line_node
*actline
, struct InstData
*data
)
139 struct line_node
*line
= NULL
;
140 struct line_node
*startline
= NULL
;
141 struct line_node
*previous
= NULL
;
142 UWORD
*styles
= NULL
;
143 UWORD
*colors
= NULL
;
150 if(InitClipboard(data
, IFFF_READ
))
152 if(StopChunk(data
->iff
, ID_FTXT
, ID_CHRS
) == 0 &&
153 StopChunk(data
->iff
, ID_FTXT
, ID_FLOW
) == 0 &&
154 StopChunk(data
->iff
, ID_FTXT
, ID_HIGH
) == 0 &&
155 StopChunk(data
->iff
, ID_FTXT
, ID_SBAR
) == 0 &&
156 StopChunk(data
->iff
, ID_FTXT
, ID_COLS
) == 0 &&
157 StopChunk(data
->iff
, ID_FTXT
, ID_STYL
) == 0 &&
158 StopChunk(data
->iff
, ID_FTXT
, ID_CSET
) == 0)
160 LONG error
, codeset
= 0;
161 UWORD flow
= MUIV_TextEditor_Flow_Left
;
164 BOOL ownclip
= FALSE
;
169 struct ContextNode
*cn
;
171 error
= ParseIFF(data
->iff
, IFFPARSE_SCAN
);
172 SHOWVALUE(DBF_CLIPBOARD
, error
);
173 if(error
== IFFERR_EOC
)
178 if((cn
= CurrentChunk(data
->iff
)) != NULL
)
183 D(DBF_CLIPBOARD
, "reading FLOW");
184 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
187 /* Only the first four bytes are interesting */
188 if(ReadChunkBytes(data
->iff
, &codeset
, 4) != 4)
192 SHOWVALUE(DBF_CLIPBOARD
, codeset
);
197 D(DBF_CLIPBOARD
, "reading FLOW");
198 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
201 if(ReadChunkBytes(data
->iff
, &flow
, 2) == 2)
202 if(flow
> MUIV_TextEditor_Flow_Right
)
203 flow
= MUIV_TextEditor_Flow_Left
;
204 SHOWVALUE(DBF_CLIPBOARD
, flow
);
209 D(DBF_CLIPBOARD
, "reading HIGH");
210 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
211 if (cn
->cn_Size
== 2)
213 error
= ReadChunkBytes(data
->iff
, &color
, 2);
214 SHOWVALUE(DBF_CLIPBOARD
, color
);
215 SHOWVALUE(DBF_CLIPBOARD
, error
);
220 D(DBF_CLIPBOARD
, "reading SBAR");
221 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
222 if (cn
->cn_Size
== 2)
224 error
= ReadChunkBytes(data
->iff
, &separator
, 2);
225 SHOWVALUE(DBF_CLIPBOARD
, separator
);
226 SHOWVALUE(DBF_CLIPBOARD
, error
);
231 D(DBF_CLIPBOARD
, "reading COLS");
232 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
235 MyFreePooled(data
->mypool
, colors
);
238 // allocate one word more than the chunk tell us, because we terminate the array with an additional value
239 if(cn
->cn_Size
> 0 && (colors
= (UWORD
*)MyAllocPooled(data
->mypool
, cn
->cn_Size
+ sizeof(UWORD
))) != NULL
)
241 error
= ReadChunkBytes(data
->iff
, colors
, cn
->cn_Size
);
242 SHOWVALUE(DBF_CLIPBOARD
, error
);
243 colors
[cn
->cn_Size
/ 2] = 0xffff;
248 D(DBF_CLIPBOARD
, "reading STYL");
249 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
253 MyFreePooled(data
->mypool
, styles
);
256 // allocate one word more than the chunk tell us, because we terminate the array with an additional value
257 if(cn
->cn_Size
> 0 && (styles
= (UWORD
*)MyAllocPooled(data
->mypool
, cn
->cn_Size
+ sizeof(UWORD
))) != NULL
)
259 error
= ReadChunkBytes(data
->iff
, styles
, cn
->cn_Size
);
260 SHOWVALUE(DBF_CLIPBOARD
, error
);
261 styles
[cn
->cn_Size
/ 2] = EOS
;
267 D(DBF_CLIPBOARD
, "reading CHRS");
268 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
270 data
->HasChanged
= TRUE
;
272 if(cn
->cn_Size
> 0 && !ownclip
)
275 ULONG length
= cn
->cn_Size
;
277 if((contents
= (char *)MyAllocPooled(data
->mypool
, length
+ 1)) != NULL
)
279 error
= ReadChunkBytes(data
->iff
, contents
, length
);
280 SHOWVALUE(DBF_CLIPBOARD
, error
);
282 if(contents
[length
- 1] != '\n')
290 contents
[length
] = '\0';
292 #if defined(__MORPHOS__)
293 if (codeset
== CODESET_UTF8
)
296 contents
= utf8_to_ansi(data
, contents
);
300 if((line
= ImportText(contents
, data
, &ImPlainHook
, data
->ImportWrap
)))
305 previous
->next
= line
;
307 line
->previous
= previous
;
308 line
->visual
= VisualHeight(line
, data
);
309 data
->totallines
+= line
->visual
;
313 line
->visual
= VisualHeight(line
, data
);
314 data
->totallines
+= line
->visual
;
318 MyFreePooled(data
->mypool
, contents
);
323 ULONG length
= cn
->cn_Size
;
325 if(length
> 0 && (textline
= (char *)MyAllocPooled(data
->mypool
, length
+ 2)) != NULL
)
327 error
= ReadChunkBytes(data
->iff
, textline
, length
);
328 SHOWVALUE(DBF_CLIPBOARD
, error
);
330 if (textline
[length
- 1] != '\n')
333 textline
[length
] = '\n';
336 textline
[length
] = '\0';
338 if((line
= AllocLine(data
)))
341 line
->previous
= previous
;
342 line
->line
.Contents
= textline
;
343 line
->line
.Length
= length
;
344 line
->visual
= VisualHeight(line
, data
);
345 line
->line
.Color
= color
;
346 line
->line
.Flow
= flow
;
347 line
->line
.Separator
= separator
;
348 line
->line
.Styles
= styles
;
349 line
->line
.Colors
= colors
;
350 data
->totallines
+= line
->visual
;
355 previous
->next
= line
;
362 MyFreePooled(data
->mypool
, (void *)styles
);
364 MyFreePooled(data
->mypool
, (void *)colors
);
370 MyFreePooled(data
->mypool
, styles
);
372 MyFreePooled(data
->mypool
, (void *)colors
);
376 flow
= MUIV_TextEditor_Flow_Left
;
389 BOOL oneline
= FALSE
;
391 SplitLine(x
, actline
, FALSE
, NULL
, data
);
392 line
->next
= actline
->next
;
393 actline
->next
->previous
= line
;
394 actline
->next
= startline
;
395 startline
->previous
= actline
;
396 data
->CPos_X
= line
->line
.Length
-1;
397 if(actline
->next
== line
)
399 data
->CPos_X
+= actline
->line
.Length
-1;
403 MergeLines(line
, data
);
404 MergeLines(actline
, data
);
412 data
->actualline
= line
;
421 D(DBF_CLIPBOARD
, "no FTXT clip!");
422 DoMethod(data
->object
, MUIM_TextEditor_HandleError
, Error_ClipboardIsNotFTXT
);
425 D(DBF_CLIPBOARD
, "clipboard is empty!");
426 DoMethod(data
->object
, MUIM_TextEditor_HandleError
, Error_ClipboardIsEmpty
);
432 ScrollIntoDisplay(data
);
433 updatefrom
= LineToVisual(actline
, data
)-1;
436 DumpText(data
->visual_y
+updatefrom
, updatefrom
, data
->maxlines
, TRUE
, data
);
444 EndClipSession(data
);
450 /*--------------------------*
451 * Merge two lines into one *
452 *--------------------------*/
453 BOOL
MergeLines(struct line_node
*line
, struct InstData
*data
)
455 struct line_node
*next
;
457 LONG visual
, oldvisual
, line_nr
;
458 LONG emptyline
= FALSE
;
459 LONG color
= line
->line
.Color
;
460 UWORD flow
= line
->line
.Flow
;
461 UWORD separator
= line
->line
.Separator
;
465 data
->HasChanged
= TRUE
;
466 if(line
->line
.Length
== 1)
469 color
= line
->next
->line
.Color
;
470 flow
= line
->next
->line
.Flow
;
471 separator
= line
->next
->line
.Separator
;
473 visual
= line
->visual
+ line
->next
->visual
;
475 if((newbuffer
= MyAllocPooled(data
->mypool
, line
->line
.Length
+line
->next
->line
.Length
+1)) != NULL
)
477 memcpy(newbuffer
, line
->line
.Contents
, line
->line
.Length
-1);
478 memcpy(newbuffer
+line
->line
.Length
-1, line
->next
->line
.Contents
, line
->next
->line
.Length
+1);
479 MyFreePooled(data
->mypool
, line
->line
.Contents
);
480 MyFreePooled(data
->mypool
, line
->next
->line
.Contents
);
482 if(emptyline
== TRUE
)
484 if(line
->line
.Styles
!= NULL
)
485 MyFreePooled(data
->mypool
, line
->line
.Styles
);
487 line
->line
.Styles
= line
->next
->line
.Styles
;
489 if(line
->line
.Colors
!= NULL
)
490 MyFreePooled(data
->mypool
, line
->line
.Colors
);
492 line
->line
.Colors
= line
->next
->line
.Colors
;
497 UWORD
*styles1
= line
->line
.Styles
;
498 UWORD
*styles2
= line
->next
->line
.Styles
;
500 UWORD
*colors1
= line
->line
.Colors
;
501 UWORD
*colors2
= line
->next
->line
.Colors
;
505 length
+= *((long *)styles1
-1) - 4;
507 length
+= *((long *)styles2
-1) - 4;
509 if((styles
= MyAllocPooled(data
->mypool
, length
)) != NULL
)
511 unsigned short* t_styles
= styles
;
512 unsigned short style
= 0;
514 SHOWVALUE(DBF_CLIPBOARD
, length
);
515 SHOWVALUE(DBF_CLIPBOARD
, styles
);
516 SHOWVALUE(DBF_CLIPBOARD
, styles1
);
517 SHOWVALUE(DBF_CLIPBOARD
, styles2
);
521 unsigned short* t_styles2
= styles2
;
523 while(*t_styles2
++ == 1)
525 if(*t_styles2
> 0xff)
526 style
&= *t_styles2
++;
528 style
|= *t_styles2
++;
534 while(*styles1
!= EOS
)
536 if((*styles1
== line
->line
.Length
) && ((~*(styles1
+1) & style
) == (*(styles1
+1) ^ 0xffff)))
538 style
&= *(styles1
+1);
543 *styles
++ = *styles1
++;
544 *styles
++ = *styles1
++;
547 SHOWVALUE(DBF_CLIPBOARD
, line
->line
.Styles
);
548 MyFreePooled(data
->mypool
, line
->line
.Styles
);
553 while(*styles2
!= EOS
)
555 if((*styles2
== 1) && (!(*(styles2
+1) & style
)))
561 *styles
++ = *styles2
++ + line
->line
.Length
- 1;
562 *styles
++ = *styles2
++;
565 SHOWVALUE(DBF_CLIPBOARD
, line
->next
->line
.Styles
);
566 MyFreePooled(data
->mypool
, line
->next
->line
.Styles
);
569 line
->line
.Styles
= t_styles
;
575 length
+= *((long *)colors1
-1) - 4;
577 length
+= *((long *)colors2
-1) - 4;
579 if((colors
= MyAllocPooled(data
->mypool
, length
)) != NULL
)
581 UWORD
*t_colors
= colors
;
584 SHOWVALUE(DBF_CLIPBOARD
, length
);
585 SHOWVALUE(DBF_CLIPBOARD
, colors
);
586 SHOWVALUE(DBF_CLIPBOARD
, colors1
);
587 SHOWVALUE(DBF_CLIPBOARD
, colors2
);
591 while(*colors1
< line
->line
.Length
&& *colors1
!= 0xffff)
593 *colors
++ = *colors1
++;
594 end_color
= *colors1
;
595 *colors
++ = *colors1
++;
597 SHOWVALUE(DBF_CLIPBOARD
, line
->line
.Colors
);
598 MyFreePooled(data
->mypool
, line
->line
.Colors
);
601 if(end_color
&& (colors2
== NULL
|| *colors2
!= 1))
603 *colors
++ = line
->line
.Length
;
609 if(*colors2
== 1 && *(colors2
+1) == end_color
)
612 while(*colors2
!= 0xffff)
614 *colors
++ = *colors2
++ + line
->line
.Length
- 1;
615 *colors
++ = *colors2
++;
617 SHOWVALUE(DBF_CLIPBOARD
, line
->next
->line
.Colors
);
618 MyFreePooled(data
->mypool
, line
->next
->line
.Colors
);
621 line
->line
.Colors
= t_colors
;
625 line
->line
.Contents
= newbuffer
;
626 line
->line
.Length
= strlen(newbuffer
);
629 line
->next
= line
->next
->next
;
630 if(line
->next
!= NULL
)
631 line
->next
->previous
= line
;
632 oldvisual
= line
->visual
;
633 line
->visual
= VisualHeight(line
, data
);
634 line
->line
.Color
= color
;
635 line
->line
.Flow
= flow
;
636 line
->line
.Separator
= separator
;
638 FreeLine(next
, data
);
640 line_nr
= LineToVisual(line
, data
);
642 // handle that we have to scroll up/down due to word wrapping
643 // that occurrs when merging lines
644 if(visual
> line
->visual
)
646 data
->totallines
-= 1;
647 if(line_nr
+line
->visual
-1 < data
->maxlines
)
649 if(emptyline
&& line_nr
> 0)
651 if(data
->fastbackground
)
653 ScrollUp(line_nr
- 1, 1, data
);
654 SetCursor(data
->CPos_X
, data
->actualline
, TRUE
, data
);
657 DumpText(data
->visual_y
+line_nr
-1, line_nr
-1, data
->maxlines
, TRUE
, data
);
661 if(data
->fastbackground
)
662 ScrollUp(line_nr
+ line
->visual
- 1, 1, data
);
664 DumpText(data
->visual_y
+line_nr
+line
->visual
-1, line_nr
+line
->visual
-1, data
->maxlines
, TRUE
, data
);
668 else if(visual
< line
->visual
)
670 data
->totallines
+= 1;
671 if(line_nr
+line
->visual
-1 < data
->maxlines
)
672 ScrollDown(line_nr
+ line
->visual
- 2, 1, data
);
675 if(!(emptyline
&& (line_nr
+ line
->visual
- 1 < data
->maxlines
)))
677 LONG t_oldvisual
= oldvisual
;
678 LONG t_line_nr
= line_nr
;
681 while((--t_oldvisual
) && (t_line_nr
++ <= data
->maxlines
))
682 c
= c
+ LineCharsWidth(line
->line
.Contents
+c
, data
);
684 while((c
< line
->line
.Length
) && (t_line_nr
<= data
->maxlines
))
685 c
= c
+ PrintLine(c
, line
, t_line_nr
++, TRUE
, data
);
688 if(line_nr
+ oldvisual
== 1 && line
->visual
== visual
-1)
691 data
->totallines
-= 1;
693 if(data
->fastbackground
)
694 DumpText(data
->visual_y
, 0, visual
-1, TRUE
, data
);
696 DumpText(data
->visual_y
, 0, data
->maxlines
, TRUE
, data
);
708 /*---------------------*
709 * Split line into two *
710 *---------------------*/
711 BOOL
SplitLine(LONG x
, struct line_node
*line
, BOOL move_crsr
, struct UserAction
*buffer
, struct InstData
*data
)
713 struct line_node
*newline
;
714 struct line_node
*next
;
718 UWORD crsr_x
= data
->CPos_X
;
719 struct line_node
*crsr_l
= data
->actualline
;
723 OffsetToLines(x
, line
, &pos
, data
);
727 if((newline
= AllocLine(data
)) != NULL
)
729 UWORD
*styles
= line
->line
.Styles
;
730 UWORD
*newstyles
= NULL
;
731 UWORD
*colors
= line
->line
.Colors
;
732 UWORD
*newcolors
= NULL
;
734 data
->HasChanged
= TRUE
;
735 Init_LineNode(newline
, line
, line
->line
.Contents
+x
, data
);
736 newline
->line
.Color
= line
->line
.Color
;
737 newline
->line
.Flow
= line
->line
.Flow
;
738 newline
->line
.Separator
= line
->line
.Separator
;
741 newline
->line
.Color
= buffer
->del
.style
;
742 newline
->line
.Flow
= buffer
->del
.flow
;
743 newline
->line
.Separator
= buffer
->del
.separator
;
752 while(*styles
++ <= x
+1)
761 while(*(styles
+length
) != EOS
)
763 length
= (length
*2) + 16;
765 if((newstyles
= MyAllocPooled(data
->mypool
, length
)) != NULL
)
767 UWORD
*nstyles
= newstyles
;
769 if(isFlagSet(style
, BOLD
))
774 if(isFlagSet(style
, ITALIC
))
779 if(isFlagSet(style
, UNDERLINE
))
782 *nstyles
++ = UNDERLINE
;
785 while(*styles
!= EOS
)
787 *nstyles
++ = (*styles
++) - x
;
788 *nstyles
++ = *styles
++;
793 if(isFlagSet(style
, BOLD
))
798 if(isFlagSet(style
, ITALIC
))
801 *ostyles
++ = ~ITALIC
;
803 if(isFlagSet(style
, UNDERLINE
))
806 *ostyles
++ = ~UNDERLINE
;
809 ostyles
= line
->line
.Styles
;
812 newline
->line
.Styles
= newstyles
;
816 UWORD color
= GetColor(x
, line
);
820 while(*colors
<= x
+1)
826 while(*(colors
+length
) != 0xffff)
828 length
= (length
*2) + 16;
830 if((newcolors
= MyAllocPooled(data
->mypool
, length
)) != NULL
)
832 UWORD
*ncolors
= newcolors
;
834 if(color
&& *colors
-x
!= 1)
840 while(*colors
!= 0xffff)
842 *ncolors
++ = (*colors
++) - x
;
843 *ncolors
++ = *colors
++;
848 ocolors
= line
->line
.Colors
;
851 newline
->line
.Colors
= newcolors
;
854 newline
->next
= next
;
856 next
->previous
= newline
;
858 *(line
->line
.Contents
+x
) = '\n';
859 *(line
->line
.Contents
+x
+1) = '\0';
860 line
->line
.Length
= x
+1;
862 /*------------------*/
864 line
->visual
= VisualHeight(line
, data
);
865 CompressLine(line
, data
);
867 line_nr
= LineToVisual(line
, data
) + line
->visual
- 1;
874 data
->actualline
= data
->actualline
->next
;
879 line
->line
.Color
= 0;
880 line
->line
.Separator
= 0;
881 if(!(line
->previous
&& line
->previous
->line
.Flow
== line
->line
.Flow
))
883 line
->line
.Flow
= MUIV_TextEditor_Flow_Left
;
885 if(line_nr
!= data
->maxlines
)
887 data
->totallines
+= 1;
888 if(data
->fastbackground
)
892 ScrollDown(line_nr
-1, 1, data
);
893 PrintLine(0, line
, line_nr
, FALSE
, data
);
897 ScrollDown(line_nr
, 1, data
);
900 else DumpText(data
->visual_y
+line_nr
-1, line_nr
-1, data
->maxlines
, TRUE
, data
);
905 data
->totallines
+= 1;
906 if(isFlagClear(data
->flags
, FLG_Quiet
))
908 struct Hook
*oldhook
;
910 oldhook
= InstallLayerHook(data
->rport
->Layer
, LAYERS_NOBACKFILL
);
911 ScrollRasterBF(data
->rport
, 0, data
->height
,
912 data
->xpos
, data
->ypos
,
913 data
->xpos
+ data
->innerwidth
- 1, (data
->ypos
+ ((data
->maxlines
-1) * data
->height
)) - 1);
914 InstallLayerHook(data
->rport
->Layer
, oldhook
);
916 PrintLine(0, line
, data
->maxlines
-1, FALSE
, data
);
917 if(!data
->fastbackground
)
919 DumpText(data
->visual_y
+data
->maxlines
-1, data
->maxlines
-1, data
->maxlines
, TRUE
, data
);
928 if(x
== (LONG
)(line
->line
.Length
+ newline
->line
.Length
- 2))
930 data
->totallines
+= 1;
933 line
->next
->line
.Color
= 0;
934 line
->next
->line
.Separator
= 0;
936 SetCursor(crsr_x
, crsr_l
, FALSE
, data
);
937 if(line_nr
< data
->maxlines
)
939 if(data
->fastbackground
)
941 ScrollDown(line_nr
, 1, data
);
942 if(line_nr
+1 <= data
->maxlines
)
943 PrintLine(0, line
->next
, line_nr
+1, FALSE
, data
);
945 else DumpText(data
->visual_y
+line_nr
, line_nr
, data
->maxlines
, TRUE
, data
);
951 x
= line
->line
.Length
;
953 OffsetToLines(x
-1, line
, &pos
, data
);
954 if(((ULONG
)(line
->visual
+ line
->next
->visual
) >= c
) && (line
->visual
== lines
))
956 if((ULONG
)(line
->visual
+ line
->next
->visual
) > c
)
957 data
->totallines
+= 1;
959 PrintLine(pos
.bytes
, line
, line_nr
, TRUE
, data
);
961 if((line_nr
+line
->next
->visual
-1 < data
->maxlines
) && ((ULONG
)(line
->visual
+ line
->next
->visual
) > c
))
963 ScrollDown(line_nr
+line
->next
->visual
-1, 1, data
);
968 PrintLine((x
-1)-pos
.x
, line
, line_nr
, TRUE
, data
);
970 if((line_nr
< data
->maxlines
) && ((ULONG
)(line
->visual
+ line
->next
->visual
) < c
))
972 data
->totallines
-= 1;
973 ScrollUp(line_nr
, 1, data
);
976 /*------------------*/
980 while((c
< line
->line
.Length
) && (line_nr
<= data
->maxlines
))
981 c
= c
+ PrintLine(c
, line
, line_nr
++, TRUE
, data
);
982 /* Her printes !HELE! den nye linie, burde optimeres! */
993 /*------------------------------------------------------------------*
994 * Backwards string copy, please replace with some assembler stuff! *
995 *------------------------------------------------------------------*/
996 static void strcpyback(char *dest
, char *src
)
1002 length
= strlen(src
)+1;
1003 dest
= dest
+ length
;
1013 /* ------------------------------------ *
1014 * Functions which updates the display *
1015 * ------------------------------------ */
1016 void OptimizedPrint(LONG x
, struct line_node
*line
, LONG line_nr
, LONG width
, struct InstData
*data
)
1024 twidth
= PrintLine(x
, line
, line_nr
, TRUE
, data
);
1027 if(twidth
!= width
&& x
+twidth
< (LONG
)line
->line
.Length
&& line_nr
<= data
->maxlines
)
1030 width
= LineCharsWidth(line
->line
.Contents
+x
+width
, data
) + width
- twidth
;
1040 static void UpdateChange(LONG x
, struct line_node
*line
, LONG length
, const char *characters
, struct UserAction
*buffer
, struct InstData
*data
)
1047 LONG lineabove_width
=0;
1051 line_nr
= LineToVisual(line
, data
);
1052 orgline_nr
= line_nr
;
1056 // don't exceed the line length!
1057 if(skip
> (LONG
)line
->line
.Length
)
1060 width
= LineCharsWidth(line
->line
.Contents
+ skip
, data
);
1061 if(width
> 0 && skip
+ width
< x
)
1063 lineabove_width
= width
;
1072 if(characters
!= NULL
)
1074 strcpyback(line
->line
.Contents
+x
+length
, line
->line
.Contents
+x
);
1075 memcpy(line
->line
.Contents
+x
, characters
, length
);
1077 line
->line
.Length
+= length
;
1080 UWORD style
= buffer
->del
.style
;
1082 AddStyleToLine(x
, line
, 1, (style
& BOLD
) ? BOLD
: ~BOLD
, data
);
1083 AddStyleToLine(x
, line
, 1, (style
& ITALIC
) ? ITALIC
: ~ITALIC
, data
);
1084 AddStyleToLine(x
, line
, 1, (style
& UNDERLINE
) ? UNDERLINE
: ~UNDERLINE
, data
);
1085 line
->line
.Flow
= buffer
->del
.flow
;
1086 line
->line
.Separator
= buffer
->del
.separator
;
1091 strlcpy(line
->line
.Contents
+x
, line
->line
.Contents
+x
+length
, line
->line
.Length
);
1093 line
->line
.Length
-= length
;
1096 diff
= VisualHeight(line
, data
) - line
->visual
;
1101 movement
= orgline_nr
+ line
->visual
- 1;
1103 line
->visual
+= diff
;
1104 data
->totallines
+= diff
;
1108 if(movement
< data
->maxlines
)
1109 ScrollDown(movement
, diff
, data
);
1113 movement
= orgline_nr
+ line
->visual
- 1;
1114 if(movement
<= data
->maxlines
)
1115 ScrollUp(movement
, -diff
, data
);
1119 if(orgline_nr
!= line_nr
)
1121 if(lineabove_width
!= LineCharsWidth(line
->line
.Contents
+skip
-lineabove_width
, data
))
1125 newwidth
= PrintLine(skip
-lineabove_width
, line
, line_nr
-1, TRUE
, data
) - lineabove_width
;
1128 if(skip
>= (LONG
)line
->line
.Length
)
1136 OptimizedPrint(skip
, line
, line_nr
, width
, data
);
1137 ScrollIntoDisplay(data
);
1138 data
->HasChanged
= TRUE
;
1143 /*------------------------------*
1144 * Paste n characters to a line *
1145 *------------------------------*/
1146 BOOL
PasteChars(LONG x
, struct line_node
*line
, LONG length
, const char *characters
, struct UserAction
*buffer
, struct InstData
*data
)
1150 if(line
->line
.Styles
!= NULL
)
1152 if(*line
->line
.Styles
!= EOS
)
1156 while(*(line
->line
.Styles
+c
) <= x
+1)
1158 while(*(line
->line
.Styles
+c
) != EOS
)
1160 *(line
->line
.Styles
+c
) += length
;
1166 if(line
->line
.Colors
!= NULL
)
1168 if(*line
->line
.Colors
!= 0xffff)
1172 while(*(line
->line
.Colors
+c
) <= x
+1)
1174 while(*(line
->line
.Colors
+c
) != 0xffff)
1176 *(line
->line
.Colors
+c
) += length
;
1182 if((*((long *)line
->line
.Contents
-1))-4 < (LONG
)(line
->line
.Length
+ length
+ 1))
1184 if(ExpandLine(line
, length
, data
) == FALSE
)
1191 UpdateChange(x
, line
, length
, characters
, buffer
, data
);
1196 /*----------------------------*
1197 * Remove n chars from a line *
1198 *----------------------------*/
1199 BOOL
RemoveChars(LONG x
, struct line_node
*line
, LONG length
, struct InstData
*data
)
1203 if(line
->line
.Styles
!= NULL
)
1205 if(*line
->line
.Styles
!= EOS
)
1207 UWORD start_style
= GetStyle(x
-1, line
);
1208 UWORD end_style
= GetStyle(x
+length
, line
);
1211 while(*(line
->line
.Styles
+c
) <= x
)
1214 if(start_style
!= end_style
)
1216 UWORD turn_off
= start_style
& ~end_style
;
1217 UWORD turn_on
= end_style
& ~start_style
;
1219 if(isFlagSet(turn_off
, BOLD
))
1221 *(line
->line
.Styles
+c
++) = x
+1;
1222 *(line
->line
.Styles
+c
++) = ~BOLD
;
1224 if(isFlagSet(turn_off
, ITALIC
))
1226 *(line
->line
.Styles
+c
++) = x
+1;
1227 *(line
->line
.Styles
+c
++) = ~ITALIC
;
1229 if(isFlagSet(turn_off
, UNDERLINE
))
1231 *(line
->line
.Styles
+c
++) = x
+1;
1232 *(line
->line
.Styles
+c
++) = ~UNDERLINE
;
1234 if(isFlagSet(turn_on
, BOLD
))
1236 *(line
->line
.Styles
+c
++) = x
+1;
1237 *(line
->line
.Styles
+c
++) = BOLD
;
1239 if(isFlagSet(turn_on
, ITALIC
))
1241 *(line
->line
.Styles
+c
++) = x
+1;
1242 *(line
->line
.Styles
+c
++) = ITALIC
;
1244 if(isFlagSet(turn_on
, UNDERLINE
))
1246 *(line
->line
.Styles
+c
++) = x
+1;
1247 *(line
->line
.Styles
+c
++) = UNDERLINE
;
1252 while(*(line
->line
.Styles
+c
) <= x
+length
+1)
1255 while(*(line
->line
.Styles
+c
) != EOS
)
1257 *(line
->line
.Styles
+store
++) = *(line
->line
.Styles
+c
++)-length
;
1258 *(line
->line
.Styles
+store
++) = *(line
->line
.Styles
+c
++);
1260 *(line
->line
.Styles
+store
) = EOS
;
1264 if(line
->line
.Colors
!= NULL
)
1266 if(*line
->line
.Colors
!= 0xffff)
1268 UWORD start_color
= x
? GetColor(x
-1, line
) : 0;
1269 UWORD end_color
= GetColor(x
+length
, line
);
1272 while(*(line
->line
.Colors
+c
) <= x
)
1275 if(start_color
!= end_color
)
1277 *(line
->line
.Colors
+c
++) = x
+1;
1278 *(line
->line
.Colors
+c
++) = end_color
;
1282 while(*(line
->line
.Colors
+c
) <= x
+length
+1)
1285 while(*(line
->line
.Colors
+c
) != 0xffff)
1287 *(line
->line
.Colors
+store
++) = *(line
->line
.Colors
+c
++)-length
;
1288 *(line
->line
.Colors
+store
++) = *(line
->line
.Colors
+c
++);
1290 *(line
->line
.Colors
+store
) = 0xffff;
1294 UpdateChange(x
, line
, length
, NULL
, NULL
, data
);