std::pair<LocalPoint,LocalVector> secondOrderAccurate( const GlobalPoint& startingPos, const GlobalVector& startingDir, double rho, const Plane& plane) { typedef Basic2DVector<float> Vector2D; // translate problem to local frame of the plane LocalPoint lPos = plane.toLocal(startingPos); LocalVector lDir = plane.toLocal(startingDir); LocalVector yPrime = plane.toLocal( GlobalVector(0,0,1.f)); float sinPhi=0, cosPhi=0; Vector2D pos; Vector2D dir; sinPhi = yPrime.y(); cosPhi = yPrime.x(); pos = Vector2D( lPos.x()*cosPhi + lPos.y()*sinPhi, -lPos.x()*sinPhi + lPos.y()*cosPhi); dir = Vector2D( lDir.x()*cosPhi + lDir.y()*sinPhi, -lDir.x()*sinPhi + lDir.y()*cosPhi); double d = -lPos.z(); double x = pos.x() + dir.x()/lDir.z()*d - 0.5*rho*d*d; double y = pos.y() + dir.y()/lDir.z()*d; LocalPoint thePos( x*cosPhi - y*sinPhi, x*sinPhi + y*cosPhi, 0); float px = dir.x()+rho*d; LocalVector theDir( px*cosPhi - dir.y()*sinPhi, px*sinPhi + dir.y()*cosPhi, lDir.z()); return std::pair<LocalPoint,LocalVector>(thePos,theDir); }
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); } }