From db5455164865b4ad34868567e210523535a0f402 Mon Sep 17 00:00:00 2001 From: Reuben Thomas Date: Tue, 20 Nov 2007 21:07:16 +0000 Subject: Add "putclip" command to set the clipboard, using code from klipsi. --- plpftp/ftp.cc | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- plpftp/ftp.h | 8 +-- plpftp/main.cc | 15 +++++- 3 files changed, 182 insertions(+), 5 deletions(-) (limited to 'plpftp') diff --git a/plpftp/ftp.cc b/plpftp/ftp.cc index 69d6709..3571c91 100644 --- a/plpftp/ftp.cc +++ b/plpftp/ftp.cc @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -50,6 +52,7 @@ #include #include #include +#include #include "ftp.h" @@ -68,6 +71,8 @@ static char psionDir[1024]; static rfsv *comp_a; static int continueRunning; +#define CLIPFILE "C:/System/Data/Clpboard.cbd" + void ftp:: resetUnixPwd() @@ -115,6 +120,7 @@ void ftp::usage() { cout << endl << _("Known RPC commands:") << endl << endl; cout << " ps" << endl; cout << " kill " << endl; + cout << " putclip " << endl; cout << " run [args]" << endl; cout << " killsave " << endl; cout << " runrestore " << endl; @@ -337,8 +343,159 @@ startPrograms(rpcs & r, rfsv & a, const char *file) { return 0; } +bool +ftp::checkClipConnection(rfsv &a, rclip & rc, ppsocket & rclipSocket) +{ + if (canClip == false) + return false; + + if (a.getProtocolVersion() == 3) { + cerr << _("Clipboard protocol not supported by Psion Series 3.") << endl; + return false; + } + + Enum ret; + if ((ret = rc.initClipbd()) == rfsv::E_PSI_GEN_NONE) + return true; + else if (ret == rfsv::E_PSI_GEN_NSUP) + cerr << _("Your Psion does not support the clipboard protocol.\n\ + The reason for that is usually a missing server library.\n\ + Make sure that C:\\System\\Libs\\clipsvr.rsy exists.\n\ + This file is part of PsiWin and usually gets copied to\n\ + your Psion when you enable CopyAnywhere in PsiWin.\n\ + You can also get it from a PsiWin installation directory\n\ + and copy it to your Psion manually.") << endl; + return false; +} + +static void +psiText2ascii(char *buf, int len) { + char *p; + + for (p = buf; len; len--, p++) + switch (*p) { + case 6: + case 7: + *p = '\n'; + break; + case 8: + *p = '\f'; + break; + case 10: + *p = '\t'; + break; + case 11: + case 12: + *p = '-'; + break; + case 15: + case 16: + *p = ' '; + break; + } +} + +static void +ascii2PsiText(char *buf, int len) { + char *p; + + for (p = buf; len; len--, p++) + switch (*p) { + case '\0': + *p = ' '; + case '\n': + *p = 6; + break; + case '\f': + *p = 8; + break; + case '-': + *p = 11; + break; + } +} + +// FIXME: This is almost the same as getln. Ugh. +static char * +slurp(FILE *fp, size_t *final_len) +{ + size_t len = 256; + int c; + char *l = (char *)malloc(len), *s = l; + + assert(l); + for (c = getc(fp); c != EOF; c = getc(fp)) { + if (s == l + len) { + l = (char *)realloc(l, len * 2); + assert(l); + len *= 2; + } + *s++ = c; + } + if (s == l + len) { + l = (char *)realloc(l, len + 1); + assert(l); + } + *s++ = '\0'; + + *final_len = s - l; + l = (char *)realloc(l, s - l); + assert(l); + return l; +} + +int +ftp::putClipText(rpcs & r, rfsv & a, rclip & rc, ppsocket & rclipSocket, const char *file) +{ + Enum res; + u_int32_t fh; + u_int32_t l; + const unsigned char *p; + bufferStore b; + char *data; + FILE *fp; + + if (!checkClipConnection(a, rc, rclipSocket)) + return 1; + + if ((fp = fopen(file, "r")) == NULL) + return 1; + + size_t len; + data = slurp(fp, &len); + fclose(fp); + ascii2PsiText(data, len); + + res = a.freplacefile(0x200, CLIPFILE, fh); + if (res == rfsv::E_PSI_GEN_NONE) { + // Base Header + b.addDWord(0x10000037); // @00 UID 0 + b.addDWord(0x1000003b); // @04 UID 1 + b.addDWord(0); // @08 UID 3 + b.addDWord(0x4739d53b); // @0c Checksum the above + + // Section Table + b.addDWord(0x00000014); // @10 Offset of Section Table + b.addByte(2); // @14 Section Table, length in DWords + b.addDWord(0x10000033); // @15 Section Type (ASCII) + b.addDWord(0x0000001d); // @19 Section Offset + + // Data + b.addDWord(strlen(data)); // @1e Section (String) length + b.addStringT(data); // @22 Data (Psion Word seems to need a + // terminating 0. + + p = (const unsigned char *)b.getString(0); + a.fwrite(fh, p, b.getLen(), l); + a.fclose(fh); + a.fsetattr(CLIPFILE, 0x20, 0x07); + } + + return 0; +} + int ftp:: -session(rfsv & a, rpcs & r, int xargc, char **xargv) +session(rfsv & a, rpcs & r, rclip & rc, ppsocket & rclipSocket, int xargc, char **xargv) { int argc; char *argv[10]; @@ -1075,6 +1232,11 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) stopPrograms(r, argv[1]); continue; } + if (!strcmp(argv[0], "putclip") && (argc == 2)) { + if (putClipText(r, a, rc, rclipSocket, argv[1])) + cerr << _("Error setting clipboard") << endl; + continue; + } if (!strcmp(argv[0], "kill") && (argc >= 2)) { processList tmp; bool anykilled = false; diff --git a/plpftp/ftp.h b/plpftp/ftp.h index aabdf23..73e0586 100644 --- a/plpftp/ftp.h +++ b/plpftp/ftp.h @@ -38,11 +38,14 @@ class ftp { public: ftp(); ~ftp(); - int session(rfsv & a, rpcs & r, int xargc, char **xargv); + int session(rfsv & a, rpcs & r, rclip & rc, ppsocket & rclipSocket, int xargc, char **xargv); + bool canClip; - private: + private: void getCommand(int &argc, char **argv); void initReadline(void); + int putClipText(rpcs & r, rfsv & a, rclip & rc, ppsocket & rclipSocket, const char *data); + bool checkClipConnection(rfsv &a, rclip & rc, ppsocket & rclipSocket); // utilities bool unixDirExists(const char *dir); @@ -60,7 +63,6 @@ class ftp { #endif char defDrive[9]; char localDir[1024]; - // char psionDir[1024]; }; #endif diff --git a/plpftp/main.cc b/plpftp/main.cc index a8a809a..bde68bc 100644 --- a/plpftp/main.cc +++ b/plpftp/main.cc @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -132,6 +134,8 @@ main(int argc, char **argv) ppsocket *skt2; rfsv *a; rpcs *r; + ppsocket *rclipSocket; + rclip *rc; ftp f; const char *host = "127.0.0.1"; int status = 0; @@ -183,12 +187,21 @@ main(int argc, char **argv) rpcsfactory *rp = new rpcsfactory(skt2); a = rf->create(false); r = rp->create(false); + rclipSocket = new ppsocket(); + rclipSocket->connect(NULL, sockNum); + if (rclipSocket) + rc = new rclip(rclipSocket); + f.canClip = rclipSocket && rc ? true : false; if ((a != NULL) && (r != NULL)) { - status = f.session(*a, *r, argc - optind, &argv[optind]); + status = f.session(*a, *r, *rc, *rclipSocket, argc - optind, &argv[optind]); delete r; delete a; delete skt; delete skt2; + if (rclipSocket) + delete rclipSocket; + if (rc) + delete rc; } else { cerr << "plpftp: " << X_(rf->getError()) << endl; status = 1; -- cgit v1.2.3