Merged TextEditor MCC 15.45
[AROS.git] / workbench / classes / zune / texteditor / mcc / ClipboardServer.c
blobd8572038cbf836ebb50722f90326eca5b0132cca
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>
24 #include <stdlib.h>
26 #include <proto/dos.h>
27 #include <proto/exec.h>
28 #include <proto/intuition.h>
30 #include <dos/dostags.h>
32 // for iffparse.library no global variable definitions are needed
33 #define __NOLIBBASE__
34 #define __NOGLOBALIFACE__
35 #include <proto/iffparse.h>
37 #include "private.h"
38 #include "Debug.h"
40 static struct Library *IFFParseBase = NULL;
41 #if defined(__amigaos4__)
42 static struct IFFParseIFace *IIFFParse = NULL;
43 #endif
44 static struct SignalSemaphore *serverLock = NULL;
45 static struct Process *serverProcess = NULL;
46 static struct MsgPort *serverPort = NULL;
47 static struct MsgPort replyPort;
48 static struct Message msg;
50 struct ServerData
52 ULONG sd_Command;
53 IPTR sd_Session;
54 ULONG sd_Mode;
55 struct line_node *sd_Line;
56 LONG sd_Start;
57 LONG sd_Length;
58 ULONG sd_Codeset;
59 LONG sd_Error;
62 #define SERVER_SHUTDOWN 0xdeadf00d
63 #define SERVER_START_SESSION 0x00000001
64 #define SERVER_WRITE_CHARS 0x00000002
65 #define SERVER_WRITE_LINE 0x00000003
66 #define SERVER_READ_LINE 0x00000004
67 #define SERVER_END_SESSION 0x0000000f
69 #define ID_FORM MAKE_ID('F','O','R','M')
70 #define ID_FTXT MAKE_ID('F','T','X','T')
71 #define ID_CHRS MAKE_ID('C','H','R','S')
72 #define ID_CSET MAKE_ID('C','S','E','T')
74 /// ServerStartSession
75 static IPTR ServerStartSession(ULONG mode)
77 IPTR result = (IPTR)NULL;
78 struct IFFHandle *iff;
80 ENTER();
82 if((iff = AllocIFF()) != NULL)
84 if((iff->iff_Stream = (IPTR)OpenClipboard(0)) != 0)
86 InitIFFasClip(iff);
88 if(OpenIFF(iff, mode) == 0)
90 if(mode == IFFF_WRITE)
92 PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
94 else if(mode == IFFF_READ)
96 StopChunk(iff, ID_FTXT, ID_CHRS);
97 StopChunk(iff, ID_FTXT, ID_FLOW);
98 StopChunk(iff, ID_FTXT, ID_HIGH);
99 StopChunk(iff, ID_FTXT, ID_SBAR);
100 StopChunk(iff, ID_FTXT, ID_COLS);
101 StopChunk(iff, ID_FTXT, ID_STYL);
102 StopChunk(iff, ID_FTXT, ID_CSET);
105 result = (IPTR)iff;
107 else
109 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
110 FreeIFF(iff);
113 else
114 FreeIFF(iff);
117 RETURN(result);
118 return result;
122 /// ServerEndSession
123 static void ServerEndSession(IPTR session)
125 struct IFFHandle *iff = (struct IFFHandle *)session;
127 ENTER();
129 if(iff != NULL)
131 CloseIFF(iff);
133 if(iff->iff_Stream != 0)
134 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
136 FreeIFF(iff);
139 LEAVE();
143 /// ServerWriteInfo
144 static void ServerWriteInfo(IPTR session, struct line_node *line)
146 struct IFFHandle *iff = (struct IFFHandle *)session;
147 LONG error;
149 ENTER();
151 if(line->line.Flow != MUIV_TextEditor_Flow_Left || line->line.clearFlow == TRUE)
153 UWORD uwordBool = line->line.clearFlow;
155 D(DBF_CLIPBOARD, "writing FLOW");
156 error = PushChunk(iff, 0, ID_FLOW, IFFSIZE_UNKNOWN);
157 SHOWVALUE(DBF_CLIPBOARD, error);
158 error = WriteChunkBytes(iff, &line->line.Flow, 2);
159 SHOWVALUE(DBF_CLIPBOARD, error);
160 error = WriteChunkBytes(iff, &uwordBool, 2);
161 SHOWVALUE(DBF_CLIPBOARD, error);
162 error = PopChunk(iff);
163 SHOWVALUE(DBF_CLIPBOARD, error);
166 if(line->line.Separator != LNSF_None)
168 D(DBF_CLIPBOARD, "writing SBAR");
169 error = PushChunk(iff, 0, ID_SBAR, IFFSIZE_UNKNOWN);
170 SHOWVALUE(DBF_CLIPBOARD, error);
171 error = WriteChunkBytes(iff, &line->line.Separator, 2);
172 SHOWVALUE(DBF_CLIPBOARD, error);
173 error = PopChunk(iff);
174 SHOWVALUE(DBF_CLIPBOARD, error);
177 if(line->line.Highlight == TRUE)
179 UWORD uwordBool = TRUE;
181 D(DBF_CLIPBOARD, "writing HIGH");
182 error = PushChunk(iff, 0, ID_HIGH, IFFSIZE_UNKNOWN);
183 SHOWVALUE(DBF_CLIPBOARD, error);
184 error = WriteChunkBytes(iff, &uwordBool, sizeof(uwordBool));
185 SHOWVALUE(DBF_CLIPBOARD, error);
186 error = PopChunk(iff);
187 SHOWVALUE(DBF_CLIPBOARD, error);
190 LEAVE();
194 /// ServerWriteChars
195 static void ServerWriteChars(IPTR session, struct line_node *line, LONG start, LONG length)
197 struct IFFHandle *iff = (struct IFFHandle *)session;
198 LONG error;
199 struct LineStyle style = {1, GetStyle(start-1, line)};
200 struct LineColor color = {1, 0};
201 struct LineColor *colors = line->line.Colors;
203 ENTER();
205 ServerWriteInfo(session, line);
207 if(colors != NULL)
209 D(DBF_CLIPBOARD, "writing COLS");
210 error = PushChunk(iff, 0, ID_COLS, IFFSIZE_UNKNOWN);
211 SHOWVALUE(DBF_CLIPBOARD, error);
213 while(colors->column <= start && colors->column != EOC)
215 color.color = colors->color;
216 colors++;
219 if(color.color != 0 && colors->column-start != 1)
221 error = WriteChunkBytes(iff, &color, sizeof(color));
222 SHOWVALUE(DBF_CLIPBOARD, error);
225 if(colors->column != EOC)
227 while(colors->column <= start+length)
229 color.column = colors->column - start;
230 color.color = colors->color;
231 colors++;
233 error = WriteChunkBytes(iff, &color, sizeof(color));
234 SHOWVALUE(DBF_CLIPBOARD, error);
238 error = PopChunk(iff);
239 SHOWVALUE(DBF_CLIPBOARD, error);
242 D(DBF_CLIPBOARD, "writing STYL");
243 error = PushChunk(iff, 0, ID_STYL, IFFSIZE_UNKNOWN);
244 SHOWVALUE(DBF_CLIPBOARD, error);
246 if(style.style != 0)
248 UWORD t_style = style.style;
250 if(isFlagSet(t_style, BOLD))
252 style.style = BOLD;
253 error = WriteChunkBytes(iff, &style, sizeof(style));
254 SHOWVALUE(DBF_CLIPBOARD, error);
256 if(isFlagSet(t_style, ITALIC))
258 style.style = ITALIC;
259 error = WriteChunkBytes(iff, &style, sizeof(style));
260 SHOWVALUE(DBF_CLIPBOARD, error);
262 if(isFlagSet(t_style, UNDERLINE))
264 style.style = UNDERLINE;
265 error = WriteChunkBytes(iff, &style, sizeof(style));
266 SHOWVALUE(DBF_CLIPBOARD, error);
270 if(line->line.Styles != NULL)
272 struct LineStyle *styles = line->line.Styles;
274 while(styles->column <= start && styles->column != EOS)
275 styles++;
277 if(styles->column != EOS)
279 while(styles->column <= start+length)
281 style.column = styles->column - start;
282 style.style = styles->style;
283 styles++;
284 error = WriteChunkBytes(iff, &style, sizeof(style));
285 SHOWVALUE(DBF_CLIPBOARD, error);
288 style.column = length+1;
289 style.style = GetStyle(start+length-1, line);
290 if(style.style != 0)
292 UWORD t_style = style.style;
294 if(isFlagSet(t_style, BOLD))
296 style.style = ~BOLD;
297 error = WriteChunkBytes(iff, &style, sizeof(style));
298 SHOWVALUE(DBF_CLIPBOARD, error);
300 if(isFlagSet(t_style, ITALIC))
302 style.style = ~ITALIC;
303 error = WriteChunkBytes(iff, &style, sizeof(style));
304 SHOWVALUE(DBF_CLIPBOARD, error);
306 if(isFlagSet(t_style, UNDERLINE))
308 style.style = ~UNDERLINE;
309 error = WriteChunkBytes(iff, &style, sizeof(style));
310 SHOWVALUE(DBF_CLIPBOARD, error);
316 error = PopChunk(iff);
317 SHOWVALUE(DBF_CLIPBOARD, error);
319 D(DBF_CLIPBOARD, "writing CHRS");
320 error = PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN);
321 SHOWVALUE(DBF_CLIPBOARD, error);
322 error = WriteChunkBytes(iff, line->line.Contents + start, length);
323 SHOWVALUE(DBF_CLIPBOARD, error);
324 error = PopChunk(iff);
325 SHOWVALUE(DBF_CLIPBOARD, error);
327 LEAVE();
331 /// ServerWriteLine
332 static void ServerWriteLine(IPTR session, struct line_node *line)
334 struct IFFHandle *iff = (struct IFFHandle *)session;
335 LONG error;
336 struct LineStyle *styles = line->line.Styles;
337 struct LineColor *colors = line->line.Colors;
339 ENTER();
341 ServerWriteInfo(session, line);
343 if(colors != NULL)
345 LONG numColors = 0;
347 D(DBF_CLIPBOARD, "writing COLS");
348 error = PushChunk(iff, 0, ID_COLS, IFFSIZE_UNKNOWN);
349 SHOWVALUE(DBF_CLIPBOARD, error);
351 while(colors->column != EOC)
353 colors++;
354 numColors++;
357 SHOWVALUE(DBF_CLIPBOARD, numColors);
358 error = WriteChunkBytes(iff, line->line.Colors, numColors * sizeof(*colors));
359 SHOWVALUE(DBF_CLIPBOARD, error);
360 error = PopChunk(iff);
361 SHOWVALUE(DBF_CLIPBOARD, error);
364 if(styles != NULL)
366 LONG numStyles = 0;
368 D(DBF_CLIPBOARD, "writing STYL");
369 error = PushChunk(iff, 0, ID_STYL, IFFSIZE_UNKNOWN);
370 SHOWVALUE(DBF_CLIPBOARD, error);
372 while(styles->column != EOS)
374 styles++;
375 numStyles++;
378 SHOWVALUE(DBF_CLIPBOARD, numStyles);
379 error = WriteChunkBytes(iff, line->line.Styles, numStyles * sizeof(*styles));
380 SHOWVALUE(DBF_CLIPBOARD, error);
381 error = PopChunk(iff);
382 SHOWVALUE(DBF_CLIPBOARD, error);
385 D(DBF_CLIPBOARD, "writing CHRS");
386 error = PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN);
387 SHOWVALUE(DBF_CLIPBOARD, error);
388 error = WriteChunkBytes(iff, line->line.Contents, line->line.Length);
389 SHOWVALUE(DBF_CLIPBOARD, error);
390 error = PopChunk(iff);
391 SHOWVALUE(DBF_CLIPBOARD, error);
393 LEAVE();
397 /// ServerReadLine
398 static LONG ServerReadLine(IPTR session, struct line_node **linePtr, ULONG *csetPtr)
400 struct IFFHandle *iff = (struct IFFHandle *)session;
401 struct line_node *line = NULL;
402 struct LineStyle *styles = NULL;
403 struct LineColor *colors = NULL;
404 STRPTR textline;
405 LONG codeset = 0;
406 UWORD flow = MUIV_TextEditor_Flow_Left;
407 BOOL clearFlow = FALSE;
408 BOOL highlight = FALSE;
409 UWORD separator = LNSF_None;
410 LONG error;
411 BOOL lineFinished = FALSE;
413 ENTER();
415 D(DBF_CLIPBOARD, "server reading next line");
418 struct ContextNode *cn;
420 error = ParseIFF(iff, IFFPARSE_SCAN);
421 SHOWVALUE(DBF_CLIPBOARD, error);
422 if(error == IFFERR_EOC)
423 continue;
424 else if(error != 0)
425 break;
427 if((cn = CurrentChunk(iff)) != NULL)
429 switch (cn->cn_ID)
431 case ID_CSET:
433 D(DBF_CLIPBOARD, "reading CSET");
434 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
435 if(cn->cn_Size >= (LONG)sizeof(codeset))
437 /* Only the first four bytes are interesting */
438 if(ReadChunkBytes(iff, &codeset, 4) != 4)
440 codeset = 0;
442 SHOWVALUE(DBF_CLIPBOARD, codeset);
445 break;
447 case ID_FLOW:
449 UWORD uwordBool;
451 D(DBF_CLIPBOARD, "reading FLOW");
452 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
453 if(cn->cn_Size >= (LONG)(sizeof(flow)+sizeof(uwordBool)))
455 if((error = ReadChunkBytes(iff, &flow, sizeof(flow))) == 2)
457 if(flow > MUIV_TextEditor_Flow_Right)
458 flow = MUIV_TextEditor_Flow_Left;
460 SHOWVALUE(DBF_CLIPBOARD, flow);
461 SHOWVALUE(DBF_CLIPBOARD, error);
462 error = ReadChunkBytes(iff, &uwordBool, 2);
463 clearFlow = (uwordBool != 0) ? TRUE : FALSE;
464 SHOWVALUE(DBF_CLIPBOARD, clearFlow);
465 SHOWVALUE(DBF_CLIPBOARD, error);
468 break;
470 case ID_HIGH:
472 UWORD uwordBool;
474 D(DBF_CLIPBOARD, "reading HIGH");
475 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
476 if(cn->cn_Size >= (LONG)sizeof(uwordBool))
478 error = ReadChunkBytes(iff, &uwordBool, 2);
479 highlight = (uwordBool != 0) ? TRUE : FALSE;
480 SHOWVALUE(DBF_CLIPBOARD, highlight);
481 SHOWVALUE(DBF_CLIPBOARD, error);
484 break;
486 case ID_SBAR:
488 D(DBF_CLIPBOARD, "reading SBAR");
489 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
490 if (cn->cn_Size >= (LONG)sizeof(separator))
492 error = ReadChunkBytes(iff, &separator, 2);
493 SHOWVALUE(DBF_CLIPBOARD, separator);
494 SHOWVALUE(DBF_CLIPBOARD, error);
497 break;
499 case ID_COLS:
501 ULONG numColors = cn->cn_Size / sizeof(struct LineColor);
503 D(DBF_CLIPBOARD, "reading COLS");
504 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
505 if(colors != NULL)
507 // forget any duplicate colors
508 FreeVec(colors);
509 colors = NULL;
511 // allocate one word more than the chunk tell us, because we terminate the array with EOC
512 if(numColors > 0 && (colors = AllocVecShared((numColors+1) * sizeof(*colors), MEMF_ANY)) != NULL)
514 error = ReadChunkBytes(iff, colors, numColors * sizeof(struct LineColor));
515 SHOWVALUE(DBF_CLIPBOARD, error);
516 colors[numColors].column = EOC;
519 break;
521 case ID_STYL:
523 ULONG numStyles = cn->cn_Size / sizeof(struct LineStyle);
525 D(DBF_CLIPBOARD, "reading STYL");
526 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
527 if(styles != NULL && styles != (APTR)-1)
529 // forget any duplicate styles
530 FreeVec(styles);
531 styles = NULL;
533 // allocate one word more than the chunk tell us, because we terminate the array with EOS
534 if(numStyles > 0 && (styles = AllocVecShared((numStyles+1) * sizeof(struct LineStyle), MEMF_ANY)) != NULL)
536 error = ReadChunkBytes(iff, styles, numStyles * sizeof(struct LineStyle));
537 SHOWVALUE(DBF_CLIPBOARD, error);
538 styles[numStyles].column = EOS;
541 break;
543 case ID_CHRS:
545 ULONG length = cn->cn_Size;
547 D(DBF_CLIPBOARD, "reading CHRS");
548 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
550 if(length > 0)
552 // allocate 2 additional bytes:
553 // - one for the trailing LF
554 // - another one for the terminating NUL
555 if((textline = AllocVecShared(length + 2, MEMF_ANY)) != NULL)
557 error = ReadChunkBytes(iff, textline, length);
558 SHOWVALUE(DBF_CLIPBOARD, error);
559 textline[length] = '\0';
562 if(textline != NULL && (line = AllocVecShared(sizeof(*line), MEMF_ANY|MEMF_CLEAR)) != NULL)
564 line->line.Contents = textline;
565 line->line.Length = length;
566 line->line.allocatedContents = length+2;
567 line->line.Highlight = highlight;
568 line->line.Flow = flow;
569 line->line.clearFlow = clearFlow;
570 line->line.Separator = separator;
571 line->line.Styles = styles;
572 line->line.Colors = colors;
574 lineFinished = TRUE;
575 error = 0;
577 else
579 if(textline != NULL)
580 FreeVec(textline);
581 if(styles != NULL)
582 FreeVec(styles);
583 if(colors != NULL)
584 FreeVec(colors);
587 styles = NULL;
588 colors = NULL;
589 flow = MUIV_TextEditor_Flow_Left;
590 clearFlow = FALSE;
591 highlight = FALSE;
592 separator = LNSF_None;
595 break;
599 while(lineFinished == FALSE);
601 // in case we didn't read a complete line but at least some other of our
602 // chunks we free them here to avoid leaks.
603 if(line == NULL)
605 if(styles != NULL)
606 FreeVec(styles);
607 if(colors != NULL)
608 FreeVec(colors);
611 *linePtr = line;
612 *csetPtr = codeset;
614 RETURN(error);
615 return error;
619 /// ClientStartSession
620 // copy a line to the clipboard, public callable function
621 IPTR ClientStartSession(ULONG mode)
623 IPTR session = (IPTR)NULL;
625 // lock out other tasks
626 if(AttemptSemaphore(serverLock))
628 struct ServerData sd;
630 // set up the data packet
631 sd.sd_Command = SERVER_START_SESSION;
632 sd.sd_Mode = mode;
634 // set up the message, send it and wait for a reply
635 msg.mn_Node.ln_Name = (STRPTR)&sd;
636 replyPort.mp_SigTask = FindTask(NULL);
638 PutMsg(serverPort, &msg);
639 Remove((struct Node *)WaitPort(&replyPort));
641 session = sd.sd_Session;
643 // allow other tasks again
644 ReleaseSemaphore(serverLock);
646 else
647 DisplayBeep(0);
649 return session;
653 /// ClientEndSession
654 // copy a line to the clipboard, public callable function
655 void ClientEndSession(IPTR session)
657 // lock out other tasks
658 if(AttemptSemaphore(serverLock))
660 struct ServerData sd;
662 // set up the data packet
663 sd.sd_Command = SERVER_END_SESSION;
664 sd.sd_Session = session;
666 // set up the message, send it and wait for a reply
667 msg.mn_Node.ln_Name = (STRPTR)&sd;
668 replyPort.mp_SigTask = FindTask(NULL);
670 PutMsg(serverPort, &msg);
671 Remove((struct Node *)WaitPort(&replyPort));
673 // allow other tasks again
674 ReleaseSemaphore(serverLock);
676 else
677 DisplayBeep(0);
681 /// ClientWriteChars
682 void ClientWriteChars(IPTR session, struct line_node *line, LONG start, LONG length)
684 // lock out other tasks
685 if(AttemptSemaphore(serverLock))
687 struct ServerData sd;
689 // set up the data packet
690 sd.sd_Command = SERVER_WRITE_CHARS;
691 sd.sd_Session = session;
692 sd.sd_Line = line;
693 sd.sd_Start = start;
694 sd.sd_Length = length;
696 // set up the message, send it and wait for a reply
697 msg.mn_Node.ln_Name = (STRPTR)&sd;
698 replyPort.mp_SigTask = FindTask(NULL);
700 PutMsg(serverPort, &msg);
701 Remove((struct Node *)WaitPort(&replyPort));
703 // allow other tasks again
704 ReleaseSemaphore(serverLock);
706 else
707 DisplayBeep(0);
711 /// ClientWriteLine
712 void ClientWriteLine(IPTR session, struct line_node *line)
714 // lock out other tasks
715 if(AttemptSemaphore(serverLock))
717 struct ServerData sd;
719 // set up the data packet
720 sd.sd_Command = SERVER_WRITE_LINE;
721 sd.sd_Session = session;
722 sd.sd_Line = line;
724 // set up the message, send it and wait for a reply
725 msg.mn_Node.ln_Name = (STRPTR)&sd;
726 replyPort.mp_SigTask = FindTask(NULL);
728 PutMsg(serverPort, &msg);
729 Remove((struct Node *)WaitPort(&replyPort));
731 // allow other tasks again
732 ReleaseSemaphore(serverLock);
734 else
735 DisplayBeep(0);
739 /// ClientReadLine
740 LONG ClientReadLine(IPTR session, struct line_node **line, ULONG *cset)
742 LONG error = IFFERR_NOTIFF;
744 // lock out other tasks
745 if(AttemptSemaphore(serverLock))
747 struct ServerData sd;
749 // set up the data packet
750 sd.sd_Command = SERVER_READ_LINE;
751 sd.sd_Session = session;
753 // set up the message, send it and wait for a reply
754 msg.mn_Node.ln_Name = (STRPTR)&sd;
755 replyPort.mp_SigTask = FindTask(NULL);
757 PutMsg(serverPort, &msg);
758 Remove((struct Node *)WaitPort(&replyPort));
760 *line = sd.sd_Line;
761 *cset = sd.sd_Codeset;
762 error = sd.sd_Error;
764 // allow other tasks again
765 ReleaseSemaphore(serverLock);
767 else
768 DisplayBeep(0);
770 return error;
774 /// ClipboardServer
775 // the clipboard server process
776 #if defined(__amigaos4__)
777 static LONG ClipboardServer(UNUSED STRPTR args, UNUSED LONG length, struct ExecBase *SysBase)
778 #else
779 static SAVEDS ASM LONG ClipboardServer(UNUSED REG(a0, STRPTR args), UNUSED REG(d0, LONG length))
780 #endif
782 struct Process *me;
783 struct Message *msg;
784 #if defined(__amigaos4__)
785 struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
786 #endif
788 me = (struct Process *)FindTask(NULL);
789 WaitPort(&me->pr_MsgPort);
790 msg = GetMsg(&me->pr_MsgPort);
792 if((IFFParseBase = OpenLibrary("iffparse.library", 36)) != NULL)
794 #if defined(__amigaos4__)
796 if((IIFFParse = (struct IFFParseIFace *)GetInterface(IFFParseBase, "main", 1, NULL)) != NULL)
798 #endif
799 struct MsgPort *mp;
801 #if defined(__amigaos4__)
802 mp = AllocSysObjectTags(ASOT_PORT, TAG_DONE);
803 #else
804 mp = CreateMsgPort();
805 #endif
806 if(mp != NULL)
808 BOOL running = TRUE;
810 // return something as a valid reply
811 msg->mn_Node.ln_Name = (STRPTR)mp;
812 ReplyMsg(msg);
816 WaitPort(mp);
818 while((msg = GetMsg(mp)) != NULL)
820 struct ServerData *sd = (struct ServerData *)msg->mn_Node.ln_Name;
822 switch(sd->sd_Command)
824 case SERVER_SHUTDOWN:
826 running = FALSE;
828 break;
830 case SERVER_START_SESSION:
832 sd->sd_Session = ServerStartSession(sd->sd_Mode);
834 break;
836 case SERVER_END_SESSION:
838 ServerEndSession(sd->sd_Session);
840 break;
842 case SERVER_WRITE_CHARS:
844 ServerWriteChars(sd->sd_Session, sd->sd_Line, sd->sd_Start, sd->sd_Length);
846 break;
848 case SERVER_WRITE_LINE:
850 ServerWriteLine(sd->sd_Session, sd->sd_Line);
852 break;
854 case SERVER_READ_LINE:
856 sd->sd_Error = ServerReadLine(sd->sd_Session, &sd->sd_Line, &sd->sd_Codeset);
858 break;
861 ReplyMsg(msg);
864 while(running == TRUE);
866 #if defined(__amigaos4__)
867 FreeSysObject(ASOT_PORT, mp);
868 #else
869 DeleteMsgPort(mp);
870 #endif
873 #if defined(__amigaos4__)
874 DropInterface((struct Interface *)IIFFParse);
876 #endif
878 CloseLibrary(IFFParseBase);
881 Forbid();
883 return 0;
887 /// StartClipboardServer
888 // launch the clipboard server process
889 // we must use a separate process, because accessing the clipboard via iffparse.library
890 // allocates 2 signals for every instance of this class. Hence we will run out of signals
891 // sooner or later. The separate process avoids this situation.
892 BOOL StartClipboardServer(void)
894 BOOL success = FALSE;
896 ENTER();
898 // create a semaphore to protect several concurrent tasks
899 #if defined(__amigaos4__)
900 serverLock = AllocSysObjectTags(ASOT_SEMAPHORE, TAG_DONE);
901 #else
902 serverLock = AllocVec(sizeof(*serverLock), MEMF_CLEAR);
903 #endif
904 if(serverLock != NULL)
906 #if defined(__amigaos4__)
907 uint32 oldStackSize;
908 #else
909 InitSemaphore(serverLock);
910 #endif
912 #if defined(__amigaos4__)
913 // set a minimum stack size of 8K, no matter what the user has set
914 DosControlTags(DC_MinProcStackR, &oldStackSize,
915 DC_MinProcStackW, 8192,
916 TAG_DONE);
917 #endif
919 // create the server process
920 // this must *NOT* be a child process
921 serverProcess = CreateNewProcTags(NP_Entry, ClipboardServer,
922 NP_Name, "TextEditor.mcc clipboard server",
923 NP_Priority, 1,
924 NP_StackSize, 8192,
925 NP_WindowPtr, ~0L,
926 #if defined(__amigaos4__)
927 NP_Child, FALSE,
928 #elif defined(__MORPHOS__)
929 NP_CodeType, CODETYPE_PPC,
930 #endif
931 TAG_DONE);
932 if(serverProcess != NULL)
934 // we use one global reply port with a static signal bit
935 replyPort.mp_Node.ln_Type = NT_MSGPORT;
936 NewList(&replyPort.mp_MsgList);
937 replyPort.mp_SigBit = SIGB_SINGLE;
938 replyPort.mp_SigTask = FindTask(NULL);
940 msg.mn_ReplyPort = &replyPort;
941 msg.mn_Node.ln_Name = (STRPTR)NULL;
943 // send out the startup message and wait for a reply
944 PutMsg(&serverProcess->pr_MsgPort, &msg);
945 Remove((struct Node *)WaitPort(&replyPort));
947 // check whether everything went ok
948 if((serverPort = (struct MsgPort *)msg.mn_Node.ln_Name) != NULL)
950 success = TRUE;
954 #if defined(__amigaos4__)
955 // restore the old minimum stack size
956 DosControlTags(DC_MinProcStackW, oldStackSize,
957 TAG_DONE);
958 #endif
961 RETURN(success);
962 return success;
966 /// ShutdownClipboardServer
967 // shutdown the server process and clean up
968 void ShutdownClipboardServer(void)
970 if(serverPort != NULL)
972 struct ServerData sd;
974 sd.sd_Command = SERVER_SHUTDOWN;
976 msg.mn_Node.ln_Name = (STRPTR)&sd;
977 replyPort.mp_SigTask = FindTask(NULL);
979 PutMsg(serverPort, &msg);
980 WaitPort(&replyPort);
982 serverPort = NULL;
985 if(serverLock != NULL)
987 #if defined(__amigaos4__)
988 FreeSysObject(ASOT_SEMAPHORE, serverLock);
989 #else
990 FreeVec(serverLock);
991 #endif
993 serverLock = NULL;