You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/RnQMacros.pas

535 lines
14 KiB
Plaintext

unit RnQMacros;
{$I RnQConfig.inc}
interface
uses
windows, graphics, types, Menus, classes, RDGlobal, GR32, GR32_Backends;
{$I NoRTTI.inc}
type
Tmacro = record
hk: Tshortcut;
sw: boolean;
opcode: integer;
data: RawByteString;
end;
Tmacros = array of Tmacro;
TRnQMACROS = record
Name: String;
Cptn: String;
DefShortCut: String;
ev: procedure;
end;
TRnQbtn = record
Name, Cptn, Hint: String;
ImageName: TPicName;
// DefShortCut : String;
ev: procedure;
end;
function InitMacroses: boolean;
function removeMacro(i: integer): boolean;
function findHK(hk: Tshortcut): integer;
function addMacro(hk: Tshortcut; sw: boolean; op: integer): boolean;
procedure executeMacro(m: integer);
// convert
procedure str2macros(s: RawByteString; var m: Tmacros);
function str2macro(s: RawByteString): Tmacro;
function macros2str(m: Tmacros): RawByteString;
procedure popupMenu(m: Tpopupmenu);
procedure popupHintByMacro();
procedure toggleAutosize;
procedure toggleShowGroups;
procedure startMenuViaMacro;
procedure stopMenuViaMacro;
procedure MacroBossMode;
// var
// chatButtons : array[0..0] of TRnQbtn;
implementation
uses
forms,
RQUtil, RDUtils, RnQSysUtils, RnQBinUtils, RnQLangs, RnQGlobal,
RnQGraphics32,
roasterLib, utilLib, globalLib, iniLib, themesLib,
{$IFDEF RNQ_PLAYER}
uSimplePlayer,
{$ENDIF RNQ_PLAYER}
mainDlg, RnQTips, tipDlg, chatDlg, addContactDlg,
RnQProtocol;
{ const
macroses : array[0..34] of TRnQMACROS = (
( Name:'chat'; Cptn:'show/hide chat window'; DefShortCut:'ctrl+shift+o'; ev:),
( Name:'roaster'; Cptn:'show/hide contact list'; DefShortCut:''),
( Name:'tray'; Cptn:'simulate double-click on tray'; DefShortCut:'ctrl+shift+i'),
( Name:'clear event'; Cptn:'clear event'; DefShortCut:''),
( Name:'clear events'; Cptn:'clear all events'; DefShortCut:''),
( Name:'pop event'; Cptn:'pop event'; DefShortCut:''; ev: chopAndRealizeEvent),
( Name:'quit'; Cptn:'quit'; DefShortCut:''),
( Name:'shutdown'; Cptn:'shutdown the computer'; DefShortCut:''),
( Name:'groups'; Cptn:'show/hide groups'; DefShortCut:''),
( Name:'main menu'; Cptn:'pop up main menu'; DefShortCut:''),
( Name:'status menu'; Cptn:'pop up status menu'; DefShortCut:''),
( Name:'visibility menu'; Cptn:'pop up visibility menu'; DefShortCut:''),
( Name:'browser'; Cptn:'open browser'; DefShortCut:''),
( Name:'offline contacts'; Cptn:'show/hide offline contacts'; DefShortCut:''),
( Name:'autosize'; Cptn:'toggle autosize'; DefShortCut:''),
( Name:'connect'; Cptn:'connect'; DefShortCut:''),
( Name:'cd play'; Cptn:'play audio cd'; DefShortCut:''),
( Name:'cd stop'; Cptn:'stop/eject audio cd'; DefShortCut:''),
( Name:'view info'; Cptn:'show contact info'; DefShortCut:''),
( Name:'by uin'; Cptn:'show ''add by uin'' dialog'; DefShortCut:''),
( Name:'wp'; Cptn:'show white-pages'; DefShortCut:''),
( Name:'toggle border'; Cptn:'toggle contact list border'; DefShortCut:''),
( Name:'preferences'; Cptn:'show preferences'; DefShortCut:''),
( Name:'lock'; Cptn:'lock'; DefShortCut:''),
( Name:'show hint'; Cptn:'contact tip pop up'; DefShortCut:''; ev: popupHintByMacro),
( Name:'tip'; Cptn:'simulate double-click on tip message'; DefShortCut:''),
( Name:'reload theme'; Cptn:'reload theme'; DefShortCut:''; ev=reloadCurrentTheme),
( Name:'reload language'; Cptn:'reload language'; DefShortCut:''),
( Name:'visible to'; Cptn:'visible to selected contact'; DefShortCut:''),
( Name:'toggle sound'; Cptn:'sound on/off'; DefShortCut:''),
//( Name:''; Cptn:''; DefShortCut:''),
( Name:'RnQPlay'; Cptn:'Play'; DefShortCut:'ctrl+shift+ins'),
( Name:'RnQPause'; Cptn:'Pause'; DefShortCut:'ctrl+shift+home'),
( Name:'RnQStop'; Cptn:'Stop'; DefShortCut:'ctrl+shift+end'),
( Name:'RnQNext'; Cptn:'Next'; DefShortCut:'ctrl+shift+pgdn'),
( Name:'RnQPrev'; Cptn:'Prev'; DefShortCut:'ctrl+shift+pgup')
);
}
procedure executeMacro(m: integer);
var
// s:string;
c: TRnQContact;
begin
if BossMode.isBossKeyOn and askPassOnBossKeyOn and Assigned(Account.AccProto) and (Length(Account.AccProto.pwd) > 0) and
(m <> OP_BOSSKEY) then
Exit;
// if m in [OP_CHAT, OP_ROASTER, OP_TRAY, OP_QUIT, op] then
case m of
OP_CHAT:
if chatFrm.isVisible then
begin
chatFrm.close;
restoreForeWindow;
end
else if chatFrm.chats.count > 0 then
begin
oldForeWindow := getForegroundWindow;
bringForeground := chatFrm.handle;
chatFrm.open;
end;
OP_ROSTER:
RnQmain.toggleVisible;
OP_TRAY:
trayAction;
OP_CLEAREVENT:
begin
if not(chatFrm.isVisible and chatFrm.sawAllHere) and not eventQ.empty then
eventQ.pop.free;
TipsHideAll;
// tipFrm.hide();
end;
OP_CLEAREVENTS:
begin
eventQ.clear;
TipsHideAll;
// tipfrm.hide();
end;
OP_POPEVENT:
chopAndRealizeEvent;
OP_QUIT:
RnQmain.close;
OP_SHUTDOWN:
ExitWindows(0, 0);
OP_GROUPS:
toggleShowGroups;
OP_MAINMENU:
popupMenu(RnQmain.menu);
OP_STATUSMENU:
popupMenu(RnQmain.statusMenuNEW);
OP_VISIBILITYMENU:
if Assigned(RnQmain.vismenuExt) then
popupMenu(RnQmain.vismenuExt);
OP_BROWSER:
openURL(' ');
OP_OFFLINECONTACTS:
toggleOnlyOnline;
OP_AUTOSIZE:
toggleAutosize;
OP_CONNECT:
doConnect;
{ OP_CD_PLAY:
begin
if sendMCIcommand('status cdaudio mode')='open' then
sendMCIcommand('set cdaudio door closed');
sendMCIcommand('play cdaudio');
end;
OP_CD_STOP:
begin
if s='playing' then
sendMCIcommand('stop cdaudio')
else
if s='open' then
sendMCIcommand('set cdaudio door closed')
else
sendMCIcommand('set cdaudio door open');
end; }
OP_VIEWINFO:
begin
if Assigned(clickedContact) then
clickedContact.ViewInfo
end;
OP_ADDBYUIN:
RnQmain.byUIN1Click(NIL); // showForm(addContactFrm);
OP_WP:
showForm(WF_WP);
OP_TOGGLEBORDER:
toggleMainfrmBorder;
OP_PREFERENCES:
showForm(WF_PREF);
OP_LOCK:
doLock;
OP_HINT:
popupHintByMacro();
{ OP_TIP:
begin
tipFrm.actionCount:=1;
tipFrm.action:=TA_2lclick;
end; }
OP_RELOADTHEME:
reloadCurrentTheme();
OP_RELOADLANG:
reloadCurrentLang();
OP_VISIBLE_TO:
begin
c := focusedContact;
if (c = NIL) or c.imVisibleTo then
Exit;
c.fProto.AddToList(LT_TEMPVIS, c);
roasterLib.redraw(c);
end;
OP_TOGGLE_SOUND:
begin
playSounds := not playSounds;
// saveCFG;
saveCfgDelayed := True;
end;
{$IFDEF RNQ_PLAYER}
OP_PLR_PLAY:
begin
if Assigned(RnQPlayer) then
RnQPlayer.btnPlayClick(NIL);
end;
OP_PLR_PAUSE:
if Assigned(RnQPlayer) then
RnQPlayer.btnPauseClick(NIL);
OP_PLR_STOP:
if Assigned(RnQPlayer) then
RnQPlayer.btnStopClick(NIL);
OP_PLR_NEXT:
if Assigned(RnQPlayer) then
RnQPlayer.btnNextClick(NIL);
OP_PLR_PREV:
if Assigned(RnQPlayer) then
RnQPlayer.btnPrevClick(NIL);
OP_PLR_ADD:
if Assigned(RnQPlayer) then
RnQPlayer.btnAddClick(NIL);
{$ENDIF RNQ_PLAYER}
OP_BOSSKEY:
MacroBossMode;
OP_RESTARTRNQ:
RnQmain.ReStart(nil);
OP_SEARCHALLHISTORY:
showForm(WF_SEARCH);
end;
end; // executeMacro
function InitMacroses: boolean;
begin
setlength(macros, 0);
addMacro(TextToShortCut('ctrl+shift+i'), True, OP_TRAY);
addMacro(TextToShortCut('ctrl+shift+o'), True, OP_CHAT);
addMacro(TextToShortCut('ctrl+o'), FALSE, OP_OFFLINECONTACTS);
addMacro(TextToShortCut('ctrl+g'), FALSE, OP_GROUPS);
addMacro(TextToShortCut('ctrl+a'), FALSE, OP_AUTOSIZE);
addMacro(TextToShortCut('ctrl+p'), FALSE, OP_PREFERENCES);
addMacro(TextToShortCut('alt+i'), FALSE, OP_VIEWINFO);
addMacro(TextToShortCut('F11'), FALSE, OP_TOGGLEBORDER);
addMacro(TextToShortCut('F3'), FALSE, OP_HINT);
addMacro(TextToShortCut('ctrl+shift+m'), FALSE, OP_MAINMENU);
result := True;
end;
function removeMacro(i: integer): boolean;
begin
result := (i >= 0) and (i < Length(macros));
if result then
begin
while i < Length(macros) - 1 do
begin
macros[i] := macros[i + 1];
inc(i);
end;
setlength(macros, i);
end;
end; // removeMacro
function findHK(hk: Tshortcut): integer;
begin
for result := 0 to Length(macros) - 1 do
if macros[result].hk = hk then
Exit;
result := -1;
end; // findHK
function addMacro(hk: Tshortcut; sw: boolean; op: integer): boolean;
var
i: integer;
begin
if hk = 0 then
begin
result := FALSE;
Exit;
end;
i := findHK(hk);
result := i < 0;
if result then
begin
i := Length(macros);
setlength(macros, i + 1);
end;
macros[i].hk := hk;
macros[i].sw := sw;
macros[i].opcode := op;
end; // addMacro
const
MFK_HK = 1;
MFK_SW = 2;
MFK_OP = 3;
function macro2str(m: Tmacro): RawByteString;
begin
result := TLV2(MFK_HK, int2str(m.hk)) + TLV2(MFK_SW, bool2str(m.sw)) + TLV2(MFK_OP, int2str(m.opcode))
end; // macro2str
function str2macro(s: RawByteString): Tmacro;
var
t, l: integer;
d: AnsiString;
begin
while s > '' do
begin
t := dword_LEat(@s[1]); // 1234
l := dword_LEat(@s[5]); // 5678
d := copy(s, 9, l);
case t of
MFK_HK:
result.hk := str2int(d);
MFK_SW:
result.sw := boolean(d[1]);
MFK_OP:
result.opcode := str2int(d);
end;
delete(s, 1, 8 + l);
end;
end; // str2macro
function macros2str(m: Tmacros): RawByteString;
var
i: integer;
s: RawByteString;
begin
result := '';
for i := 0 to Length(m) - 1 do
begin
s := macro2str(m[i]);
result := result + int2str(Length(s)) + s;
end;
end; // macros2str
procedure str2macros(s: RawByteString; var m: Tmacros);
var
l, n: integer;
begin
n := 0;
while Length(s) > 0 do
begin
l := str2int(s);
inc(n);
setlength(m, n);
m[n - 1] := str2macro(copy(s, 5, l));
delete(s, 1, 4 + l);
end;
end; // str2macros
procedure popupHintByMacro();
var
bmp: Tbitmap32;
r: Trect;
node: Tnode;
pt: Tpoint;
vRnQpicEx: TRnQBitmap;
RnQPicStream: TMemoryStream;
begin
bmp := Tbitmap32.Create;
bmp.SetSize(1, 1);
pt := RnQmain.roster.ScreenToClient(mousepos);
if within(0, pt.x, RnQmain.roster.width) and within(0, pt.y, RnQmain.roster.height) then
node := roasterLib.nodeAt(pt.x, pt.y)
else
node := NIL;
if node = NIL then
node := clickedNode;
if node <> NIL then
begin
RnQPicStream := TMemoryStream.Create;
bmp.SaveToStream(RnQPicStream);
vRnQpicEx := TRnQBitmap.Create;
if loadPic(TStream(RnQPicStream), vRnQpicEx, 0, PA_FORMAT_UNK, 'RnQImageEx', True) then
begin
// drawNodeHint(bmp.canvas, node.treenode, r);
drawHint(bmp.canvas, node.kind, node.groupId, node.contact, r, True);
bmp.width := r.Right + 1;
bmp.height := r.bottom + 1;
// drawNodeHint(bmp.canvas, node.treenode, r);
drawHint(bmp.canvas, node.kind, node.groupId, node.contact, r);
// TipAdd(bmp, 50);
TipAdd3(nil, vRnQpicEx, nil, behaviour[1].TipTime * 2 + behaviour[1].TipTimePlus);
// tipfrm.show(bmp);
end;
vRnQpicEx.free;
RnQPicStream.free;
end;
bmp.free;
end; // popupHintByMacro
procedure popupMenu(m: Tpopupmenu);
begin
if docking.Dock2Chat and docking.Docked2chat then
bringForeground := chatFrm.handle
else
bringForeground := RnQmain.handle;
m.Popup(Screen.width div 2, Screen.height div 2);
end; // popupMenu
procedure toggleAutosize;
begin
autosizeRoster := not autosizeRoster;
// design_fr.resetAutosize();
autosizeDelayed := True;
end; // toggleAutosize
procedure toggleShowGroups;
begin
showGroups := not showGroups;
saveCfgDelayed := True;
// design_fr.prefToggleShowGroups;
rosterRebuildDelayed := True;
end;
procedure startMenuViaMacro;
begin
menuViaMacro := True;
ShowWindow(application.handle, SW_SHOW);
application.bringtofront;
end; // startMenuViaMacro
procedure stopMenuViaMacro;
begin
menuViaMacro := FALSE
end;
procedure MacroBossMode;
var
pass: String;
s: String;
begin
if BossMode.isBossKeyOn and askPassOnBossKeyOn then
begin
if (AccPass > '') or (Assigned(Account.AccProto) and (Length(Account.AccProto.pwd) > 0)) then
begin
if enteringICQpwd then
Exit;
if AccPass > '' then
s := 'Account password'
else
s := 'Enter your password';
enteringICQpwd := True;
enterPwdDlg(pass, getTranslation(s));
enteringICQpwd := FALSE;
end;
if (AccPass > '') then
begin
if (AccPass <> pass) then
Exit;
end
else if (Assigned(Account.AccProto) and (Length(Account.AccProto.pwd) > 0)) then
begin
if not Account.AccProto.pwdEqual(pass) then
Exit;
end;
end;
BossMode.isBossKeyOn := not BossMode.isBossKeyOn;
if BossMode.isBossKeyOn then
begin
BossMode.toShowChat := chatFrm.Visible;
BossMode.toShowCL := formVisible(RnQmain) and (RnQmain.windowstate <> wsMinimized);
if docking.Dock2Chat and docking.Docked2chat AND NOT RnQmain.Floating and BossMode.toShowChat then
BossMode.toShowChat := FALSE;
if BossMode.toShowChat then
begin
chatFrm.close;
restoreForeWindow;
end;
if BossMode.toShowCL then
begin
RnQmain.toggleVisible;
end;
BossMode.activeChat := True;
TipsHideAll;
end
else
begin
if not BossMode.activeChat then
if BossMode.toShowChat then
if chatFrm.chats.count > 0 then
begin
chatFrm.open;
end;
if BossMode.toShowCL and not formVisible(RnQmain) then
begin
bringForeground := 0;
RnQmain.toggleVisible;
end;
if BossMode.activeChat then
if BossMode.toShowChat then
if chatFrm.chats.count > 0 then
begin
chatFrm.open;
end;
end;
if Assigned(statusIcon) and Assigned(statusIcon.trayIcon) then
statusIcon.trayIcon.update;
end;
end.