1 /***************************************************************************
3 TextEditor.mcc - Textediting MUI Custom Class
4 Copyright (C) 2017 The AROS Dev Team
5 Copyright (C) 1997-2000 Allan Odgaard
6 Copyright (C) 2005-2014 TextEditor.mcc Open Source Team
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 TextEditor class Support Site: http://www.sf.net/projects/texteditor-mcc
22 ***************************************************************************/
27 #include <proto/dos.h>
28 #include <proto/exec.h>
29 #include <proto/intuition.h>
31 #include <dos/dostags.h>
33 // for iffparse.library no global variable definitions are needed
35 #define __NOGLOBALIFACE__
36 #include <proto/iffparse.h>
41 static struct Library
*IFFParseBase
= NULL
;
42 #if defined(__amigaos4__)
43 static struct IFFParseIFace
*IIFFParse
= NULL
;
45 static struct SignalSemaphore
*serverLock
= NULL
;
46 static struct Process
*serverProcess
= NULL
;
47 static struct MsgPort
*serverPort
= NULL
;
48 static struct MsgPort replyPort
;
49 static struct Message msg
;
56 struct line_node
*sd_Line
;
63 #define SERVER_SHUTDOWN 0xdeadf00d
64 #define SERVER_START_SESSION 0x00000001
65 #define SERVER_WRITE_CHARS 0x00000002
66 #define SERVER_WRITE_LINE 0x00000003
67 #define SERVER_READ_LINE 0x00000004
68 #define SERVER_END_SESSION 0x0000000f
70 #define ID_FORM MAKE_ID('F','O','R','M')
71 #define ID_FTXT MAKE_ID('F','T','X','T')
72 #define ID_CHRS MAKE_ID('C','H','R','S')
73 #define ID_CSET MAKE_ID('C','S','E','T')
75 /// ServerStartSession
76 static IPTR
ServerStartSession(ULONG mode
)
78 IPTR result
= (IPTR
)NULL
;
79 struct IFFHandle
*iff
;
83 if((iff
= AllocIFF()) != NULL
)
85 if((iff
->iff_Stream
= (IPTR
)OpenClipboard(0)) != 0)
89 if(OpenIFF(iff
, mode
) == 0)
91 if(mode
== IFFF_WRITE
)
93 PushChunk(iff
, ID_FTXT
, ID_FORM
, IFFSIZE_UNKNOWN
);
95 else if(mode
== IFFF_READ
)
97 StopChunk(iff
, ID_FTXT
, ID_CHRS
);
98 StopChunk(iff
, ID_FTXT
, ID_FLOW
);
99 StopChunk(iff
, ID_FTXT
, ID_HIGH
);
100 StopChunk(iff
, ID_FTXT
, ID_SBAR
);
101 StopChunk(iff
, ID_FTXT
, ID_COLS
);
102 StopChunk(iff
, ID_FTXT
, ID_STYL
);
103 StopChunk(iff
, ID_FTXT
, ID_CSET
);
110 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
124 static void ServerEndSession(IPTR session
)
126 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
134 if(iff
->iff_Stream
!= 0)
135 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
145 static void ServerWriteInfo(IPTR session
, struct line_node
*line
)
147 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
152 if(line
->line
.Flow
!= MUIV_TextEditor_Flow_Left
|| line
->line
.clearFlow
== TRUE
)
154 UWORD uwordBool
= line
->line
.clearFlow
;
156 D(DBF_CLIPBOARD
, "writing FLOW");
157 error
= PushChunk(iff
, 0, ID_FLOW
, IFFSIZE_UNKNOWN
);
158 SHOWVALUE(DBF_CLIPBOARD
, error
);
159 error
= WriteChunkBytes(iff
, &line
->line
.Flow
, 2);
160 SHOWVALUE(DBF_CLIPBOARD
, error
);
161 error
= WriteChunkBytes(iff
, &uwordBool
, 2);
162 SHOWVALUE(DBF_CLIPBOARD
, error
);
163 error
= PopChunk(iff
);
164 SHOWVALUE(DBF_CLIPBOARD
, error
);
167 if(line
->line
.Separator
!= LNSF_None
)
169 D(DBF_CLIPBOARD
, "writing SBAR");
170 error
= PushChunk(iff
, 0, ID_SBAR
, IFFSIZE_UNKNOWN
);
171 SHOWVALUE(DBF_CLIPBOARD
, error
);
172 error
= WriteChunkBytes(iff
, &line
->line
.Separator
, 2);
173 SHOWVALUE(DBF_CLIPBOARD
, error
);
174 error
= PopChunk(iff
);
175 SHOWVALUE(DBF_CLIPBOARD
, error
);
178 if(line
->line
.Highlight
== TRUE
)
180 UWORD uwordBool
= TRUE
;
182 D(DBF_CLIPBOARD
, "writing HIGH");
183 error
= PushChunk(iff
, 0, ID_HIGH
, IFFSIZE_UNKNOWN
);
184 SHOWVALUE(DBF_CLIPBOARD
, error
);
185 error
= WriteChunkBytes(iff
, &uwordBool
, sizeof(uwordBool
));
186 SHOWVALUE(DBF_CLIPBOARD
, error
);
187 error
= PopChunk(iff
);
188 SHOWVALUE(DBF_CLIPBOARD
, error
);
196 static void ServerWriteChars(IPTR session
, struct line_node
*line
, LONG start
, LONG length
)
198 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
200 struct LineStyle style
= {1, GetStyle(start
-1, line
)};
201 struct LineColor color
= {1, 0};
202 struct LineColor
*colors
= line
->line
.Colors
;
206 ServerWriteInfo(session
, line
);
210 D(DBF_CLIPBOARD
, "writing COLS");
211 error
= PushChunk(iff
, 0, ID_COLS
, IFFSIZE_UNKNOWN
);
212 SHOWVALUE(DBF_CLIPBOARD
, error
);
214 while(colors
->column
<= start
&& colors
->column
!= EOC
)
216 color
.color
= colors
->color
;
220 if(color
.color
!= 0 && colors
->column
-start
!= 1)
222 error
= WriteChunkBytes(iff
, &color
, sizeof(color
));
223 SHOWVALUE(DBF_CLIPBOARD
, error
);
226 if(colors
->column
!= EOC
)
228 while(colors
->column
<= start
+length
)
230 color
.column
= colors
->column
- start
;
231 color
.color
= colors
->color
;
234 error
= WriteChunkBytes(iff
, &color
, sizeof(color
));
235 SHOWVALUE(DBF_CLIPBOARD
, error
);
239 error
= PopChunk(iff
);
240 SHOWVALUE(DBF_CLIPBOARD
, error
);
243 D(DBF_CLIPBOARD
, "writing STYL");
244 error
= PushChunk(iff
, 0, ID_STYL
, IFFSIZE_UNKNOWN
);
245 SHOWVALUE(DBF_CLIPBOARD
, error
);
249 UWORD t_style
= style
.style
;
251 if(isFlagSet(t_style
, BOLD
))
254 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
255 SHOWVALUE(DBF_CLIPBOARD
, error
);
257 if(isFlagSet(t_style
, ITALIC
))
259 style
.style
= ITALIC
;
260 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
261 SHOWVALUE(DBF_CLIPBOARD
, error
);
263 if(isFlagSet(t_style
, UNDERLINE
))
265 style
.style
= UNDERLINE
;
266 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
267 SHOWVALUE(DBF_CLIPBOARD
, error
);
271 if(line
->line
.Styles
!= NULL
)
273 struct LineStyle
*styles
= line
->line
.Styles
;
275 while(styles
->column
<= start
&& styles
->column
!= EOS
)
278 if(styles
->column
!= EOS
)
280 while(styles
->column
<= start
+length
)
282 style
.column
= styles
->column
- start
;
283 style
.style
= styles
->style
;
285 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
286 SHOWVALUE(DBF_CLIPBOARD
, error
);
289 style
.column
= length
+1;
290 style
.style
= GetStyle(start
+length
-1, line
);
293 UWORD t_style
= style
.style
;
295 if(isFlagSet(t_style
, BOLD
))
298 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
299 SHOWVALUE(DBF_CLIPBOARD
, error
);
301 if(isFlagSet(t_style
, ITALIC
))
303 style
.style
= ~ITALIC
;
304 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
305 SHOWVALUE(DBF_CLIPBOARD
, error
);
307 if(isFlagSet(t_style
, UNDERLINE
))
309 style
.style
= ~UNDERLINE
;
310 error
= WriteChunkBytes(iff
, &style
, sizeof(style
));
311 SHOWVALUE(DBF_CLIPBOARD
, error
);
317 error
= PopChunk(iff
);
318 SHOWVALUE(DBF_CLIPBOARD
, error
);
320 D(DBF_CLIPBOARD
, "writing CHRS");
321 error
= PushChunk(iff
, 0, ID_CHRS
, IFFSIZE_UNKNOWN
);
322 SHOWVALUE(DBF_CLIPBOARD
, error
);
323 error
= WriteChunkBytes(iff
, line
->line
.Contents
+ start
, length
);
324 SHOWVALUE(DBF_CLIPBOARD
, error
);
325 error
= PopChunk(iff
);
326 SHOWVALUE(DBF_CLIPBOARD
, error
);
333 static void ServerWriteLine(IPTR session
, struct line_node
*line
)
335 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
337 struct LineStyle
*styles
= line
->line
.Styles
;
338 struct LineColor
*colors
= line
->line
.Colors
;
342 ServerWriteInfo(session
, line
);
348 D(DBF_CLIPBOARD
, "writing COLS");
349 error
= PushChunk(iff
, 0, ID_COLS
, IFFSIZE_UNKNOWN
);
350 SHOWVALUE(DBF_CLIPBOARD
, error
);
352 while(colors
->column
!= EOC
)
358 SHOWVALUE(DBF_CLIPBOARD
, numColors
);
359 error
= WriteChunkBytes(iff
, line
->line
.Colors
, numColors
* sizeof(*colors
));
360 SHOWVALUE(DBF_CLIPBOARD
, error
);
361 error
= PopChunk(iff
);
362 SHOWVALUE(DBF_CLIPBOARD
, error
);
369 D(DBF_CLIPBOARD
, "writing STYL");
370 error
= PushChunk(iff
, 0, ID_STYL
, IFFSIZE_UNKNOWN
);
371 SHOWVALUE(DBF_CLIPBOARD
, error
);
373 while(styles
->column
!= EOS
)
379 SHOWVALUE(DBF_CLIPBOARD
, numStyles
);
380 error
= WriteChunkBytes(iff
, line
->line
.Styles
, numStyles
* sizeof(*styles
));
381 SHOWVALUE(DBF_CLIPBOARD
, error
);
382 error
= PopChunk(iff
);
383 SHOWVALUE(DBF_CLIPBOARD
, error
);
386 D(DBF_CLIPBOARD
, "writing CHRS");
387 error
= PushChunk(iff
, 0, ID_CHRS
, IFFSIZE_UNKNOWN
);
388 SHOWVALUE(DBF_CLIPBOARD
, error
);
389 error
= WriteChunkBytes(iff
, line
->line
.Contents
, line
->line
.Length
);
390 SHOWVALUE(DBF_CLIPBOARD
, error
);
391 error
= PopChunk(iff
);
392 SHOWVALUE(DBF_CLIPBOARD
, error
);
399 static LONG
ServerReadLine(IPTR session
, struct line_node
**linePtr
, ULONG
*csetPtr
)
401 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
402 struct line_node
*line
= NULL
;
403 struct LineStyle
*styles
= NULL
;
404 struct LineColor
*colors
= NULL
;
407 UWORD flow
= MUIV_TextEditor_Flow_Left
;
408 BOOL clearFlow
= FALSE
;
409 BOOL highlight
= FALSE
;
410 UWORD separator
= LNSF_None
;
412 BOOL lineFinished
= FALSE
;
416 D(DBF_CLIPBOARD
, "server reading next line");
419 struct ContextNode
*cn
;
421 error
= ParseIFF(iff
, IFFPARSE_SCAN
);
422 SHOWVALUE(DBF_CLIPBOARD
, error
);
423 if(error
== IFFERR_EOC
)
428 if((cn
= CurrentChunk(iff
)) != NULL
)
434 D(DBF_CLIPBOARD
, "reading CSET");
435 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
436 if(cn
->cn_Size
>= (LONG
)sizeof(codeset
))
438 /* Only the first four bytes are interesting */
439 if(ReadChunkBytes(iff
, &codeset
, 4) != 4)
443 SHOWVALUE(DBF_CLIPBOARD
, codeset
);
452 D(DBF_CLIPBOARD
, "reading FLOW");
453 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
454 if(cn
->cn_Size
>= (LONG
)(sizeof(flow
)+sizeof(uwordBool
)))
456 if((error
= ReadChunkBytes(iff
, &flow
, sizeof(flow
))) == 2)
458 if(flow
> MUIV_TextEditor_Flow_Right
)
459 flow
= MUIV_TextEditor_Flow_Left
;
461 SHOWVALUE(DBF_CLIPBOARD
, flow
);
462 SHOWVALUE(DBF_CLIPBOARD
, error
);
463 error
= ReadChunkBytes(iff
, &uwordBool
, 2);
464 clearFlow
= (uwordBool
!= 0) ? TRUE
: FALSE
;
465 SHOWVALUE(DBF_CLIPBOARD
, clearFlow
);
466 SHOWVALUE(DBF_CLIPBOARD
, error
);
475 D(DBF_CLIPBOARD
, "reading HIGH");
476 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
477 if(cn
->cn_Size
>= (LONG
)sizeof(uwordBool
))
479 error
= ReadChunkBytes(iff
, &uwordBool
, 2);
480 highlight
= (uwordBool
!= 0) ? TRUE
: FALSE
;
481 SHOWVALUE(DBF_CLIPBOARD
, highlight
);
482 SHOWVALUE(DBF_CLIPBOARD
, error
);
489 D(DBF_CLIPBOARD
, "reading SBAR");
490 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
491 if (cn
->cn_Size
>= (LONG
)sizeof(separator
))
493 error
= ReadChunkBytes(iff
, &separator
, 2);
494 SHOWVALUE(DBF_CLIPBOARD
, separator
);
495 SHOWVALUE(DBF_CLIPBOARD
, error
);
502 ULONG numColors
= cn
->cn_Size
/ sizeof(struct LineColor
);
504 D(DBF_CLIPBOARD
, "reading COLS");
505 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
508 // forget any duplicate colors
512 // allocate one word more than the chunk tell us, because we terminate the array with EOC
513 if(numColors
> 0 && (colors
= AllocVecShared((numColors
+1) * sizeof(*colors
), MEMF_ANY
)) != NULL
)
515 error
= ReadChunkBytes(iff
, colors
, numColors
* sizeof(struct LineColor
));
516 SHOWVALUE(DBF_CLIPBOARD
, error
);
517 colors
[numColors
].column
= EOC
;
524 ULONG numStyles
= cn
->cn_Size
/ sizeof(struct LineStyle
);
526 D(DBF_CLIPBOARD
, "reading STYL");
527 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
528 if(styles
!= NULL
&& styles
!= (APTR
)-1)
530 // forget any duplicate styles
534 // allocate one word more than the chunk tell us, because we terminate the array with EOS
535 if(numStyles
> 0 && (styles
= AllocVecShared((numStyles
+1) * sizeof(struct LineStyle
), MEMF_ANY
)) != NULL
)
537 error
= ReadChunkBytes(iff
, styles
, numStyles
* sizeof(struct LineStyle
));
538 SHOWVALUE(DBF_CLIPBOARD
, error
);
539 styles
[numStyles
].column
= EOS
;
546 ULONG length
= cn
->cn_Size
;
548 D(DBF_CLIPBOARD
, "reading CHRS");
549 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
553 // allocate 2 additional bytes:
554 // - one for the trailing LF
555 // - another one for the terminating NUL
556 if((textline
= AllocVecShared(length
+ 2, MEMF_ANY
)) != NULL
)
558 error
= ReadChunkBytes(iff
, textline
, length
);
559 SHOWVALUE(DBF_CLIPBOARD
, error
);
560 textline
[length
] = '\0';
563 if(textline
!= NULL
&& (line
= AllocVecShared(sizeof(*line
), MEMF_ANY
|MEMF_CLEAR
)) != NULL
)
565 line
->line
.Contents
= textline
;
566 line
->line
.Length
= length
;
567 line
->line
.allocatedContents
= length
+2;
568 line
->line
.Highlight
= highlight
;
569 line
->line
.Flow
= flow
;
570 line
->line
.clearFlow
= clearFlow
;
571 line
->line
.Separator
= separator
;
572 line
->line
.Styles
= styles
;
573 line
->line
.Colors
= colors
;
590 flow
= MUIV_TextEditor_Flow_Left
;
593 separator
= LNSF_None
;
600 while(lineFinished
== FALSE
);
602 // in case we didn't read a complete line but at least some other of our
603 // chunks we free them here to avoid leaks.
620 /// ClientStartSession
621 // copy a line to the clipboard, public callable function
622 IPTR
ClientStartSession(ULONG mode
)
624 IPTR session
= (IPTR
)NULL
;
626 // lock out other tasks
627 if(AttemptSemaphore(serverLock
))
629 struct ServerData sd
;
631 // set up the data packet
632 sd
.sd_Command
= SERVER_START_SESSION
;
635 // set up the message, send it and wait for a reply
636 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
637 replyPort
.mp_SigTask
= FindTask(NULL
);
639 PutMsg(serverPort
, &msg
);
640 Remove((struct Node
*)WaitPort(&replyPort
));
642 session
= sd
.sd_Session
;
644 // allow other tasks again
645 ReleaseSemaphore(serverLock
);
655 // copy a line to the clipboard, public callable function
656 void ClientEndSession(IPTR session
)
658 // lock out other tasks
659 if(AttemptSemaphore(serverLock
))
661 struct ServerData sd
;
663 // set up the data packet
664 sd
.sd_Command
= SERVER_END_SESSION
;
665 sd
.sd_Session
= session
;
667 // set up the message, send it and wait for a reply
668 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
669 replyPort
.mp_SigTask
= FindTask(NULL
);
671 PutMsg(serverPort
, &msg
);
672 Remove((struct Node
*)WaitPort(&replyPort
));
674 // allow other tasks again
675 ReleaseSemaphore(serverLock
);
683 void ClientWriteChars(IPTR session
, struct line_node
*line
, LONG start
, LONG length
)
685 // lock out other tasks
686 if(AttemptSemaphore(serverLock
))
688 struct ServerData sd
;
690 // set up the data packet
691 sd
.sd_Command
= SERVER_WRITE_CHARS
;
692 sd
.sd_Session
= session
;
695 sd
.sd_Length
= length
;
697 // set up the message, send it and wait for a reply
698 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
699 replyPort
.mp_SigTask
= FindTask(NULL
);
701 PutMsg(serverPort
, &msg
);
702 Remove((struct Node
*)WaitPort(&replyPort
));
704 // allow other tasks again
705 ReleaseSemaphore(serverLock
);
713 void ClientWriteLine(IPTR session
, struct line_node
*line
)
715 // lock out other tasks
716 if(AttemptSemaphore(serverLock
))
718 struct ServerData sd
;
720 // set up the data packet
721 sd
.sd_Command
= SERVER_WRITE_LINE
;
722 sd
.sd_Session
= session
;
725 // set up the message, send it and wait for a reply
726 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
727 replyPort
.mp_SigTask
= FindTask(NULL
);
729 PutMsg(serverPort
, &msg
);
730 Remove((struct Node
*)WaitPort(&replyPort
));
732 // allow other tasks again
733 ReleaseSemaphore(serverLock
);
741 LONG
ClientReadLine(IPTR session
, struct line_node
**line
, ULONG
*cset
)
743 LONG error
= IFFERR_NOTIFF
;
745 // lock out other tasks
746 if(AttemptSemaphore(serverLock
))
748 struct ServerData sd
;
750 // set up the data packet
751 sd
.sd_Command
= SERVER_READ_LINE
;
752 sd
.sd_Session
= session
;
754 // set up the message, send it and wait for a reply
755 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
756 replyPort
.mp_SigTask
= FindTask(NULL
);
758 PutMsg(serverPort
, &msg
);
759 Remove((struct Node
*)WaitPort(&replyPort
));
762 *cset
= sd
.sd_Codeset
;
765 // allow other tasks again
766 ReleaseSemaphore(serverLock
);
776 // the clipboard server process
777 #if defined(__amigaos4__)
778 static LONG
ClipboardServer(UNUSED STRPTR args
, UNUSED LONG length
, struct ExecBase
*SysBase
)
780 static SAVEDS ASM LONG
ClipboardServer(UNUSED
REG(a0
, STRPTR args
), UNUSED
REG(d0
, LONG length
))
785 #if defined(__amigaos4__)
786 struct ExecIFace
*IExec
= (struct ExecIFace
*)SysBase
->MainInterface
;
789 me
= (struct Process
*)FindTask(NULL
);
790 WaitPort(&me
->pr_MsgPort
);
791 msg
= GetMsg(&me
->pr_MsgPort
);
793 if((IFFParseBase
= OpenLibrary("iffparse.library", 36)) != NULL
)
795 #if defined(__amigaos4__)
797 if((IIFFParse
= (struct IFFParseIFace
*)GetInterface(IFFParseBase
, "main", 1, NULL
)) != NULL
)
802 #if defined(__amigaos4__)
803 mp
= AllocSysObjectTags(ASOT_PORT
, TAG_DONE
);
805 mp
= CreateMsgPort();
811 // return something as a valid reply
812 msg
->mn_Node
.ln_Name
= (STRPTR
)mp
;
819 while((msg
= GetMsg(mp
)) != NULL
)
821 struct ServerData
*sd
= (struct ServerData
*)msg
->mn_Node
.ln_Name
;
823 switch(sd
->sd_Command
)
825 case SERVER_SHUTDOWN
:
831 case SERVER_START_SESSION
:
833 sd
->sd_Session
= ServerStartSession(sd
->sd_Mode
);
837 case SERVER_END_SESSION
:
839 ServerEndSession(sd
->sd_Session
);
843 case SERVER_WRITE_CHARS
:
845 ServerWriteChars(sd
->sd_Session
, sd
->sd_Line
, sd
->sd_Start
, sd
->sd_Length
);
849 case SERVER_WRITE_LINE
:
851 ServerWriteLine(sd
->sd_Session
, sd
->sd_Line
);
855 case SERVER_READ_LINE
:
857 sd
->sd_Error
= ServerReadLine(sd
->sd_Session
, &sd
->sd_Line
, &sd
->sd_Codeset
);
865 while(running
== TRUE
);
867 #if defined(__amigaos4__)
868 FreeSysObject(ASOT_PORT
, mp
);
874 #if defined(__amigaos4__)
875 DropInterface((struct Interface
*)IIFFParse
);
879 CloseLibrary(IFFParseBase
);
888 /// StartClipboardServer
889 // launch the clipboard server process
890 // we must use a separate process, because accessing the clipboard via iffparse.library
891 // allocates 2 signals for every instance of this class. Hence we will run out of signals
892 // sooner or later. The separate process avoids this situation.
893 BOOL
StartClipboardServer(void)
895 BOOL success
= FALSE
;
899 // create a semaphore to protect several concurrent tasks
900 #if defined(__amigaos4__)
901 serverLock
= AllocSysObjectTags(ASOT_SEMAPHORE
, TAG_DONE
);
903 serverLock
= AllocVec(sizeof(*serverLock
), MEMF_CLEAR
);
905 if(serverLock
!= NULL
)
907 #if defined(__amigaos4__)
910 InitSemaphore(serverLock
);
913 #if defined(__amigaos4__)
914 // set a minimum stack size of 8K, no matter what the user has set
915 DosControlTags(DC_MinProcStackR
, &oldStackSize
,
916 DC_MinProcStackW
, 8192,
920 // create the server process
921 // this must *NOT* be a child process
922 serverProcess
= CreateNewProcTags(NP_Entry
, ClipboardServer
,
923 NP_Name
, "TextEditor.mcc clipboard server",
927 #if defined(__amigaos4__)
929 #elif defined(__MORPHOS__)
930 NP_CodeType
, CODETYPE_PPC
,
933 if(serverProcess
!= NULL
)
935 // we use one global reply port with a static signal bit
936 memset( &replyPort
, 0, sizeof( replyPort
) );
937 replyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
938 NewList(&replyPort
.mp_MsgList
);
939 replyPort
.mp_SigBit
= SIGB_SINGLE
;
940 replyPort
.mp_SigTask
= FindTask(NULL
);
942 msg
.mn_ReplyPort
= &replyPort
;
943 msg
.mn_Node
.ln_Name
= (STRPTR
)NULL
;
945 // send out the startup message and wait for a reply
946 PutMsg(&serverProcess
->pr_MsgPort
, &msg
);
947 Remove((struct Node
*)WaitPort(&replyPort
));
949 // check whether everything went ok
950 if((serverPort
= (struct MsgPort
*)msg
.mn_Node
.ln_Name
) != NULL
)
956 #if defined(__amigaos4__)
957 // restore the old minimum stack size
958 DosControlTags(DC_MinProcStackW
, oldStackSize
,
968 /// ShutdownClipboardServer
969 // shutdown the server process and clean up
970 void ShutdownClipboardServer(void)
972 if(serverPort
!= NULL
)
974 struct ServerData sd
;
976 sd
.sd_Command
= SERVER_SHUTDOWN
;
978 msg
.mn_Node
.ln_Name
= (STRPTR
)&sd
;
979 replyPort
.mp_SigTask
= FindTask(NULL
);
981 PutMsg(serverPort
, &msg
);
982 WaitPort(&replyPort
);
987 if(serverLock
!= NULL
)
989 #if defined(__amigaos4__)
990 FreeSysObject(ASOT_SEMAPHORE
, serverLock
);