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
21 ***************************************************************************/
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
34 #define __NOGLOBALIFACE__
35 #include <proto/iffparse.h>
40 static struct Library
*IFFParseBase
= NULL
;
41 #if defined(__amigaos4__)
42 static struct IFFParseIFace
*IIFFParse
= NULL
;
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
;
55 struct line_node
*sd_Line
;
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
;
82 if((iff
= AllocIFF()) != NULL
)
84 if((iff
->iff_Stream
= (IPTR
)OpenClipboard(0)) != 0)
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
);
109 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
123 static void ServerEndSession(IPTR session
)
125 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
133 if(iff
->iff_Stream
!= 0)
134 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
144 static void ServerWriteInfo(IPTR session
, struct line_node
*line
)
146 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
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
);
195 static void ServerWriteChars(IPTR session
, struct line_node
*line
, LONG start
, LONG length
)
197 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
199 struct LineStyle style
= {1, GetStyle(start
-1, line
)};
200 struct LineColor color
= {1, 0};
201 struct LineColor
*colors
= line
->line
.Colors
;
205 ServerWriteInfo(session
, line
);
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
;
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
;
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
);
248 UWORD t_style
= style
.style
;
250 if(isFlagSet(t_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
)
277 if(styles
->column
!= EOS
)
279 while(styles
->column
<= start
+length
)
281 style
.column
= styles
->column
- start
;
282 style
.style
= styles
->style
;
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
);
292 UWORD t_style
= style
.style
;
294 if(isFlagSet(t_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
);
332 static void ServerWriteLine(IPTR session
, struct line_node
*line
)
334 struct IFFHandle
*iff
= (struct IFFHandle
*)session
;
336 struct LineStyle
*styles
= line
->line
.Styles
;
337 struct LineColor
*colors
= line
->line
.Colors
;
341 ServerWriteInfo(session
, line
);
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
)
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
);
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
)
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
);
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
;
406 UWORD flow
= MUIV_TextEditor_Flow_Left
;
407 BOOL clearFlow
= FALSE
;
408 BOOL highlight
= FALSE
;
409 UWORD separator
= LNSF_None
;
411 BOOL lineFinished
= FALSE
;
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
)
427 if((cn
= CurrentChunk(iff
)) != NULL
)
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)
442 SHOWVALUE(DBF_CLIPBOARD
, codeset
);
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
);
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
);
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
);
501 ULONG numColors
= cn
->cn_Size
/ sizeof(struct LineColor
);
503 D(DBF_CLIPBOARD
, "reading COLS");
504 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
507 // forget any duplicate colors
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
;
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
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
;
545 ULONG length
= cn
->cn_Size
;
547 D(DBF_CLIPBOARD
, "reading CHRS");
548 SHOWVALUE(DBF_CLIPBOARD
, cn
->cn_Size
);
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
;
589 flow
= MUIV_TextEditor_Flow_Left
;
592 separator
= LNSF_None
;
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.
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
;
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
);
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
);
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
;
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
);
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
;
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
);
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
));
761 *cset
= sd
.sd_Codeset
;
764 // allow other tasks again
765 ReleaseSemaphore(serverLock
);
775 // the clipboard server process
776 #if defined(__amigaos4__)
777 static LONG
ClipboardServer(UNUSED STRPTR args
, UNUSED LONG length
, struct ExecBase
*SysBase
)
779 static SAVEDS ASM LONG
ClipboardServer(UNUSED
REG(a0
, STRPTR args
), UNUSED
REG(d0
, LONG length
))
784 #if defined(__amigaos4__)
785 struct ExecIFace
*IExec
= (struct ExecIFace
*)SysBase
->MainInterface
;
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
)
801 #if defined(__amigaos4__)
802 mp
= AllocSysObjectTags(ASOT_PORT
, TAG_DONE
);
804 mp
= CreateMsgPort();
810 // return something as a valid reply
811 msg
->mn_Node
.ln_Name
= (STRPTR
)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
:
830 case SERVER_START_SESSION
:
832 sd
->sd_Session
= ServerStartSession(sd
->sd_Mode
);
836 case SERVER_END_SESSION
:
838 ServerEndSession(sd
->sd_Session
);
842 case SERVER_WRITE_CHARS
:
844 ServerWriteChars(sd
->sd_Session
, sd
->sd_Line
, sd
->sd_Start
, sd
->sd_Length
);
848 case SERVER_WRITE_LINE
:
850 ServerWriteLine(sd
->sd_Session
, sd
->sd_Line
);
854 case SERVER_READ_LINE
:
856 sd
->sd_Error
= ServerReadLine(sd
->sd_Session
, &sd
->sd_Line
, &sd
->sd_Codeset
);
864 while(running
== TRUE
);
866 #if defined(__amigaos4__)
867 FreeSysObject(ASOT_PORT
, mp
);
873 #if defined(__amigaos4__)
874 DropInterface((struct Interface
*)IIFFParse
);
878 CloseLibrary(IFFParseBase
);
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
;
898 // create a semaphore to protect several concurrent tasks
899 #if defined(__amigaos4__)
900 serverLock
= AllocSysObjectTags(ASOT_SEMAPHORE
, TAG_DONE
);
902 serverLock
= AllocVec(sizeof(*serverLock
), MEMF_CLEAR
);
904 if(serverLock
!= NULL
)
906 #if defined(__amigaos4__)
909 InitSemaphore(serverLock
);
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,
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",
926 #if defined(__amigaos4__)
928 #elif defined(__MORPHOS__)
929 NP_CodeType
, CODETYPE_PPC
,
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
)
954 #if defined(__amigaos4__)
955 // restore the old minimum stack size
956 DosControlTags(DC_MinProcStackW
, oldStackSize
,
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
);
985 if(serverLock
!= NULL
)
987 #if defined(__amigaos4__)
988 FreeSysObject(ASOT_SEMAPHORE
, serverLock
);