Updated from its repository.
[cake.git] / workbench / classes / gadgets / texteditor / mcc / EditorStuff.c
blob1b2cb705ec3ec2d72fb79d07eb11116554bf2b56
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
19 $Id$
21 ***************************************************************************/
23 #include <string.h>
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>
35 #include "private.h"
36 #include "Debug.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;
48 CONST_STRPTR ptr;
49 STRPTR dst;
50 ULONG octets, strlength;
52 ENTER();
54 keymap = AskKeyMapDefault();
56 strlength = 0;
57 ptr = src;
61 WCHAR wc;
62 UBYTE c;
64 ptr += (octets = UTF8_Decode(ptr, &wc));
65 c = ToANSI(wc, keymap);
67 strlength++;
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);
75 if (p)
77 while (p[1])
79 strlength++;
80 p++;
85 while (octets > 0);
87 dst = MyAllocPooled(data->mypool, strlength);
89 if (dst)
91 STRPTR bufptr = dst;
93 ptr = src;
97 WCHAR wc;
98 UBYTE c;
100 ptr += (octets = UTF8_Decode(ptr, &wc));
101 c = ToANSI(wc, keymap);
103 *bufptr++ = c;
105 if (c == '?' && wc != '?')
107 CONST_WSTRPTR p = UCS4_Decompose(wc);
109 if (p)
111 bufptr--;
113 while (*p)
115 *bufptr++ = ToANSI(*p, keymap);
116 p++;
121 while (octets > 0);
123 MyFreePooled(data->mypool, src); // Free original buffer
126 if(dst == NULL)
127 dst = src;
129 RETURN(dst);
130 return dst;
132 #endif
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;
144 STRPTR textline;
145 BOOL newline = TRUE;
146 BOOL res = FALSE;
148 ENTER();
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;
162 UWORD color = FALSE;
163 UWORD separator = 0;
164 BOOL ownclip = FALSE;
165 LONG updatefrom;
167 while(TRUE)
169 struct ContextNode *cn;
171 error = ParseIFF(data->iff, IFFPARSE_SCAN);
172 SHOWVALUE(DBF_CLIPBOARD, error);
173 if(error == IFFERR_EOC)
174 continue;
175 else if(error)
176 break;
178 if((cn = CurrentChunk(data->iff)) != NULL)
180 switch (cn->cn_ID)
182 case ID_CSET:
183 D(DBF_CLIPBOARD, "reading FLOW");
184 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
185 if(cn->cn_Size >= 4)
187 /* Only the first four bytes are interesting */
188 if(ReadChunkBytes(data->iff, &codeset, 4) != 4)
190 codeset = 0;
192 SHOWVALUE(DBF_CLIPBOARD, codeset);
194 break;
196 case ID_FLOW:
197 D(DBF_CLIPBOARD, "reading FLOW");
198 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
199 if(cn->cn_Size == 2)
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);
206 break;
208 case ID_HIGH:
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);
217 break;
219 case ID_SBAR:
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);
228 break;
230 case ID_COLS:
231 D(DBF_CLIPBOARD, "reading COLS");
232 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
233 if(colors)
235 MyFreePooled(data->mypool, colors);
236 colors = NULL;
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;
245 break;
247 case ID_STYL:
248 D(DBF_CLIPBOARD, "reading STYL");
249 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
250 ownclip = TRUE;
251 if(styles)
253 MyFreePooled(data->mypool, styles);
254 styles = NULL;
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;
263 break;
265 case ID_CHRS:
267 D(DBF_CLIPBOARD, "reading CHRS");
268 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
270 data->HasChanged = TRUE;
272 if(cn->cn_Size > 0 && !ownclip)
274 char *contents;
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')
284 newline = FALSE;
286 else
288 length--;
290 contents[length] = '\0';
292 #if defined(__MORPHOS__)
293 if (codeset == CODESET_UTF8)
295 if (IS_MORPHOS2)
296 contents = utf8_to_ansi(data, contents);
298 #endif
300 if((line = ImportText(contents, data, &ImPlainHook, data->ImportWrap)))
302 if(!startline)
303 startline = line;
304 if(previous)
305 previous->next = line;
307 line->previous = previous;
308 line->visual = VisualHeight(line, data);
309 data->totallines += line->visual;
310 while(line->next)
312 line = line->next;
313 line->visual = VisualHeight(line, data);
314 data->totallines += line->visual;
316 previous = line;
318 MyFreePooled(data->mypool, contents);
321 else
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')
332 newline = FALSE;
333 textline[length] = '\n';
334 length++;
336 textline[length] = '\0';
338 if((line = AllocLine(data)))
340 line->next = NULL;
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;
352 if(!startline)
353 startline = line;
354 if(previous)
355 previous->next = line;
357 previous = line;
359 else
361 if(styles)
362 MyFreePooled(data->mypool, (void *)styles);
363 if(colors)
364 MyFreePooled(data->mypool, (void *)colors);
367 else
369 if(styles)
370 MyFreePooled(data->mypool, styles);
371 if(colors)
372 MyFreePooled(data->mypool, (void *)colors);
374 styles = NULL;
375 colors = NULL;
376 flow = MUIV_TextEditor_Flow_Left;
377 color = FALSE;
378 separator = 0;
379 ownclip = FALSE;
382 break;
387 if(line)
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;
400 oneline = TRUE;
402 if(!newline)
403 MergeLines(line, data);
404 MergeLines(actline, data);
405 if(oneline)
406 line = actline;
407 if(newline)
409 line = line->next;
410 data->CPos_X = 0;
412 data->actualline = line;
414 else
416 switch(error)
418 case IFFERR_MANGLED:
419 case IFFERR_SYNTAX:
420 case IFFERR_NOTIFF:
421 D(DBF_CLIPBOARD, "no FTXT clip!");
422 DoMethod(data->object, MUIM_TextEditor_HandleError, Error_ClipboardIsNotFTXT);
423 break;
424 default:
425 D(DBF_CLIPBOARD, "clipboard is empty!");
426 DoMethod(data->object, MUIM_TextEditor_HandleError, Error_ClipboardIsEmpty);
427 break;
430 data->update = TRUE;
432 ScrollIntoDisplay(data);
433 updatefrom = LineToVisual(actline, data)-1;
434 if(updatefrom < 0)
435 updatefrom = 0;
436 DumpText(data->visual_y+updatefrom, updatefrom, data->maxlines, TRUE, data);
438 if(data->update)
439 res = TRUE;
440 else
441 data->update = TRUE;
444 EndClipSession(data);
447 RETURN(res);
448 return res;
450 /*--------------------------*
451 * Merge two lines into one *
452 *--------------------------*/
453 BOOL MergeLines(struct line_node *line, struct InstData *data)
455 struct line_node *next;
456 char *newbuffer;
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;
463 ENTER();
465 data->HasChanged = TRUE;
466 if(line->line.Length == 1)
468 emptyline = TRUE;
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;
494 else
496 UWORD *styles;
497 UWORD *styles1 = line->line.Styles;
498 UWORD *styles2 = line->next->line.Styles;
499 UWORD *colors;
500 UWORD *colors1 = line->line.Colors;
501 UWORD *colors2 = line->next->line.Colors;
502 UWORD length = 12;
504 if(styles1 != NULL)
505 length += *((long *)styles1-1) - 4;
506 if(styles2 != NULL)
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);
519 if(styles2 != NULL)
521 unsigned short* t_styles2 = styles2;
523 while(*t_styles2++ == 1)
525 if(*t_styles2 > 0xff)
526 style &= *t_styles2++;
527 else
528 style |= *t_styles2++;
532 if(styles1 != NULL)
534 while(*styles1 != EOS)
536 if((*styles1 == line->line.Length) && ((~*(styles1+1) & style) == (*(styles1+1) ^ 0xffff)))
538 style &= *(styles1+1);
539 styles1 += 2;
541 else
543 *styles++ = *styles1++;
544 *styles++ = *styles1++;
547 SHOWVALUE(DBF_CLIPBOARD, line->line.Styles);
548 MyFreePooled(data->mypool, line->line.Styles);
551 if(styles2 != NULL)
553 while(*styles2 != EOS)
555 if((*styles2 == 1) && (!(*(styles2+1) & style)))
557 styles2 += 2;
559 else
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);
568 *styles = EOS;
569 line->line.Styles = t_styles;
572 length = 12;
574 if(colors1 != NULL)
575 length += *((long *)colors1-1) - 4;
576 if(colors2 != NULL)
577 length += *((long *)colors2-1) - 4;
579 if((colors = MyAllocPooled(data->mypool, length)) != NULL)
581 UWORD *t_colors = colors;
582 UWORD end_color = 0;
584 SHOWVALUE(DBF_CLIPBOARD, length);
585 SHOWVALUE(DBF_CLIPBOARD, colors);
586 SHOWVALUE(DBF_CLIPBOARD, colors1);
587 SHOWVALUE(DBF_CLIPBOARD, colors2);
589 if(colors1 != NULL)
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;
604 *colors++ = 0;
607 if(colors2 != NULL)
609 if(*colors2 == 1 && *(colors2+1) == end_color)
610 colors2 += 2;
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);
620 *colors = 0xffff;
621 line->line.Colors = t_colors;
625 line->line.Contents = newbuffer;
626 line->line.Length = strlen(newbuffer);
628 next = line->next;
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);
656 else
657 DumpText(data->visual_y+line_nr-1, line_nr-1, data->maxlines, TRUE, data);
659 else
661 if(data->fastbackground)
662 ScrollUp(line_nr + line->visual - 1, 1, data);
663 else
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;
679 ULONG c = 0;
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)
690 data->visual_y--;
691 data->totallines -= 1;
693 if(data->fastbackground)
694 DumpText(data->visual_y, 0, visual-1, TRUE, data);
695 else
696 DumpText(data->visual_y, 0, data->maxlines, TRUE, data);
699 RETURN(TRUE);
700 return(TRUE);
702 else
704 RETURN(FALSE);
705 return(FALSE);
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;
715 struct pos_info pos;
716 LONG line_nr, lines;
717 ULONG c;
718 UWORD crsr_x = data->CPos_X;
719 struct line_node *crsr_l = data->actualline;
721 ENTER();
723 OffsetToLines(x, line, &pos, data);
724 lines = pos.lines;
726 next = line->next;
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;
739 if(buffer != NULL)
741 newline->line.Color = buffer->del.style;
742 newline->line.Flow = buffer->del.flow;
743 newline->line.Separator = buffer->del.separator;
746 if(styles != NULL)
748 LONG style = 0;
749 LONG length = 0;
750 UWORD *ostyles;
752 while(*styles++ <= x+1)
754 if(*styles > 0xff)
755 style &= *styles++;
756 else
757 style |= *styles++;
759 styles--;
760 ostyles = styles;
761 while(*(styles+length) != EOS)
762 length += 2;
763 length = (length*2) + 16;
765 if((newstyles = MyAllocPooled(data->mypool, length)) != NULL)
767 UWORD *nstyles = newstyles;
769 if(isFlagSet(style, BOLD))
771 *nstyles++ = 1;
772 *nstyles++ = BOLD;
774 if(isFlagSet(style, ITALIC))
776 *nstyles++ = 1;
777 *nstyles++ = ITALIC;
779 if(isFlagSet(style, UNDERLINE))
781 *nstyles++ = 1;
782 *nstyles++ = UNDERLINE;
785 while(*styles != EOS)
787 *nstyles++ = (*styles++) - x;
788 *nstyles++ = *styles++;
790 *nstyles = EOS;
793 if(isFlagSet(style, BOLD))
795 *ostyles++ = x+1;
796 *ostyles++ = ~BOLD;
798 if(isFlagSet(style, ITALIC))
800 *ostyles++ = x+1;
801 *ostyles++ = ~ITALIC;
803 if(isFlagSet(style, UNDERLINE))
805 *ostyles++ = x+1;
806 *ostyles++ = ~UNDERLINE;
808 if(x != 0)
809 ostyles = line->line.Styles;
810 *ostyles = EOS;
812 newline->line.Styles = newstyles;
814 if(colors != NULL)
816 UWORD color = GetColor(x, line);
817 UWORD length = 0;
818 UWORD *ocolors;
820 while(*colors <= x+1)
822 colors += 2;
824 ocolors = colors;
826 while(*(colors+length) != 0xffff)
827 length += 2;
828 length = (length*2) + 16;
830 if((newcolors = MyAllocPooled(data->mypool, length)) != NULL)
832 UWORD *ncolors = newcolors;
834 if(color && *colors-x != 1)
836 *ncolors++ = 1;
837 *ncolors++ = color;
840 while(*colors != 0xffff)
842 *ncolors++ = (*colors++) - x;
843 *ncolors++ = *colors++;
845 *ncolors = 0xffff;
847 if(x != 0)
848 ocolors = line->line.Colors;
849 *ocolors = 0xffff;
851 newline->line.Colors = newcolors;
854 newline->next = next;
855 if(next != NULL)
856 next->previous = newline;
858 *(line->line.Contents+x) = '\n';
859 *(line->line.Contents+x+1) = '\0';
860 line->line.Length = x+1;
862 /*------------------*/
863 c = line->visual;
864 line->visual = VisualHeight(line, data);
865 CompressLine(line, data);
867 line_nr = LineToVisual(line, data) + line->visual - 1;
868 if(line_nr < 0)
869 line_nr = 0;
871 if(move_crsr)
873 data->CPos_X = 0;
874 data->actualline = data->actualline->next;
877 if(x == 0)
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)
890 if(line_nr)
892 ScrollDown(line_nr-1, 1, data);
893 PrintLine(0, line, line_nr, FALSE, data);
895 else
897 ScrollDown(line_nr, 1, data);
900 else DumpText(data->visual_y+line_nr-1, line_nr-1, data->maxlines, TRUE, data);
902 else
904 data->visual_y++;
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);
924 RETURN(TRUE);
925 return(TRUE);
928 if(x == (LONG)(line->line.Length + newline->line.Length - 2))
930 data->totallines += 1;
931 if(buffer == NULL)
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);
948 RETURN(TRUE);
949 return(TRUE);
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);
966 else
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 /*------------------*/
977 line = line->next;
978 line_nr++;
979 c = 0;
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! */
984 RETURN(TRUE);
985 return (TRUE);
987 else
989 RETURN(FALSE);
990 return (FALSE);
993 /*------------------------------------------------------------------*
994 * Backwards string copy, please replace with some assembler stuff! *
995 *------------------------------------------------------------------*/
996 static void strcpyback(char *dest, char *src)
998 size_t length;
1000 ENTER();
1002 length = strlen(src)+1;
1003 dest = dest + length;
1004 src = src + length;
1006 length++;
1007 while(--length)
1008 *--dest = *--src;
1010 LEAVE();
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)
1018 ENTER();
1022 LONG twidth;
1024 twidth = PrintLine(x, line, line_nr, TRUE, data);
1025 line_nr++;
1027 if(twidth != width && x+twidth < (LONG)line->line.Length && line_nr <= data->maxlines)
1029 x += twidth;
1030 width = LineCharsWidth(line->line.Contents+x+width, data) + width - twidth;
1032 else
1033 break;
1035 while(TRUE);
1037 LEAVE();
1040 static void UpdateChange(LONG x, struct line_node *line, LONG length, const char *characters, struct UserAction *buffer, struct InstData *data)
1042 LONG diff;
1043 LONG skip=0;
1044 LONG line_nr;
1045 LONG orgline_nr;
1046 LONG width=0;
1047 LONG lineabove_width=0;
1049 ENTER();
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)
1058 break;
1060 width = LineCharsWidth(line->line.Contents + skip, data);
1061 if(width > 0 && skip + width < x)
1063 lineabove_width = width;
1064 skip += width;
1065 line_nr++;
1067 else
1068 break;
1070 while(TRUE);
1072 if(characters != NULL)
1074 strcpyback(line->line.Contents+x+length, line->line.Contents+x);
1075 memcpy(line->line.Contents+x, characters, length);
1076 width += length;
1077 line->line.Length += length;
1078 if(buffer != NULL)
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;
1089 else
1091 strlcpy(line->line.Contents+x, line->line.Contents+x+length, line->line.Length);
1092 width -= length;
1093 line->line.Length -= length;
1096 diff = VisualHeight(line, data) - line->visual;
1097 if(diff != 0)
1099 LONG movement;
1101 movement = orgline_nr + line->visual - 1;
1103 line->visual += diff;
1104 data->totallines += diff;
1106 if(diff > 0)
1108 if(movement < data->maxlines)
1109 ScrollDown(movement, diff, data);
1111 else
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))
1123 LONG newwidth;
1125 newwidth = PrintLine(skip-lineabove_width, line, line_nr-1, TRUE, data) - lineabove_width;
1126 skip += newwidth;
1127 width -= newwidth;
1128 if(skip >= (LONG)line->line.Length)
1130 LEAVE();
1131 return;
1136 OptimizedPrint(skip, line, line_nr, width, data);
1137 ScrollIntoDisplay(data);
1138 data->HasChanged = TRUE;
1140 LEAVE();
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)
1148 ENTER();
1150 if(line->line.Styles != NULL)
1152 if(*line->line.Styles != EOS)
1154 ULONG c = 0;
1156 while(*(line->line.Styles+c) <= x+1)
1157 c += 2;
1158 while(*(line->line.Styles+c) != EOS)
1160 *(line->line.Styles+c) += length;
1161 c += 2;
1166 if(line->line.Colors != NULL)
1168 if(*line->line.Colors != 0xffff)
1170 ULONG c = 0;
1172 while(*(line->line.Colors+c) <= x+1)
1173 c += 2;
1174 while(*(line->line.Colors+c) != 0xffff)
1176 *(line->line.Colors+c) += length;
1177 c += 2;
1182 if((*((long *)line->line.Contents-1))-4 < (LONG)(line->line.Length + length + 1))
1184 if(ExpandLine(line, length, data) == FALSE)
1186 RETURN(FALSE);
1187 return(FALSE);
1191 UpdateChange(x, line, length, characters, buffer, data);
1193 RETURN(TRUE);
1194 return(TRUE);
1196 /*----------------------------*
1197 * Remove n chars from a line *
1198 *----------------------------*/
1199 BOOL RemoveChars(LONG x, struct line_node *line, LONG length, struct InstData *data)
1201 ENTER();
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);
1209 ULONG c = 0, store;
1211 while(*(line->line.Styles+c) <= x)
1212 c += 2;
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;
1251 store = c;
1252 while(*(line->line.Styles+c) <= x+length+1)
1253 c += 2;
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);
1270 ULONG c = 0, store;
1272 while(*(line->line.Colors+c) <= x)
1273 c += 2;
1275 if(start_color != end_color)
1277 *(line->line.Colors+c++) = x+1;
1278 *(line->line.Colors+c++) = end_color;
1281 store = c;
1282 while(*(line->line.Colors+c) <= x+length+1)
1283 c += 2;
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);
1296 RETURN(TRUE);
1297 return(TRUE);