status_t RuleFilter::ProcessMailMessage ( BPositionIO** , BEntry* entry, BMessage* io_headers, BPath* io_folder, const char* ) { const char *data; if (!attribute) return B_OK; //----That field doesn't exist? NO match if (io_headers->FindString(attribute,&data) < B_OK) { //--Maybe the capitalization was wrong? BString capped(attribute); capped.CapitalizeEachWord(); //----Enfore capitalization if (io_headers->FindString(capped.String(),&data) < B_OK) //----This time it's *really* not there return B_OK; //---No match } if (data == NULL) //--- How would this happen? No idea return B_OK; if (!matcher.Match(data)) return B_OK; //-----There wasn't an error. We're just not supposed to do anything switch (do_what) { case Z_MOVE_TO: if (io_headers->ReplaceString("DESTINATION",arg) != B_OK) io_headers->AddString("DESTINATION",arg); break; case Z_TRASH: return B_MAIL_DISCARD; case Z_FLAG: { BString string = arg; BNode(entry).WriteAttrString("MAIL:filter_flags",&string); } break; case Z_SET_REPLY: BNode(entry).WriteAttr("MAIL:reply_with",B_INT32_TYPE,0,&chain_id,4); break; case Z_SET_READ: if (io_headers->ReplaceString("STATUS", "Read") != B_OK) io_headers->AddString("STATUS", "Read"); break; default: fprintf(stderr,"Unknown do_what: 0x%04x!\n",do_what); } return B_OK; }
status_t OpenAction(const BMessage &action, entry_ref &ref) { entry_ref app; BString appName(""); if (be_roster->FindApp(&ref,&app) == B_OK) appName = app.name; status_t status = be_roster->Launch(&ref); if (status == B_OK) printf("\tOpened %s in program %s\n",ref.name,appName.String()); else { // R5 (and probably others) don't seem to want to open folders in Tracker -- // FindApp() returns B_OK, but sets the entry_ref of the app to open it to // the folder's ref, which is dumb. This works around this apparent stupidity. BString typestr; if (BNode(&ref).ReadAttrString("BEOS:TYPE",&typestr) == B_OK && typestr.Compare("application/x-vnd.Be-directory") == 0) { BMessage *msg = new BMessage(B_REFS_RECEIVED); msg->AddRef("refs",&ref); be_roster->Launch("application/x-vnd.Be-TRAK",msg); printf("\tOpened %s in program Tracker\n",ref.name); return B_OK; } if (appName.CountChars() > 0) printf("\tCouldn't open %s in program %s\n",ref.name,appName.String()); else printf("\tCouldn't open %s -- the system couldn't find a program to do it.\n",ref.name); } return status; }
void ActivityView::_LoadBackgroundInfo(bool watch) { fCachedOutline = false; fCachedWorkspace = -1; BPath path; if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { BNode desktopNode = BNode(path.Path()); attr_info info; if (desktopNode.GetAttrInfo(kDesktopAttrName, &info) != B_OK) return; char* buffer = new char[info.size]; if (desktopNode.ReadAttr(kDesktopAttrName, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) fBackgroundInfo = message; } delete[] buffer; if (watch) { node_ref nref; desktopNode.GetNodeRef(&nref); watch_node(&nref, B_WATCH_ATTR, this); } } }
void POP3Protocol::CheckForDeletedMessages() { { // Delete things from the manifest no longer on the server BStringList list; NotHere(fUniqueIDs, fManifest, &list); fManifest.Remove(list); } if (!fSettings.FindBool("delete_remote_when_local") || fManifest.CountStrings() == 0) return; BStringList toDelete; BStringList queryContents; BVolumeRoster volumes; BVolume volume; while (volumes.GetNextVolume(&volume) == B_OK) { BQuery fido; entry_ref entry; fido.SetVolume(&volume); fido.PushAttr(B_MAIL_ATTR_ACCOUNT_ID); fido.PushInt32(fAccountSettings.AccountID()); fido.PushOp(B_EQ); fido.Fetch(); BString uid; while (fido.GetNextRef(&entry) == B_OK) { BNode(&entry).ReadAttrString("MAIL:unique_id", &uid); queryContents.Add(uid); } } NotHere(queryContents, fManifest, &toDelete); for (int32 i = 0; i < toDelete.CountStrings(); i++) { printf("delete mail on server uid %s\n", toDelete.StringAt(i).String()); Delete(fUniqueIDs.IndexOf(toDelete.StringAt(i))); } // Don't remove ids from fUniqueIDs, the indices have to stay the same when // retrieving new messages. fManifest.Remove(toDelete); // TODO: at some point the purged manifest should be written to disk // otherwise it will grow forever }
void POP3Protocol::CheckForDeletedMessages() { { //---Delete things from the manifest no longer on the server BStringList temp; fManifest.NotThere(fUniqueIDs, &temp); fManifest -= temp; } if (!fSettings.FindBool("delete_remote_when_local") || fManifest.CountItems() == 0) return; BStringList to_delete; BStringList query_contents; BVolumeRoster volumes; BVolume volume; while (volumes.GetNextVolume(&volume) == B_OK) { BQuery fido; entry_ref entry; fido.SetVolume(&volume); fido.PushAttr(B_MAIL_ATTR_ACCOUNT_ID); fido.PushInt32(fAccountSettings.AccountID()); fido.PushOp(B_EQ); fido.Fetch(); BString uid; while (fido.GetNextRef(&entry) == B_OK) { BNode(&entry).ReadAttrString("MAIL:unique_id", &uid); query_contents.AddItem(uid.String()); } } query_contents.NotHere(fManifest, &to_delete); for (int32 i = 0; i < to_delete.CountItems(); i++) { printf("delete mail on server uid %s\n", to_delete[i]); Delete(fUniqueIDs.IndexOf(to_delete[i])); } //*(unique_ids) -= to_delete; --- This line causes bad things to // happen (POP3 client uses the wrong indices to retrieve // messages). Without it, bad things don't happen. fManifest -= to_delete; }
/* * Given a local file path, * update the corresponding file on Dropbox */ void update_file_in_dropbox(const char * filepath, const char *parent_rev) { char * argv[4]; argv[0] = "db_put.py"; BString db_filepath = local_to_db_filepath(filepath); const char * tmp = db_filepath.String(); char not_const[db_filepath.CountChars()]; strcpy(not_const,tmp); argv[2] = not_const; char not_const2[strlen(filepath)]; strcpy(not_const2,filepath); argv[1] = not_const2; char not_const3[strlen(parent_rev)]; strcpy(not_const3,parent_rev); argv[3] = not_const3; BString *result = run_python_script(argv,4); BString *real_path = parse_path(result); BString *new_parent_rev = parse_parent_rev(result); delete result; printf("path:|%s|\nparent_rev:|%s|\n",real_path->String(),new_parent_rev->String()); BNode node = BNode(filepath); set_parent_rev(&node,new_parent_rev); delete new_parent_rev; BEntry entry = BEntry(filepath); BPath old_path; entry.GetPath(&old_path); BPath new_path = BPath(db_to_local_filepath(real_path->String()).String()); printf("Should I move %s to %s?\n", old_path.Path(), new_path.Path()); if(strcmp(new_path.Leaf(),old_path.Leaf()) != 0) { printf("moving %s to %s\n", old_path.Leaf(), new_path.Leaf()); BEntry entry = BEntry(old_path.Path()); //entry for local path status_t err = entry.Rename(new_path.Leaf(),true); if(err != B_OK) printf("error moving: %s\n",strerror(err)); } delete real_path; }
void BlockerApp::RefsReceived(BMessage *msg) { entry_ref ref; BNode node; attr_info info; IM::Manager man; for (int32 i = 0; msg->FindRef("refs", i, &ref ) == B_OK; i++ ) { node = BNode(&ref); char *type = ReadAttribute(node, "BEOS:TYPE"); if (strcmp(type, "application/x-person") == 0) { IM::Contact contact(ref); char status[256]; if (contact.GetStatus(status, sizeof(status)) != B_OK ) status[0] = '\0'; if (strcmp(status, BLOCKED_TEXT) == 0) { // already blocked, unblocked contact.SetStatus(OFFLINE_TEXT); BMessage update_msg(IM::UPDATE_CONTACT_STATUS); update_msg.AddRef("contact", &ref); man.SendMessage(&update_msg); } else { if (contact.SetStatus(BLOCKED_TEXT) != B_OK) { LOG("im_blocker", liHigh, "Error setting contact status"); }; }; }; free(type); }; BMessenger(this).SendMessage(B_QUIT_REQUESTED); };
/* * Message Handling Function * If it's a node monitor message, * then figure out what to do based on it. * Otherwise, let BApplication handle it. */ void App::MessageReceived(BMessage *msg) { printf("message received:\n"); msg->PrintToStream(); switch(msg->what) { case MY_DELTA_CONST: { printf("Pulling changes from Dropbox\n"); pull_and_apply_deltas(); break; } case B_NODE_MONITOR: { printf("Received Node Monitor Alert\n"); status_t err; int32 opcode; err = msg->FindInt32("opcode",&opcode); if(err == B_OK) { switch(opcode) { case B_ENTRY_CREATED: { printf("CREATED NEW FILE\n"); entry_ref ref; BPath path; const char * name; // unpack the message msg->FindInt32("device",&ref.device); msg->FindInt64("directory",&ref.directory); msg->FindString("name",&name); ref.set_name(name); BEntry new_file = BEntry(&ref); new_file.GetPath(&path); //if we said to ignore a `NEW` msg from the path, then ignore it if(this->ignore_created(&path)) return; this->track_file(&new_file); if(new_file.IsDirectory()) { add_folder_to_dropbox(path.Path()); BDirectory new_dir = BDirectory(&new_file); this->recursive_watch(&new_dir); } else { BString *result = add_file_to_dropbox(path.Path()); BString *real_path = parse_path(result); BString *parent_rev = parse_parent_rev(result); delete result; printf("path:|%s|\nparent_rev:|%s|\n",real_path->String(),parent_rev->String()); BNode node = BNode(&new_file); set_parent_rev(&node,parent_rev); delete parent_rev; BPath new_path = BPath(db_to_local_filepath(real_path->String()).String()); if(strcmp(new_path.Leaf(),path.Leaf()) != 0) { printf("moving %s to %s\n", path.Leaf(), new_path.Leaf()); BEntry entry = BEntry(path.Path()); //entry for local path status_t err = entry.Rename(new_path.Leaf(),true); if(err != B_OK) printf("error moving: %s\n",strerror(err)); } delete real_path; watch_entry(&new_file,B_WATCH_STAT); } break; } case B_ENTRY_MOVED: { printf("MOVED FILE\n"); entry_ref eref; BDirectory from_dir, to_dir; node_ref from_ref,to_ref,nref; BPath path; const char* name; msg->FindInt32("device",&from_ref.device); msg->FindInt32("device",&to_ref.device); msg->FindInt32("device",&eref.device); msg->FindInt32("device",&nref.device); msg->FindInt64("from directory",&from_ref.node); msg->FindInt64("to directory",&to_ref.node); msg->FindInt64("to directory",&eref.directory); msg->FindInt64("node",&nref.node); msg->FindString("name",&name); eref.set_name(name); err = from_dir.SetTo(&from_ref); err = to_dir.SetTo(&to_ref); BEntry dest_entry = BEntry(&eref); BEntry test = BEntry("/boot/home/Dropbox/hi"); BDirectory dropbox_local = BDirectory(local_path_string); bool into_dropbox = dropbox_local.Contains(&dest_entry); int32 index = this->find_nref_in_tracked_files(nref); if((index >= 0) && into_dropbox) { printf("moving within dropbox\n"); BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index); BPath new_path; dest_entry.GetPath(&new_path); char *argv[3]; argv[0] = "db_mv.py"; BString opath = local_to_db_filepath(old_path->Path()); BString npath = local_to_db_filepath(new_path.Path()); char not_const_o[opath.CountChars()]; char not_const_n[npath.CountChars()]; strcpy(not_const_o,opath.String()); strcpy(not_const_n,npath.String()); argv[1] = not_const_o; argv[2] = not_const_n; run_python_script(argv,3); old_path->SetTo(&dest_entry); } else if(index >= 0) { printf("moving the file out of dropbox\n"); BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index); delete_file_on_dropbox(old_path->Path()); this->tracked_files.RemoveItem(index); this->tracked_filepaths.RemoveItem(index); } else if(into_dropbox) { printf("moving file into dropbox\n"); BPath new_path; dest_entry.GetPath(&new_path); this->track_file(&dest_entry); if(dest_entry.IsDirectory()) { add_folder_to_dropbox(new_path.Path()); BDirectory new_dir = BDirectory(&dest_entry); this->recursive_watch(&new_dir); } else { add_file_to_dropbox(new_path.Path()); watch_entry(&dest_entry,B_WATCH_STAT); } } else { printf("moving unrelated file...?\n"); } break; } case B_ENTRY_REMOVED: { printf("DELETED FILE\n"); node_ref nref; msg->FindInt32("device", &nref.device); msg->FindInt64("node", &nref.node); int32 index = this->find_nref_in_tracked_files(nref); if(index >= 0) { BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index); printf("local file %s deleted\n",path->Path()); if(ignore_removed(path)) return; delete_file_on_dropbox(path->Path()); this->tracked_files.RemoveItem(index); this->tracked_filepaths.RemoveItem(index); } else { printf("could not find deleted file\n"); } break; } case B_STAT_CHANGED: { printf("EDITED FILE\n"); node_ref nref; msg->FindInt32("device", &nref.device); msg->FindInt64("node", &nref.node); int32 index = this->find_nref_in_tracked_files(nref); if(index >= 0) { BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index); if(ignore_edited(path)) return; BNode node = BNode(path->Path()); BString * rev = get_parent_rev(&node); printf("parent_rev:|%s|\n",rev->String()); update_file_in_dropbox(path->Path(),rev->String()); } else { printf("Could not find edited file\n"); } break; } default: { printf("default case opcode...\n"); } } } break; } default: { BApplication::MessageReceived(msg); break; } } }
/* * Given a single line of the output of db_delta.py * Figures out what to do and does it. * (adds and removes files and directories) */ int App::parse_command(BString command) { command.RemoveAll("\n"); //remove trailing whitespace if(command.Compare("RESET") == 0) { printf("Burn Everything. 8D\n"); status_t err = stop_watching(be_app_messenger); if(err != B_OK) printf("stop_watching error: %s\n",strerror(err)); BDirectory dir = BDirectory(local_path_string); rm_rf(&dir); BString str = BString("/"); //create_local_path wants a remote path create_local_directory(&str); this->recursive_watch(&dir); } else if(command.Compare("FILE ",5) == 0) { BString path, dirpath, partial_path; BPath *bpath; int32 last_space = command.FindLast(" "); command.CopyInto(path,5,last_space - 5); path.CopyInto(dirpath,0,path.FindLast("/")); create_local_directory(&dirpath); //TODO fix watching new dirs bpath = new BPath(db_to_local_filepath(path.String()).String()); BEntry new_file = BEntry(bpath->Path()); if(new_file.InitCheck() && new_file.Exists()) { this->new_paths.AddItem((void*)bpath); } else { this->edited_paths.AddItem((void*)bpath); } printf("create a file at |%s|\n",path.String()); char *argv[3]; argv[0] = "db_get.py"; char not_const1[path.CountChars() + 1]; strcpy(not_const1,path.String()); argv[1] = not_const1; BString tmp = db_to_local_filepath(path.String()); char not_const2[tmp.CountChars() + 1]; //plus one for null strcpy(not_const2,tmp.String()); argv[2] = not_const2; //create/update file //potential problem: takes awhile to do this step // having watching for dir turned off is risky. BString * b = run_python_script(argv,3); delete b; //start watching the new/updated file node_ref nref; new_file = BEntry(db_to_local_filepath(path.String()).String()); new_file.GetNodeRef(&nref); status_t err = watch_node(&nref,B_WATCH_STAT,be_app_messenger); BString parent_rev; command.CopyInto(parent_rev,last_space + 1, command.CountChars() - (last_space+1)); BNode node = BNode(db_to_local_filepath(path.String()).String()); set_parent_rev(&node,&parent_rev); } else if(command.Compare("FOLDER ",7) == 0) { BString path; command.CopyInto(path,7,command.FindLast(" ") - 7); //ignore the creation message BPath bpath = BPath(db_to_local_filepath(path.String()).String()); BPath *actually_exists = find_existing_subpath(&bpath); this->new_paths.AddItem((void*)actually_exists); //create all nescessary dirs in path printf("create a folder at |%s|\n", path.String()); create_local_directory(&path); //start watching the new dir BDirectory existing_dir = BDirectory(actually_exists->Path()); recursive_watch(&existing_dir); } else if(command.Compare("REMOVE ",7) == 0) { //TODO: deal with Dropbox file paths being case-insensitive //which here means all lower case BString path; command.CopyInto(path,7,command.Length() - 7); const char * pathstr = db_to_local_filepath(path.String()).String(); BPath *bpath = new BPath(pathstr); //TODO: check if it exists... this->removed_paths.AddItem((void*)bpath); printf("Remove whatever is at |%s|\n", pathstr); BEntry entry = BEntry(pathstr); status_t err = entry.Remove(); if(err != B_OK) printf("Removal error: %s\n", strerror(err)); } else { printf("Did not recognize command.\n"); return B_ERROR; } return B_OK; }
void ChatWindow::MessageReceived( BMessage * msg ) { switch ( msg->what ) { case IM::SETTINGS_UPDATED: { if (msg->FindString("people_handler", &fPeopleHandler) != B_OK) { fPeopleHandler = kDefaultPeopleHandler; }; RebuildDisplay(); } break; case IM::USER_STOPPED_TYPING: { BMessage im_msg(IM::MESSAGE); im_msg.AddInt32("im_what",IM::USER_STOPPED_TYPING); im_msg.AddRef("contact",&fEntry); fMan->SendMessage(&im_msg); stopSelfTypingTimer(); } break; case IM::USER_STARTED_TYPING: { BMessage im_msg(IM::MESSAGE); im_msg.AddInt32("im_what", IM::USER_STARTED_TYPING); im_msg.AddRef("contact", &fEntry); fMan->SendMessage(&im_msg); startSelfTypingTimer(); } break; case IM::DESKBAR_ICON_CLICKED: { // deskbar icon clicked, move to current workspace and activate SetWorkspaces( 1 << current_workspace() ); Activate(); } break; case IM::ERROR: case IM::MESSAGE: { entry_ref contact; if ( msg->FindRef("contact",&contact) != B_OK ) return; if ( contact != fEntry ) // message not for us, skip it. return; int32 im_what=IM::ERROR; if ( msg->FindInt32("im_what",&im_what) != B_OK ) im_what = IM::ERROR; // int32 old_sel_start, old_sel_end; char timestr[10]; time_t now = time(NULL); strftime(timestr, sizeof(timestr),"[%H:%M]: ", localtime(&now) ); switch ( im_what ) { case IM::STATUS_CHANGED: { // This means we're rebuilding menus we don't rally need to rebuild.. BuildProtocolMenu(); } break; case IM::MESSAGE_SENT: { fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP); BString message; msg->FindString("message", &message); if (message.Compare("/me ", 4) == 0) { fText->Append(_T("* You "), C_ACTION, C_ACTION, F_ACTION); message.Remove(0, 4); fText->Append(message.String(), C_ACTION, C_ACTION, F_ACTION); } else { fText->Append(_T("You say: "), C_OWNNICK, C_OWNNICK, F_TEXT); //fText->Append(msg->FindString("message"), C_TEXT, C_TEXT, F_TEXT); emoticor->AddText(fText,msg->FindString("message"), C_TEXT, F_TEXT,C_TEXT,F_EMOTICON); //by xeD } fText->Append("\n", C_TEXT, C_TEXT, F_TEXT); fText->ScrollToSelection(); } break; case IM::ERROR: { BMessage error; msg->FindMessage("message", &error); int32 error_what = -1; error.FindInt32("im_what", &error_what ); if ( error_what != IM::USER_STARTED_TYPING && error_what != IM::USER_STOPPED_TYPING ) { // ignore messages du to typing fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP); fText->Append("Error: ", C_TEXT, C_TEXT, F_TEXT); fText->Append(msg->FindString("error"), C_TEXT, C_TEXT, F_TEXT); fText->Append("\n", C_TEXT, C_TEXT, F_TEXT); if (!IsActive()) startNotify(); } } break; case IM::MESSAGE_RECEIVED: { if ( msg->FindString("message") == NULL ) { // no message to display, probably opened by user return; } fText->Append(timestr, C_TIMESTAMP, C_TIMESTAMP, F_TIMESTAMP); BString protocol = msg->FindString("protocol"); BString message = msg->FindString("message"); if (protocol.Length() > 0) { fName.ReplaceAll("$protocol$",protocol.String()); } else { fName.ReplaceAll("$protocol$"," "); }; if (message.Compare("/me ", 4) == 0) { fText->Append("* ", C_ACTION, C_ACTION, F_ACTION); fText->Append(fName.String(), C_ACTION, C_ACTION, F_ACTION); fText->Append(" ", C_ACTION, C_ACTION, F_ACTION); message.Remove(0, 4); fText->Append(message.String(), C_ACTION, C_ACTION, F_ACTION); } else { fText->Append(fName.String(), C_OTHERNICK, C_OTHERNICK, F_TEXT); fText->Append(": ", C_OTHERNICK, C_OTHERNICK, F_TEXT); emoticor->AddText(fText,msg->FindString("message"), C_TEXT, F_TEXT,C_TEXT,F_EMOTICON); //by xeD } fText->Append("\n", C_TEXT, C_TEXT, F_TEXT); fText->ScrollToSelection(); if (!IsActive()) startNotify(); stopTypingTimer(); } break; case IM::CONTACT_STARTED_TYPING: { startTypingTimer(); } break; case IM::CONTACT_STOPPED_TYPING: { stopTypingTimer(); } break; } fText->ScrollToSelection(); } break; case SEND_MESSAGE: { if (fInput->TextLength() == 0) return; BMessage im_msg(IM::MESSAGE); im_msg.AddInt32("im_what",IM::SEND_MESSAGE); im_msg.AddRef("contact",&fEntry); im_msg.AddString("message", fInput->Text() ); BMenu *menu = fProtocolMenu->Menu(); if (menu) { IconMenuItem *item = dynamic_cast<IconMenuItem*>(menu->FindMarked()); if ( item ) { BString connection = item->Extra(); if (connection.Length() > 0) { IM::Connection conn(connection.String()); im_msg.AddString("protocol", conn.Protocol()); im_msg.AddString("id", conn.ID()); } } }; if ( fMan->SendMessage(&im_msg) == B_OK ) { fInput->SetText(""); } else { LOG("im_emoclient", liHigh, "Error sending message to im_server"); fText->Append(_T("Error: im_server not running, can't send message\n"), C_TEXT, C_TEXT, F_TEXT); fText->ScrollToSelection(); }; } break; case SHOW_INFO: { BMessage open_msg(B_REFS_RECEIVED); open_msg.AddRef("refs", &fEntry); be_roster->Launch(fPeopleHandler.String(), &open_msg); } break; case VIEW_LOG: { BMessage open(B_REFS_RECEIVED); open.AddRef("refs", &fEntry); be_roster->Launch("application/x-vnd.BeClan.im_binlog_viewer", &open); } break; case VIEW_WEBPAGE: { entry_ref htmlRef; be_roster->FindApp("application/x-vnd.Be.URL.http", &htmlRef); BPath htmlPath(&htmlRef); BMessage argv(B_ARGV_RECEIVED); argv.AddString("argv", htmlPath.Path()); int32 length = -1; char *url = ReadAttribute(BNode(&fEntry), "META:url", &length); if ((url != NULL) && (length > 1)) { url = (char *)realloc(url, (length + 1) * sizeof(char)); url[length] = '\0'; argv.AddString("argv", url); argv.AddInt32("argc", 2); be_roster->Launch(&htmlRef, &argv); } else { LOG("im_emoclient", liMedium, "Contact had no homepage"); }; if (url) free(url); } break; case VIEW_EMOTICONS: { //find emoticon button BView* button = FindView("Emoticons"); BRect buttonBounds = button->Bounds(); //move emoticon window to just below the button BPoint emotLeftBottom = button->ConvertToScreen(buttonBounds.LeftBottom()); popup->SetTargetForItems(this); popup->Go(emotLeftBottom,true,true); } break; case ADD_EMOTICON: { int32 index=msg->FindInt32("index"); BString txt; emoticor->config->menu.FindString("face",index,&txt); txt << " "; fInput->Insert(txt.String()); } break; case EMAIL: { BMessage open_msg(B_REFS_RECEIVED); open_msg.AddRef("refs", &fEntry); // "application/x-vnd.Be-MAIL" be_roster->Launch("text/x-email", &open_msg ); } break; case BLOCK: { IM::Contact contact(fEntry); char status[256]; if ( contact.GetStatus( status, sizeof(status) ) != B_OK ) status[0] = 0; if ( strcmp(status, BLOCKED_TEXT) == 0 ) { // already blocked, unblocked contact.SetStatus(OFFLINE_TEXT); BMessage update_msg(IM::UPDATE_CONTACT_STATUS); update_msg.AddRef("contact", &fEntry); fMan->SendMessage( &update_msg ); } else { if ( contact.SetStatus(BLOCKED_TEXT) != B_OK ) { LOG("im_emoclient", liHigh, "Block: Error setting contact status"); } } } break; case AUTH: { BMessage auth_msg(IM::MESSAGE); auth_msg.AddInt32("im_what", IM::REQUEST_AUTH); auth_msg.AddRef("contact", &fEntry); fMan->SendMessage( &auth_msg ); } break; case B_NODE_MONITOR: { int32 opcode=0; if ( msg->FindInt32("opcode",&opcode) != B_OK ) return; switch ( opcode ) { case B_ENTRY_REMOVED: { // oops. should we close down this window now? // Nah, we'll just disable everything. fInput->MakeEditable(false); fInput->SetViewColor( 198,198,198 ); fInput->Invalidate(); BString title( Title() ); title += " - DELETED!"; SetTitle( title.String() ); } break; case B_ENTRY_MOVED: { entry_ref ref; msg->FindInt32("device", &ref.device); msg->FindInt64("to directory", &ref.directory); ref.set_name( msg->FindString("name") ); fEntry = ref; BEntry entry(&fEntry); if ( !entry.Exists() ) { LOG("im_emoclient", liHigh, "Entry moved: New entry invalid"); } } break; case B_STAT_CHANGED: case B_ATTR_CHANGED: reloadContact(); BuildProtocolMenu(); break; } } break; case kResizeMessage: { BView *view = NULL; msg->FindPointer("view", reinterpret_cast<void**>(&view)); if (dynamic_cast<BScrollView *>(view)) { BPoint point; msg->FindPoint("loc", &point); fResize->MoveTo(fResize->Frame().left, point.y); fTextScroll->ResizeTo(fTextScroll->Frame().Width(), point.y - 1 - fDock->Frame().Height() - 1); fInputScroll->MoveTo(fInputScroll->Frame().left, point.y + 3); fInputScroll->ResizeTo( fInputScroll->Bounds().Width(), fStatusBar->Frame().top - fInputScroll->Frame().top ); fInput->SetTextRect(fInput->Bounds()); fInput->ScrollToSelection(); if ( fSendButton ) { fSendButton->MoveTo(fSendButton->Frame().left, point.y + 3); fSendButton->ResizeTo( fSendButton->Bounds().Width(), fStatusBar->Frame().top - fSendButton->Frame().top ); } }; } break; case B_MOUSE_WHEEL_CHANGED: { fText->MessageReceived(msg); } break; case B_COPY: { int32 start = 0; int32 end = 0; fInput->GetSelection(&start, &end); //printf("%ld - > %ld\n", start, end); } break; case B_SIMPLE_DATA: { entry_ref ref; BNode node; // attr_info info; for (int i = 0; msg->FindRef("refs", i, &ref) == B_OK; i++) { node = BNode(&ref); char *type = ReadAttribute(node, "BEOS:TYPE"); if (strcmp(type, "application/x-person") == 0) { char *name = ReadAttribute(node, "META:name"); char *nickname = ReadAttribute(node, "META:nickname"); char connection[100]; IM::Contact con(ref); con.ConnectionAt(0, connection); if (fInput->TextLength() > 0) fInput->Insert("\n"); fInput->Insert(name); fInput->Insert(" ("); fInput->Insert(nickname); fInput->Insert("): "); fInput->Insert(connection); free(name); free(nickname); }; free(type); }; fInput->ScrollToOffset(fInput->TextLength()); } break; case CLEAR_TYPING: stopTypingTimer(); break; case PROTOCOL_SELECTED: { // a protocol has been selected. Since BMenuField doesn't resize until later, // we have to wait 1000us before actually responding to the change, see below if ( fProtocolHack ) delete fProtocolHack; BMessage protoHack(PROTOCOL_SELECTED2); fProtocolHack = new BMessageRunner( BMessenger(this), &protoHack, 1000, 1 ); } break; case PROTOCOL_SELECTED2: // do what should be done on protocol change fStatusBar->PositionViews(); fInfoView->ResizeTo( fStatusBar->Bounds().Width() - fInfoView->Frame().left, fInfoView->Bounds().Height() ); break; default: BWindow::MessageReceived(msg); } }