DragDropInternet.pas 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. unit DragDropInternet;
  2. // -----------------------------------------------------------------------------
  3. // Project: Drag and Drop Component Suite.
  4. // Module: DragDropInternet
  5. // Description: Implements Dragging and Dropping of internet related data.
  6. // Version: 4.0
  7. // Date: 18-MAY-2001
  8. // Target: Win32, Delphi 5-6
  9. // Authors: Anders Melander, anders@melander.dk, http://www.melander.dk
  10. // Copyright © 1997-2001 Angus Johnson & Anders Melander
  11. // -----------------------------------------------------------------------------
  12. interface
  13. uses
  14. DragDrop,
  15. DropTarget,
  16. DropSource,
  17. DragDropFormats,
  18. Windows,
  19. Classes,
  20. ActiveX;
  21. type
  22. ////////////////////////////////////////////////////////////////////////////////
  23. //
  24. // TURLClipboardFormat
  25. //
  26. ////////////////////////////////////////////////////////////////////////////////
  27. // Implements support for the 'UniformResourceLocator' format.
  28. ////////////////////////////////////////////////////////////////////////////////
  29. TURLClipboardFormat = class(TCustomTextClipboardFormat)
  30. public
  31. function GetClipboardFormat: TClipFormat; override;
  32. property URL: string read GetString write SetString;
  33. end;
  34. ////////////////////////////////////////////////////////////////////////////////
  35. //
  36. // TNetscapeBookmarkClipboardFormat
  37. //
  38. ////////////////////////////////////////////////////////////////////////////////
  39. // Implements support for the 'Netscape Bookmark' format.
  40. ////////////////////////////////////////////////////////////////////////////////
  41. TNetscapeBookmarkClipboardFormat = class(TCustomSimpleClipboardFormat)
  42. private
  43. FURL : string;
  44. FTitle : string;
  45. protected
  46. function ReadData(Value: pointer; Size: integer): boolean; override;
  47. function WriteData(Value: pointer; Size: integer): boolean; override;
  48. function GetSize: integer; override;
  49. public
  50. function GetClipboardFormat: TClipFormat; override;
  51. procedure Clear; override;
  52. property URL: string read FURL write FURL;
  53. property Title: string read FTitle write FTitle;
  54. end;
  55. ////////////////////////////////////////////////////////////////////////////////
  56. //
  57. // TNetscapeImageClipboardFormat
  58. //
  59. ////////////////////////////////////////////////////////////////////////////////
  60. // Implements support for the 'Netscape Image Format' format.
  61. ////////////////////////////////////////////////////////////////////////////////
  62. TNetscapeImageClipboardFormat = class(TCustomSimpleClipboardFormat)
  63. private
  64. FURL : string;
  65. FTitle : string;
  66. FImage : string;
  67. FLowRes : string;
  68. FExtra : string;
  69. FHeight : integer;
  70. FWidth : integer;
  71. protected
  72. function ReadData(Value: pointer; Size: integer): boolean; override;
  73. function WriteData(Value: pointer; Size: integer): boolean; override;
  74. function GetSize: integer; override;
  75. public
  76. function GetClipboardFormat: TClipFormat; override;
  77. procedure Clear; override;
  78. property URL: string read FURL write FURL;
  79. property Title: string read FTitle write FTitle;
  80. property Image: string read FImage write FImage;
  81. property LowRes: string read FLowRes write FLowRes;
  82. property Extra: string read FExtra write FExtra;
  83. property Height: integer read FHeight write FHeight;
  84. property Width: integer read FWidth write FWidth;
  85. end;
  86. ////////////////////////////////////////////////////////////////////////////////
  87. //
  88. // TVCardClipboardFormat
  89. //
  90. ////////////////////////////////////////////////////////////////////////////////
  91. // Implements support for the '+//ISBN 1-887687-00-9::versit::PDI//vCard'
  92. // (vCard) format.
  93. ////////////////////////////////////////////////////////////////////////////////
  94. TVCardClipboardFormat = class(TCustomStringListClipboardFormat)
  95. protected
  96. function ReadData(Value: pointer; Size: integer): boolean; override;
  97. function WriteData(Value: pointer; Size: integer): boolean; override;
  98. function GetSize: integer; override;
  99. public
  100. function GetClipboardFormat: TClipFormat; override;
  101. property Items: TStrings read GetLines;
  102. end;
  103. ////////////////////////////////////////////////////////////////////////////////
  104. //
  105. // THTMLClipboardFormat
  106. //
  107. ////////////////////////////////////////////////////////////////////////////////
  108. // Implements support for the 'HTML Format' format.
  109. ////////////////////////////////////////////////////////////////////////////////
  110. THTMLClipboardFormat = class(TCustomStringListClipboardFormat)
  111. public
  112. function GetClipboardFormat: TClipFormat; override;
  113. function HasData: boolean; override;
  114. function Assign(Source: TCustomDataFormat): boolean; override;
  115. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  116. property HTML: TStrings read GetLines;
  117. end;
  118. ////////////////////////////////////////////////////////////////////////////////
  119. //
  120. // TRFC822ClipboardFormat
  121. //
  122. ////////////////////////////////////////////////////////////////////////////////
  123. TRFC822ClipboardFormat = class(TCustomStringListClipboardFormat)
  124. public
  125. function GetClipboardFormat: TClipFormat; override;
  126. function Assign(Source: TCustomDataFormat): boolean; override;
  127. function AssignTo(Dest: TCustomDataFormat): boolean; override;
  128. property Text: TStrings read GetLines;
  129. end;
  130. ////////////////////////////////////////////////////////////////////////////////
  131. //
  132. // TURLDataFormat
  133. //
  134. ////////////////////////////////////////////////////////////////////////////////
  135. // Renderer for URL formats.
  136. ////////////////////////////////////////////////////////////////////////////////
  137. TURLDataFormat = class(TCustomDataFormat)
  138. private
  139. FURL : string;
  140. FTitle : string;
  141. procedure SetTitle(const Value: string);
  142. procedure SetURL(const Value: string);
  143. protected
  144. public
  145. function Assign(Source: TClipboardFormat): boolean; override;
  146. function AssignTo(Dest: TClipboardFormat): boolean; override;
  147. procedure Clear; override;
  148. function HasData: boolean; override;
  149. function NeedsData: boolean; override;
  150. property URL: string read FURL write SetURL;
  151. property Title: string read FTitle write SetTitle;
  152. end;
  153. ////////////////////////////////////////////////////////////////////////////////
  154. //
  155. // THTMLDataFormat
  156. //
  157. ////////////////////////////////////////////////////////////////////////////////
  158. // Renderer for HTML text data.
  159. ////////////////////////////////////////////////////////////////////////////////
  160. THTMLDataFormat = class(TCustomDataFormat)
  161. private
  162. FHTML: TStrings;
  163. procedure SetHTML(const Value: TStrings);
  164. protected
  165. public
  166. constructor Create(AOwner: TDragDropComponent); override;
  167. destructor Destroy; override;
  168. function Assign(Source: TClipboardFormat): boolean; override;
  169. function AssignTo(Dest: TClipboardFormat): boolean; override;
  170. procedure Clear; override;
  171. function HasData: boolean; override;
  172. function NeedsData: boolean; override;
  173. property HTML: TStrings read FHTML write SetHTML;
  174. end;
  175. ////////////////////////////////////////////////////////////////////////////////
  176. //
  177. // TOutlookMailDataFormat
  178. //
  179. ////////////////////////////////////////////////////////////////////////////////
  180. // Renderer for Microsoft Outlook email formats.
  181. ////////////////////////////////////////////////////////////////////////////////
  182. (*
  183. TOutlookMessage = class;
  184. TOutlookAttachments = class(TObject)
  185. public
  186. property Attachments[Index: integer]: TOutlookMessage; default;
  187. property Count: integer;
  188. end;
  189. TOutlookMessage = class(TObject)
  190. public
  191. property Text: string;
  192. property Stream: IStream;
  193. property Attachments: TOutlookAttachments;
  194. end;
  195. *)
  196. TOutlookMailDataFormat = class(TCustomDataFormat)
  197. private
  198. FStorages : TStorageInterfaceList;
  199. protected
  200. public
  201. constructor Create(AOwner: TDragDropComponent); override;
  202. destructor Destroy; override;
  203. function Assign(Source: TClipboardFormat): boolean; override;
  204. function AssignTo(Dest: TClipboardFormat): boolean; override;
  205. procedure Clear; override;
  206. function HasData: boolean; override;
  207. function NeedsData: boolean; override;
  208. property Storages: TStorageInterfaceList read FStorages;
  209. // property Streams: TStreamInterfaceList;
  210. // property Messages: TOutlookAttachments;
  211. end;
  212. ////////////////////////////////////////////////////////////////////////////////
  213. //
  214. // TDropURLTarget
  215. //
  216. ////////////////////////////////////////////////////////////////////////////////
  217. // URL drop target component.
  218. ////////////////////////////////////////////////////////////////////////////////
  219. TDropURLTarget = class(TCustomDropMultiTarget)
  220. private
  221. FURLFormat : TURLDataFormat;
  222. protected
  223. function GetTitle: string;
  224. function GetURL: string;
  225. function GetPreferredDropEffect: LongInt; override;
  226. public
  227. constructor Create(AOwner: TComponent); override;
  228. destructor Destroy; override;
  229. property URL: string read GetURL;
  230. property Title: string read GetTitle;
  231. end;
  232. ////////////////////////////////////////////////////////////////////////////////
  233. //
  234. // TDropHtmlTarget
  235. //
  236. ////////////////////////////////////////////////////////////////////////////////
  237. // Html drop target component.
  238. ////////////////////////////////////////////////////////////////////////////////
  239. TDropHtmlTarget = class(TCustomDropMultiTarget)
  240. private
  241. FHTMLFormat : THTMLDataFormat;
  242. protected
  243. function GetHtml: string;
  244. function GetPreferredDropEffect: LongInt; override;
  245. public
  246. constructor Create(AOwner: TComponent); override;
  247. destructor Destroy; override;
  248. property Html: string read GetHtml;
  249. end;
  250. ////////////////////////////////////////////////////////////////////////////////
  251. //
  252. // TDropURLSource
  253. //
  254. ////////////////////////////////////////////////////////////////////////////////
  255. // URL drop source component.
  256. ////////////////////////////////////////////////////////////////////////////////
  257. TDropURLSource = class(TCustomDropMultiSource)
  258. private
  259. FURLFormat : TURLDataFormat;
  260. procedure SetTitle(const Value: string);
  261. procedure SetURL(const Value: string);
  262. protected
  263. function GetTitle: string;
  264. function GetURL: string;
  265. public
  266. constructor Create(AOwner: TComponent); override;
  267. destructor Destroy; override;
  268. published
  269. property URL: string read GetURL write SetURL;
  270. property Title: string read GetTitle write SetTitle;
  271. end;
  272. ////////////////////////////////////////////////////////////////////////////////
  273. //
  274. // Component registration
  275. //
  276. ////////////////////////////////////////////////////////////////////////////////
  277. procedure Register;
  278. ////////////////////////////////////////////////////////////////////////////////
  279. //
  280. // Misc.
  281. //
  282. ////////////////////////////////////////////////////////////////////////////////
  283. function GetURLFromFile(const Filename: string; var URL: string): boolean;
  284. function GetURLFromStream(Stream: TStream; var URL: string): boolean;
  285. function ConvertURLToFilename(const url: string): string;
  286. function IsHTML(const s: string): boolean;
  287. function MakeHTML(const s: string): string;
  288. ////////////////////////////////////////////////////////////////////////////////
  289. ////////////////////////////////////////////////////////////////////////////////
  290. //
  291. // IMPLEMENTATION
  292. //
  293. ////////////////////////////////////////////////////////////////////////////////
  294. ////////////////////////////////////////////////////////////////////////////////
  295. implementation
  296. uses
  297. SysUtils,
  298. ShlObj,
  299. DragDropFile,
  300. DragDropPIDL;
  301. ////////////////////////////////////////////////////////////////////////////////
  302. //
  303. // Component registration
  304. //
  305. ////////////////////////////////////////////////////////////////////////////////
  306. procedure Register;
  307. begin
  308. RegisterComponents(DragDropComponentPalettePage, [TDropURLTarget,
  309. TDropURLSource, TDropHtmlTarget]);
  310. end;
  311. ////////////////////////////////////////////////////////////////////////////////
  312. //
  313. // Utilities
  314. //
  315. ////////////////////////////////////////////////////////////////////////////////
  316. function GetURLFromFile(const Filename: string; var URL: string): boolean;
  317. var
  318. Stream : TStream;
  319. begin
  320. Stream := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  321. try
  322. Result := GetURLFromStream(Stream, URL);
  323. finally
  324. Stream.Free;
  325. end;
  326. end;
  327. function GetURLFromString(const s: string; var URL: string): boolean;
  328. var
  329. Stream : TMemoryStream;
  330. begin
  331. Stream := TMemoryStream.Create;
  332. try
  333. Stream.Size := Length(s);
  334. Move(PChar(s)^, Stream.Memory^, Length(s));
  335. Result := GetURLFromStream(Stream, URL);
  336. finally
  337. Stream.Free;
  338. end;
  339. end;
  340. const
  341. // *** DO NOT LOCALIZE ***
  342. InternetShortcut = '[InternetShortcut]';
  343. InternetShortcutExt = '.url';
  344. function GetURLFromStream(Stream: TStream; var URL: string): boolean;
  345. var
  346. URLfile : TStringList;
  347. i : integer;
  348. s : string;
  349. p : PChar;
  350. begin
  351. Result := False;
  352. URLfile := TStringList.Create;
  353. try
  354. URLFile.LoadFromStream(Stream);
  355. i := 0;
  356. while (i < URLFile.Count-1) do
  357. begin
  358. if (CompareText(URLFile[i], InternetShortcut) = 0) then
  359. begin
  360. inc(i);
  361. while (i < URLFile.Count) do
  362. begin
  363. s := URLFile[i];
  364. p := PChar(s);
  365. if (StrLIComp(p, 'URL=', length('URL=')) = 0) then
  366. begin
  367. inc(p, length('URL='));
  368. URL := p;
  369. Result := True;
  370. exit;
  371. end else
  372. if (p^ = '[') then
  373. exit;
  374. inc(i);
  375. end;
  376. end;
  377. inc(i);
  378. end;
  379. finally
  380. URLFile.Free;
  381. end;
  382. end;
  383. function ConvertURLToFilename(const url: string): string;
  384. const
  385. Invalids : set of char
  386. = ['\', '/', ':', '?', '*', '<', '>', ',', '|', '''', '"'];
  387. var
  388. i: integer;
  389. LastInvalid: boolean;
  390. begin
  391. Result := url;
  392. if (AnsiStrLIComp(PChar(lowercase(Result)), 'http://', 7) = 0) then
  393. delete(Result, 1, 7)
  394. else if (AnsiStrLIComp(PChar(lowercase(Result)), 'ftp://', 6) = 0) then
  395. delete(Result, 1, 6)
  396. else if (AnsiStrLIComp(PChar(lowercase(Result)), 'mailto:', 7) = 0) then
  397. delete(Result, 1, 7)
  398. else if (AnsiStrLIComp(PChar(lowercase(Result)), 'file:', 5) = 0) then
  399. delete(Result, 1, 5);
  400. if (length(Result) > 120) then
  401. SetLength(Result, 120);
  402. // Truncate at first slash
  403. i := pos('/', Result);
  404. if (i > 0) then
  405. SetLength(Result, i-1);
  406. // Replace invalids with spaces.
  407. // If string starts with invalids, they are trimmed.
  408. LastInvalid := True;
  409. for i := length(Result) downto 1 do
  410. if (Result[i] in Invalids) then
  411. begin
  412. if (not LastInvalid) then
  413. begin
  414. Result[i] := ' ';
  415. LastInvalid := True;
  416. end else
  417. // Repeating invalids are trimmed.
  418. Delete(Result, i, 1);
  419. end else
  420. LastInvalid := False;
  421. if Result = '' then
  422. Result := 'untitled';
  423. Result := Result+InternetShortcutExt;
  424. end;
  425. function IsHTML(const s: string): boolean;
  426. begin
  427. Result := (pos('<html', LowerCase(Copy(s, 1, 500))) > 0);
  428. end;
  429. function MakeHTML(const s: string): string;
  430. begin
  431. { TODO -oanme -cImprovement : Needs to escape special chars in text to HTML conversion. }
  432. { TODO -oanme -cImprovement : Needs better text to HTML conversion. }
  433. if (not IsHTML(s)) then
  434. Result := '<HTML>'#13#10'<BODY>'#13#10 + s + #13#10'</BODY>'#13#10'</HTML>'
  435. else
  436. Result := s;
  437. end;
  438. ////////////////////////////////////////////////////////////////////////////////
  439. //
  440. // TURLClipboardFormat
  441. //
  442. ////////////////////////////////////////////////////////////////////////////////
  443. var
  444. CF_URL: TClipFormat = 0;
  445. function TURLClipboardFormat.GetClipboardFormat: TClipFormat;
  446. begin
  447. if (CF_URL = 0) then
  448. CF_URL := RegisterClipboardFormat(CFSTR_SHELLURL);
  449. Result := CF_URL;
  450. end;
  451. ////////////////////////////////////////////////////////////////////////////////
  452. //
  453. // TNetscapeBookmarkClipboardFormat
  454. //
  455. ////////////////////////////////////////////////////////////////////////////////
  456. var
  457. CF_NETSCAPEBOOKMARK: TClipFormat = 0;
  458. function TNetscapeBookmarkClipboardFormat.GetClipboardFormat: TClipFormat;
  459. begin
  460. if (CF_NETSCAPEBOOKMARK = 0) then
  461. CF_NETSCAPEBOOKMARK := RegisterClipboardFormat('Netscape Bookmark'); // *** DO NOT LOCALIZE ***
  462. Result := CF_NETSCAPEBOOKMARK;
  463. end;
  464. function TNetscapeBookmarkClipboardFormat.GetSize: integer;
  465. begin
  466. Result := 0;
  467. if (FURL <> '') then
  468. begin
  469. inc(Result, 1024);
  470. if (FTitle <> '') then
  471. inc(Result, 1024);
  472. end;
  473. end;
  474. function TNetscapeBookmarkClipboardFormat.ReadData(Value: pointer;
  475. Size: integer): boolean;
  476. begin
  477. // Note: No check for missing string terminator!
  478. FURL := PChar(Value);
  479. if (Size > 1024) then
  480. begin
  481. inc(PChar(Value), 1024);
  482. FTitle := PChar(Value);
  483. end;
  484. Result := True;
  485. end;
  486. function TNetscapeBookmarkClipboardFormat.WriteData(Value: pointer;
  487. Size: integer): boolean;
  488. begin
  489. StrLCopy(Value, PChar(FURL), Size);
  490. dec(Size, 1024);
  491. if (Size > 0) and (FTitle <> '') then
  492. begin
  493. inc(PChar(Value), 1024);
  494. StrLCopy(Value, PChar(FTitle), Size);
  495. end;
  496. Result := True;
  497. end;
  498. procedure TNetscapeBookmarkClipboardFormat.Clear;
  499. begin
  500. FURL := '';
  501. FTitle := '';
  502. end;
  503. ////////////////////////////////////////////////////////////////////////////////
  504. //
  505. // TNetscapeImageClipboardFormat
  506. //
  507. ////////////////////////////////////////////////////////////////////////////////
  508. var
  509. CF_NETSCAPEIMAGE: TClipFormat = 0;
  510. function TNetscapeImageClipboardFormat.GetClipboardFormat: TClipFormat;
  511. begin
  512. if (CF_NETSCAPEIMAGE = 0) then
  513. CF_NETSCAPEIMAGE := RegisterClipboardFormat('Netscape Image Format');
  514. Result := CF_NETSCAPEIMAGE;
  515. end;
  516. type
  517. TNetscapeImageRec = record
  518. Size ,
  519. _Unknown1 ,
  520. Width ,
  521. Height ,
  522. HorMargin ,
  523. VerMargin ,
  524. Border ,
  525. OfsLowRes ,
  526. OfsTitle ,
  527. OfsURL ,
  528. OfsExtra : DWORD
  529. end;
  530. PNetscapeImageRec = ^TNetscapeImageRec;
  531. function TNetscapeImageClipboardFormat.GetSize: integer;
  532. begin
  533. Result := SizeOf(TNetscapeImageRec);
  534. inc(Result, Length(FImage)+1);
  535. if (FLowRes <> '') then
  536. inc(Result, Length(FLowRes)+1);
  537. if (FTitle <> '') then
  538. inc(Result, Length(FTitle)+1);
  539. if (FUrl <> '') then
  540. inc(Result, Length(FUrl)+1);
  541. if (FExtra <> '') then
  542. inc(Result, Length(FExtra)+1);
  543. end;
  544. function TNetscapeImageClipboardFormat.ReadData(Value: pointer;
  545. Size: integer): boolean;
  546. begin
  547. Result := (Size > SizeOf(TNetscapeImageRec));
  548. if (Result) then
  549. begin
  550. FWidth := PNetscapeImageRec(Value)^.Width;
  551. FHeight := PNetscapeImageRec(Value)^.Height;
  552. FImage := PChar(Value) + SizeOf(TNetscapeImageRec);
  553. if (PNetscapeImageRec(Value)^.OfsLowRes <> 0) then
  554. FLowRes := PChar(Value) + PNetscapeImageRec(Value)^.OfsLowRes;
  555. if (PNetscapeImageRec(Value)^.OfsTitle <> 0) then
  556. FTitle := PChar(Value) + PNetscapeImageRec(Value)^.OfsTitle;
  557. if (PNetscapeImageRec(Value)^.OfsURL <> 0) then
  558. FUrl := PChar(Value) + PNetscapeImageRec(Value)^.OfsUrl;
  559. if (PNetscapeImageRec(Value)^.OfsExtra <> 0) then
  560. FExtra := PChar(Value) + PNetscapeImageRec(Value)^.OfsExtra;
  561. end;
  562. end;
  563. function TNetscapeImageClipboardFormat.WriteData(Value: pointer;
  564. Size: integer): boolean;
  565. var
  566. NetscapeImageRec : PNetscapeImageRec;
  567. begin
  568. Result := (Size > SizeOf(TNetscapeImageRec));
  569. if (Result) then
  570. begin
  571. NetscapeImageRec := PNetscapeImageRec(Value);
  572. NetscapeImageRec^.Width := FWidth;
  573. NetscapeImageRec^.Height := FHeight;
  574. inc(PChar(Value), SizeOf(TNetscapeImageRec));
  575. dec(Size, SizeOf(TNetscapeImageRec));
  576. StrLCopy(Value, PChar(FImage), Size);
  577. dec(Size, Length(FImage)+1);
  578. if (Size <= 0) then
  579. exit;
  580. if (FLowRes <> '') then
  581. begin
  582. StrLCopy(Value, PChar(FLowRes), Size);
  583. NetscapeImageRec^.OfsLowRes := integer(Value) - integer(NetscapeImageRec);
  584. dec(Size, Length(FLowRes)+1);
  585. inc(PChar(Value), Length(FLowRes)+1);
  586. if (Size <= 0) then
  587. exit;
  588. end;
  589. if (FTitle <> '') then
  590. begin
  591. StrLCopy(Value, PChar(FTitle), Size);
  592. NetscapeImageRec^.OfsTitle := integer(Value) - integer(NetscapeImageRec);
  593. dec(Size, Length(FTitle)+1);
  594. inc(PChar(Value), Length(FTitle)+1);
  595. if (Size <= 0) then
  596. exit;
  597. end;
  598. if (FUrl <> '') then
  599. begin
  600. StrLCopy(Value, PChar(FUrl), Size);
  601. NetscapeImageRec^.OfsUrl := integer(Value) - integer(NetscapeImageRec);
  602. dec(Size, Length(FUrl)+1);
  603. inc(PChar(Value), Length(FUrl)+1);
  604. if (Size <= 0) then
  605. exit;
  606. end;
  607. if (FExtra <> '') then
  608. begin
  609. StrLCopy(Value, PChar(FExtra), Size);
  610. NetscapeImageRec^.OfsExtra := integer(Value) - integer(NetscapeImageRec);
  611. dec(Size, Length(FExtra)+1);
  612. inc(PChar(Value), Length(FExtra)+1);
  613. if (Size <= 0) then
  614. exit;
  615. end;
  616. end;
  617. end;
  618. procedure TNetscapeImageClipboardFormat.Clear;
  619. begin
  620. FURL := '';
  621. FTitle := '';
  622. FImage := '';
  623. FLowRes := '';
  624. FExtra := '';
  625. FHeight := 0;
  626. FWidth := 0;
  627. end;
  628. ////////////////////////////////////////////////////////////////////////////////
  629. //
  630. // TVCardClipboardFormat
  631. //
  632. ////////////////////////////////////////////////////////////////////////////////
  633. var
  634. CF_VCARD: TClipFormat = 0;
  635. function TVCardClipboardFormat.GetClipboardFormat: TClipFormat;
  636. begin
  637. if (CF_VCARD = 0) then
  638. CF_VCARD := RegisterClipboardFormat('+//ISBN 1-887687-00-9::versit::PDI//vCard'); // *** DO NOT LOCALIZE ***
  639. Result := CF_VCARD;
  640. end;
  641. function TVCardClipboardFormat.GetSize: integer;
  642. var
  643. i : integer;
  644. begin
  645. if (Items.Count > 0) then
  646. begin
  647. Result := 22; // Length('begin:vcard'+#13+'end:vcard'+#0);
  648. for i := 0 to Items.Count-1 do
  649. inc(Result, Length(Items[i])+1);
  650. end else
  651. Result := 0;
  652. end;
  653. function TVCardClipboardFormat.ReadData(Value: pointer; Size: integer): boolean;
  654. var
  655. i : integer;
  656. s : string;
  657. begin
  658. Result := inherited ReadData(Value, Size);
  659. if (Result) then
  660. begin
  661. // Zap vCard header and trailer
  662. if (Items.Count > 0) and (CompareText(Items[0], 'begin:vcard') = 0) then
  663. Items.Delete(0);
  664. if (Items.Count > 0) and (CompareText(Items[Items.Count-1], 'end:vcard') = 0) then
  665. Items.Delete(Items.Count-1);
  666. // Convert to item/value list
  667. for i := 0 to Items.Count-1 do
  668. if (pos(':', Items[i]) > 0) then
  669. begin
  670. s := Items[i];
  671. s[pos(':', Items[i])] := '=';
  672. Items[i] := s;
  673. end;
  674. end;
  675. end;
  676. function DOSStringToUnixString(dos: string): string;
  677. var
  678. s, d : PChar;
  679. l : integer;
  680. begin
  681. SetLength(Result, Length(dos)+1);
  682. s := PChar(dos);
  683. d := PChar(Result);
  684. l := 1;
  685. while (s^ <> #0) do
  686. begin
  687. // Ignore LF
  688. if (s^ <> #10) then
  689. begin
  690. d^ := s^;
  691. inc(l);
  692. inc(d);
  693. end;
  694. inc(s);
  695. end;
  696. SetLength(Result, l);
  697. end;
  698. function TVCardClipboardFormat.WriteData(Value: pointer; Size: integer): boolean;
  699. var
  700. s : string;
  701. begin
  702. Result := (Items.Count > 0);
  703. if (Result) then
  704. begin
  705. s := DOSStringToUnixString('begin:vcard'+#13+Items.Text+#13+'end:vcard');
  706. StrLCopy(Value, PChar(s), Size);
  707. end;
  708. end;
  709. ////////////////////////////////////////////////////////////////////////////////
  710. //
  711. // THTMLClipboardFormat
  712. //
  713. ////////////////////////////////////////////////////////////////////////////////
  714. var
  715. CF_HTML: TClipFormat = 0;
  716. function THTMLClipboardFormat.GetClipboardFormat: TClipFormat;
  717. begin
  718. if (CF_HTML = 0) then
  719. CF_HTML := RegisterClipboardFormat('HTML Format');
  720. Result := CF_HTML;
  721. end;
  722. function THTMLClipboardFormat.HasData: boolean;
  723. begin
  724. Result := inherited HasData and IsHTML(HTML.Text);
  725. end;
  726. function THTMLClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  727. begin
  728. Result := True;
  729. if (Source is TTextDataFormat) then
  730. HTML.Text := MakeHTML(TTextDataFormat(Source).Text)
  731. else
  732. Result := inherited Assign(Source);
  733. end;
  734. function THTMLClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  735. begin
  736. Result := True;
  737. if (Dest is TTextDataFormat) then
  738. TTextDataFormat(Dest).Text := HTML.Text
  739. else
  740. Result := inherited AssignTo(Dest);
  741. end;
  742. ////////////////////////////////////////////////////////////////////////////////
  743. //
  744. // TRFC822ClipboardFormat
  745. //
  746. ////////////////////////////////////////////////////////////////////////////////
  747. var
  748. CF_RFC822: TClipFormat = 0;
  749. function TRFC822ClipboardFormat.GetClipboardFormat: TClipFormat;
  750. begin
  751. if (CF_RFC822 = 0) then
  752. CF_RFC822 := RegisterClipboardFormat('Internet Message (rfc822/rfc1522)'); // *** DO NOT LOCALIZE ***
  753. Result := CF_RFC822;
  754. end;
  755. function TRFC822ClipboardFormat.Assign(Source: TCustomDataFormat): boolean;
  756. begin
  757. Result := True;
  758. if (Source is TTextDataFormat) then
  759. Text.Text := TTextDataFormat(Source).Text
  760. else
  761. Result := inherited Assign(Source);
  762. end;
  763. function TRFC822ClipboardFormat.AssignTo(Dest: TCustomDataFormat): boolean;
  764. begin
  765. Result := True;
  766. if (Dest is TTextDataFormat) then
  767. TTextDataFormat(Dest).Text := Text.Text
  768. else
  769. Result := inherited AssignTo(Dest);
  770. end;
  771. ////////////////////////////////////////////////////////////////////////////////
  772. //
  773. // TURLDataFormat
  774. //
  775. ////////////////////////////////////////////////////////////////////////////////
  776. function TURLDataFormat.Assign(Source: TClipboardFormat): boolean;
  777. var
  778. s : string;
  779. begin
  780. Result := False;
  781. (*
  782. ** TURLClipboardFormat
  783. *)
  784. if (Source is TURLClipboardFormat) then
  785. begin
  786. if (FURL = '') then
  787. FURL := TURLClipboardFormat(Source).URL;
  788. Result := True;
  789. end else
  790. (*
  791. ** TTextClipboardFormat
  792. *)
  793. if (Source is TTextClipboardFormat) then
  794. begin
  795. if (FURL = '') then
  796. begin
  797. s := TTextClipboardFormat(Source).Text;
  798. // Convert from text if the string looks like an URL
  799. if (pos('://', s) > 1) then
  800. begin
  801. FURL := s;
  802. Result := True;
  803. end;
  804. end;
  805. end else
  806. (*
  807. ** TFileClipboardFormat
  808. *)
  809. if (Source is TFileClipboardFormat) then
  810. begin
  811. if (FURL = '') then
  812. begin
  813. s := TFileClipboardFormat(Source).Files[0];
  814. // Convert from Internet Shortcut file format.
  815. if (CompareText(ExtractFileExt(s), InternetShortcutExt) = 0) and
  816. (GetURLFromFile(s, FURL)) then
  817. begin
  818. if (FTitle = '') then
  819. FTitle := ChangeFileExt(ExtractFileName(s), '');
  820. Result := True;
  821. end;
  822. end;
  823. end else
  824. (*
  825. ** TFileContentsClipboardFormat
  826. *)
  827. if (Source is TFileContentsClipboardFormat) then
  828. begin
  829. if (FURL = '') then
  830. begin
  831. s := TFileContentsClipboardFormat(Source).Data;
  832. Result := GetURLFromString(s, FURL);
  833. end;
  834. end else
  835. (*
  836. ** TFileGroupDescritorClipboardFormat
  837. *)
  838. if (Source is TFileGroupDescritorClipboardFormat) then
  839. begin
  840. if (FTitle = '') then
  841. begin
  842. if (TFileGroupDescritorClipboardFormat(Source).FileGroupDescriptor^.cItems > 0) then
  843. begin
  844. // Extract the title of an Internet Shortcut
  845. s := TFileGroupDescritorClipboardFormat(Source).FileGroupDescriptor^.fgd[0].cFileName;
  846. if (CompareText(ExtractFileExt(s), InternetShortcutExt) = 0) then
  847. begin
  848. FTitle := ChangeFileExt(s, '');
  849. Result := True;
  850. end;
  851. end;
  852. end;
  853. end else
  854. (*
  855. ** TNetscapeBookmarkClipboardFormat
  856. *)
  857. if (Source is TNetscapeBookmarkClipboardFormat) then
  858. begin
  859. if (FURL = '') then
  860. FURL := TNetscapeBookmarkClipboardFormat(Source).URL;
  861. if (FTitle = '') then
  862. FTitle := TNetscapeBookmarkClipboardFormat(Source).Title;
  863. Result := True;
  864. end else
  865. (*
  866. ** TNetscapeImageClipboardFormat
  867. *)
  868. if (Source is TNetscapeImageClipboardFormat) then
  869. begin
  870. if (FURL = '') then
  871. FURL := TNetscapeImageClipboardFormat(Source).URL;
  872. if (FTitle = '') then
  873. FTitle := TNetscapeImageClipboardFormat(Source).Title;
  874. Result := True;
  875. end else
  876. Result := inherited Assign(Source);
  877. end;
  878. function TURLDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  879. var
  880. FGD : TFileGroupDescriptor;
  881. s : string;
  882. begin
  883. Result := True;
  884. (*
  885. ** TURLClipboardFormat
  886. *)
  887. if (Dest is TURLClipboardFormat) then
  888. begin
  889. TURLClipboardFormat(Dest).URL := FURL;
  890. end else
  891. (*
  892. ** TTextClipboardFormat
  893. *)
  894. if (Dest is TTextClipboardFormat) then
  895. begin
  896. TTextClipboardFormat(Dest).Text := FURL;
  897. end else
  898. (*
  899. ** TFileContentsClipboardFormat
  900. *)
  901. if (Dest is TFileContentsClipboardFormat) then
  902. begin
  903. TFileContentsClipboardFormat(Dest).Data := InternetShortcut + #13#10 +
  904. 'URL='+FURL + #13#10;
  905. end else
  906. (*
  907. ** TFileGroupDescritorClipboardFormat
  908. *)
  909. if (Dest is TFileGroupDescritorClipboardFormat) then
  910. begin
  911. FillChar(FGD, SizeOf(FGD), 0);
  912. FGD.cItems := 1;
  913. if (FTitle = '') then
  914. s := FURL
  915. else
  916. s := FTitle;
  917. StrLCopy(@FGD.fgd[0].cFileName[0], PChar(ConvertURLToFilename(s)),
  918. SizeOf(FGD.fgd[0].cFileName));
  919. FGD.fgd[0].dwFlags := FD_LINKUI;
  920. TFileGroupDescritorClipboardFormat(Dest).CopyFrom(@FGD);
  921. end else
  922. (*
  923. ** TNetscapeBookmarkClipboardFormat
  924. *)
  925. if (Dest is TNetscapeBookmarkClipboardFormat) then
  926. begin
  927. TNetscapeBookmarkClipboardFormat(Dest).URL := FURL;
  928. TNetscapeBookmarkClipboardFormat(Dest).Title := FTitle;
  929. end else
  930. (*
  931. ** TNetscapeImageClipboardFormat
  932. *)
  933. if (Dest is TNetscapeImageClipboardFormat) then
  934. begin
  935. TNetscapeImageClipboardFormat(Dest).URL := FURL;
  936. TNetscapeImageClipboardFormat(Dest).Title := FTitle;
  937. end else
  938. Result := inherited AssignTo(Dest);
  939. end;
  940. procedure TURLDataFormat.Clear;
  941. begin
  942. Changing;
  943. FURL := '';
  944. FTitle := '';
  945. end;
  946. procedure TURLDataFormat.SetTitle(const Value: string);
  947. begin
  948. Changing;
  949. FTitle := Value;
  950. end;
  951. procedure TURLDataFormat.SetURL(const Value: string);
  952. begin
  953. Changing;
  954. FURL := Value;
  955. end;
  956. function TURLDataFormat.HasData: boolean;
  957. begin
  958. Result := (FURL <> '') or (FTitle <> '');
  959. end;
  960. function TURLDataFormat.NeedsData: boolean;
  961. begin
  962. Result := (FURL = '') or (FTitle = '');
  963. end;
  964. ////////////////////////////////////////////////////////////////////////////////
  965. //
  966. // THTMLDataFormat
  967. //
  968. ////////////////////////////////////////////////////////////////////////////////
  969. function THTMLDataFormat.Assign(Source: TClipboardFormat): boolean;
  970. begin
  971. Result := True;
  972. if (Source is THTMLClipboardFormat) then
  973. FHTML.Assign(THTMLClipboardFormat(Source).HTML)
  974. else
  975. Result := inherited Assign(Source);
  976. end;
  977. function THTMLDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  978. begin
  979. Result := True;
  980. if (Dest is THTMLClipboardFormat) then
  981. THTMLClipboardFormat(Dest).HTML.Assign(FHTML)
  982. else
  983. Result := inherited AssignTo(Dest);
  984. end;
  985. procedure THTMLDataFormat.Clear;
  986. begin
  987. Changing;
  988. FHTML.Clear;
  989. end;
  990. constructor THTMLDataFormat.Create(AOwner: TDragDropComponent);
  991. begin
  992. inherited Create(AOwner);
  993. FHTML := TStringList.Create;
  994. end;
  995. destructor THTMLDataFormat.Destroy;
  996. begin
  997. FHTML.Free;
  998. inherited Destroy;
  999. end;
  1000. function THTMLDataFormat.HasData: boolean;
  1001. begin
  1002. Result := (FHTML.Count > 0);
  1003. end;
  1004. function THTMLDataFormat.NeedsData: boolean;
  1005. begin
  1006. Result := (FHTML.Count = 0);
  1007. end;
  1008. procedure THTMLDataFormat.SetHTML(const Value: TStrings);
  1009. begin
  1010. FHTML.Assign(Value);
  1011. end;
  1012. ////////////////////////////////////////////////////////////////////////////////
  1013. //
  1014. // TOutlookMailDataFormat
  1015. //
  1016. ////////////////////////////////////////////////////////////////////////////////
  1017. constructor TOutlookMailDataFormat.Create(AOwner: TDragDropComponent);
  1018. begin
  1019. inherited Create(AOwner);
  1020. FStorages := TStorageInterfaceList.Create;
  1021. FStorages.OnChanging := DoOnChanging;
  1022. end;
  1023. destructor TOutlookMailDataFormat.Destroy;
  1024. begin
  1025. Clear;
  1026. FStorages.Free;
  1027. inherited Destroy;
  1028. end;
  1029. procedure TOutlookMailDataFormat.Clear;
  1030. begin
  1031. Changing;
  1032. FStorages.Clear;
  1033. end;
  1034. function TOutlookMailDataFormat.Assign(Source: TClipboardFormat): boolean;
  1035. begin
  1036. Result := True;
  1037. if (Source is TFileContentsStorageClipboardFormat) then
  1038. FStorages.Assign(TFileContentsStorageClipboardFormat(Source).Storages)
  1039. else
  1040. Result := inherited Assign(Source);
  1041. end;
  1042. function TOutlookMailDataFormat.AssignTo(Dest: TClipboardFormat): boolean;
  1043. begin
  1044. Result := True;
  1045. if (Dest is TFileContentsStorageClipboardFormat) then
  1046. TFileContentsStorageClipboardFormat(Dest).Storages.Assign(FStorages)
  1047. else
  1048. Result := inherited AssignTo(Dest);
  1049. end;
  1050. function TOutlookMailDataFormat.HasData: boolean;
  1051. begin
  1052. Result := (FStorages.Count > 0);
  1053. end;
  1054. function TOutlookMailDataFormat.NeedsData: boolean;
  1055. begin
  1056. Result := (FStorages.Count = 0);
  1057. end;
  1058. ////////////////////////////////////////////////////////////////////////////////
  1059. //
  1060. // TDropURLTarget
  1061. //
  1062. ////////////////////////////////////////////////////////////////////////////////
  1063. constructor TDropURLTarget.Create(AOwner: TComponent);
  1064. begin
  1065. inherited Create(AOwner);
  1066. DragTypes := [dtCopy, dtLink];
  1067. GetDataOnEnter := True;
  1068. FURLFormat := TURLDataFormat.Create(Self);
  1069. end;
  1070. destructor TDropURLTarget.Destroy;
  1071. begin
  1072. FURLFormat.Free;
  1073. inherited Destroy;
  1074. end;
  1075. function TDropURLTarget.GetTitle: string;
  1076. begin
  1077. Result := FURLFormat.Title;
  1078. end;
  1079. function TDropURLTarget.GetURL: string;
  1080. begin
  1081. Result := FURLFormat.URL;
  1082. end;
  1083. function TDropURLTarget.GetPreferredDropEffect: LongInt;
  1084. begin
  1085. Result := GetPreferredDropEffect;
  1086. if (Result = DROPEFFECT_NONE) then
  1087. Result := DROPEFFECT_LINK;
  1088. end;
  1089. ////////////////////////////////////////////////////////////////////////////////
  1090. //
  1091. // TDropURLSource
  1092. //
  1093. ////////////////////////////////////////////////////////////////////////////////
  1094. constructor TDropURLSource.Create(AOwner: TComponent);
  1095. begin
  1096. inherited Create(AOwner);
  1097. DragTypes := [dtCopy, dtLink];
  1098. PreferredDropEffect := DROPEFFECT_LINK;
  1099. FURLFormat := TURLDataFormat.Create(Self);
  1100. end;
  1101. destructor TDropURLSource.Destroy;
  1102. begin
  1103. FURLFormat.Free;
  1104. inherited Destroy;
  1105. end;
  1106. function TDropURLSource.GetTitle: string;
  1107. begin
  1108. Result := FURLFormat.Title;
  1109. end;
  1110. procedure TDropURLSource.SetTitle(const Value: string);
  1111. begin
  1112. FURLFormat.Title := Value;
  1113. end;
  1114. function TDropURLSource.GetURL: string;
  1115. begin
  1116. Result := FURLFormat.URL;
  1117. end;
  1118. procedure TDropURLSource.SetURL(const Value: string);
  1119. begin
  1120. FURLFormat.URL := Value;
  1121. end;
  1122. ////////////////////////////////////////////////////////////////////////////////
  1123. //
  1124. // Initialization/Finalization
  1125. //
  1126. ////////////////////////////////////////////////////////////////////////////////
  1127. { TDropHtmlTarget }
  1128. constructor TDropHtmlTarget.Create(AOwner: TComponent);
  1129. begin
  1130. inherited Create(AOwner);
  1131. DragTypes := [dtCopy, dtLink];
  1132. GetDataOnEnter := False;
  1133. FHTMLFormat := THTMLDataFormat.Create(Self);
  1134. end;
  1135. destructor TDropHtmlTarget.Destroy;
  1136. begin
  1137. FHTMLFormat.Free;
  1138. inherited Destroy;
  1139. end;
  1140. function TDropHtmlTarget.GetHtml: string;
  1141. begin
  1142. Result := FHTMLFormat.HTML.Text;
  1143. end;
  1144. function TDropHtmlTarget.GetPreferredDropEffect: LongInt;
  1145. begin
  1146. Result := GetPreferredDropEffect;
  1147. if (Result = DROPEFFECT_NONE) then
  1148. Result := DROPEFFECT_LINK;
  1149. end;
  1150. initialization
  1151. // Data format registration
  1152. TURLDataFormat.RegisterDataFormat;
  1153. THTMLDataFormat.RegisterDataFormat;
  1154. // Clipboard format registration
  1155. TURLDataFormat.RegisterCompatibleFormat(TNetscapeBookmarkClipboardFormat, 0, csSourceTarget, [ddRead]);
  1156. TURLDataFormat.RegisterCompatibleFormat(TNetscapeImageClipboardFormat, 1, csSourceTarget, [ddRead]);
  1157. TURLDataFormat.RegisterCompatibleFormat(TFileContentsClipboardFormat, 2, csSourceTarget, [ddRead]);
  1158. TURLDataFormat.RegisterCompatibleFormat(TFileGroupDescritorClipboardFormat, 2, csSourceTarget, [ddRead]);
  1159. TURLDataFormat.RegisterCompatibleFormat(TURLClipboardFormat, 2, csSourceTarget, [ddRead]);
  1160. TURLDataFormat.RegisterCompatibleFormat(TTextClipboardFormat, 3, csSourceTarget, [ddRead]);
  1161. TURLDataFormat.RegisterCompatibleFormat(TFileClipboardFormat, 4, [csTarget], [ddRead]);
  1162. THTMLDataFormat.RegisterCompatibleFormat(THTMLClipboardFormat, 0, csSourceTarget, [ddRead]);
  1163. TTextDataFormat.RegisterCompatibleFormat(TRFC822ClipboardFormat, 1, csSourceTarget, [ddRead]);
  1164. TTextDataFormat.RegisterCompatibleFormat(THTMLClipboardFormat, 2, csSourceTarget, [ddRead]);
  1165. finalization
  1166. // Clipboard format unregistration
  1167. TNetscapeBookmarkClipboardFormat.UnregisterClipboardFormat;
  1168. TNetscapeImageClipboardFormat.UnregisterClipboardFormat;
  1169. TURLClipboardFormat.UnregisterClipboardFormat;
  1170. TVCardClipboardFormat.UnregisterClipboardFormat;
  1171. THTMLClipboardFormat.UnregisterClipboardFormat;
  1172. TRFC822ClipboardFormat.UnregisterClipboardFormat;
  1173. // Target format unregistration
  1174. TURLDataFormat.UnregisterDataFormat;
  1175. end.