bool ChannelAgent::RemoveUser(const char* data) { ASSERT(data != NULL); /* * Function purpose: Remove nickname {data} from the ChannelAgent's * NamesView and update the status counts */ if (fNamesList == NULL) return false; // if nickname is present in tab completion lists, remove RemoveNickFromList(fRecentNicks, data); RemoveNickFromList(fCompletionNicks, data); int32 myIndex(FindPosition(data)); if (myIndex >= 0) { NameItem* item; fNamesList->Deselect(myIndex); if ((item = static_cast<NameItem*>(fNamesList->RemoveItem(myIndex))) != NULL) { BString buffer; if ((item->Status() & STATUS_OP_BIT) != 0) { --fOpsCount; buffer << fOpsCount; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_OPS, buffer.String()); buffer = ""; } --fUserCount; buffer << fUserCount; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_USERS, buffer.String()); delete item; return true; } } return false; }
void ChannelAgent::MessageReceived(BMessage* msg) { int32 i(0); switch (msg->what) { case M_USER_QUIT: { const char* nick(NULL); msg->FindString("nick", &nick); if (RemoveUser(nick)) { BMessage display; if (msg->FindMessage("display", &display) == B_NO_ERROR) ClientAgent::MessageReceived(&display); } } break; case M_USER_ADD: { const char* nick(NULL); bool ignore(false); int32 iStatus(STATUS_NORMAL_BIT); msg->FindString("nick", &nick); msg->FindBool("ignore", &ignore); if (nick == NULL) { printf("ERROR: attempted to AddUser an empty nick in ChannelAgent, channel: %s\n", fId.String()); break; } if (ignore) iStatus |= STATUS_IGNORE_BIT; AddUser(nick, iStatus); BMessage display; if (msg->FindMessage("display", &display) == B_NO_ERROR) ClientAgent::MessageReceived(&display); } break; case M_CHANGE_NICK: { const char* oldNick(NULL), *newNick(NULL); NameItem* item(NULL); int32 thePos(-1); if ((msg->FindString("oldnick", &oldNick) != B_OK) || (msg->FindString("newnick", &newNick) != B_OK)) { printf("Error: invalid pointer, ChannelAgent::MessageReceived, M_CHANGE_NICK"); break; } if (fMyNick.ICompare(oldNick) == 0 && !IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_NICK, newNick); if (((thePos = FindPosition(oldNick)) >= 0) && ((item = (static_cast<NameItem*>(fNamesList->ItemAt(thePos)))) != 0)) { item->SetName(newNick); fNamesList->SortItems(SortNames); if (fLastExpansion.ICompare(oldNick, fLastExpansion.Length()) == 0) { int32 count(fRecentNicks.CountItems()); BString* name(NULL); for (i = 0; i < count; i++) if ((name = fRecentNicks.ItemAt(i))->ICompare(oldNick) == 0) { if (fLastExpansion.ICompare(newNick, fLastExpansion.Length()) == 0) name->SetTo(newNick); else delete fRecentNicks.RemoveItemAt(i); break; } count = fCompletionNicks.CountItems(); for (i = 0; i < count; i++) if ((name = fCompletionNicks.ItemAt(i))->ICompare(oldNick) == 0) { if (fLastExpansion.ICompare(newNick, fLastExpansion.Length()) == 0) name->SetTo(newNick); else delete fCompletionNicks.RemoveItemAt(i); break; } } } else break; ClientAgent::MessageReceived(msg); } break; case M_CHANNEL_NAMES: { for (i = 0; msg->HasString("nick", i); ++i) { const char* nick(NULL); bool founder(false), protect(false), op(false), voice(false), helper(false), ignored(false); msg->FindString("nick", i, &nick); msg->FindBool("founder", i, &founder); msg->FindBool("protect", i, &protect); msg->FindBool("op", i, &op); msg->FindBool("voice", i, &voice); msg->FindBool("helper", i, &helper); msg->FindBool("ignored", i, &ignored); if (FindPosition(nick) < 0) { int32 iStatus(ignored ? STATUS_IGNORE_BIT : 0); if (founder) { ++nick; ++fOpsCount; iStatus |= STATUS_FOUNDER_BIT; } else if (protect) { ++nick; ++fOpsCount; iStatus |= STATUS_PROTECTED_BIT; } else if (op) { ++nick; ++fOpsCount; iStatus |= STATUS_OP_BIT; } else if (voice) { ++nick; iStatus |= STATUS_VOICE_BIT; } else if (helper) { ++nick; iStatus |= STATUS_HELPER_BIT; } else iStatus |= STATUS_NORMAL_BIT; fUserCount++; fNamesList->AddItem(new NameItem(nick, iStatus)); } } fNamesList->SortItems(SortNames); if (!IsHidden()) { BString buffer; buffer << fOpsCount; vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_OPS, buffer.String()); buffer = ""; buffer << fUserCount; vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_USERS, buffer.String()); } } break; case M_RESIZE_VIEW: { BPoint point; msg->FindPoint("loc", &point); point.x -= Frame().left; float offset((int32)(point.x - (fNamesScroll->Frame().left))); fResize->MoveBy(offset, 0.0); fTextScroll->ResizeBy(offset, 0.0); fNamesScroll->ResizeBy(-offset, 0.0); fNamesScroll->MoveBy(offset, 0.0); BRect namesRect(0, 0, fNamesScroll->Bounds().Width(), 0); vision_app->SetRect("namesListRect", namesRect); } break; case M_SERVER_DISCONNECT: { // clear names list on disconnect fNamesList->ClearList(); fOpsCount = 0; fUserCount = 0; // clear heuristics completion list - this ensures that no stale nicks are left // over in it after reconnect -- list will quickly be rebuilt anyhow if there // is any conversation whatsoever going on while (fRecentNicks.CountItems() > 0) delete fRecentNicks.RemoveItemAt(0L); } break; case M_REJOIN: { const char* newNick(NULL); if (msg->FindString("nickname", &newNick) != B_OK) { printf("Error: ChannelAgent::MessageReceived, M_REJOIN: invalid pointer\n"); break; } fMyNick = newNick; // update nickname (might have changed on reconnect) if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_NICK, fMyNick.String()); Display(S_CHANNEL_RECON_REJOIN B_UTF8_ELLIPSIS "\n", C_ERROR, C_BACKGROUND, F_SERVER); // send join cmd BMessage send(M_SERVER_SEND); AddSend(&send, "JOIN "); AddSend(&send, fId); if (fChanKey != "") { AddSend(&send, " "); AddSend(&send, fChanKey); } AddSend(&send, endl); } break; case M_CHANNEL_TOPIC: { const char* theTopic(NULL); BString buffer; if (msg->FindString("topic", &theTopic) != B_OK) { printf("ChannelAgent::MessageReceived, M_CHANNEL_TOPIC: invalid pointer\n"); break; } fTopic = theTopic; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue( STATUS_META, FilterCrap(theTopic, true).String()); BMessage display; if (msg->FindMessage("display", &display) == B_NO_ERROR) ClientAgent::MessageReceived(&display); } break; case M_OPEN_MSGAGENT: { const char* theNick(NULL); msg->FindString("nick", &theNick); if (theNick == NULL) { NameItem* myUser; int32 pos = fNamesList->CurrentSelection(); if (pos >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(pos)); BString targetNick = myUser->Name(); msg->AddString("nick", targetNick.String()); } } fSMsgr.SendMessage(msg); } break; case M_CHANNEL_GOT_KICKED: { const char* theChannel(NULL), *kicker(NULL), *rest(NULL); if ((msg->FindString("channel", &theChannel) != B_OK) || (msg->FindString("kicker", &kicker) != B_OK) || (msg->FindString("rest", &rest) != B_OK)) { printf("Error: ClientAgent::MessageReceived, M_CHANNEL_GOT_KICKED, invalid pointer\n"); break; } BMessage wegotkicked(M_DISPLAY); // "you were kicked" BString buffer; buffer += S_CHANNEL_GOT_KICKED; buffer += theChannel; buffer += " " S_CHANNEL_GOT_KICKED2 " "; buffer += kicker; buffer += " ("; buffer += rest; buffer += ")\n"; PackDisplay(&wegotkicked, buffer.String(), C_QUIT, C_BACKGROUND, F_TEXT); // clean up fNamesList->ClearList(); fOpsCount = 0; fUserCount = 0; fMsgr.SendMessage(&wegotkicked); BMessage attemptrejoin(M_DISPLAY); // "you were kicked" buffer = S_CHANNEL_REJOIN; buffer += theChannel; buffer += B_UTF8_ELLIPSIS "\n"; PackDisplay(&attemptrejoin, buffer.String(), C_QUIT, C_BACKGROUND, F_TEXT); fMsgr.SendMessage(&attemptrejoin); BMessage send(M_SERVER_SEND); AddSend(&send, "JOIN "); AddSend(&send, theChannel); if (fChanKey != "") { AddSend(&send, " "); AddSend(&send, fChanKey); } AddSend(&send, endl); } break; case M_CHANNEL_MODE: { ModeEvent(msg); } break; case M_CHANNEL_MSG: { bool hasNick(false); BString tempString, theNick, knownAs; msg->FindString("msgz", &tempString); msg->FindString("nick", &theNick); if (theNick != fMyNick) FirstKnownAs(tempString, knownAs, &hasNick); if (IsHidden()) { UpdateStatus((hasNick) ? WIN_NICK_BIT : WIN_NEWS_BIT); if (hasNick) { if (tempString[0] == '\1') { tempString.RemoveFirst("\1ACTION "); tempString.RemoveLast("\1"); } BNotification notification(B_INFORMATION_NOTIFICATION); notification.SetGroup(BString("Vision")); entry_ref ref = vision_app->AppRef(); notification.SetOnClickFile(&ref); notification.SetTitle(fServerName.String()); BString content; content.SetToFormat("%s - %s said: %s", fId.String(), theNick.String(), tempString.String()); notification.SetContent(content); notification.Send(); } } else if (hasNick) system_beep(kSoundEventNames[(uint32)seNickMentioned]); ClientAgent::MessageReceived(msg); } break; case M_CHANNEL_MODES: { const char* mode(NULL), *chan(NULL), *msgz(NULL); if ((msg->FindString("mode", &mode) != B_OK) || (msg->FindString("chan", &chan) != B_OK) || (msg->FindString("msgz", &msgz) != B_OK)) { printf("Error: ChannelAgent::MessageReceived, M_CHANNEL_MODES: invalid pointer\n"); break; } if (fId.ICompare(chan) == 0) { BString realMode(GetWord(mode, 1)); int32 place(2); if (realMode.FindFirst("l") >= 0) fChanLimit = GetWord(mode, place++); if (realMode.FindFirst("k") >= 0) { fChanKey = GetWord(mode, place++); // u2 may not send the channel key, thats why we stored the /join cmd // in a string in ParseCmd if (fChanKey == "*" && fIrcdtype == IRCD_UNDERNET) { BString tempId(fId); tempId.Remove(0, 1); // remove any #, &, !, blah. if (vision_app->pClientWin()->joinStrings.FindFirst(tempId) < 1) { // can't find the join cmd for this channel in joinStrings! } else { BString joinStringsL(vision_app->pClientWin()->joinStrings); // FindLast to make sure we get the last attempt (user might have // tried several keys) int32 idPos(joinStringsL.FindLast(tempId)); BString tempKeyString; joinStringsL.MoveInto(tempKeyString, idPos, joinStringsL.Length()); fChanKey = GetWord(tempKeyString.String(), 2); } } // end u2-kludge stuff } fChanMode = mode; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_MODES, fChanMode.String()); } BMessage dispMsg(M_DISPLAY); PackDisplay(&dispMsg, msgz, C_OP, C_BACKGROUND, F_TEXT); BMessenger display(this); display.SendMessage(&dispMsg); } break; case M_NAMES_POPUP_MODE: { const char* inaction(NULL); msg->FindString("action", &inaction); int32 count(0), index(0); BString victims, targetNick, action(inaction), modechar, polarity; NameItem* myUser(NULL); /// action /// if (action.FindFirst("voice") >= 0) modechar = "v"; else if (action.FindFirst("op") >= 0) modechar = "o"; else break; /// polarity /// if (action.FindFirst("de") >= 0) polarity += " -"; else polarity += " +"; /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); victims += " "; victims += targetNick; count++; } BString command("/mode "); command += fId; command += polarity; for (i = 0; i < count; i++) command += modechar; command += victims; ParseCmd(command.String()); } break; case M_NAMES_POPUP_CTCP: { const char* inaction(NULL); msg->FindString("action", &inaction); int32 index(0); BString victims, targetNick, action(inaction); NameItem* myUser(NULL); action.ToUpper(); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); victims += targetNick; victims += ","; } victims.RemoveLast(","); BString command("/ctcp "); command += victims; command += " "; command += action; ParseCmd(command.String()); } break; case M_NAMES_POPUP_WHOIS: { int32 index(0); BString victims, targetNick; NameItem* myUser(NULL); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); victims += targetNick; victims += ","; } victims.RemoveLast(","); BString command("/whois "); command += victims; ParseCmd(command.String()); } break; case M_NAMES_POPUP_NOTIFY: { int32 index(0); BString victims, targetNick; NameItem* myUser(NULL); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); victims += targetNick; victims += " "; } victims.RemoveLast(","); BString command("/notify "); command += victims; ParseCmd(command.String()); } break; case M_NAMES_POPUP_DCCCHAT: { int32 index(0); BString targetNick; NameItem* myUser(NULL); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); BString command("/dcc chat "); command += targetNick; ParseCmd(command.String()); } } break; case M_NAMES_POPUP_DCCSEND: { int32 index(0); BString targetNick; NameItem* myUser(NULL); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); BString command("/dcc send "); command += targetNick; ParseCmd(command.String()); } } break; case M_NAMES_POPUP_KICK: { int32 index(0); BString targetNick, kickMsg(vision_app->GetCommand(CMD_KICK)); NameItem* myUser(NULL); /// iterate /// while ((i = fNamesList->CurrentSelection(index++)) >= 0) { myUser = static_cast<NameItem*>(fNamesList->ItemAt(i)); targetNick = myUser->Name(); BString command("/kick "); command += targetNick; command += " "; command += kickMsg; ParseCmd(command.String()); } } break; case M_STATUS_ADDITEMS: { vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem(0, ""), true); vision_app->pClientWin()->pStatusView()->AddItem( new StatusItem(S_STATUS_LAG, "", STATUS_ALIGN_LEFT), true); vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem(0, "", STATUS_ALIGN_LEFT), true); vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem(S_STATUS_USERS, ""), true); vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem(S_STATUS_OPS, ""), true); vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem(S_STATUS_MODES, ""), true); vision_app->pClientWin()->pStatusView()->AddItem(new StatusItem("", "", STATUS_ALIGN_LEFT), true); // The false bool for SetItemValue() tells the StatusView not to Invalidate() the view. // We send true on the last SetItemValue(). vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_SERVER, fServerName.String(), false); vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_LAG, fMyLag.String(), false); vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_NICK, fMyNick.String(), false); vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_MODES, fChanMode.String(), false); vision_app->pClientWin()->pStatusView()->SetItemValue( STATUS_META, FilterCrap(fTopic.String(), true).String()); BString buffer; buffer << fUserCount; vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_USERS, buffer.String(), false); buffer = ""; buffer << fOpsCount; vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_OPS, buffer.String(), true); } break; case M_CHANNEL_OPTIONS_SHOW: { if (fChanOpt) fChanOpt->Activate(); else { fChanOpt = new ChannelOptions(fId.String(), this); fChanOpt->Show(); } } break; case M_CHANNEL_OPTIONS_CLOSE: { fChanOpt = NULL; } break; case M_CLIENT_QUIT: { if ((msg->HasBool("vision:part") && msg->FindBool("vision:part")) || (msg->HasBool("vision:winlist") && msg->FindBool("vision:winlist"))) { BMessage send(M_SERVER_SEND); AddSend(&send, "PART "); AddSend(&send, fId); if (msg->HasString("vision:partmsg")) { AddSend(&send, " :"); AddSend(&send, msg->FindString("vision:partmsg")); } AddSend(&send, endl); } ClientAgent::MessageReceived(msg); } break; default: ClientAgent::MessageReceived(msg); } }
void ChannelAgent::ModeEvent(BMessage* msg) { int32 modPos(0), targetPos(1); const char* mode(0), *target(0), *theNick(0); char theOperator(0); bool hit(false); // TODO Change Status to bitmask -- Too hard this way msg->FindString("mode", &mode); msg->FindString("target", &target); msg->FindString("nick", &theNick); BString buffer, targetS(target); buffer += "*** "; buffer += theNick; buffer += S_CHANNEL_SET_MODE; buffer += mode; if (targetS != "-9z99") { buffer += " "; buffer += targetS; } buffer += "\n"; BMessenger display(this); BMessage modeMsg(M_DISPLAY); PackDisplay(&modeMsg, buffer.String(), C_OP, C_BACKGROUND, F_TEXT); display.SendMessage(&modeMsg); // at least one if (mode && *mode && *(mode + 1)) theOperator = mode[modPos++]; while (theOperator && mode[modPos]) { char theModifier(mode[modPos]); if (theModifier == 'o' || theModifier == 'v' || theModifier == 'h') { BString myTarget(GetWord(target, targetPos++)); NameItem* item; int32 pos; if ((pos = FindPosition(myTarget.String())) < 0 || (item = static_cast<NameItem*>(fNamesList->ItemAt(pos))) == 0) { printf("[ERROR] Couldn't find %s in NamesView\n", myTarget.String()); return; } int32 iStatus(item->Status()); if (theOperator == '+' && theModifier == 'o') { hit = true; if ((iStatus & STATUS_OP_BIT) == 0) { item->SetStatus((iStatus & ~STATUS_NORMAL_BIT) | STATUS_OP_BIT); ++fOpsCount; buffer = ""; buffer << fOpsCount; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_OPS, buffer.String()); } } else if (theModifier == 'o') { hit = true; if ((iStatus & STATUS_OP_BIT) != 0) { iStatus &= ~STATUS_OP_BIT; if ((iStatus & STATUS_VOICE_BIT) == 0) iStatus |= STATUS_NORMAL_BIT; item->SetStatus(iStatus); --fOpsCount; buffer = ""; buffer << fOpsCount; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue(STATUS_OPS, buffer.String()); } } if (theOperator == '+' && theModifier == 'v') { hit = true; item->SetStatus((iStatus & ~STATUS_NORMAL_BIT) | STATUS_VOICE_BIT); } else if (theModifier == 'v') { hit = true; iStatus &= ~STATUS_VOICE_BIT; if ((iStatus & STATUS_OP_BIT) == 0) iStatus |= STATUS_NORMAL_BIT; item->SetStatus(iStatus); } if (theOperator == '+' && theModifier == 'h') { hit = true; item->SetStatus((iStatus & ~STATUS_NORMAL_BIT) | STATUS_HELPER_BIT); } else if (theModifier == 'h') { hit = true; iStatus &= ~STATUS_HELPER_BIT; if ((iStatus & STATUS_HELPER_BIT) == 0) iStatus |= STATUS_NORMAL_BIT; item->SetStatus(iStatus); } } else if (theModifier == 'l' && theOperator == '-') { BString myTarget(GetWord(target, targetPos++)); UpdateMode('-', 'l'); fChanLimit = ""; } else if (theModifier == 'l') { BString myTarget(GetWord(target, targetPos++)); fChanLimitOld = fChanLimit; fChanLimit = myTarget; UpdateMode('+', 'l'); } else if (theModifier == 'k' && theOperator == '-') { UpdateMode('-', 'k'); fChanKey = ""; } else if (theModifier == 'k') { BString myTarget(GetWord(target, targetPos++)); fChanKeyOld = fChanKey; fChanKey = myTarget; UpdateMode('+', 'k'); } else if (theModifier == 'b' || theModifier == 'a' || theModifier == 'q') { // dont do anything else } else { UpdateMode(theOperator, theModifier); } ++modPos; if (mode[modPos] == '+' || mode[modPos] == '-') theOperator = mode[modPos++]; } if (hit) { fNamesList->SortItems(SortNames); fNamesList->Invalidate(); } }
void NamesView::MessageReceived (BMessage *msg) { switch (msg->what) { case M_THEME_FOREGROUND_CHANGE: { int16 which (msg->FindInt16 ("which")); bool refresh (false); switch (which) { case C_NAMES_BACKGROUND: fActiveTheme->ReadLock(); SetViewColor (fActiveTheme->ForegroundAt (C_NAMES_BACKGROUND)); refresh = true; fActiveTheme->ReadUnlock(); break; case C_OP: case C_VOICE: case C_HELPER: case C_NAMES_SELECTION: refresh = true; break; default: break; } if (refresh) Invalidate(); } break; case M_THEME_FONT_CHANGE: { int16 which (msg->FindInt16 ("which")); if (which == F_NAMES) { fActiveTheme->ReadLock(); BFont newFont (fActiveTheme->FontAt (F_NAMES)); fActiveTheme->ReadUnlock(); SetFont (&newFont); for (int32 i = 0; i < CountItems(); i++) ItemAt(i)->Update(this, &newFont); Invalidate(); } } break; case B_SIMPLE_DATA: { if (msg->HasRef("refs")) { // this only grabs the first ref for now // TODO: maybe implement queueing of multiple sends next time entry_ref ref; msg->FindRef("refs", &ref); BDirectory dir (&ref); // don't try to dcc send a dir if (dir.InitCheck() == B_OK) break; int32 idx (CurrentSelection()); if (idx >= 0) { NameItem *item (dynamic_cast<NameItem *>(ItemAt(idx))); BMessage message (M_CHOSE_FILE); message.AddString ("nick", item->Name()); message.AddRef ("refs", &ref); ClientAgent *myParent (dynamic_cast<ClientAgent *>(Parent()->Parent())); if (myParent) myParent->fSMsgr.SendMessage (&message); } } } break; default: { BListView::MessageReceived (msg); } break; } }
void NamesView::MouseDown (BPoint myPoint) { int32 selected (IndexOf (myPoint)); bool handled (false); if (selected < 0) { DeselectAll(); return; } BMessage *inputMsg (Window()->CurrentMessage()); int32 mousebuttons (0), keymodifiers (0), mouseclicks (0); inputMsg->FindInt32 ("buttons", &mousebuttons); inputMsg->FindInt32 ("modifiers", &keymodifiers); inputMsg->FindInt32 ("clicks", &mouseclicks); if (mouseclicks > 1 && CurrentSelection(1) <= 0 && mousebuttons == B_PRIMARY_MOUSE_BUTTON && (keymodifiers & B_SHIFT_KEY) == 0 && (keymodifiers & B_OPTION_KEY) == 0 && (keymodifiers & B_COMMAND_KEY) == 0 && (keymodifiers & B_CONTROL_KEY) == 0) { // user double clicked BListItem *item (ItemAt (IndexOf(myPoint))); if (item && !item->IsSelected()) { // "double" clicked away from another selection Select (IndexOf (myPoint), false); fCurrentindex = IndexOf (myPoint); fTracking = true; } else if (item && item->IsSelected()) { // double clicking on a single item NameItem *myItem (reinterpret_cast<NameItem *>(item)); BString theNick (myItem->Name()); BMessage msg (M_OPEN_MSGAGENT); msg.AddString ("nick", theNick.String()); reinterpret_cast<ChannelAgent *>(Parent()->Parent())->fMsgr.SendMessage (&msg); } handled = true; } if (mouseclicks == 1 && CurrentSelection(1) <= 0 && mousebuttons == B_PRIMARY_MOUSE_BUTTON && (keymodifiers & B_SHIFT_KEY) == 0 && (keymodifiers & B_OPTION_KEY) == 0 && (keymodifiers & B_COMMAND_KEY) == 0 && (keymodifiers & B_CONTROL_KEY) == 0) { // user single clicks BListItem *item (ItemAt (IndexOf(myPoint))); if (item && !item->IsSelected()) Select (IndexOf (myPoint), false); fTracking = true; fCurrentindex = IndexOf (myPoint); handled = true; } if (mouseclicks >= 1 && CurrentSelection(1) >= 0 && mousebuttons == B_PRIMARY_MOUSE_BUTTON && (keymodifiers & B_SHIFT_KEY) == 0 && (keymodifiers & B_OPTION_KEY) == 0 && (keymodifiers & B_COMMAND_KEY) == 0 && (keymodifiers & B_CONTROL_KEY) == 0) { // user clicks on something in the middle of a sweep selection BListItem *item (ItemAt (IndexOf(myPoint))); if (item) Select (IndexOf (myPoint), false); fTracking = true; fCurrentindex = IndexOf (myPoint); handled = true; } if (mousebuttons == B_SECONDARY_MOUSE_BUTTON && (keymodifiers & B_SHIFT_KEY) == 0 && (keymodifiers & B_OPTION_KEY) == 0 && (keymodifiers & B_COMMAND_KEY) == 0 && (keymodifiers & B_CONTROL_KEY) == 0) { // user right clicks - display popup menu BListItem *item (ItemAt (IndexOf(myPoint))); if (item && !item->IsSelected()) Select (IndexOf (myPoint), false); fMyPopUp->Go ( ConvertToScreen (myPoint), true, false, ConvertToScreen (ItemFrame (selected))); handled = true; } if (mousebuttons == B_TERTIARY_MOUSE_BUTTON) BListView::MouseDown (myPoint); fLastSelected = selected; if (!handled) BListView::MouseDown (myPoint); }
bool ClientWindow::ParseCmd (const char *data) { BString firstWord (GetWord(data, 1).ToUpper()); if (firstWord == "/WALLOPS" // we need to insert a ':' before parm2 || firstWord == "/SQUIT" // for the user || firstWord == "/PRIVMSG") { BString theCmd (firstWord.RemoveAll ("/")), theRest (RestOfString (data, 2)); BMessage send (M_SERVER_SEND); AddSend (&send, theCmd); if (theRest != "-9z99") { AddSend (&send, " :"); AddSend (&send, theRest); } AddSend (&send, endl); return true; } if (firstWord == "/KILL") // we need to insert a ':' before parm3 { // for the user BString theCmd (firstWord.RemoveAll ("/")), theTarget (GetWord (data, 2)), theRest (RestOfString (data, 3)); BMessage send (M_SERVER_SEND); AddSend (&send, theCmd); AddSend (&send, " "); AddSend (&send, theTarget); if (theRest != "-9z99") { AddSend (&send, " :"); AddSend (&send, theRest); } AddSend (&send, endl); return true; } // some quick aliases for scripts, these will of course be // moved to an aliases section eventually if (firstWord == "/SOUNDPLAY" || firstWord == "/CL-AMP") { app_info ai; be_app->GetAppInfo (&ai); BEntry entry (&ai.ref); BPath path; entry.GetPath (&path); path.GetParent (&path); //path.Append ("data"); path.Append ("scripts"); if (firstWord == "/SOUNDPLAY") path.Append ("soundplay-hey"); else path.Append ("cl-amp-clr"); BMessage *msg (new BMessage); msg->AddString ("exec", path.Path()); msg->AddPointer ("client", this); thread_id execThread = spawn_thread ( ExecPipe, "exec_thread", B_LOW_PRIORITY, msg); resume_thread (execThread); return true; } if (firstWord == "/ABOUT") { be_app_messenger.SendMessage (B_ABOUT_REQUESTED); return true; } if (firstWord == "/AWAY") { BString theReason (RestOfString (data, 2)); BString tempString; if (theReason != "-9z99") { //nothing to do } else { theReason = "BRB"; // Todo: make a default away msg option } const char *expansions[1]; expansions[0] = theReason.String(); tempString = ExpandKeyed (bowser_app->GetCommand (CMD_AWAY).String(), "R", expansions); tempString.RemoveFirst("\n"); BMessage send (M_SERVER_SEND); AddSend (&send, "AWAY"); AddSend (&send, " :"); AddSend (&send, theReason.String()); AddSend (&send, endl); if (id != serverName) { ActionMessage (tempString.String(), myNick.String()); } return true; } if (firstWord == "/BACK") { BMessage send (M_SERVER_SEND); AddSend (&send, "AWAY"); AddSend (&send, endl); if (id != serverName) { ActionMessage ( bowser_app->GetCommand (CMD_BACK).String(), myNick.String()); } return true; } if (firstWord == "/CHANSERV" || firstWord == "/NICKSERV" || firstWord == "/MEMOSERV") { BString theCmd (firstWord.RemoveFirst ("/")), theRest (RestOfString (data, 2)); theCmd.ToLower(); if (theRest != "-9z99") { if (bowser_app->GetMessageOpenState()) { BMessage msg (OPEN_MWINDOW); BMessage buffer (M_SUBMIT); buffer.AddString ("input", theRest.String()); msg.AddMessage ("msg", &buffer); msg.AddString ("nick", theCmd.String()); sMsgr.SendMessage (&msg); } else { BString tempString; tempString << "[M]-> " << theCmd << " > " << theRest << "\n"; Display (tempString.String(), 0); BMessage send (M_SERVER_SEND); AddSend (&send, "PRIVMSG "); AddSend (&send, theCmd); AddSend (&send, " :"); AddSend (&send, theRest); AddSend (&send, endl); } } return true; } if (firstWord == "/CLEAR") { text->ClearView (false); return true; } if (firstWord == "/FCLEAR") { text->ClearView (true); return true; } if (firstWord == "/CTCP") { BString theTarget (GetWord (data, 2)); BString theAction (RestOfString (data, 3)); if (theAction != "-9z99") { theAction.ToUpper(); if (theAction.ICompare ("PING") == 0) { time_t now (time (0)); theAction << " " << now; } CTCPAction (theTarget, theAction); BMessage send (M_SERVER_SEND); AddSend (&send, "PRIVMSG "); AddSend (&send, theTarget << " :\1" << theAction << "\1"); AddSend (&send, endl); } return true; } if (firstWord == "/DCC") { BString secondWord (GetWord (data, 2)); BString theNick (GetWord (data, 3)); BString theFile (RestOfString(data, 4)); if (secondWord.ICompare ("SEND") == 0 && theNick != "-9z99") { BMessage *msg (new BMessage (CHOSE_FILE)); msg->AddString ("nick", theNick.String()); if (theFile != "-9z99") { char filePath[B_PATH_NAME_LENGTH] = "\0"; if (theFile.ByteAt(0) != '/') { find_directory(B_USER_DIRECTORY, 0, false, filePath, B_PATH_NAME_LENGTH); filePath[strlen(filePath)] = '/'; } strcat(filePath, theFile.LockBuffer(0)); theFile.UnlockBuffer(); // use BPath to resolve relative pathnames, above code forces it // to use /boot/home as a working dir as opposed to the app path BPath sendPath(filePath, NULL, true); // the BFile is used to verify if the file exists // based off the documentation get_ref_for_path *should* // return something other than B_OK if the file doesn't exist // but that doesn't seem to be working correctly BFile sendFile(sendPath.Path(), B_READ_ONLY); // if the file exists, send, otherwise drop to the file panel if (sendFile.InitCheck() == B_OK) { sendFile.Unset(); entry_ref ref; get_ref_for_path(sendPath.Path(), &ref); msg->AddRef("refs", &ref); sMsgr.SendMessage(msg); return true; } } BFilePanel *myPanel (new BFilePanel); BString myTitle ("Sending a file to "); myTitle.Append (theNick); myPanel->Window()->SetTitle (myTitle.String()); myPanel->SetMessage (msg); myPanel->SetButtonLabel (B_DEFAULT_BUTTON, "Send"); myPanel->SetTarget (sMsgr); myPanel->Show(); } else if (secondWord.ICompare ("CHAT") == 0 && theNick != "-9z99") { BMessage msg (CHAT_ACTION); msg.AddString ("nick", theNick.String()); sMsgr.SendMessage (&msg); } return true; } if (firstWord == "/DOP" || firstWord == "/DEOP") { BString theNick (RestOfString (data, 2)); if (theNick != "-9z99") { BMessage send (M_SERVER_SEND); AddSend (&send, "MODE "); AddSend (&send, id); AddSend (&send, " -oooo "); AddSend (&send, theNick); AddSend (&send, endl); } return true; } if (firstWord == "/DESCRIBE") { BString theTarget (GetWord (data, 2)); BString theAction (RestOfString (data, 3)); if (theAction != "-9z99") { BMessage send (M_SERVER_SEND); AddSend (&send, "PRIVMSG "); AddSend (&send, theTarget); AddSend (&send, " :\1ACTION "); AddSend (&send, theAction); AddSend (&send, "\1"); AddSend (&send, endl); BString theActionMessage ("[ACTION]-> "); theActionMessage << theTarget << " -> " << theAction << "\n"; Display (theActionMessage.String(), 0); } return true; } if (firstWord == "/DNS") { BString parms (GetWord(data, 2)); ChannelWindow *window; MessageWindow *message; if ((window = dynamic_cast<ChannelWindow *>(this))) { int32 count (window->namesList->CountItems()); for (int32 i = 0; i < count; ++i) { NameItem *item ((NameItem *)(window->namesList->ItemAt (i))); if (!item->Name().ICompare (parms.String(), strlen (parms.String()))) //nick { BMessage send (M_SERVER_SEND); AddSend (&send, "USERHOST "); AddSend (&send, item->Name().String()); AddSend (&send, endl); PostMessage(&send); return true; } } } else if ((message = dynamic_cast<MessageWindow *>(this))) { BString eid (id); eid.RemoveLast (" [DCC]"); if (!ICompare(eid, parms) || !ICompare(myNick, parms)) { BMessage send (M_SERVER_SEND); AddSend (&send, "USERHOST "); AddSend (&send, parms.String()); AddSend (&send, endl); PostMessage(&send); return true; } } if (parms != "-9z99") { BMessage *msg (new BMessage); msg->AddString ("lookup", parms.String()); msg->AddPointer ("client", this); thread_id lookupThread = spawn_thread ( DNSLookup, "dns_lookup", B_LOW_PRIORITY, msg); resume_thread (lookupThread); } return true; } if (firstWord == "/PEXEC") // piped exec { BString theCmd (RestOfString (data, 2)); if (theCmd != "-9z99") { BMessage *msg (new BMessage); msg->AddString ("exec", theCmd.String()); msg->AddPointer ("client", this); thread_id execThread = spawn_thread ( ExecPipe, "exec_thread", B_LOW_PRIORITY, msg); resume_thread (execThread); } return true; } if (firstWord == "/EXCLUDE") { BString second (GetWord (data, 2)), rest (RestOfString (data, 3)); if (rest != "-9z99" && rest != "-9z99") { BMessage msg (M_EXCLUDE_COMMAND); msg.AddString ("second", second.String()); msg.AddString ("cmd", rest.String()); msg.AddString ("server", serverName.String()); msg.AddRect ("frame", Frame()); bowser_app->PostMessage (&msg); } return true; } if (firstWord == "/IGNORE") { BString rest (RestOfString (data, 2)); if (rest != "-9z99") { BMessage msg (M_IGNORE_COMMAND); msg.AddString ("cmd", rest.String()); msg.AddString ("server", serverName.String()); msg.AddRect ("frame", Frame()); bowser_app->PostMessage (&msg); } return true; } if (firstWord == "/INVITE" || firstWord == "/I") { BString theUser (GetWord (data, 2)); if (theUser != "-9z99") { BString theChan (GetWord (data, 3)); if (theChan == "-9z99") theChan = id; BMessage send (M_SERVER_SEND); AddSend (&send, "INVITE "); AddSend (&send, theUser << " " << theChan); AddSend (&send, endl); } return true; } if (firstWord == "/JOIN" || firstWord == "/J") { BString channel (GetWord (data, 2)); if (channel != "-9z99") { if (channel[0] != '#' && channel[0] != '&') channel.Prepend("#"); BMessage send (M_SERVER_SEND); AddSend (&send, "JOIN "); AddSend (&send, channel); BString key (GetWord (data, 3)); if (key != "-9z99") { AddSend (&send, " "); AddSend (&send, key); } AddSend (&send, endl); } return true; } if (firstWord == "/KICK" || firstWord == "/K") { BString theNick (GetWord (data, 2)); if (theNick != "-9z99") { BString theReason (RestOfString (data, 3)); if (theReason == "-9z99") { // No expansions theReason = bowser_app ->GetCommand (CMD_KICK); } BMessage send (M_SERVER_SEND); AddSend (&send, "KICK "); AddSend (&send, id); AddSend (&send, " "); AddSend (&send, theNick); AddSend (&send, " :"); AddSend (&send, theReason); AddSend (&send, endl); } return true; } if (firstWord == "/LIST") { BMessage msg (M_LIST_COMMAND); msg.AddString ("cmd", data); msg.AddString ("server", serverName.String()); msg.AddRect ("frame", Frame()); bowser_app->PostMessage (&msg); return true; } if (firstWord == "/M") { BString theMode (RestOfString (data, 2)); BMessage send (M_SERVER_SEND); AddSend (&send, "MODE "); if (id == serverName) AddSend (&send, myNick); else if (id[0] == '#' || id[0] == '&') AddSend (&send, id); else AddSend (&send, myNick); if (theMode != "-9z99") { AddSend (&send, " "); AddSend (&send, theMode); } AddSend (&send, endl); return true; } if (firstWord == "/ME") { BString theAction (RestOfString (data, 2)); if (theAction != "-9z99") { ActionMessage (theAction.String(), myNick.String()); } return true; } if (firstWord == "/MODE") { BString theMode (RestOfString (data, 3)); BString theTarget (GetWord (data, 2)); if (theTarget != "-9z99") { BMessage send (M_SERVER_SEND); AddSend (&send, "MODE "); if (theMode == "-9z99") AddSend (&send, theTarget); else AddSend (&send, theTarget << " " << theMode); AddSend (&send, endl); } return true; } if (firstWord == "/MSG") { BString theRest (RestOfString (data, 3)); BString theNick (GetWord (data, 2)); if (theRest != "-9z99" && myNick.ICompare (theNick)) { if (bowser_app->GetMessageOpenState()) { BMessage msg (OPEN_MWINDOW); BMessage buffer (M_SUBMIT); buffer.AddString ("input", theRest.String()); msg.AddMessage ("msg", &buffer); msg.AddString ("nick", theNick.String()); sMsgr.SendMessage (&msg); } else { BString tempString; tempString << "[M]-> " << theNick << " > " << theRest << "\n"; Display (tempString.String(), 0); BMessage send (M_SERVER_SEND); AddSend (&send, "PRIVMSG "); AddSend (&send, theNick); AddSend (&send, " :"); AddSend (&send, theRest); AddSend (&send, endl); } } return true; } if (firstWord == "/NICK") { BString newNick (GetWord (data, 2)); if (newNick != "-9z99") { BString tempString ("*** Trying new nick "); tempString << newNick << ".\n"; Display (tempString.String(), 0); BMessage send (M_SERVER_SEND); AddSend (&send, "NICK "); AddSend (&send, newNick); AddSend (&send, endl); } return true; } if (firstWord == "/NOTICE") { BString theTarget (GetWord (data, 2)); BString theMsg (RestOfString (data, 3)); if (theMsg != "-9z99") { BMessage send (M_SERVER_SEND); AddSend (&send, "NOTICE "); AddSend (&send, theTarget); AddSend (&send, " :"); AddSend (&send, theMsg); AddSend (&send, endl); BString tempString ("[N]-> "); tempString << theTarget << " -> " << theMsg << '\n'; Display (tempString.String(), 0); } return true; } if (firstWord == "/NOTIFY") { BString rest (RestOfString (data, 2)); if (rest != "-9z99") { BMessage msg (M_NOTIFY_COMMAND); msg.AddString ("cmd", rest.String()); msg.AddBool ("add", true); msg.AddString ("server", serverName.String()); msg.AddRect ("frame", Frame()); bowser_app->PostMessage (&msg); } return true; } if (firstWord == "/OP") { BString theNick (RestOfString (data, 2)); if (theNick != "-9z99") { // TODO only applies to a channel BMessage send (M_SERVER_SEND); AddSend (&send, "MODE "); AddSend (&send, id); AddSend (&send, " +oooo "); AddSend (&send, theNick); AddSend (&send, endl); } return true; } if (firstWord == "/PART") { BMessage msg (B_QUIT_REQUESTED); msg.AddBool ("bowser:part", true); PostMessage (&msg); return true; } if (firstWord == "/PING") { BString theNick (GetWord (data, 2)); if (theNick != "-9z99") { long theTime (time (0)); BString tempString ("/CTCP "); tempString << theNick << " PING " << theTime; SlashParser (tempString.String()); } return true; } if (firstWord == "/PREFERENCES") { be_app_messenger.SendMessage (M_PREFS_BUTTON); return true; } if (firstWord == "/QUERY" || firstWord == "/Q") { BString theNick (GetWord (data, 2)); if (theNick != "-9z99") { BMessage msg (OPEN_MWINDOW); msg.AddString ("nick", theNick.String()); sMsgr.SendMessage (&msg); } return true; } if (firstWord == "/QUIT") { BString theRest (RestOfString (data, 2)); BString buffer; if (theRest == "-9z99") { const char *expansions[1]; BString version (bowser_app->BowserVersion()); expansions[0] = version.String(); theRest = ExpandKeyed (bowser_app ->GetCommand (CMD_QUIT).String(), "V", expansions); } buffer << "QUIT :" << theRest; BMessage msg (B_QUIT_REQUESTED); msg.AddString ("bowser:quit", buffer.String()); sMsgr.SendMessage (&msg); return true; } if (firstWord == "/RAW" || firstWord == "/QUOTE") { BString theRaw (RestOfString (data, 2)); if (theRaw != "-9z99") { BMessage send (M_SERVER_SEND); AddSend (&send, theRaw); AddSend (&send, endl); BString tempString ("[R]-> "); tempString << theRaw << '\n'; Display (tempString.String(), 0); } return true; } if (firstWord == "/RECONNECT") { BMessage msg (M_SLASH_RECONNECT); msg.AddString ("server", serverName.String()); bowser_app->PostMessage (&msg); return true; } if (firstWord == "/SLEEP") { BString rest (RestOfString (data, 2)); if (rest != "-9z99") { // this basically locks up the window its run from, // but I can't think of a better way with our current // commands implementation int32 time = atoi(rest.String()); snooze(time * 1000 * 100); // deciseconds? 10 = one second } return true; } if (firstWord == "/TOPIC" || firstWord == "/T") { BString theChan (id); BString theTopic (RestOfString (data, 2)); BMessage send (M_SERVER_SEND); AddSend (&send, "TOPIC "); if (theTopic == "-9z99") AddSend (&send, theChan); else AddSend (&send, theChan << " :" << theTopic); AddSend (&send, endl); return true; } if (firstWord == "/UNIGNORE") { BString rest (RestOfString (data, 2)); if (rest != "-9z99") { BMessage msg (M_UNIGNORE_COMMAND); msg.AddString ("cmd", rest.String()); msg.AddString ("server", serverName.String()); msg.AddRect ("frame", Frame()); bowser_app->PostMessage (&msg); } return true; } if (firstWord == "/UNNOTIFY") { BString rest (RestOfString (data, 2)); if (rest != "-9z99") { BMessage msg (M_NOTIFY_COMMAND); msg.AddString ("cmd", rest.String()); msg.AddBool ("add", false); msg.AddRect ("frame", Frame()); msg.AddString ("server", serverName.String()); bowser_app->PostMessage (&msg); } return true; } if (firstWord == "/UPTIME") { BString parms (GetWord(data, 2)); BString uptime (DurationString(system_time())); BString expandedString; const char *expansions[1]; expansions[0] = uptime.String(); expandedString = ExpandKeyed (bowser_app->GetCommand (CMD_UPTIME).String(), "U", expansions); expandedString.RemoveFirst("\n"); if ((id != serverName) && (parms == "-9z99")) { BMessage send (M_SERVER_SEND); AddSend (&send, "PRIVMSG "); AddSend (&send, id); AddSend (&send, " :"); AddSend (&send, expandedString.String()); AddSend (&send, endl); ChannelMessage (expandedString.String(), myNick.String()); } else if ((parms == "-l") || (id == serverName)) // echo locally { BString tempString; tempString << "Uptime: " << expandedString << "\n"; Display (tempString.String(), &whoisColor); } return true; } if (firstWord == "/VERSION" || firstWord == "/TIME") { BString theCmd (firstWord.RemoveFirst ("/")), theNick (GetWord (data, 2)); theCmd.ToUpper(); // the "." check is because the user might specify a server name if (theNick != "-9z99" && theNick.FindFirst(".") < 0) { BString tempString ("/CTCP "); tempString << theNick << " " << theCmd; SlashParser (tempString.String()); } else { BMessage send (M_SERVER_SEND); AddSend (&send, theCmd); if (theNick != "-9z99") { AddSend (&send, " "); AddSend (&send, theNick); } AddSend (&send, endl); } return true; } if (firstWord == "/VISIT") { BString buffer (data); int32 place; if ((place = buffer.FindFirst (" ")) >= 0) { buffer.Remove (0, place + 1); const char *arguments[] = {buffer.String(), 0}; be_roster->Launch ( "text/html", 1, const_cast<char **>(arguments)); } return true; } if (firstWord != "" && firstWord[0] == '/') // != "" is required to prevent a nasty crash with string[0] { BString theCmd (firstWord.RemoveAll ("/")), theRest (RestOfString (data, 2)); BMessage send (M_SERVER_SEND); if (theCmd == "W") theCmd = "WHOIS"; AddSend (&send, theCmd); if (theRest != "-9z99") { AddSend (&send, " "); AddSend (&send, theRest); } AddSend (&send, endl); return true; } return false; // we couldn't handle this message }