Merging NList MCC 0.119 into the main branch.
[AROS.git] / workbench / classes / zune / nlist / nlist_mcc / ClipboardServer.c
blob01ce505934064562b8304a68f71e2e7952c9de1c
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-2014 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;
62 LONG sd_Result;
65 #define SERVER_SHUTDOWN 0xdeadf00d
66 #define SERVER_WRITE 0x00000001
68 #define ID_FORM MAKE_ID('F','O','R','M')
69 #define ID_FTXT MAKE_ID('F','T','X','T')
70 #define ID_CHRS MAKE_ID('C','H','R','S')
72 /// StringToClipboard
73 // copy a string to the clipboard, public callable function
74 LONG StringToClipboard(ULONG unit, STRPTR str)
76 LONG result = MUIV_NLCT_Failed;
78 // lock out other tasks
79 if(AttemptSemaphore(serverLock))
81 if(str != NULL && strlen(str) > 0)
83 struct ServerData sd;
85 // set up the data packet
86 sd.sd_Command = SERVER_WRITE;
87 sd.sd_Unit = unit;
88 sd.sd_String = str;
90 // set up the message, send it and wait for a reply
91 msg.mn_Node.ln_Name = (STRPTR)&sd;
92 replyPort.mp_SigTask = FindTask(NULL);
94 PutMsg(serverPort, &msg);
95 Remove((struct Node *)WaitPort(&replyPort));
97 result = sd.sd_Result;
99 else
100 DisplayBeep(0);
102 // allow other tasks again
103 ReleaseSemaphore(serverLock);
105 else
106 DisplayBeep(0);
108 return result;
112 /// WriteToClipboard
113 // write a given string via iffparse.library to the clipboard
114 // non-public server side function
115 static LONG WriteToClipboard(ULONG unit, STRPTR str)
117 LONG result = MUIV_NLCT_Failed;
118 struct IFFHandle *iff;
120 if((iff = AllocIFF()) != NULL)
122 if((iff->iff_Stream = (IPTR)OpenClipboard(unit)) != 0)
124 InitIFFasClip(iff);
126 if(OpenIFF(iff, IFFF_WRITE) == 0)
128 LONG size = strlen(str);
130 PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
131 PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN);
132 if(WriteChunkBytes(iff, str, size) == size)
133 result = MUIV_NLCT_Success;
134 else
135 result = MUIV_NLCT_WriteErr;
136 PopChunk(iff);
137 PopChunk(iff);
139 CloseIFF(iff);
142 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
145 FreeIFF(iff);
148 return result;
152 /// ClipboardServer
153 // the clipboard server process
154 #if defined(__amigaos4__)
155 static LONG ClipboardServer(UNUSED STRPTR args, UNUSED LONG length, struct ExecBase *SysBase)
156 #else
157 static SAVEDS ASM LONG ClipboardServer(UNUSED REG(a0, STRPTR args), UNUSED REG(d0, LONG length))
158 #endif
160 struct Process *me;
161 struct Message *msg;
162 #if defined(__amigaos4__)
163 struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
164 #endif
166 ENTER();
168 D(DBF_CLIPBOARD, "clipboard server starting up");
170 me = (struct Process *)FindTask(NULL);
171 WaitPort(&me->pr_MsgPort);
172 msg = GetMsg(&me->pr_MsgPort);
174 if((IFFParseBase = OpenLibrary("iffparse.library", 36)) != NULL)
176 #if defined(__amigaos4__)
178 if((IIFFParse = (struct IFFParseIFace *)GetInterface(IFFParseBase, "main", 1, NULL)) != NULL)
180 #endif
181 struct MsgPort *mp;
183 #if defined(__amigaos4__)
184 mp = AllocSysObjectTags(ASOT_PORT, TAG_DONE);
185 #else
186 mp = CreateMsgPort();
187 #endif
188 if(mp != NULL)
190 BOOL running = TRUE;
192 // return something as a valid reply
193 msg->mn_Node.ln_Name = (STRPTR)mp;
194 ReplyMsg(msg);
196 D(DBF_CLIPBOARD, "clipboard server main loop");
199 WaitPort(mp);
201 while((msg = GetMsg(mp)) != NULL)
203 struct ServerData *sd = (struct ServerData *)msg->mn_Node.ln_Name;
205 switch(sd->sd_Command)
207 case SERVER_SHUTDOWN:
209 running = FALSE;
211 break;
213 case SERVER_WRITE:
215 sd->sd_Result = WriteToClipboard(sd->sd_Unit, sd->sd_String);
217 break;
220 ReplyMsg(msg);
223 while(running == TRUE);
225 #if defined(__amigaos4__)
226 FreeSysObject(ASOT_PORT, mp);
227 #else
228 DeleteMsgPort(mp);
229 #endif
232 #if defined(__amigaos4__)
233 DropInterface((struct Interface *)IIFFParse);
235 #endif
237 CloseLibrary(IFFParseBase);
240 D(DBF_CLIPBOARD, "clipboard server shutting down");
242 Forbid();
244 LEAVE();
245 return 0;
249 /// StartClipboardServer
250 // launch the clipboard server process
251 // we must use a separate process, because accessing the clipboard via iffparse.library
252 // allocates 2 signals for every instance of this class. Hence we will run out of signals
253 // sooner or later. The separate process avoids this situation.
254 BOOL StartClipboardServer(void)
256 BOOL success = FALSE;
258 ENTER();
260 // create a semaphore to protect several concurrent tasks
261 #if defined(__amigaos4__)
262 serverLock = AllocSysObjectTags(ASOT_SEMAPHORE, TAG_DONE);
263 #else
264 serverLock = AllocVecShared(sizeof(*serverLock), MEMF_CLEAR);
265 #endif
266 if(serverLock != NULL)
268 #if defined(__amigaos4__)
269 uint32 oldStackSize;
270 #else
271 InitSemaphore(serverLock);
272 #endif
274 #if defined(__amigaos4__)
275 // set a minimum stack size of 8K, no matter what the user has set
276 DosControlTags(DC_MinProcStackR, &oldStackSize,
277 DC_MinProcStackW, 8192,
278 TAG_DONE);
279 #endif
281 // create the server process
282 // this must *NOT* be a child process
283 serverProcess = CreateNewProcTags(NP_Entry, ClipboardServer,
284 NP_Name, "NList.mcc clipboard server",
285 NP_Priority, 1,
286 NP_StackSize, 8192,
287 NP_WindowPtr, ~0L,
288 #if defined(__amigaos4__)
289 NP_Child, FALSE,
290 #elif defined(__MORPHOS__)
291 NP_CodeType, CODETYPE_PPC,
292 #endif
293 TAG_DONE);
294 if(serverProcess != NULL)
296 // we use one global reply port with a static signal bit
297 replyPort.mp_Node.ln_Type = NT_MSGPORT;
298 NewList(&replyPort.mp_MsgList);
299 replyPort.mp_SigBit = SIGB_SINGLE;
300 replyPort.mp_SigTask = FindTask(NULL);
302 msg.mn_ReplyPort = &replyPort;
303 msg.mn_Node.ln_Name = (STRPTR)NULL;
305 // send out the startup message and wait for a reply
306 PutMsg(&serverProcess->pr_MsgPort, &msg);
307 Remove((struct Node *)WaitPort(&replyPort));
309 // check whether everything went ok
310 if((serverPort = (struct MsgPort *)msg.mn_Node.ln_Name) != NULL)
312 success = TRUE;
316 #if defined(__amigaos4__)
317 // restore the old minimum stack size
318 DosControlTags(DC_MinProcStackW, oldStackSize,
319 TAG_DONE);
320 #endif
323 RETURN(success);
324 return success;
328 /// ShutdownClipboardServer
329 // shutdown the server process and clean up
330 void ShutdownClipboardServer(void)
332 if(serverPort != NULL)
334 struct ServerData sd;
336 sd.sd_Command = SERVER_SHUTDOWN;
338 msg.mn_Node.ln_Name = (STRPTR)&sd;
339 replyPort.mp_SigTask = FindTask(NULL);
341 PutMsg(serverPort, &msg);
342 WaitPort(&replyPort);
344 serverPort = NULL;
347 if(serverLock != NULL)
349 #if defined(__amigaos4__)
350 FreeSysObject(ASOT_SEMAPHORE, serverLock);
351 #else
352 FreeVec(serverLock);
353 #endif
355 serverLock = NULL;