revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / zune / texteditor / mcc / ClipboardServer.c
blobd53d37f757693e4efae9b56eab7eb80c370610d6
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
20 $Id$
22 ***************************************************************************/
24 #include <string.h>
25 #include <stdlib.h>
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
34 #define __NOLIBBASE__
35 #define __NOGLOBALIFACE__
36 #include <proto/iffparse.h>
38 #include "private.h"
39 #include "Debug.h"
41 static struct Library *IFFParseBase = NULL;
42 #if defined(__amigaos4__)
43 static struct IFFParseIFace *IIFFParse = NULL;
44 #endif
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;
51 struct ServerData
53 ULONG sd_Command;
54 IPTR sd_Session;
55 ULONG sd_Mode;
56 struct line_node *sd_Line;
57 LONG sd_Start;
58 LONG sd_Length;
59 ULONG sd_Codeset;
60 LONG sd_Error;
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;
81 ENTER();
83 if((iff = AllocIFF()) != NULL)
85 if((iff->iff_Stream = (IPTR)OpenClipboard(0)) != 0)
87 InitIFFasClip(iff);
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);
106 result = (IPTR)iff;
108 else
110 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
111 FreeIFF(iff);
114 else
115 FreeIFF(iff);
118 RETURN(result);
119 return result;
123 /// ServerEndSession
124 static void ServerEndSession(IPTR session)
126 struct IFFHandle *iff = (struct IFFHandle *)session;
128 ENTER();
130 if(iff != NULL)
132 CloseIFF(iff);
134 if(iff->iff_Stream != 0)
135 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
137 FreeIFF(iff);
140 LEAVE();
144 /// ServerWriteInfo
145 static void ServerWriteInfo(IPTR session, struct line_node *line)
147 struct IFFHandle *iff = (struct IFFHandle *)session;
148 LONG error;
150 ENTER();
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);
191 LEAVE();
195 /// ServerWriteChars
196 static void ServerWriteChars(IPTR session, struct line_node *line, LONG start, LONG length)
198 struct IFFHandle *iff = (struct IFFHandle *)session;
199 LONG error;
200 struct LineStyle style = {1, GetStyle(start-1, line)};
201 struct LineColor color = {1, 0};
202 struct LineColor *colors = line->line.Colors;
204 ENTER();
206 ServerWriteInfo(session, line);
208 if(colors != NULL)
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;
217 colors++;
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;
232 colors++;
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);
247 if(style.style != 0)
249 UWORD t_style = style.style;
251 if(isFlagSet(t_style, BOLD))
253 style.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)
276 styles++;
278 if(styles->column != EOS)
280 while(styles->column <= start+length)
282 style.column = styles->column - start;
283 style.style = styles->style;
284 styles++;
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);
291 if(style.style != 0)
293 UWORD t_style = style.style;
295 if(isFlagSet(t_style, BOLD))
297 style.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);
328 LEAVE();
332 /// ServerWriteLine
333 static void ServerWriteLine(IPTR session, struct line_node *line)
335 struct IFFHandle *iff = (struct IFFHandle *)session;
336 LONG error;
337 struct LineStyle *styles = line->line.Styles;
338 struct LineColor *colors = line->line.Colors;
340 ENTER();
342 ServerWriteInfo(session, line);
344 if(colors != NULL)
346 LONG numColors = 0;
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)
354 colors++;
355 numColors++;
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);
365 if(styles != NULL)
367 LONG numStyles = 0;
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)
375 styles++;
376 numStyles++;
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);
394 LEAVE();
398 /// ServerReadLine
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;
405 STRPTR textline;
406 LONG codeset = 0;
407 UWORD flow = MUIV_TextEditor_Flow_Left;
408 BOOL clearFlow = FALSE;
409 BOOL highlight = FALSE;
410 UWORD separator = LNSF_None;
411 LONG error;
412 BOOL lineFinished = FALSE;
414 ENTER();
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)
424 continue;
425 else if(error != 0)
426 break;
428 if((cn = CurrentChunk(iff)) != NULL)
430 switch (cn->cn_ID)
432 case ID_CSET:
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)
441 codeset = 0;
443 SHOWVALUE(DBF_CLIPBOARD, codeset);
446 break;
448 case ID_FLOW:
450 UWORD uwordBool;
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);
469 break;
471 case ID_HIGH:
473 UWORD uwordBool;
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);
485 break;
487 case ID_SBAR:
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);
498 break;
500 case ID_COLS:
502 ULONG numColors = cn->cn_Size / sizeof(struct LineColor);
504 D(DBF_CLIPBOARD, "reading COLS");
505 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
506 if(colors != NULL)
508 // forget any duplicate colors
509 FreeVec(colors);
510 colors = NULL;
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;
520 break;
522 case ID_STYL:
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
531 FreeVec(styles);
532 styles = NULL;
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;
542 break;
544 case ID_CHRS:
546 ULONG length = cn->cn_Size;
548 D(DBF_CLIPBOARD, "reading CHRS");
549 SHOWVALUE(DBF_CLIPBOARD, cn->cn_Size);
551 if(length > 0)
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;
575 lineFinished = TRUE;
576 error = 0;
578 else
580 if(textline != NULL)
581 FreeVec(textline);
582 if(styles != NULL)
583 FreeVec(styles);
584 if(colors != NULL)
585 FreeVec(colors);
588 styles = NULL;
589 colors = NULL;
590 flow = MUIV_TextEditor_Flow_Left;
591 clearFlow = FALSE;
592 highlight = FALSE;
593 separator = LNSF_None;
596 break;
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.
604 if(line == NULL)
606 if(styles != NULL)
607 FreeVec(styles);
608 if(colors != NULL)
609 FreeVec(colors);
612 *linePtr = line;
613 *csetPtr = codeset;
615 RETURN(error);
616 return error;
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;
633 sd.sd_Mode = mode;
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);
647 else
648 DisplayBeep(0);
650 return session;
654 /// ClientEndSession
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);
677 else
678 DisplayBeep(0);
682 /// ClientWriteChars
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;
693 sd.sd_Line = line;
694 sd.sd_Start = start;
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);
707 else
708 DisplayBeep(0);
712 /// ClientWriteLine
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;
723 sd.sd_Line = line;
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);
735 else
736 DisplayBeep(0);
740 /// ClientReadLine
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));
761 *line = sd.sd_Line;
762 *cset = sd.sd_Codeset;
763 error = sd.sd_Error;
765 // allow other tasks again
766 ReleaseSemaphore(serverLock);
768 else
769 DisplayBeep(0);
771 return error;
775 /// ClipboardServer
776 // the clipboard server process
777 #if defined(__amigaos4__)
778 static LONG ClipboardServer(UNUSED STRPTR args, UNUSED LONG length, struct ExecBase *SysBase)
779 #else
780 static SAVEDS ASM LONG ClipboardServer(UNUSED REG(a0, STRPTR args), UNUSED REG(d0, LONG length))
781 #endif
783 struct Process *me;
784 struct Message *msg;
785 #if defined(__amigaos4__)
786 struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
787 #endif
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)
799 #endif
800 struct MsgPort *mp;
802 #if defined(__amigaos4__)
803 mp = AllocSysObjectTags(ASOT_PORT, TAG_DONE);
804 #else
805 mp = CreateMsgPort();
806 #endif
807 if(mp != NULL)
809 BOOL running = TRUE;
811 // return something as a valid reply
812 msg->mn_Node.ln_Name = (STRPTR)mp;
813 ReplyMsg(msg);
817 WaitPort(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:
827 running = FALSE;
829 break;
831 case SERVER_START_SESSION:
833 sd->sd_Session = ServerStartSession(sd->sd_Mode);
835 break;
837 case SERVER_END_SESSION:
839 ServerEndSession(sd->sd_Session);
841 break;
843 case SERVER_WRITE_CHARS:
845 ServerWriteChars(sd->sd_Session, sd->sd_Line, sd->sd_Start, sd->sd_Length);
847 break;
849 case SERVER_WRITE_LINE:
851 ServerWriteLine(sd->sd_Session, sd->sd_Line);
853 break;
855 case SERVER_READ_LINE:
857 sd->sd_Error = ServerReadLine(sd->sd_Session, &sd->sd_Line, &sd->sd_Codeset);
859 break;
862 ReplyMsg(msg);
865 while(running == TRUE);
867 #if defined(__amigaos4__)
868 FreeSysObject(ASOT_PORT, mp);
869 #else
870 DeleteMsgPort(mp);
871 #endif
874 #if defined(__amigaos4__)
875 DropInterface((struct Interface *)IIFFParse);
877 #endif
879 CloseLibrary(IFFParseBase);
882 Forbid();
884 return 0;
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;
897 ENTER();
899 // create a semaphore to protect several concurrent tasks
900 #if defined(__amigaos4__)
901 serverLock = AllocSysObjectTags(ASOT_SEMAPHORE, TAG_DONE);
902 #else
903 serverLock = AllocVec(sizeof(*serverLock), MEMF_CLEAR);
904 #endif
905 if(serverLock != NULL)
907 #if defined(__amigaos4__)
908 uint32 oldStackSize;
909 #else
910 InitSemaphore(serverLock);
911 #endif
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,
917 TAG_DONE);
918 #endif
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",
924 NP_Priority, 1,
925 NP_StackSize, 8192,
926 NP_WindowPtr, ~0L,
927 #if defined(__amigaos4__)
928 NP_Child, FALSE,
929 #elif defined(__MORPHOS__)
930 NP_CodeType, CODETYPE_PPC,
931 #endif
932 TAG_DONE);
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)
952 success = TRUE;
956 #if defined(__amigaos4__)
957 // restore the old minimum stack size
958 DosControlTags(DC_MinProcStackW, oldStackSize,
959 TAG_DONE);
960 #endif
963 RETURN(success);
964 return success;
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);
984 serverPort = NULL;
987 if(serverLock != NULL)
989 #if defined(__amigaos4__)
990 FreeSysObject(ASOT_SEMAPHORE, serverLock);
991 #else
992 FreeVec(serverLock);
993 #endif
995 serverLock = NULL;