Hint added.
[AROS.git] / workbench / c / ConClip.c
blobe68cfc5bc58ecfe2f662db40f96c29177f05ad88
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Conclip CLI command
6 Lang: English
7 */
8 /******************************************************************************
10 NAME
12 Conclip
14 FORMAT
16 CONCLIP [ [UNIT | CLIPUNIT] <unitnumber>] [OFF]
18 SYNOPSIS
20 CLIPUNIT=UNIT/N, ON/S, OFF/S
22 LOCATION
26 FUNCTION
28 Enable clipboard cut/copy/paste functionality in console windows
29 and string gadgets. This enables the use of a system global clipboard.
31 INPUTS
33 CLIPUNIT=UNIT -- the number associated to the clipboard exchange unit
34 ON/S -- Activates conclip (default unit will be set to 1)
35 OFF/S -- Deactivates Conclip
37 RESULT
39 NOTES
41 EXAMPLE
43 Conclip CLIPUNIT=1
45 This will set the global clipboard unit to 1. The available clipboards
46 can be checked in clips: dirDir Clips:
48 BUGS
50 SEE ALSO
52 INTERNALS
54 HISTORY
56 ******************************************************************************//*****************************************************************************************/
58 #include <aros/asmcall.h>
59 #include <dos/dos.h>
60 #include <intuition/intuition.h>
61 #include <intuition/sghooks.h>
62 #include <intuition/classusr.h>
63 #include <libraries/iffparse.h>
64 #include <devices/inputevent.h>
65 #include <datatypes/textclass.h>
66 #include <utility/hooks.h>
67 #include <proto/exec.h>
68 #include <proto/dos.h>
69 #include <proto/intuition.h>
70 #include <proto/iffparse.h>
71 #include <proto/alib.h>
72 #include <proto/utility.h>
74 #include <string.h>
76 #undef DEBUG
77 #define DEBUG 0
78 #include <aros/debug.h>
80 /*****************************************************************************************/
82 #define ARG_TEMPLATE "CLIPUNIT=UNIT/N,OFF/S"
83 #define ARG_CLIPUNIT 0
84 #define ARG_OFF 1
85 #define NUM_ARGS 2
87 /*****************************************************************************************/
89 #define CODE_COPY 'C'
90 #define CODE_PASTE 'V'
92 const TEXT version[] = "$VER: Conclip 42.1 (19.2.2015)\n";
94 struct MyEditHookMsg
96 struct Message msg;
97 struct SGWork *sgw;
98 WORD code;
101 /*****************************************************************************************/
103 const STRPTR CONCLIP_TASKNAME = "ConClip >>";
104 const STRPTR CONCLIP_PORTNAME = "ConClip.rendezvous";
106 /*****************************************************************************************/
108 static struct MsgPort *progport;
109 static struct Hook edithook, *oldedithook;
110 static struct Task *progtask;
111 static ULONG clipunit, portmask;
112 static BOOL off;
113 static UBYTE s[256];
115 /*****************************************************************************************/
117 static void cleanup(STRPTR msg)
119 if (msg) Printf("ConClip: %s\n", msg);
121 if (oldedithook) SetEditHook(oldedithook);
122 if (progport) DeletePort(progport);
125 /*****************************************************************************************/
127 static void init(void)
129 progtask = FindTask(NULL);
130 ((struct Process *)progtask)->pr_WindowPtr = (APTR)-1;
133 /*****************************************************************************************/
135 static BOOL getarguments(void)
137 struct RDArgs *myargs;
138 IPTR args[NUM_ARGS] = {0, 0};
140 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
142 Fault(IoErr(), 0, s, 255);
143 cleanup(s);
144 return FALSE;
147 if (args[ARG_CLIPUNIT]) clipunit = (ULONG)(*(IPTR *)args[ARG_CLIPUNIT]);
148 if (args[ARG_OFF]) off = args[ARG_OFF] ? TRUE : FALSE;
150 FreeArgs(myargs);
151 return TRUE;
154 /*****************************************************************************************/
156 static BOOL checkport(void)
158 Forbid();
159 progport = FindPort(CONCLIP_PORTNAME);
160 if (progport)
162 if (off) Signal(progport->mp_SigTask, SIGBREAKF_CTRL_C);
163 Permit();
164 progport = NULL;
165 cleanup(NULL);
166 return FALSE;
168 progport = CreatePort(CONCLIP_PORTNAME, 1);
169 Permit();
171 if (!progport)
173 cleanup("Could not create MsgPort!");
174 return FALSE;
177 portmask = 1L << progport->mp_SigBit;
178 return TRUE;
181 /*****************************************************************************************/
183 AROS_UFH3(ULONG, conclipeditfunc,
184 AROS_UFHA(struct Hook *, hook, A0),
185 AROS_UFHA(struct SGWork *, sgw, A2),
186 AROS_UFHA(ULONG *, command, A1)
189 AROS_USERFUNC_INIT
191 struct MsgPort *port, replyport;
192 struct MyEditHookMsg msg;
193 BOOL calloldhook = TRUE;
194 ULONG retcode = 0;
196 switch (*command)
198 case SGH_KEY:
199 D(bug("ConClip/conclipeditfunc: is SGH_KEY\n"));
201 if (sgw->IEvent->ie_Qualifier & IEQUALIFIER_RCOMMAND)
203 D(bug("ConClip/conclipeditfunc: qualifier RCOMMAND okay\n"));
205 switch(ToUpper(sgw->Code))
207 case 'C':
208 if (!sgw->NumChars) break;
209 /* fall through */
211 case 'V':
212 D(bug("ConClip/conclipeditfunc: key = %c\n", toupper(sgw->Code)));
214 if ((port = FindPort(CONCLIP_PORTNAME)))
216 calloldhook = FALSE;
218 replyport.mp_Node.ln_Type = NT_MSGPORT;
219 replyport.mp_Node.ln_Name = NULL;
220 replyport.mp_Node.ln_Pri = 0;
221 replyport.mp_Flags = PA_SIGNAL;
222 replyport.mp_SigBit = SIGB_SINGLE;
223 replyport.mp_SigTask = FindTask(NULL);
224 NewList(&replyport.mp_MsgList);
226 msg.msg.mn_Node.ln_Type = NT_MESSAGE;
227 msg.msg.mn_ReplyPort = &replyport;
228 msg.msg.mn_Length = sizeof(msg);
230 msg.code = ToUpper(sgw->Code);
231 msg.sgw = sgw;
233 if ((msg.code == CODE_COPY) || (sgw->NumChars < sgw->StringInfo->MaxChars - 1))
235 SetSignal(0, SIGF_SINGLE);
236 PutMsg(port, &msg.msg);
237 WaitPort(&replyport);
240 if (msg.code == CODE_PASTE)
242 WORD len = strlen(sgw->WorkBuffer);
244 if (len != sgw->NumChars)
246 sgw->NumChars = len;
247 sgw->EditOp = EO_BIGCHANGE;
248 sgw->Actions = SGA_USE | SGA_REDISPLAY;
250 retcode = 1;
253 } /* if (msg.code == CODE_COPY) */
255 } /* if ((port = FindPort(CONCLIP_PORTNAME))) */
257 break;
259 } /* switch(ToUpper(sgw->Code)) */
261 } /* if (sgw->IEvent->ie_Qualifier & IEQUALIFIER_RCOMMAND) */
262 break;
264 } /* switch (*command) */
266 if (calloldhook) retcode = CallHookPkt(oldedithook, sgw, command);
268 return retcode;
270 AROS_USERFUNC_EXIT
273 /*****************************************************************************************/
275 static void installedithook(void)
277 edithook.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(conclipeditfunc);
278 edithook.h_SubEntry = NULL;
279 edithook.h_Data = NULL;
281 oldedithook = SetEditHook(&edithook);
284 /*****************************************************************************************/
285 /*****************************************************************************************/
286 /*****************************************************************************************/
288 static void savetoclipboard(struct SGWork *sgw)
290 struct IFFHandle *iff;
292 if((iff = AllocIFF()))
294 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
296 InitIFFasClip(iff);
297 if(!OpenIFF(iff,IFFF_WRITE))
299 if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN))
301 if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN))
303 WriteChunkBytes(iff, sgw->WorkBuffer, sgw->NumChars);
305 PopChunk(iff);
307 } /* if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN)) */
308 PopChunk(iff);
310 } /* if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) */
311 CloseIFF(iff);
313 } /* if(!OpenIFF(iff,IFFF_WRITE)) */
314 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
316 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
317 FreeIFF(iff);
319 } /* if((iff = AllocIFF()))) */
322 /*****************************************************************************************/
324 static void readfromclipboard(struct SGWork *sgw)
326 struct IFFHandle *iff;
327 struct ContextNode *cn;
329 if((iff = AllocIFF()))
331 D(bug("ConClip/conclipeditfunc: AllocIFF okay\n"));
333 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
335 D(bug("ConClip/conclipeditfunc: OpenClipboard okay\n"));
337 InitIFFasClip(iff);
338 if(!OpenIFF(iff, IFFF_READ))
340 D(bug("ConClip/conclipeditfunc: OpenIff okay\n"));
342 if (!(StopChunk(iff, ID_FTXT, ID_CHRS)))
344 D(bug("ConClip/conclipeditfunc: StopChunk okay\n"));
346 if (!ParseIFF(iff, IFFPARSE_SCAN))
348 D(bug("ConClip/conclipeditfunc: ParseIFF okay\n"));
350 cn = CurrentChunk(iff);
351 if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0))
353 WORD readsize;
355 D(bug("ConClip: readfromclipboard: Found FTXT CHRS Chunk\n"));
356 D(bug("ConClip: readfromclipboard: Old text = \"%s\"\n", sgw->WorkBuffer));
358 readsize = sgw->StringInfo->MaxChars - 1 - sgw->BufferPos;
359 if (cn->cn_Size < readsize) readsize = cn->cn_Size;
360 if (readsize > 0)
362 memmove(sgw->WorkBuffer + sgw->BufferPos + readsize,
363 sgw->WorkBuffer + sgw->BufferPos,
364 sgw->StringInfo->MaxChars - sgw->BufferPos - readsize);
365 ReadChunkBytes(iff, sgw->WorkBuffer + sgw->BufferPos, readsize);
367 D(bug("ConClip: readfromclipboard: New text = \"%s\"\n", sgw->WorkBuffer));
369 sgw->BufferPos += readsize;
372 } /* if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0)) */
374 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
376 } /* if (!(StopChunk(iff, ID_FTXT, ID_CHRS))) */
378 CloseIFF(iff);
380 } /* if(!OpenIFF(iff, IFFF_READ)) */
381 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
383 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
384 FreeIFF(iff);
386 } /* if((iff = AllocIFF()))) */
389 /*****************************************************************************************/
391 static void handleall(void)
393 BOOL quitme = FALSE;
394 ULONG sigs;
396 while(!quitme)
398 sigs = Wait(SIGBREAKF_CTRL_C | portmask);
400 if (sigs & portmask)
402 struct MyEditHookMsg *msg;
404 while((msg = (struct MyEditHookMsg *)GetMsg(progport)))
406 switch(msg->code)
408 case CODE_COPY:
409 D(bug("ConClip: Received CODE_COPY message\n"));
410 savetoclipboard(msg->sgw);
411 break;
413 case CODE_PASTE:
414 D(bug("ConClip: Received CODE_PASTE message\n"));
415 readfromclipboard(msg->sgw);
416 break;
418 } /* switch(msg->code) */
420 ReplyMsg(&msg->msg);
422 } /* while((msg = (struct MyEditHookMsg *)GetMsg(progport))) */
424 } /* if (sigs & portmask) */
426 if (sigs & SIGBREAKF_CTRL_C) quitme = TRUE;
428 } /* while(!quitme) */
431 /*****************************************************************************************/
433 int main(void)
435 init();
437 if (!getarguments())
438 return 0;
439 if (!checkport())
440 return 0;
442 installedithook();
443 handleall();
445 cleanup(NULL);
446 return 0;
449 /*****************************************************************************************/