Stop building the DFA image automatically
[mspang/inapt.git] / acqprogress.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: acqprogress.cc,v 1.24 2003/04/27 01:56:48 doogie Exp $
4 /* ######################################################################
5
6    Acquire Progress - Command line progress meter 
7    
8    ##################################################################### */
9                                                                         /*}}}*/
10 // Include files                                                        /*{{{*/
11 #include "acqprogress.h"
12 #include <apt-pkg/acquire-item.h>
13 #include <apt-pkg/acquire-worker.h>
14 #include <apt-pkg/strutl.h>
15 #include <apt-pkg/error.h>
16
17     
18 #include <stdio.h>
19 #include <signal.h>
20 #include <iostream>
21
22 #define _
23                                                                         /*}}}*/
24
25 using namespace std;
26
27 // AcqTextStatus::AcqTextStatus - Constructor                           /*{{{*/
28 // ---------------------------------------------------------------------
29 /* */
30 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
31     ScreenWidth(ScreenWidth), Quiet(Quiet)
32 {
33 }
34                                                                         /*}}}*/
35 // AcqTextStatus::Start - Downloading has started                       /*{{{*/
36 // ---------------------------------------------------------------------
37 /* */
38 void AcqTextStatus::Start() 
39 {
40    pkgAcquireStatus::Start(); 
41    BlankLine[0] = 0;
42    ID = 1;
43 };
44                                                                         /*}}}*/
45 // AcqTextStatus::IMSHit - Called when an item got a HIT response       /*{{{*/
46 // ---------------------------------------------------------------------
47 /* */
48 void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm)
49 {
50    if (Quiet > 1)
51       return;
52
53    if (Quiet <= 0)
54       cout << '\r' << BlankLine << '\r';   
55    
56    cout << _("Hit ") << Itm.Description;
57    if (Itm.Owner->FileSize != 0)
58       cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
59    cout << endl;
60    Update = true;
61 };
62                                                                         /*}}}*/
63 // AcqTextStatus::Fetch - An item has started to download               /*{{{*/
64 // ---------------------------------------------------------------------
65 /* This prints out the short description and the expected size */
66 void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm)
67 {
68    Update = true;
69    if (Itm.Owner->Complete == true)
70       return;
71    
72    Itm.Owner->ID = ID++;
73    
74    if (Quiet > 1)
75       return;
76
77    if (Quiet <= 0)
78       cout << '\r' << BlankLine << '\r';
79    
80    cout << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description;
81    if (Itm.Owner->FileSize != 0)
82       cout << " [" << SizeToStr(Itm.Owner->FileSize) << "B]";
83    cout << endl;
84 };
85                                                                         /*}}}*/
86 // AcqTextStatus::Done - Completed a download                           /*{{{*/
87 // ---------------------------------------------------------------------
88 /* We don't display anything... */
89 void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm)
90 {
91    Update = true;
92 };
93                                                                         /*}}}*/
94 // AcqTextStatus::Fail - Called when an item fails to download          /*{{{*/
95 // ---------------------------------------------------------------------
96 /* We print out the error text  */
97 void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm)
98 {
99    if (Quiet > 1)
100       return;
101
102    // Ignore certain kinds of transient failures (bad code)
103    if (Itm.Owner->Status == pkgAcquire::Item::StatIdle)
104       return;
105       
106    if (Quiet <= 0)
107       cout << '\r' << BlankLine << '\r';
108    
109    if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
110    {
111       cout << _("Ign ") << Itm.Description << endl;
112    }
113    else
114    {
115       cout << _("Err ") << Itm.Description << endl;
116       cout << "  " << Itm.Owner->ErrorText << endl;
117    }
118    
119    Update = true;
120 };
121                                                                         /*}}}*/
122 // AcqTextStatus::Stop - Finished downloading                           /*{{{*/
123 // ---------------------------------------------------------------------
124 /* This prints out the bytes downloaded and the overall average line
125    speed */
126 void AcqTextStatus::Stop()
127 {
128    pkgAcquireStatus::Stop();
129    if (Quiet > 1)
130       return;
131
132    if (Quiet <= 0)
133       cout << '\r' << BlankLine << '\r' << flush;
134
135    if (FetchedBytes != 0 && _error->PendingError() == false)
136       ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"),
137                SizeToStr(FetchedBytes).c_str(),
138                TimeToStr(ElapsedTime).c_str(),
139                SizeToStr(CurrentCPS).c_str());
140 }
141                                                                         /*}}}*/
142 // AcqTextStatus::Pulse - Regular event pulse                           /*{{{*/
143 // ---------------------------------------------------------------------
144 /* This draws the current progress. Each line has an overall percent
145    meter and a per active item status meter along with an overall 
146    bandwidth and ETA indicator. */
147 bool AcqTextStatus::Pulse(pkgAcquire *Owner)
148 {
149    pkgAcquireStatus::Pulse(Owner);
150    
151    if (Quiet > 0)
152       return true;
153    
154    enum {Long = 0,Medium,Short} Mode = Long;
155    
156    char Buffer[sizeof(BlankLine)];
157    char *End = Buffer + sizeof(Buffer);
158    char *S = Buffer;
159    if (ScreenWidth >= sizeof(Buffer))
160       ScreenWidth = sizeof(Buffer)-1;
161
162    // Put in the percent done
163    sprintf(S,"%ld%%",long(double((CurrentBytes + CurrentItems)*100.0)/double(TotalBytes+TotalItems)));
164
165    bool Shown = false;
166    for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
167         I = Owner->WorkerStep(I))
168    {
169       S += strlen(S);
170       
171       // There is no item running 
172       if (I->CurrentItem == 0)
173       {
174          if (I->Status.empty() == false)
175          {
176             snprintf(S,End-S," [%s]",I->Status.c_str());
177             Shown = true;
178          }
179          
180          continue;
181       }
182
183       Shown = true;
184       
185       // Add in the short description
186       if (I->CurrentItem->Owner->ID != 0)
187          snprintf(S,End-S," [%lu %s",I->CurrentItem->Owner->ID,
188                   I->CurrentItem->ShortDesc.c_str());
189       else
190          snprintf(S,End-S," [%s",I->CurrentItem->ShortDesc.c_str());
191       S += strlen(S);
192
193       // Show the short mode string
194       if (I->CurrentItem->Owner->Mode != 0)
195       {
196          snprintf(S,End-S," %s",I->CurrentItem->Owner->Mode);
197          S += strlen(S);
198       }
199             
200       // Add the current progress
201       if (Mode == Long)
202          snprintf(S,End-S," %lu",I->CurrentSize);
203       else
204       {
205          if (Mode == Medium || I->TotalSize == 0)
206             snprintf(S,End-S," %sB",SizeToStr(I->CurrentSize).c_str());
207       }
208       S += strlen(S);
209       
210       // Add the total size and percent
211       if (I->TotalSize > 0 && I->CurrentItem->Owner->Complete == false)
212       {
213          if (Mode == Short)
214             snprintf(S,End-S," %lu%%",
215                      long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
216          else
217             snprintf(S,End-S,"/%sB %lu%%",SizeToStr(I->TotalSize).c_str(),
218                      long(double(I->CurrentSize*100.0)/double(I->TotalSize)));
219       }      
220       S += strlen(S);
221       snprintf(S,End-S,"]");
222    }
223
224    // Show something..
225    if (Shown == false)
226       snprintf(S,End-S,_(" [Working]"));
227       
228    /* Put in the ETA and cps meter, block off signals to prevent strangeness
229       during resizing */
230    sigset_t Sigs,OldSigs;
231    sigemptyset(&Sigs);
232    sigaddset(&Sigs,SIGWINCH);
233    sigprocmask(SIG_BLOCK,&Sigs,&OldSigs);
234    
235    if (CurrentCPS != 0)
236    {      
237       char Tmp[300];
238       unsigned long ETA = (unsigned long)((TotalBytes - CurrentBytes)/CurrentCPS);
239       sprintf(Tmp," %sB/s %s",SizeToStr(CurrentCPS).c_str(),TimeToStr(ETA).c_str());
240       unsigned int Len = strlen(Buffer);
241       unsigned int LenT = strlen(Tmp);
242       if (Len + LenT < ScreenWidth)
243       {  
244          memset(Buffer + Len,' ',ScreenWidth - Len);
245          strcpy(Buffer + ScreenWidth - LenT,Tmp);
246       }      
247    }
248    Buffer[ScreenWidth] = 0;
249    BlankLine[ScreenWidth] = 0;
250    sigprocmask(SIG_SETMASK,&OldSigs,0);
251
252    // Draw the current status
253    if (strlen(Buffer) == strlen(BlankLine))
254       cout << '\r' << Buffer << flush;
255    else
256       cout << '\r' << BlankLine << '\r' << Buffer << flush;
257    memset(BlankLine,' ',strlen(Buffer));
258    BlankLine[strlen(Buffer)] = 0;
259    
260    Update = false;
261
262    return true;
263 }
264                                                                         /*}}}*/
265 // AcqTextStatus::MediaChange - Media need to be swapped                /*{{{*/
266 // ---------------------------------------------------------------------
267 /* Prompt for a media swap */
268 bool AcqTextStatus::MediaChange(string Media,string Drive)
269 {
270    if (Quiet <= 0)
271       cout << '\r' << BlankLine << '\r';
272    ioprintf(cout,_("Media change: please insert the disc labeled\n"
273                    " '%s'\n"
274                    "in the drive '%s' and press enter\n"),
275             Media.c_str(),Drive.c_str());
276
277    char C = 0;
278    bool bStatus = true;
279    while (C != '\n' && C != '\r')
280    {
281       int len = read(STDIN_FILENO,&C,1);
282       if(C == 'c' || len <= 0)
283          bStatus = false;
284    }
285
286    if(bStatus)
287       Update = true;
288    return bStatus;
289 }
290                                                                         /*}}}*/