X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/d6cf2345a35896448e19bfb294ffe66faab00f86..dfad5beea77d75983f6ff8a1b8296b74dd48203e:/apt-private/acqprogress.cc?ds=sidebyside diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index 14a53eacb..0c606e48e 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -1,10 +1,9 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $ /* ###################################################################### - Acquire Progress - Command line progress meter - + Acquire Progress - Command line progress meter + ##################################################################### */ /*}}}*/ // Include files /*{{{*/ @@ -23,20 +22,18 @@ #include #include #include +#include #include #include /*}}}*/ -using namespace std; - // AcqTextStatus::AcqTextStatus - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) : - pkgAcquireStatus(), ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet) +AcqTextStatus::AcqTextStatus(std::ostream &out, unsigned int &ScreenWidth,unsigned int const Quiet) : + pkgAcquireStatus(), out(out), ScreenWidth(ScreenWidth), LastLineLength(0), ID(0), Quiet(Quiet) { - BlankLine[0] = 0; // testcases use it to disable pulses without disabling other user messages if (Quiet == 0 && _config->FindB("quiet::NoUpdate", false) == true) this->Quiet = 1; @@ -48,7 +45,7 @@ AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) void AcqTextStatus::Start() { pkgAcquireStatus::Start(); - BlankLine[0] = 0; + LastLineLength = 0; ID = 1; } /*}}}*/ @@ -60,11 +57,10 @@ void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); - cout << _("Hit ") << Itm.Description; - cout << endl; + out << _("Hit ") << Itm.Description; + out << std::endl; Update = true; } /*}}}*/ @@ -82,13 +78,12 @@ void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); - cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description; + out << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description; if (Itm.Owner->FileSize != 0) - cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; - cout << endl; + out << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; + out << std::endl; } /*}}}*/ // AcqTextStatus::Done - Completed a download /*{{{*/ @@ -111,20 +106,19 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; + clearLastLine(); if (Itm.Owner->Status == pkgAcquire::Item::StatDone) { - cout << _("Ign ") << Itm.Description << endl; + out << _("Ign ") << Itm.Description << std::endl; if (Itm.Owner->ErrorText.empty() == false && _config->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true) - cout << " " << Itm.Owner->ErrorText << endl; + out << " " << Itm.Owner->ErrorText << std::endl; } else { - cout << _("Err ") << Itm.Description << endl; - cout << " " << Itm.Owner->ErrorText << endl; + out << _("Err ") << Itm.Description << std::endl; + out << " " << Itm.Owner->ErrorText << std::endl; } Update = true; @@ -140,14 +134,13 @@ void AcqTextStatus::Stop() if (Quiet > 1) return; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r' << flush; + clearLastLine(); if (_config->FindB("quiet::NoStatistic", false) == true) return; if (FetchedBytes != 0 && _error->PendingError() == false) - ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"), + ioprintf(out,_("Fetched %sB in %s (%sB/s)\n"), SizeToStr(FetchedBytes).c_str(), TimeToStr(ElapsedTime).c_str(), SizeToStr(CurrentCPS).c_str()); @@ -156,7 +149,7 @@ void AcqTextStatus::Stop() // AcqTextStatus::Pulse - Regular event pulse /*{{{*/ // --------------------------------------------------------------------- /* This draws the current progress. Each line has an overall percent - meter and a per active item status meter along with an overall + meter and a per active item status meter along with an overall bandwidth and ETA indicator. */ bool AcqTextStatus::Pulse(pkgAcquire *Owner) { @@ -167,77 +160,66 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) enum {Long = 0,Medium,Short} Mode = Medium; - char Buffer[sizeof(BlankLine)]; - char *End = Buffer + sizeof(Buffer); - char *S = Buffer; - if (ScreenWidth >= sizeof(Buffer)) - ScreenWidth = sizeof(Buffer)-1; - - // Put in the percent done - sprintf(S,"%.0f%%", Percent); - - bool Shown = false; - for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; - I = Owner->WorkerStep(I)) + std::string Line; { - S += strlen(S); - - // There is no item running - if (I->CurrentItem == 0) + std::stringstream S; + for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0; + I = Owner->WorkerStep(I)) { - if (I->Status.empty() == false) + // There is no item running + if (I->CurrentItem == 0) { - snprintf(S,End-S," [%s]",I->Status.c_str()); - Shown = true; - } - - continue; - } + if (I->Status.empty() == false) + S << " [" << I->Status << "]"; - Shown = true; - - // Add in the short description - if (I->CurrentItem->Owner->ID != 0) - snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID, - I->CurrentItem->ShortDesc.c_str()); - else - snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str()); - S += strlen(S); + continue; + } - // Show the short mode string - if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false) - { - snprintf(S,End-S, " %s", I->CurrentItem->Owner->ActiveSubprocess.c_str()); - S += strlen(S); - } + // Add in the short description + S << " ["; + if (I->CurrentItem->Owner->ID != 0) + S << I->CurrentItem->Owner->ID << " "; + S << I->CurrentItem->ShortDesc; - // Add the current progress - if (Mode == Long) - snprintf(S,End-S," %llu",I->CurrentSize); - else - { - if (Mode == Medium || I->TotalSize == 0) - snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str()); - } - S += strlen(S); + // Show the short mode string + if (I->CurrentItem->Owner->ActiveSubprocess.empty() == false) + S << " " << I->CurrentItem->Owner->ActiveSubprocess; - // Add the total size and percent - if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) - { - if (Mode == Short) - snprintf(S,End-S," %.0f%%", - (I->CurrentSize*100.0)/I->TotalSize); + // Add the current progress + if (Mode == Long) + S << " " << I->CurrentSize; else - snprintf(S,End-S,"/%sB %.0f%%",SizeToStr(I->TotalSize).c_str(), + { + if (Mode == Medium || I->TotalSize == 0) + S << " " << SizeToStr(I->CurrentSize) << "B"; + } + + // Add the total size and percent + if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false) + { + if (Mode == Short) + ioprintf(S, " %.0f%%", (I->CurrentSize*100.0)/I->TotalSize); + else + ioprintf(S, "/%sB %.0f%%", SizeToStr(I->TotalSize).c_str(), (I->CurrentSize*100.0)/I->TotalSize); + } + S << "]"; } - S += strlen(S); - snprintf(S,End-S,"]"); - } - // Show something.. - if (Shown == false) - snprintf(S,End-S,_(" [Working]")); + // Show at least something + Line = S.str(); + S.clear(); + if (Line.empty() == true) + Line = _(" [Working]"); + } + // Put in the percent done + { + std::stringstream S; + ioprintf(S, "%.0f%%", Percent); + S << Line; + Line = S.str(); + S.clear(); + } /* Put in the ETA and cps meter, block off signals to prevent strangeness during resizing */ @@ -248,34 +230,33 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) if (CurrentCPS != 0) { - char Tmp[300]; unsigned long long ETA = (TotalBytes - CurrentBytes)/CurrentCPS; - sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str()); - unsigned int Len = strlen(Buffer); - unsigned int LenT = strlen(Tmp); - if (Len + LenT < ScreenWidth) + std::string Tmp = " " + SizeToStr(CurrentCPS) + "B/s " + TimeToStr(ETA); + size_t alignment = Line.length() + Tmp.length(); + if (alignment < ScreenWidth) { - memset(Buffer + Len,' ',ScreenWidth - Len); - strcpy(Buffer + ScreenWidth - LenT,Tmp); + alignment = ScreenWidth - alignment; + for (size_t i = 0; i < alignment; ++i) + Line.append(" "); + Line.append(Tmp); } } - Buffer[ScreenWidth] = 0; - BlankLine[ScreenWidth] = 0; + if (Line.length() > ScreenWidth) + Line.erase(ScreenWidth); sigprocmask(SIG_SETMASK,&OldSigs,0); // Draw the current status if (_config->FindB("Apt::Color", false) == true) - cout << _config->Find("APT::Color::Yellow"); - if (strlen(Buffer) == strlen(BlankLine)) - cout << '\r' << Buffer << flush; + out << _config->Find("APT::Color::Yellow"); + if (LastLineLength > Line.length()) + clearLastLine(); else - cout << '\r' << BlankLine << '\r' << Buffer << flush; + out << '\r'; + out << Line << std::flush; if (_config->FindB("Apt::Color", false) == true) - cout << _config->Find("APT::Color::Neutral") << flush; - - memset(BlankLine,' ',strlen(Buffer)); - BlankLine[strlen(Buffer)] = 0; + out << _config->Find("APT::Color::Neutral") << std::flush; + LastLineLength = Line.length(); Update = false; return true; @@ -284,7 +265,7 @@ bool AcqTextStatus::Pulse(pkgAcquire *Owner) // AcqTextStatus::MediaChange - Media need to be swapped /*{{{*/ // --------------------------------------------------------------------- /* Prompt for a media swap */ -bool AcqTextStatus::MediaChange(string Media,string Drive) +bool AcqTextStatus::MediaChange(std::string Media, std::string Drive) { // If we do not output on a terminal and one of the options to avoid user // interaction is given, we assume that no user is present who could react @@ -296,9 +277,8 @@ bool AcqTextStatus::MediaChange(string Media,string Drive) return false; - if (Quiet <= 0) - cout << '\r' << BlankLine << '\r'; - ioprintf(cout,_("Media change: please insert the disc labeled\n" + clearLastLine(); + ioprintf(out,_("Media change: please insert the disc labeled\n" " '%s'\n" "in the drive '%s' and press enter\n"), Media.c_str(),Drive.c_str()); @@ -317,3 +297,17 @@ bool AcqTextStatus::MediaChange(string Media,string Drive) return bStatus; } /*}}}*/ +void AcqTextStatus::clearLastLine() { /*{{{*/ + if (Quiet > 0 || LastLineLength == 0) + return; + + // do not try to clear more than the (now smaller) screen + if (LastLineLength > ScreenWidth) + LastLineLength = ScreenWidth; + + out << '\r'; + for (size_t i = 0; i < LastLineLength; ++i) + out << ' '; + out << '\r' << std::flush; +} + /*}}}*/