void TBarView::ChangeState(int32 state, bool vertical, bool left, bool top) { bool vertSwap = (fVertical != vertical); bool leftSwap = (fLeft != left); fState = state; fVertical = vertical; fLeft = left; fTop = top; BRect screenFrame = (BScreen(Window())).Frame(); PlaceBeMenu(); PlaceTray(vertSwap, leftSwap, screenFrame); // We need to keep track of what apps are expanded. BList expandedItems; BString* signature = NULL; if (fVertical && Expando() && static_cast<TBarApp*>(be_app)->Settings()->superExpando) { // Get a list of the signatures of expanded apps. Can't use // team_id because there can be more than one team per application if (fVertical && Expando() && vertical && fExpando) { for (int index = 0; index < fExpando->CountItems(); index++) { TTeamMenuItem* item = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(index)); if (item != NULL && item->IsExpanded()) { signature = new BString(item->Signature()); expandedItems.AddItem((void*)signature); } } } } PlaceApplicationBar(screenFrame); SizeWindow(screenFrame); PositionWindow(screenFrame); Window()->UpdateIfNeeded(); // Re-expand those apps. if (expandedItems.CountItems() > 0) { for (int sigIndex = expandedItems.CountItems(); sigIndex-- > 0;) { signature = static_cast<BString*>(expandedItems.ItemAt(sigIndex)); if (signature == NULL) continue; // Start at the 'bottom' of the list working up. // Prevents being thrown off by expanding items. for (int teamIndex = fExpando->CountItems(); teamIndex-- > 0;) { TTeamMenuItem* item = dynamic_cast<TTeamMenuItem*>(fExpando->ItemAt(teamIndex)); if (item != NULL && !signature->Compare(item->Signature())) { item->ToggleExpandState(false); break; } } } // Clean up expanded signature list. while (!expandedItems.IsEmpty()) { delete static_cast<BString*>(expandedItems.RemoveItem((int32)0)); } fExpando->SizeWindow(); } Invalidate(); }
void PeepsWindow::MessageReceived(BMessage *msg) { switch(msg->what) { case B_ABOUT_REQUESTED: { be_app->PostMessage(msg); break; } case M_RUN_TOOL: { BString sig; if(msg->FindString("signature",&sig)==B_OK) { if(strcmp(sig.String(),"application/x-vnd.wgp-PeopleMover")==0) { be_roster->Launch(sig.String()); break; } // Get the filename for the currently-selected person int32 selection=fPeopleList->CurrentSelection(); if(selection<0) break; PeepsListItem *peepsitem=(PeepsListItem*)fPeopleList->ItemAt(selection); if(!peepsitem || peepsitem->IsGroup()) break; PersonItem *personitem=(PersonItem*)peepsitem; PersonData *persondata=personitem->GetData(); if(!persondata) break; entry_ref ref=persondata->FileRef(); BPath path(&ref); char *launchv[1]; launchv[0]=new char[255]; sprintf(launchv[0],"%s",path.Path()); be_roster->Launch(sig.String(),1,launchv,NULL); delete [] launchv[0]; } break; } case M_SHOW_ACTIONS: { uint32 buttons; BPoint pt; fPeopleList->GetMouse(&pt,&buttons,false); pt.x=(pt.x>5)?pt.x-5:0; pt.y=(pt.y>5)?pt.y-5:0; fPeopleList->ShowContextMenu(fPeopleList->ConvertToScreen(pt)); break; } case M_BITMAP_REMOVED: case M_PHOTO_MODIFIED: { fPeopleList->SaveImageData(); break; } case B_REFS_RECEIVED: case B_SIMPLE_DATA: { entry_ref ref; if(msg->FindRef("refs",0,&ref)==B_OK) { if(!IsPerson(ref)) { // Might be an image dropped on the photo view. find out which child is the // target BPoint pt; if(msg->FindPoint("_drop_offset",&pt)!=B_OK) break; BView *target=FindView(pt); if(!target || strcmp(target->Name(),"photoview")!=0) break; // This will set the image, if possible target->MessageReceived(msg); // Save the image data to a real file and attach the Person attributes // to it fPeopleList->SaveImageData(); } // Offer to move/copy file if not in People directory BDirectory dir,peopledir("/boot/home/people"); BEntry entry(&ref); entry.GetParent(&dir); if(dir!=peopledir) { BString refname(ref.name); BString errstr=TRANSLATE("%s is not currently stored in the People folder. Mr. Peeps! will not" " see it on startup unless it is stored there. Would you like to move it" " there?"); char errmsg[errstr.CountChars() - 2 + refname.CountChars() + 1]; sprintf(errmsg,errstr.String(),refname.String()); BAlert *alert=new BAlert("Mr. Peeps!",errmsg,TRANSLATE("Move"),TRANSLATE("Don't Move")); if(alert->Go()==0) { entry.MoveTo(&peopledir); entry.GetRef(&ref); } } if(!SelectPerson(ref)) AddPerson(ref,true); } break; } case M_PREV_ITEM: { if(fPeopleList->CountItems()==0) break; int32 selection=fPeopleList->CurrentSelection(); if(!fPeopleList->IsFocus()) { fPeopleList->MakeFocus(true); PeepsListItem *pitem=(PeepsListItem*)fPeopleList->ItemAt(selection); if(!pitem->IsGroup()) { fPeopleList->SyncData((PersonItem*)pitem); // fPeopleList->SaveData(); } fPeopleList->SaveData(); } if(selection>=0) { if(selection>0) fPeopleList->Select(selection-1); } else { fPeopleList->Select(0L); } break; } case M_NEXT_ITEM: { if(fPeopleList->CountItems()==0) break; int32 selection=fPeopleList->CurrentSelection(); if(!fPeopleList->IsFocus()) { fPeopleList->MakeFocus(true); PeepsListItem *pitem=(PeepsListItem*)fPeopleList->ItemAt(selection); if(!pitem->IsGroup()) { fPeopleList->SyncData((PersonItem*)pitem); // fPeopleList->SaveData(); } fPeopleList->SaveData(); } if(selection==fPeopleList->CountItems()-1 || selection<0) fPeopleList->Select(fPeopleList->CountItems()-1); else fPeopleList->Select(selection+1); break; } case M_MOD_DATA: case M_SAVE: { fPeopleList->SyncData(NULL); fPeopleList->SaveData(); break; } case M_ADD_PERSON: { entry_ref ref; status_t stat=CreatePerson(&ref); if(stat==B_FILE_EXISTS) { for(int32 i=0;i<gPeopleData.CountItems(); i++) { PersonData *pdata=(PersonData*)gPeopleData.ItemAt(i); if(BString(TRANSLATE("New Person")).ICompare(pdata->Name())==0) { int32 selection=fPeopleList->CurrentSelection(); if(selection>=0) { PeepsListItem *peepsitem=(PeepsListItem*)fPeopleList->ItemAt(selection); if(peepsitem && !peepsitem->IsGroup()) fPeopleList->Collapse(fPeopleList->Superitem(peepsitem)); } PersonItem *pitem=pdata->InstanceAt(0); GroupItem *gitem=(GroupItem*)fPeopleList->Superitem(pitem); if(!gitem->IsExpanded()) fPeopleList->Expand(gitem); fPeopleList->Select(fPeopleList->IndexOf(pitem)); fPeopleList->ScrollToSelection(); break; } } } else { // Add the current group to the New Person's file so that we end up staying // in the current group. if(stat==B_OK) { int32 selection=fPeopleList->CurrentSelection(); BString groupstr(TRANSLATE("Ungrouped")); if(selection>=0) { PeepsListItem *currentitem=(PeepsListItem*)fPeopleList->ItemAt(selection); if(currentitem->IsGroup()) groupstr=currentitem->Name(); else groupstr=((PersonItem*)currentitem)->Group(); } PersonData *pdata=new PersonData(ref); pdata->SetGroup(groupstr.String()); pdata->SetName(TRANSLATE("New Person")); pdata->SaveToFile(); delete pdata; AddPerson(ref,true); SortList(); SelectPerson(TRANSLATE("New Person")); dataview->SetFirstFieldFocus(); } } break; } case M_DELETE_PERSON: { int32 selection=fPeopleList->CurrentSelection(); if(selection<0) break; PeepsListItem *item=(PeepsListItem*)fPeopleList->ItemAt(selection); if(item->IsGroup()) DeleteGroup((GroupItem*)item); else { DeletePerson(((PersonItem*)item)->GetData()); } break; } case M_DISABLE_DELETE: { BMenuItem *item=fPeopleMenu->FindItem(TRANSLATE("Move To Trash")); if(item) item->SetEnabled(false); break; } case M_ENABLE_DELETE: { BMenuItem *item=fPeopleMenu->FindItem(TRANSLATE("Move To Trash")); if(item) item->SetEnabled(true); break; } case M_SET_LANGUAGE: { // Restart MrPeeps! gRestartApp=true; int32 language; if(msg->FindInt32("index",&language)!=B_OK) break; BMenuItem *item = fLanguageMenu->ItemAt(language); if(!item) break; fLocale = item->Label(); WriteLocaleSettings(); be_app->PostMessage(B_QUIT_REQUESTED); break; } case M_HANDLE_NO_SELECTION: { // This is the initial case. No selection means quite a few different // menu items are disabled. fTabMenu->SetEnabled(false); fEditMenu->SetEnabled(false); if(fToolPeopleAtAGlance) fToolPeopleAtAGlance->SetEnabled(false); if(fToolVCardExport) fToolVCardExport->SetEnabled(false); UpdateActions(true); break; } case M_HANDLE_GROUP_SELECTION: { // This is the initial case. No selection means quite a few different // menu items are disabled. fTabMenu->SetEnabled(false); fEditMenu->SetEnabled(true); if(fToolPeopleAtAGlance) fToolPeopleAtAGlance->SetEnabled(false); if(fToolVCardExport) fToolVCardExport->SetEnabled(false); UpdateActions(true); break; } case M_HANDLE_PERSON_SELECTION: { // This is the initial case. No selection means quite a few different // menu items are disabled. fTabMenu->SetEnabled(true); fEditMenu->SetEnabled(true); if(fToolPeopleAtAGlance) fToolPeopleAtAGlance->SetEnabled(true); if(fToolVCardExport) fToolVCardExport->SetEnabled(true); UpdateActions(false); break; } case M_SEND_PERSONAL_EMAIL: { if(dataview->Email()) { BMessage *emailmsg=new BMessage(M_SEND_EMAIL); emailmsg->AddString("address",dataview->Email()); be_app->PostMessage(emailmsg); } break; } case M_SEND_WORK_EMAIL: { if(dataview->WorkEmail()) { BMessage *emailmsg=new BMessage(M_SEND_EMAIL); emailmsg->AddString("address",dataview->WorkEmail()); be_app->PostMessage(emailmsg); } break; } case M_SEND_ALT_EMAIL: { if(dataview->Email3()) { BMessage *emailmsg=new BMessage(M_SEND_EMAIL); emailmsg->AddString("address",dataview->Email3()); be_app->PostMessage(emailmsg); } break; } case M_BROWSE_WWW_HOME: { if(dataview->URL()) { BMessage *wwwmsg=new BMessage(M_LAUNCH_BROWSER); wwwmsg->AddString("address",dataview->URL()); be_app->PostMessage(wwwmsg); } break; } case M_BROWSE_WWW_WORK: { if(dataview->WorkURL()) { BMessage *wwwmsg=new BMessage(M_LAUNCH_BROWSER); wwwmsg->AddString("address",dataview->WorkURL()); be_app->PostMessage(wwwmsg); } break; } case M_BROWSE_WWW_ALT: { if(dataview->OtherURL()) { BMessage *wwwmsg=new BMessage(M_LAUNCH_BROWSER); wwwmsg->AddString("address",dataview->OtherURL()); be_app->PostMessage(wwwmsg); } break; } case M_TAB_1: { fPeopleList->SyncData(); fPeopleList->SaveData(); dataview->ShowTab(0); if(!fPeopleList->IsFocus()) dataview->SetFirstFieldFocus(); break; } case M_TAB_2: { fPeopleList->SyncData(); fPeopleList->SaveData(); dataview->ShowTab(1); if(!fPeopleList->IsFocus()) dataview->SetFirstFieldFocus(); break; } case M_TAB_3: { fPeopleList->SyncData(); fPeopleList->SaveData(); dataview->ShowTab(2); if(!fPeopleList->IsFocus()) dataview->SetFirstFieldFocus(); break; } case M_TAB_4: { fPeopleList->SyncData(); fPeopleList->SaveData(); dataview->ShowTab(3); if(!fPeopleList->IsFocus()) dataview->SetFirstFieldFocus(); break; } case M_TAB_5: { fPeopleList->SyncData(); fPeopleList->SaveData(); dataview->ShowTab(4); if(!fPeopleList->IsFocus()) dataview->SetFirstFieldFocus(); break; } case M_UNDO: { dataview->UndoField(); break; } case M_CUT: { dataview->CutField(); break; } case M_COPY: { dataview->CopyField(); break; } case M_PASTE: { dataview->PasteField(); break; } case B_NODE_MONITOR: { HandleNodeMonitoring(msg); break; } default: { BWindow::MessageReceived(msg); break; } } }
/* EEAAAAAAAGHH! My new code uses the current time from the transport * to add signature information to the params. God I hope this is OK. */ int32 AmInputQueue::PerformLoop() { while (mPerformAvail >= B_OK) { while (acquire_sem(mPerformAvail) == B_INTERRUPTED) ; BList items; if (mPerformLock.Lock()) { items = mPerformItems; mPerformItems.MakeEmpty(); mPerformLock.Unlock(); } am_filter_params params; am_filter_params* p = 0; AmSongRef songRef = AmGlobals().SongRef(mSong); if (songRef.IsValid()) { for (int32 i=0; i<items.CountItems(); i++) { record_item* ri = (record_item*)items.ItemAt(i); if (!ri) continue; { // READ SONG BLOCK #ifdef AM_TRACE_LOCKS printf("AmInputQueue::PerformLoop() read lock\n"); fflush(stdout); #endif const AmSong* song = songRef.ReadLock(); const AmTrack* track = song ? song->Track(ri->track) : NULL; if (track) { p = 0; AmEvent* signatures = 0; AmTime currentTime = song->Transport().CurrentTime(); if (currentTime >= 0) { signatures = song->PlaybackList(currentTime, currentTime, PLAYBACK_NO_PERFORMANCE | PLAYBACK_NO_TEMPO | PLAYBACK_RAW_CONTEXT); if (signatures) { // printf("Sigs: \n"); signatures->PrintChain(); params.cur_signature = dynamic_cast<AmSignature*>(signatures); } else params.cur_signature = 0; p = ¶ms; } // Run events through input filters ri->events = ArpExecFilters(ri->events, REALTIME_EXEC_TYPE, false, p, 0, 0, 0, signatures); if (ri->events) ri->events = ri->events->HeadEvent(); // Run result through output filters. AmFilterHolderI* h = track->Filter(OUTPUT_PIPELINE); if (h) { AmEvent* pos = ri->events; while (pos) { if (!pos->NextFilter()) pos->SetNextFilter(h); pos = pos->NextEvent(); } ri->events = ArpExecFilters(ri->events, REALTIME_EXEC_TYPE, false, p, 0, 0, 0, signatures); if (ri->events) ri->events = ri->events->HeadEvent(); } song->Transport().Merge(ri->events); ri->events = NULL; } params.cur_signature = 0; songRef.ReadUnlock(song); // END READ SONG BLOCK } if (ri->events) ri->events->DeleteChain(); delete ri; } } } return B_OK; }
int32 AmInputQueue::RecordLoop() { while (mRecordAvail >= B_OK) { while (acquire_sem(mRecordAvail) == B_INTERRUPTED) ; BList items; if (mRecordLock.Lock()) { items = mRecordItems; mRecordItems.MakeEmpty(); mRecordLock.Unlock(); } AmSongRef songRef = AmGlobals().SongRef(mSong); if (songRef.IsValid()) { for (int32 i=0; i<items.CountItems(); i++) { record_item* ri = (record_item*)items.ItemAt(i); if (!ri) continue; { // READ SONG BLOCK #ifdef AM_TRACE_LOCKS printf("AmInputQueue::RecordLoop() read lock\n"); fflush(stdout); #endif const AmSong* song = songRef.ReadLock(); if (song) { ri->events = ArpExecFilters(ri->events, REALTIME_EXEC_TYPE, false); if (ri->events) ri->events = ri->events->HeadEvent(); songRef.ReadUnlock(song); } // END READ SONG BLOCK } { // WRITE SONG BLOCK AmSong* song = songRef.WriteLock(); if (song) { #if 1 /* New mechanism -- all events should have been supplied * a track by the last filter they went through. So, * record to the requested track. This wouldn't be * necessary if we had a full architecture -- that is, * the tracks were just another filter in the pipeline. */ AmTrack* track = 0; AmEvent* e = 0; AmEvent* head = ri->events; while ((e = _get_record_t_and_e(head, song, &head, &track)) != 0) { if (track) track->RecordEvents(e); else e->DeleteChain(); } if (head) head->DeleteChain(); ri->events = 0; #endif #if 0 AmTrack* track = song->Track(ri->track); if (track && ri->events) { track->RecordEvents(ri->events); ri->events = NULL; } #endif songRef.WriteUnlock(song); } // END WRITE SONG BLOCK } if (ri->events) ri->events->DeleteChain(); delete ri; } } } return B_OK; }
void update_preferred_app_menu(BMenu* menu, BMimeType* type, uint32 what, const char* preferredFrom) { // clear menu (but leave the first entry, ie. "None") for (int32 i = menu->CountItems(); i-- > 1;) { delete menu->RemoveItem(i); } // fill it again menu->ItemAt(0)->SetMarked(true); BMessage applications; if (type == NULL || type->GetSupportingApps(&applications) != B_OK) return; char preferred[B_MIME_TYPE_LENGTH]; if (type->GetPreferredApp(preferred) != B_OK) preferred[0] = '\0'; int32 lastFullSupport; if (applications.FindInt32("be:sub", &lastFullSupport) != B_OK) lastFullSupport = -1; BList subList; BList superList; const char* signature; int32 i = 0; while (applications.FindString("applications", i, &signature) == B_OK) { BMenuItem* item = create_application_item(signature, what); if (i < lastFullSupport) subList.AddItem(item); else superList.AddItem(item); i++; } // sort lists subList.SortItems(compare_menu_items); superList.SortItems(compare_menu_items); // add lists to the menu if (subList.CountItems() != 0 || superList.CountItems() != 0) menu->AddSeparatorItem(); for (int32 i = 0; i < subList.CountItems(); i++) { menu->AddItem((BMenuItem*)subList.ItemAt(i)); } // Add type separator if (superList.CountItems() != 0 && subList.CountItems() != 0) menu->AddSeparatorItem(); for (int32 i = 0; i < superList.CountItems(); i++) { menu->AddItem((BMenuItem*)superList.ItemAt(i)); } // make items unique and select current choice bool lastItemSame = false; const char* lastSignature = NULL; BMenuItem* last = NULL; BMenuItem* select = NULL; for (int32 index = 0; index < menu->CountItems(); index++) { BMenuItem* item = menu->ItemAt(index); if (item == NULL) continue; if (item->Message() == NULL || item->Message()->FindString("signature", &signature) != B_OK) continue; if ((preferredFrom == NULL && !strcasecmp(signature, preferred)) || (preferredFrom != NULL && !strcasecmp(signature, preferredFrom))) { select = item; } if (last == NULL || strcmp(last->Label(), item->Label())) { if (lastItemSame) add_signature(last, lastSignature); lastItemSame = false; last = item; lastSignature = signature; continue; } lastItemSame = true; add_signature(last, lastSignature); last = item; lastSignature = signature; } if (lastItemSame) add_signature(last, lastSignature); if (select != NULL) { // We don't select the item earlier, so that the menu field can // pick up the signature as well as label. select->SetMarked(true); } else if ((preferredFrom == NULL && preferred[0]) || (preferredFrom != NULL && preferredFrom[0])) { // The preferred application is not an application that support // this file type! BMenuItem* item = create_application_item(preferredFrom ? preferredFrom : preferred, what); menu->AddSeparatorItem(); menu->AddItem(item); item->SetMarked(item); } }
void Win::UrlTypedHandler( bool show_all ) { // printf( "Win::UrlTypedHandler()\n" ); // get the stripped list from GlobalHistory BList* slist = ( ( App* )be_app )->GetGlobalHistory()->GetStrippedList(); // create the matching urls list BList* list = new BList( 0 ); BString typed_url; // the typed url BString cached_url; // the cached url BString cached_url_proto( "" ); // protocol of the cached url if( show_all == true ) typed_url.SetTo( "" ); else { typed_url.SetTo( navview->urlview->Text() ); typed_url.ToLower(); } // printf( " typed_url: %s length: %ld\n", typed_url.String(), typed_url.Length() ); int32 count = slist->CountItems(); for( int32 i = 0; i < count; i++ ) { GlobalHistoryItem* item = ( GlobalHistoryItem* )slist->ItemAt( i ); if( item != NULL ) { cached_url.SetTo( item->Text() ); // printf( " cached_url: %s\n", cached_url.String() ); if( typed_url.Length() != 0 ) { // if the typed url matches beginning of cached url, add it if( strncmp( cached_url.String(), typed_url.String(), typed_url.Length() ) == 0 ) { list->AddItem( new BStringItem( cached_url.String() ) ); } else { // if the urls dont match, take away the protocol of the cached url if( cached_url.FindFirst( "://" ) > 0 ) { cached_url.MoveInto( cached_url_proto, 0, cached_url.FindFirst( "://" ) + 3 ); } // if the urls fit now if( strncmp( cached_url.String(), typed_url.String(), typed_url.Length() ) == 0 ) { // add the missing proto again if( cached_url_proto.Length() != 0 ) cached_url.Prepend( cached_url_proto ); list->AddItem( new BStringItem( cached_url.String() ) ); } else { // if they still don't fit, remove 'www.' from cached url if( cached_url.FindFirst( "www." ) == 0 ) { cached_url.Remove( 0, 4 ); } // check if they finally fit if( strncmp( cached_url.String(), typed_url.String(), typed_url.Length() ) == 0 ) { // add missing 'www.' and proto cached_url.Prepend( "www." ); if( cached_url_proto.Length() != 0 ) cached_url.Prepend( cached_url_proto ); list->AddItem( new BStringItem( cached_url.String() ) ); } } cached_url_proto.SetTo( "" ); } } else { list->AddItem( new BStringItem( cached_url.String() ) ); } } // if( item != NULL ) } // delete slist ( not needed anymore ) for( int32 i = 0; i < count; i++ ) { GlobalHistoryItem* item = ( GlobalHistoryItem* )slist->ItemAt( i ); if( item != NULL ) { slist->RemoveItem( item ); delete item; } } delete slist; // add the urlpopupwindow if needed if( list->CountItems() > 0 ) { CreateUrlPopUpWindow(); // add the list urlpopupwindow->Lock(); urlpopupwindow->ListToDisplay( list ); urlpopupwindow->Unlock(); } else { if( urlpopupwindow != NULL ) { urlpopupwindow->Lock(); urlpopupwindow->Quit(); urlpopupwindow = NULL; } } }
status_t TerminalThemesAddon::ApplyThemeHaiku(BMessage &theme, uint32 flags) { BMessage termpref; BMessage lines; status_t err; struct termprefs tp; int32 ival; rgb_color color; BString s; err = MyMessage(theme, termpref); if (err) return err; if (termpref.FindInt32(TP_COLS, &ival) < B_OK) ival = 80; s = ""; s << ival; lines.AddString(PREF_COLS, s.String()); if (termpref.FindInt32(TP_ROWS, &ival) < B_OK) ival = 25; s = ""; s << ival; lines.AddString(PREF_ROWS, s.String()); if (termpref.FindInt32(TP_TABWIDTH, &ival) >= B_OK) { //XXX: handle that ? } BFont tFont; tp.p.font_size = 12; strcpy(tp.p.font, "Courier10 BT/Roman"); if (FindFont(termpref, TP_FONT, 0, &tFont) == B_OK) { font_family ff; font_style fs; tFont.GetFamilyAndStyle(&ff, &fs); s = ""; s << ff; lines.AddString(PREF_HALF_FONT_FAMILY, s.String()); s = ""; s << fs; lines.AddString(PREF_HALF_FONT_STYLE, s.String()); s = ""; s << tFont.Size(); lines.AddString(PREF_HALF_FONT_SIZE, s.String()); } if (FindRGBColor(termpref, TP_BG, 0, &color) != B_OK) color = make_color(255,255,255,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_TEXT_BACK_COLOR, s.String()); if (FindRGBColor(termpref, TP_FG, 0, &color) != B_OK) color = make_color(0,0,0,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_TEXT_FORE_COLOR, s.String()); if (FindRGBColor(termpref, TP_CURBG, 0, &color) != B_OK) color = make_color(255,255,255,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_CURSOR_BACK_COLOR, s.String()); if (FindRGBColor(termpref, TP_CURFG, 0, &color) != B_OK) color = make_color(0,0,0,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_CURSOR_FORE_COLOR, s.String()); if (FindRGBColor(termpref, TP_SELBG, 0, &color) != B_OK) color = make_color(0,0,0,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_SELECT_BACK_COLOR, s.String()); if (FindRGBColor(termpref, TP_SELFG, 0, &color) != B_OK) color = make_color(255,255,255,255); s = ""; s << color.red << ", " << color.green << ", " << color.blue; lines.AddString(PREF_SELECT_FORE_COLOR, s.String()); /* XXX: handle PREF_IM_FORE_COLOR PREF_IM_BACK_COLOR PREF_IM_SELECT_COLOR */ if (termpref.FindInt32(TP_ENCODING, &ival) != B_OK) ival = 0; // UTF-8 s = ""; s << ival; //XXX: shouldn't really be touched... //lines.AddString(, s.String()); if (flags & UI_THEME_SETTINGS_SAVE && AddonFlags() & Z_THEME_ADDON_DO_SAVE) { SaveHaikuTerminalSettings(lines); } if (flags & UI_THEME_SETTINGS_APPLY && AddonFlags() & Z_THEME_ADDON_DO_APPLY) { BList teamList; app_info ainfo; int32 count, i; be_roster->GetAppList(&teamList); count = teamList.CountItems(); for (i = 0; i < count; i++) { if (be_roster->GetRunningAppInfo((team_id)(teamList.ItemAt(i)), &ainfo) == B_OK) { if (!strcmp(ainfo.signature, kHaikuTerminalAppSig)) { err = B_OK; //XXX: WRITEME /* BMessage msg(MSG_R5_SET_PREF); BMessenger msgr(NULL, ainfo.team); tp.x = 0; tp.y = 0; //msg.AddData("", 'UBYT', &(tp.p), sizeof(struct tpref)); msg.AddData("", 'UBYT', &(tp), sizeof(struct termprefs)); msg.AddSpecifier("Window", 0L); err = msgr.SendMessage(&msg); */ } } } } return B_OK; }
status_t TerminalThemesAddon::ApplyThemeR5(BMessage &theme, uint32 flags) { BMessage termpref; status_t err; struct termprefs tp; err = MyMessage(theme, termpref); if (err) return err; tp.magic = TP_MAGIC; tp.version = TP_VERSION; tp.x = 0; // don't open at specific coords tp.y = 0; if (termpref.FindInt32(TP_COLS, (int32 *)&tp.p.cols) != B_OK) tp.p.cols = 80; if (termpref.FindInt32(TP_ROWS, (int32 *)&tp.p.rows) != B_OK) tp.p.rows = 25; if (termpref.FindInt32(TP_TABWIDTH, (int32 *)&tp.p.tab_width) != B_OK) tp.p.tab_width = 8; BFont tFont; tp.p.font_size = 12; strcpy(tp.p.font, "Courier10 BT/Roman"); if (FindFont(termpref, TP_FONT, 0, &tFont) == B_OK) { font_family ff; font_style fs; tFont.GetFamilyAndStyle(&ff, &fs); strcpy(tp.p.font, ff); strcat(tp.p.font, "/"); strcat(tp.p.font, fs); tp.p.font_size = (uint32)tFont.Size(); } tp.p.cursor_blink_rate = 1000000; tp.p.refresh_rate = 0; if (FindRGBColor(termpref, TP_BG, 0, &tp.p.bg) != B_OK) tp.p.bg = make_color(255,255,255,255); if (FindRGBColor(termpref, TP_FG, 0, &tp.p.fg) != B_OK) tp.p.fg = make_color(0,0,0,255); if (FindRGBColor(termpref, TP_CURBG, 0, &tp.p.curbg) != B_OK) tp.p.curbg = make_color(255,255,255,255); if (FindRGBColor(termpref, TP_CURFG, 0, &tp.p.curfg) != B_OK) tp.p.curfg = make_color(0,0,0,255); if (FindRGBColor(termpref, TP_SELBG, 0, &tp.p.selbg) != B_OK) tp.p.selbg = make_color(0,0,0,255); if (FindRGBColor(termpref, TP_SELFG, 0, &tp.p.selfg) != B_OK) tp.p.selfg = make_color(255,255,255,255); if (termpref.FindInt32(TP_ENCODING, (int32 *)&tp.p.encoding) != B_OK) tp.p.encoding = 0; // UTF-8 if (flags & UI_THEME_SETTINGS_SAVE && AddonFlags() & Z_THEME_ADDON_DO_SAVE) { BPath pTermPref; if (find_directory(B_USER_SETTINGS_DIRECTORY, &pTermPref) < B_OK) return EINVAL; pTermPref.Append("Terminal"); BFile fTermPref(pTermPref.Path(), B_WRITE_ONLY|B_CREATE_FILE|B_ERASE_FILE); if (fTermPref.InitCheck() != B_OK) { return fTermPref.InitCheck(); } fTermPref.Write(&tp, sizeof(struct termprefs)); BNodeInfo ni(&fTermPref); if (ni.InitCheck() == B_OK) ni.SetType("application/x-vnd.Be-pref"); } if (flags & UI_THEME_SETTINGS_APPLY && AddonFlags() & Z_THEME_ADDON_DO_APPLY) { BList teamList; app_info ainfo; int32 count, i; be_roster->GetAppList(&teamList); count = teamList.CountItems(); for (i = 0; i < count; i++) { if (be_roster->GetRunningAppInfo((team_id)(teamList.ItemAt(i)), &ainfo) == B_OK) { if (!strcmp(ainfo.signature, kBeOSTerminalAppSig)) { err = B_OK; BMessage msg(MSG_R5_SET_PREF); BMessenger msgr(NULL, ainfo.team); tp.x = 0; tp.y = 0; //msg.AddData("", 'UBYT', &(tp.p), sizeof(struct tpref)); msg.AddData("", 'UBYT', &(tp), sizeof(struct termprefs)); msg.AddSpecifier("Window", 0L); err = msgr.SendMessage(&msg); } } } } return B_OK; }
_EXPORT ssize_t utf8_to_rfc2047 (char **bufp, ssize_t length, uint32 charset, char encoding) { struct word { BString originalWord; BString convertedWord; bool needsEncoding; // Convert the word from UTF-8 to the desired character set. The // converted version also includes the escape codes to return to ASCII // mode, if relevant. Also note if it uses unprintable characters, // which means it will need that special encoding treatment later. void ConvertWordToCharset (uint32 charset) { int32 state = 0; int32 originalLength = originalWord.Length(); int32 convertedLength = originalLength * 5 + 1; char *convertedBuffer = convertedWord.LockBuffer (convertedLength); mail_convert_from_utf8 (charset, originalWord.String(), &originalLength, convertedBuffer, &convertedLength, &state); for (int i = 0; i < convertedLength; i++) { if ((convertedBuffer[i] & (1 << 7)) || (convertedBuffer[i] >= 0 && convertedBuffer[i] < 32)) { needsEncoding = true; break; } } convertedWord.UnlockBuffer (convertedLength); }; }; struct word *currentWord; BList words; // Break the header into words. White space characters (including tabs and // newlines) separate the words. Each word includes any space before it as // part of the word. Actually, quotes and other special characters // (",()<>@) are treated as separate words of their own so that they don't // get encoded (because MIME headers get the quotes parsed before character // set unconversion is done). The reader is supposed to ignore all white // space between encoded words, which can be inserted so that older mail // parsers don't have overly long line length problems. const char *source = *bufp; const char *bufEnd = *bufp + length; const char *specialChars = "\"()<>@,"; while (source < bufEnd) { currentWord = new struct word; currentWord->needsEncoding = false; int wordEnd = 0; // Include leading spaces as part of the word. while (source + wordEnd < bufEnd && isspace (source[wordEnd])) wordEnd++; if (source + wordEnd < bufEnd && strchr (specialChars, source[wordEnd]) != NULL) { // Got a quote mark or other special character, which is treated as // a word in itself since it shouldn't be encoded, which would hide // it from the mail system. wordEnd++; } else { // Find the end of the word. Leave wordEnd pointing just after the // last character in the word. while (source + wordEnd < bufEnd) { if (isspace(source[wordEnd]) || strchr (specialChars, source[wordEnd]) != NULL) break; if (wordEnd > 51 /* Makes Base64 ISO-2022-JP "word" a multiple of 4 bytes */ && 0xC0 == (0xC0 & (unsigned int) source[wordEnd])) { // No English words are that long (46 is the longest), // break up what is likely Asian text (which has no spaces) // at the start of the next non-ASCII UTF-8 character (high // two bits are both ones). Note that two encoded words in // a row get joined together, even if there is a space // between them in the final output text, according to the // standard. Next word will also be conveniently get // encoded due to the 0xC0 test. currentWord->needsEncoding = true; break; } wordEnd++; } } currentWord->originalWord.SetTo (source, wordEnd); currentWord->ConvertWordToCharset (charset); words.AddItem(currentWord); source += wordEnd; } // Combine adjacent words which contain unprintable text so that the // overhead of switching back and forth between regular text and specially // encoded text is reduced. However, the combined word must be shorter // than the maximum of 75 bytes, including character set specification and // all those delimiters (worst case 22 bytes of overhead). struct word *run; for (int32 i = 0; (currentWord = (struct word *) words.ItemAt (i)) != NULL; i++) { if (!currentWord->needsEncoding) continue; // No need to combine unencoded words. for (int32 g = i+1; (run = (struct word *) words.ItemAt (g)) != NULL; g++) { if (!run->needsEncoding) break; // Don't want to combine encoded and unencoded words. if ((currentWord->convertedWord.Length() + run->convertedWord.Length() <= 53)) { currentWord->originalWord.Append (run->originalWord); currentWord->ConvertWordToCharset (charset); words.RemoveItem(g); delete run; g--; } else // Can't merge this word, result would be too long. break; } } // Combine the encoded and unencoded words into one line, doing the // quoted-printable or base64 encoding. Insert an extra space between // words which are both encoded to make word wrapping easier, since there // is normally none, and you're allowed to insert space (the receiver // throws it away if it is between encoded words). BString rfc2047; bool previousWordNeededEncoding = false; const char *charset_dec = "none-bug"; for (int32 i = 0; mail_charsets[i].charset != NULL; i++) { if (mail_charsets[i].flavor == charset) { charset_dec = mail_charsets[i].charset; break; } } while ((currentWord = (struct word *)words.RemoveItem(0L)) != NULL) { if ((encoding != quoted_printable && encoding != base64) || !currentWord->needsEncoding) { rfc2047.Append (currentWord->convertedWord); } else { // This word needs encoding. Try to insert a space between it and // the previous word. if (previousWordNeededEncoding) rfc2047 << ' '; // Can insert as many spaces as you want between encoded words. else { // Previous word is not encoded, spaces are significant. Try // to move a space from the start of this word to be outside of // the encoded text, so that there is a bit of space between // this word and the previous one to enhance word wrapping // chances later on. if (currentWord->originalWord.Length() > 1 && isspace (currentWord->originalWord[0])) { rfc2047 << currentWord->originalWord[0]; currentWord->originalWord.Remove (0 /* offset */, 1 /* length */); currentWord->ConvertWordToCharset (charset); } } char *encoded = NULL; ssize_t encoded_len = 0; int32 convertedLength = currentWord->convertedWord.Length (); const char *convertedBuffer = currentWord->convertedWord.String (); switch (encoding) { case quoted_printable: encoded = (char *) malloc (convertedLength * 3); encoded_len = encode_qp (encoded, convertedBuffer, convertedLength, true /* headerMode */); break; case base64: encoded = (char *) malloc (convertedLength * 2); encoded_len = encode_base64 (encoded, convertedBuffer, convertedLength, true /* headerMode */); break; default: // Unknown encoding type, shouldn't happen. encoded = (char *) convertedBuffer; encoded_len = convertedLength; break; } rfc2047 << "=?" << charset_dec << '?' << encoding << '?'; rfc2047.Append (encoded, encoded_len); rfc2047 << "?="; if (encoding == quoted_printable || encoding == base64) free(encoded); } previousWordNeededEncoding = currentWord->needsEncoding; delete currentWord; } free(*bufp); ssize_t finalLength = rfc2047.Length (); *bufp = (char *) (malloc (finalLength + 1)); memcpy (*bufp, rfc2047.String(), finalLength); (*bufp)[finalLength] = 0; return finalLength; }