PageRenderTime 87ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/ProSnooperFx_src/ProSnooper200b202src/mainform.pas

http://github.com/lookias/ProSnooper
Pascal | 1285 lines | 1158 code | 113 blank | 14 comment | 61 complexity | caade37b10e070f20b43188bc52ce972 MD5 | raw file
  1. (*
  2. This program is licensed under the rndware License, which can be found in LICENSE.TXT
  3. Copyright (c) Simon Hughes 2007-2008
  4. *)
  5. unit mainform;
  6. interface
  7. uses
  8. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  9. Dialogs, ExtCtrls, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,
  10. IdTCPConnection, IdTCPClient, Menus, StrUtils, vortex,
  11. CoolTrayIcon, Registry, IdHTTP, ShellAPI, DockPanel, nickdock, gamedock,
  12. ImgList, IdCmdTCPClient, IdContext, IdAntiFreezeBase,
  13. IdAntiFreeze, RichEditURL, DBCtrls, richedit;
  14. type
  15. TWords = class
  16. private
  17. FText: string;
  18. FWords: TStringList;
  19. procedure Parse;
  20. function GetWord(Index: Integer): string;
  21. procedure SetText(const Value: string);
  22. function GetCount: integer;
  23. public
  24. constructor Create;
  25. destructor Destroy; override;
  26. function ConcatToEnd(From: integer): string;
  27. property Text: string
  28. read FText
  29. write SetText;
  30. property Words[Index: Integer]: string
  31. read GetWord;
  32. default;
  33. property Count: integer
  34. read GetCount;
  35. end;
  36. TfrmMain = class(TForm)
  37. MainMenu1: TMainMenu;
  38. Files1: TMenuItem;
  39. Exit1: TMenuItem;
  40. About1: TMenuItem;
  41. Panel1: TPanel;
  42. rechat: TRichEditURL;
  43. Memo1: TMemo;
  44. StatusBar1: TStatusBar;
  45. Connection1: TMenuItem;
  46. SaveDialog1: TSaveDialog;
  47. Saveas1: TMenuItem;
  48. N1: TMenuItem;
  49. irc: TVortex;
  50. CoolTrayIcon1: TCoolTrayIcon;
  51. Autologin1: TMenuItem;
  52. tmrGames: TTimer;
  53. pmChatEditBox: TPopupMenu;
  54. Copy1: TMenuItem;
  55. N4: TMenuItem;
  56. SelectAll1: TMenuItem;
  57. http: TIdHTTP;
  58. DockPanel1: TDockPanel;
  59. Settings1: TMenuItem;
  60. DockPanel2: TDockPanel;
  61. DockPanel3: TDockPanel;
  62. DockPanel4: TDockPanel;
  63. Games1: TMenuItem;
  64. JoindirectIP1: TMenuItem;
  65. N2: TMenuItem;
  66. N5: TMenuItem;
  67. lbIgnore: TListBox;
  68. N6: TMenuItem;
  69. HostWormnet1: TMenuItem;
  70. pnAway: TPanel;
  71. Label1: TLabel;
  72. Label2: TLabel;
  73. Channellist1: TMenuItem;
  74. IdAntiFreeze1: TIdAntiFreeze;
  75. Label3: TLabel;
  76. lblHiLites: TLabel;
  77. Label5: TLabel;
  78. lblMsgs: TLabel;
  79. tmrWhoCompat: TTimer;
  80. lbIgnoreAway: TListBox;
  81. Icons: TImageList;
  82. FD: TFindDialog;
  83. N3: TMenuItem;
  84. Find1: TMenuItem;
  85. Clear1: TMenuItem;
  86. Image1: TImage;
  87. procedure Memo1KeyDown(Sender: TObject; var Key: Word;
  88. Shift: TShiftState);
  89. procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  90. procedure rechatMouseMove(Sender: TObject; Shift: TShiftState; X,
  91. Y: Integer);
  92. procedure lbnicksMouseMove(Sender: TObject; Shift: TShiftState; X,
  93. Y: Integer);
  94. procedure Saveas1Click(Sender: TObject);
  95. procedure Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
  96. Y: Integer);
  97. procedure ircMOTD(Line: String; EndOfMotd: Boolean);
  98. procedure ircNickInUse(Nickname: String);
  99. procedure ircChannelMessage(Channelname, Content, Nickname, Ident,
  100. Mask: String);
  101. procedure ircAfterPrivateMessage(Nickname, Ident, Mask,
  102. Content: String);
  103. procedure ircAfterUserJoin(Nickname, Hostname, Channel: String);
  104. procedure ircAfterUserPart(Nickname, Hostname, Channelname,
  105. Reason: String);
  106. procedure ircAfterUserQuit(Nickname, Reason: String);
  107. procedure ircNames(Commanicks, Channel: String; endofnames: Boolean);
  108. procedure ircAfterUserKick(KickedUser, Kicker, Channel,
  109. Reason: String);
  110. procedure ircConnect;
  111. procedure ircDisconnect;
  112. procedure ircAfterAction(NickName, Content, Destination: String);
  113. procedure About1Click(Sender: TObject);
  114. procedure CoolTrayIcon1Click(Sender: TObject);
  115. procedure CoolTrayIcon1MinimizeToTray(Sender: TObject);
  116. procedure lbGamesMouseMove(Sender: TObject; Shift: TShiftState; X,
  117. Y: Integer);
  118. procedure FormShow(Sender: TObject);
  119. procedure Autologin1Click(Sender: TObject);
  120. procedure tmrGamesTimer(Sender: TObject);
  121. procedure Copy1Click(Sender: TObject);
  122. procedure SelectAll1Click(Sender: TObject);
  123. procedure FormCreate(Sender: TObject);
  124. procedure Exit1Click(Sender: TObject);
  125. procedure Settings1Click(Sender: TObject);
  126. procedure AddRichLine(RichEdit: TRichEdit; const StrToAdd: String);
  127. procedure JoindirectIP1Click(Sender: TObject);
  128. procedure ircQuoteServer(Command: String);
  129. function FindListViewItem(lv: TListView; const S: string; column: Integer): TListItem;
  130. procedure ircWho(Channel, Nickname, Username, Hostname, Name,
  131. Servername, status, other: String; EndOfWho: Boolean);
  132. procedure ircAfterJoined(Channelname: String);
  133. procedure HostWormnet1Click(Sender: TObject);
  134. procedure GoAway(Reason: String);
  135. procedure FormDestroy(Sender: TObject);
  136. procedure ircServerError(ErrorString: String);
  137. procedure Label2Click(Sender: TObject);
  138. procedure Channellist1Click(Sender: TObject);
  139. procedure Label3Click(Sender: TObject);
  140. procedure tmrWhoCompatTimer(Sender: TObject);
  141. procedure ircAfterUserNickChange(Oldnick, Newnick: String);
  142. procedure rechatURLClick(Sender: TObject; const URL: String);
  143. procedure Find1Click(Sender: TObject);
  144. procedure FDFind(Sender: TObject);
  145. function FindText(const SearchStr: string;
  146. StartPos, FindLength : LongInt; Options: TSearchTypes;
  147. SearchDown: Boolean = TRUE): Integer;
  148. procedure Clear1Click(Sender: TObject);
  149. procedure ircNoSuchNickChannel(Value: String);
  150. procedure ircAfterInvited(NickName, Channel: String);
  151. procedure ircMode(Nickname, Destination, Mode: String);
  152. procedure SetFlagRank(Flag, Rank: Integer; Nickname: String);
  153. procedure ircAfterTopic(ChannelName, Nickname, Topic: String);
  154. private
  155. procedure AppException(Sender: TObject; E: Exception);
  156. public
  157. IsAway: Boolean;
  158. function MakeTimeStamp: String;
  159. function MakeTimeStampNoTags: String;
  160. end;
  161. var
  162. frmMain: TfrmMain;
  163. PreviousFoundPos: integer;
  164. nickfrm: TfrmdkNickList;
  165. gmfrm: TfrmdkGmList;
  166. AwayReason: String;
  167. implementation
  168. uses loginform, aboutform, preferform, joinform, hostform,
  169. chanlistform, messagesform;
  170. {$R *.dfm}
  171. procedure TfrmMain.AppException(Sender: TObject; E: Exception);
  172. begin
  173. AddRichLine(rechat,MakeTimeStamp+'ProSnooperFx error: '+e.Message+' ['+Sender.ClassName+']');
  174. end;
  175. constructor TWords.Create;
  176. begin
  177. inherited;
  178. FWords := TStringList.Create;
  179. end;
  180. destructor TWords.Destroy;
  181. begin
  182. FWords.Free;
  183. inherited;
  184. end;
  185. function TWords.GetCount: integer;
  186. begin
  187. Result := FWords.Count;
  188. end;
  189. function TWords.GetWord(Index: Integer): string;
  190. begin
  191. if index >= Count then
  192. Result := ''
  193. else
  194. Result := FWords[index];
  195. end;
  196. procedure TWords.Parse;
  197. var
  198. i: integer;
  199. w: string;
  200. begin
  201. FWords.Clear;
  202. w := '';
  203. for i := 1 to Length(FText) do
  204. begin
  205. case FText[i] of
  206. #9, #10, #13, #32: // whitespace
  207. if w <> '' then
  208. begin
  209. FWords.Add(w);
  210. w := '';
  211. end;
  212. else
  213. w := w + FText[i]
  214. end;
  215. end;
  216. if w <> '' then
  217. FWords.Add(w);
  218. end;
  219. procedure TWords.SetText(const Value: string);
  220. begin
  221. if Value <> FText then
  222. begin
  223. FText := Value;
  224. Parse;
  225. end;
  226. end;
  227. function TWords.ConcatToEnd(From: integer): string;
  228. var
  229. i: integer;
  230. begin
  231. result := '';
  232. for i := From to Count-1 do
  233. begin
  234. if i <> From then
  235. Result := Result + ' ';
  236. Result := Result + Words[i];
  237. end;
  238. end;
  239. procedure TfrmMain.AddRichLine(RichEdit: TRichEdit; const StrToAdd: String);
  240. var
  241. StrLeft: String;
  242. TempStyle: TFontStyles;
  243. TempStr: String;
  244. changed: boolean;
  245. HadFocus: Boolean;
  246. WasHideSel: Boolean;
  247. SelSt, SelL: Integer;
  248. function FromLeftUntilStr(var OriginalStr: String; const UntilStr: String; const ToEndIfNotFound, Trim: Boolean): String;
  249. var
  250. TempPos: Integer;
  251. begin
  252. TempPos := Pos(UntilStr, OriginalStr);
  253. If TempPos > 0 Then
  254. Begin
  255. Result := Copy(OriginalStr, 1, TempPos - 1);
  256. If Trim Then
  257. Delete(OriginalStr, 1, TempPos - 1);
  258. End
  259. Else
  260. Begin
  261. If ToEndIfNotFound Then
  262. Begin
  263. Result := OriginalStr;
  264. If Trim Then
  265. OriginalStr := '';
  266. End
  267. Else
  268. Result := '';
  269. End;
  270. end;
  271. function FromLeftUntilStrX(var OriginalStr: String; const UntilStr: String; const ToEndIfNotFound, Trim: Boolean): String;
  272. var
  273. xStr : String;
  274. begin
  275. xStr := Copy(OriginalStr,2,Length(OriginalStr));
  276. result := '<' + FromLeftUntilStr(xStr,UntilStr,ToEndIfNotFound,Trim);
  277. OriginalStr := xStr;
  278. end;
  279. function StrStartsWith(var OriginalStr: String; const StartsWith: String; const IgnoreCase, Trim: Boolean): Boolean;
  280. var
  281. PartOfOriginalStr: String;
  282. NewStartsWith: String;
  283. begin
  284. PartOfOriginalStr := Copy(OriginalStr, 1, Length(StartsWith));
  285. NewStartsWith := StartsWith;
  286. If IgnoreCase Then Begin
  287. PartOfOriginalStr := LowerCase(PartOfOriginalStr);
  288. NewStartsWith := LowerCase(NewStartsWith);
  289. End;
  290. Result := PartOfOriginalStr = NewStartsWith;
  291. If (Result = True) And (Trim = True) Then
  292. Delete(OriginalStr, 1, Length(NewStartsWith));
  293. end;
  294. procedure AddToStyle(var Style: TFontStyles; AStyle: TFontStyle);
  295. begin
  296. If Not (AStyle In Style) Then
  297. Style := Style + [AStyle];
  298. end;
  299. procedure RemoveFromStyle(var Style: TFontStyles; AStyle: TFontStyle);
  300. begin
  301. If AStyle In Style Then
  302. Style := Style - [AStyle];
  303. end;
  304. begin
  305. // ProSnooperFx hack: don't move the scrollbar
  306. if frmSettings.cbDisableScroll.Checked then begin
  307. HadFocus := GetFocus = RichEdit.Handle;
  308. if HadFocus then Windows.SetFocus(0);
  309. WasHideSel := RichEdit.HideSelection;
  310. RichEdit.HideSelection := true;
  311. SelSt := RichEdit.SelStart;
  312. SelL := RichEdit.SelLength;
  313. end;
  314. TempStyle := RichEdit.Font.Style;
  315. StrLeft := StrToAdd;
  316. RichEdit.SelStart := Length(RichEdit.Text);
  317. if Pos('\',StrLeft) <> 0 then begin
  318. StrLeft := StringReplace(StrLeft,'\r','<pcol=clRed>',[rfReplaceAll, rfIgnoreCase]);
  319. StrLeft := StringReplace(StrLeft,'\b','<pcol=clAqua>',[rfReplaceAll, rfIgnoreCase]);
  320. StrLeft := StringReplace(StrLeft,'\g','<pcol=clLime>',[rfReplaceAll, rfIgnoreCase]);
  321. StrLeft := StringReplace(StrLeft,'\k','<pcol=clGray>',[rfReplaceAll, rfIgnoreCase]);
  322. StrLeft := StringReplace(StrLeft,'\n','<pcol=clMedGray>',[rfReplaceAll, rfIgnoreCase]);
  323. StrLeft := StringReplace(StrLeft,'\p','<pcol=$00FCB6F4>',[rfReplaceAll, rfIgnoreCase]);
  324. StrLeft := StringReplace(StrLeft,'\w','<pcol=clWhite>',[rfReplaceAll, rfIgnoreCase]);
  325. StrLeft := StringReplace(StrLeft,'\y','<pcol=clYellow>',[rfReplaceAll, rfIgnoreCase]);
  326. StrLeft := StringReplace(StrLeft,'\m','<pcol=clMoneyGreen>',[rfReplaceAll, rfIgnoreCase]);
  327. end;
  328. While StrLeft > '' Do Begin
  329. If StrStartsWith(StrLeft, '<', True, False) then
  330. Begin
  331. changed := false;
  332. // Bold Style
  333. If StrStartsWith(StrLeft, '<b>', True, True) Then
  334. begin AddToStyle(TempStyle, fsBold); changed := true; end;
  335. If StrStartsWith(StrLeft, '</b>', True, True) Then
  336. begin RemoveFromStyle(TempStyle, fsBold); changed := true; end;
  337. // Italic Style
  338. If StrStartsWith(StrLeft, '<i>', True, True) Then
  339. begin AddToStyle(TempStyle, fsItalic); changed := true; end;
  340. If StrStartsWith(StrLeft, '</i>', True, True) Then
  341. begin RemoveFromStyle(TempStyle, fsItalic); changed := true; end;
  342. // Underline Style
  343. If StrStartsWith(StrLeft, '<u>', True, True) Then
  344. begin AddToStyle(TempStyle, fsUnderline); changed := true; end;
  345. If StrStartsWith(StrLeft, '</u>', True, True) Then
  346. begin RemoveFromStyle(TempStyle, fsUnderline); changed := true; end;
  347. // Strikeout Style
  348. If StrStartsWith(StrLeft, '<s>', True, True) Then
  349. begin AddToStyle(TempStyle, fsStrikeOut); changed := true; end;
  350. If StrStartsWith(StrLeft, '</s>', True, True) Then
  351. begin RemoveFromStyle(TempStyle, fsStrikeOut); changed := true; end;
  352. // Color
  353. If StrStartsWith(StrLeft, '</color>', True, True) Then
  354. begin RichEdit.SelAttributes.Color := RichEdit.Font.Color; changed := true; end;
  355. If StrStartsWith(StrLeft, '<color=', True, True) Then Begin
  356. TempStr := FromLeftUntilStr(StrLeft, '>', False, True); changed := true;
  357. Try
  358. RichEdit.SelAttributes.Color := StringToColor('cl'+TempStr);
  359. Except
  360. RichEdit.SelAttributes.Color := RichEdit.Font.Color;
  361. End;
  362. Delete(StrLeft, 1, 1);
  363. End;
  364. If StrStartsWith(StrLeft, '</pcol>', True, True) Then
  365. begin RichEdit.SelAttributes.Color := RichEdit.Font.Color; changed := true; end;
  366. If StrStartsWith(StrLeft, '<pcol=', True, True) Then Begin
  367. TempStr := FromLeftUntilStr(StrLeft, '>', False, True); changed := true;
  368. Try
  369. RichEdit.SelAttributes.Color := StringToColor(TempStr);
  370. Except
  371. RichEdit.SelAttributes.Color := RichEdit.Font.Color;
  372. End;
  373. Delete(StrLeft, 1, 1);
  374. End;
  375. if not changed then
  376. begin
  377. RichEdit.SelAttributes.Style := TempStyle;
  378. RichEdit.Font.Color := frmSettings.colText2.Selected;
  379. RichEdit.SelAttributes.Size := StrToInt(frmSettings.edFntSize.Text);
  380. RichEdit.SelText := FromLeftUntilStrX(StrLeft, '<', True, True);
  381. end;
  382. End
  383. Else
  384. Begin
  385. RichEdit.SelAttributes.Style := TempStyle;
  386. RichEdit.Font.Color := frmSettings.colText2.Selected;
  387. RichEdit.SelAttributes.Size := StrToInt(frmSettings.edFntSize.Text);
  388. RichEdit.SelText := FromLeftUntilStr(StrLeft, '<', True, True);
  389. End;
  390. RichEdit.SelStart := Length(RichEdit.Text);
  391. End;
  392. RichEdit.SelText := #13#10;
  393. if frmSettings.cbDisableScroll.Checked then begin
  394. RichEdit.SelStart := SelSt;
  395. RichEdit.SelLength := SelL;
  396. if not WasHideSel then
  397. RichEdit.HideSelection := false;
  398. if HadFocus then
  399. Windows.SetFocus(RichEdit.Handle);
  400. end;
  401. end;
  402. function TfrmMain.MakeTimeStamp: String;
  403. begin
  404. if frmSettings.cbTimeStamps.Checked = True then
  405. Result := '<pcol='+ColorToString(frmSettings.colText2.Selected)+'>['+FormatDateTime(frmSettings.edTimeStamp.Text,now)+']</pcol> '
  406. else
  407. Result := '';
  408. end;
  409. function TfrmMain.MakeTimeStampNoTags: String;
  410. begin
  411. if frmSettings.cbTimeStamps.Checked = True then
  412. Result := '['+FormatDateTime(frmSettings.edTimeStamp.Text,now)+'] '
  413. else
  414. Result := '';
  415. end;
  416. procedure TfrmMain.Memo1KeyDown(Sender: TObject; var Key: Word;
  417. Shift: TShiftState);
  418. var
  419. W: TWords;
  420. S: String;
  421. begin
  422. if Key = VK_RETURN then begin
  423. W := TWords.Create;
  424. W.Text := Memo1.Text;
  425. if LowerCase(W[0]) = '/me' then begin
  426. irc.SendCTCP(frmLogin.cbchan.Text, 'ACTION '+W.ConcatToEnd(1)+#1);
  427. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colActions.Selected)+'><i>* <b>'+irc.IrcOptions.MyNick+' '+W.ConcatToEnd(1)+'</i></b></pcol>');
  428. W.Free;
  429. Memo1.Clear;
  430. Exit;
  431. end;
  432. if LowerCase(W[0]) = '/quote' then begin
  433. IRC.Quote(W.ConcatToEnd(1));
  434. AddRichLine(rechat,MakeTimeStamp+'Command to server: '+W.ConcatToEnd(1));
  435. W.Free;
  436. Memo1.Clear;
  437. Exit;
  438. end;
  439. if LowerCase(W[0]) = '/msg' then begin
  440. irc.Say(W[1], W.ConcatToEnd(2));
  441. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colPrivate.Selected)+'>-> <b>['+W[1]+'] '+W.ConcatToEnd(2)+'</pcol></b>');
  442. W.Free;
  443. Memo1.Clear;
  444. Exit;
  445. end;
  446. if LowerCase(W[0]) = '/away' then begin
  447. GoAway(w.ConcatToEnd(1));
  448. W.Free;
  449. Memo1.Clear;
  450. Exit;
  451. end;
  452. if LowerCase(W[0]) = '/sex' then begin
  453. try
  454. S := http.Get('http://djlol.dk/sex/');
  455. finally
  456. irc.Say(frmLogin.cbchan.Text,S);
  457. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colText1.Selected)+'><b>['+irc.IrcOptions.Mynick+'] '+S+'</b></pcol>');
  458. end;
  459. W.Free;
  460. Memo1.Clear;
  461. Exit;
  462. end;
  463. if LowerCase(W[0]) = '/buddymsg' then begin
  464. irc.Say(frmSettings.lbBuddies.Items.CommaText,W.ConcatToEnd(1));
  465. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colPrivate.Selected)+'>-> <b>[*All buddies*] '+W.ConcatToEnd(1)+'</b></pcol>');
  466. W.Free;
  467. Memo1.Clear;
  468. Exit;
  469. end;
  470. if Copy(W[0],1,1) = '/' then begin
  471. AddRichLine(rechat,MakeTimeStamp+'Unknown command.');
  472. W.Free;
  473. Memo1.Clear;
  474. Exit;
  475. end;
  476. irc.Say(frmLogin.cbchan.Text,Memo1.Text);
  477. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colText1.Selected)+'><b>['+irc.IrcOptions.Mynick+'] '+Memo1.Text+'</b></pcol>');
  478. W.Free;
  479. Memo1.Clear;
  480. end;
  481. end;
  482. procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  483. function GetAppVersion:string;
  484. var
  485. Size, Size2: DWord;
  486. Pt, Pt2: Pointer;
  487. begin
  488. Size := GetFileVersionInfoSize(PChar (ParamStr (0)), Size2);
  489. if Size > 0 then
  490. begin
  491. GetMem (Pt, Size);
  492. try
  493. GetFileVersionInfo (PChar (ParamStr (0)), 0, Size, Pt);
  494. VerQueryValue (Pt, '\', Pt2, Size2);
  495. with TVSFixedFileInfo (Pt2^) do
  496. begin
  497. Result:= IntToStr (HiWord (dwFileVersionMS)) + '.' +
  498. IntToStr (LoWord (dwFileVersionMS)) + '.' +
  499. IntToStr (HiWord (dwFileVersionLS)) + ' build ' +
  500. IntToStr (LoWord (dwFileVersionLS));
  501. end;
  502. finally
  503. FreeMem (Pt);
  504. end;
  505. end;
  506. end;
  507. var
  508. ans: Word;
  509. begin
  510. ans := MessageDlg('Do you really want to quit?', mtConfirmation,[mbYes, mbNo], 0);
  511. if ans = mrNo then
  512. CanClose := false
  513. else begin
  514. DockHandler.SaveDesktop('\Software\ProSnooperFx');
  515. if frmMain.WindowState <> wsMaximized then begin
  516. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','Pos1',rdInteger,Height);
  517. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','Pos2',rdInteger,Top);
  518. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','Pos3',rdInteger,Left);
  519. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','Pos4',rdInteger,Width);
  520. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','Buddies',rdString,frmSettings.lbBuddies.Items.CommaText);
  521. end;
  522. if frmMain.WindowState = wsMaximized then
  523. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','WindowState',rdString,'Maximized')
  524. else if frmMain.WindowState = wsMinimized then
  525. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','WindowState',rdString,'Minimized')
  526. else
  527. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','WindowState',rdString,'Normal');
  528. irc.Quit('ProSnooperFx');
  529. Application.Terminate;
  530. end;
  531. end;
  532. procedure TfrmMain.GoAway(Reason: String);
  533. begin
  534. if IsAway = False then begin
  535. if Reason = '' then
  536. AwayReason := 'No reason specified'
  537. else
  538. AwayReason := Reason;
  539. AddRichLine(rechat,MakeTimeStamp+'You have been marked as being away: '+AwayReason);
  540. IsAway := True;
  541. pnAway.Show;
  542. tmrGames.Interval := 60000;
  543. if frmSettings.cbAwayAnnounce.Checked then begin
  544. irc.SendCTCP(frmLogin.cbchan.Text, 'ACTION is away ('+AwayReason+')'+#1);
  545. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colActions.Selected)+'><i>* '+irc.IrcOptions.MyNick+' is going away ('+AwayReason+')</i></pcol>');
  546. end;
  547. end else begin
  548. if Reason <> '' then begin //change away reason while away
  549. AddRichLine(rechat,MakeTimeStamp+'Away reason changed to: '+AwayReason);
  550. AwayReason := Reason;
  551. end else begin
  552. AddRichLine(rechat,MakeTimeStamp+'You are not marked as being away any longer.');
  553. IsAway := False;
  554. AwayReason := '';
  555. lblMsgs.Caption := '0';
  556. lblHiLites.Caption := '0';
  557. frmMessages.Memo1.Clear;
  558. lbIgnoreAway.Clear;
  559. pnAway.Hide;
  560. tmrGames.Interval := 10000;
  561. tmrGames.OnTimer(nil);
  562. if frmSettings.cbResumeAnnounce.Checked then begin
  563. irc.SendCTCP(frmLogin.cbchan.Text, 'ACTION is no longer marked as being away.'+#1);
  564. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colActions.Selected)+'><i>* '+irc.IrcOptions.MyNick+' is no longer marked as being away.</i></pcol>');
  565. end;
  566. end;
  567. end;
  568. end;
  569. procedure TfrmMain.rechatMouseMove(Sender: TObject; Shift: TShiftState; X,
  570. Y: Integer);
  571. begin
  572. StatusBar1.Panels[1].Text := 'Chat window: Messages are displayed here.';
  573. end;
  574. procedure TfrmMain.lbnicksMouseMove(Sender: TObject; Shift: TShiftState; X,
  575. Y: Integer);
  576. begin
  577. StatusBar1.Panels[1].Text := 'User list: Users on the current channel are listed here.';
  578. end;
  579. procedure TfrmMain.Saveas1Click(Sender: TObject);
  580. begin
  581. if SaveDialog1.Execute then
  582. rechat.Lines.SaveToFile(SaveDialog1.FileName);
  583. end;
  584. procedure TfrmMain.Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
  585. Y: Integer);
  586. begin
  587. StatusBar1.Panels[1].Text := 'Message field: Enter your message and press ''Return'' to send.';
  588. end;
  589. procedure TfrmMain.ircMOTD(Line: String; EndOfMotd: Boolean);
  590. begin
  591. if Endofmotd then begin
  592. irc.Join(frmLogin.cbchan.Text,'');
  593. tmrGames.OnTimer(nil);
  594. end;
  595. end;
  596. procedure TfrmMain.ircNickInUse(Nickname: String);
  597. begin
  598. irc.Nick(Nickname+'-PrSnp');
  599. end;
  600. procedure TfrmMain.ircChannelMessage(Channelname, Content, Nickname, Ident,
  601. Mask: String);
  602. begin
  603. if lbIgNore.Items.IndexOf(NickName) = -1 then begin
  604. if Pos(Lowercase(frmLogin.cbUser.Text),Lowercase(Content)) <> 0 then begin // if highlighted
  605. if IsAway = True then begin
  606. lblHiLites.Caption := IntToStr(StrToInt(lblHiLites.Caption) + 1);
  607. frmMessages.Memo1.Lines.Add(MakeTimeStampNoTags+Nickname+' highlighted you: '+Content);
  608. if lbIgnoreAway.Items.IndexOf(NickName) = -1 then
  609. if frmSettings.cbSendAwayHiLite.Checked then begin
  610. lbIgnoreAway.Items.Add(Nickname);
  611. irc.Say(NickName,'Away: '+AwayReason);
  612. end;
  613. end;
  614. if frmSettings.cbBlink.Checked then
  615. CoolTrayIcon1.CycleIcons := True;
  616. if frmSettings.edsndHiLite.Text <> '' then begin
  617. frmSettings.mp.Close;
  618. frmSettings.mp.FileName := frmSettings.edsndHiLite.Text;
  619. frmSettings.mp.Open;
  620. frmSettings.mp.Play;
  621. end;
  622. CoolTrayIcon1.ShowBalloonHint('ProSnooperFx',Nickname+' highlighted you.',bitInfo,10);
  623. end; //end highlight
  624. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colText1.Selected)+'>['+Nickname+'] '+Content+'</pcol>');
  625. end;
  626. end;
  627. procedure TfrmMain.ircAfterPrivateMessage(Nickname, Ident, Mask,
  628. Content: String);
  629. begin
  630. if lbIgnore.Items.IndexOf(NickName) = -1 then begin
  631. if frmSettings.edsndMsg.Text <> '' then begin
  632. frmSettings.mp.Close;
  633. frmSettings.mp.FileName := frmSettings.edsndMsg.Text;
  634. frmSettings.mp.Open;
  635. frmSettings.mp.Play;
  636. end;
  637. if IsAway = True then begin // away message
  638. if lbIgnoreAway.Items.IndexOf(NickName) = -1 then
  639. if frmSettings.cbSendAwayPriv.Checked then begin
  640. lbIgnoreAway.Items.Add(Nickname);
  641. irc.Say(NickName,'Away: '+AwayReason);
  642. end;
  643. lblMsgs.Caption := IntToStr(StrToInt(lblMsgs.Caption) + 1);
  644. frmMessages.Memo1.Lines.Add(MakeTimeStampNoTags+Nickname+' messaged you: '+Content);
  645. end;
  646. CoolTrayIcon1.ShowBalloonHint('ProSnooperFx','You received a private message.',bitInfo,10);
  647. if frmSettings.cbBlink.Checked then
  648. CoolTrayIcon1.CycleIcons := True;
  649. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colPrivate.Selected)+'><- ['+Nickname+'] '+Content+'</pcol>');
  650. end;
  651. end;
  652. procedure TfrmMain.ircAfterUserJoin(Nickname, Hostname, Channel: String);
  653. begin
  654. if frmSettings.lbBuddies.Items.IndexOf(NickName) <> -1 then begin
  655. if frmSettings.edsndBuddy.Text <> '' then begin
  656. frmSettings.mp.Close;
  657. frmSettings.mp.FileName := frmSettings.edsndBuddy.Text;
  658. frmSettings.mp.Open;
  659. frmSettings.mp.Play;
  660. end;
  661. if frmSettings.cbBlink.Checked then
  662. CoolTrayIcon1.CycleIcons := True;
  663. CoolTrayIcon1.ShowBalloonHint('ProSnooperFx',Nickname+' logged on.',bitInfo,10);
  664. end;
  665. if frmSettings.cbJoins.Checked = True then
  666. AddRichLine(rechat,MakeTimeStamp+'<b><pcol='+ColorToString(frmSettings.colJoins.Selected)+'>Join: </b>'+Nickname+'.</pcol>');
  667. with nickfrm.lvNicks.Items.Add do begin
  668. ImageIndex := 49;
  669. SubItemImages[Subitems.Add('')] := 74;
  670. SubItems.Add(NickName);
  671. irc.whois(NickName,'');
  672. end;
  673. end;
  674. procedure TfrmMain.ircAfterUserPart(Nickname, Hostname, Channelname,
  675. Reason: String);
  676. begin
  677. if FindListViewItem(nickfrm.lvNicks,nickname,2) <> nil then begin
  678. if frmSettings.cbParts.Checked = True then begin
  679. AddRichLine(rechat,MakeTimeStamp+'<b><pcol='+ColorToString(frmSettings.colParts.Selected)+'>Part: </b>'+Nickname+'</pcol>');
  680. end;
  681. nickfrm.lvNicks.Items[FindListViewItem(nickfrm.lvNicks,NickName,2).Index].Delete;
  682. end;
  683. end;
  684. procedure TfrmMain.ircAfterUserQuit(Nickname, Reason: String);
  685. var
  686. ReasonTemp: String;
  687. begin
  688. if FindListViewItem(nickfrm.lvNicks,nickname,2) <> nil then begin // TheCyberShadow's IRC server sends a QUIT even if the nick is not on the channel
  689. if frmSettings.cbJoins.Checked = True then begin
  690. if Reason <> '' then
  691. ReasonTemp := ' ('+Reason+')'
  692. else
  693. ReasonTemp := '';
  694. AddRichLine(rechat,MakeTimeStamp+'<b><pcol='+ColorToString(frmSettings.colQuits.Selected)+'>Quit: </b>'+Nickname+ReasonTemp+'</pcol>');
  695. end;
  696. nickfrm.lvNicks.Items[FindListViewItem(nickfrm.lvNicks,NickName,2).Index].Delete;
  697. end;
  698. end;
  699. procedure TfrmMain.ircAfterUserKick(KickedUser, Kicker, Channel,
  700. Reason: String);
  701. begin
  702. if FindListViewItem(nickfrm.lvNicks,kickeduser,2) <> nil then begin
  703. AddRichLine(rechat,MakeTimeStamp+'<b><pcol='+ColorToString(frmSettings.colQuits.Selected)+'> Kick: '+KickedUser+' was kicked by '+Kicker+' ('+Reason+')</pcol>');
  704. nickfrm.lvNicks.Items[FindListViewItem(nickfrm.lvNicks,KickedUser,2).Index].Delete;
  705. end;
  706. end;
  707. procedure TfrmMain.ircConnect;
  708. begin
  709. StatusBar1.Panels[0].Text := 'Connected.';
  710. end;
  711. procedure TfrmMain.ircDisconnect;
  712. begin
  713. StatusBar1.Panels[0].Text := 'Disconnected.';
  714. AddRichLine(rechat,'You have been disconnected.');
  715. tmrGames.Enabled := True;
  716. end;
  717. procedure TfrmMain.ircAfterAction(NickName, Content, Destination: String);
  718. begin
  719. if lbIgNore.Items.IndexOf(NickName) = -1 then begin
  720. if Pos(Lowercase(frmLogin.cbUser.Text),Lowercase(Content)) <> 0 then begin // if highlighted
  721. if IsAway = True then begin
  722. lblHiLites.Caption := IntToStr(StrToInt(lblHiLites.Caption) + 1);
  723. frmMessages.Memo1.Lines.Add(MakeTimeStampNoTags+Nickname+' highlighted you: * '+Content);
  724. if lbIgnoreAway.Items.IndexOf(NickName) = -1 then
  725. if frmSettings.cbSendAwayHiLite.Checked then begin
  726. lbIgnoreAway.Items.Add(Nickname);
  727. irc.Say(NickName,'Away: '+AwayReason);
  728. end;
  729. end;
  730. CoolTrayIcon1.ShowBalloonHint('ProSnooperFx',Nickname+' highlighted you.',bitInfo,10);
  731. if frmSettings.cbBlink.Checked then
  732. CoolTrayIcon1.CycleIcons := True;
  733. if frmSettings.edsndHiLite.Text <> '' then begin
  734. frmSettings.mp.Close;
  735. frmSettings.mp.FileName := frmSettings.edsndHiLite.Text;
  736. frmSettings.mp.Open;
  737. frmSettings.mp.Play;
  738. end;
  739. end; //end highlight
  740. AddRichLine(rechat,MakeTimeStamp+'<pcol='+ColorToString(frmSettings.colActions.Selected)+'><i>* '+Nickname+' '+Content+'</i></pcol>')
  741. end;
  742. end;
  743. procedure TfrmMain.About1Click(Sender: TObject);
  744. begin
  745. frmAbout.ShowModal;
  746. end;
  747. procedure TfrmMain.CoolTrayIcon1Click(Sender: TObject);
  748. begin
  749. Application.Restore;
  750. CoolTrayIcon1.IconVisible := False;
  751. CoolTrayIcon1.IconIndex := 0;
  752. CoolTrayIcon1.CycleIcons := False;
  753. frmMain.Show;
  754. ShowWindow(Application.Handle, SW_SHOW);
  755. end;
  756. procedure TfrmMain.CoolTrayIcon1MinimizeToTray(Sender: TObject);
  757. begin
  758. CoolTrayIcon1.ShowBalloonHint('ProSnooperFx','ProSnooperFx has been minimized to the tray.',bitInfo,10);
  759. frmMain.Hide;
  760. end;
  761. procedure TfrmMain.lbGamesMouseMove(Sender: TObject; Shift: TShiftState;
  762. X, Y: Integer);
  763. begin
  764. StatusBar1.Panels[1].Text := 'The Game List: A list of games on the current channel. Right-click for menu.';
  765. end;
  766. procedure TfrmMain.FormShow(Sender: TObject);
  767. begin
  768. tmrGames.Enabled := True;
  769. if frmLogin.cbServer.Text <> 'wormnet1.team17.com' then tmrWhoCompat.Enabled := True;
  770. frmLogin.Hide;
  771. frmSettings.SetColors;
  772. end;
  773. procedure TfrmMain.Autologin1Click(Sender: TObject);
  774. begin
  775. frmLogin.SetRegistryData(HKEY_CURRENT_USER,'\Software\ProSnooperFx','AutoLogin',rdString,BoolToStr(AutoLogin1.Checked))
  776. end;
  777. procedure TfrmMain.tmrGamesTimer(Sender: TObject);
  778. var
  779. W: TWords;
  780. Sl: TStringList;
  781. I, ITemp: Integer;
  782. begin
  783. Sl := TStringList.Create;
  784. W := TWords.Create;
  785. try
  786. Sl.Text := http.Get('http://'+frmLogin.cbServer.Text+'/wormageddonweb/GameList.asp?Channel='+StringReplace(frmLogin.cbchan.Text,'#','',[]));
  787. Itemp := gmfrm.lvGames.ItemIndex;
  788. gmfrm.lvGames.Clear;
  789. // gmfrm.lvGames.Items.BeginUpdate;
  790. for I := 1 to Sl.Count-2 do begin
  791. if Pos('<GAMELIST',Sl[I]) = 0 then
  792. if Sl[I] <> '' then begin
  793. W.Text := Sl[I];
  794. with gmfrm.lvGames.Items.Add do begin
  795. if W[6] = '1' then
  796. ImageIndex := 63
  797. else
  798. ImageIndex := 62;
  799. SubItemImages[Subitems.Add('')] := StrToInt(W[4]);
  800. SubItems.Add(W[1]);
  801. SubItems.Add(W[2]);
  802. SubItems.Add(W[3]);
  803. SubItems.Add(W[7]);
  804. end;
  805. end;
  806. end;
  807. // gmfrm.lvGames.Items.EndUpdate;
  808. gmfrm.lvGames.ItemIndex := Itemp;
  809. except
  810. end;
  811. W.Free;
  812. Sl.Free;
  813. end;
  814. procedure TfrmMain.Copy1Click(Sender: TObject);
  815. begin
  816. rechat.CopyToClipboard;
  817. end;
  818. procedure TfrmMain.SelectAll1Click(Sender: TObject);
  819. begin
  820. rechat.SelectAll;
  821. end;
  822. procedure TfrmMain.FormCreate(Sender: TObject);
  823. begin
  824. Application.OnException := AppException;
  825. IsAway := False;
  826. DockHandler.ShowGrabberBars := True;
  827. gmfrm := TfrmdkGmList.Create(self);
  828. nickfrm := TfrmdkNickList.Create(self);
  829. DockHandler.LoadDesktop('\Software\ProSnooperFx');
  830. if DockHandler.bLoadSuccess = False then begin
  831. gmfrm.ManualDock(DockPanel1);
  832. nickfrm.ManualDock(DockPanel1);
  833. gmfrm.Show;
  834. nickfrm.Show;
  835. end;
  836. DockHandler.Refresh;
  837. end;
  838. procedure TfrmMain.Exit1Click(Sender: TObject);
  839. begin
  840. frmMain.Close;
  841. end;
  842. procedure TfrmMain.Settings1Click(Sender: TObject);
  843. begin
  844. frmSettings.ShowModal;
  845. end;
  846. procedure TfrmMain.JoindirectIP1Click(Sender: TObject);
  847. begin
  848. frmJoinGame.Show;
  849. end;
  850. function TfrmMain.FindListViewItem(lv: TListView; const S: string; column: Integer): TListItem;
  851. var
  852. i: Integer;
  853. found: Boolean;
  854. begin
  855. Assert(Assigned(lv));
  856. Assert((lv.viewstyle = vsReport) or (column = 0));
  857. Assert(S > '');
  858. for i := 0 to lv.Items.Count - 1 do
  859. begin
  860. Result := lv.Items[i];
  861. if column = 0 then
  862. found := AnsiCompareText(Result.Caption, S) = 0
  863. else if column > 0 then
  864. found := AnsiCompareText(Result.SubItems[column - 1], S) = 0
  865. else
  866. found := False;
  867. if found then
  868. Exit;
  869. end;
  870. // No hit if we get here
  871. Result := nil;
  872. end;
  873. procedure TfrmMain.SetFlagRank(Flag, Rank: Integer; Nickname: String);
  874. var
  875. I: Integer;
  876. begin
  877. I := FindListViewItem(nickfrm.lvNicks,NickName,2).Index;
  878. if (Rank > 74) or (Rank < 0) then Rank := 74; // can't get buddyflag or ignoreflag
  879. if (Flag > 61) or (Flag < 0) then Flag := 49; // can't get ranks as flags
  880. nickfrm.lvNicks.Items.Item[I].ImageIndex := Flag;
  881. if frmSettings.lbBuddies.Items.IndexOf(NickName) <> -1 then
  882. nickfrm.lvNicks.Items.Item[I].SubItemImages[0] := 75
  883. else
  884. if lbIgnore.Items.IndexOf(NickName) <> -1 then // if ignored
  885. nickfrm.lvNicks.Items.Item[I].SubItemImages[0] := 76
  886. else
  887. nickfrm.lvNicks.Items.Item[I].SubItemImages[0] := Rank;
  888. end;
  889. procedure TfrmMain.ircQuoteServer(Command: String);
  890. var
  891. W: TWords;
  892. begin
  893. W := TWords.Create;
  894. W.Text := Command;
  895. if W[1] = '311' then begin
  896. SetFlagRank(StrToIntDef(StringReplace(W[7], ':', '',[]),49),
  897. StrToIntDef(W[8],12)+62,
  898. W[3]);
  899. end;
  900. if W[1] = '403' then begin // if channel doesn't exist
  901. frmChanList.lvChans.Clear;
  902. frmChanList.Show;
  903. irc.Quote('LIST');
  904. frmChanList.DoPart := False; //some servers send a 403 if the parted channel doesnt exist
  905. end;
  906. if W[1] = '437' then begin // if channel doesn't exist
  907. frmChanList.lvChans.Clear;
  908. frmChanList.Show;
  909. irc.Quote('LIST');
  910. frmChanList.DoPart := False;
  911. end;
  912. if (W[1] = '461') and (W[3] = 'JOIN') then begin // if channel not specified
  913. frmChanList.lvChans.Clear;
  914. frmChanList.Show;
  915. irc.Quote('LIST');
  916. frmChanList.DoPart := False;
  917. end;
  918. if W[1] = '322' then begin // on list event
  919. with frmChanList.lvChans.Items.Add do begin
  920. Caption := W[3];
  921. SubItems.Add(w[4]);
  922. SubItems.Add(StringReplace(W.ConcatToEnd(5),':','',[]));
  923. end;
  924. end;
  925. if W[1] = '432' then begin
  926. ShowMessage('Invalid nickname. Please choose another.');
  927. irc.Quit('');
  928. frmMain.Hide;
  929. frmLogin.Show;
  930. end;
  931. W.Free;
  932. end;
  933. procedure TfrmMain.ircNames(Commanicks, Channel: String;
  934. endofnames: Boolean);
  935. var
  936. Sl: TStringList;
  937. I: Integer;
  938. begin
  939. nickfrm.lvNicks.Clear;
  940. Sl := TStringList.Create;
  941. Sl.CommaText := irc.GetUsersFromChannel(Channel);
  942. nickfrm.lvNicks.Items.BeginUpdate;
  943. for I := 0 to Sl.Count-1 do
  944. with nickfrm.lvNicks.Items.Add do begin
  945. ImageIndex := 49;
  946. SubItemImages[Subitems.Add('')] := 74;
  947. SubItems.Add(StringReplace(Sl[I], '@','',[]));
  948. SubItems.Add('lol');
  949. end;
  950. nickfrm.lvNicks.Items.EndUpdate;
  951. end;
  952. procedure TfrmMain.ircWho(Channel, Nickname, Username, Hostname, Name,
  953. Servername, status, other: String; EndOfWho: Boolean);
  954. var
  955. W: TWords;
  956. begin
  957. if EndOfWho = False then begin
  958. W := TWords.Create;
  959. W.Text := Name;
  960. if Channel = frmLogin.cbchan.Text then begin
  961. SetFlagRank(StrToIntDef(StringReplace(W[0], ':', '',[]), 49),
  962. StrToIntDef(W[1],12)+62,
  963. Nickname);
  964. end;
  965. W.Free;
  966. end;
  967. end;
  968. procedure TfrmMain.ircAfterJoined(Channelname: String);
  969. begin
  970. irc.Quote('WHO '+Channelname);
  971. end;
  972. procedure TfrmMain.HostWormnet1Click(Sender: TObject);
  973. begin
  974. frmHost.Show;
  975. end;
  976. procedure TfrmMain.FormDestroy(Sender: TObject);
  977. begin
  978. Application.OnException := nil;
  979. end;
  980. procedure TfrmMain.ircServerError(ErrorString: String);
  981. begin
  982. AddRichLine(rechat, 'IRC Error: '+ErrorString);
  983. end;
  984. procedure TfrmMain.Label2Click(Sender: TObject);
  985. begin
  986. GoAway('');
  987. end;
  988. procedure TfrmMain.Channellist1Click(Sender: TObject);
  989. begin
  990. frmChanList.Show;
  991. frmChanList.lvChans.Clear;
  992. irc.Quote('LIST');
  993. frmChanList.DoPart := True;
  994. end;
  995. procedure TfrmMain.Label3Click(Sender: TObject);
  996. begin
  997. frmMessages.Show;
  998. end;
  999. procedure TfrmMain.tmrWhoCompatTimer(Sender: TObject);
  1000. begin
  1001. // TheCyberShadow's server can't handle WHOIS, so we send out a WHO once in a while to sync the nicklist
  1002. irc.Quote('WHO '+frmLogin.cbchan.Text);
  1003. end;
  1004. procedure TfrmMain.ircAfterUserNickChange(Oldnick, Newnick: String);
  1005. begin
  1006. if FindListViewItem(nickfrm.lvNicks,oldnick,2) <> nil then begin
  1007. nickfrm.lvNicks.Items.Item[FindListViewItem(nickfrm.lvNicks,oldnick,2).Index].SubItems[1] := NewNick;
  1008. AddRichLine(rechat,MakeTimeStamp+'<b><pcol='+ColorToString(frmSettings.colJoins.Selected)+'>Nick: </b>'+OldNick+' -> '+NewNick+'.</pcol>');
  1009. end;
  1010. end;
  1011. procedure TfrmMain.rechatURLClick(Sender: TObject; const URL: String);
  1012. begin
  1013. Shellexecute(Handle,PChar('Open'),PChar(URL),nil,nil,SW_SHOW);
  1014. end;
  1015. procedure TfrmMain.Find1Click(Sender: TObject);
  1016. begin
  1017. FD.Execute;
  1018. end;
  1019. function TfrmMain.FindText(const SearchStr: string; // custom find routine
  1020. StartPos, FindLength : LongInt; Options: TSearchTypes;
  1021. SearchDown: Boolean = TRUE): Integer;
  1022. var
  1023. Find: TFindText;
  1024. Flags: Word;
  1025. begin
  1026. with Find do begin
  1027. chrg.cpMin := StartPos;
  1028. chrg.cpMax := StartPos + FindLength;
  1029. lpstrText := PChar(SearchStr);
  1030. end;
  1031. Flags := 0;
  1032. if stWholeWord in Options then
  1033. Flags := Flags or FT_WHOLEWORD
  1034. else
  1035. Flags := Flags and not FT_WHOLEWORD;
  1036. if stMatchCase in Options then
  1037. Flags := Flags or FT_MATCHCASE
  1038. else
  1039. Flags := Flags and not FT_MATCHCASE;
  1040. if SearchDown then
  1041. Flags := Flags OR $01
  1042. else
  1043. Flags := Flags OR $01;
  1044. Result := -1;
  1045. if SearchDown then
  1046. Result := SendMessage(rechat.Handle, EM_FINDTEXT, Flags, LongInt(@Find))
  1047. else // Search up doesn't work at all, so we loop through the text backwards
  1048. while (StartPos > -1) and (result = -1) do begin
  1049. //result := RichEdit1.Perform(EM_FindText, Flags, LongInt(@Find));
  1050. Result := SendMessage(rechat.Handle, EM_FINDTEXT, Flags, LongInt(@Find));
  1051. Dec(StartPos);
  1052. Find.chrg.cpMin := StartPos;
  1053. end;
  1054. end;
  1055. procedure TfrmMain.FDFind(Sender: TObject);
  1056. var
  1057. FoundAt: LongInt;
  1058. StartPos, FindLength: LongInt;
  1059. TheFindOptions: TFindOptions;
  1060. TheSearchTypes: TSearchTypes;
  1061. begin
  1062. TheFindOptions := [];
  1063. TheSearchTypes := [];
  1064. if frDown in FD.Options then begin
  1065. StartPos := rechat.SelStart + rechat.SelLength;
  1066. FindLength := Length(rechat.Text) - StartPos;
  1067. end else begin
  1068. StartPos := rechat.SelStart;
  1069. FindLength := 0;
  1070. end;
  1071. with Sender as TFindDialog do begin
  1072. if frMatchCase in Options then
  1073. TheSearchTypes := TheSearchTypes + [stMatchCase];
  1074. if frWholeWord in Options then
  1075. TheSearchTypes := TheSearchTypes + [stWholeWord];
  1076. end;
  1077. FoundAt := FindText(FD.FindText, StartPos, FindLength, TheSearchTypes, (frDown in FD.Options) );
  1078. if FoundAt <> -1 then begin
  1079. rechat.SetFocus;
  1080. rechat.SelStart := FoundAt;
  1081. rechat.SelLength := Length(FD.FindText);
  1082. rechat.Perform(EM_SCROLLCARET, 0, 0); //scroll to found line
  1083. end else
  1084. MessageDlg('"' + FD.FindText + '" could not be found.', mtInformation, [mbOk], 0);
  1085. end;
  1086. procedure TfrmMain.Clear1Click(Sender: TObject);
  1087. begin
  1088. rechat.Clear;
  1089. end;
  1090. procedure TfrmMain.ircNoSuchNickChannel(Value: String);
  1091. begin
  1092. AddRichLine(rechat, MakeTimeStamp+'No such nick/channel.');
  1093. end;
  1094. procedure TfrmMain.ircAfterInvited(NickName, Channel: String);
  1095. begin
  1096. AddRichLine(rechat, MakeTimeStamp+Nickname+' invites you to join '+Channel);
  1097. end;
  1098. procedure TfrmMain.ircMode(Nickname, Destination, Mode: String);
  1099. begin
  1100. AddRichLine(rechat, MakeTimeStamp+Nickname+' sets mode: ['+Destination+'] '+Mode);
  1101. end;
  1102. procedure TfrmMain.ircAfterTopic(ChannelName, Nickname, Topic: String);
  1103. begin
  1104. if NIckname = '' then
  1105. AddRichLine(rechat, MakeTimeStamp+'Topic is: ['+ChannelName+'] '+Topic)
  1106. else
  1107. AddRichLine(rechat, MakeTimeStamp+Nickname+' changes topic: ['+ChannelName+'] '+Topic);
  1108. end;
  1109. end.