revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / zune / nlist / nlist_mcc / ClipboardServer.c
blobc703712b3b876b2d0fb4fb607ad82015fda2adb2
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) 2017 The AROS Dev Team
8 Copyright (C) 1996-2001 by Gilles Masson
9 Copyright (C) 2001-2014 NList Open Source Team
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 NList classes Support Site: http://www.sf.net/projects/nlist-classes
23 $Id$
25 ***************************************************************************/
27 #include <string.h>
28 #include <stdlib.h>
30 #include <proto/dos.h>
31 #include <proto/exec.h>
32 #include <proto/intuition.h>
33 #include <proto/keymap.h>
34 #include <proto/locale.h>
36 #include <dos/dostags.h>
37 #include <mui/NList_mcc.h>
39 // for iffparse.library no global variable definitions are needed
40 #define __NOLIBBASE__
41 #define __NOGLOBALIFACE__
42 #include <proto/iffparse.h>
44 #include "private.h"
46 #include "Debug.h"
48 static struct Library *IFFParseBase = NULL;
49 #if defined(__amigaos4__)
50 static struct IFFParseIFace *IIFFParse = NULL;
51 #endif
52 static struct SignalSemaphore *serverLock = NULL;
53 static struct Process *serverProcess = NULL;
54 static struct MsgPort *serverPort = NULL;
55 static struct MsgPort replyPort;
56 static struct Message msg;
58 struct ServerData
60 ULONG sd_Command;
61 ULONG sd_Unit;
62 STRPTR sd_String;
63 LONG sd_Result;
66 #define SERVER_SHUTDOWN 0xdeadf00d
67 #define SERVER_WRITE 0x00000001
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')
73 /// StringToClipboard
74 // copy a string to the clipboard, public callable function
75 LONG StringToClipboard(ULONG unit, STRPTR str)
77 LONG result = MUIV_NLCT_Failed;
79 // lock out other tasks
80 if(AttemptSemaphore(serverLock))
82 if(str != NULL && strlen(str) > 0)
84 struct ServerData sd;
86 // set up the data packet
87 sd.sd_Command = SERVER_WRITE;
88 sd.sd_Unit = unit;
89 sd.sd_String = str;
91 // set up the message, send it and wait for a reply
92 msg.mn_Node.ln_Name = (STRPTR)&sd;
93 replyPort.mp_SigTask = FindTask(NULL);
95 PutMsg(serverPort, &msg);
96 Remove((struct Node *)WaitPort(&replyPort));
98 result = sd.sd_Result;
100 else
101 DisplayBeep(0);
103 // allow other tasks again
104 ReleaseSemaphore(serverLock);
106 else
107 DisplayBeep(0);
109 return result;
113 /// WriteToClipboard
114 // write a given string via iffparse.library to the clipboard
115 // non-public server side function
116 static LONG WriteToClipboard(ULONG unit, STRPTR str)
118 LONG result = MUIV_NLCT_Failed;
119 struct IFFHandle *iff;
121 if((iff = AllocIFF()) != NULL)
123 if((iff->iff_Stream = (IPTR)OpenClipboard(unit)) != 0)
125 InitIFFasClip(iff);
127 if(OpenIFF(iff, IFFF_WRITE) == 0)
129 LONG size = strlen(str);
131 PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN);
132 PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN);
133 if(WriteChunkBytes(iff, str, size) == size)
134 result = MUIV_NLCT_Success;
135 else
136 result = MUIV_NLCT_WriteErr;
137 PopChunk(iff);
138 PopChunk(iff);
140 CloseIFF(iff);
143 CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
146 FreeIFF(iff);
149 return result;
153 /// ClipboardServer
154 // the clipboard server process
155 #if defined(__amigaos4__)
156 static LONG ClipboardServer(UNUSED STRPTR args, UNUSED LONG length, struct ExecBase *SysBase)
157 #else
158 static SAVEDS ASM LONG ClipboardServer(UNUSED REG(a0, STRPTR args), UNUSED REG(d0, LONG length))
159 #endif
161 struct Process *me;
162 struct Message *msg;
163 #if defined(__amigaos4__)
164 struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
165 #endif
167 ENTER();
169 D(DBF_CLIPBOARD, "clipboard server starting up");
171 me = (struct Process *)FindTask(NULL);
172 WaitPort(&me->pr_MsgPort);
173 msg = GetMsg(&me->pr_MsgPort);
175 if((IFFParseBase = OpenLibrary("iffparse.library", 36)) != NULL)
177 #if defined(__amigaos4__)
179 if((IIFFParse = (struct IFFParseIFace *)GetInterface(IFFParseBase, "main", 1, NULL)) != NULL)
181 #endif
182 struct MsgPort *mp;
184 #if defined(__amigaos4__)
185 mp = AllocSysObjectTags(ASOT_PORT, TAG_DONE);
186 #else
187 mp = CreateMsgPort();
188 #endif
189 if(mp != NULL)
191 BOOL running = TRUE;
193 // return something as a valid reply
194 msg->mn_Node.ln_Name = (STRPTR)mp;
195 ReplyMsg(msg);
197 D(DBF_CLIPBOARD, "clipboard server main loop");
200 WaitPort(mp);
202 while((msg = GetMsg(mp)) != NULL)
204 struct ServerData *sd = (struct ServerData *)msg->mn_Node.ln_Name;
206 switch(sd->sd_Command)
208 case SERVER_SHUTDOWN:
210 running = FALSE;
212 break;
214 case SERVER_WRITE:
216 sd->sd_Result = WriteToClipboard(sd->sd_Unit, sd->sd_String);
218 break;
221 ReplyMsg(msg);
224 while(running == TRUE);
226 #if defined(__amigaos4__)
227 FreeSysObject(ASOT_PORT, mp);
228 #else
229 DeleteMsgPort(mp);
230 #endif
233 #if defined(__amigaos4__)
234 DropInterface((struct Interface *)IIFFParse);
236 #endif
238 CloseLibrary(IFFParseBase);
241 D(DBF_CLIPBOARD, "clipboard server shutting down");
243 Forbid();
245 LEAVE();
246 return 0;
250 /// StartClipboardServer
251 // launch the clipboard server process
252 // we must use a separate process, because accessing the clipboard via iffparse.library
253 // allocates 2 signals for every instance of this class. Hence we will run out of signals
254 // sooner or later. The separate process avoids this situation.
255 BOOL StartClipboardServer(void)
257 BOOL success = FALSE;
259 ENTER();
261 // create a semaphore to protect several concurrent tasks
262 #if defined(__amigaos4__)
263 serverLock = AllocSysObjectTags(ASOT_SEMAPHORE, TAG_DONE);
264 #else
265 serverLock = AllocVecShared(sizeof(*serverLock), MEMF_CLEAR);
266 #endif
267 if(serverLock != NULL)
269 #if defined(__amigaos4__)
270 uint32 oldStackSize;
271 #else
272 InitSemaphore(serverLock);
273 #endif
275 #if defined(__amigaos4__)
276 // set a minimum stack size of 8K, no matter what the user has set
277 DosControlTags(DC_MinProcStackR, &oldStackSize,
278 DC_MinProcStackW, 8192,
279 TAG_DONE);
280 #endif
282 // create the server process
283 // this must *NOT* be a child process
284 serverProcess = CreateNewProcTags(NP_Entry, ClipboardServer,
285 NP_Name, "NList.mcc clipboard server",
286 NP_Priority, 1,
287 NP_StackSize, 8192,
288 NP_WindowPtr, ~0L,
289 #if defined(__amigaos4__)
290 NP_Child, FALSE,
291 #elif defined(__MORPHOS__)
292 NP_CodeType, CODETYPE_PPC,
293 #endif
294 TAG_DONE);
295 if(serverProcess != NULL)
297 // we use one global reply port with a static signal bit
298 memset( &replyPort, 0, sizeof( replyPort ) );
299 replyPort.mp_Node.ln_Type = NT_MSGPORT;
300 replyPort.mp_SigBit = SIGB_SINGLE;
301 replyPort.mp_SigTask = FindTask(NULL);
302 NewList(&replyPort.mp_MsgList);
304 msg.mn_ReplyPort = &replyPort;
305 msg.mn_Node.ln_Name = (STRPTR)NULL;
307 // send out the startup message and wait for a reply
308 PutMsg(&serverProcess->pr_MsgPort, &msg);
309 Remove((struct Node *)WaitPort(&replyPort));
311 // check whether everything went ok
312 if((serverPort = (struct MsgPort *)msg.mn_Node.ln_Name) != NULL)
314 success = TRUE;
318 #if defined(__amigaos4__)
319 // restore the old minimum stack size
320 DosControlTags(DC_MinProcStackW, oldStackSize,
321 TAG_DONE);
322 #endif
325 RETURN(success);
326 return success;
330 /// ShutdownClipboardServer
331 // shutdown the server process and clean up
332 void ShutdownClipboardServer(void)
334 if(serverPort != NULL)
336 struct ServerData sd;
338 sd.sd_Command = SERVER_SHUTDOWN;
340 msg.mn_Node.ln_Name = (STRPTR)&sd;
341 replyPort.mp_SigTask = FindTask(NULL);
343 PutMsg(serverPort, &msg);
344 WaitPort(&replyPort);
346 serverPort = NULL;
349 if(serverLock != NULL)
351 #if defined(__amigaos4__)
352 FreeSysObject(ASOT_SEMAPHORE, serverLock);
353 #else
354 FreeVec(serverLock);
355 #endif
357 serverLock = NULL;