Corrections to SVN properties.
[AROS.git] / workbench / classes / zune / nlist / nlisttree_mcc / ClipboardServer.c
blobf5723abac102916e8658e97c0b5416ce8a1970d0
1 /***************************************************************************
3 NList.mcc - New List MUI Custom Class
4 Registered MUI class, Serial Number: 1d51 0x9d510030 to 0x9d5100A0
5 0x9d5100C0 to 0x9d5100FF
7 Copyright (C) 1996-2001 by Gilles Masson
8 Copyright (C) 2001-2013 by NList Open Source Team
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 NList classes Support Site: http://www.sf.net/projects/nlist-classes
22 $Id$
24 ***************************************************************************/
26 #include <string.h>
27 #include <stdlib.h>
29 #include <proto/dos.h>
30 #include <proto/exec.h>
31 #include <proto/intuition.h>
32 #include <proto/keymap.h>
33 #include <proto/locale.h>
35 #include <dos/dostags.h>
36 #include <mui/NList_mcc.h>
38 // for iffparse.library no global variable definitions are needed
39 #define __NOLIBBASE__
40 #define __NOGLOBALIFACE__
41 #include <proto/iffparse.h>
43 #include "private.h"
45 #include "Debug.h"
47 static struct Library *IFFParseBase = NULL;
48 #if defined(__amigaos4__)
49 static struct IFFParseIFace *IIFFParse = NULL;
50 #endif
51 static struct SignalSemaphore *serverLock = NULL;
52 static struct Process *serverProcess = NULL;
53 static struct MsgPort *serverPort = NULL;
54 static struct MsgPort replyPort;
55 static struct Message msg;
57 struct ServerData
59 ULONG sd_Command;
60 ULONG sd_Unit;
61 STRPTR sd_String;
64 #define SERVER_SHUTDOWN 0xdeadf00d
65 #define SERVER_WRITE 0x00000001
67 #define ID_FORM MAKE_ID('F','O','R','M')
68 #define ID_FTXT MAKE_ID('F','T','X','T')
69 #define ID_CHRS MAKE_ID('C','H','R','S')
71 /// StringToClipboard
72 // copy a string to the clipboard, public callable function
73 void StringToClipboard(ULONG unit, STRPTR str)
75 // lock out other tasks
76 if(AttemptSemaphore(serverLock))
78 struct ServerData sd;
80 // set up the data packet
81 sd.sd_Command = SERVER_WRITE;
82 sd.sd_Unit = unit;
83 sd.sd_String = str;
85 if(strlen(str) > 0)
87 // set up the message, send it and wait for a reply
88 msg.mn_Node.ln_Name = (STRPTR)&sd;
89 replyPort.mp_SigTask = FindTask(NULL);
91 PutMsg(serverPort, &msg);
92 Remove((struct Node *)WaitPort(&replyPort));
94 else
95 DisplayBeep(0);
97 // allow other tasks again
98 ReleaseSemaphore(serverLock);
100 else
101 DisplayBeep(0);
105 /// WriteToClipboard
106 // write a given string via iffparse.library to the clipboard
107 // non-public server side function
108 static void WriteToClipboard(ULONG unit, STRPTR str)
110 struct IFFHandle *iff;
112 if((iff = AllocIFF()) != NULL)
114 if((iff->iff_Stream = (IPTR)OpenClipboard(unit)) != 0)
116 InitIFFasClip(iff);
118 if(OpenIFF(iff, IFFF_WRITE) == 0)
120 PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
121 PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN);
122 WriteChunkBytes(iff, str, strlen(str));
123 PopChunk(iff);
124 PopChunk(iff);
126 CloseIFF(iff);
129 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
132 FreeIFF(iff);
137 /// ClipboardServer
138 // the clipboard server process
139 #if defined(__amigaos4__)
140 static LONG ClipboardServer(UNUSED STRPTR args, UNUSED LONG length, struct ExecBase *SysBase)
141 #else
142 static SAVEDS ASM LONG ClipboardServer(UNUSED REG(a0, STRPTR args), UNUSED REG(d0, LONG length))
143 #endif
145 struct Process *me;
146 struct Message *msg;
147 #if defined(__amigaos4__)
148 struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
149 #endif
151 ENTER();
153 D(DBF_CLIPBOARD, "clipboard server starting up");
155 me = (struct Process *)FindTask(NULL);
156 WaitPort(&me->pr_MsgPort);
157 msg = GetMsg(&me->pr_MsgPort);
159 if((IFFParseBase = OpenLibrary("iffparse.library", 36)) != NULL)
161 #if defined(__amigaos4__)
163 if((IIFFParse = (struct IFFParseIFace *)GetInterface(IFFParseBase, "main", 1, NULL)) != NULL)
165 #endif
166 struct MsgPort *mp;
168 #if defined(__amigaos4__)
169 mp = AllocSysObjectTags(ASOT_PORT, TAG_DONE);
170 #else
171 mp = CreateMsgPort();
172 #endif
173 if(mp != NULL)
175 BOOL running = TRUE;
177 // return something as a valid reply
178 msg->mn_Node.ln_Name = (STRPTR)mp;
179 ReplyMsg(msg);
181 D(DBF_CLIPBOARD, "clipboard server main loop");
184 WaitPort(mp);
186 while((msg = GetMsg(mp)) != NULL)
188 struct ServerData *sd = (struct ServerData *)msg->mn_Node.ln_Name;
190 switch(sd->sd_Command)
192 case SERVER_SHUTDOWN:
194 running = FALSE;
196 break;
198 case SERVER_WRITE:
200 WriteToClipboard(sd->sd_Unit, sd->sd_String);
202 break;
205 ReplyMsg(msg);
208 while(running == TRUE);
210 #if defined(__amigaos4__)
211 FreeSysObject(ASOT_PORT, mp);
212 #else
213 DeleteMsgPort(mp);
214 #endif
217 #if defined(__amigaos4__)
218 DropInterface((struct Interface *)IIFFParse);
220 #endif
222 CloseLibrary(IFFParseBase);
225 D(DBF_CLIPBOARD, "clipboard server shutting down");
227 Forbid();
229 LEAVE();
230 return 0;
234 /// StartClipboardServer
235 // launch the clipboard server process
236 // we must use a separate process, because accessing the clipboard via iffparse.library
237 // allocates 2 signals for every instance of this class. Hence we will run out of signals
238 // sooner or later. The separate process avoids this situation.
239 BOOL StartClipboardServer(void)
241 BOOL success = FALSE;
243 ENTER();
245 // create a semaphore to protect several concurrent tasks
246 #if defined(__amigaos4__)
247 serverLock = AllocSysObjectTags(ASOT_SEMAPHORE, TAG_DONE);
248 #else
249 serverLock = AllocVecShared(sizeof(*serverLock), MEMF_CLEAR);
250 #endif
251 if(serverLock != NULL)
253 #if defined(__amigaos4__)
254 uint32 oldStackSize;
255 #else
256 InitSemaphore(serverLock);
257 #endif
259 #if defined(__amigaos4__)
260 // set a minimum stack size of 8K, no matter what the user has set
261 DosControlTags(DC_MinProcStackR, &oldStackSize,
262 DC_MinProcStackW, 8192,
263 TAG_DONE);
264 #endif
266 // create the server process
267 // this must *NOT* be a child process
268 serverProcess = CreateNewProcTags(NP_Entry, ClipboardServer,
269 NP_Name, "NListtree.mcc clipboard server",
270 NP_Priority, 1,
271 NP_StackSize, 8192,
272 NP_WindowPtr, ~0L,
273 #if defined(__amigaos4__)
274 NP_Child, FALSE,
275 #elif defined(__MORPHOS__)
276 NP_CodeType, CODETYPE_PPC,
277 #endif
278 TAG_DONE);
279 if(serverProcess != NULL)
281 // we use one global reply port with a static signal bit
282 replyPort.mp_Node.ln_Type = NT_MSGPORT;
283 NewList(&replyPort.mp_MsgList);
284 replyPort.mp_SigBit = SIGB_SINGLE;
285 replyPort.mp_SigTask = FindTask(NULL);
287 msg.mn_ReplyPort = &replyPort;
288 msg.mn_Node.ln_Name = (STRPTR)NULL;
290 // send out the startup message and wait for a reply
291 PutMsg(&serverProcess->pr_MsgPort, &msg);
292 Remove((struct Node *)WaitPort(&replyPort));
294 // check whether everything went ok
295 if((serverPort = (struct MsgPort *)msg.mn_Node.ln_Name) != NULL)
297 success = TRUE;
301 #if defined(__amigaos4__)
302 // restore the old minimum stack size
303 DosControlTags(DC_MinProcStackW, oldStackSize,
304 TAG_DONE);
305 #endif
308 RETURN(success);
309 return success;
313 /// ShutdownClipboardServer
314 // shutdown the server process and clean up
315 void ShutdownClipboardServer(void)
317 if(serverPort != NULL)
319 struct ServerData sd;
321 sd.sd_Command = SERVER_SHUTDOWN;
323 msg.mn_Node.ln_Name = (STRPTR)&sd;
324 replyPort.mp_SigTask = FindTask(NULL);
326 PutMsg(serverPort, &msg);
327 WaitPort(&replyPort);
329 serverPort = NULL;
332 if(serverLock != NULL)
334 #if defined(__amigaos4__)
335 FreeSysObject(ASOT_SEMAPHORE, serverLock);
336 #else
337 FreeVec(serverLock);
338 #endif
340 serverLock = NULL;