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
25 ***************************************************************************/
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
41 #define __NOGLOBALIFACE__
42 #include <proto/iffparse.h>
48 static struct Library
*IFFParseBase
= NULL
;
49 #if defined(__amigaos4__)
50 static struct IFFParseIFace
*IIFFParse
= NULL
;
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
;
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')
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)
86 // set up the data packet
87 sd
.sd_Command
= SERVER_WRITE
;
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
;
103 // allow other tasks again
104 ReleaseSemaphore(serverLock
);
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)
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
;
136 result
= MUIV_NLCT_WriteErr
;
143 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
154 // the clipboard server process
155 #if defined(__amigaos4__)
156 static LONG
ClipboardServer(UNUSED STRPTR args
, UNUSED LONG length
, struct ExecBase
*SysBase
)
158 static SAVEDS ASM LONG
ClipboardServer(UNUSED
REG(a0
, STRPTR args
), UNUSED
REG(d0
, LONG length
))
163 #if defined(__amigaos4__)
164 struct ExecIFace
*IExec
= (struct ExecIFace
*)SysBase
->MainInterface
;
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
)
184 #if defined(__amigaos4__)
185 mp
= AllocSysObjectTags(ASOT_PORT
, TAG_DONE
);
187 mp
= CreateMsgPort();
193 // return something as a valid reply
194 msg
->mn_Node
.ln_Name
= (STRPTR
)mp
;
197 D(DBF_CLIPBOARD
, "clipboard server main loop");
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
:
216 sd
->sd_Result
= WriteToClipboard(sd
->sd_Unit
, sd
->sd_String
);
224 while(running
== TRUE
);
226 #if defined(__amigaos4__)
227 FreeSysObject(ASOT_PORT
, mp
);
233 #if defined(__amigaos4__)
234 DropInterface((struct Interface
*)IIFFParse
);
238 CloseLibrary(IFFParseBase
);
241 D(DBF_CLIPBOARD
, "clipboard server shutting down");
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
;
261 // create a semaphore to protect several concurrent tasks
262 #if defined(__amigaos4__)
263 serverLock
= AllocSysObjectTags(ASOT_SEMAPHORE
, TAG_DONE
);
265 serverLock
= AllocVecShared(sizeof(*serverLock
), MEMF_CLEAR
);
267 if(serverLock
!= NULL
)
269 #if defined(__amigaos4__)
272 InitSemaphore(serverLock
);
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,
282 // create the server process
283 // this must *NOT* be a child process
284 serverProcess
= CreateNewProcTags(NP_Entry
, ClipboardServer
,
285 NP_Name
, "NListtree.mcc clipboard server",
289 #if defined(__amigaos4__)
291 #elif defined(__MORPHOS__)
292 NP_CodeType
, CODETYPE_PPC
,
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
)
318 #if defined(__amigaos4__)
319 // restore the old minimum stack size
320 DosControlTags(DC_MinProcStackW
, oldStackSize
,
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
);
349 if(serverLock
!= NULL
)
351 #if defined(__amigaos4__)
352 FreeSysObject(ASOT_SEMAPHORE
, serverLock
);