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
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
;
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')
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)
85 // set up the data packet
86 sd
.sd_Command
= SERVER_WRITE
;
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
;
102 // allow other tasks again
103 ReleaseSemaphore(serverLock
);
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)
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
;
135 result
= MUIV_NLCT_WriteErr
;
142 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
153 // the clipboard server process
154 #if defined(__amigaos4__)
155 static LONG
ClipboardServer(UNUSED STRPTR args
, UNUSED LONG length
, struct ExecBase
*SysBase
)
157 static SAVEDS ASM LONG
ClipboardServer(UNUSED
REG(a0
, STRPTR args
), UNUSED
REG(d0
, LONG length
))
162 #if defined(__amigaos4__)
163 struct ExecIFace
*IExec
= (struct ExecIFace
*)SysBase
->MainInterface
;
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
)
183 #if defined(__amigaos4__)
184 mp
= AllocSysObjectTags(ASOT_PORT
, TAG_DONE
);
186 mp
= CreateMsgPort();
192 // return something as a valid reply
193 msg
->mn_Node
.ln_Name
= (STRPTR
)mp
;
196 D(DBF_CLIPBOARD
, "clipboard server main loop");
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
:
215 sd
->sd_Result
= WriteToClipboard(sd
->sd_Unit
, sd
->sd_String
);
223 while(running
== TRUE
);
225 #if defined(__amigaos4__)
226 FreeSysObject(ASOT_PORT
, mp
);
232 #if defined(__amigaos4__)
233 DropInterface((struct Interface
*)IIFFParse
);
237 CloseLibrary(IFFParseBase
);
240 D(DBF_CLIPBOARD
, "clipboard server shutting down");
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
;
260 // create a semaphore to protect several concurrent tasks
261 #if defined(__amigaos4__)
262 serverLock
= AllocSysObjectTags(ASOT_SEMAPHORE
, TAG_DONE
);
264 serverLock
= AllocVecShared(sizeof(*serverLock
), MEMF_CLEAR
);
266 if(serverLock
!= NULL
)
268 #if defined(__amigaos4__)
271 InitSemaphore(serverLock
);
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,
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",
288 #if defined(__amigaos4__)
290 #elif defined(__MORPHOS__)
291 NP_CodeType
, CODETYPE_PPC
,
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
)
316 #if defined(__amigaos4__)
317 // restore the old minimum stack size
318 DosControlTags(DC_MinProcStackW
, oldStackSize
,
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
);
347 if(serverLock
!= NULL
)
349 #if defined(__amigaos4__)
350 FreeSysObject(ASOT_SEMAPHORE
, serverLock
);