Fixed out-by-one error in previous commit.
[AROS.git] / workbench / c / ConClip.c
blobd375fdae7aceae1509a8a584d95e703c300ed162
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 struct MyEditHookMsg
94 struct Message msg;
95 struct SGWork *sgw;
96 WORD code;
99 /*****************************************************************************************/
101 const STRPTR CONCLIP_TASKNAME = "ConClip >>";
102 const STRPTR CONCLIP_PORTNAME = "ConClip.rendezvous";
104 /*****************************************************************************************/
106 static struct MsgPort *progport;
107 static struct Hook edithook, *oldedithook;
108 static struct Task *progtask;
109 static ULONG clipunit, portmask;
110 static BOOL off;
111 static UBYTE s[256];
113 /*****************************************************************************************/
115 static void cleanup(STRPTR msg)
117 if (msg) Printf("ConClip: %s\n", msg);
119 if (oldedithook) SetEditHook(oldedithook);
120 if (progport) DeletePort(progport);
123 /*****************************************************************************************/
125 static void init(void)
127 progtask = FindTask(NULL);
128 ((struct Process *)progtask)->pr_WindowPtr = (APTR)-1;
131 /*****************************************************************************************/
133 static BOOL getarguments(void)
135 struct RDArgs *myargs;
136 IPTR args[NUM_ARGS] = {0, 0};
138 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
140 Fault(IoErr(), 0, s, 255);
141 cleanup(s);
142 return FALSE;
145 if (args[ARG_CLIPUNIT]) clipunit = (ULONG)(*(IPTR *)args[ARG_CLIPUNIT]);
146 if (args[ARG_OFF]) off = args[ARG_OFF] ? TRUE : FALSE;
148 FreeArgs(myargs);
149 return TRUE;
152 /*****************************************************************************************/
154 static BOOL checkport(void)
156 Forbid();
157 progport = FindPort(CONCLIP_PORTNAME);
158 if (progport)
160 if (off) Signal(progport->mp_SigTask, SIGBREAKF_CTRL_C);
161 Permit();
162 progport = NULL;
163 cleanup(NULL);
164 return FALSE;
166 progport = CreatePort(CONCLIP_PORTNAME, 1);
167 Permit();
169 if (!progport)
171 cleanup("Could not create MsgPort!");
172 return FALSE;
175 portmask = 1L << progport->mp_SigBit;
176 return TRUE;
179 /*****************************************************************************************/
181 AROS_UFH3(ULONG, conclipeditfunc,
182 AROS_UFHA(struct Hook *, hook, A0),
183 AROS_UFHA(struct SGWork *, sgw, A2),
184 AROS_UFHA(ULONG *, command, A1)
187 AROS_USERFUNC_INIT
189 struct MsgPort *port, replyport;
190 struct MyEditHookMsg msg;
191 BOOL calloldhook = TRUE;
192 ULONG retcode = 0;
194 switch (*command)
196 case SGH_KEY:
197 D(bug("ConClip/conclipeditfunc: is SGH_KEY\n"));
199 if (sgw->IEvent->ie_Qualifier & IEQUALIFIER_RCOMMAND)
201 D(bug("ConClip/conclipeditfunc: qualifier RCOMMAND okay\n"));
203 switch(ToUpper(sgw->Code))
205 case 'C':
206 if (!sgw->NumChars) break;
207 /* fall through */
209 case 'V':
210 D(bug("ConClip/conclipeditfunc: key = %c\n", toupper(sgw->Code)));
212 if ((port = FindPort(CONCLIP_PORTNAME)))
214 calloldhook = FALSE;
216 replyport.mp_Node.ln_Type = NT_MSGPORT;
217 replyport.mp_Node.ln_Name = NULL;
218 replyport.mp_Node.ln_Pri = 0;
219 replyport.mp_Flags = PA_SIGNAL;
220 replyport.mp_SigBit = SIGB_SINGLE;
221 replyport.mp_SigTask = FindTask(NULL);
222 NewList(&replyport.mp_MsgList);
224 msg.msg.mn_Node.ln_Type = NT_MESSAGE;
225 msg.msg.mn_ReplyPort = &replyport;
226 msg.msg.mn_Length = sizeof(msg);
228 msg.code = ToUpper(sgw->Code);
229 msg.sgw = sgw;
231 if ((msg.code == CODE_COPY) || (sgw->NumChars < sgw->StringInfo->MaxChars - 1))
233 SetSignal(0, SIGF_SINGLE);
234 PutMsg(port, &msg.msg);
235 WaitPort(&replyport);
238 if (msg.code == CODE_PASTE)
240 WORD len = strlen(sgw->WorkBuffer);
242 if (len != sgw->NumChars)
244 sgw->NumChars = len;
245 sgw->EditOp = EO_BIGCHANGE;
246 sgw->Actions = SGA_USE | SGA_REDISPLAY;
248 retcode = 1;
251 } /* if (msg.code == CODE_COPY) */
253 } /* if ((port = FindPort(CONCLIP_PORTNAME))) */
255 break;
257 } /* switch(ToUpper(sgw->Code)) */
259 } /* if (sgw->IEvent->ie_Qualifier & IEQUALIFIER_RCOMMAND) */
260 break;
262 } /* switch (*command) */
264 if (calloldhook) retcode = CallHookPkt(oldedithook, sgw, command);
266 return retcode;
268 AROS_USERFUNC_EXIT
271 /*****************************************************************************************/
273 static void installedithook(void)
275 edithook.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(conclipeditfunc);
276 edithook.h_SubEntry = NULL;
277 edithook.h_Data = NULL;
279 oldedithook = SetEditHook(&edithook);
282 /*****************************************************************************************/
283 /*****************************************************************************************/
284 /*****************************************************************************************/
286 static void savetoclipboard(struct SGWork *sgw)
288 struct IFFHandle *iff;
290 if((iff = AllocIFF()))
292 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
294 InitIFFasClip(iff);
295 if(!OpenIFF(iff,IFFF_WRITE))
297 if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN))
299 if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN))
301 WriteChunkBytes(iff, sgw->WorkBuffer, sgw->NumChars);
303 PopChunk(iff);
305 } /* if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN)) */
306 PopChunk(iff);
308 } /* if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) */
309 CloseIFF(iff);
311 } /* if(!OpenIFF(iff,IFFF_WRITE)) */
312 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
314 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
315 FreeIFF(iff);
317 } /* if((iff = AllocIFF()))) */
320 /*****************************************************************************************/
322 static void readfromclipboard(struct SGWork *sgw)
324 struct IFFHandle *iff;
325 struct ContextNode *cn;
327 if((iff = AllocIFF()))
329 D(bug("ConClip/conclipeditfunc: AllocIFF okay\n"));
331 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
333 D(bug("ConClip/conclipeditfunc: OpenClipboard okay\n"));
335 InitIFFasClip(iff);
336 if(!OpenIFF(iff, IFFF_READ))
338 D(bug("ConClip/conclipeditfunc: OpenIff okay\n"));
340 if (!(StopChunk(iff, ID_FTXT, ID_CHRS)))
342 D(bug("ConClip/conclipeditfunc: StopChunk okay\n"));
344 if (!ParseIFF(iff, IFFPARSE_SCAN))
346 D(bug("ConClip/conclipeditfunc: ParseIFF okay\n"));
348 cn = CurrentChunk(iff);
349 if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0))
351 WORD readsize;
353 D(bug("ConClip: readfromclipboard: Found FTXT CHRS Chunk\n"));
354 D(bug("ConClip: readfromclipboard: Old text = \"%s\"\n", sgw->WorkBuffer));
356 readsize = sgw->StringInfo->MaxChars - 1 - sgw->BufferPos;
357 if (cn->cn_Size < readsize) readsize = cn->cn_Size;
358 if (readsize > 0)
360 memmove(sgw->WorkBuffer + sgw->BufferPos + readsize,
361 sgw->WorkBuffer + sgw->BufferPos,
362 sgw->StringInfo->MaxChars - sgw->BufferPos - readsize);
363 ReadChunkBytes(iff, sgw->WorkBuffer + sgw->BufferPos, readsize);
365 D(bug("ConClip: readfromclipboard: New text = \"%s\"\n", sgw->WorkBuffer));
367 sgw->BufferPos += readsize;
370 } /* if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0)) */
372 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
374 } /* if (!(StopChunk(iff, ID_FTXT, ID_CHRS))) */
376 CloseIFF(iff);
378 } /* if(!OpenIFF(iff, IFFF_READ)) */
379 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
381 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
382 FreeIFF(iff);
384 } /* if((iff = AllocIFF()))) */
387 /*****************************************************************************************/
389 static void handleall(void)
391 BOOL quitme = FALSE;
392 ULONG sigs;
394 while(!quitme)
396 sigs = Wait(SIGBREAKF_CTRL_C | portmask);
398 if (sigs & portmask)
400 struct MyEditHookMsg *msg;
402 while((msg = (struct MyEditHookMsg *)GetMsg(progport)))
404 switch(msg->code)
406 case CODE_COPY:
407 D(bug("ConClip: Received CODE_COPY message\n"));
408 savetoclipboard(msg->sgw);
409 break;
411 case CODE_PASTE:
412 D(bug("ConClip: Received CODE_PASTE message\n"));
413 readfromclipboard(msg->sgw);
414 break;
416 } /* switch(msg->code) */
418 ReplyMsg(&msg->msg);
420 } /* while((msg = (struct MyEditHookMsg *)GetMsg(progport))) */
422 } /* if (sigs & portmask) */
424 if (sigs & SIGBREAKF_CTRL_C) quitme = TRUE;
426 } /* while(!quitme) */
429 /*****************************************************************************************/
431 int main(void)
433 init();
435 if (!getarguments())
436 return 0;
437 if (!checkport())
438 return 0;
440 installedithook();
441 handleall();
443 cleanup(NULL);
444 return 0;
447 /*****************************************************************************************/