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
24 ***************************************************************************/
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
40 #define __NOGLOBALIFACE__
41 #include <proto/iffparse.h>
47 static struct Library
*IFFParseBase
= NULL
;
48 #if defined(__amigaos4__)
49 static struct IFFParseIFace
*IIFFParse
= NULL
;
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
;
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')
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
))
80 // set up the data packet
81 sd
.sd_Command
= SERVER_WRITE
;
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
));
97 // allow other tasks again
98 ReleaseSemaphore(serverLock
);
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)
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
));
129 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
138 // the clipboard server process
139 #if defined(__amigaos4__)
140 static LONG
ClipboardServer(UNUSED STRPTR args
, UNUSED LONG length
, struct ExecBase
*SysBase
)
142 static SAVEDS ASM LONG
ClipboardServer(UNUSED
REG(a0
, STRPTR args
), UNUSED
REG(d0
, LONG length
))
147 #if defined(__amigaos4__)
148 struct ExecIFace
*IExec
= (struct ExecIFace
*)SysBase
->MainInterface
;
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
)
168 #if defined(__amigaos4__)
169 mp
= AllocSysObjectTags(ASOT_PORT
, TAG_DONE
);
171 mp
= CreateMsgPort();
177 // return something as a valid reply
178 msg
->mn_Node
.ln_Name
= (STRPTR
)mp
;
181 D(DBF_CLIPBOARD
, "clipboard server main loop");
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
:
200 WriteToClipboard(sd
->sd_Unit
, sd
->sd_String
);
208 while(running
== TRUE
);
210 #if defined(__amigaos4__)
211 FreeSysObject(ASOT_PORT
, mp
);
217 #if defined(__amigaos4__)
218 DropInterface((struct Interface
*)IIFFParse
);
222 CloseLibrary(IFFParseBase
);
225 D(DBF_CLIPBOARD
, "clipboard server shutting down");
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
;
245 // create a semaphore to protect several concurrent tasks
246 #if defined(__amigaos4__)
247 serverLock
= AllocSysObjectTags(ASOT_SEMAPHORE
, TAG_DONE
);
249 serverLock
= AllocVecShared(sizeof(*serverLock
), MEMF_CLEAR
);
251 if(serverLock
!= NULL
)
253 #if defined(__amigaos4__)
256 InitSemaphore(serverLock
);
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,
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",
273 #if defined(__amigaos4__)
275 #elif defined(__MORPHOS__)
276 NP_CodeType
, CODETYPE_PPC
,
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
)
301 #if defined(__amigaos4__)
302 // restore the old minimum stack size
303 DosControlTags(DC_MinProcStackW
, oldStackSize
,
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
);
332 if(serverLock
!= NULL
)
334 #if defined(__amigaos4__)
335 FreeSysObject(ASOT_SEMAPHORE
, serverLock
);