WMFTPClient.Mod 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. MODULE WMFTPClient; (** AUTHOR "PL"; PURPOSE "FTPClient GUI"; *)
  2. IMPORT
  3. WMStandardComponents, WMWindowManager, WMComponents, FTPClient, TextUtilities,
  4. WMMessages, WMGraphics, Strings, WMRectangles, Modules, KernelLog, WMPopups, Raster, Texts,
  5. WMEditors, WMGrids, WMStringGrids, WMDialogs, WMProperties, WMDropTarget, Streams;
  6. CONST
  7. BufSize = 16*1024; (* internal buffer size, used for file transfer *)
  8. TYPE
  9. KillerMsg = OBJECT
  10. END KillerMsg;
  11. SelectionWrapper = POINTER TO RECORD
  12. sel : FTPClient.FTPListing;
  13. END;
  14. FTPDropInterface = OBJECT(WMDropTarget.DropFiles)
  15. VAR w : Streams.Writer;
  16. ftp : FTPClient.FTPClient;
  17. PROCEDURE &New*(ftp : FTPClient.FTPClient);
  18. BEGIN
  19. SELF.ftp := ftp
  20. END New;
  21. PROCEDURE OpenPut*(CONST remoteName : ARRAY OF CHAR; VAR outw : Streams.Writer; VAR res : WORD);
  22. BEGIN
  23. res := -1;
  24. IF ftp = NIL THEN RETURN END;
  25. KernelLog.String("Uploading File: "); KernelLog.String(remoteName); KernelLog.Ln;
  26. ftp.OpenPut(remoteName, outw, res);
  27. IF res # 0 THEN KernelLog.String("Error: "); KernelLog.String(ftp.msg); KernelLog.Ln;
  28. ELSE w := outw END
  29. END OpenPut;
  30. PROCEDURE ClosePut*(VAR res : WORD);
  31. BEGIN
  32. res := -1;
  33. KernelLog.String("ClosePut called"); KernelLog.Ln;
  34. IF ftp = NIL THEN RETURN END;
  35. IF w # NIL THEN w.Update END;
  36. ftp.ClosePut(res)
  37. END ClosePut;
  38. END FTPDropInterface;
  39. FTPDropTarget = OBJECT(WMDropTarget.DropTarget)
  40. VAR ftp : FTPClient.FTPClient;
  41. PROCEDURE &New*(ftp : FTPClient.FTPClient);
  42. BEGIN
  43. SELF.ftp := ftp
  44. END New;
  45. PROCEDURE GetInterface*(type : LONGINT) : WMDropTarget.DropInterface;
  46. VAR di : FTPDropInterface;
  47. BEGIN
  48. IF type = WMDropTarget.TypeFiles THEN
  49. NEW(di, ftp);
  50. RETURN di
  51. ELSE RETURN NIL
  52. END
  53. END GetInterface;
  54. END FTPDropTarget;
  55. (* Client Window *)
  56. Window* = OBJECT (WMComponents.FormWindow)
  57. VAR
  58. topToolbar, statusbar : WMStandardComponents.Panel;
  59. statusLabel, conLabel, busyLabel : WMStandardComponents.Label;
  60. connect, refresh : WMStandardComponents.Button;
  61. address, port, cmd : WMEditors.Editor;
  62. fullList : WMStandardComponents.Checkbox;
  63. ftpPanel : FTPPanel;
  64. ftp : FTPClient.FTPClient;
  65. connected : BOOLEAN;
  66. busy : BOOLEAN;
  67. PROCEDURE &New*;
  68. VAR vc : WMComponents.VisualComponent;
  69. BEGIN
  70. IncCount;
  71. vc := CreateForm();
  72. Init(vc.bounds.GetWidth(), vc.bounds.GetHeight(), FALSE);
  73. SetContent(vc); ftpPanel.SetColSize;
  74. SetTitle(Strings.NewString("WMFTPClient"));
  75. SetIcon(WMGraphics.LoadImage("WMIcons.tar://WMFTPClient.png", TRUE));
  76. WMWindowManager.DefaultAddWindow(SELF);
  77. connected := FALSE;
  78. END New;
  79. PROCEDURE Handle*(VAR x : WMMessages.Message);
  80. BEGIN
  81. IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) THEN
  82. IF (x.ext IS KillerMsg) THEN Close
  83. ELSE Handle^(x)
  84. END
  85. ELSE Handle^(x)
  86. END
  87. END Handle;
  88. PROCEDURE CreateForm() : WMComponents.VisualComponent;
  89. VAR
  90. panel, pnl : WMStandardComponents.Panel;
  91. label : WMStandardComponents.Label;
  92. bearing : WMRectangles.Rectangle;
  93. BEGIN
  94. NEW(panel); panel.bounds.SetExtents(600, 400); panel.fillColor.Set(LONGINT(0CCCCCCFFH));
  95. bearing := WMRectangles.MakeRect(3, 3, 3, 3);
  96. (* --- Toolbar --- *)
  97. NEW(topToolbar); topToolbar.bounds.SetHeight(20); topToolbar.alignment.Set(WMComponents.AlignTop);
  98. panel.AddContent(topToolbar);
  99. NEW(label); label.bounds.SetWidth(40); label.alignment.Set(WMComponents.AlignLeft);
  100. label.caption.SetAOC(" Host: "); label.textColor.Set(0000000FFH); topToolbar.AddContent(label);
  101. NEW(address); address.bounds.SetWidth(150); address.alignment.Set(WMComponents.AlignLeft);
  102. address.tv.textAlignV.Set(WMGraphics.AlignCenter);
  103. address.multiLine.Set(FALSE); address.fillColor.Set(LONGINT(0FFFFFFFFH)); address.tv.showBorder.Set(TRUE);
  104. address.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  105. address.onEnter.Add(ConnectHandler);
  106. topToolbar.AddContent(address);
  107. address.SetAsString("bluebottle.ethz.ch");
  108. NEW(label); label.bounds.SetWidth(40); label.alignment.Set(WMComponents.AlignLeft);
  109. label.caption.SetAOC(" Port: "); label.textColor.Set(0000000FFH); topToolbar.AddContent(label);
  110. NEW(port); port.bounds.SetWidth(50); port.alignment.Set(WMComponents.AlignLeft);
  111. port.tv.textAlignV.Set(WMGraphics.AlignCenter);
  112. port.multiLine.Set(FALSE); port.fillColor.Set(LONGINT(0FFFFFFFFH)); port.tv.showBorder.Set(TRUE);
  113. port.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1)); port.SetAsString("21");
  114. topToolbar.AddContent(port);
  115. NEW(connect); connect.bounds.SetWidth(100); connect.alignment.Set(WMComponents.AlignLeft);
  116. connect.caption.SetAOC("Connect"); connect.onClick.Add(ConnectHandler);
  117. topToolbar.AddContent(connect);
  118. NEW(refresh); refresh.bounds.SetWidth(100); refresh.alignment.Set(WMComponents.AlignLeft);
  119. refresh.caption.SetAOC("Refresh"); refresh.onClick.Add(RefreshHandler);
  120. topToolbar.AddContent(refresh);
  121. NEW(fullList); fullList.bearing.Set(bearing); fullList.bounds.SetWidth(14); fullList.alignment.Set(WMComponents.AlignLeft);
  122. topToolbar.AddContent(fullList); fullList.state.Set(1);
  123. NEW(label); label.bounds.SetWidth(100); label.alignment.Set(WMComponents.AlignLeft);
  124. label.caption.SetAOC(" Full Listing"); label.textColor.Set(0000000FFH); topToolbar.AddContent(label);
  125. (* --- statusbar --- *)
  126. NEW(statusbar); statusbar.bounds.SetHeight(20); statusbar.alignment.Set(WMComponents.AlignBottom);
  127. panel.AddContent(statusbar);
  128. NEW(conLabel); conLabel.bounds.SetWidth(14); conLabel.alignment.Set(WMComponents.AlignLeft);
  129. statusbar.AddContent(conLabel); conLabel.bearing.Set(bearing); conLabel.fillColor.Set(LONGINT(0CC0000FFH));
  130. NEW(busyLabel); busyLabel.bounds.SetWidth(14); busyLabel.alignment.Set(WMComponents.AlignLeft);
  131. statusbar.AddContent(busyLabel); busyLabel.bearing.Set(bearing); busyLabel.fillColor.Set(LONGINT(0888888FFH));
  132. NEW(statusLabel); statusLabel.bounds.SetWidth(400); statusLabel.alignment.Set(WMComponents.AlignLeft);
  133. statusLabel.textColor.Set(0000000FFH);
  134. (* statusbar.AddContent(statusLabel); *)
  135. (* --- cmd --- *)
  136. NEW(pnl); pnl.bounds.SetHeight(20); pnl.alignment.Set(WMComponents.AlignBottom);
  137. (* panel.AddContent(pnl); *)
  138. NEW(label); label.bounds.SetWidth(80); label.alignment.Set(WMComponents.AlignLeft);
  139. label.caption.SetAOC(" Command: "); label.textColor.Set(0000000FFH); pnl.AddContent(label);
  140. NEW(cmd); cmd.alignment.Set(WMComponents.AlignClient);
  141. cmd.tv.textAlignV.Set(WMGraphics.AlignCenter);
  142. cmd.multiLine.Set(FALSE); cmd.fillColor.Set(LONGINT(0FFFFFFFFH)); cmd.tv.showBorder.Set(TRUE);
  143. cmd.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  144. cmd.onEnter.Add(CommandHandler);
  145. pnl.AddContent(cmd);
  146. statusbar.AddContent(pnl);
  147. (* --- FTP main panel --- *)
  148. NEW(ftpPanel); ftpPanel.alignment.Set(WMComponents.AlignClient); ftpPanel.fillColor.Set(LONGINT(0FFFFFFFFH));
  149. panel.AddContent(ftpPanel);
  150. ftpPanel.owner := SELF;
  151. RETURN panel
  152. END CreateForm;
  153. (* -- Handlers -------------------------------------- *)
  154. PROCEDURE ConnectHandler(sender, data : ANY);
  155. BEGIN
  156. IF connected THEN Disconnect ELSE Connect END
  157. END ConnectHandler;
  158. PROCEDURE Connect;
  159. VAR user, pass, host, temp : ARRAY 64 OF CHAR;
  160. port: LONGINT; res: WORD;
  161. BEGIN
  162. IF ftp # NIL THEN
  163. KernelLog.String("Already open"); KernelLog.Ln; RETURN
  164. END;
  165. user := "anonymous";
  166. pass := "anonymous@somewhere.net";
  167. IF WMDialogs.QueryString("Enter Username:", user) = WMDialogs.ResOk THEN
  168. IF WMDialogs.QueryPassword("Enter Password", pass) = WMDialogs.ResOk THEN
  169. address.GetAsString(host);
  170. IF (host = "") THEN RETURN END; (* check addy *)
  171. SELF.port.GetAsString(temp); Strings.StrToInt(temp, port);
  172. NEW(ftp);
  173. ftp.Open(host, user, pass, port, res);
  174. KernelLog.String(ftp.msg);
  175. IF res = 0 THEN
  176. KernelLog.String("Connected"); KernelLog.Ln;
  177. SetConnected(TRUE);
  178. RefreshHandler(SELF, NIL);
  179. ELSE
  180. ftp := NIL;
  181. KernelLog.String("Connecting failed"); KernelLog.Ln;
  182. END
  183. END
  184. END
  185. END Connect;
  186. PROCEDURE Disconnect;
  187. VAR res : WORD;
  188. BEGIN
  189. IF ftp = NIL THEN
  190. KernelLog.String("not connected"); KernelLog.Ln;
  191. RETURN
  192. END;
  193. ftp.Close(res);
  194. KernelLog.String("closed."); KernelLog.String(ftp.msg); KernelLog.Ln;
  195. ftp := NIL; ftpPanel.curList := NIL; ftpPanel.nofEntries := 0; ftpPanel.PrepareList; ftpPanel.pathEdit.SetAsString("/");
  196. SetConnected(FALSE);
  197. SetBusy(FALSE)
  198. END Disconnect;
  199. PROCEDURE Close*;
  200. BEGIN
  201. IF ftp # NIL THEN Disconnect END;
  202. Close^;
  203. DecCount
  204. END Close;
  205. PROCEDURE CommandHandler(sender, data : ANY);
  206. VAR res : WORD; command : ARRAY 256 OF CHAR;
  207. BEGIN
  208. IF ftp = NIL THEN
  209. KernelLog.String("not connected"); KernelLog.Ln;
  210. RETURN
  211. END;
  212. SetBusy(TRUE);
  213. cmd.GetAsString(command);
  214. IF command # "" THEN ftp.Raw(command, res) END;
  215. cmd.SetAsString("");
  216. SetBusy(FALSE)
  217. END CommandHandler;
  218. PROCEDURE ListHandler(sender, data : ANY);
  219. BEGIN
  220. IF ftp = NIL THEN
  221. KernelLog.String("not connected"); KernelLog.Ln;
  222. RETURN
  223. END;
  224. SetBusy(TRUE);
  225. IF fullList.state.Get() = 1 THEN
  226. ftp.EnumerateDir("")
  227. ELSE
  228. ftp.EnumerateNames
  229. END;
  230. ftpPanel.curList := ftp.listing; ftpPanel.nofEntries := ftp.nofEntries;
  231. ftpPanel.PrepareList;
  232. SetBusy(FALSE)
  233. END ListHandler;
  234. PROCEDURE ChangeDir(path :Strings.String);
  235. VAR res : WORD; dir : ARRAY 256 OF CHAR;
  236. BEGIN
  237. IF ftp = NIL THEN
  238. KernelLog.String("not connected"); KernelLog.Ln;
  239. RETURN
  240. END;
  241. SetBusy(TRUE);
  242. ftp.ChangeDir(path^, res);
  243. IF res = 0 THEN
  244. ftp.GetCurrentDir(dir, res);
  245. IF res = 0 THEN
  246. ftpPanel.pathEdit.SetAsString(dir);
  247. ListHandler(SELF, NIL)
  248. END;
  249. ELSE
  250. KernelLog.String("no such directory"); KernelLog.Ln;
  251. END;
  252. SetBusy(FALSE)
  253. END ChangeDir;
  254. PROCEDURE RefreshHandler(sender, data : ANY);
  255. VAR test : BOOLEAN;
  256. BEGIN
  257. ftpPanel.SetColSize;
  258. IF ftp # NIL THEN
  259. test := ftp.IsAlive();
  260. IF test THEN ListHandler(SELF, NIL)
  261. ELSE Disconnect END;
  262. END
  263. END RefreshHandler;
  264. PROCEDURE SetConnected(con : BOOLEAN);
  265. BEGIN
  266. connected := con;
  267. IF con THEN
  268. conLabel.fillColor.Set(0CC00FFH);
  269. connect.caption.SetAOC("Disconnect");
  270. ELSE
  271. conLabel.fillColor.Set(LONGINT(0CC0000FFH));
  272. connect.caption.SetAOC("Connect");
  273. END
  274. END SetConnected;
  275. PROCEDURE SetBusy(bus : BOOLEAN);
  276. BEGIN
  277. busy := bus;
  278. IF bus THEN busyLabel.fillColor.Set(LONGINT(0FF8800FFH))
  279. ELSE busyLabel.fillColor.Set(LONGINT(0888888FFH)) END
  280. END SetBusy;
  281. END Window;
  282. (* FTPPanel *)
  283. FTPPanel = OBJECT(WMComponents.VisualComponent)
  284. VAR
  285. grid : WMStringGrids.StringGrid;
  286. colWidths : WMGrids.Spacings;
  287. path : WMProperties.StringProperty;
  288. filter : WMProperties.StringProperty;
  289. prefixSearch : WMProperties.BooleanProperty;
  290. filterEdit, pathEdit : WMEditors.Editor;
  291. popup: WMPopups.Popup;
  292. px, py : LONGINT;
  293. parent : FTPClient.FTPEntry;
  294. selection : FTPClient.FTPListing;
  295. owner : Window;
  296. curList : FTPClient.FTPListing;
  297. nofEntries : LONGINT;
  298. PROCEDURE &Init*;
  299. VAR label : WMStandardComponents.Label;
  300. panel : WMStandardComponents.Panel;
  301. BEGIN
  302. Init^;
  303. SetNameAsString(StrFTPPanel);
  304. NEW(parent);
  305. (* new properties *)
  306. NEW(path, FileListPathProt, NIL, NIL); properties.Add(path);
  307. NEW(filter, FileListFilterProt, NIL, NIL); properties.Add(filter);
  308. NEW(panel); panel.bounds.SetHeight(20); panel.alignment.Set(WMComponents.AlignTop);
  309. panel.fillColor.Set(LONGINT(0CCCCCCFFH)); AddContent(panel);
  310. NEW(label); label.bounds.SetWidth(40); label.alignment.Set(WMComponents.AlignLeft);
  311. label.caption.SetAOC(" Path: "); panel.AddContent(label); label.textColor.Set(0000000FFH);
  312. NEW(pathEdit); pathEdit.alignment.Set(WMComponents.AlignClient);
  313. pathEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  314. panel.AddContent(pathEdit); pathEdit.fillColor.Set(LONGINT(0EEEEEEFFH));
  315. pathEdit.onEnter.Add(PathChanged); pathEdit.SetAsString("/");
  316. pathEdit.multiLine.Set(FALSE); pathEdit.tv.defaultTextBgColor.Set(pathEdit.fillColor.Get());
  317. pathEdit.tv.showBorder.Set(TRUE); pathEdit.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  318. NEW(prefixSearch, FileListPrefixSearchProt, NIL, NIL); properties.Add(prefixSearch);
  319. NEW(filterEdit); filterEdit.alignment.Set(WMComponents.AlignTop);
  320. filterEdit.tv.textAlignV.Set(WMGraphics.AlignCenter);
  321. filterEdit.bounds.SetHeight(25); AddContent(filterEdit);
  322. filterEdit.text.onTextChanged.Add(TextChanged);
  323. filterEdit.multiLine.Set(FALSE);
  324. filterEdit.tv.showBorder.Set(TRUE);
  325. NEW(grid);
  326. grid.alignment.Set(WMComponents.AlignClient);
  327. AddContent(grid);
  328. grid.onClickSelected.Add(ClickSelected);
  329. grid.SetExtContextMenuHandler(ContextMenu);
  330. grid.onStartDrag.Add(MyStartDrag);
  331. grid.SetExtDragDroppedHandler(MyDragDropped);
  332. grid.model.Acquire;
  333. grid.model.SetNofCols(4);
  334. grid.model.SetNofRows(1);
  335. grid.fixedRows.Set(1);
  336. grid.model.SetCellText(0, 0, Strings.NewString("Filename"));
  337. grid.model.SetCellText(1, 0, Strings.NewString("Size"));
  338. grid.model.SetCellText(2, 0, Strings.NewString("Modified"));
  339. grid.model.SetCellText(3, 0, Strings.NewString("Attributes"));
  340. grid.SetSelectionMode(WMGrids.GridSelectRows);
  341. NEW(colWidths, 4);
  342. grid.model.Release
  343. END Init;
  344. PROCEDURE SetColSize;
  345. BEGIN
  346. colWidths[0] := (bounds.GetWidth() DIV 2);
  347. colWidths[1] := bounds.GetWidth() DIV 6;
  348. colWidths[2] := bounds.GetWidth() DIV 6;
  349. colWidths[3] := bounds.GetWidth() DIV 6;
  350. grid.SetColSpacings(colWidths);
  351. END SetColSize;
  352. (* -- Handlers -------------------------------------- *)
  353. PROCEDURE ClickSelected(sender, data : ANY);
  354. VAR curSel : FTPClient.FTPListing;
  355. BEGIN
  356. IF (data # NIL) & (data IS FTPClient.FTPEntry) THEN
  357. NEW(curSel, 1);
  358. curSel[0] := data(FTPClient.FTPEntry);
  359. owner.SetBusy(TRUE);
  360. IF curSel[0] = parent THEN KernelLog.String("Directory UP "); owner.ChangeDir(Strings.NewString("..")) END;
  361. IF IsFolder(curSel[0]) THEN (* change into folder *)
  362. owner.ChangeDir(Strings.NewString(curSel[0].filename))
  363. END;
  364. owner.SetBusy(FALSE)
  365. END
  366. END ClickSelected;
  367. PROCEDURE ContextMenu(sender : ANY; x, y: LONGINT);
  368. VAR curSel : FTPClient.FTPListing;
  369. w : SelectionWrapper;
  370. BEGIN
  371. px := x; py := y;
  372. NEW(popup);
  373. curSel := GetSelection();
  374. NEW(w); w.sel := curSel;
  375. IF LEN(curSel) = 0 THEN RETURN END;
  376. IF LEN(curSel) = 1 THEN
  377. popup.AddParButton("Create Dir", CreateDir, w);
  378. popup.AddParButton("Rename", RenameEntry, w)
  379. END;
  380. popup.AddParButton("Delete", DeleteEntries, w);
  381. grid.ToWMCoordinates(x, y, px, py);
  382. popup.Popup(px, py)
  383. END ContextMenu;
  384. PROCEDURE DeleteEntries(sender, data : ANY);
  385. VAR d : FTPClient.FTPEntry;
  386. dr, i : LONGINT; res : WORD;
  387. dp : ARRAY 128 OF CHAR;
  388. delete, always, never : BOOLEAN;
  389. BEGIN
  390. IF popup # NIL THEN popup.Close; popup := NIL END;
  391. IF (data # NIL) & (data IS SelectionWrapper) THEN
  392. always := FALSE; never := FALSE;
  393. FOR i := 0 TO LEN(data(SelectionWrapper).sel) - 1 DO
  394. d := data(SelectionWrapper).sel[i];
  395. delete := FALSE;
  396. IF d # NIL THEN
  397. COPY(d.filename, dp);
  398. IF ~always & ~never THEN
  399. dr := WMDialogs.Message(WMDialogs.TConfirmation, "Confirm deleting file", dp,
  400. {WMDialogs.ResNo, WMDialogs.ResAbort, WMDialogs.ResYes, WMDialogs.ResAll});
  401. IF dr IN {WMDialogs.ResYes, WMDialogs.ResAll} THEN delete := TRUE END;
  402. IF dr = WMDialogs.ResAll THEN always := TRUE END;
  403. IF dr = WMDialogs.ResAbort THEN never := TRUE END;
  404. END;
  405. IF ~never & (delete OR always) THEN
  406. owner.SetBusy(TRUE);
  407. IF IsFolder(d) THEN
  408. owner.ftp.RemoveDir(dp, res)
  409. ELSE
  410. owner.ftp.DeleteFile(dp, res)
  411. END;
  412. IF res # 0 THEN
  413. WMDialogs.Error("Deleting failed", dp)
  414. END;
  415. owner.SetBusy(FALSE);
  416. (* if the dialog was shown then visually update *)
  417. (* IF delete THEN Refresh(NIL, NIL) END *)
  418. END
  419. END
  420. END;
  421. (* end of the operation refresh list *)
  422. (* Refresh(NIL, NIL) *)
  423. END
  424. END DeleteEntries;
  425. PROCEDURE RenameEntry(sender, data : ANY);
  426. VAR d : FTPClient.FTPEntry; rename : WMDialogs.MiniStringInput;
  427. res : WORD;
  428. name, op : ARRAY 128 OF CHAR;
  429. BEGIN
  430. IF popup # NIL THEN popup.Close; popup := NIL END;
  431. IF (data # NIL) & (data IS SelectionWrapper) THEN
  432. d := data(SelectionWrapper).sel[0];
  433. IF d # NIL THEN
  434. (* grid.Acquire; grid.ToWMCoordinates(px, py, wmx, wmy); grid.Release; *)
  435. NEW(rename);
  436. COPY(d.filename, name);
  437. IF rename.Show(px, py, name) = WMDialogs.ResOk THEN
  438. IF name # d.filename THEN
  439. owner.SetBusy(TRUE);
  440. COPY(d.filename, op);
  441. KernelLog.String("Renaming File/Folder: "); KernelLog.String(op); KernelLog.Ln;
  442. owner.ftp.RenameFile(op, name, res);
  443. IF res # 0 THEN
  444. KernelLog.String("Renaming failed: "); KernelLog.Int(res, 0); KernelLog.Ln;
  445. WMDialogs.Error("Renaming failed", name)
  446. END;
  447. owner.SetBusy(FALSE);
  448. (* Refresh(NIL, NIL) *)
  449. END
  450. END
  451. END
  452. END
  453. END RenameEntry;
  454. PROCEDURE CreateDir(sender, data : ANY);
  455. VAR res : WORD;
  456. name : ARRAY 128 OF CHAR;
  457. BEGIN
  458. COPY("NewFolder", name);
  459. IF WMDialogs.QueryString("Create Folder: ", name) = WMDialogs.ResOk THEN
  460. owner.SetBusy(TRUE);
  461. KernelLog.String("Creating Folder: "); KernelLog.String(name); KernelLog.Ln;
  462. owner.ftp.MakeDir(name, res);
  463. IF res # 0 THEN
  464. KernelLog.String("Creating Folder failed: "); KernelLog.Int(res, 0); KernelLog.Ln;
  465. WMDialogs.Error("Creating new Folder failed", name);
  466. END;
  467. owner.SetBusy(FALSE);
  468. (* Refresh(NIL, NIL) *)
  469. END
  470. END CreateDir;
  471. PROCEDURE TextChanged(sender, data : ANY);
  472. VAR str : ARRAY 128 OF CHAR;
  473. BEGIN
  474. filterEdit.GetAsString(str);
  475. filter.Set(Strings.NewString(str))
  476. END TextChanged;
  477. PROCEDURE PathChanged(sender, data : ANY);
  478. VAR str : ARRAY 512 OF CHAR;
  479. BEGIN
  480. pathEdit.GetAsString(str);
  481. path.Set(Strings.NewString(str))
  482. END PathChanged;
  483. PROCEDURE PropertyChanged*(sender, data : ANY);
  484. BEGIN
  485. IF data = path THEN
  486. owner.ChangeDir(path.Get());
  487. ELSIF (data = filter) OR (data = prefixSearch) THEN
  488. PrepareList
  489. ELSE PropertyChanged^(sender, data)
  490. END
  491. END PropertyChanged;
  492. PROCEDURE PrepareList;
  493. VAR i, vis : LONGINT; mask, t : ARRAY 128 OF CHAR; s : Strings.String;
  494. img: WMGraphics.Image;
  495. BEGIN
  496. IF curList = NIL THEN
  497. grid.model.Acquire;
  498. grid.model.SetNofRows(1);
  499. grid.model.Release;
  500. RETURN
  501. END;
  502. s := filter.Get();
  503. mask := "";
  504. IF s # NIL THEN COPY(s^, mask) END;
  505. IF mask = "" THEN
  506. FOR i := 0 TO nofEntries - 1 DO curList[i].visible := TRUE END;
  507. vis := nofEntries
  508. ELSE
  509. IF prefixSearch.Get() & ( mask[Strings.Length(mask)] # "*") THEN Strings.Append(mask, "*") END;
  510. vis := 0;
  511. FOR i := 0 TO nofEntries - 1 DO
  512. IF Strings.Match(mask, curList[i].filename) THEN
  513. curList[i].visible := TRUE;
  514. INC(vis)
  515. ELSE curList[i].visible := FALSE
  516. END
  517. END;
  518. END;
  519. grid.model.Acquire;
  520. grid.model.SetNofRows(vis + 2);
  521. grid.model.SetCellText(0, 1, Strings.NewString("Parent Directory")); grid.model.SetCellData(0, 1, parent);
  522. grid.model.SetCellImage(0, 1, WMGraphics.LoadImage("icons.tar://Parent.png", TRUE));
  523. vis := 0;
  524. FOR i := 0 TO nofEntries - 1 DO
  525. IF curList[i].visible THEN
  526. img := GetImage(curList[i]);
  527. grid.model.SetCellImage(0, vis+2, img);
  528. grid.model.SetCellText(0, vis+2, Strings.NewString(curList[i].filename));
  529. grid.model.SetCellData(0, vis+2, curList[i]);
  530. grid.model.SetCellText(1, vis+2, Strings.NewString(curList[i].size));
  531. COPY(curList[i].d0, t); Strings.Append(t, " "); Strings.Append(t, curList[i].d1); Strings.Append(t, " "); Strings.Append(t, curList[i].d2);
  532. grid.model.SetCellText(2, vis+2, Strings.NewString(t));
  533. grid.model.SetCellText(3, vis+2, Strings.NewString(curList[i].flags));
  534. INC(vis)
  535. END
  536. END;
  537. grid.SetTopPosition(0, 0, TRUE);
  538. grid.model.Release;
  539. END PrepareList;
  540. (* -- Drag-Drop Handlers -----------------------------*)
  541. (* called when an object has been dropped on this FTPList *)
  542. PROCEDURE MyDragDropped(x, y : LONGINT; dragInfo : WMWindowManager.DragInfo; VAR handled : BOOLEAN);
  543. BEGIN
  544. handled := TRUE;
  545. DragDroppedList(x, y, dragInfo)
  546. END MyDragDropped;
  547. (* called by MyDraggedDropped *)
  548. PROCEDURE DragDroppedList(x, y : LONGINT; dragInfo : WMWindowManager.DragInfo);
  549. VAR dropTarget : FTPDropTarget;
  550. BEGIN
  551. NEW(dropTarget, owner.ftp);
  552. dragInfo.data := dropTarget;
  553. owner.SetBusy(TRUE);
  554. IF dragInfo.sender = grid THEN ConfirmDrag(FALSE, dragInfo)
  555. ELSE ConfirmDrag(TRUE, dragInfo) END;
  556. owner.SetBusy(FALSE)
  557. END DragDroppedList;
  558. (* called when a drag-operation has been started *)
  559. PROCEDURE MyStartDrag(sender, data : ANY);
  560. VAR img : WMGraphics.Image;
  561. c : WMGraphics.BufferCanvas;
  562. top, i : LONGINT;
  563. BEGIN
  564. selection := GetSelection();
  565. (* render to bitmap *)
  566. NEW(img); Raster.Create(img, 100, 200, Raster.BGRA8888);
  567. NEW(c, img);
  568. c.SetColor(LONGINT(0FFFF00FFH));
  569. top := 0;
  570. FOR i := 0 TO LEN(selection) - 1 DO
  571. IF selection[i] # NIL THEN
  572. c.Fill(WMRectangles.MakeRect(0, top, 100, top + 25), 0FF80H, WMGraphics.ModeCopy);
  573. c.DrawString(3, top + 20, selection[i].filename);
  574. INC(top, 25)
  575. END
  576. END;
  577. IF grid.StartDrag(NIL, img, 0,0,DragArrivedList, NIL) THEN KernelLog.String("DraggingStarted")
  578. ELSE KernelLog.String("Drag could not be started")
  579. END;
  580. END MyStartDrag;
  581. (* called when an object dragged from this FTPList has been dropped anywhere *)
  582. PROCEDURE DragArrivedList(sender, data : ANY);
  583. VAR di : WMWindowManager.DragInfo;
  584. dt : WMDropTarget.DropTarget;
  585. itf : WMDropTarget.DropInterface;
  586. i : LONGINT; res : WORD;
  587. sel : FTPClient.FTPListing;
  588. url : ARRAY 1024 OF CHAR;
  589. text : Texts.Text;
  590. textPos : Texts.TextPosition;
  591. BEGIN
  592. sel := selection;
  593. IF sel = NIL THEN RETURN END;
  594. IF (data # NIL) & (data IS WMWindowManager.DragInfo) THEN
  595. di := data(WMWindowManager.DragInfo);
  596. IF (di.data # NIL) & (di.data IS WMDropTarget.DropTarget) THEN
  597. dt := di.data(WMDropTarget.DropTarget)
  598. ELSE RETURN
  599. END
  600. ELSE RETURN
  601. END;
  602. (* File *)
  603. itf := dt.GetInterface(WMDropTarget.TypeFiles);
  604. IF itf # NIL THEN
  605. FOR i := 0 TO LEN(selection) - 1 DO
  606. IF selection[i] # NIL THEN
  607. COPY(selection[i].filename, url);
  608. IF ~IsFolder(selection[i]) THEN
  609. CopyFile(itf(WMDropTarget.DropFiles), url, url, res)
  610. END
  611. END
  612. END;
  613. RETURN
  614. END;
  615. (* Text *)
  616. itf := dt.GetInterface(WMDropTarget.TypeText);
  617. IF itf # NIL THEN
  618. text := itf(WMDropTarget.DropText).text;
  619. textPos := itf(WMDropTarget.DropText).pos;
  620. IF (text # NIL) & (textPos # NIL) THEN
  621. text.AcquireWrite;
  622. FOR i := 0 TO LEN(selection) - 1 DO
  623. IF selection[i] # NIL THEN
  624. COPY(selection[i].filename, url);
  625. Strings.AppendChar(url, CHR(Texts.NewLineChar));
  626. TextUtilities.StrToText(text, textPos.GetPosition(), url)
  627. END
  628. END;
  629. text.ReleaseWrite
  630. END;
  631. RETURN
  632. END;
  633. END DragArrivedList;
  634. (* -- Helpers --------------------------------------- *)
  635. PROCEDURE GetSelection() : FTPClient.FTPListing;
  636. VAR selection : FTPClient.FTPListing;
  637. l, t, r, b, i, j : LONGINT;
  638. p : ANY;
  639. BEGIN
  640. grid.model.Acquire;
  641. grid.GetSelection(l, t, r, b);
  642. NEW(selection, b- t + 1);
  643. j := 0;
  644. FOR i := t TO b DO
  645. p := grid.model.GetCellData(0, i);
  646. IF (p # NIL) & (p IS FTPClient.FTPEntry) THEN
  647. selection[j] := p(FTPClient.FTPEntry);
  648. INC(j)
  649. END
  650. END;
  651. grid.model.Release;
  652. RETURN selection
  653. END GetSelection;
  654. PROCEDURE CopyFile(target : WMDropTarget.DropFiles; CONST local, remote : ARRAY OF CHAR; VAR res : WORD);
  655. VAR w : Streams.Writer;
  656. r : Streams.Reader;
  657. buf: ARRAY BufSize OF CHAR; len : LONGINT;
  658. BEGIN
  659. res := -1;
  660. owner.SetBusy(TRUE);
  661. owner.ftp.OpenGet(local, r, res);
  662. IF res = 0 THEN
  663. target.OpenPut(remote, w, res);
  664. KernelLog.String("Downloading File: "); KernelLog.String(local); KernelLog.Ln;
  665. IF res = 0 THEN
  666. REPEAT
  667. r.Bytes(buf, 0, BufSize, len); w.Bytes(buf, 0, len);
  668. UNTIL r.res # 0;
  669. target.ClosePut(res)
  670. END;
  671. owner.ftp.CloseGet(res)
  672. ELSE
  673. KernelLog.String("Error: "); KernelLog.String(owner.ftp.msg); KernelLog.Ln
  674. END;
  675. owner.SetBusy(FALSE)
  676. END CopyFile;
  677. PROCEDURE IsFolder(entry : FTPClient.FTPEntry) : BOOLEAN;
  678. BEGIN
  679. IF (entry.flags[0] = "<") OR (entry.flags[0] = "d") THEN RETURN TRUE;
  680. ELSE RETURN FALSE END;
  681. END IsFolder;
  682. PROCEDURE GetImage(entry : FTPClient.FTPEntry) : WMGraphics.Image;
  683. VAR img : WMGraphics.Image; temp: ARRAY 256 OF CHAR;
  684. BEGIN
  685. COPY("icons.tar://", temp);
  686. IF IsFolder(entry) THEN
  687. Strings.Append(temp, "Folder.png");
  688. ELSE
  689. Strings.Append(temp, "File.png");
  690. END;
  691. Strings.Append(temp, "");
  692. img := WMGraphics.LoadImage(temp, TRUE);
  693. RETURN img
  694. END GetImage;
  695. END FTPPanel;
  696. (* ------------------------------------------------------------------ *)
  697. VAR
  698. nofWindows : LONGINT;
  699. FileListPathProt : WMProperties.StringProperty;
  700. FileListFilterProt : WMProperties.StringProperty;
  701. FileListPrefixSearchProt : WMProperties.BooleanProperty;
  702. StrFTPPanel : Strings.String;
  703. PROCEDURE InitStrings;
  704. BEGIN
  705. StrFTPPanel := Strings.NewString("FTPPanel");
  706. END InitStrings;
  707. PROCEDURE InitPrototypes;
  708. BEGIN
  709. NEW(FileListPathProt, NIL, Strings.NewString("Path"), Strings.NewString("contains the displayed path"));
  710. NEW(FileListFilterProt, NIL, Strings.NewString("Filter"), Strings.NewString("display filename filter"));
  711. NEW(FileListPrefixSearchProt, NIL, Strings.NewString("PrefixSearch"), Strings.NewString("match prefix only"));
  712. FileListPrefixSearchProt.Set(TRUE);
  713. END InitPrototypes;
  714. PROCEDURE Open*;
  715. VAR instance : Window;
  716. BEGIN
  717. NEW(instance);
  718. END Open;
  719. PROCEDURE IncCount;
  720. BEGIN {EXCLUSIVE}
  721. INC(nofWindows)
  722. END IncCount;
  723. PROCEDURE DecCount;
  724. BEGIN {EXCLUSIVE}
  725. DEC(nofWindows)
  726. END DecCount;
  727. PROCEDURE Cleanup;
  728. VAR die : KillerMsg;
  729. msg : WMMessages.Message;
  730. m : WMWindowManager.WindowManager;
  731. BEGIN {EXCLUSIVE}
  732. NEW(die); msg.ext := die; msg.msgType := WMMessages.MsgExt;
  733. m := WMWindowManager.GetDefaultManager();
  734. m.Broadcast(msg);
  735. AWAIT(nofWindows = 0)
  736. END Cleanup;
  737. BEGIN
  738. InitStrings;
  739. InitPrototypes;
  740. Modules.InstallTermHandler(Cleanup);
  741. END WMFTPClient.
  742. ---------------------------------------------
  743. WMFTPClient.Open~ System.Free WMFTPClient ~