PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/mainform.pas

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