void ResizeUndoBuffer(struct InstData *data, ULONG level) { ENTER(); if(data->undolevel != level) { D(DBF_UNDO, "resizing undo buffer for %ld undo levels", level); if(data->undobuffer != NULL) { ResetUndoBuffer(data); MyFreePooled(data->mypool, data->undobuffer); } data->undobuffer = NULL; data->undopointer = NULL; data->undosize = 0; data->undofill = 0; data->undocur = 0; data->undolevel = level; if(level > 0) { ULONG newSize; // calculate number of bytes from number of undo levels newSize = (level * sizeof(struct UserAction)); // allocate a new undo buffer if((data->undobuffer = MyAllocPooled(data->mypool, newSize)) != NULL) { data->undopointer = data->undobuffer; data->undosize = newSize; } } } LEAVE(); }
/*---------------------* * Split line into two * *---------------------*/ BOOL SplitLine(LONG x, struct line_node *line, BOOL move_crsr, struct UserAction *buffer, struct InstData *data) { struct line_node *newline; struct line_node *next; struct pos_info pos; LONG line_nr, lines; ULONG c; UWORD crsr_x = data->CPos_X; struct line_node *crsr_l = data->actualline; ENTER(); OffsetToLines(x, line, &pos, data); lines = pos.lines; next = line->next; if((newline = AllocLine(data)) != NULL) { UWORD *styles = line->line.Styles; UWORD *newstyles = NULL; UWORD *colors = line->line.Colors; UWORD *newcolors = NULL; data->HasChanged = TRUE; Init_LineNode(newline, line, line->line.Contents+x, data); newline->line.Color = line->line.Color; newline->line.Flow = line->line.Flow; newline->line.Separator = line->line.Separator; if(buffer != NULL) { newline->line.Color = buffer->del.style; newline->line.Flow = buffer->del.flow; newline->line.Separator = buffer->del.separator; } if(styles != NULL) { LONG style = 0; LONG length = 0; UWORD *ostyles; while(*styles++ <= x+1) { if(*styles > 0xff) style &= *styles++; else style |= *styles++; } styles--; ostyles = styles; while(*(styles+length) != EOS) length += 2; length = (length*2) + 16; if((newstyles = MyAllocPooled(data->mypool, length)) != NULL) { UWORD *nstyles = newstyles; if(isFlagSet(style, BOLD)) { *nstyles++ = 1; *nstyles++ = BOLD; } if(isFlagSet(style, ITALIC)) { *nstyles++ = 1; *nstyles++ = ITALIC; } if(isFlagSet(style, UNDERLINE)) { *nstyles++ = 1; *nstyles++ = UNDERLINE; } while(*styles != EOS) { *nstyles++ = (*styles++) - x; *nstyles++ = *styles++; } *nstyles = EOS; } if(isFlagSet(style, BOLD)) { *ostyles++ = x+1; *ostyles++ = ~BOLD; } if(isFlagSet(style, ITALIC)) { *ostyles++ = x+1; *ostyles++ = ~ITALIC; } if(isFlagSet(style, UNDERLINE)) { *ostyles++ = x+1; *ostyles++ = ~UNDERLINE; } if(x != 0) ostyles = line->line.Styles; *ostyles = EOS; } newline->line.Styles = newstyles; if(colors != NULL) { UWORD color = GetColor(x, line); UWORD length = 0; UWORD *ocolors; while(*colors <= x+1) { colors += 2; } ocolors = colors; while(*(colors+length) != 0xffff) length += 2; length = (length*2) + 16; if((newcolors = MyAllocPooled(data->mypool, length)) != NULL) { UWORD *ncolors = newcolors; if(color && *colors-x != 1) { *ncolors++ = 1; *ncolors++ = color; } while(*colors != 0xffff) { *ncolors++ = (*colors++) - x; *ncolors++ = *colors++; } *ncolors = 0xffff; } if(x != 0) ocolors = line->line.Colors; *ocolors = 0xffff; } newline->line.Colors = newcolors; newline->next = next; if(next != NULL) next->previous = newline; *(line->line.Contents+x) = '\n'; *(line->line.Contents+x+1) = '\0'; line->line.Length = x+1; /*------------------*/ c = line->visual; line->visual = VisualHeight(line, data); CompressLine(line, data); line_nr = LineToVisual(line, data) + line->visual - 1; if(line_nr < 0) line_nr = 0; if(move_crsr) { data->CPos_X = 0; data->actualline = data->actualline->next; } if(x == 0) { line->line.Color = 0; line->line.Separator = 0; if(!(line->previous && line->previous->line.Flow == line->line.Flow)) { line->line.Flow = MUIV_TextEditor_Flow_Left; } if(line_nr != data->maxlines) { data->totallines += 1; if(data->fastbackground) { if(line_nr) { ScrollDown(line_nr-1, 1, data); PrintLine(0, line, line_nr, FALSE, data); } else { ScrollDown(line_nr, 1, data); } } else DumpText(data->visual_y+line_nr-1, line_nr-1, data->maxlines, TRUE, data); } else { data->visual_y++; data->totallines += 1; if(isFlagClear(data->flags, FLG_Quiet)) { struct Hook *oldhook; oldhook = InstallLayerHook(data->rport->Layer, LAYERS_NOBACKFILL); ScrollRasterBF(data->rport, 0, data->height, data->xpos, data->ypos, data->xpos + data->innerwidth - 1, (data->ypos + ((data->maxlines-1) * data->height)) - 1); InstallLayerHook(data->rport->Layer, oldhook); PrintLine(0, line, data->maxlines-1, FALSE, data); if(!data->fastbackground) { DumpText(data->visual_y+data->maxlines-1, data->maxlines-1, data->maxlines, TRUE, data); } } } RETURN(TRUE); return(TRUE); } if(x == (LONG)(line->line.Length + newline->line.Length - 2)) { data->totallines += 1; if(buffer == NULL) { line->next->line.Color = 0; line->next->line.Separator = 0; } SetCursor(crsr_x, crsr_l, FALSE, data); if(line_nr < data->maxlines) { if(data->fastbackground) { ScrollDown(line_nr, 1, data); if(line_nr+1 <= data->maxlines) PrintLine(0, line->next, line_nr+1, FALSE, data); } else DumpText(data->visual_y+line_nr, line_nr, data->maxlines, TRUE, data); } RETURN(TRUE); return(TRUE); } x = line->line.Length; OffsetToLines(x-1, line, &pos, data); if(((ULONG)(line->visual + line->next->visual) >= c) && (line->visual == lines)) { if((ULONG)(line->visual + line->next->visual) > c) data->totallines += 1; PrintLine(pos.bytes, line, line_nr, TRUE, data); if((line_nr+line->next->visual-1 < data->maxlines) && ((ULONG)(line->visual + line->next->visual) > c)) { ScrollDown(line_nr+line->next->visual-1, 1, data); } } else { PrintLine((x-1)-pos.x, line, line_nr, TRUE, data); if((line_nr < data->maxlines) && ((ULONG)(line->visual + line->next->visual) < c)) { data->totallines -= 1; ScrollUp(line_nr, 1, data); } } /*------------------*/ line = line->next; line_nr++; c = 0; while((c < line->line.Length) && (line_nr <= data->maxlines)) c = c + PrintLine(c, line, line_nr++, TRUE, data); /* Her printes !HELE! den nye linie, burde optimeres! */ RETURN(TRUE); return (TRUE); } else { RETURN(FALSE); return (FALSE); } }
/*--------------------------* * Merge two lines into one * *--------------------------*/ BOOL MergeLines(struct line_node *line, struct InstData *data) { struct line_node *next; char *newbuffer; LONG visual, oldvisual, line_nr; LONG emptyline = FALSE; LONG color = line->line.Color; UWORD flow = line->line.Flow; UWORD separator = line->line.Separator; ENTER(); data->HasChanged = TRUE; if(line->line.Length == 1) { emptyline = TRUE; color = line->next->line.Color; flow = line->next->line.Flow; separator = line->next->line.Separator; } visual = line->visual + line->next->visual; if((newbuffer = MyAllocPooled(data->mypool, line->line.Length+line->next->line.Length+1)) != NULL) { memcpy(newbuffer, line->line.Contents, line->line.Length-1); memcpy(newbuffer+line->line.Length-1, line->next->line.Contents, line->next->line.Length+1); MyFreePooled(data->mypool, line->line.Contents); MyFreePooled(data->mypool, line->next->line.Contents); if(emptyline == TRUE) { if(line->line.Styles != NULL) MyFreePooled(data->mypool, line->line.Styles); line->line.Styles = line->next->line.Styles; if(line->line.Colors != NULL) MyFreePooled(data->mypool, line->line.Colors); line->line.Colors = line->next->line.Colors; } else { UWORD *styles; UWORD *styles1 = line->line.Styles; UWORD *styles2 = line->next->line.Styles; UWORD *colors; UWORD *colors1 = line->line.Colors; UWORD *colors2 = line->next->line.Colors; UWORD length = 12; if(styles1 != NULL) length += *((long *)styles1-1) - 4; if(styles2 != NULL) length += *((long *)styles2-1) - 4; if((styles = MyAllocPooled(data->mypool, length)) != NULL) { unsigned short* t_styles = styles; unsigned short style = 0; SHOWVALUE(DBF_CLIPBOARD, length); SHOWVALUE(DBF_CLIPBOARD, styles); SHOWVALUE(DBF_CLIPBOARD, styles1); SHOWVALUE(DBF_CLIPBOARD, styles2); if(styles2 != NULL) { unsigned short* t_styles2 = styles2; while(*t_styles2++ == 1) { if(*t_styles2 > 0xff) style &= *t_styles2++; else style |= *t_styles2++; } } if(styles1 != NULL) { while(*styles1 != EOS) { if((*styles1 == line->line.Length) && ((~*(styles1+1) & style) == (*(styles1+1) ^ 0xffff))) { style &= *(styles1+1); styles1 += 2; } else { *styles++ = *styles1++; *styles++ = *styles1++; } } SHOWVALUE(DBF_CLIPBOARD, line->line.Styles); MyFreePooled(data->mypool, line->line.Styles); } if(styles2 != NULL) { while(*styles2 != EOS) { if((*styles2 == 1) && (!(*(styles2+1) & style))) { styles2 += 2; } else { *styles++ = *styles2++ + line->line.Length - 1; *styles++ = *styles2++; } } SHOWVALUE(DBF_CLIPBOARD, line->next->line.Styles); MyFreePooled(data->mypool, line->next->line.Styles); } *styles = EOS; line->line.Styles = t_styles; } length = 12; if(colors1 != NULL) length += *((long *)colors1-1) - 4; if(colors2 != NULL) length += *((long *)colors2-1) - 4; if((colors = MyAllocPooled(data->mypool, length)) != NULL) { UWORD *t_colors = colors; UWORD end_color = 0; SHOWVALUE(DBF_CLIPBOARD, length); SHOWVALUE(DBF_CLIPBOARD, colors); SHOWVALUE(DBF_CLIPBOARD, colors1); SHOWVALUE(DBF_CLIPBOARD, colors2); if(colors1 != NULL) { while(*colors1 < line->line.Length && *colors1 != 0xffff) { *colors++ = *colors1++; end_color = *colors1; *colors++ = *colors1++; } SHOWVALUE(DBF_CLIPBOARD, line->line.Colors); MyFreePooled(data->mypool, line->line.Colors); } if(end_color && (colors2 == NULL || *colors2 != 1)) { *colors++ = line->line.Length; *colors++ = 0; } if(colors2 != NULL) { if(*colors2 == 1 && *(colors2+1) == end_color) colors2 += 2; while(*colors2 != 0xffff) { *colors++ = *colors2++ + line->line.Length - 1; *colors++ = *colors2++; } SHOWVALUE(DBF_CLIPBOARD, line->next->line.Colors); MyFreePooled(data->mypool, line->next->line.Colors); } *colors = 0xffff; line->line.Colors = t_colors; } } line->line.Contents = newbuffer; line->line.Length = strlen(newbuffer); next = line->next; line->next = line->next->next; if(line->next != NULL) line->next->previous = line; oldvisual = line->visual; line->visual = VisualHeight(line, data); line->line.Color = color; line->line.Flow = flow; line->line.Separator = separator; FreeLine(next, data); line_nr = LineToVisual(line, data); // handle that we have to scroll up/down due to word wrapping // that occurrs when merging lines if(visual > line->visual) { data->totallines -= 1; if(line_nr+line->visual-1 < data->maxlines) { if(emptyline && line_nr > 0) { if(data->fastbackground) { ScrollUp(line_nr - 1, 1, data); SetCursor(data->CPos_X, data->actualline, TRUE, data); } else DumpText(data->visual_y+line_nr-1, line_nr-1, data->maxlines, TRUE, data); } else { if(data->fastbackground) ScrollUp(line_nr + line->visual - 1, 1, data); else DumpText(data->visual_y+line_nr+line->visual-1, line_nr+line->visual-1, data->maxlines, TRUE, data); } } } else if(visual < line->visual) { data->totallines += 1; if(line_nr+line->visual-1 < data->maxlines) ScrollDown(line_nr + line->visual - 2, 1, data); } if(!(emptyline && (line_nr + line->visual - 1 < data->maxlines))) { LONG t_oldvisual = oldvisual; LONG t_line_nr = line_nr; ULONG c = 0; while((--t_oldvisual) && (t_line_nr++ <= data->maxlines)) c = c + LineCharsWidth(line->line.Contents+c, data); while((c < line->line.Length) && (t_line_nr <= data->maxlines)) c = c + PrintLine(c, line, t_line_nr++, TRUE, data); } if(line_nr + oldvisual == 1 && line->visual == visual-1) { data->visual_y--; data->totallines -= 1; if(data->fastbackground) DumpText(data->visual_y, 0, visual-1, TRUE, data); else DumpText(data->visual_y, 0, data->maxlines, TRUE, data); } RETURN(TRUE); return(TRUE); } else { RETURN(FALSE); return(FALSE); } }
static char *utf8_to_ansi(struct InstData *data, STRPTR src) { static struct KeyMap *keymap; CONST_STRPTR ptr; STRPTR dst; ULONG octets, strlength; ENTER(); keymap = AskKeyMapDefault(); strlength = 0; ptr = src; do { WCHAR wc; UBYTE c; ptr += (octets = UTF8_Decode(ptr, &wc)); c = ToANSI(wc, keymap); strlength++; /* ToANSI() returns '?' if there is not matching code point in the current keymap */ if (c == '?' && wc != '?') { /* If direct conversion fails try compatibility decomposition (but without recursion) */ CONST_WSTRPTR p = UCS4_Decompose(wc); if (p) { while (p[1]) { strlength++; p++; } } } } while (octets > 0); dst = MyAllocPooled(data->mypool, strlength); if (dst) { STRPTR bufptr = dst; ptr = src; do { WCHAR wc; UBYTE c; ptr += (octets = UTF8_Decode(ptr, &wc)); c = ToANSI(wc, keymap); *bufptr++ = c; if (c == '?' && wc != '?') { CONST_WSTRPTR p = UCS4_Decompose(wc); if (p) { bufptr--; while (*p) { *bufptr++ = ToANSI(*p, keymap); p++; } } } } while (octets > 0); MyFreePooled(data->mypool, src); // Free original buffer } if(dst == NULL) dst = src; RETURN(dst); return dst; }
/*----------------------* * Paste from Clipboard * *----------------------*/ BOOL PasteClip (LONG x, struct line_node *actline, struct InstData *data) { struct line_node *line = NULL; struct line_node *startline = NULL; struct line_node *previous = NULL; UWORD *styles = NULL; UWORD *colors = NULL; STRPTR textline; BOOL newline = TRUE; BOOL res = FALSE; ENTER(); if(InitClipboard(data, IFFF_READ)) { if(StopChunk(data->iff, ID_FTXT, ID_CHRS) == 0 && StopChunk(data->iff, ID_FTXT, ID_FLOW) == 0 && StopChunk(data->iff, ID_FTXT, ID_HIGH) == 0 && StopChunk(data->iff, ID_FTXT, ID_SBAR) == 0 && StopChunk(data->iff, ID_FTXT, ID_COLS) == 0 && StopChunk(data->iff, ID_FTXT, ID_STYL) == 0 && StopChunk(data->iff, ID_FTXT, ID_CSET) == 0) { LONG error, codeset = 0; UWORD flow = MUIV_TextEditor_Flow_Left; UWORD color = FALSE; UWORD separator = 0; BOOL ownclip = FALSE; LONG updatefrom; while(TRUE) { struct ContextNode *cn; error = ParseIFF(data->iff, IFFPARSE_SCAN); SHOWVALUE(DBF_CLIPBOARD, error); if(error == IFFERR_EOC) continue; else if(error) break; if((cn = CurrentChunk(data->iff)) != NULL) { switch (cn->cn_ID) { case ID_CSET: D(DBF_CLIPBOARD, "reading FLOW"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); if(cn->cn_Size >= 4) { /* Only the first four bytes are interesting */ if(ReadChunkBytes(data->iff, &codeset, 4) != 4) { codeset = 0; } SHOWVALUE(DBF_CLIPBOARD, codeset); } break; case ID_FLOW: D(DBF_CLIPBOARD, "reading FLOW"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); if(cn->cn_Size == 2) { if(ReadChunkBytes(data->iff, &flow, 2) == 2) if(flow > MUIV_TextEditor_Flow_Right) flow = MUIV_TextEditor_Flow_Left; SHOWVALUE(DBF_CLIPBOARD, flow); } break; case ID_HIGH: D(DBF_CLIPBOARD, "reading HIGH"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); if (cn->cn_Size == 2) { error = ReadChunkBytes(data->iff, &color, 2); SHOWVALUE(DBF_CLIPBOARD, color); SHOWVALUE(DBF_CLIPBOARD, error); } break; case ID_SBAR: D(DBF_CLIPBOARD, "reading SBAR"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); if (cn->cn_Size == 2) { error = ReadChunkBytes(data->iff, &separator, 2); SHOWVALUE(DBF_CLIPBOARD, separator); SHOWVALUE(DBF_CLIPBOARD, error); } break; case ID_COLS: D(DBF_CLIPBOARD, "reading COLS"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); if(colors) { MyFreePooled(data->mypool, colors); colors = NULL; } // allocate one word more than the chunk tell us, because we terminate the array with an additional value if(cn->cn_Size > 0 && (colors = (UWORD *)MyAllocPooled(data->mypool, cn->cn_Size + sizeof(UWORD))) != NULL) { error = ReadChunkBytes(data->iff, colors, cn->cn_Size); SHOWVALUE(DBF_CLIPBOARD, error); colors[cn->cn_Size / 2] = 0xffff; } break; case ID_STYL: D(DBF_CLIPBOARD, "reading STYL"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); ownclip = TRUE; if(styles) { MyFreePooled(data->mypool, styles); styles = NULL; } // allocate one word more than the chunk tell us, because we terminate the array with an additional value if(cn->cn_Size > 0 && (styles = (UWORD *)MyAllocPooled(data->mypool, cn->cn_Size + sizeof(UWORD))) != NULL) { error = ReadChunkBytes(data->iff, styles, cn->cn_Size); SHOWVALUE(DBF_CLIPBOARD, error); styles[cn->cn_Size / 2] = EOS; } break; case ID_CHRS: { D(DBF_CLIPBOARD, "reading CHRS"); SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size); data->HasChanged = TRUE; if(cn->cn_Size > 0 && !ownclip) { char *contents; ULONG length = cn->cn_Size; if((contents = (char *)MyAllocPooled(data->mypool, length + 1)) != NULL) { error = ReadChunkBytes(data->iff, contents, length); SHOWVALUE(DBF_CLIPBOARD, error); if(contents[length - 1] != '\n') { newline = FALSE; } else { length--; } contents[length] = '\0'; #if defined(__MORPHOS__) if (codeset == CODESET_UTF8) { if (IS_MORPHOS2) contents = utf8_to_ansi(data, contents); } #endif if((line = ImportText(contents, data, &ImPlainHook, data->ImportWrap))) { if(!startline) startline = line; if(previous) previous->next = line; line->previous = previous; line->visual = VisualHeight(line, data); data->totallines += line->visual; while(line->next) { line = line->next; line->visual = VisualHeight(line, data); data->totallines += line->visual; } previous = line; } MyFreePooled(data->mypool, contents); } } else { ULONG length = cn->cn_Size; if(length > 0 && (textline = (char *)MyAllocPooled(data->mypool, length + 2)) != NULL) { error = ReadChunkBytes(data->iff, textline, length); SHOWVALUE(DBF_CLIPBOARD, error); if (textline[length - 1] != '\n') { newline = FALSE; textline[length] = '\n'; length++; } textline[length] = '\0'; if((line = AllocLine(data))) { line->next = NULL; line->previous = previous; line->line.Contents = textline; line->line.Length = length; line->visual = VisualHeight(line, data); line->line.Color = color; line->line.Flow = flow; line->line.Separator = separator; line->line.Styles = styles; line->line.Colors = colors; data->totallines += line->visual; if(!startline) startline = line; if(previous) previous->next = line; previous = line; } else { if(styles) MyFreePooled(data->mypool, (void *)styles); if(colors) MyFreePooled(data->mypool, (void *)colors); } } else { if(styles) MyFreePooled(data->mypool, styles); if(colors) MyFreePooled(data->mypool, (void *)colors); } styles = NULL; colors = NULL; flow = MUIV_TextEditor_Flow_Left; color = FALSE; separator = 0; ownclip = FALSE; } } break; } } } if(line) { BOOL oneline = FALSE; SplitLine(x, actline, FALSE, NULL, data); line->next = actline->next; actline->next->previous = line; actline->next = startline; startline->previous = actline; data->CPos_X = line->line.Length-1; if(actline->next == line) { data->CPos_X += actline->line.Length-1; oneline = TRUE; } if(!newline) MergeLines(line, data); MergeLines(actline, data); if(oneline) line = actline; if(newline) { line = line->next; data->CPos_X = 0; } data->actualline = line; } else { switch(error) { case IFFERR_MANGLED: case IFFERR_SYNTAX: case IFFERR_NOTIFF: D(DBF_CLIPBOARD, "no FTXT clip!"); DoMethod(data->object, MUIM_TextEditor_HandleError, Error_ClipboardIsNotFTXT); break; default: D(DBF_CLIPBOARD, "clipboard is empty!"); DoMethod(data->object, MUIM_TextEditor_HandleError, Error_ClipboardIsEmpty); break; } } data->update = TRUE; ScrollIntoDisplay(data); updatefrom = LineToVisual(actline, data)-1; if(updatefrom < 0) updatefrom = 0; DumpText(data->visual_y+updatefrom, updatefrom, data->maxlines, TRUE, data); if(data->update) res = TRUE; else data->update = TRUE; } EndClipSession(data); } RETURN(res); return res; }
char *GetBlock(struct marking *block, struct InstData *data) { LONG startx, stopx; struct line_node *startline, *stopline, *act; char *text = NULL; struct ExportMessage emsg; ENTER(); startx = block->startx; stopx = block->stopx; startline = block->startline; stopline = block->stopline; data->CPos_X = startx; data->actualline = startline; // clear the export message memset(&emsg, 0, sizeof(struct ExportMessage)); // fill it afterwards emsg.UserData = NULL; emsg.ExportWrap = 0; emsg.Last = FALSE; emsg.data = data; if(startline != stopline) { /* Create a firstline look-a-like */ emsg.Contents = (STRPTR)MyAllocPooled(data->mypool, startline->line.Length-startx); if(startline->line.Styles && *startline->line.Styles != EOS) { ULONG startstyle = GetStyle(startx, startline); if((emsg.Styles = (UWORD *)MyAllocPooled(data->mypool, *((ULONG *)startline->line.Styles-1)+16))) { UWORD *styles = emsg.Styles, *oldstyles = startline->line.Styles; if(startstyle & BOLD) { *styles++ = 1; *styles++ = BOLD; } if(startstyle & ITALIC) { *styles++ = 1; *styles++ = ITALIC; } if(startstyle & UNDERLINE) { *styles++ = 1; *styles++ = UNDERLINE; } while(*oldstyles <= startx) oldstyles += 2; while(*oldstyles != EOS) { *styles++ = *oldstyles++ - startx; *styles++ = *oldstyles++; } *styles = EOS; } } else emsg.Styles = NULL; emsg.Colors = NULL; if(emsg.Contents) { memcpy(emsg.Contents, startline->line.Contents + startx, startline->line.Length - startx); emsg.Length = startline->line.Length - startx; emsg.Flow = startline->line.Flow; emsg.Separator = startline->line.Separator; emsg.Highlight = startline->line.Color; emsg.UserData = (APTR)CallHookA(&ExportHookPlain, NULL, &emsg); MyFreePooled(data->mypool, emsg.Contents); } if(emsg.Styles) MyFreePooled(data->mypool, emsg.Styles); /* Start iterating... */ act = startline->next; while(act != stopline) { emsg.Contents = act->line.Contents; emsg.Length = act->line.Length; emsg.Styles = act->line.Styles; emsg.Colors = act->line.Colors; emsg.Flow = act->line.Flow; emsg.Separator = act->line.Separator; emsg.Highlight = act->line.Color; emsg.UserData = (APTR)CallHookA(&ExportHookPlain, (APTR)NULL, &emsg); act = act->next; } /* Create a Lastline look-a-like */ emsg.Contents = (STRPTR)MyAllocPooled(data->mypool, stopx); if(stopline->line.Styles && *stopline->line.Styles != EOS) { ULONG stopstyle = GetStyle(stopx, stopline); if((emsg.Styles = (UWORD *)MyAllocPooled(data->mypool, *((ULONG *)stopline->line.Styles-1)+16))) { UWORD *styles = emsg.Styles, *oldstyles = stopline->line.Styles; while(*oldstyles <= stopx) { *styles++ = *oldstyles++; *styles++ = *oldstyles++; } if(stopstyle & BOLD) { *styles++ = stopx+1; *styles++ = ~BOLD; } if(stopstyle & ITALIC) { *styles++ = stopx+1; *styles++ = ~ITALIC; } if(stopstyle & UNDERLINE) { *styles++ = stopx+1; *styles++ = ~UNDERLINE; } *styles = EOS; } } else emsg.Styles = NULL; emsg.Colors = NULL; if(emsg.Contents) { memcpy(emsg.Contents, stopline->line.Contents, stopx); emsg.Length = stopx; emsg.Flow = stopline->line.Flow; emsg.Separator = stopline->line.Separator; emsg.Highlight = stopline->line.Color; emsg.Last = TRUE; text = (STRPTR)CallHookA(&ExportHookPlain, NULL, &emsg); MyFreePooled(data->mypool, emsg.Contents); } if(emsg.Styles) MyFreePooled(data->mypool, emsg.Styles); } else { /* Create a single line */ emsg.Contents = (STRPTR)MyAllocPooled(data->mypool, stopx-startx); if(startline->line.Styles && *startline->line.Styles != EOS) { ULONG startstyle = GetStyle(startx, startline); ULONG stopstyle = GetStyle(stopx, stopline); if((emsg.Styles = (UWORD *)MyAllocPooled(data->mypool, *((ULONG *)startline->line.Styles-1)))) { UWORD *styles = emsg.Styles, *oldstyles = startline->line.Styles; if(startstyle & BOLD) { *styles++ = 1; *styles++ = BOLD; } if(startstyle & ITALIC) { *styles++ = 1; *styles++ = ITALIC; } if(startstyle & UNDERLINE) { *styles++ = 1; *styles++ = UNDERLINE; } while(*oldstyles <= startx) oldstyles += 2; while(*oldstyles <= stopx) { *styles++ = *oldstyles++ - startx; *styles++ = *oldstyles++; } if(stopstyle & BOLD) { *styles++ = stopx-startx+1; *styles++ = ~BOLD; } if(stopstyle & ITALIC) { *styles++ = stopx-startx+1; *styles++ = ~ITALIC; } if(stopstyle & UNDERLINE) { *styles++ = stopx-startx+1; *styles++ = ~UNDERLINE; } *styles = EOS; } } else emsg.Styles = NULL; emsg.Colors = NULL; if(emsg.Contents) { memcpy(emsg.Contents, startline->line.Contents+startx, stopx-startx); emsg.Length = stopx-startx; emsg.Flow = startline->line.Flow; emsg.Separator = startline->line.Separator; emsg.Highlight = startline->line.Color; emsg.Last = TRUE; text = (STRPTR)CallHookA(&ExportHookPlain, NULL, &emsg); MyFreePooled(data->mypool, emsg.Contents); } if(emsg.Styles) MyFreePooled(data->mypool, emsg.Styles); } RETURN(text); return(text); }
HOOKPROTONO(ExportHookFunc, STRPTR, struct ExportMessage *emsg) { struct Buffer *buf = emsg->UserData; LONG length; UWORD *styles = emsg->Styles; UWORD *colors = emsg->Colors; UWORD lastpos = 0; UWORD currentstyle = 0; STRPTR result = NULL; STRPTR startx; struct InstData *data = emsg->data; LONG expand; ULONG hookType = (ULONG)hook->h_Data; ENTER(); if(buf == NULL) { if(data != NULL) { buf = MyAllocPooled(data->mypool, sizeof(struct Buffer)); if(buf != NULL) { buf->buffer = MyAllocPooled(data->mypool, 512); buf->size = 512; } } else { buf = AllocVec(sizeof(struct Buffer), MEMF_SHARED|MEMF_CLEAR); if(buf != NULL) { buf->buffer = AllocVec(1024, MEMF_SHARED|MEMF_CLEAR); buf->size = 1024; } } if(buf != NULL) { buf->pointer = buf->buffer; buf->flow = 0; } } if(buf != NULL && buf->buffer != NULL) { expand = 10*emsg->Length; if(buf->buffer+buf->size < buf->pointer+expand) { STRPTR oldbuf = buf->buffer; ULONG oldsize = buf->size; ULONG offset = buf->pointer - oldbuf; if(data) { buf->buffer = MyAllocPooled(data->mypool, oldsize+expand+512); buf->size = oldsize+expand+512; } else { buf->buffer = AllocVec(oldsize+expand+1024, MEMF_SHARED|MEMF_CLEAR); buf->size = oldsize+expand+1024; } buf->pointer = buf->buffer+offset; memcpy(buf->buffer, oldbuf, offset); if(data) MyFreePooled(data->mypool, oldbuf); else FreeVec(oldbuf); } // if this hook is of plain type we have consider highlighting as well. if(emsg->Highlight && hookType == MUIV_TextEditor_ExportHook_Plain) { *buf->pointer++ = '\033'; *buf->pointer++ = 'h'; } if(hookType == MUIV_TextEditor_ExportHook_Plain && emsg->Flow != buf->flow) { *buf->pointer++ = '\033'; switch(emsg->Flow) { case MUIV_TextEditor_Flow_Right: *buf->pointer++ = 'r'; break; case MUIV_TextEditor_Flow_Center: *buf->pointer++ = 'c'; break; case MUIV_TextEditor_Flow_Left: default: *buf->pointer++ = 'l'; } buf->flow = emsg->Flow; } if(emsg->Separator) { if(hookType == MUIV_TextEditor_ExportHook_Plain) snprintf(buf->pointer, buf->size-(buf->pointer-buf->buffer), "\033[s:%d]", emsg->Separator); else strlcpy(buf->pointer, ((emsg->Separator & LNSF_Thick) ? "<tsb>" : "<sb>"), buf->size-(buf->pointer-buf->buffer)); buf->pointer += strlen(buf->pointer); } // define some start values. startx = buf->pointer; length = emsg->Length-emsg->SkipFront-emsg->SkipBack; lastpos = emsg->SkipFront; if((styles || colors) && (hookType == MUIV_TextEditor_ExportHook_EMail || hookType == MUIV_TextEditor_ExportHook_Plain)) { UWORD pos; WORD style; BOOL coloured = FALSE; UWORD colour_state = 7; while(length > 0 && ((styles && *styles != 0xffff) || (colors && *colors != 0xffff))) { BOOL color; LONG len; if(colors == NULL || (styles && (coloured ? *styles < *colors : *styles <= *colors))) { pos = *styles++ - 1; style = *styles++; color = FALSE; } else { pos = *colors++ - 1; style = *colors++; color = TRUE; } // skip styles&colors which below lastpos if(pos < lastpos) continue; // depending on how much we export // we have to fire up the style convert routines. if(pos-lastpos <= length) { len = pos-lastpos; memcpy(buf->pointer, emsg->Contents+lastpos, len); buf->pointer += len; if(hookType == MUIV_TextEditor_ExportHook_EMail) { if(color) { if((coloured = (style == colour_state ? TRUE : FALSE))) { *buf->pointer++ = '#'; colour_state ^= 7; } } else { switch(style) { case UNDERLINE: case ~UNDERLINE: { *buf->pointer++ = '_'; } break; case BOLD: case ~BOLD: { *buf->pointer++ = '*'; } break; case ITALIC: case ~ITALIC: { *buf->pointer++ = '/'; } break; } } } else if(hookType == MUIV_TextEditor_ExportHook_Plain) { if(color) { snprintf(buf->pointer, buf->size-(buf->pointer-buf->buffer), "\033p[%d]", style); buf->pointer += strlen(buf->pointer); } else { switch(style) { case UNDERLINE: { *buf->pointer++ = '\033'; *buf->pointer++ = 'u'; currentstyle |= UNDERLINE; } break; case BOLD: { *buf->pointer++ = '\033'; *buf->pointer++ = 'b'; currentstyle |= BOLD; } break; case ITALIC: { *buf->pointer++ = '\033'; *buf->pointer++ = 'i'; currentstyle |= ITALIC; } break; case ~UNDERLINE: case ~BOLD: case ~ITALIC: { currentstyle &= style; if(pos+1 != *styles || *(styles+1) < 0x8000) { *buf->pointer++ = '\033'; *buf->pointer++ = 'n'; if(currentstyle & UNDERLINE) { *buf->pointer++ = '\033'; *buf->pointer++ = 'u'; } if(currentstyle & BOLD) { *buf->pointer++ = '\033'; *buf->pointer++ = 'b'; } if(currentstyle & ITALIC) { *buf->pointer++ = '\033'; *buf->pointer++ = 'i'; } } } break; } } } } else { len = length; memcpy(buf->pointer, emsg->Contents+lastpos, len); buf->pointer += len; } length -= len; if(length == -1) length = 0; lastpos = pos; } } if(length > 0) { memcpy(buf->pointer, emsg->Contents+lastpos, length); buf->pointer += length; } // NUL terminate our buffer string *buf->pointer = '\0'; while(emsg->ExportWrap && buf->pointer-startx > (LONG)emsg->ExportWrap) { ULONG max = emsg->ExportWrap+1; if(startx[emsg->ExportWrap] != '\n') { while(--max && *(startx+max) != ' ') ; // empty while } if(max) { *(startx += max) = '\n'; } else { while(++startx < buf->pointer && *(startx) != ' ') ; // empty while if(buf->pointer != startx) { *startx = '\n'; } } } if(emsg->Last) { result = buf->buffer; if(data) { MyFreePooled(data->mypool, buf); } else { FreeVec(buf); } } else { result = (STRPTR)buf; } } RETURN(result); return(result); }