2 Copyright © 2011, The AROS Development Team. All rights reserved.
9 /******************************************************************************
17 U=UNIT/N/K,W=WAIT/S,G=GET/S,P=PUT=S=SET/S,C=COUNT/S,TEXT
25 Handle the clipboard's units (read or write text) from the Shell.
29 CLIP [COUNT] [UNIT <unit>] [ GET [WAIT] ] [ SET [TEXT] ]
33 Standard DOS return codes.
36 ******************************************************************************/
38 #include <datatypes/textclass.h>
40 #include <proto/exec.h>
41 #include <proto/dos.h>
42 #include <proto/iffparse.h>
43 #include <proto/alib.h> // __sprintf()
46 #include <aros/debug.h>
48 #define SH_GLOBAL_SYSBASE 1
49 #include <aros/shcommands.h>
52 * otigreat: Without having used the original Clip, it's not clear if
54 * has to set an empty clip unit, or to delete the said clip unit. Though the
55 * latter seems more elegant. Without CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT you
56 * get the other behaviour. The current one, however, also allows to obtain an
57 * empty clip unit by doing:
60 #define CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT 1
62 BOOL
toClip(STRPTR text
, UBYTE clipUnit
, struct Library
*IFFParseBase
);
63 STRPTR
fromClip(UBYTE clipUnit
, struct Library
*IFFParseBase
);
65 AROS_SH6H(Clip
,50.1, "read from or write to clipboard\n",
66 AROS_SHAH(LONG
*,U
= ,UNIT
,/N
/K
,NULL
, "Clipboard unit to be used by GET or SET (default = 0)\n"
67 "\t\tUNIT must be between 0 and 255"),
68 AROS_SHAH(BOOL
,W
= ,WAIT
,/S
,FALSE
, "Make GET wait for the UNIT to be filled with text data"),
69 AROS_SHAH(BOOL
,G
= ,GET
,/S
,FALSE
,"\tRetrieve text data from the UNIT"),
70 AROS_SHAH(BOOL
,P
=PUT
=S
=,SET
,/S
,FALSE
, "Store supplied TEXT data in the UNIT"),
71 AROS_SHAH(BOOL
,C
= ,COUNT
,/S
,FALSE
, "Output the number of filled units"),
72 AROS_SHAH(STRPTR
, ,TEXT
, ,NULL
,"\tText data to be SET in the UNIT, requires to be quoted\n"
73 "\t\tif there is more than a single word\n") )
78 BOOL get
= ((SHArg(GET
)) || (!SHArg(SET
) && !SHArg(COUNT
)));
80 UBYTE unit
, clipUnitPath
[10]; /* "CLIPS:255\0" */
83 struct Library
*IFFParseBase
;
84 struct NotifyRequest
*clipUnitNR
;
88 else if ((*SHArg(UNIT
) < 0L) || (*SHArg(UNIT
) > 255L))
90 PrintFault(ERROR_BAD_NUMBER
, (CONST_STRPTR
)"Clip");
91 return (RETURN_ERROR
);
96 if ((IFFParseBase
= OpenLibrary((STRPTR
)"iffparse.library", 36)))
98 __sprintf(clipUnitPath
, (const UBYTE
*)"CLIPS:%d", unit
);
99 D(bug("[Clip] clipUnitPath == '%s'\n", clipUnitPath
));
101 if(get
&& SHArg(WAIT
))
103 if((waitSig
= AllocSignal(-1L)) != -1)
105 if ((clipUnitNR
= AllocMem(sizeof(struct NotifyRequest
), MEMF_CLEAR
)))
107 waitMask
= 1L << waitSig
;
109 clipUnitNR
->nr_Name
= clipUnitPath
;
110 clipUnitNR
->nr_Flags
= NRF_SEND_SIGNAL
;
111 clipUnitNR
->nr_stuff
.nr_Signal
.nr_Task
= FindTask(NULL
);
112 clipUnitNR
->nr_stuff
.nr_Signal
.nr_SignalNum
= waitSig
;
114 StartNotify(clipUnitNR
);
115 sigs
= Wait(waitMask
| SIGBREAKF_CTRL_C
);
116 EndNotify(clipUnitNR
);
117 FreeMem(clipUnitNR
, sizeof(struct NotifyRequest
));
119 if (sigs
& SIGBREAKF_CTRL_C
)
121 SetIoErr(ERROR_BREAK
);
126 } /* if ((clipUnitNR = AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR))) */
128 } /* if((waitSig = AllocSignal(-1L)) != -1) */
131 /* :-/ AllocSignal() doesn't SetIoErr() on error... but what is the right error to set? */
132 SetIoErr(ERROR_NO_FREE_STORE
);
134 } /* if(SHArg(GET) && SHArg(WAIT)) */
136 /* We don't want to proceed if we had to WAIT and it failed... */
137 if (!(SHArg(WAIT
) && (rc
!= RETURN_OK
)))
141 if ((outstr
= fromClip(unit
, IFFParseBase
)))
145 FPutC(Output(), '\n');
154 #if CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT
157 if (DeleteFile(clipUnitPath
) || (IoErr() == ERROR_OBJECT_NOT_FOUND
))
163 if (toClip(SHArg(TEXT
), unit
, IFFParseBase
))
170 /* There must be a better way??? */
178 __sprintf(clipUnitPath
, (const UBYTE
*)"CLIPS:%d", unit
);
179 if ((handle
= Open(clipUnitPath
, MODE_OLDFILE
)) || (IoErr() != ERROR_OBJECT_NOT_FOUND
))
185 } while (unit
++ < 255);
186 Printf((STRPTR
)"%d\n", count
);
189 } /* if (!(SHArg(WAIT) && (rc != RETURN_OK))) */
190 CloseLibrary(IFFParseBase
);
191 } /* if ((IFFParseBase = OpenLibrary((STRPTR)"iffparse.library", 36))) */
194 PrintFault(IoErr(), (CONST_STRPTR
)"Clip");
202 BOOL
toClip(STRPTR text
, UBYTE clipUnit
, struct Library
*IFFParseBase
)
204 struct IFFHandle
*iff
;
208 if ((iff
= AllocIFF()))
210 if ((iff
->iff_Stream
= (IPTR
)OpenClipboard(clipUnit
)))
214 if (!OpenIFF(iff
, IFFF_WRITE
))
216 if (!PushChunk(iff
, ID_FTXT
, ID_FORM
, IFFSIZE_UNKNOWN
))
218 if (!PushChunk(iff
, 0, ID_CHRS
, IFFSIZE_UNKNOWN
))
220 len
= text
? strlen((char *)text
) : 0; /* strlen() crashes if text == NULL */
222 if (WriteChunkBytes(iff
, text
, len
) == len
)
227 } /* if (!PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)) */
229 } /* if (!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) */
231 } /* if (!OpenIFF(iff, IFFF_WRITE)) */
232 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
233 } /* if ((iff->iff_Stream = (IPTR)OpenClipboard(clipUnit))) */
241 STRPTR
fromClip(UBYTE clipUnit
, struct Library
*IFFParseBase
)
243 struct IFFHandle
*iff
;
244 struct ContextNode
*cn
;
245 STRPTR filebuffer
= NULL
,
246 new_filebuffer
= NULL
;
247 ULONG filebuffer_size
= 0;
254 if ((iff
->iff_Stream
= (IPTR
)OpenClipboard(clipUnit
)))
258 if (!OpenIFF(iff
, IFFF_READ
))
260 if (!StopChunk(iff
, ID_FTXT
, ID_CHRS
))
264 error
= ParseIFF(iff
, IFFPARSE_SCAN
);
266 if ((error
!= 0) && (error
!= IFFERR_EOC
))
269 if (NULL
== (cn
= CurrentChunk(iff
)))
271 kprintf("[Clip] ZERO CONTEXTNODE!!!\n\n");
275 if ((cn
->cn_Type
== ID_FTXT
) && (cn
->cn_ID
== ID_CHRS
))
279 if (NULL
== (filebuffer
= AllocVec(cn
->cn_Size
+ 1, MEMF_ANY
)))
286 if (NULL
== (new_filebuffer
= AllocVec(filebuffer_size
+ cn
->cn_Size
+ 1, MEMF_ANY
)))
292 CopyMem(filebuffer
, new_filebuffer
, filebuffer_size
);
294 filebuffer
= new_filebuffer
;
297 if (ReadChunkBytes(iff
, filebuffer
+ filebuffer_size
, cn
->cn_Size
) != cn
->cn_Size
)
303 filebuffer_size
+= cn
->cn_Size
;
304 filebuffer
[filebuffer_size
] = '\0';
305 } /* if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS)) */
308 if (filebuffer
&& !ok
) {
312 } /* if (!StopChunk(iff, ID_FTXT, ID_CHRS)) */
314 } /* if (!OpenIFF(iff, IFFF_READ)) */
315 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
316 } /* if ((iff->iff_Stream = (IPTR)OpenClipboard(clipUnit))) */