diff --git a/configure.in b/configure.in index 64ea21da..8ee297b5 100644 --- a/configure.in +++ b/configure.in @@ -19,7 +19,7 @@ dnl ======================== if test "$unicode" = "yes" ; then ncurses_config_bin=ncursesw5-config ncurses_lib=ncursesw - CPPFLAGS="$CPPFLAGS -DUTF8_ENABLED" + CPPFLAGS="$CPPFLAGS -D_UTF8" else ncurses_config_bin=ncurses5-config ncurses_lib=ncurses diff --git a/src/Makefile.am b/src/Makefile.am index 0fedb998..1510d947 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,7 @@ bin_PROGRAMS = ncmpcpp -ncmpcpp_SOURCES = browser.cpp color_parser.cpp help.cpp helpers.cpp \ - libmpdclient.c lyrics.cpp menu.cpp misc.cpp mpdpp.cpp ncmpcpp.cpp scrollpad.cpp \ - search_engine.cpp settings.cpp song.cpp status_checker.cpp str_pool.c tag_editor.cpp \ - window.cpp +ncmpcpp_SOURCES = browser.cpp help.cpp helpers.cpp libmpdclient.c lyrics.cpp \ + menu.cpp misc.cpp mpdpp.cpp ncmpcpp.cpp scrollpad.cpp search_engine.cpp \ + settings.cpp song.cpp status_checker.cpp str_pool.c tag_editor.cpp window.cpp # set the include path found by configure INCLUDES= $(all_includes) diff --git a/src/help.cpp b/src/help.cpp index 991898a9..9a9d1b8d 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -88,133 +88,129 @@ namespace } } -string GetKeybindings() +void GetKeybindings(Scrollpad &help) { - string result; - - result += " [.b]Keys - Movement\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Up) + "Move Cursor up\n"; - result += DisplayKeys(Key.Down) + "Move Cursor down\n"; - result += DisplayKeys(Key.PageUp) + "Page up\n"; - result += DisplayKeys(Key.PageDown) + "Page down\n"; - result += DisplayKeys(Key.Home) + "Home\n"; - result += DisplayKeys(Key.End) + "End\n\n"; - - result += DisplayKeys(Key.ScreenSwitcher) + "Switch between playlist and browser\n"; - result += DisplayKeys(Key.Help) + "Help screen\n"; - result += DisplayKeys(Key.Playlist) + "Playlist screen\n"; - result += DisplayKeys(Key.Browser) + "Browse screen\n"; - result += DisplayKeys(Key.SearchEngine) + "Search engine\n"; - result += DisplayKeys(Key.MediaLibrary) + "Media library\n"; - result += DisplayKeys(Key.PlaylistEditor) + "Playlist editor\n"; + help << " " << fmtBold << "Keys - Movement\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Up) << "Move Cursor up\n"; + help << DisplayKeys(Key.Down) << "Move Cursor down\n"; + help << DisplayKeys(Key.PageUp) << "Page up\n"; + help << DisplayKeys(Key.PageDown) << "Page down\n"; + help << DisplayKeys(Key.Home) << "Home\n"; + help << DisplayKeys(Key.End) << "End\n\n"; + + help << DisplayKeys(Key.ScreenSwitcher) << "Switch between playlist and browser\n"; + help << DisplayKeys(Key.Help) << "Help screen\n"; + help << DisplayKeys(Key.Playlist) << "Playlist screen\n"; + help << DisplayKeys(Key.Browser) << "Browse screen\n"; + help << DisplayKeys(Key.SearchEngine) << "Search engine\n"; + help << DisplayKeys(Key.MediaLibrary) << "Media library\n"; + help << DisplayKeys(Key.PlaylistEditor) << "Playlist editor\n"; # ifdef HAVE_TAGLIB_H - result += DisplayKeys(Key.TagEditor) + "Tag editor\n\n\n"; + help << DisplayKeys(Key.TagEditor) << "Tag editor\n\n\n"; # else - result += "\n\n"; + help << "\n\n"; # endif // HAVE_TAGLIB_H - result += " [.b]Keys - Global\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Stop) + "Stop\n"; - result += DisplayKeys(Key.Pause) + "Pause\n"; - result += DisplayKeys(Key.Next) + "Next track\n"; - result += DisplayKeys(Key.Prev) + "Previous track\n"; - result += DisplayKeys(Key.SeekForward) + "Seek forward\n"; - result += DisplayKeys(Key.SeekBackward) + "Seek backward\n"; - result += DisplayKeys(Key.VolumeDown) + "Decrease volume\n"; - result += DisplayKeys(Key.VolumeUp) + "Increase volume\n\n"; - - result += DisplayKeys(Key.ToggleSpaceMode) + "Toggle space mode (select/add)\n"; - result += DisplayKeys(Key.ToggleAddMode) + "Toggle add mode\n"; - result += DisplayKeys(Key.ReverseSelection) + "Reverse selection\n"; - result += DisplayKeys(Key.DeselectAll) + "Deselect all items\n"; - result += DisplayKeys(Key.AddSelected) + "Add selected items to playlist/m3u file\n\n"; - - result += DisplayKeys(Key.ToggleRepeat) + "Toggle repeat mode\n"; - result += DisplayKeys(Key.ToggleRepeatOne) + "Toggle \"repeat one\" mode\n"; - result += DisplayKeys(Key.ToggleRandom) + "Toggle random mode\n"; - result += DisplayKeys(Key.Shuffle) + "Shuffle playlist\n"; - result += DisplayKeys(Key.ToggleCrossfade) + "Toggle crossfade mode\n"; - result += DisplayKeys(Key.SetCrossfade) + "Set crossfade\n"; - result += DisplayKeys(Key.UpdateDB) + "Start a music database update\n\n"; - - result += DisplayKeys(Key.FindForward) + "Forward find\n"; - result += DisplayKeys(Key.FindBackward) + "Backward find\n"; - result += DisplayKeys(Key.PrevFoundPosition) + "Go to previous found position\n"; - result += DisplayKeys(Key.NextFoundPosition) + "Go to next found position\n"; - result += DisplayKeys(Key.ToggleFindMode) + "Toggle find mode (normal/wrapped)\n"; - result += DisplayKeys(Key.GoToContainingDir) + "Go to directory containing current item\n"; + help << " " << fmtBold << "Keys - Global\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Stop) << "Stop\n"; + help << DisplayKeys(Key.Pause) << "Pause\n"; + help << DisplayKeys(Key.Next) << "Next track\n"; + help << DisplayKeys(Key.Prev) << "Previous track\n"; + help << DisplayKeys(Key.SeekForward) << "Seek forward\n"; + help << DisplayKeys(Key.SeekBackward) << "Seek backward\n"; + help << DisplayKeys(Key.VolumeDown) << "Decrease volume\n"; + help << DisplayKeys(Key.VolumeUp) << "Increase volume\n\n"; + + help << DisplayKeys(Key.ToggleSpaceMode) << "Toggle space mode (select/add)\n"; + help << DisplayKeys(Key.ToggleAddMode) << "Toggle add mode\n"; + help << DisplayKeys(Key.ReverseSelection) << "Reverse selection\n"; + help << DisplayKeys(Key.DeselectAll) << "Deselect all items\n"; + help << DisplayKeys(Key.AddSelected) << "Add selected items to playlist/m3u file\n\n"; + + help << DisplayKeys(Key.ToggleRepeat) << "Toggle repeat mode\n"; + help << DisplayKeys(Key.ToggleRepeatOne) << "Toggle \"repeat one\" mode\n"; + help << DisplayKeys(Key.ToggleRandom) << "Toggle random mode\n"; + help << DisplayKeys(Key.Shuffle) << "Shuffle playlist\n"; + help << DisplayKeys(Key.ToggleCrossfade) << "Toggle crossfade mode\n"; + help << DisplayKeys(Key.SetCrossfade) << "Set crossfade\n"; + help << DisplayKeys(Key.UpdateDB) << "Start a music database update\n\n"; + + help << DisplayKeys(Key.FindForward) << "Forward find\n"; + help << DisplayKeys(Key.FindBackward) << "Backward find\n"; + help << DisplayKeys(Key.PrevFoundPosition) << "Go to previous found position\n"; + help << DisplayKeys(Key.NextFoundPosition) << "Go to next found position\n"; + help << DisplayKeys(Key.ToggleFindMode) << "Toggle find mode (normal/wrapped)\n"; + help << DisplayKeys(Key.GoToContainingDir) << "Go to directory containing current item\n"; # ifdef HAVE_TAGLIB_H - result += DisplayKeys(Key.EditTags) + "Edit song's tags/playlist's name\n"; + help << DisplayKeys(Key.EditTags) << "Edit song's tags/playlist's name\n"; # endif // HAVE_TAGLIB_H - result += DisplayKeys(Key.GoToPosition) + "Go to chosen position in current song\n"; - result += DisplayKeys(Key.SongInfo) + "Show song's info\n"; + help << DisplayKeys(Key.GoToPosition) << "Go to chosen position in current song\n"; + help << DisplayKeys(Key.SongInfo) << "Show song's info\n"; # ifdef HAVE_CURL_CURL_H - result += DisplayKeys(Key.ArtistInfo) + "Show artist's info\n"; + help << DisplayKeys(Key.ArtistInfo) << "Show artist's info\n"; # endif // HAVE_CURL_CURL_H - result += DisplayKeys(Key.Lyrics) + "Show/hide song's lyrics\n\n"; - - result += DisplayKeys(Key.Quit) + "Quit\n\n\n"; - - - result += " [.b]Keys - Playlist screen\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Enter) + "Play\n"; - result += DisplayKeys(Key.Delete) + "Delete item/selected items from playlist\n"; - result += DisplayKeys(Key.Clear) + "Clear playlist\n"; - result += DisplayKeys(Key.Crop) + "Clear playlist but hold currently playing/selected items\n"; - result += DisplayKeys(Key.MvSongUp) + "Move item/group of items up\n"; - result += DisplayKeys(Key.MvSongDown) + "Move item/group of items down\n"; - result += DisplayKeys(Key.Add) + "Add url/file/directory to playlist\n"; - result += DisplayKeys(Key.SavePlaylist) + "Save playlist\n"; - result += DisplayKeys(Key.GoToNowPlaying) + "Go to currently playing position\n"; - result += DisplayKeys(Key.TogglePlaylistDisplayMode) + "Toggle playlist display mode\n"; - result += DisplayKeys(Key.ToggleAutoCenter) + "Toggle auto center mode\n\n\n"; - - result += " [.b]Keys - Browse screen\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Enter) + "Enter directory/Add item to playlist and play\n"; - result += DisplayKeys(Key.Space) + "Add item to playlist\n"; + help << DisplayKeys(Key.Lyrics) << "Show/hide song's lyrics\n\n"; + + help << DisplayKeys(Key.Quit) << "Quit\n\n\n"; + + + help << " " << fmtBold << "Keys - Playlist screen\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Enter) << "Play\n"; + help << DisplayKeys(Key.Delete) << "Delete item/selected items from playlist\n"; + help << DisplayKeys(Key.Clear) << "Clear playlist\n"; + help << DisplayKeys(Key.Crop) << "Clear playlist but hold currently playing/selected items\n"; + help << DisplayKeys(Key.MvSongUp) << "Move item/group of items up\n"; + help << DisplayKeys(Key.MvSongDown) << "Move item/group of items down\n"; + help << DisplayKeys(Key.Add) << "Add url/file/directory to playlist\n"; + help << DisplayKeys(Key.SavePlaylist) << "Save playlist\n"; + help << DisplayKeys(Key.GoToNowPlaying) << "Go to currently playing position\n"; + help << DisplayKeys(Key.TogglePlaylistDisplayMode) << "Toggle playlist display mode\n"; + help << DisplayKeys(Key.ToggleAutoCenter) << "Toggle auto center mode\n\n\n"; + + help << " " << fmtBold << "Keys - Browse screen\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Enter) << "Enter directory/Add item to playlist and play\n"; + help << DisplayKeys(Key.Space) << "Add item to playlist\n"; if (Mpd->GetHostname()[0] == '/') // are we connected to unix socket? - result += DisplayKeys(Key.SwitchTagTypeList) + "Browse MPD database/local filesystem\n"; - result += DisplayKeys(Key.GoToParentDir) + "Go to parent directory\n"; - result += DisplayKeys(Key.Delete) + "Delete playlist\n\n\n"; + help << DisplayKeys(Key.SwitchTagTypeList) << "Browse MPD database/local filesystem\n"; + help << DisplayKeys(Key.GoToParentDir) << "Go to parent directory\n"; + help << DisplayKeys(Key.Delete) << "Delete playlist\n\n\n"; - result += " [.b]Keys - Search engine\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Enter) + "Add item to playlist and play/change option\n"; - result += DisplayKeys(Key.Space) + "Add item to playlist\n"; - result += DisplayKeys(Key.StartSearching) + "Start searching immediately\n\n\n"; + help << " " << fmtBold << "Keys - Search engine\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Enter) << "Add item to playlist and play/change option\n"; + help << DisplayKeys(Key.Space) << "Add item to playlist\n"; + help << DisplayKeys(Key.StartSearching) << "Start searching immediately\n\n\n"; - result += " [.b]Keys - Media library\n -----------------------------------------[/b]\n"; - result += DisplayKeys(&Key.VolumeDown[0], 1) + "Previous column\n"; - result += DisplayKeys(&Key.VolumeUp[0], 1) + "Next column\n"; - result += DisplayKeys(Key.Enter) + "Add to playlist and play song/album/artist's songs\n"; - result += DisplayKeys(Key.Space) + "Add to playlist song/album/artist's songs\n"; - result += DisplayKeys(Key.SwitchTagTypeList) + "Tag type list switcher (left column)\n\n\n"; + help << " " << fmtBold << "Keys - Media library\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(&Key.VolumeDown[0], 1) << "Previous column\n"; + help << DisplayKeys(&Key.VolumeUp[0], 1) << "Next column\n"; + help << DisplayKeys(Key.Enter) << "Add to playlist and play song/album/artist's songs\n"; + help << DisplayKeys(Key.Space) << "Add to playlist song/album/artist's songs\n"; + help << DisplayKeys(Key.SwitchTagTypeList) << "Tag type list switcher (left column)\n\n\n"; - result += " [.b]Keys - Playlist Editor\n -----------------------------------------[/b]\n"; - result += DisplayKeys(&Key.VolumeDown[0], 1) + "Previous column\n"; - result += DisplayKeys(&Key.VolumeUp[0], 1) + "Next column\n"; - result += DisplayKeys(Key.Enter) + "Add item to playlist and play\n"; - result += DisplayKeys(Key.Space) + "Add to playlist/select item\n"; + help << " " << fmtBold << "Keys - Playlist Editorz\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(&Key.VolumeDown[0], 1) << "Previous column\n"; + help << DisplayKeys(&Key.VolumeUp[0], 1) << "Next column\n"; + help << DisplayKeys(Key.Enter) << "Add item to playlist and play\n"; + help << DisplayKeys(Key.Space) << "Add to playlist/select item\n"; # ifndef HAVE_TAGLIB_H - result += DisplayKeys(Key.EditTags) + "Edit playlist's name\n"; + help << DisplayKeys(Key.EditTags) << "Edit playlist's name\n"; # endif // ! HAVE_TAGLIB_H - result += DisplayKeys(Key.MvSongUp) + "Move item/group of items up\n"; - result += DisplayKeys(Key.MvSongDown) + "Move item/group of items down\n"; + help << DisplayKeys(Key.MvSongUp) << "Move item/group of items up\n"; + help << DisplayKeys(Key.MvSongDown) << "Move item/group of items down\n"; - result += "\n\n [.b]Keys - Lyrics\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Space) + "Switch for following lyrics of now playing song\n"; + help << "\n\n " << fmtBold << "Keys - Lyrics\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Space) << "Switch for following lyrics of now playing song\n"; # ifdef HAVE_TAGLIB_H - result += "\n\n [.b]Keys - Tag editor\n -----------------------------------------[/b]\n"; - result += DisplayKeys(Key.Enter) + "Change tag/filename for one song (left column)\n"; - result += DisplayKeys(Key.Enter) + "Perform operation on all/selected songs (middle column)\n"; - result += DisplayKeys(Key.Space) + "Switch to albums/directories view (left column)\n"; - result += DisplayKeys(Key.Space) + "Select/deselect song (right column)\n"; - result += DisplayKeys(&Key.VolumeDown[0], 1) + "Previous column\n"; - result += DisplayKeys(&Key.VolumeUp[0], 1) + "Next column\n"; + help << "\n\n " << fmtBold << "Keys - Tag editor\n -----------------------------------------\n" << fmtBoldEnd; + help << DisplayKeys(Key.Enter) << "Change tag/filename for one song (left column)\n"; + help << DisplayKeys(Key.Enter) << "Perform operation on all/selected songs (middle column)\n"; + help << DisplayKeys(Key.Space) << "Switch to albums/directories view (left column)\n"; + help << DisplayKeys(Key.Space) << "Select/deselect song (right column)\n"; + help << DisplayKeys(&Key.VolumeDown[0], 1) << "Previous column\n"; + help << DisplayKeys(&Key.VolumeUp[0], 1) << "Next column\n"; # endif // HAVE_TAGLIB_H - - return result; } diff --git a/src/help.h b/src/help.h index 15f941b2..3694deb4 100644 --- a/src/help.h +++ b/src/help.h @@ -23,7 +23,7 @@ #include "ncmpcpp.h" -string GetKeybindings(); +void GetKeybindings(Scrollpad &); #endif diff --git a/src/helpers.cpp b/src/helpers.cpp index 27c666f2..dadbb2bb 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -86,7 +86,7 @@ bool ParseArgv(int argc, char **argv) # ifdef HAVE_TAGLIB_H << " taglib" # endif -# ifdef UTF8_ENABLED +# ifdef _UTF8 << " unicode" # endif << endl; @@ -462,7 +462,7 @@ string DisplaySongInColumns(const Song &s, void *s_template, const Menu *) my_string_t result, v; -# ifdef UTF8_ENABLED +# ifdef _UTF8 const wstring space = L" "; const wstring open_col = L"[."; const wstring close_col = L"]"; @@ -534,7 +534,7 @@ string DisplaySongInColumns(const Song &s, void *s_template, const Menu *) break; } - v = TO_WSTRING(Window::OmitBBCodes(ss)).substr(0, width-1); + v = TO_WSTRING(ss.substr(0, width-1)); for (int i = v.length(); i < width; i++, v += space) { } if (!color.empty()) { @@ -822,14 +822,13 @@ string DisplaySong(const Song &s, void *s_template, const Menu *menu) } if (right && menu) { - result = lresult + "[." + IntoStr(menu->GetWidth()-Window::RealLength(result)) + "]" + result; + result = lresult + "[." + IntoStr(menu->GetWidth()-result.length()) + "]" + result; } return result; } -string GetInfo(Song &s) +void GetInfo(Song &s, Scrollpad &info) { - string result; # ifdef HAVE_TAGLIB_H string path_to_file; if (s.IsFromDB()) @@ -840,28 +839,27 @@ string GetInfo(Song &s) s.SetComment(f.tag()->comment().to8Bit(UNICODE)); # endif // HAVE_TAGLIB_H - result = "[.b][." + Config.color1 + "]Filename: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + s.GetName() + "[/" + Config.color2 + "]\n"; - result += "[.b][." + Config.color1 + "]Directory: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + s.GetDirectory() + "[/" + Config.color2 + "]\n\n"; - result += "[.b][." + Config.color1 + "]Length: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + s.GetLength() + "[/" + Config.color2 + "]\n"; + info << fmtBold << clWhite << "Filename: " << fmtBoldEnd << clGreen << s.GetName() << "\n" << clEnd; + info << fmtBold << "Directory: " << fmtBoldEnd << clGreen << s.GetDirectory() + "\n\n" << clEnd; + info << fmtBold << "Length: " << fmtBoldEnd << clGreen << s.GetLength() + "\n" << clEnd; # ifdef HAVE_TAGLIB_H if (!f.isNull()) { - result += "[.b][." + Config.color1 + "]Bitrate: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + IntoStr(f.audioProperties()->bitrate()) + " kbps[/" + Config.color2 + "]\n"; - result += "[.b][." + Config.color1 + "]Sample rate: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + IntoStr(f.audioProperties()->sampleRate()) + " Hz[/" + Config.color2 + "]\n"; - result += "[.b][." + Config.color1 + "]Channels: [/" + Config.color1 + "][." + Config.color2 + "][/b]" + string(f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") + "[/" + Config.color2 + "]\n"; + info << fmtBold << "Bitrate: " << fmtBoldEnd << clGreen << f.audioProperties()->bitrate() << " kbps\n" << clEnd; + info << fmtBold << "Sample rate: " << fmtBoldEnd << clGreen << f.audioProperties()->sampleRate() << " Hz\n" << clEnd; + info << fmtBold << "Channels: " << fmtBoldEnd << clGreen << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << "\n" << clDefault; } # endif // HAVE_TAGLIB_H - result += "\n[.b]Title:[/b] " + s.GetTitle(); - result += "\n[.b]Artist:[/b] " + s.GetArtist(); - result += "\n[.b]Album:[/b] " + s.GetAlbum(); - result += "\n[.b]Year:[/b] " + s.GetYear(); - result += "\n[.b]Track:[/b] " + s.GetTrack(); - result += "\n[.b]Genre:[/b] " + s.GetGenre(); - result += "\n[.b]Composer:[/b] " + s.GetComposer(); - result += "\n[.b]Performer:[/b] " + s.GetPerformer(); - result += "\n[.b]Disc:[/b] " + s.GetDisc(); - result += "\n[.b]Comment:[/b] " + s.GetComment(); - return result; + info << fmtBold << "\nTitle: " << fmtBoldEnd << s.GetTitle(); + info << fmtBold << "\nArtist: " << fmtBoldEnd << s.GetArtist(); + info << fmtBold << "\nAlbum: " << fmtBoldEnd << s.GetAlbum(); + info << fmtBold << "\nYear: " << fmtBoldEnd << s.GetYear(); + info << fmtBold << "\nTrack: " << fmtBoldEnd << s.GetTrack(); + info << fmtBold << "\nGenre: " << fmtBoldEnd << s.GetGenre(); + info << fmtBold << "\nComposer: " << fmtBoldEnd << s.GetComposer(); + info << fmtBold << "\nPerformer: " << fmtBoldEnd << s.GetPerformer(); + info << fmtBold << "\nDisc: " << fmtBoldEnd << s.GetDisc(); + info << fmtBold << "\nComment: " << fmtBoldEnd << s.GetComment(); } void ShowMessage(const char *format, ...) @@ -877,9 +875,9 @@ void ShowMessage(const char *format, ...) wFooter->Bold(0); va_list list; va_start(list, format); - wmove(wFooter->RawWin(), Config.statusbar_visibility, 0); - vw_printw(wFooter->RawWin(), format, list); - wclrtoeol(wFooter->RawWin()); + wmove(wFooter->Raw(), Config.statusbar_visibility, 0); + vw_printw(wFooter->Raw(), format, list); + wclrtoeol(wFooter->Raw()); va_end(list); wFooter->Bold(1); wFooter->Refresh(); diff --git a/src/helpers.h b/src/helpers.h index 80124f66..2944d640 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -55,7 +55,7 @@ string DisplayStringPair(const StringPair &, void *, const Menu *); string DisplayColumns(string); string DisplaySongInColumns(const Song &, void *, const Menu *); string DisplaySong(const Song &, void * = &Config.song_list_format, const Menu * = NULL); -string GetInfo(Song &); +void GetInfo(Song &, Scrollpad &); void ShowMessage(const char *, ...); #endif diff --git a/src/lyrics.cpp b/src/lyrics.cpp index 99444ffe..c0693f08 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -26,13 +26,16 @@ #include "settings.h" #include "song.h" +extern Scrollpad *sLyrics; +extern Scrollpad *sInfo; + const string artists_folder = home_folder + "/" + ".ncmpcpp/artists"; const string lyrics_folder = home_folder + "/" + ".lyrics"; #ifdef HAVE_CURL_CURL_H +extern pthread_t lyrics_downloader; +extern pthread_t artist_info_downloader; pthread_mutex_t curl = PTHREAD_MUTEX_INITIALIZER; -bool artist_info_ready = 0; -bool lyrics_ready = 0; #endif namespace @@ -74,18 +77,24 @@ void * GetArtistInfo(void *ptr) const string fullpath = artists_folder + "/" + filename; mkdir(artists_folder.c_str(), 0755); - string *result = new string(); + string result; std::ifstream input(fullpath.c_str()); if (input.is_open()) { + bool first = 1; string line; while (getline(input, line)) - *result += line + "\n"; + { + if (!first) + *sInfo << "\n"; + *sInfo << line; + first = 0; + } input.close(); - *result = result->substr(0, result->length()-1); - artist_info_ready = 1; - pthread_exit(result); + sInfo->Flush(); + artist_info_downloader = 0; + pthread_exit(NULL); } for (string::iterator it = artist.begin(); it != artist.end(); it++) @@ -100,7 +109,7 @@ void * GetArtistInfo(void *ptr) CURL *info = curl_easy_init(); curl_easy_setopt(info, CURLOPT_URL, url.c_str()); curl_easy_setopt(info, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(info, CURLOPT_WRITEDATA, result); + curl_easy_setopt(info, CURLOPT_WRITEDATA, &result); curl_easy_setopt(info, CURLOPT_CONNECTTIMEOUT, 10); code = curl_easy_perform(info); curl_easy_cleanup(info); @@ -108,131 +117,137 @@ void * GetArtistInfo(void *ptr) if (code != CURLE_OK) { - *result = "Error while fetching artist's info: " + string(curl_easy_strerror(code)); - artist_info_ready = 1; - pthread_exit(result); + *sInfo << "Error while fetching artist's info: " << curl_easy_strerror(code); + sInfo->Flush(); + artist_info_downloader = 0; + pthread_exit(NULL); } size_t a, b; bool erase = 0; bool save = 1; - a = result->find("status=\"failed\""); + a = result.find("status=\"failed\""); if (a != string::npos) { - EscapeHtml(*result); - *result = "Last.fm returned an error message: " + *result; - artist_info_ready = 1; - pthread_exit(result); + EscapeHtml(result); + *sInfo << "Last.fm returned an error message: " << result; + sInfo->Flush(); + artist_info_downloader = 0; + pthread_exit(NULL); } vector similar; - for (size_t i = result->find(""); i != string::npos; i = result->find("")) + for (size_t i = result.find(""); i != string::npos; i = result.find("")) { - (*result)[i] = '.'; - size_t j = result->find(""); - (*result)[j] = '.'; + result[i] = '.'; + size_t j = result.find(""); + result[j] = '.'; i += 6; - similar.push_back(result->substr(i, j-i)); + similar.push_back(result.substr(i, j-i)); EscapeHtml(similar.back()); } vector urls; - for (size_t i = result->find(""); i != string::npos; i = result->find("")) + for (size_t i = result.find(""); i != string::npos; i = result.find("")) { - (*result)[i] = '.'; - size_t j = result->find(""); - (*result)[j] = '.'; + result[i] = '.'; + size_t j = result.find(""); + result[j] = '.'; i += 5; - urls.push_back(result->substr(i, j-i)); + urls.push_back(result.substr(i, j-i)); } - a = result->find("")+9; - b = result->find(""); + a = result.find("")+9; + b = result.find(""); if (a == b) { - *result = "No description available for this artist."; + result = "No description available for this artist."; save = 0; } else { a += 9; // for - *result = result->substr(a, b-a); + result = result.substr(a, b-a); } - EscapeHtml(*result); - for (size_t i = 0; i < result->length(); i++) + EscapeHtml(result); + for (size_t i = 0; i < result.length(); i++) { if (erase) { - result->erase(result->begin()+i); + result.erase(result.begin()+i); erase = 0; } - if ((*result)[i] == 13) + if (result[i] == 13) { - (*result)[i] = '\n'; + result[i] = '\n'; erase = 1; } - else if ((*result)[i] == '\t') - (*result)[i] = ' '; + else if (result[i] == '\t') + result[i] = ' '; } - int i = result->length(); - if (!isgraph((*result)[i-1])) + int i = result.length(); + if (!isgraph(result[i-1])) { - while (!isgraph((*result)[--i])) { } - *result = result->substr(0, i+1); + while (!isgraph(result[--i])) { } + result = result.substr(0, i+1); } - *result += "\n\n[.b]Similar artists:[/b]\n"; + *sInfo << result; + + *sInfo << fmtBold << "\n\nSimilar artists:\n" << fmtBoldEnd; for (size_t i = 1; i < similar.size(); i++) - *result += "\n [." + Config.color2 + "]*[/" + Config.color2 + "] " + similar[i] + " (" + urls[i] + ")"; + *sInfo << "\n" << clGreen << " * " << clEnd << similar[i] << " (" << urls[i] << ")"; - *result += "\n\n" + urls.front(); + *sInfo << "\n\n" << urls.front(); if (save) { std::ofstream output(fullpath.c_str()); if (output.is_open()) { - output << *result; + output << TO_STRING(sInfo->Content()); output.close(); } } - - artist_info_ready = 1; - pthread_exit(result); + sInfo->Flush(); + artist_info_downloader = 0; + pthread_exit(NULL); } #endif // HAVE_CURL_CURL_H -void * GetLyrics(void *song) +void *GetLyrics(void *song) { string artist = static_cast(song)->GetArtist(); string title = static_cast(song)->GetTitle(); - const string filename = artist + " - " + title + ".txt"; + string filename = artist + " - " + title + ".txt"; const string fullpath = lyrics_folder + "/" + filename; mkdir(lyrics_folder.c_str(), 0755); - string *result = new string(); - std::ifstream input(fullpath.c_str()); if (input.is_open()) { + bool first = 1; string line; while (getline(input, line)) - *result += line + "\n"; - input.close(); - *result = result->substr(0, result->length()-1); + { + if (!first) + *sLyrics << "\n"; + *sLyrics << line; + first = 0; + } # ifdef HAVE_CURL_CURL_H - lyrics_ready = 1; - pthread_exit(result); + sLyrics->Flush(); + lyrics_downloader = 0; + pthread_exit(NULL); # endif } - # ifdef HAVE_CURL_CURL_H for (string::iterator it = artist.begin(); it != artist.end(); it++) if (*it == ' ') @@ -244,13 +259,19 @@ void * GetLyrics(void *song) CURLcode code; - string url = "http://lyricwiki.org/api.php?artist=" + artist + "&song=" + title + "&fmt=xml"; + string result; + + string url = "http://lyricwiki.org/api.php?artist="; + url += artist; + url += "&song="; + url += title; + url += "&fmt=xml"; pthread_mutex_lock(&curl); CURL *lyrics = curl_easy_init(); curl_easy_setopt(lyrics, CURLOPT_URL, url.c_str()); curl_easy_setopt(lyrics, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(lyrics, CURLOPT_WRITEDATA, result); + curl_easy_setopt(lyrics, CURLOPT_WRITEDATA, &result); curl_easy_setopt(lyrics, CURLOPT_CONNECTTIMEOUT, 10); code = curl_easy_perform(lyrics); curl_easy_cleanup(lyrics); @@ -258,43 +279,49 @@ void * GetLyrics(void *song) if (code != CURLE_OK) { - *result = "Error while fetching lyrics: " + string(curl_easy_strerror(code)); - lyrics_ready = 1; - pthread_exit(result); + *sLyrics << "Error while fetching lyrics: " << curl_easy_strerror(code); + sLyrics->Flush(); + lyrics_downloader = 0; + pthread_exit(NULL); } int a, b; - a = result->find("")+8; - b = result->find(""); + a = result.find("")+8; + b = result.find(""); - *result = result->substr(a, b-a); + result = result.substr(a, b-a); - if (*result == "Not found") + if (result == "Not found") { - lyrics_ready = 1; - pthread_exit(result); + *sLyrics << result; + sLyrics->Flush(); + lyrics_downloader = 0; + pthread_exit(NULL); } - for (size_t i = result->find("<"); i != string::npos; i = result->find("<")) - result->replace(i, 4, "<"); - for (size_t i = result->find(">"); i != string::npos; i = result->find(">")) - result->replace(i, 4, ">"); + for (size_t i = result.find("<"); i != string::npos; i = result.find("<")) + result.replace(i, 4, "<"); + for (size_t i = result.find(">"); i != string::npos; i = result.find(">")) + result.replace(i, 4, ">"); + + EscapeHtml(result); - EscapeHtml(*result); + *sLyrics << result; std::ofstream output(fullpath.c_str()); if (output.is_open()) { - output << *result; + output << result; output.close(); } - - lyrics_ready = 1; - pthread_exit(result); + sLyrics->Flush(); + lyrics_downloader = 0; + pthread_exit(NULL); # else else - *result = "Local lyrics not found. As ncmpcpp has been compiled without curl support, you can put appropriate lyrics into ~/.lyrics directory (file syntax is \"ARTIST - TITLE.txt\") or recompile ncmpcpp with curl support."; - return result; + *sLyrics << "Local lyrics not found. As ncmpcpp has been compiled without curl support, you can put appropriate lyrics into ~/.lyrics directory (file syntax is \"ARTIST - TITLE.txt\") or recompile ncmpcpp with curl support."; + sLyrics->Flush(); + return NULL; # endif } diff --git a/src/menu.h b/src/menu.h index 4a3a7b89..82ddb27a 100644 --- a/src/menu.h +++ b/src/menu.h @@ -67,8 +67,8 @@ class Menu : public Window void InsertSeparator(int where) { Insert(where, T(), 0, 1, 1); } virtual string GetOption(int i = -1) const; - virtual void Refresh(bool redraw_whole_window = 0); - virtual void Go(Where); + virtual void Refresh(); + virtual void Scroll(Where); virtual void Highlight(int); virtual void Reset(); virtual void Clear(bool clear_screen = 1); @@ -90,8 +90,8 @@ class Menu : public Window bool Empty() const { return itsOptions.empty(); } bool IsBold(int = -1) const; virtual bool IsStatic(int = -1) const; - virtual Window * Clone() const { return new Menu(*this); } - virtual Window * EmptyClone() const; + virtual Menu *Clone() const { return new Menu(*this); } + virtual Menu *EmptyClone() const; T & Back() { return itsOptions.back()->item; } const T & Back() const { return itsOptions.back()->item; } @@ -317,10 +317,11 @@ void Menu::redraw_screen() } template -void Menu::Refresh(bool redraw_whole_window) +void Menu::Refresh() { + bool redraw_whole_window = 1; if (!itsOptions.empty() && is_static()) - itsHighlight == 0 ? Go(wDown) : Go(wUp); + itsHighlight == 0 ? Scroll(wDown) : Scroll(wUp); int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight; if (itsBeginning > MaxBeginning) @@ -376,7 +377,7 @@ void Menu::Refresh(bool redraw_whole_window) if (itsOptions[*it]->selected) option += itsSelectedSuffix; - int strlength = itsOptions[*it]->location != lLeft && BBEnabled ? Window::RealLength(option) : option.length(); + int strlength = option.length(); if (strlength) { @@ -429,7 +430,7 @@ void Menu::Refresh(bool redraw_whole_window) } template -void Menu::Go(Where where) +void Menu::Scroll(Where where) { if (Empty()) return; @@ -459,7 +460,7 @@ void Menu::Go(Where where) } if (is_static()) { - itsHighlight == 0 ? Go(wDown) : Go(wUp); + itsHighlight == 0 ? Scroll(wDown) : Scroll(wUp); } break; } @@ -481,7 +482,7 @@ void Menu::Go(Where where) } if (is_static()) { - itsHighlight == MaxHighlight ? Go(wUp) : Go(wDown); + itsHighlight == MaxHighlight ? Scroll(wUp) : Scroll(wDown); } break; } @@ -497,7 +498,7 @@ void Menu::Go(Where where) } if (is_static()) { - itsHighlight == 0 ? Go(wDown) : Go(wUp); + itsHighlight == 0 ? Scroll(wDown) : Scroll(wUp); } redraw_screen(); break; @@ -514,7 +515,7 @@ void Menu::Go(Where where) } if (is_static()) { - itsHighlight == MaxHighlight ? Go(wUp) : Go(wDown); + itsHighlight == MaxHighlight ? Scroll(wUp) : Scroll(wDown); } redraw_screen(); break; @@ -525,7 +526,7 @@ void Menu::Go(Where where) itsBeginning = 0; if (is_static()) { - itsHighlight == 0 ? Go(wDown) : Go(wUp); + itsHighlight == 0 ? Scroll(wDown) : Scroll(wUp); } redraw_screen(); break; @@ -536,7 +537,7 @@ void Menu::Go(Where where) itsBeginning = MaxBeginning; if (is_static()) { - itsHighlight == MaxHighlight ? Go(wUp) : Go(wDown); + itsHighlight == MaxHighlight ? Scroll(wUp) : Scroll(wDown); } redraw_screen(); break; @@ -702,9 +703,9 @@ bool Menu::IsStatic(int option) const } template -Window * Menu::EmptyClone() const +Menu *Menu::EmptyClone() const { - return new Menu(GetStartX(), GetStartY(), GetWidth(), GetHeight(), itsTitle, itsBaseColor, itsBorder); + return new Menu(GetStartX(), GetStartY(), GetWidth(), GetHeight(), itsTitle, itsBaseColor, itsBorder); } template diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index cf4c91fc..474c98c6 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -47,30 +47,30 @@ #define REFRESH_MEDIA_LIBRARY_SCREEN \ do { \ - mLibArtists->Display(redraw_screen); \ + mLibArtists->Display(); \ mvvline(main_start_y, middle_col_startx-1, 0, main_height); \ - mLibAlbums->Display(redraw_screen); \ + mLibAlbums->Display(); \ mvvline(main_start_y, right_col_startx-1, 0, main_height); \ - mLibSongs->Display(redraw_screen); \ + mLibSongs->Display(); \ if (mLibAlbums->Empty()) \ mLibAlbums->WriteXY(0, 0, "No albums found."); \ } while (0) #define REFRESH_PLAYLIST_EDITOR_SCREEN \ do { \ - mPlaylistList->Display(redraw_screen); \ + mPlaylistList->Display(); \ mvvline(main_start_y, middle_col_startx-1, 0, main_height); \ - mPlaylistEditor->Display(redraw_screen); \ + mPlaylistEditor->Display(); \ } while (0) #ifdef HAVE_TAGLIB_H # define REFRESH_TAG_EDITOR_SCREEN \ do { \ - mEditorLeftCol->Display(redraw_screen); \ + mEditorLeftCol->Display(); \ mvvline(main_start_y, middle_col_startx-1, 0, main_height); \ - mEditorTagTypes->Display(redraw_screen); \ + mEditorTagTypes->Display(); \ mvvline(main_start_y, right_col_startx-1, 0, main_height); \ - mEditorTags->Display(redraw_screen); \ + mEditorTags->Display(); \ } while (0) #endif // HAVE_TAGLIB_H @@ -138,8 +138,6 @@ NcmpcppScreen prev_screen; #ifdef HAVE_CURL_CURL_H pthread_t lyrics_downloader; pthread_t artist_info_downloader; -extern bool artist_info_ready; -extern bool lyrics_ready; #endif bool dont_change_now_playing = 0; @@ -202,14 +200,10 @@ int main(int argc, char *argv[]) if (!ConnectToMPD()) return -1; - setlocale(LC_ALL, ""); - initscr(); - noecho(); - cbreak(); - curs_set(0); + InitScreen(); - if (Config.colors_enabled) - Window::EnableColors(); + //if (Config.colors_enabled) + // Window::EnableColors(); int main_start_y = 2; int main_height = LINES-4; @@ -223,7 +217,6 @@ int main(int argc, char *argv[]) main_height++; mPlaylist = new Menu(0, main_start_y, COLS, main_height, Config.columns_in_playlist ? DisplayColumns(Config.song_columns_list_format) : "", Config.main_color, brNone); - mPlaylist->AutoRefresh(0); mPlaylist->SetTimeout(ncmpcpp_window_timeout); mPlaylist->HighlightColor(Config.main_highlight_color); mPlaylist->SetSelectPrefix(Config.selected_item_prefix); @@ -311,12 +304,13 @@ int main(int argc, char *argv[]) sHelp = new Scrollpad(0, main_start_y, COLS, main_height, "", Config.main_color, brNone); sHelp->SetTimeout(ncmpcpp_window_timeout); - sHelp->Add(GetKeybindings()); + GetKeybindings(*sHelp); + sHelp->Flush(); - sLyrics = static_cast(sHelp->EmptyClone()); + sLyrics = sHelp->EmptyClone(); sLyrics->SetTimeout(ncmpcpp_window_timeout); - sInfo = static_cast(sHelp->EmptyClone()); + sInfo = sHelp->EmptyClone(); sInfo->SetTimeout(ncmpcpp_window_timeout); if (Config.header_visibility) @@ -356,6 +350,12 @@ int main(int argc, char *argv[]) signal(SIGPIPE, SIG_IGN); +# ifdef HAVE_CURL_CURL_H + pthread_attr_t attr_detached; + pthread_attr_init(&attr_detached); + pthread_attr_setdetachstate(&attr_detached, PTHREAD_CREATE_DETACHED); +# endif // HAVE_CURL_CURL_H + while (!main_exit) { if (!Mpd->Connected()) @@ -430,7 +430,7 @@ int main(int argc, char *argv[]) wHeader->Bold(1); if (browsed_dir.length() > max_length_without_scroll) { -# ifdef UTF8_ENABLED +# ifdef _UTF8 wbrowseddir += L" ** "; # else wbrowseddir += " ** "; @@ -460,10 +460,10 @@ int main(int argc, char *argv[]) wHeader->SetColor(Config.volume_color); wHeader->WriteXY(max_allowed_title_length, 0, volume_state); wHeader->SetColor(Config.header_color); + wHeader->Refresh(); redraw_header = 0; } // header stuff end - // media library stuff if (current_screen == csLibrary) { @@ -704,7 +704,7 @@ int main(int argc, char *argv[]) if (redraw_screen && wCurrent == mEditorTagTypes && mEditorTagTypes->GetChoice() < 13) { - mEditorTags->Refresh(1); + mEditorTags->Refresh(); redraw_screen = 0; } else if (mEditorTagTypes->GetChoice() >= 13) @@ -722,36 +722,11 @@ int main(int argc, char *argv[]) else reload_lyrics = 0; } -# ifdef HAVE_CURL_CURL_H - if (artist_info_ready) - { - void *result; - string *str_result = 0; - pthread_join(artist_info_downloader, &result); - str_result = static_cast(result); - sInfo->Add(*str_result); - delete str_result; - artist_info_downloader = 0; - artist_info_ready = 0; - } - else if (lyrics_ready) - { - void *result; - string *str_result = 0; - pthread_join(lyrics_downloader, &result); - str_result = static_cast(result); - sLyrics->Add(*str_result); - delete str_result; - lyrics_downloader = 0; - lyrics_ready = 0; - } -# endif - // lyrics end if (Config.columns_in_playlist && wCurrent == mPlaylist) - wCurrent->Display(redraw_screen); + wCurrent->Display(); else - wCurrent->Refresh(redraw_screen); + wCurrent->Refresh(); redraw_screen = 0; wCurrent->ReadKey(input); @@ -811,14 +786,14 @@ int main(int argc, char *argv[]) wCurrent->SetTimeout(50); while (Keypressed(input, Key.Up)) { - wCurrent->Go(wUp); + wCurrent->Scroll(wUp); wCurrent->Refresh(); wCurrent->ReadKey(input); } wCurrent->SetTimeout(ncmpcpp_window_timeout); } else - wCurrent->Go(wUp); + wCurrent->Scroll(wUp); } else if (Keypressed(input, Key.Down)) { @@ -827,30 +802,30 @@ int main(int argc, char *argv[]) wCurrent->SetTimeout(50); while (Keypressed(input, Key.Down)) { - wCurrent->Go(wDown); + wCurrent->Scroll(wDown); wCurrent->Refresh(); wCurrent->ReadKey(input); } wCurrent->SetTimeout(ncmpcpp_window_timeout); } else - wCurrent->Go(wDown); + wCurrent->Scroll(wDown); } else if (Keypressed(input, Key.PageUp)) { - wCurrent->Go(wPageUp); + wCurrent->Scroll(wPageUp); } else if (Keypressed(input, Key.PageDown)) { - wCurrent->Go(wPageDown); + wCurrent->Scroll(wPageDown); } else if (Keypressed(input, Key.Home)) { - wCurrent->Go(wHome); + wCurrent->Scroll(wHome); } else if (Keypressed(input, Key.End)) { - wCurrent->Go(wEnd); + wCurrent->Scroll(wEnd); } else if (input == KEY_RESIZE) { @@ -1315,8 +1290,8 @@ int main(int argc, char *argv[]) ShowMessage("Searching finished!"); for (int i = 0; i < search_engine_static_options-4; i++) mSearcher->MakeStatic(i, 1); - mSearcher->Go(wDown); - mSearcher->Go(wDown); + mSearcher->Scroll(wDown); + mSearcher->Scroll(wDown); } else ShowMessage("No results found"); @@ -1461,7 +1436,7 @@ int main(int argc, char *argv[]) FreeSongList(list); if (Keypressed(input, Key.Space)) { - wCurrent->Go(wDown); + wCurrent->Scroll(wDown); if (wCurrent == mLibArtists) { mLibAlbums->Clear(0); @@ -1548,7 +1523,7 @@ int main(int argc, char *argv[]) } FreeSongList(list); if (Keypressed(input, Key.Space)) - wCurrent->Go(wDown); + wCurrent->Scroll(wDown); break; } # ifdef HAVE_TAGLIB_H @@ -1668,7 +1643,7 @@ int main(int argc, char *argv[]) UnlockStatusbar(); if (!new_name.empty() && new_name != old_name) s.SetNewName(new_name + extension); - mEditorTags->Go(wDown); + mEditorTags->Scroll(wDown); } continue; } @@ -1732,7 +1707,7 @@ int main(int argc, char *argv[]) UnlockStatusbar(); if (new_tag != mEditorTags->GetOption()) (mEditorTags->Current().*set)(new_tag); - mEditorTags->Go(wDown); + mEditorTags->Scroll(wDown); } } # endif // HAVE_TAGLIB_H @@ -1748,7 +1723,7 @@ int main(int argc, char *argv[]) { int i = wCurrent->GetChoice(); wCurrent->Select(i, !wCurrent->Selected(i)); - wCurrent->Go(wDown); + wCurrent->Scroll(wDown); } } else @@ -1825,7 +1800,7 @@ int main(int argc, char *argv[]) break; } } - mBrowser->Go(wDown); + mBrowser->Scroll(wDown); } else if (current_screen == csSearcher && mSearcher->Current().first == ".") { @@ -1855,7 +1830,7 @@ int main(int argc, char *argv[]) mSearcher->BoldOption(mSearcher->GetChoice(), 1); } } - mSearcher->Go(wDown); + mSearcher->Scroll(wDown); } else if (current_screen == csLibrary) goto ENTER_LIBRARY_SCREEN; // sorry, but that's stupid to copy the same code here. @@ -2203,7 +2178,7 @@ int main(int argc, char *argv[]) timer = time(NULL); to--; mPlaylist->Swap(to, to+1); - mPlaylist->Go(wUp); + mPlaylist->Scroll(wUp); mPlaylist->Refresh(); mPlaylist->ReadKey(input); } @@ -2249,7 +2224,7 @@ int main(int argc, char *argv[]) timer = time(NULL); to--; mPlaylistEditor->Swap(to, to+1); - mPlaylistEditor->Go(wUp); + mPlaylistEditor->Scroll(wUp); mPlaylistEditor->Refresh(); mPlaylistEditor->ReadKey(input); } @@ -2306,7 +2281,7 @@ int main(int argc, char *argv[]) timer = time(NULL); to++; mPlaylist->Swap(to, to-1); - mPlaylist->Go(wDown); + mPlaylist->Scroll(wDown); mPlaylist->Refresh(); mPlaylist->ReadKey(input); } @@ -2353,7 +2328,7 @@ int main(int argc, char *argv[]) timer = time(NULL); to++; mPlaylistEditor->Swap(to, to-1); - mPlaylistEditor->Go(wDown); + mPlaylistEditor->Scroll(wDown); mPlaylistEditor->Refresh(); mPlaylistEditor->ReadKey(input); } @@ -2434,9 +2409,9 @@ int main(int argc, char *argv[]) double progressbar_size = (double)songpos/(s.GetTotalLength()); int howlong = wFooter->GetWidth()*progressbar_size; - mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); - mvwhline(wFooter->RawWin(), 0, 0, '=',howlong); - mvwaddch(wFooter->RawWin(), 0, howlong, '>'); + mvwhline(wFooter->Raw(), 0, 0, 0, wFooter->GetWidth()); + mvwhline(wFooter->Raw(), 0, 0, '=',howlong); + mvwaddch(wFooter->Raw(), 0, howlong, '>'); wFooter->Bold(0); wFooter->Refresh(); } @@ -2902,17 +2877,17 @@ int main(int argc, char *argv[]) mDialog->ReadKey(input); if (Keypressed(input, Key.Up)) - mDialog->Go(wUp); + mDialog->Scroll(wUp); else if (Keypressed(input, Key.Down)) - mDialog->Go(wDown); + mDialog->Scroll(wDown); else if (Keypressed(input, Key.PageUp)) - mDialog->Go(wPageUp); + mDialog->Scroll(wPageUp); else if (Keypressed(input, Key.PageDown)) - mDialog->Go(wPageDown); + mDialog->Scroll(wPageDown); else if (Keypressed(input, Key.Home)) - mDialog->Go(wHome); + mDialog->Scroll(wHome); else if (Keypressed(input, Key.End)) - mDialog->Go(wEnd); + mDialog->Scroll(wEnd); } int id = mDialog->GetChoice(); @@ -2927,7 +2902,7 @@ int main(int argc, char *argv[]) REFRESH_PLAYLIST_EDITOR_SCREEN; } else - wCurrent->Refresh(1); + wCurrent->Refresh(); if (id == 0) { @@ -3040,7 +3015,7 @@ int main(int argc, char *argv[]) ShowMessage("Searching..."); for (int i = (wCurrent == mSearcher ? search_engine_static_options-1 : 0); i < wCurrent->Size(); i++) { - string name = Window::OmitBBCodes(wCurrent->GetOption(i)); + string name = wCurrent->GetOption(i); ToLower(name); if (name.find(findme) != string::npos && !wCurrent->IsStatic(i)) { @@ -3218,7 +3193,8 @@ int main(int argc, char *argv[]) redraw_header = 1; info_title = "Song info"; sInfo->Clear(); - sInfo->Add(GetInfo(*s)); + GetInfo(*s, *sInfo); + sInfo->Flush(); sInfo->Hide(); } } @@ -3293,7 +3269,9 @@ int main(int argc, char *argv[]) sInfo->WriteXY(0, 0, "Fetching artist's info..."); sInfo->Refresh(); if (!artist_info_downloader) - pthread_create(&artist_info_downloader, NULL, GetArtistInfo, artist); + { + pthread_create(&artist_info_downloader, &attr_detached, GetArtistInfo, artist); + } } else delete artist; @@ -3383,11 +3361,11 @@ int main(int argc, char *argv[]) sLyrics->Refresh(); # ifdef HAVE_CURL_CURL_H if (!lyrics_downloader) - pthread_create(&lyrics_downloader, NULL, GetLyrics, s); + { + pthread_create(&lyrics_downloader, &attr_detached, GetLyrics, s); + } # else - string *lyrics = static_cast(GetLyrics(s)); - sLyrics->Add(*lyrics); - delete lyrics; + GetLyrics(s); # endif } } @@ -3551,8 +3529,7 @@ int main(int argc, char *argv[]) // key mapping end } Mpd->Disconnect(); - curs_set(1); - endwin(); + DestroyScreen(); return 0; } diff --git a/src/scrollpad.cpp b/src/scrollpad.cpp index 67b4b04d..9388e0d4 100644 --- a/src/scrollpad.cpp +++ b/src/scrollpad.cpp @@ -20,11 +20,17 @@ #include "scrollpad.h" -Scrollpad::Scrollpad(int startx, int starty, int width, int height, const string &title, Color color, Border border) : - Window(startx, starty, width, height, title, color, border), - itsBeginning(0), - itsRealHeight(1), - itsXPos(0) +Scrollpad::Scrollpad(size_t startx, + size_t starty, + size_t width, + size_t height, + const string &title, + Color color, + Border border) + : Window(startx, starty, width, height, title, color, border), + itsBeginning(0), + itsRealHeight(1), + itsXPos(0) { delwin(itsWindow); itsWindow = newpad(itsHeight, itsWidth); @@ -34,32 +40,21 @@ Scrollpad::Scrollpad(int startx, int starty, int width, int height, const string Scrollpad::Scrollpad(const Scrollpad &s) : Window(s) { - itsContent = s.itsContent; - itsRawContent = s.itsRawContent; + itsBuffer << s.itsBuffer; itsBeginning = s.itsBeginning; itsRealHeight = s.itsRealHeight; itsXPos = s.itsXPos; } -void Scrollpad::Add(string str) +void Scrollpad::Flush() { - if (itsXPos > 0 && (str[0] != ' ' || str[0] != '\n')) - str = " " + str; - - itsRawContent += str; + itsRealHeight = 1; -# ifdef UTF8_ENABLED - wstring s = ToWString(str); - wstring tmp; -# else - string &s = str; - string tmp; -# endif + std::basic_string s = itsBuffer.Str(); - int x_pos = 0; - int space_pos = 0; + int x_pos; + int space_pos; int tab_size; - bool collect = 0; for (size_t i = 0; i < s.length(); i++) { @@ -67,7 +62,7 @@ void Scrollpad::Add(string str) if (s[i] != '\t') { -# ifdef UTF8_ENABLED +# ifdef _UTF8 itsXPos += wcwidth(s[i]); # else itsXPos++; @@ -76,41 +71,13 @@ void Scrollpad::Add(string str) else itsXPos += tab_size; - if (BBEnabled) - { - if (s[i] == '[' && (s[i+1] == '.' || s[i+1] == '/')) - collect = 1; - - if (collect) - { - if (s[i] != '[') - { - tmp += s[i]; - if (tmp.length() > 10) // the longest bbcode is 10 chars long - collect = 0; - } - else - tmp = s[i]; - } - - if (s[i] == ']') - collect = 0; - - if (!collect && !tmp.empty()) - { - if (IsValidColor(TO_STRING(tmp))) - itsXPos -= tmp.length(); - tmp.clear(); - } - } - if (s[i] == ' ') // if space, remember its position; { space_pos = i; x_pos = itsXPos; } - if (!collect && itsXPos >= itsWidth) + if (itsXPos >= itsWidth) { // if line is over, there was at least one space in this line and we are in the middle of the word, restore position to last known space and make it EOL if (space_pos > 0 && (s[i] != ' ' || s[i+1] != ' ')) @@ -121,15 +88,17 @@ void Scrollpad::Add(string str) } } - if (!collect && (itsXPos >= itsWidth || s[i] == '\n')) + if (itsXPos >= itsWidth || s[i] == '\n') { itsRealHeight++; itsXPos = 0; space_pos = 0; } } - itsContent += TO_STRING(s); Recreate(); + itsBuffer.SetTemp(&s); + reinterpret_cast(*this) << itsBuffer; + itsBuffer.SetTemp(0); } void Scrollpad::Recreate() @@ -139,16 +108,25 @@ void Scrollpad::Recreate() SetTimeout(itsWindowTimeout); SetColor(itsBaseColor, itsBgColor); keypad(itsWindow, 1); - Write(itsContent.c_str()); } -void Scrollpad::Refresh(bool) +void Scrollpad::Refresh() { prefresh(itsWindow, itsBeginning, 0, itsStartY, itsStartX, itsStartY+itsHeight-1, itsStartX+itsWidth); } -void Scrollpad::Resize(int width, int height) +void Scrollpad::MoveTo(size_t x, size_t y) +{ + itsStartX = x; + itsStartY = y; +} + +void Scrollpad::Resize(size_t width, size_t height) { + if (width+itsStartX > size_t(COLS) + || height+itsStartY > size_t(LINES)) + throw BadSize(); + if (itsBorder != brNone) { delwin(itsWinBorder); @@ -161,48 +139,45 @@ void Scrollpad::Resize(int width, int height) if (!itsTitle.empty()) width -= 2; - if (height > 0 && width > 0) - { - itsHeight = height; - itsWidth = width; - - itsBeginning = 0; - itsRealHeight = 1; - itsXPos = 0; - itsContent.clear(); - string tmp = itsRawContent; - itsRawContent.clear(); - Add(tmp); - Recreate(); - } + itsHeight = height; + itsWidth = width; + + itsBeginning = 0; + itsRealHeight = itsHeight; + itsXPos = 0; + Flush(); } -void Scrollpad::Go(Where where) +void Scrollpad::Scroll(Where where) { - int MaxBeginning = itsContent.size() < itsHeight ? 0 : itsRealHeight-itsHeight; + int MaxBeginning = /*itsContent.size() < itsHeight ? 0 : */itsRealHeight-itsHeight; switch (where) { case wUp: { - if (itsBeginning > 0) itsBeginning--; // for scrolling + if (itsBeginning > 0) + itsBeginning--; break; } case wDown: { - if (itsBeginning < MaxBeginning) itsBeginning++; // scroll + if (itsBeginning < MaxBeginning) + itsBeginning++; break; } case wPageUp: { itsBeginning -= itsHeight; - if (itsBeginning < 0) itsBeginning = 0; + if (itsBeginning < 0) + itsBeginning = 0; break; } case wPageDown: { itsBeginning += itsHeight; - if (itsBeginning > MaxBeginning) itsBeginning = MaxBeginning; + if (itsBeginning > MaxBeginning) + itsBeginning = MaxBeginning; break; } case wHome: @@ -218,24 +193,44 @@ void Scrollpad::Go(Where where) } } -void Scrollpad::Clear(bool clear_screen) +void Scrollpad::Clear(bool clrscr) { itsBeginning = 0; - itsRealHeight = 1; + itsRealHeight = itsHeight; itsXPos = 0; - itsContent.clear(); - itsRawContent.clear(); + itsBuffer.Clear(); wclear(itsWindow); delwin(itsWindow); itsWindow = newpad(itsHeight, itsWidth); SetTimeout(itsWindowTimeout); SetColor(itsColor, itsBgColor); keypad(itsWindow, 1); - if (clear_screen) + if (clrscr) Window::Clear(); } -Window * Scrollpad::EmptyClone() const +Scrollpad &Scrollpad::operator<<(std::ostream &(*os)(std::ostream&)) +{ + itsBuffer << os; + return *this; +} + +#ifdef _UTF8 +Scrollpad &Scrollpad::operator<<(const char *s) +{ + wchar_t *ws = ToWString(s); + itsBuffer << ws; + delete [] ws; + return *this; +} + +Scrollpad &Scrollpad::operator<<(const std::string &s) +{ + return operator<<(s.c_str()); +} +#endif // _UTF8 + +Scrollpad *Scrollpad::EmptyClone() const { return new Scrollpad(GetStartX(), GetStartY(), GetWidth(), GetHeight(), itsTitle, itsBaseColor, itsBorder); } diff --git a/src/scrollpad.h b/src/scrollpad.h index 3291b3ca..89803479 100644 --- a/src/scrollpad.h +++ b/src/scrollpad.h @@ -22,28 +22,50 @@ #define HAVE_SCROLLPAD_H #include "window.h" +#include "strbuffer.h" class Scrollpad: public Window { public: - Scrollpad(int, int, int, int, const string &, Color, Border); + Scrollpad(size_t, size_t, size_t, size_t, const std::string &, Color, Border); Scrollpad(const Scrollpad &); - virtual ~Scrollpad() {} - virtual void Add(string); - virtual void Refresh(bool = 0); - virtual void Go(Where); - virtual void Resize(int, int); - virtual void Clear(bool clear_screen = 1); - virtual Window * Clone() const { return new Scrollpad(*this); } - virtual Window * EmptyClone() const; + virtual ~Scrollpad() { } + + void Flush(); + std::basic_string Content() { return itsBuffer.Str(); } + + virtual void Refresh(); + virtual void Scroll(Where); + + virtual void MoveTo(size_t, size_t); + virtual void Resize(size_t, size_t); + virtual void Clear(bool = 1); + + template Scrollpad &operator<<(const T &t) + { + itsBuffer << t; + return *this; + } + + Scrollpad &operator<<(std::ostream &(*os)(std::ostream &)); + +# ifdef _UTF8 + Scrollpad &operator<<(const char *s); + Scrollpad &operator<<(const std::string &s); +# endif // _UTF8 + + virtual Scrollpad *Clone() const { return new Scrollpad(*this); } + virtual Scrollpad *EmptyClone() const; protected: virtual void Recreate(); - string itsContent; - string itsRawContent; + + basic_buffer itsBuffer; + int itsBeginning; - int itsRealHeight; - int itsXPos; + + size_t itsRealHeight; + size_t itsXPos; }; #endif diff --git a/src/song.cpp b/src/song.cpp index 70035565..0d041d72 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -30,7 +30,7 @@ string UNKNOWN_ALBUM; void DefineEmptyTags() { - if (Config.empty_tags_color != clDefault) + /*if (Config.empty_tags_color != clDefault) { const string et_col = IntoStr(Config.empty_tags_color); EMPTY_TAG = "[." + et_col + "][/" + et_col + "]"; @@ -39,12 +39,12 @@ void DefineEmptyTags() UNKNOWN_ALBUM = "[." + et_col + "][/" + et_col + "]"; } else - { + {*/ EMPTY_TAG = ""; - UNKNOWN_ARTIST = ""; - UNKNOWN_TITLE = ""; - UNKNOWN_ALBUM = "DisableBB(); - wFooter->AutoRefresh(0); wFooter->Bold(1); wFooter->GetXY(sx, sy); @@ -174,7 +172,7 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) { if (!playlist_length || mPlaylist->Size() < mPlaylist->GetHeight()) mPlaylist->Window::Clear(); - mPlaylist->Refresh(1); + mPlaylist->Refresh(); } } else @@ -263,7 +261,7 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) { WindowTitle("ncmpc++ ver. "VERSION); wFooter->SetColor(Config.progressbar_color); - mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); + mvwhline(wFooter->Raw(), 0, 0, 0, wFooter->GetWidth()); wFooter->SetColor(Config.statusbar_color); mPlaylist->BoldOption(old_playing, 0); now_playing = -1; @@ -291,7 +289,7 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) repeat_one_allowed = 0; if (!Mpd->GetElapsedTime()) - mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); + mvwhline(wFooter->Raw(), 0, 0, 0, wFooter->GetWidth()); if (Config.now_playing_lyrics && !Config.repeat_one_mode && current_screen == csLyrics && prev_screen == csPlaylist) reload_lyrics = 1; @@ -330,7 +328,7 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) wFooter->Bold(0); if (playing_song.length() > max_length_without_scroll) { -# ifdef UTF8_ENABLED +# ifdef _UTF8 playing_song += L" ** "; # else playing_song += " ** "; @@ -354,11 +352,11 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) double progressbar_size = (double)elapsed/(s.GetTotalLength()); int howlong = wFooter->GetWidth()*progressbar_size; wFooter->SetColor(Config.progressbar_color); - mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth()); + mvwhline(wFooter->Raw(), 0, 0, 0, wFooter->GetWidth()); if (s.GetTotalLength()) { - mvwhline(wFooter->RawWin(), 0, 0, '=',howlong); - mvwaddch(wFooter->RawWin(), 0, howlong, '>'); + mvwhline(wFooter->Raw(), 0, 0, '=',howlong); + mvwaddch(wFooter->Raw(), 0, howlong, '>'); } wFooter->SetColor(Config.statusbar_color); } @@ -413,10 +411,9 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) if (mpd_db_updating) switch_state += mpd_db_updating; - wHeader->DisableBB(); wHeader->Bold(1); wHeader->SetColor(Config.state_line_color); - mvwhline(wHeader->RawWin(), 1, 0, 0, wHeader->GetWidth()); + mvwhline(wHeader->Raw(), 1, 0, 0, wHeader->GetWidth()); if (!switch_state.empty()) { wHeader->WriteXY(wHeader->GetWidth()-switch_state.length()-3, 1, "["); @@ -425,10 +422,8 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) wHeader->SetColor(Config.state_line_color); wHeader->WriteXY(wHeader->GetWidth()-2, 1, "]"); } - wHeader->Refresh(); wHeader->SetColor(Config.header_color); wHeader->Bold(0); - wHeader->EnableBB(); header_update_status = 0; } if ((changed.Volume) && Config.header_visibility) @@ -439,12 +434,11 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) wHeader->WriteXY(wHeader->GetWidth()-volume_state.length(), 0, volume_state); wHeader->SetColor(Config.header_color); } + wHeader->Refresh(); if (current_screen == csPlaylist) mPlaylist->Refresh(); wFooter->Bold(0); wFooter->GotoXY(sx, sy); wFooter->Refresh(); - wFooter->AutoRefresh(1); - wFooter->EnableBB(); } diff --git a/src/tag_editor.cpp b/src/tag_editor.cpp index 2336e481..d8b3fc2a 100644 --- a/src/tag_editor.cpp +++ b/src/tag_editor.cpp @@ -107,7 +107,7 @@ namespace string GenerateFilename(const Song &s, string &pattern) { - string result = Window::OmitBBCodes(DisplaySong(s, &pattern)); + string result = DisplaySong(s, &pattern); EscapeUnallowedChars(result); return result; } @@ -440,9 +440,9 @@ void __deal_with_filenames(SongList &v) Main->Refresh(); Main->ReadKey(input); if (Keypressed(input, Key.Down)) - Main->Go(wDown); + Main->Scroll(wDown); else if (Keypressed(input, Key.Up)) - Main->Go(wUp); + Main->Scroll(wUp); } width = COLS*0.9; @@ -465,7 +465,7 @@ void __deal_with_filenames(SongList &v) { Legend = new Scrollpad((COLS-width)/2+one_width, (LINES-height)/2, two_width, height, "Legend", Config.main_color, Config.window_border); Legend->SetTimeout(ncmpcpp_window_timeout); - Legend->Add("%a - artist\n"); +/* Legend->Add("%a - artist\n"); Legend->Add("%t - title\n"); Legend->Add("%b - album\n"); Legend->Add("%y - year\n"); @@ -477,7 +477,7 @@ void __deal_with_filenames(SongList &v) Legend->Add("%C - comment\n\n"); Legend->Add("[.b]Files:[/b]\n"); for (SongList::const_iterator it = v.begin(); it != v.end(); it++) - Legend->Add("[." + Config.color2 + "]*[/" + Config.color2 + "] " + (*it)->GetName() + "\n"); + Legend->Add("[." + Config.color2 + "]*[/" + Config.color2 + "] " + (*it)->GetName() + "\n");*/ Preview = static_cast(Legend->EmptyClone()); Preview->SetTitle("Preview"); @@ -517,17 +517,17 @@ void __deal_with_filenames(SongList &v) Active->ReadKey(input); if (Keypressed(input, Key.Up)) - Active->Go(wUp); + Active->Scroll(wUp); else if (Keypressed(input, Key.Down)) - Active->Go(wDown); + Active->Scroll(wDown); else if (Keypressed(input, Key.PageUp)) - Active->Go(wPageUp); + Active->Scroll(wPageUp); else if (Keypressed(input, Key.PageDown)) - Active->Go(wPageDown); + Active->Scroll(wPageDown); else if (Keypressed(input, Key.Home)) - Active->Go(wHome); + Active->Scroll(wHome); else if (Keypressed(input, Key.End)) - Active->Go(wEnd); + Active->Scroll(wEnd); else if (Keypressed(input, Key.Enter) && Active == Main) { switch (Main->GetRealChoice()) @@ -559,8 +559,8 @@ void __deal_with_filenames(SongList &v) { if (preview) { - Preview->Add("[.b]" + s.GetName() + ":[/b]\n"); - Preview->Add(ParseFilename(s, Config.pattern, preview) + "\n"); +// Preview->Add("[.b]" + s.GetName() + ":[/b]\n"); +// Preview->Add(ParseFilename(s, Config.pattern, preview) + "\n"); } else ParseFilename(s, Config.pattern, preview); @@ -585,7 +585,7 @@ void __deal_with_filenames(SongList &v) } if (!preview) s.SetNewName(new_file + extension); - Preview->Add(file + " [." + Config.color2 + "]->[/" + Config.color2 + "] " + new_file + extension + "\n\n"); +// Preview->Add(file + " [." + Config.color2 + "]->[/" + Config.color2 + "] " + new_file + extension + "\n\n"); s.GetEmptyFields(0); } } @@ -635,7 +635,7 @@ void __deal_with_filenames(SongList &v) else if (Keypressed(input, Key.VolumeUp) && Active == Main) { Active->SetBorder(Config.window_border); - Active->Display(1); + Active->Display(); Active = Helper; Active->SetBorder(Config.active_window_border); Active->Display(); @@ -646,7 +646,7 @@ void __deal_with_filenames(SongList &v) Active->Display(); Active = Main; Active->SetBorder(Config.active_window_border); - Active->Display(1); + Active->Display(); } } } diff --git a/src/window.cpp b/src/window.cpp index 6e053137..640055b7 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -20,26 +20,59 @@ #include "window.h" -Window::Window(int startx, int starty, int width, int height, const string &title, Color color, Border border) : - itsWindow(0), - itsWinBorder(0), - itsGetStringHelper(0), - itsStartX(startx), - itsStartY(starty), - itsWidth(width), - itsHeight(height), - itsWindowTimeout(-1), - BBEnabled(1), - AutoRefreshEnabled(1), - itsTitle(title), - itsColor(color), - itsBaseColor(color), - itsBgColor(clDefault), - itsBaseBgColor(clDefault), - itsBorder(border) -{ - if (itsStartX < 0) itsStartX = 0; - if (itsStartY < 0) itsStartY = 0; +void InitScreen() +{ + setlocale(LC_ALL, ""); + initscr(); + if (has_colors()) + { + start_color(); + use_default_colors(); + int num = 1; + for (int i = -1; i < 8; i++) + for (int j = 0; j < 8; j++) + init_pair(num++, j, i); + } + noecho(); + cbreak(); + curs_set(0); +} + +void DestroyScreen() +{ + curs_set(1); + endwin(); +} + +Window::Window(size_t startx, + size_t starty, + size_t width, + size_t height, + const string &title, + Color color, + Border border) + : itsWindow(0), + itsWinBorder(0), + itsGetStringHelper(0), + itsStartX(startx), + itsStartY(starty), + itsWidth(width), + itsHeight(height), + itsWindowTimeout(-1), + itsX(0), + itsY(0), + itsTitle(title), + itsColor(color), + itsBaseColor(color), + itsBgColor(clDefault), + itsBaseBgColor(clDefault), + itsBorder(border) +{ + if (itsStartX > size_t(COLS) + || itsStartY > size_t(LINES) + || itsWidth+itsStartX > size_t(COLS) + || itsHeight+itsStartY > size_t(LINES)) + throw BadSize(); if (itsBorder != brNone) { @@ -57,10 +90,7 @@ Window::Window(int startx, int starty, int width, int height, const string &titl itsHeight -= 2; } - if (itsWidth > 0 && itsHeight > 0) - itsWindow = newwin(itsHeight, itsWidth, itsStartY, itsStartX); - else - itsWindow = newwin(0, 0, 0, 0); + itsWindow = newwin(itsHeight, itsWidth, itsStartY, itsStartX); SetColor(itsColor); keypad(itsWindow, 1); @@ -71,12 +101,13 @@ Window::Window(const Window &w) itsWindow = dupwin(w.itsWindow); itsWinBorder = dupwin(w.itsWinBorder); itsGetStringHelper = w.itsGetStringHelper; + itsWindowTimeout = w.itsWindowTimeout; + itsX = w.itsX; + itsY = w.itsY; itsStartX = w.itsStartX; itsStartY = w.itsStartY; itsWidth = w.itsWidth; itsHeight = w.itsHeight; - BBEnabled = w.BBEnabled; - AutoRefreshEnabled = w.AutoRefreshEnabled; itsTitle = w.itsTitle; itsColors = w.itsColors; itsColor = w.itsColor; @@ -84,6 +115,8 @@ Window::Window(const Window &w) itsBgColor = w.itsBgColor; itsBaseBgColor = w.itsBaseBgColor; itsBorder = w.itsBorder; + SetColor(itsColor, itsBgColor); + keypad(itsWindow, 1); } Window::~Window() @@ -230,13 +263,13 @@ void Window::ShowBorder() const refresh(); } -void Window::Display(bool stub) +void Window::Display() { ShowBorder(); - Refresh(stub); + Refresh(); } -void Window::Refresh(bool) +void Window::Refresh() { wrefresh(itsWindow); } @@ -269,11 +302,6 @@ void Window::AltCharset(bool alt) const alt ? wattron(itsWindow, A_ALTCHARSET) : wattroff(itsWindow, A_ALTCHARSET); } -void Window::Delay(bool delay) const -{ - nodelay(itsWindow, !delay); -} - void Window::SetTimeout(int timeout) { itsWindowTimeout = timeout; @@ -292,145 +320,17 @@ void Window::ReadKey() const void Window::Write(int limit, const string &str, bool clrtoeol) { - if (BBEnabled) - { - bool collect = false; - string color, tmp; - for (string::const_iterator it = str.begin(); it != str.end() && limit > 0; it++) - { - if (*it == '[' && (*(it+1) == '.' || *(it+1) == '/')) - collect = 1; - - if (!collect) - { - tmp += *it; - limit--; - } - else - { - if (*it != '[') - { - color += *it; - if (color.length() > 10) collect = 0; // longest bbcode is 10 chars long - } - else - { - limit -= color.length(); - tmp += color; - color = *it; - } - } - - if (*it == ']' || it+1 == str.end()) - collect = 0; - - if (!collect && !color.empty()) - { - waddstr(itsWindow,tmp.c_str()); - tmp.clear(); - - if (isdigit(color[2])) - { - int x, y; - getyx(itsWindow, y, x); - Coordinates coords = IntoCoordinates(color); - wmove(itsWindow, coords.second == -1 ? y : coords.second, coords.first); - limit -= coords.first-x; - } - else if (IsValidColor(color)) - { - ColorPair colors = IntoColor(color); - SetColor(colors.first, colors.second); - } - else - { - limit -= color.length(); - tmp += limit > 0 ? color : color.substr(0, color.length()+limit); - } - color.clear(); - } - } - if (!tmp.empty()) waddstr(itsWindow,tmp.c_str()); - } - else - waddstr(itsWindow,str.c_str()); - + waddstr(itsWindow,str.c_str()); if (clrtoeol) wclrtoeol(itsWindow); - if (AutoRefreshEnabled) - wrefresh(itsWindow); } -#ifdef UTF8_ENABLED +#ifdef _UTF8 void Window::Write(int limit, const wstring &str, bool clrtoeol) { - if (BBEnabled) - { - bool collect = false; - wstring color, tmp; - for (wstring::const_iterator it = str.begin(); it != str.end() && limit > 0; it++) - { - if (*it == '[' && (*(it+1) == '.' || *(it+1) == '/')) - collect = 1; - - if (!collect) - { - tmp += *it; - limit -= wcwidth(*it); - } - else - { - if (*it != '[') - { - color += *it; - if (color.length() > 10) collect = 0; // longest bbcode is 10 chars long - } - else - { - limit -= Length(color); - tmp += color; - color = *it; - } - } - - if (*it == ']' || it+1 == str.end()) - collect = 0; - - if (!collect && !color.empty()) - { - wprintw(itsWindow, "%ls", tmp.c_str()); - tmp.clear(); - - if (isdigit(color[2])) - { - int x, y; - getyx(itsWindow, y, x); - Coordinates coords = IntoCoordinates(ToString(color)); - wmove(itsWindow, coords.second < 0 ? y : coords.second, coords.first); - limit -= coords.first-x; - } - else if (IsValidColor(ToString(color))) - { - ColorPair colors = IntoColor(ToString(color)); - SetColor(colors.first, colors.second); - } - else - { - limit -= Length(color); - tmp += limit > 0 ? color : color.substr(0, color.length()+limit); - } - color.clear(); - } - } - if (!tmp.empty()) wprintw(itsWindow, "%ls", tmp.c_str()); - } - else - wprintw(itsWindow, "%ls", str.c_str()); - + wprintw(itsWindow, "%ls", str.c_str()); if (clrtoeol) wclrtoeol(itsWindow); - if (AutoRefreshEnabled) - wrefresh(itsWindow); } void Window::WriteXY(int x, int y, int limit, const wstring &str, bool cleartoeol) @@ -446,20 +346,20 @@ void Window::WriteXY(int x, int y, int limit, const string &str, bool cleartoeol Write(limit, str, cleartoeol); } -string Window::GetString(const string &base, unsigned int length, int width) const +string Window::GetString(const string &base, size_t length, size_t width) const { - int input, beginning, maxbeginning, minx, x, y, maxx; + int input; + size_t beginning, maxbeginning, minx, x, y, maxx; + getyx(itsWindow, y, x); minx = maxx = x; width--; - if (width == -1) + if (width == size_t(-1)) width = itsWidth-x-1; - if (width < 0) - return ""; curs_set(1); - wstring tmp = ToWString(base); + std::wstring tmp = ToWString(base); string tmp_in; wchar_t wc_in; @@ -570,26 +470,41 @@ string Window::GetString(const string &base, unsigned int length, int width) con } while (input != 10); curs_set(0); + return ToString(tmp); } -void Window::Scrollable(bool scrollable) const +void Window::GetXY(int &x, int &y) { - scrollok(itsWindow, scrollable); - idlok(itsWindow, scrollable); + getyx(itsWindow, y, x); + itsX = x; + itsY = y; } -void Window::GetXY(int &x, int &y) const +void Window::GotoXY(int x, int y) { - getyx(itsWindow, y, x); + wmove(itsWindow, y, x); + itsX = x; + itsY = y; } -void Window::GotoXY(int x, int y) const +const int &Window::X() const { - wmove(itsWindow, y, x); + return itsX; } -int Window::GetWidth() const +const int &Window::Y() const +{ + return itsY; +} + +void Window::Scrollable(bool scrollable) const +{ + scrollok(itsWindow, scrollable); + idlok(itsWindow, scrollable); +} + +size_t Window::GetWidth() const { if (itsBorder != brNone) return itsWidth+2; @@ -597,9 +512,9 @@ int Window::GetWidth() const return itsWidth; } -int Window::GetHeight() const +size_t Window::GetHeight() const { - int height = itsHeight; + size_t height = itsHeight; if (itsBorder != brNone) height += 2; if (!itsTitle.empty()) @@ -607,7 +522,7 @@ int Window::GetHeight() const return height; } -int Window::GetStartX() const +size_t Window::GetStartX() const { if (itsBorder != brNone) return itsStartX-1; @@ -615,9 +530,9 @@ int Window::GetStartX() const return itsStartX; } -int Window::GetStartY() const +size_t Window::GetStartY() const { - int starty = itsStartY; + size_t starty = itsStartY; if (itsBorder != brNone) starty--; if (!itsTitle.empty()) @@ -625,7 +540,7 @@ int Window::GetStartY() const return starty; } -string Window::GetTitle() const +const string &Window::GetTitle() const { return itsTitle; } @@ -640,186 +555,216 @@ Border Window::GetBorder() const return itsBorder; } -void Window::EnableColors() +void Window::Scroll(Where where) { - if (has_colors()) + idlok(itsWindow, 1); + scrollok(itsWindow, 1); + switch (where) { - start_color(); - use_default_colors(); - int num = 1; - for (int i = -1; i < 8; i++) - for (int j = 0; j < 8; j++) - init_pair(num++, j, i); + case wUp: + wscrl(itsWindow, 1); + break; + case wDown: + wscrl(itsWindow, -1); + break; + case wPageUp: + wscrl(itsWindow, itsWidth); + break; + case wPageDown: + wscrl(itsWindow, -itsWidth); + break; + default: + break; } + idlok(itsWindow, 0); + scrollok(itsWindow, 0); } -Window * Window::EmptyClone() const + +Window &Window::operator<<(const Colors &colors) { - return new Window(GetStartX(),GetStartY(),GetWidth(),GetHeight(),itsTitle,itsBaseColor,itsBorder); + if (colors.fg == clEnd || colors.bg == clEnd) + return *this; + itsColors.push(colors); + SetColor(colors.fg, colors.bg); + return *this; } -/*char * ToString(const wchar_t *ws) +Window &Window::operator<<(const Color &color) { - string s; - for (int i = 0; i < wcslen(ws); i++) + switch (color) { - char *c = new char[MB_CUR_MAX+1](); - if (wctomb(c, ws[i]) > 0) - s += c; - delete [] c; + case clDefault: + while (!itsColors.empty()) + itsColors.pop(); + SetColor(itsBaseColor, itsBaseBgColor); + break; + case clEnd: + if (!itsColors.empty()) + itsColors.pop(); + if (!itsColors.empty()) + SetColor(itsColors.top().fg, itsColors.top().bg); + else + SetColor(itsBaseColor, itsBaseBgColor); + break; + default: + itsColors.push(Colors(color, clDefault)); + SetColor(itsColors.top().fg, itsColors.top().bg); } - char *result = strdup(s.c_str()); - return result; + return *this; } -wchar_t * ToWString(const char *s) +Window &Window::operator<<(const Format &format) { - wchar_t *ws = new wchar_t[strlen(s)+1](); - mbstowcs(ws, s, strlen(s)); - return ws; -}*/ + switch (format) + { + case fmtNone: + Bold(0); + Reverse(0); + AltCharset(0); + break; + case fmtBold: + Bold(1); + break; + case fmtBoldEnd: + Bold(0); + break; + case fmtReverse: + Reverse(1); + break; + case fmtReverseEnd: + Reverse(0); + break; + case fmtAltCharset: + AltCharset(1); + break; + case fmtAltCharsetEnd: + AltCharset(0); + break; + } + return *this; +} -string ToString(const wstring &ws) +Window &Window::operator<<(const XY &coords) +{ + GotoXY(coords.x, coords.y); + return *this; +} + +Window &Window::operator<<(const char *s) +{ + wprintw(itsWindow, "%s", s); + return *this; +} + +Window &Window::operator<<(const char &c) +{ + wprintw(itsWindow, "%c", c); + return *this; +} + +Window &Window::operator<<(const wchar_t *ws) +{ + wprintw(itsWindow, "%ls", ws); + return *this; +} + +Window &Window::operator<<(const wchar_t &wc) +{ + wprintw(itsWindow, "%lc", wc); + return *this; +} + +Window &Window::operator<<(const int &i) +{ + wprintw(itsWindow, "%d", i); + return *this; +} + +Window &Window::operator<<(const double &d) +{ + wprintw(itsWindow, "%f", d); + return *this; +} + +Window &Window::operator<<(const string &s) +{ + wprintw(itsWindow, "%s", s.c_str()); + return *this; +} + +Window &Window::operator<<(const wstring &ws) +{ + for (wstring::const_iterator it = ws.begin(); it != ws.end(); it++) + wprintw(itsWindow, "%lc", *it); + return *this; +} + +Window &Window::operator<<(const size_t &s) +{ + wprintw(itsWindow, "%u", s); + return *this; +} + +Window * Window::EmptyClone() const +{ + return new Window(GetStartX(), GetStartY(), GetWidth(), GetHeight(), itsTitle, itsBaseColor, itsBorder); +} + +char *ToString(const wchar_t *ws) { - string s; - const wchar_t *c_ws = ws.c_str(); mbstate_t mbs; memset(&mbs, 0, sizeof(mbs)); - int len = wcsrtombs(NULL, &c_ws, 0, &mbs); + size_t len = wcsrtombs(NULL, &ws, 0, &mbs); - if (len <= 0) - return s; + if (len == size_t(-1)) + return 0; - char *c_s = new char[len+1](); - wcsrtombs(c_s, &c_ws, len, &mbs); - c_s[len] = 0; - s = c_s; - delete [] c_s; + char *s = new char[len+1](); + wcsrtombs(s, &ws, len, &mbs); + s[len] = 0; return s; } -wstring ToWString(const string &s) +wchar_t *ToWString(const char *s) { - wstring ws; - const char *c_s = s.c_str(); mbstate_t mbs; memset(&mbs, 0, sizeof(mbs)); - int len = mbsrtowcs(NULL, &c_s, 0, &mbs); + size_t len = mbsrtowcs(NULL, &s, 0, &mbs); - if (len <= 0) - return ws; + if (len == size_t(-1)) + return 0; - wchar_t *c_ws = new wchar_t[len+1](); - mbsrtowcs(c_ws, &c_s, len, &mbs); - c_ws[len] = 0; - ws = c_ws; - delete [] c_ws; + wchar_t *ws = new wchar_t[len+1](); + mbsrtowcs(ws, &s, len, &mbs); + ws[len] = 0; return ws; } -Coordinates Window::IntoCoordinates(const string &s) +string ToString(const wstring &ws) { - Coordinates result; - size_t sep = s.find(","); - if (sep != string::npos) + string result; + char *s = ToString(ws.c_str()); + if (s) { - result.first = atoi(s.substr(2, sep-2).c_str()); - result.second = atoi(s.substr(sep+1).c_str()); - } - else - { - result.first = atoi(s.substr(2).c_str()); - result.second = -1; + result = s; + delete [] s; } return result; } -string Window::OmitBBCodes(const string &str) +wstring ToWString(const string &s) { - bool collect = false; - string tmp, color, result; - for (string::const_iterator it = str.begin(); it != str.end(); it++) + wstring result; + wchar_t *ws = ToWString(s.c_str()); + if (ws) { - if (*it == '[' && (*(it+1) == '.' || *(it+1) == '/')) - collect = 1; - - if (!collect) - tmp += *it; - else - { - if (*it != '[') - color += *it; - else - { - tmp += color; - color = *it; - } - } - - if (*it == ']' || it+1 == str.end()) - collect = 0; - - if (!collect && !color.empty()) - { - result += tmp; - tmp.clear(); - if (!isdigit(tmp[2]) && !IsValidColor(color)) - tmp += color; - color.clear(); - } + result = ws; + delete [] ws; } - if (!tmp.empty()) result += tmp; return result; } -size_t Window::RealLength(const string &s) -{ - if (s.empty()) - return 0; - - bool collect = false; - int length = 0; - -# ifdef UTF8_ENABLED - wstring ws = ToWString(s); - wstring tmp; -# else - const string &ws = s; - string tmp; -# endif - - for (int i = 0; i < ws.length(); i++, length++) - { - if (ws[i] == '[' && (ws[i+1] == '.' || ws[i+1] == '/')) - collect = 1; - - if (collect) - { - if (ws[i] != '[') - tmp += ws[i]; - else - tmp = ws[i]; - } - - if (ws[i] == ']') - collect = 0; - - if (!collect && !tmp.empty()) - { - if (isdigit(tmp[2]) || IsValidColor(TO_STRING(tmp))) - { -# ifdef UTF8_ENABLED - length -= Length(tmp); -# else - length -= tmp.length(); -# endif - } - tmp.clear(); - } - } - return length; -} - size_t Window::Length(const wstring &ws) { size_t length = 0; diff --git a/src/window.h b/src/window.h index 2d926b1e..1b38178c 100644 --- a/src/window.h +++ b/src/window.h @@ -33,13 +33,15 @@ #include #include -#ifdef UTF8_ENABLED +#ifdef _UTF8 # define UNICODE 1 +# define my_char_t wchar_t # define my_string_t wstring # define TO_STRING(x) ToString(x) # define TO_WSTRING(x) ToWString(x) #else # define UNICODE 0 +# define my_char_t char # define my_string_t string # define TO_STRING(x) x # define TO_WSTRING(x) x @@ -49,70 +51,114 @@ using std::string; using std::wstring; using std::vector; -enum Color { clDefault, clBlack, clRed, clGreen, clYellow, clBlue, clMagenta, clCyan, clWhite }; +enum Color { clDefault, clBlack, clRed, clGreen, clYellow, clBlue, clMagenta, clCyan, clWhite, clEnd }; +enum Format { fmtNone = 100, fmtBold, fmtBoldEnd, fmtReverse, fmtReverseEnd, fmtAltCharset, fmtAltCharsetEnd }; enum Border { brNone, brBlack, brRed, brGreen, brYellow, brBlue, brMagenta, brCyan, brWhite }; enum Where { wUp, wDown, wPageUp, wPageDown, wHome, wEnd }; typedef void (*GetStringHelper)(); -typedef std::pair ColorPair; -typedef std::pair Coordinates; -string ToString(const wstring &); -wstring ToWString(const string &); +void InitScreen(); +void DestroyScreen(); + +struct Colors +{ + Colors(Color one, Color two = clDefault) : fg(one), bg(two) { } + Color fg; + Color bg; +}; + +struct XY +{ + XY(int xx, int yy) : x(xx), y(yy) { } + int x; + int y; +}; + +char *ToString(const wchar_t *); +wchar_t *ToWString(const char *); +std::string ToString(const std::wstring &); +std::wstring ToWString(const std::string &); class Window { public: - Window(int, int, int, int, const string &, Color, Border); + Window(size_t, size_t, size_t, size_t, const std::string &, Color, Border); Window(const Window &); virtual ~Window(); - virtual WINDOW *RawWin() const { return itsWindow; } - virtual void SetGetStringHelper(GetStringHelper helper) { itsGetStringHelper = helper; } - virtual void SetColor(Color, Color = clDefault); - virtual void SetBaseColor(Color, Color = clDefault); - virtual void SetBorder(Border); - virtual void EnableBB() { BBEnabled = 1; } - virtual void DisableBB() { BBEnabled = 0; } - virtual void SetTitle(const string &); + + WINDOW *Raw() const { return itsWindow; } + + size_t GetWidth() const; + size_t GetHeight() const; + size_t GetStartX() const; + size_t GetStartY() const; + + const std::string &GetTitle() const; + Color GetColor() const; + Border GetBorder() const; + std::string GetString(const std::string &, size_t = -1, size_t = 0) const; + string GetString(unsigned int length = -1, int width = 0) const { return GetString("", length, width); } + void GetXY(int &, int &); + void GotoXY(int, int); + const int &X() const; + const int &Y() const; + + void SetGetStringHelper(GetStringHelper helper) { itsGetStringHelper = helper; } + void SetColor(Color, Color = clDefault); + void SetBaseColor(Color, Color = clDefault); + void SetBorder(Border); + void SetTimeout(int); + void SetTitle(const string &); + + void Hide(char = 32) const; + void Bold(bool) const; + void Reverse(bool) const; + void AltCharset(bool) const; + + void Display(); + virtual void Refresh(); + virtual void MoveTo(int, int); virtual void Resize(int, int); - virtual void Display(bool = 0); - virtual void Refresh(bool = 0); virtual void Clear(bool stub = 1); - virtual void Hide(char = 32) const; - virtual void Bold(bool) const; - virtual void Reverse(bool) const; - virtual void AltCharset(bool) const; - virtual void Delay(bool) const; - virtual void SetTimeout(int); - virtual void AutoRefresh(bool val) { AutoRefreshEnabled = val; } - virtual void ReadKey(int &) const; - virtual void ReadKey() const; - virtual void Write(const string &s, bool cte = 0) { Write(0xFFFF, s, cte); } - virtual void Write(int, const string &, bool = 0); - virtual void WriteXY(int x, int y, const string &s, bool ete = 0) { WriteXY(x, y, 0xFFFF, s, ete); } - virtual void WriteXY(int, int, int, const string &, bool = 0); -# ifdef UTF8_ENABLED - virtual void Write(const wstring &s, bool cte = 0) { Write(0xFFFF, s, cte); } - virtual void Write(int, const wstring &, bool = 0); - virtual void WriteXY(int x, int y, const wstring &s, bool ete = 0) { WriteXY(x, y, 0xFFFF, s, ete); } - virtual void WriteXY(int, int, int, const wstring &, bool = 0); + + void ReadKey(int &) const; + void ReadKey() const; + + void Write(const string &s, bool cte = 0) { Write(0xFFFF, s, cte); } + void Write(int, const string &, bool = 0); + void WriteXY(int x, int y, const string &s, bool ete = 0) { WriteXY(x, y, 0xFFFF, s, ete); } + void WriteXY(int, int, int, const string &, bool = 0); +# ifdef _UTF8 + void Write(const wstring &s, bool cte = 0) { Write(0xFFFF, s, cte); } + void Write(int, const wstring &, bool = 0); + void WriteXY(int x, int y, const wstring &s, bool ete = 0) { WriteXY(x, y, 0xFFFF, s, ete); } + void WriteXY(int, int, int, const wstring &, bool = 0); # endif - virtual string GetString(const string &, unsigned int = -1, int = 0) const; - virtual string GetString(unsigned int length = -1, int width = 0) const { return GetString("", length, width); } - virtual void Scrollable(bool) const; - virtual void GetXY(int &, int &) const; - virtual void GotoXY(int, int) const; - virtual int GetWidth() const; - virtual int GetHeight() const; - virtual int GetStartX() const; - virtual int GetStartY() const; - virtual string GetTitle() const; - virtual Color GetColor() const; - virtual Border GetBorder() const; - - virtual Window * Clone() const { return new Window(*this); } - virtual Window * EmptyClone() const; + + void Scrollable(bool) const; + virtual void Scroll(Where); + + Window &operator<<(const Colors &); + Window &operator<<(const Color &); + Window &operator<<(const Format &); + Window &operator<<(const XY &); + Window &operator<<(const char *); + Window &operator<<(const char &); + Window &operator<<(const wchar_t *); + Window &operator<<(const wchar_t &); + Window &operator<<(const int &); + Window &operator<<(const double &); + Window &operator<<(const size_t &); + + Window &operator<<(const std::string &); + Window &operator<<(const std::wstring &); + + virtual Window *Clone() const { return new Window(*this); } + virtual Window *EmptyClone() const; + + // stubs for inherits, ugly shit, needs improvement virtual void Select(int, bool) { } @@ -123,38 +169,40 @@ class Window virtual bool IsStatic(int = -1) const { return 0; } virtual void Highlight(int) { } virtual string GetOption(int = -1) const { return ""; } - virtual void Go(Where) { } // for Menu and Scrollpad class virtual int GetChoice() const { return -1; } // for Menu class - virtual void Add(string str) { Write(str); } // for Scrollpad class - - static void EnableColors(); - static Coordinates IntoCoordinates(const string &); - static bool IsValidColor(const string &); - static string OmitBBCodes(const string &); - static size_t RealLength(const string &); - static size_t Length(const string &s) { return Length(ToWString(s)); } + //virtual void Add(string str) { Write(str); } // for Scrollpad class + static size_t Length(const wstring &); protected: + + class BadSize { }; + virtual void Recreate(); virtual void ShowBorder() const; - virtual ColorPair IntoColor(const string &); + WINDOW *itsWindow; WINDOW *itsWinBorder; + GetStringHelper itsGetStringHelper; - int itsStartX; - int itsStartY; - int itsWidth; - int itsHeight; + + size_t itsStartX; + size_t itsStartY; + size_t itsWidth; + size_t itsHeight; + int itsWindowTimeout; - bool BBEnabled; - bool AutoRefreshEnabled; + int itsX; + int itsY; + string itsTitle; - std::stack itsColors; + std::stack itsColors; + Color itsColor; Color itsBaseColor; Color itsBgColor; Color itsBaseBgColor; + Border itsBorder; };