Improvements to comments etc.
[AROS.git] / workbench / classes / zune / texteditor / mcc / ImportHook.c
blob7596e9c4078b9d49a3fa70eb6843cd09e440cec6
1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2014 TextEditor.mcc Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 TextEditor class Support Site: http://www.sf.net/projects/texteditor-mcc
19 $Id$
21 ***************************************************************************/
23 #include <string.h>
25 #include <proto/dos.h>
26 #include <proto/exec.h>
28 #include "private.h"
29 #include "Debug.h"
31 /*************************************************************************/
35 /*************************************************************************/
36 /// GetHex()
37 static LONG GetHex(const char *src)
39 LONG result = -1;
41 ENTER();
43 if((src[0] >= '0' && src[0] <= '9'))
44 result = src[0] - '0';
45 else if((src[0] >= 'a' && src[0] <= 'f'))
46 result = src[0] - 'a' + 10;
47 else if((src[0] >= 'A' && src[0] <= 'F'))
48 result = src[0] - 'A' + 10;
50 RETURN(result);
51 return result;
54 ///
55 /// GetQP()
56 /************************************************************************
57 Convert a =XX string to its value (into *val). Returns TRUE if
58 conversion was successful; in that case *src_ptr will be advanced as well.
59 *************************************************************************/
60 static BOOL GetQP(const char **src_ptr, unsigned char *val)
62 unsigned char v;
63 const char *src = *src_ptr;
64 int rc;
65 BOOL result = FALSE;
67 ENTER();
69 if((rc = GetHex(src)) != -1)
71 v = rc << 4;
73 if((rc = GetHex(src)) != -1)
75 v |= rc;
76 *val = v;
77 *src_ptr = src + 2;
79 result = TRUE;
83 RETURN(result);
84 return result;
87 ///
88 /// GetLong()
89 /************************************************************************
90 Reads out the next value at *src_ptr and advances src_ptr.
91 Returns TRUE if succedded else FALSE
92 *************************************************************************/
93 static BOOL GetLong(const char **src_ptr, LONG *val)
95 LONG chars;
96 BOOL result = FALSE;
98 ENTER();
100 if((chars = StrToLong(*src_ptr, val)) != -1)
102 *src_ptr += chars;
104 result = TRUE;
107 RETURN(result);
108 return result;
112 /// FindEOL()
113 /************************************************************************
114 Returns the end of line in the current line (pointing at the linefeed).
115 If a 0 byte is encountered it returns the pointer to the 0 byte.
117 This function also counts the number of tabs within this line.
118 *************************************************************************/
119 static const char *FindEOL(const char *src, int *tabs_ptr)
121 int tabs = 0;
122 char c;
123 const char *eol = src;
125 ENTER();
127 while((c = *eol) != '\0')
129 if(c == '\t')
130 tabs++;
131 else if(c == '\r' || c == '\n')
132 break;
134 eol++;
137 if(tabs_ptr != NULL)
138 *tabs_ptr = tabs;
140 RETURN(eol);
141 return eol;
145 /// ContainsText()
146 /************************************************************************
147 searches through a string and returns TRUE if the string contains
148 any text (except newlines) until the stopchar is found
149 *************************************************************************/
150 static BOOL ContainsText(const char *str, const char stopchar)
152 BOOL contains = FALSE;
154 ENTER();
156 if(str != NULL)
158 while(contains == FALSE && *str >= ' ')
160 if(*str == stopchar)
161 break;
162 else if(*str > ' ') // greater than 0x20 (space) == readable text
163 contains = TRUE;
165 str++;
169 RETURN(contains);
170 return contains;
174 /// PlainImportHookFunc()
175 /************************************************************************
176 The plain import hook. It supports following escape sequences:
178 <ESC> + u Set the soft style to underline.
179 <ESC> + b Set the soft style to bold.
180 <ESC> + i Set the soft style to italic.
181 <ESC> + n Set the soft style back to normal.
182 <ESC> + h Highlight the current line.
183 <ESC> + p[x] Change to color x, where x is taken from the colormap.
184 0 means normal. The color is reset for each new line.
187 The following sequences are only valid at the beginning of a line.
189 <ESC> + l Left justify current and following lines.
190 <ESC> + r Right justify current and following lines.
191 <ESC> + c Center current and following lines.
192 <ESC> + [s:x] Create a separator. x is a bit combination of flags:
193 Placement (mutually exclusive):
194 1 = Top
195 2 = Middle
196 4 = Bottom
197 Cosmetical:
198 8 = StrikeThru - Draw separator ontop of text.
199 16 = Thick - Make separator extra thick.
201 Note: Tabs are converted to the number of spaces specified in the
202 TE.mcc object used
204 *************************************************************************/
205 HOOKPROTONHNO(PlainImportHookFunc, STRPTR, struct ImportMessage *msg)
207 STRPTR result = NULL;
208 const char *eol;
209 const char *src = msg->Data;
210 int tabs = 0;
212 ENTER();
214 // check for a valid TAB size
215 if(msg->TabSize <= 0)
217 E(DBF_IMPORT, "invalid TAB size %ld", msg->TabSize);
218 // assume the default TAB size to avoid a division by zero
219 msg->TabSize = 4;
222 if((eol = FindEOL(src, msg->ConvertTabs == FALSE ? NULL : &tabs)) != NULL)
224 int len;
225 struct LineNode *line = msg->linenode;
226 LONG wrap = msg->ImportWrap;
227 ULONG allocatedContents;
229 len = eol - src + (msg->TabSize * tabs);
231 // allocate memory for the contents plus the trailing LF and NUL bytes
232 allocatedContents = len+2;
233 if((line->Contents = AllocVecPooled(msg->PoolHandle, allocatedContents)) != NULL)
235 unsigned char *dest_start = (unsigned char *)line->Contents;
236 unsigned char *dest = dest_start;
237 unsigned char *dest_word_start = dest_start;
238 unsigned char *src_word_start = (unsigned char *)src;
240 /* Style and color state */
241 int state = 0;
243 struct Grow style_grow;
244 struct Grow color_grow;
246 struct LineStyle newStyle;
247 struct LineColor newColor;
249 InitGrow(&style_grow, msg->PoolHandle, sizeof(newStyle));
250 InitGrow(&color_grow, msg->PoolHandle, sizeof(newColor));
252 // remember the allocation size
253 line->allocatedContents = allocatedContents;
255 // Copy loop
256 while(src < eol)
258 unsigned char c = *src++;
260 if(c == '\t' && msg->ConvertTabs == TRUE)
262 LONG i;
264 for(i=(dest - dest_start) % msg->TabSize; i < msg->TabSize; i++)
265 *dest++ = ' ';
267 continue;
269 else if(c == '\033') // ESC sequence
271 c = *src++;
272 switch(c)
274 case 'b':
276 if(isFlagClear(state, BOLD))
278 newStyle.column = dest - dest_start + 1;
279 newStyle.style = BOLD;
280 D(DBF_IMPORT, "adding bold style at column %ld", newStyle.column);
281 AddToGrow(&style_grow, &newStyle);
282 setFlag(state, BOLD);
285 break;
287 case 'i':
289 if(isFlagClear(state, ITALIC))
291 newStyle.column = dest - dest_start + 1;
292 newStyle.style = ITALIC;
293 D(DBF_IMPORT, "adding italic style at column %ld", newStyle.column);
294 AddToGrow(&style_grow, &newStyle);
295 setFlag(state, ITALIC);
298 break;
300 case 'u':
302 if(isFlagClear(state, UNDERLINE))
304 newStyle.column = dest - dest_start + 1;
305 newStyle.style = UNDERLINE;
306 D(DBF_IMPORT, "adding underline style at column %ld", newStyle.column);
307 AddToGrow(&style_grow, &newStyle);
308 setFlag(state, UNDERLINE);
311 break;
313 case 'h':
315 line->Highlight = TRUE;
317 break;
319 case 'n':
321 if(isFlagSet(state, BOLD))
323 newStyle.column = dest - dest_start + 1;
324 newStyle.style = ~BOLD;
325 D(DBF_IMPORT, "removing bold style at column %ld", newStyle.column);
326 AddToGrow(&style_grow, &newStyle);
327 clearFlag(state, BOLD);
329 if(isFlagSet(state, ITALIC))
331 newStyle.column = dest - dest_start + 1;
332 newStyle.style = ~ITALIC;
333 D(DBF_IMPORT, "removing italic style at column %ld", newStyle.column);
334 AddToGrow(&style_grow, &newStyle);
335 clearFlag(state, ITALIC);
337 if(isFlagSet(state, UNDERLINE))
339 newStyle.column = dest - dest_start + 1;
340 newStyle.style = ~UNDERLINE;
341 D(DBF_IMPORT, "removing italic style at column %ld", newStyle.column);
342 AddToGrow(&style_grow, &newStyle);
343 clearFlag(state, UNDERLINE);
346 break;
348 case 'l':
350 line->Flow = MUIV_TextEditor_Flow_Left;
351 D(DBF_IMPORT, "left aligned text flow");
353 break;
355 case 'c':
357 line->Flow = MUIV_TextEditor_Flow_Center;
358 D(DBF_IMPORT, "centered flow");
360 break;
362 case 'r':
364 line->Flow = MUIV_TextEditor_Flow_Right;
365 D(DBF_IMPORT, "right aligned text flow");
367 break;
369 case 'p':
371 if(*src == '[')
373 LONG pen;
375 src++;
377 if(GetLong(&src, &pen) == TRUE)
379 if(*src == ']')
381 newColor.column = dest - dest_start + 1;
382 newColor.color = pen;
383 D(DBF_IMPORT, "adding color %ld at column %ld", newColor.color, newColor.column);
384 AddToGrow(&color_grow, &newColor);
386 if(pen == 0)
387 state ^= COLOURED;
388 else
389 setFlag(state, COLOURED);
391 src++;
396 break;
398 case '[':
400 if(*src == 's')
402 src++;
403 if(*src == ':')
405 LONG flags;
407 src++;
409 if(GetLong(&src, &flags) == TRUE)
411 if(*src == ']')
413 line->Separator = flags;
414 src++;
420 break;
423 continue;
426 if(c == ' ')
428 // src is already advanced
429 src_word_start = (unsigned char *)src;
430 dest_word_start = dest;
433 if(wrap != 0 && dest - dest_start >= wrap)
435 /* Only leave the loop, if we really have added some characters
436 * (at least one word) to the line */
437 if(dest_word_start != dest_start)
439 /* src points to the real word start, but we add one when we return eol */
440 eol = (char *)(src_word_start - 1);
441 dest = dest_word_start;
442 break;
446 *dest++ = c;
447 } /* while (src < eol) */
449 // terminate the color array, but only if there are any colors at all
450 if(color_grow.itemCount > 0)
452 // ensure that we terminate the clip with color 0
453 if(isFlagSet(state, COLOURED))
455 D(DBF_IMPORT, "removing color as termination");
456 newColor.column = strlen(line->Contents)+1;
457 newColor.color = 0;
458 AddToGrow(&color_grow, &newColor);
461 newColor.column = EOC;
462 newColor.color = 0;
463 AddToGrow(&color_grow, &newColor);
466 D(DBF_IMPORT, "added %ld color sections", color_grow.itemCount);
467 line->Colors = (struct LineColor *)color_grow.array;
469 // terminate the style array, but only if there are any styles at all
470 if(style_grow.itemCount > 0)
472 LONG lastColumn = strlen(line->Contents)+1;
474 // ensure that we terminate the clip with plain style
475 if(isFlagSet(state, BOLD))
477 D(DBF_IMPORT, "removing bold style as termination");
478 newStyle.column = lastColumn;
479 newStyle.style = ~BOLD;
480 AddToGrow(&style_grow, &newStyle);
482 if(isFlagSet(state, ITALIC))
484 D(DBF_IMPORT, "removing italic style as termination");
485 newStyle.column = lastColumn;
486 newStyle.style = ~ITALIC;
487 AddToGrow(&style_grow, &newStyle);
489 if(isFlagSet(state, UNDERLINE))
491 D(DBF_IMPORT, "removing underline style as termination");
492 newStyle.column = lastColumn;
493 newStyle.style = ~UNDERLINE;
494 AddToGrow(&style_grow, &newStyle);
497 newStyle.column = EOS;
498 newStyle.style = 0;
499 AddToGrow(&style_grow, &newStyle);
502 D(DBF_IMPORT, "added %ld style sections", style_grow.itemCount);
503 line->Styles = (struct LineStyle *)style_grow.array;
505 *dest++ = '\n';
506 *dest = 0;
508 line->Length = dest - dest_start; /* this excludes \n */
511 if(eol != NULL && eol[0] != '\0')
513 eol++;
514 result = (STRPTR)eol;
518 RETURN(result);
519 return result;
521 MakeHook(ImPlainHook, PlainImportHookFunc);
524 /// MimeImport()
525 /************************************************************************
526 The MIME import hook. It supports following escape sequences:
528 <ESC> + u Set the soft style to underline.
529 <ESC> + b Set the soft style to bold.
530 <ESC> + i Set the soft style to italic.
531 <ESC> + n Set the soft style back to normal.
532 <ESC> + h Highlight the current line.
533 <ESC> + p[x] Change to color x, where x is taken from the colormap.
534 0 means normal. The color is reset for each new line.
537 The following sequences are only valid at the beginning of a line.
539 <ESC> + l Left justify current and following lines.
540 <ESC> + r Right justify current and following lines.
541 <ESC> + c Center current and following lines.
542 <ESC> + [s:x] Create a separator. x is a bit combination of flags:
543 Placement (mutually exclusive):
544 1 = Top
545 2 = Middle
546 4 = Bottom
547 Cosmetical:
548 8 = StrikeThru - Draw separator ontop of text.
549 16 = Thick - Make separator extra thick.
551 Note: Tabs are converted to the number of spaces specified in the
552 TE.mcc object used
554 *************************************************************************/
555 static STRPTR MimeImport(struct ImportMessage *msg, LONG type)
557 STRPTR result = NULL;
558 const char *eol;
559 const char *src = msg->Data;
560 int tabs=0;
562 ENTER();
564 if((eol = FindEOL(src, msg->ConvertTabs == FALSE ? NULL : &tabs)) != NULL)
566 int len;
567 struct LineNode *line = msg->linenode;
568 LONG wrap = msg->ImportWrap;
569 ULONG allocatedContents;
571 len = eol - src + (msg->TabSize * tabs);
573 // allocate some more memory for the possible quote mark '>', note that if
574 // a '=' is detected at the end of a line this memory is not sufficient!
575 allocatedContents = len+4;
576 if((line->Contents = AllocVecPooled(msg->PoolHandle, allocatedContents)) != NULL)
578 BOOL lastWasSeparator = TRUE;
579 unsigned char *dest_start = (unsigned char *)line->Contents;
580 unsigned char *dest = dest_start;
581 unsigned char *dest_word_start = dest_start;
582 unsigned char *src_word_start = (unsigned char *)src;
584 /* Style and color state */
585 int state = 0;
586 int escstate = 0;
587 int shownext = 0;
589 struct Grow style_grow;
590 struct Grow color_grow;
592 struct LineStyle newStyle;
593 struct LineColor newColor;
595 InitGrow(&style_grow, msg->PoolHandle, sizeof(newStyle));
596 InitGrow(&color_grow, msg->PoolHandle, sizeof(newColor));
598 // remember the allocation size
599 line->allocatedContents = allocatedContents;
601 if(src[0] == '>')
602 line->Highlight = TRUE;
603 else if(src[0] == '<')
605 if(src[1] == 's' && src[2] == 'b' && src[3] == '>')
607 line->Separator = LNSF_Middle;
608 src += 4;
609 line->Flow = MUIV_TextEditor_Flow_Center;
610 line->clearFlow = TRUE;
612 else if(src[1] == 't' && src[2] == 's' && src[3] == 'b' && src[4] == '>')
614 src += 5;
615 line->Separator = LNSF_Thick|LNSF_Middle;
616 line->Flow = MUIV_TextEditor_Flow_Center;
617 line->clearFlow = TRUE;
621 if(type == 2)
623 *dest++ = '>';
624 line->Highlight = TRUE;
627 // Copy loop
628 while (src < eol)
630 unsigned char c = *src++;
632 if(c == '\n')
634 lastWasSeparator = TRUE;
636 else if(c == '\t' && msg->ConvertTabs == TRUE)
638 LONG i;
640 for(i=(dest - dest_start) % msg->TabSize; i < msg->TabSize; i++)
641 *dest++ = ' ';
643 lastWasSeparator = TRUE;
645 continue;
647 else if(c == '/')
649 if(escstate == 0)
651 if(shownext & ITALIC)
652 shownext ^= ITALIC;
653 else if(isFlagSet(state, ITALIC) || (lastWasSeparator == TRUE && ContainsText(src, '/') == TRUE))
655 newStyle.column = dest - dest_start + 1;
656 newStyle.style = isFlagSet(state, ITALIC) ? ~ITALIC : ITALIC;
657 AddToGrow(&style_grow, &newStyle);
658 state ^= ITALIC;
660 lastWasSeparator = TRUE;
661 continue;
663 else
664 shownext |= ITALIC;
667 lastWasSeparator = TRUE;
669 else if(c == '*')
671 if(escstate == 0)
673 if(shownext & BOLD)
674 shownext ^= BOLD;
675 else if(isFlagSet(state, BOLD) || (lastWasSeparator == TRUE && ContainsText(src, '*') == TRUE))
677 newStyle.column = dest - dest_start + 1;
678 newStyle.style = isFlagSet(state, BOLD) ? ~BOLD : BOLD;
679 AddToGrow(&style_grow, &newStyle);
680 state ^= BOLD;
682 lastWasSeparator = TRUE;
683 continue;
685 else
686 shownext |= BOLD;
689 lastWasSeparator = TRUE;
691 else if(c == '_')
693 if(escstate == 0)
695 if(shownext & UNDERLINE)
696 shownext ^= UNDERLINE;
697 else if(isFlagSet(state, UNDERLINE) || (lastWasSeparator == TRUE && ContainsText(src, '_') == TRUE))
699 newStyle.column = dest - dest_start + 1;
700 newStyle.style = isFlagSet(state, UNDERLINE) ? ~UNDERLINE : UNDERLINE;
701 AddToGrow(&style_grow, &newStyle);
702 state ^= UNDERLINE;
704 lastWasSeparator = TRUE;
705 continue;
707 else
708 shownext |= UNDERLINE;
711 lastWasSeparator = TRUE;
713 else if(c == '#')
715 if(escstate == 0)
717 if(shownext & COLOURED)
718 shownext ^= COLOURED;
719 else if(isFlagSet(state, COLOURED) || (lastWasSeparator == TRUE && ContainsText(src, '#') == TRUE))
721 newColor.column = dest - dest_start + 1;
722 newColor.color = isFlagSet(state, COLOURED) ? 0 : 7;
723 AddToGrow(&style_grow, &newStyle);
724 state ^= COLOURED;
726 lastWasSeparator = TRUE;
727 continue;
729 else
730 shownext |= COLOURED;
733 lastWasSeparator = TRUE;
735 else if(c == '=')
737 // This is a concatenated line
738 if(type > 0 && GetQP(&src, &c) == FALSE)
740 int i;
742 i = 0;
743 if(src[0] == '\r')
744 i++;
746 if(src[i] == '\n')
748 unsigned char *new_dest_start;
750 src += i + 1;
752 if((eol = FindEOL(src, msg->ConvertTabs == FALSE ? NULL : &tabs)) == NULL)
753 break;
755 /* The size of the dest buffer has to be increased now */
756 len += eol - src + (msg->TabSize * tabs);
758 if((new_dest_start = (unsigned char*)AllocVecPooled(msg->PoolHandle, len + 4)) == NULL)
759 break;
761 memcpy(new_dest_start, dest_start, dest - dest_start);
762 FreeVecPooled(msg->PoolHandle,dest_start);
764 /* Update all dest variables */
765 dest_word_start = new_dest_start + (dest_word_start - dest_start);
766 dest = new_dest_start + (dest - dest_start);
767 line->Contents = (char *)new_dest_start;
768 dest_start = (unsigned char *)line->Contents;
770 lastWasSeparator = FALSE;
771 continue;
775 else if(c == '\033') // like the plain import hook we manage ESC sequences as well
777 switch(*src++)
779 case 'b':
781 newStyle.column = dest - dest_start + 1;
782 newStyle.style = BOLD;
783 AddToGrow(&style_grow, &newStyle);
784 setFlag(escstate, BOLD);
786 break;
788 case 'i':
790 newStyle.column = dest - dest_start + 1;
791 newStyle.style = ITALIC;
792 AddToGrow(&style_grow, &newStyle);
793 setFlag(escstate, ITALIC);
795 break;
797 case 'u':
799 newStyle.column = dest - dest_start + 1;
800 newStyle.style = UNDERLINE;
801 AddToGrow(&style_grow, &newStyle);
802 setFlag(escstate, UNDERLINE);
804 break;
806 case 'h':
808 line->Highlight = TRUE;
810 break;
812 case 'n':
814 if(isFlagSet(state, BOLD))
816 newStyle.column = dest - dest_start + 1;
817 newStyle.style = ~BOLD;
818 AddToGrow(&style_grow, &newStyle);
819 clearFlag(state, BOLD);
820 clearFlag(escstate, BOLD);
822 if(isFlagSet(state, ITALIC))
824 newStyle.column = dest - dest_start + 1;
825 newStyle.style = ~ITALIC;
826 AddToGrow(&style_grow, &newStyle);
827 clearFlag(state, ITALIC);
828 clearFlag(escstate, ITALIC);
830 if(isFlagSet(state, UNDERLINE))
832 newStyle.column = dest - dest_start + 1;
833 newStyle.style = ~UNDERLINE;
834 AddToGrow(&style_grow, &newStyle);
835 clearFlag(state, UNDERLINE);
836 clearFlag(escstate, UNDERLINE);
839 break;
841 case 'l':
843 line->Flow = MUIV_TextEditor_Flow_Left;
845 break;
847 case 'c':
849 line->Flow = MUIV_TextEditor_Flow_Center;
851 break;
853 case 'r':
855 line->Flow = MUIV_TextEditor_Flow_Right;
857 break;
859 case 'p':
861 if(*src == '[')
863 LONG pen;
865 src++;
867 if(GetLong(&src, &pen) == TRUE)
869 if(*src == ']')
871 newColor.column = dest - dest_start + 1;
872 newColor.color = pen;
873 AddToGrow(&color_grow, &newColor);
875 if(pen == 0)
876 escstate ^= COLOURED;
877 else
878 escstate |= COLOURED;
880 src++;
885 break;
887 case '[':
889 if(*src == 's')
891 src++;
892 if(*src == ':')
894 LONG flags;
896 src++;
898 if(GetLong(&src, &flags) == TRUE)
900 if(*src == ']')
902 line->Separator = flags;
903 src++;
909 break;
912 lastWasSeparator = FALSE;
913 continue;
916 if(c == ' ')
918 /* src is already advanced */
919 src_word_start = (unsigned char *)src;
920 dest_word_start = dest;
922 lastWasSeparator = TRUE;
924 else if(c == '\n')
926 lastWasSeparator = TRUE;
928 else
930 lastWasSeparator = FALSE;
933 if(wrap != 0 && dest - dest_start >= wrap)
935 /* Only leave the loop, if we really have added some characters
936 * (at least one word) to the line */
937 if(dest_word_start != dest_start)
939 /* src points to the real word start, but we add one when we return eol */
940 eol = (char *)(src_word_start - 1);
941 dest = dest_word_start;
942 break;
946 *dest++ = c;
947 } /* while (src < eol) */
949 // terminate the color array, but only if there are any colors at all
950 if(color_grow.itemCount > 0)
952 newColor.column = EOC;
953 newColor.color = 0;
954 AddToGrow(&color_grow, &newColor);
957 line->Colors = (struct LineColor *)color_grow.array;
959 // terminate the style array, but only if there are any styles at all
960 if(style_grow.itemCount > 0)
962 newStyle.column = EOS;
963 newStyle.style = 0;
964 AddToGrow(&style_grow, &newStyle);
967 line->Styles = (struct LineStyle *)style_grow.array;
969 *dest++ = '\n';
970 *dest = 0;
972 line->Length = dest - dest_start; /* this excludes \n */
975 if(eol != NULL && eol[0] != '\0')
977 eol++;
978 result = (STRPTR)eol;
982 RETURN(result);
983 return result;
987 /// EMailImportHookFunc()
988 HOOKPROTONHNO(EMailImportHookFunc, STRPTR , struct ImportMessage *msg)
990 return MimeImport(msg, 0);
992 MakeHook(ImEMailHook, EMailImportHookFunc);
995 /// MIMEImportHookFunc()
996 HOOKPROTONHNO(MIMEImportHookFunc, STRPTR, struct ImportMessage *msg)
998 return MimeImport(msg, 1);
1000 MakeHook(ImMIMEHook, MIMEImportHookFunc);
1003 /// MIMEQuoteImportHookFunc()
1004 HOOKPROTONHNO(MIMEQuoteImportHookFunc, STRPTR, struct ImportMessage *msg)
1006 return MimeImport(msg, 2);
1008 MakeHook(ImMIMEQuoteHook, MIMEQuoteImportHookFunc);