[CLIP]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 1 Nov 2015 14:47:12 +0000 (14:47 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 1 Nov 2015 14:47:12 +0000 (14:47 +0000)
Adds a simple CLIP utility, as found on Windows, to ReactOS.
Like the Windows version, it can just redirect the output of another console program or a file to the clipboard.
By Ricardo Hanke, with minor corrections by me.
CORE-10411

svn path=/trunk/; revision=69775

reactos/base/applications/cmdutils/CMakeLists.txt
reactos/base/applications/cmdutils/clip/CMakeLists.txt [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/clip.c [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/clip.rc [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/lang/de-DE.rc [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/lang/en-US.rc [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/lang/fr-FR.rc [new file with mode: 0644]
reactos/base/applications/cmdutils/clip/resource.h [new file with mode: 0644]

index 782baed..473ac1f 100644 (file)
@@ -1,3 +1,4 @@
+add_subdirectory(clip)
 add_subdirectory(comp)
 add_subdirectory(cscript)
 add_subdirectory(dbgprint)
diff --git a/reactos/base/applications/cmdutils/clip/CMakeLists.txt b/reactos/base/applications/cmdutils/clip/CMakeLists.txt
new file mode 100644 (file)
index 0000000..53b3991
--- /dev/null
@@ -0,0 +1,5 @@
+
+add_executable(clip clip.c clip.rc)
+set_module_type(clip win32cui UNICODE)
+add_importlibs(clip user32 msvcrt kernel32 advapi32)
+add_cd_file(TARGET clip DESTINATION reactos/system32 FOR all)
diff --git a/reactos/base/applications/cmdutils/clip/clip.c b/reactos/base/applications/cmdutils/clip/clip.c
new file mode 100644 (file)
index 0000000..237cac3
--- /dev/null
@@ -0,0 +1,137 @@
+#include <stdio.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <winuser.h>
+
+#include "resource.h"
+
+static void PrintError(void)
+{
+    DWORD dwError;
+    LPWSTR lpMsgBuf = NULL;
+
+    dwError = GetLastError();
+    if (dwError == NO_ERROR)
+        return;
+
+    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                   NULL, dwError, 0, (LPWSTR)&lpMsgBuf, 0,  NULL);
+    wprintf(L"%s", lpMsgBuf);
+    LocalFree(lpMsgBuf);
+}
+
+static void PrintResourceString(UINT uID)
+{
+    WCHAR buff[500];
+
+    if (LoadStringW(GetModuleHandle(NULL), uID, buff, ARRAYSIZE(buff)))
+    {
+        wprintf(L"%s", buff);
+    }
+}
+
+static BOOL IsDataUnicode(HGLOBAL hGlobal)
+{
+    BOOL bReturn;
+    LPVOID lpBuffer;
+
+    lpBuffer = GlobalLock(hGlobal);
+    bReturn = IsTextUnicode(lpBuffer, GlobalSize(hGlobal), NULL);
+    GlobalUnlock(hGlobal);
+
+    return bReturn;
+}
+
+int wmain(int argc, wchar_t** argv)
+{
+    HANDLE hInput;
+    DWORD dwBytesRead;
+    BOOL bStatus;
+    HGLOBAL hBuffer;
+    HGLOBAL hTemp;
+    LPBYTE lpBuffer;
+    SIZE_T dwSize = 0;
+
+    hInput = GetStdHandle(STD_INPUT_HANDLE);
+
+    /* Check for usage */
+    if (argc > 1 && wcsncmp(argv[1], L"/?", 2) == 0)
+    {
+        PrintResourceString(IDS_HELP);
+        return 0;
+    }
+
+    if (GetFileType(hInput) == FILE_TYPE_CHAR)
+    {
+        PrintResourceString(IDS_USAGE);
+        return 0;
+    }
+
+    /* Initialize a growable buffer for holding clipboard data */
+    hBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
+    if (!hBuffer)
+    {
+        PrintError();
+        return -1;
+    }
+
+    /*
+     * Read data from the input stream by chunks of 4096 bytes
+     * and resize the buffer each time when needed.
+     */
+    do
+    {
+        lpBuffer = GlobalLock(hBuffer);
+        if (!lpBuffer)
+            goto cleanup;
+
+        bStatus = ReadFile(hInput, lpBuffer + dwSize, 4096, &dwBytesRead, NULL);
+        dwSize += dwBytesRead;
+        GlobalUnlock(hBuffer);
+
+        hTemp = GlobalReAlloc(hBuffer, GlobalSize(hBuffer) + 4096, GMEM_ZEROINIT);
+        if (!hTemp)
+            goto cleanup;
+
+        hBuffer = hTemp;
+    }
+    while (dwBytesRead > 0 && bStatus);
+
+    /*
+     * Resize the buffer to the total size of data read.
+     * Note that, if the call fails, we still have the old buffer valid.
+     * The old buffer would be larger than the actual size of data it contains,
+     * but this is not a problem for us.
+     */
+    hTemp = GlobalReAlloc(hBuffer, dwSize + sizeof(WCHAR), GMEM_ZEROINIT);
+    if (hTemp)
+        hBuffer = hTemp;
+
+    /* Attempt to open the clipboard */
+    if (!OpenClipboard(NULL))
+        goto cleanup;
+
+    /* Empty it, copy our data, then close it */
+
+    EmptyClipboard();
+
+    if (IsDataUnicode(hBuffer))
+    {
+        SetClipboardData(CF_UNICODETEXT, hBuffer);
+    }
+    else
+    {
+        // TODO: Convert text from current console page to standard ANSI.
+        // Alternatively one can use CF_OEMTEXT as done here.
+        SetClipboardData(CF_OEMTEXT, hBuffer);
+    }
+
+    CloseClipboard();
+    return 0;
+
+cleanup:
+    GlobalFree(hBuffer);
+    PrintError();
+    return -1;
+}
diff --git a/reactos/base/applications/cmdutils/clip/clip.rc b/reactos/base/applications/cmdutils/clip/clip.rc
new file mode 100644 (file)
index 0000000..88cfa98
--- /dev/null
@@ -0,0 +1,21 @@
+#include <windef.h>
+
+#include "resource.h"
+
+#define REACTOS_STR_FILE_DESCRIPTION  "ReactOS Clip Command"
+#define REACTOS_STR_INTERNAL_NAME     "clip"
+#define REACTOS_STR_ORIGINAL_FILENAME "clip.exe"
+#include <reactos/version.rc>
+
+/* UTF-8 */
+#pragma code_page(65001)
+
+#ifdef LANGUAGE_DE_DE
+    #include "lang/de-DE.rc"
+#endif
+#ifdef LANGUAGE_EN_US
+    #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+    #include "lang/fr-FR.rc"
+#endif
diff --git a/reactos/base/applications/cmdutils/clip/lang/de-DE.rc b/reactos/base/applications/cmdutils/clip/lang/de-DE.rc
new file mode 100644 (file)
index 0000000..eeac136
--- /dev/null
@@ -0,0 +1,9 @@
+LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
+
+STRINGTABLE
+BEGIN
+    IDS_USAGE "\nGeben Sie ""CLIP /?"" ein, um die Syntax anzuzeigen.\n"
+    IDS_HELP "\nLeitet die Ausgabe von Befehlszeilenprogrammen in die Zwischenablage um.\n\n\
+CLIP [/?]\n\n\
+    /?  Zeigt diese Hilfe an.\n"
+END
diff --git a/reactos/base/applications/cmdutils/clip/lang/en-US.rc b/reactos/base/applications/cmdutils/clip/lang/en-US.rc
new file mode 100644 (file)
index 0000000..e51837a
--- /dev/null
@@ -0,0 +1,9 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE
+BEGIN
+    IDS_USAGE "\nType ""CLIP /?"" for usage information.\n"
+    IDS_HELP "\nRedirects the output of command line programs to the clipboard.\n\n\
+CLIP [/?]\n\n\
+    /?  Show this help message.\n"
+END
diff --git a/reactos/base/applications/cmdutils/clip/lang/fr-FR.rc b/reactos/base/applications/cmdutils/clip/lang/fr-FR.rc
new file mode 100644 (file)
index 0000000..aed4143
--- /dev/null
@@ -0,0 +1,9 @@
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
+
+STRINGTABLE
+BEGIN
+    IDS_USAGE "\nEntrez ""CLIP /?"" pour afficher la syntaxe.\n"
+    IDS_HELP "\nRedirige la sortie des programmes en ligne de commande vers le Presse-Papiers.\n\n\
+CLIP [/?]\n\n\
+    /?  Affiche ce message d'aide.\n"
+END
diff --git a/reactos/base/applications/cmdutils/clip/resource.h b/reactos/base/applications/cmdutils/clip/resource.h
new file mode 100644 (file)
index 0000000..026f35f
--- /dev/null
@@ -0,0 +1,4 @@
+#pragma once
+
+#define IDS_USAGE 100
+#define IDS_HELP  101