Example #1
0
void ResetUndoBuffer(struct InstData *data)
{
    ENTER();

    if(data->undosize != 0)
    {
        struct UserAction *buffer = (struct UserAction *)data->undobuffer;

        while(data->undocur > 0)
        {
            if(buffer->type == ET_DELETEBLOCK)
                MyFreePooled(data->mypool, buffer->clip);

            buffer++;
            data->undocur--;
            data->undofill--;
        }

        while(data->undofill > 0)
        {
            if(buffer->type == ET_PASTEBLOCK)
                MyFreePooled(data->mypool, buffer->clip);

            buffer++;
            data->undofill--;
        }

        data->undopointer = data->undobuffer;

        ASSERT(data->undocur == 0);
        ASSERT(data->undofill == 0);
    }

    LEAVE();
}
Example #2
0
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();
}
Example #3
0
long Undo(struct InstData *data)
{
    ENTER();

    D(DBF_UNDO, "undolevel: %ld undocur: %ld undofill: %ld", data->undolevel, data->undocur, data->undofill);

    // check if there is something in the undo
    // buffer available
    if(data->undolevel > 0 && data->undocur > 0)
    {
        struct UserAction *buffer;
        BOOL  crsr_move = TRUE;

        if(Enabled(data))
        {
            data->blockinfo.enabled = FALSE;
            MarkText(data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline, data);
        }

        // as the redo operation automatically
        // becomes available when undo is used we just
        // check here if we didn't yet set RedoAvailable
        // as we only want to set it once
        if(data->undocur == data->undofill)
            set(data->object, MUIA_TextEditor_RedoAvailable, TRUE);

        data->undopointer = (APTR)((char *)data->undopointer - sizeof(struct UserAction));
        data->undocur--;
        buffer = (struct UserAction *)data->undopointer;

//    if(data->actualline != LineNode(buffer->y, data) || data->CPos_X != buffer->x)
        SetCursor(data->CPos_X, data->actualline, FALSE, data);

        data->CPos_X = buffer->x;
        data->actualline = LineNode(buffer->y, data);
        ScrollIntoDisplay(data);

        switch(buffer->type)
        {
        case ET_PASTECHAR:
        {
            buffer->del.character = *(data->actualline->line.Contents+data->CPos_X);
            buffer->del.style = GetStyle(data->CPos_X, data->actualline);
            buffer->del.flow = data->actualline->line.Flow;
            buffer->del.separator = data->actualline->line.Separator;
            RemoveChars(data->CPos_X, data->actualline, 1, data);
        }
        break;

        case ET_BACKSPACECHAR:
        {
            PasteChars(data->CPos_X++, data->actualline, 1, (char *)&buffer->del.character, buffer, data);
        }
        break;

        case ET_DELETECHAR:
        {
            PasteChars(data->CPos_X, data->actualline, 1, (char *)&buffer->del.character, buffer, data);
        }
        break;

        case ET_SPLITLINE:
        {
            MergeLines(data->actualline, data);
        }
        break;

        case ET_MERGELINES:
        {
            SplitLine(data->CPos_X, data->actualline, FALSE, buffer, data);
        }
        break;

        case ET_BACKSPACEMERGE:
        {
            SplitLine(data->CPos_X, data->actualline, TRUE, buffer, data);
        }
        break;

        case ET_PASTEBLOCK:
        {
            struct marking block =
            {
                TRUE,
                LineNode(buffer->y, data),
                buffer->x,
                LineNode(buffer->blk.y, data),
                buffer->blk.x
            };
            char *clip = GetBlock(&block, data);

            CutBlock2(data, FALSE, FALSE, &block, TRUE);
            buffer->clip = (unsigned char *)clip;
        }
        break;

        case ET_DELETEBLOCK_NOMOVE:
            crsr_move = FALSE;
        // continue

        case ET_DELETEBLOCK:
        {
            struct Hook *oldhook = data->ImportHook;
            char *clip = (char *)buffer->clip;

            data->ImportHook = &ImPlainHook;
            InsertText(data, clip, crsr_move);
            data->ImportHook = oldhook;
            MyFreePooled(data->mypool, clip);

            buffer->blk.x = data->CPos_X;
            buffer->blk.y = LineNr(data->actualline, data);

            if(!crsr_move)
            {
                data->CPos_X = buffer->x;
                data->actualline = LineNode(buffer->y, data);
            }
        }
        break;

        default:
            // nothing to do
            break;
        }

        ScrollIntoDisplay(data);

        if(data->flags & FLG_Active)
            SetCursor(data->CPos_X, data->actualline, TRUE, data);

        // if there are no further undo levels we
        // have to set UndoAvailable to FALSE
        if(data->undocur == 0)
        {
            set(data->object, MUIA_TextEditor_UndoAvailable, FALSE);

            if(!(data->flags & FLG_UndoLost))
                data->HasChanged = FALSE;
        }

        RETURN(TRUE);
        return(TRUE);
    }
    else
    {
        DoMethod(data->object, MUIM_TextEditor_HandleError, Error_NothingToUndo);

        RETURN(FALSE);
        return(FALSE);
    }
}
Example #4
0
long AddToUndoBuffer(enum EventType eventtype, char *eventdata, struct InstData *data)
{
    ENTER();

    D(DBF_UNDO, "undolevel: %ld undocur: %ld undofill: %ld", data->undolevel, data->undocur, data->undofill);

    if(data->undolevel > 0)
    {
        struct UserAction *buffer;

        // check if there is still enough space in our undo buffer
        // and if not we clean it up a bit (10 entries)
        if(data->undofill+1 > data->undolevel)
        {
            ULONG c;
            char *t_undobuffer = (char *)data->undobuffer;

            // cleanup at most the first 10 entries in our undobuffer
            for(c=0; c < 10 && data->undofill > 0; c++)
            {
                struct UserAction *t_buffer = (struct UserAction *)t_undobuffer;

                if(t_buffer->type == ET_DELETEBLOCK)
                    MyFreePooled(data->mypool, t_buffer->clip);

                t_undobuffer += sizeof(struct UserAction);

                data->undocur--;
                data->undofill--;
            }

            D(DBF_UNDO, "undobuffer was filled up, cleaned up the first %ld entries", c+1);

            if(data->undofill > 0)
            {
                // copy everything from t_undobuffer to our start of the
                // undobuffer and set the undopointer accordingly.
                memcpy(data->undobuffer, t_undobuffer, data->undosize-(t_undobuffer-(char *)data->undobuffer));
                data->undopointer = (APTR)(t_undobuffer - (char *)data->undopointer);
            }

            // signal the user that something in the
            // undo buffer was lost.
            data->flags |= FLG_UndoLost;
        }

        buffer = data->undopointer;

        // as we are about to set something new for an undo
        // operation we have to signal that redo operation
        // is cleared now.
        if(data->undocur < data->undofill)
        {
            char *t_undobuffer = (char *)data->undopointer;

            D(DBF_UNDO, "cleaning up %ld dropped undo nodes", data->undofill-data->undocur);

            // we have to first cleanup each buffer of the ET_PASTEBLOCK
            // event or otherwise we lost some memory.
            while(data->undofill > data->undocur)
            {
                struct UserAction *t_buffer = (struct UserAction *)t_undobuffer;

                if(t_buffer->type == ET_PASTEBLOCK)
                {
                    D(DBF_UNDO, "cleaning uf paste buffer of user action %08lx", t_buffer);
                    MyFreePooled(data->mypool, t_buffer->clip);
                }

                t_undobuffer += sizeof(struct UserAction);
                data->undofill--;
            }

            set(data->object, MUIA_TextEditor_RedoAvailable, FALSE);
        }

        // if undocur is zero we have to send the undoavailable
        // signal
        if(data->undocur == 0)
            set(data->object, MUIA_TextEditor_UndoAvailable, TRUE);

        data->undopointer = (APTR)((char *)data->undopointer + sizeof(struct UserAction));
        data->undocur++;
        data->undofill = data->undocur;

        buffer->x  = data->CPos_X;
        buffer->y  = LineNr(data->actualline, data);
        buffer->type = eventtype;

        switch(eventtype)
        {
        case ET_BACKSPACEMERGE:
        case ET_MERGELINES:
        {
            buffer->del.style = data->actualline->next->line.Color;
            buffer->del.flow = data->actualline->next->line.Flow;
            buffer->del.separator = data->actualline->next->line.Separator;
        }
        break;

        case ET_DELETECHAR:
        case ET_BACKSPACECHAR:
        {
            buffer->del.character = *eventdata;
            buffer->del.style = GetStyle(data->CPos_X, data->actualline);
            buffer->del.flow = data->actualline->line.Flow;
            buffer->del.separator = data->actualline->line.Separator;
        }
        break;

        case ET_PASTEBLOCK:
        {
            struct marking *block = (struct marking *)eventdata;

            buffer->x  = block->startx;
            buffer->y  = LineNr(block->startline, data);
            buffer->blk.x = block->stopx;
            buffer->blk.y = LineNr(block->stopline, data);
        }
        break;

        case ET_DELETEBLOCK:
        {
            char *text;
            struct marking *block = (struct marking *)eventdata;

            if((text = GetBlock((struct marking *)eventdata, data)))
            {
                buffer->x = block->startx;
                buffer->y = LineNr(block->startline, data);
                buffer->clip = (unsigned char *)text;

                if(data->flags & FLG_FreezeCrsr)
                    buffer->type = ET_DELETEBLOCK_NOMOVE;
            }
            else
            {
                ResetUndoBuffer(data);
                DoMethod(data->object, MUIM_TextEditor_HandleError, Error_NotEnoughUndoMem);
            }
        }
        break;

        default:
            // nothing to do
            break;
        }
    }

    RETURN(TRUE);
    return(TRUE);
}
Example #5
0
/*--------------------------*
 * 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);
  }
}
Example #6
0
long Redo(struct InstData *data)
{
    ENTER();

    D(DBF_UNDO, "undolevel: %ld undocur: %ld undofill: %ld", data->undolevel, data->undocur, data->undofill);

    // check if there something to redo at all
    if(data->undofill > 0 && data->undocur < data->undofill)
    {
        struct UserAction *buffer = (struct UserAction *)data->undopointer;

        if(Enabled(data))
        {
            data->blockinfo.enabled = FALSE;
            MarkText(data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline, data);
        }

        // in case undocur is equal zero then we have to
        // set the undoavailable attribute to true to signal
        // others that undo is available
        if(data->undocur == 0)
            set(data->object, MUIA_TextEditor_UndoAvailable, TRUE);

        data->undopointer = (APTR)((char *)data->undopointer + sizeof(struct UserAction));
        data->undocur++;

//    if(data->actualline != LineNode(buffer->y, data) || data->CPos_X != buffer->x)
        SetCursor(data->CPos_X, data->actualline, FALSE, data);
        data->CPos_X = buffer->x;
        data->actualline = LineNode(buffer->y, data);
        ScrollIntoDisplay(data);

        switch(buffer->type)
        {
        case ET_PASTECHAR:
            PasteChars(data->CPos_X++, data->actualline, 1, (char *)&buffer->del.character, buffer, data);
            break;

        case ET_BACKSPACECHAR:
        case ET_DELETECHAR:
            RemoveChars(data->CPos_X, data->actualline, 1, data);
            break;

        case ET_SPLITLINE:
            SplitLine(data->CPos_X, data->actualline, TRUE, NULL, data);
            break;

        case ET_MERGELINES:
        case ET_BACKSPACEMERGE:
            MergeLines(data->actualline, data);
            break;

        case ET_PASTEBLOCK:
        {
            struct Hook *oldhook = data->ImportHook;

            data->ImportHook = &ImPlainHook;
            InsertText(data, (char *)buffer->clip, TRUE);
            data->ImportHook = oldhook;
            MyFreePooled(data->mypool, buffer->clip);

            buffer->blk.x = data->CPos_X;
            buffer->blk.y = LineNr(data->actualline, data);
        }
        break;

        case ET_DELETEBLOCK_NOMOVE:
        case ET_DELETEBLOCK:
        {
            struct marking block =
            {
                TRUE,
                LineNode(buffer->y, data),
                buffer->x,
                LineNode(buffer->blk.y, data),
                buffer->blk.x
            };
            char  *clip = GetBlock(&block, data);

            CutBlock2(data, FALSE, FALSE, &block, TRUE);
            buffer->clip = (unsigned char *)clip;
        }
        break;

        default:
            // nothing to do
            break;
        }

        ScrollIntoDisplay(data);

        if(data->flags & FLG_Active)
            SetCursor(data->CPos_X, data->actualline, TRUE, data);

        // if undocur == undofill this signals that we
        // don't have any things to redo anymore.
        if(data->undocur == data->undofill)
            set(data->object, MUIA_TextEditor_RedoAvailable, FALSE);

        RETURN(TRUE);
        return(TRUE);
    }
    else
    {
        DoMethod(data->object, MUIM_TextEditor_HandleError, Error_NothingToRedo);

        RETURN(FALSE);
        return(FALSE);
    }
}
Example #7
0
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;
}
Example #8
0
/*----------------------*
 * 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;
}
Example #9
0
LONG CutBlock2(struct InstData *data, BOOL Clipboard, BOOL NoCut, struct marking *newblock, BOOL update)
{
  LONG  tvisual_y, error;
  LONG  startx, stopx;
  LONG  res = 0;
  struct  line_node *startline, *stopline;

  ENTER();

  startx    = newblock->startx;
  stopx     = newblock->stopx;
  startline = newblock->startline;
  stopline  = newblock->stopline;

  //D(DBF_STARTUP, "CutBlock2: %ld-%ld %lx-%lx %ld %ld", startx, stopx, startline, stopline, Clipboard, NoCut);

  if(startline != stopline)
  {
    struct line_node *c_startline = startline->next;

    data->update = FALSE;

    if(Clipboard == TRUE)
    {
      if(InitClipboard(data, IFFF_WRITE))
      {
        D(DBF_CLIPBOARD, "writing FORM");
        error = PushChunk(data->iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
        SHOWVALUE(DBF_CLIPBOARD, error);

        ClipChars(startx, startline, startline->line.Length-startx, data);
      }
      else
      {
        Clipboard = FALSE;
      }
    }

    while(c_startline != stopline)
    {
      if(Clipboard == TRUE)
      {
        ClipLine(c_startline, data);
      }

      if(NoCut == FALSE)
      {
        struct line_node *cc_startline = c_startline;

        MyFreePooled(data->mypool, c_startline->line.Contents);
        if(c_startline->line.Styles != NULL)
          MyFreePooled(data->mypool, c_startline->line.Styles);
        data->totallines -= c_startline->visual;
        c_startline = c_startline->next;

        //D(DBF_STARTUP, "FreeLine %08lx", cc_startline);

        FreeLine(cc_startline, data);
      }
      else
        c_startline = c_startline->next;
    }

    if(Clipboard == TRUE)
    {
      if(stopx != 0)
        ClipChars(0, stopline, stopx, data);

      EndClipSession(data);
    }

    if(NoCut == FALSE)
    {
      startline->next = stopline;
      stopline->previous = startline;

      //D(DBF_STARTUP, "RemoveChars: %ld %ld %08lx %ld", startx, stopx, startline, startline->line.Length);

      if(startline->line.Length-startx-1 > 0)
        RemoveChars(startx, startline, startline->line.Length-startx-1, data);

      if(stopx != 0)
        RemoveChars(0, stopline, stopx, data);

      data->CPos_X = startx;
      data->actualline = startline;
      MergeLines(startline, data);
    }
  }
  else
  {
    if(Clipboard == TRUE)
    {
      if(InitClipboard(data, IFFF_WRITE))
      {
        D(DBF_CLIPBOARD, "writing FORM");
        error = PushChunk(data->iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
        SHOWVALUE(DBF_CLIPBOARD, error);

        ClipChars(startx, startline, stopx-startx, data);
        EndClipSession(data);
      }

      if(update == TRUE && NoCut == TRUE)
      {
        MarkText(data->blockinfo.startx, data->blockinfo.startline, data->blockinfo.stopx, data->blockinfo.stopline, data);
          goto end;
      }
    }

    if(NoCut == FALSE)
    {
      data->CPos_X = startx;
      RemoveChars(startx, startline, stopx-startx, data);
      if(update == TRUE)
        goto end;
    }
  }

  tvisual_y = LineToVisual(startline, data)-1;
  if(tvisual_y < 0 || tvisual_y > data->maxlines)
  {
    //D(DBF_STARTUP, "ScrollIntoDisplay");
    ScrollIntoDisplay(data);
    tvisual_y = 0;
  }

  if(update == TRUE)
  {
    //D(DBF_STARTUP, "DumpText! %ld %ld %ld", data->visual_y, tvisual_y, data->maxlines);
    data->update = TRUE;
    DumpText(data->visual_y+tvisual_y, tvisual_y, data->maxlines, TRUE, data);
  }
  res = tvisual_y;

end:

  RETURN(res);
  return res;
}
Example #10
0
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);
}
Example #11
0
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);
}