use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / ConClip.c
blob9d153512520d1316f12c95e585857f76f7169f84
1 /*
2 Copyright © 1995-2018, 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.2 (27.5.2018)\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 memset( &replyport, 0, sizeof( replyport ) );
219 replyport.mp_Node.ln_Type = NT_MSGPORT;
220 replyport.mp_Flags = PA_SIGNAL;
221 replyport.mp_SigBit = SIGB_SINGLE;
222 replyport.mp_SigTask = FindTask(NULL);
223 NewList(&replyport.mp_MsgList);
225 msg.msg.mn_Node.ln_Type = NT_MESSAGE;
226 msg.msg.mn_ReplyPort = &replyport;
227 msg.msg.mn_Length = sizeof(msg);
229 msg.code = ToUpper(sgw->Code);
230 msg.sgw = sgw;
232 if ((msg.code == CODE_COPY) || (sgw->NumChars < sgw->StringInfo->MaxChars - 1))
234 SetSignal(0, SIGF_SINGLE);
235 PutMsg(port, &msg.msg);
236 WaitPort(&replyport);
239 if (msg.code == CODE_PASTE)
241 WORD len = strlen(sgw->WorkBuffer);
243 if (len != sgw->NumChars)
245 sgw->NumChars = len;
246 sgw->EditOp = EO_BIGCHANGE;
247 sgw->Actions = SGA_USE | SGA_REDISPLAY;
249 retcode = 1;
252 } /* if (msg.code == CODE_COPY) */
254 } /* if ((port = FindPort(CONCLIP_PORTNAME))) */
256 break;
258 } /* switch(ToUpper(sgw->Code)) */
260 } /* if (sgw->IEvent->ie_Qualifier & IEQUALIFIER_RCOMMAND) */
261 break;
263 } /* switch (*command) */
265 if (calloldhook) retcode = CallHookPkt(oldedithook, sgw, command);
267 return retcode;
269 AROS_USERFUNC_EXIT
272 /*****************************************************************************************/
274 static void installedithook(void)
276 edithook.h_Entry = (HOOKFUNC)AROS_ASMSYMNAME(conclipeditfunc);
277 edithook.h_SubEntry = NULL;
278 edithook.h_Data = NULL;
280 oldedithook = SetEditHook(&edithook);
283 /*****************************************************************************************/
284 /*****************************************************************************************/
285 /*****************************************************************************************/
287 static void savetoclipboard(struct SGWork *sgw)
289 struct IFFHandle *iff;
291 if((iff = AllocIFF()))
293 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
295 InitIFFasClip(iff);
296 if(!OpenIFF(iff,IFFF_WRITE))
298 if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN))
300 if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN))
302 WriteChunkBytes(iff, sgw->WorkBuffer, sgw->NumChars);
304 PopChunk(iff);
306 } /* if(!PushChunk(iff, ID_FTXT, ID_CHRS, IFFSIZE_UNKNOWN)) */
307 PopChunk(iff);
309 } /* if(!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) */
310 CloseIFF(iff);
312 } /* if(!OpenIFF(iff,IFFF_WRITE)) */
313 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
315 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
316 FreeIFF(iff);
318 } /* if((iff = AllocIFF()))) */
321 /*****************************************************************************************/
323 static void readfromclipboard(struct SGWork *sgw)
325 struct IFFHandle *iff;
326 struct ContextNode *cn;
328 if((iff = AllocIFF()))
330 D(bug("ConClip/conclipeditfunc: AllocIFF okay\n"));
332 if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit)))
334 D(bug("ConClip/conclipeditfunc: OpenClipboard okay\n"));
336 InitIFFasClip(iff);
337 if(!OpenIFF(iff, IFFF_READ))
339 D(bug("ConClip/conclipeditfunc: OpenIff okay\n"));
341 if (!(StopChunk(iff, ID_FTXT, ID_CHRS)))
343 D(bug("ConClip/conclipeditfunc: StopChunk okay\n"));
345 if (!ParseIFF(iff, IFFPARSE_SCAN))
347 D(bug("ConClip/conclipeditfunc: ParseIFF okay\n"));
349 cn = CurrentChunk(iff);
350 if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0))
352 WORD readsize;
354 D(bug("ConClip: readfromclipboard: Found FTXT CHRS Chunk\n"));
355 D(bug("ConClip: readfromclipboard: Old text = \"%s\"\n", sgw->WorkBuffer));
357 readsize = sgw->StringInfo->MaxChars - 1 - sgw->BufferPos;
358 if (cn->cn_Size < readsize) readsize = cn->cn_Size;
359 if (readsize > 0)
361 memmove(sgw->WorkBuffer + sgw->BufferPos + readsize,
362 sgw->WorkBuffer + sgw->BufferPos,
363 sgw->StringInfo->MaxChars - sgw->BufferPos - readsize);
364 ReadChunkBytes(iff, sgw->WorkBuffer + sgw->BufferPos, readsize);
366 D(bug("ConClip: readfromclipboard: New text = \"%s\"\n", sgw->WorkBuffer));
368 sgw->BufferPos += readsize;
371 } /* if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS) && (cn->cn_Size > 0)) */
373 } /* if (!ParseIFF(iff, IFFPARSE_SCAN)) */
375 } /* if (!(StopChunk(iff, ID_FTXT, ID_CHRS))) */
377 CloseIFF(iff);
379 } /* if(!OpenIFF(iff, IFFF_READ)) */
380 CloseClipboard((struct ClipboardHandle*)iff->iff_Stream);
382 } /* if((iff->iff_Stream = (IPTR)OpenClipboard(clipunit))) */
383 FreeIFF(iff);
385 } /* if((iff = AllocIFF()))) */
388 /*****************************************************************************************/
390 static void handleall(void)
392 BOOL quitme = FALSE;
393 ULONG sigs;
395 while(!quitme)
397 sigs = Wait(SIGBREAKF_CTRL_C | portmask);
399 if (sigs & portmask)
401 struct MyEditHookMsg *msg;
403 while((msg = (struct MyEditHookMsg *)GetMsg(progport)))
405 switch(msg->code)
407 case CODE_COPY:
408 D(bug("ConClip: Received CODE_COPY message\n"));
409 savetoclipboard(msg->sgw);
410 break;
412 case CODE_PASTE:
413 D(bug("ConClip: Received CODE_PASTE message\n"));
414 readfromclipboard(msg->sgw);
415 break;
417 } /* switch(msg->code) */
419 ReplyMsg(&msg->msg);
421 } /* while((msg = (struct MyEditHookMsg *)GetMsg(progport))) */
423 } /* if (sigs & portmask) */
425 if (sigs & SIGBREAKF_CTRL_C) quitme = TRUE;
427 } /* while(!quitme) */
430 /*****************************************************************************************/
432 int main(void)
434 init();
436 if (!getarguments())
437 return 0;
438 if (!checkport())
439 return 0;
441 installedithook();
442 handleall();
444 cleanup(NULL);
445 return 0;
448 /*****************************************************************************************/