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 #include <aros/shcommands.h>
51 * otigreat: Without having used the original Clip, it's not clear if
53 * has to set an empty clip unit, or to delete the said clip unit. Though the
54 * latter seems more elegant. Without CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT you
55 * get the other behaviour. The current one, however, also allows to obtain an
56 * empty clip unit by doing:
59 #define CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT 1
61 BOOL
toClip(STRPTR text
, UBYTE clipUnit
, struct Library
*IFFParseBase
);
62 STRPTR
fromClip(UBYTE clipUnit
, struct Library
*IFFParseBase
);
64 AROS_SH6H(Clip
,50.1, "read from or write to clipboard\n",
65 AROS_SHAH(IPTR
*,U
= ,UNIT
,/N
/K
,NULL
, "Clipboard unit to be used by GET or SET (default = 0)\n"
66 "\t\tUNIT must be between 0 and 255"),
67 AROS_SHAH(BOOL
,W
= ,WAIT
,/S
,FALSE
, "Make GET wait for the UNIT to be filled with text data"),
68 AROS_SHAH(BOOL
,G
= ,GET
,/S
,FALSE
,"\tRetrieve text data from the UNIT"),
69 AROS_SHAH(BOOL
,P
=PUT
=S
=,SET
,/S
,FALSE
, "Store supplied TEXT data in the UNIT"),
70 AROS_SHAH(BOOL
,C
= ,COUNT
,/S
,FALSE
, "Output the number of filled units"),
71 AROS_SHAH(STRPTR
, ,TEXT
, ,NULL
,"\tText data to be SET in the UNIT, requires to be quoted\n"
72 "\t\tif there is more than a single word\n") )
77 BOOL get
= ((SHArg(GET
)) || (!SHArg(SET
) && !SHArg(COUNT
)));
79 UBYTE unit
, clipUnitPath
[10]; /* "CLIPS:255\0" */
82 struct Library
*IFFParseBase
;
83 struct NotifyRequest
*clipUnitNR
;
87 else if ((*SHArg(UNIT
) < 0L) || (*SHArg(UNIT
) > 255L))
89 PrintFault(ERROR_BAD_NUMBER
, (CONST_STRPTR
)"Clip");
90 return (RETURN_ERROR
);
95 if ((IFFParseBase
= OpenLibrary((STRPTR
)"iffparse.library", 36)))
97 __sprintf(clipUnitPath
, (const UBYTE
*)"CLIPS:%d", unit
);
98 D(bug("[Clip] clipUnitPath == '%s'\n", clipUnitPath
));
100 if(get
&& SHArg(WAIT
))
102 if((waitSig
= AllocSignal(-1L)) != -1)
104 if ((clipUnitNR
= AllocMem(sizeof(struct NotifyRequest
), MEMF_CLEAR
)))
106 waitMask
= 1L << waitSig
;
108 clipUnitNR
->nr_Name
= clipUnitPath
;
109 clipUnitNR
->nr_Flags
= NRF_SEND_SIGNAL
;
110 clipUnitNR
->nr_stuff
.nr_Signal
.nr_Task
= FindTask(NULL
);
111 clipUnitNR
->nr_stuff
.nr_Signal
.nr_SignalNum
= waitSig
;
113 StartNotify(clipUnitNR
);
114 sigs
= Wait(waitMask
| SIGBREAKF_CTRL_C
);
115 EndNotify(clipUnitNR
);
116 FreeMem(clipUnitNR
, sizeof(struct NotifyRequest
));
118 if (sigs
& SIGBREAKF_CTRL_C
)
120 SetIoErr(ERROR_BREAK
);
125 } /* if ((clipUnitNR = AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR))) */
127 } /* if((waitSig = AllocSignal(-1L)) != -1) */
130 /* :-/ AllocSignal() doesn't SetIoErr() on error... but what is the right error to set? */
131 SetIoErr(ERROR_NO_FREE_STORE
);
133 } /* if(SHArg(GET) && SHArg(WAIT)) */
135 /* We don't want to proceed if we had to WAIT and it failed... */
136 if (!(SHArg(WAIT
) && (rc
!= RETURN_OK
)))
140 if ((outstr
= fromClip(unit
, IFFParseBase
)))
144 FPutC(Output(), '\n');
153 #if CLIP_SET_NO_TEXT_MEANS_DELETE_UNIT
156 if (DeleteFile(clipUnitPath
) || (IoErr() == ERROR_OBJECT_NOT_FOUND
))
162 if (toClip(SHArg(TEXT
), unit
, IFFParseBase
))
169 /* There must be a better way??? */
177 __sprintf(clipUnitPath
, (const UBYTE
*)"CLIPS:%d", unit
);
178 if ((handle
= Open(clipUnitPath
, MODE_OLDFILE
)) || (IoErr() != ERROR_OBJECT_NOT_FOUND
))
184 } while (unit
++ < 255);
185 Printf((STRPTR
)"%d\n", count
);
188 } /* if (!(SHArg(WAIT) && (rc != RETURN_OK))) */
189 CloseLibrary(IFFParseBase
);
190 } /* if ((IFFParseBase = OpenLibrary((STRPTR)"iffparse.library", 36))) */
193 PrintFault(IoErr(), (CONST_STRPTR
)"Clip");
201 BOOL
toClip(STRPTR text
, UBYTE clipUnit
, struct Library
*IFFParseBase
)
203 struct IFFHandle
*iff
;
207 if ((iff
= AllocIFF()))
209 if ((iff
->iff_Stream
= (IPTR
)OpenClipboard(clipUnit
)))
213 if (!OpenIFF(iff
, IFFF_WRITE
))
215 if (!PushChunk(iff
, ID_FTXT
, ID_FORM
, IFFSIZE_UNKNOWN
))
217 if (!PushChunk(iff
, 0, ID_CHRS
, IFFSIZE_UNKNOWN
))
219 len
= text
? strlen((char *)text
) : 0; /* strlen() crashes if text == NULL */
221 if (WriteChunkBytes(iff
, text
, len
) == len
)
226 } /* if (!PushChunk(iff, 0, ID_CHRS, IFFSIZE_UNKNOWN)) */
228 } /* if (!PushChunk(iff, ID_FTXT, ID_FORM, IFFSIZE_UNKNOWN)) */
230 } /* if (!OpenIFF(iff, IFFF_WRITE)) */
231 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
232 } /* if ((iff->iff_Stream = (IPTR)OpenClipboard(clipUnit))) */
240 STRPTR
fromClip(UBYTE clipUnit
, struct Library
*IFFParseBase
)
242 struct IFFHandle
*iff
;
243 struct ContextNode
*cn
;
244 STRPTR filebuffer
= NULL
,
245 new_filebuffer
= NULL
;
246 ULONG filebuffer_size
= 0;
253 if ((iff
->iff_Stream
= (IPTR
)OpenClipboard(clipUnit
)))
257 if (!OpenIFF(iff
, IFFF_READ
))
259 if (!StopChunk(iff
, ID_FTXT
, ID_CHRS
))
263 error
= ParseIFF(iff
, IFFPARSE_SCAN
);
265 if ((error
!= 0) && (error
!= IFFERR_EOC
))
268 if (NULL
== (cn
= CurrentChunk(iff
)))
270 kprintf("[Clip] ZERO CONTEXTNODE!!!\n\n");
274 if ((cn
->cn_Type
== ID_FTXT
) && (cn
->cn_ID
== ID_CHRS
))
278 if (NULL
== (filebuffer
= AllocVec(cn
->cn_Size
+ 1, MEMF_ANY
)))
285 if (NULL
== (new_filebuffer
= AllocVec(filebuffer_size
+ cn
->cn_Size
+ 1, MEMF_ANY
)))
291 CopyMem(filebuffer
, new_filebuffer
, filebuffer_size
);
293 filebuffer
= new_filebuffer
;
296 if (ReadChunkBytes(iff
, filebuffer
+ filebuffer_size
, cn
->cn_Size
) != cn
->cn_Size
)
302 filebuffer_size
+= cn
->cn_Size
;
303 filebuffer
[filebuffer_size
] = '\0';
304 } /* if ((cn->cn_Type == ID_FTXT) && (cn->cn_ID == ID_CHRS)) */
307 if (filebuffer
&& !ok
) {
311 } /* if (!StopChunk(iff, ID_FTXT, ID_CHRS)) */
313 } /* if (!OpenIFF(iff, IFFF_READ)) */
314 CloseClipboard((struct ClipboardHandle
*)iff
->iff_Stream
);
315 } /* if ((iff->iff_Stream = (IPTR)OpenClipboard(clipUnit))) */