Meter.c 14.3 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop - Meter.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2004-2011 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
8
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

#include "Meter.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9
10

#include "RichString.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
11
12
#include "Object.h"
#include "CRT.h"
David Hunt's avatar
David Hunt committed
13
#include "StringUtils.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
14
#include "ListItem.h"
15
#include "Settings.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
16
17
18
19
20

#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
21
#include <assert.h>
22
#include <sys/time.h>
23

Hisham Muhammad's avatar
Hisham Muhammad committed
24
#define METER_BUFFER_LEN 256
Hisham Muhammad's avatar
Hisham Muhammad committed
25

26
27
#define GRAPH_DELAY (DEFAULT_DELAY/2)

28
29
#define GRAPH_HEIGHT 4 /* Unit: rows (lines) */

Hisham Muhammad's avatar
Hisham Muhammad committed
30
/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
31
#include "ListItem.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
32
33

#include <sys/time.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
34
35
36

typedef struct Meter_ Meter;

37
38
39
typedef void(*Meter_Init)(Meter*);
typedef void(*Meter_Done)(Meter*);
typedef void(*Meter_UpdateMode)(Meter*, int);
40
typedef void(*Meter_SetValues)(Meter*, char*, int);
Hisham Muhammad's avatar
Hisham Muhammad committed
41
42
typedef void(*Meter_Draw)(Meter*, int, int, int);

43
44
45
46
47
48
49
50
51
52
typedef struct MeterClass_ {
   ObjectClass super;
   const Meter_Init init;
   const Meter_Done done;
   const Meter_UpdateMode updateMode;
   const Meter_Draw draw;
   const Meter_SetValues setValues;
   const int defaultMode;
   const double total;
   const int* attributes;
Hisham Muhammad's avatar
Hisham Muhammad committed
53
54
55
   const char* name;
   const char* uiName;
   const char* caption;
56
   const char* description;
57
58
   const char maxItems;
   char curItems;
59
60
61
62
63
64
65
66
67
68
69
70
} MeterClass;

#define As_Meter(this_)                ((MeterClass*)((this_)->super.klass))
#define Meter_initFn(this_)            As_Meter(this_)->init
#define Meter_init(this_)              As_Meter(this_)->init((Meter*)(this_))
#define Meter_done(this_)              As_Meter(this_)->done((Meter*)(this_))
#define Meter_updateModeFn(this_)      As_Meter(this_)->updateMode
#define Meter_updateMode(this_, m_)    As_Meter(this_)->updateMode((Meter*)(this_), m_)
#define Meter_drawFn(this_)            As_Meter(this_)->draw
#define Meter_doneFn(this_)            As_Meter(this_)->done
#define Meter_setValues(this_, c_, i_) As_Meter(this_)->setValues((Meter*)(this_), c_, i_)
#define Meter_defaultMode(this_)       As_Meter(this_)->defaultMode
71
72
#define Meter_getItems(this_)          As_Meter(this_)->curItems
#define Meter_setItems(this_, n_)      As_Meter(this_)->curItems = (n_)
73
74
75
#define Meter_attributes(this_)        As_Meter(this_)->attributes
#define Meter_name(this_)              As_Meter(this_)->name
#define Meter_uiName(this_)            As_Meter(this_)->uiName
76
77
78

struct Meter_ {
   Object super;
79
80
   Meter_Draw draw;
   
81
82
83
   char* caption;
   int mode;
   int param;
84
   void* drawData;
85
   int h;
Hisham Muhammad's avatar
Hisham Muhammad committed
86
   struct ProcessList_* pl;
Hisham Muhammad's avatar
Hisham Muhammad committed
87
88
89
90
   double* values;
   double total;
};

91
92
93
94
95
typedef struct MeterMode_ {
   Meter_Draw draw;
   const char* uiName;
   int h;
} MeterMode;
96

97
98
99
100
101
102
103
104
105
typedef enum {
   CUSTOM_METERMODE = 0,
   BAR_METERMODE,
   TEXT_METERMODE,
   GRAPH_METERMODE,
   LED_METERMODE,
   LAST_METERMODE
} MeterModeId;

106
107
108
109
110
typedef struct GraphData_ {
   struct timeval time;
   double values[METER_BUFFER_LEN];
} GraphData;

Hisham Muhammad's avatar
Hisham Muhammad committed
111
112
113
114
115
}*/

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
116
117
118
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
119
120
121
#ifndef CLAMP
#define CLAMP(x,low,high) (((x)>(high))?(high):(((x)<(low))?(low):(x)))
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
122

123
124
125
126
127
MeterClass Meter_class = {
   .super = {
      .extends = Class(Object)
   }
};
Hisham Muhammad's avatar
Hisham Muhammad committed
128

Hisham Muhammad's avatar
Hisham Muhammad committed
129
Meter* Meter_new(struct ProcessList_* pl, int param, MeterClass* type) {
Hisham's avatar
Hisham committed
130
   Meter* this = xCalloc(1, sizeof(Meter));
131
   Object_setClass(this, type);
132
133
134
   this->h = 1;
   this->param = param;
   this->pl = pl;
135
136
   type->curItems = type->maxItems;
   this->values = xCalloc(type->maxItems, sizeof(double));
137
   this->total = type->total;
Hisham's avatar
Hisham committed
138
   this->caption = xStrdup(type->caption);
139
140
141
   if (Meter_initFn(this))
      Meter_init(this);
   Meter_setMode(this, type->defaultMode);
142
   return this;
Hisham Muhammad's avatar
Hisham Muhammad committed
143
144
}

Christian Hesse's avatar
Christian Hesse committed
145
int Meter_humanUnit(char* buffer, unsigned long int value, int size) {
Hisham Muhammad's avatar
Hisham Muhammad committed
146
147
148
   const char * prefix = "KMGTPEZY";
   unsigned long int powi = 1;
   unsigned int written, powj = 1, precision = 2;
Christian Hesse's avatar
Christian Hesse committed
149

Hisham Muhammad's avatar
Hisham Muhammad committed
150
151
152
   for(;;) {
      if (value / 1024 < powi)
         break;
Christian Hesse's avatar
Christian Hesse committed
153

Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
      if (prefix[1] == 0)
         break;
Christian Hesse's avatar
Christian Hesse committed
156

Hisham Muhammad's avatar
Hisham Muhammad committed
157
158
159
      powi *= 1024;
      ++prefix;
   }
Christian Hesse's avatar
Christian Hesse committed
160

161
162
163
   if (*prefix == 'K')
      precision = 0;

Hisham Muhammad's avatar
Hisham Muhammad committed
164
165
166
167
168
   for (; precision > 0; precision--) {
      powj *= 10;
      if (value / powi < powj)
         break;
   }
Christian Hesse's avatar
Christian Hesse committed
169

Hisham Muhammad's avatar
Hisham Muhammad committed
170
171
   written = snprintf(buffer, size, "%.*f%c",
      precision, (double) value / powi, *prefix);
Christian Hesse's avatar
Christian Hesse committed
172

Hisham Muhammad's avatar
Hisham Muhammad committed
173
   return written;
Christian Hesse's avatar
Christian Hesse committed
174
175
}

Hisham Muhammad's avatar
Hisham Muhammad committed
176
void Meter_delete(Object* cast) {
177
178
   if (!cast)
      return;
Hisham Muhammad's avatar
Hisham Muhammad committed
179
   Meter* this = (Meter*) cast;
180
181
   if (Meter_doneFn(this)) {
      Meter_done(this);
182
   }
183
184
   if (this->drawData)
      free(this->drawData);
185
186
   free(this->caption);
   free(this->values);
Hisham Muhammad's avatar
Hisham Muhammad committed
187
188
189
   free(this);
}

Hisham Muhammad's avatar
Hisham Muhammad committed
190
void Meter_setCaption(Meter* this, const char* caption) {
191
   free(this->caption);
Hisham's avatar
Hisham committed
192
   this->caption = xStrdup(caption);
193
194
}

195
static inline void Meter_displayBuffer(Meter* this, char* buffer, RichString* out) {
196
197
   if (Object_displayFn(this)) {
      Object_display(this, out);
198
   } else {
199
      RichString_write(out, CRT_colors[Meter_attributes(this)[0]], buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
200
   }
201
202
203
}

void Meter_setMode(Meter* this, int modeIndex) {
Hisham Muhammad's avatar
Hisham Muhammad committed
204
   if (modeIndex > 0 && modeIndex == this->mode)
205
206
207
208
      return;
   if (!modeIndex)
      modeIndex = 1;
   assert(modeIndex < LAST_METERMODE);
209
210
211
212
   if (Meter_defaultMode(this) == CUSTOM_METERMODE) {
      this->draw = Meter_drawFn(this);
      if (Meter_updateModeFn(this))
         Meter_updateMode(this, modeIndex);
213
   } else {
Hisham Muhammad's avatar
Hisham Muhammad committed
214
      assert(modeIndex >= 1);
215
216
217
      if (this->drawData)
         free(this->drawData);
      this->drawData = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
218
219
220
221

      MeterMode* mode = Meter_modes[modeIndex];
      this->draw = mode->draw;
      this->h = mode->h;
Hisham Muhammad's avatar
Hisham Muhammad committed
222
   }
223
   this->mode = modeIndex;
Hisham Muhammad's avatar
Hisham Muhammad committed
224
225
}

226
ListItem* Meter_toListItem(Meter* this, bool moving) {
227
228
229
230
231
232
233
234
235
236
237
   char mode[21];
   if (this->mode)
      snprintf(mode, 20, " [%s]", Meter_modes[this->mode]->uiName);
   else
      mode[0] = '\0';
   char number[11];
   if (this->param > 0)
      snprintf(number, 10, " %d", this->param);
   else
      number[0] = '\0';
   char buffer[51];
238
   snprintf(buffer, 50, "%s%s%s", Meter_uiName(this), number, mode);
239
240
241
   ListItem* li = ListItem_new(buffer, 0);
   li->moving = moving;
   return li;
Hisham Muhammad's avatar
Hisham Muhammad committed
242
243
}

244
245
/* ---------- TextMeterMode ---------- */

246
static void TextMeterMode_draw(Meter* this, int x, int y, int w) {
247
   char buffer[METER_BUFFER_LEN];
248
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
249
   (void) w;
250
251
252
253
254
255

   attrset(CRT_colors[METER_TEXT]);
   mvaddstr(y, x, this->caption);
   int captionLen = strlen(this->caption);
   x += captionLen;
   attrset(CRT_colors[RESET_COLOR]);
256
257
258
259
   RichString_begin(out);
   Meter_displayBuffer(this, buffer, &out);
   RichString_printVal(out, y, x);
   RichString_end(out);
260
261
262
263
}

/* ---------- BarMeterMode ---------- */

264
static char BarMeterMode_characters[] = "|#*@$%&.";
265

266
static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
267
   char buffer[METER_BUFFER_LEN];
268
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
269

Hisham Muhammad's avatar
Hisham Muhammad committed
270
271
   w -= 2;
   attrset(CRT_colors[METER_TEXT]);
Hisham Muhammad's avatar
Hisham Muhammad committed
272
273
   int captionLen = 3;
   mvaddnstr(y, x, this->caption, captionLen);
Hisham Muhammad's avatar
Hisham Muhammad committed
274
275
276
277
278
279
280
281
   x += captionLen;
   w -= captionLen;
   attrset(CRT_colors[BAR_BORDER]);
   mvaddch(y, x, '[');
   mvaddch(y, x + w, ']');
   
   w--;
   x++;
282
283
284
285
286
287

   if (w < 1) {
      attrset(CRT_colors[RESET_COLOR]);
      return;
   }
   char bar[w + 1];
Hisham Muhammad's avatar
Hisham Muhammad committed
288
289
290
291
292
   
   int blockSizes[10];
   for (int i = 0; i < w; i++)
      bar[i] = ' ';

293
   const size_t barOffset = w - MIN((int)strlen(buffer), w);
294
   snprintf(bar + barOffset, w - barOffset + 1, "%s", buffer);
Hisham Muhammad's avatar
Hisham Muhammad committed
295
296
297

   // First draw in the bar[] buffer...
   int offset = 0;
298
299
   int items = Meter_getItems(this);
   for (int i = 0; i < items; i++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
300
      double value = this->values[i];
301
      value = CLAMP(value, 0.0, this->total);
Hisham Muhammad's avatar
Hisham Muhammad committed
302
303
304
305
306
307
308
      if (value > 0) {
         blockSizes[i] = ceil((value/this->total) * w);
      } else {
         blockSizes[i] = 0;
      }
      int nextOffset = offset + blockSizes[i];
      // (Control against invalid values)
309
      nextOffset = CLAMP(nextOffset, 0, w);
Hisham Muhammad's avatar
Hisham Muhammad committed
310
311
312
      for (int j = offset; j < nextOffset; j++)
         if (bar[j] == ' ') {
            if (CRT_colorScheme == COLORSCHEME_MONOCHROME) {
313
               bar[j] = BarMeterMode_characters[i];
Hisham Muhammad's avatar
Hisham Muhammad committed
314
315
316
317
318
319
320
321
322
            } else {
               bar[j] = '|';
            }
         }
      offset = nextOffset;
   }

   // ...then print the buffer.
   offset = 0;
323
324
   for (int i = 0; i < items; i++) {
      attrset(CRT_colors[Meter_attributes(this)[i]]);
Hisham Muhammad's avatar
Hisham Muhammad committed
325
326
      mvaddnstr(y, x + offset, bar + offset, blockSizes[i]);
      offset += blockSizes[i];
327
      offset = CLAMP(offset, 0, w);
Hisham Muhammad's avatar
Hisham Muhammad committed
328
329
330
331
332
333
334
335
336
337
   }
   if (offset < w) {
      attrset(CRT_colors[BAR_SHADOW]);
      mvaddnstr(y, x + offset, bar + offset, w - offset);
   }

   move(y, x + w + 1);
   attrset(CRT_colors[RESET_COLOR]);
}

338
339
/* ---------- GraphMeterMode ---------- */

340
341
#ifdef HAVE_LIBNCURSESW

Christian Hesse's avatar
Christian Hesse committed
342
343
#define PIXPERROW_UTF8 4
static const char* GraphMeterMode_dotsUtf8[] = {
344
   /*00*/" ", /*01*/"⢀", /*02*/"⢠", /*03*/"⢰", /*04*/ "⢸",
Christian Hesse's avatar
Christian Hesse committed
345
346
347
348
   /*10*/"⡀", /*11*/"⣀", /*12*/"⣠", /*13*/"⣰", /*14*/ "⣸",
   /*20*/"⡄", /*21*/"⣄", /*22*/"⣤", /*23*/"⣴", /*24*/ "⣼",
   /*30*/"⡆", /*31*/"⣆", /*32*/"⣦", /*33*/"⣶", /*34*/ "⣾",
   /*40*/"⡇", /*41*/"⣇", /*42*/"⣧", /*43*/"⣷", /*44*/ "⣿"
Hisham Muhammad's avatar
Hisham Muhammad committed
349
};
350

351
352
#endif

Christian Hesse's avatar
Christian Hesse committed
353
354
355
356
357
#define PIXPERROW_ASCII 2
static const char* GraphMeterMode_dotsAscii[] = {
   /*00*/" ", /*01*/".", /*02*/":",
   /*10*/".", /*11*/".", /*12*/":",
   /*20*/":", /*21*/":", /*22*/":"
358
359
};

Christian Hesse's avatar
Christian Hesse committed
360
static const char** GraphMeterMode_dots;
Hisham Muhammad's avatar
Hisham Muhammad committed
361
static int GraphMeterMode_pixPerRow;
362

363
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
364

Hisham's avatar
Hisham committed
365
   if (!this->drawData) this->drawData = xCalloc(1, sizeof(GraphData));
Hisham Muhammad's avatar
Hisham Muhammad committed
366
    GraphData* data = (GraphData*) this->drawData;
367
   const int nValues = METER_BUFFER_LEN;
Hisham Muhammad's avatar
Hisham Muhammad committed
368

369
#ifdef HAVE_LIBNCURSESW
Hisham Muhammad's avatar
Hisham Muhammad committed
370
371
   if (CRT_utf8) {
      GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
Hisham Muhammad's avatar
Hisham Muhammad committed
372
      GraphMeterMode_pixPerRow = PIXPERROW_UTF8;
373
374
375
   } else
#endif
   {
Hisham Muhammad's avatar
Hisham Muhammad committed
376
      GraphMeterMode_dots = GraphMeterMode_dotsAscii;
Hisham Muhammad's avatar
Hisham Muhammad committed
377
      GraphMeterMode_pixPerRow = PIXPERROW_ASCII;
Hisham Muhammad's avatar
Hisham Muhammad committed
378
379
380
381
382
383
384
   }

   attrset(CRT_colors[METER_TEXT]);
   int captionLen = 3;
   mvaddnstr(y, x, this->caption, captionLen);
   x += captionLen;
   w -= captionLen;
385
   
386
387
388
   struct timeval now;
   gettimeofday(&now, NULL);
   if (!timercmp(&now, &(data->time), <)) {
389
      struct timeval delay = { .tv_sec = (int)(CRT_delay/10), .tv_usec = (CRT_delay-((int)(CRT_delay/10)*10)) * 100000 };
390
      timeradd(&now, &delay, &(data->time));
391

392
393
394
395
      for (int i = 0; i < nValues - 1; i++)
         data->values[i] = data->values[i+1];
   
      char buffer[nValues];
396
      Meter_setValues(this, buffer, nValues - 1);
397
398
   
      double value = 0.0;
399
400
      int items = Meter_getItems(this);
      for (int i = 0; i < items; i++)
401
402
403
404
405
         value += this->values[i];
      value /= this->total;
      data->values[nValues - 1] = value;
   }
   
Hisham's avatar
Hisham committed
406
407
408
409
410
411
   int i = nValues - (w*2) + 2, k = 0;
   if (i < 0) {
      k = -i/2;
      i = 0;
   }
   for (; i < nValues; i+=2, k++) {
412
413
414
      int pix = GraphMeterMode_pixPerRow * GRAPH_HEIGHT;
      int v1 = CLAMP(data->values[i] * pix, 1, pix);
      int v2 = CLAMP(data->values[i+1] * pix, 1, pix);
Christian Hesse's avatar
Christian Hesse committed
415

Hisham Muhammad's avatar
Hisham Muhammad committed
416
      int colorIdx = GRAPH_1;
417
418
419
      for (int line = 0; line < GRAPH_HEIGHT; line++) {
         int line1 = CLAMP(v1 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow);
         int line2 = CLAMP(v2 - (GraphMeterMode_pixPerRow * (GRAPH_HEIGHT - 1 - line)), 0, GraphMeterMode_pixPerRow);
Christian Hesse's avatar
Christian Hesse committed
420

Hisham Muhammad's avatar
Hisham Muhammad committed
421
         attrset(CRT_colors[colorIdx]);
Hisham Muhammad's avatar
Hisham Muhammad committed
422
         mvaddstr(y+line, x+k, GraphMeterMode_dots[line1 * (GraphMeterMode_pixPerRow + 1) + line2]);
Hisham Muhammad's avatar
Hisham Muhammad committed
423
424
         colorIdx = GRAPH_2;
      }
425
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
426
427
428
   attrset(CRT_colors[RESET_COLOR]);
}

429
430
/* ---------- LEDMeterMode ---------- */

Christian Hesse's avatar
Christian Hesse committed
431
432
433
434
static const char* LEDMeterMode_digitsAscii[] = {
   " __ ","    "," __ "," __ ","    "," __ "," __ "," __ "," __ "," __ ",
   "|  |","   |"," __|"," __|","|__|","|__ ","|__ ","   |","|__|","|__|",
   "|__|","   |","|__ "," __|","   |"," __|","|__|","   |","|__|"," __|"
435
};
Hisham Muhammad's avatar
Hisham Muhammad committed
436

437
438
#ifdef HAVE_LIBNCURSESW

Christian Hesse's avatar
Christian Hesse committed
439
440
441
442
static const char* LEDMeterMode_digitsUtf8[] = {
   "┌──┐","  ┐ ","╶──┐","╶──┐","╷  ╷","┌──╴","┌──╴","╶──┐","┌──┐","┌──┐",
   "│  │","  │ ","┌──┘"," ──┤","└──┤","└──┐","├──┐","   │","├──┤","└──┤",
   "└──┘","  ╵ ","└──╴","╶──┘","   ╵","╶──┘","└──┘","   ╵","└──┘"," ──┘"
443
444
};

445
446
#endif

Christian Hesse's avatar
Christian Hesse committed
447
static const char** LEDMeterMode_digits;
Hisham Muhammad's avatar
Hisham Muhammad committed
448

449
static void LEDMeterMode_drawDigit(int x, int y, int n) {
Hisham Muhammad's avatar
Hisham Muhammad committed
450
   for (int i = 0; i < 3; i++)
Christian Hesse's avatar
Christian Hesse committed
451
      mvaddstr(y+i, x, LEDMeterMode_digits[i * 10 + n]);
452
453
}

454
static void LEDMeterMode_draw(Meter* this, int x, int y, int w) {
Hisham Muhammad's avatar
Hisham Muhammad committed
455
   (void) w;
Hisham Muhammad's avatar
Hisham Muhammad committed
456

457
458
#ifdef HAVE_LIBNCURSESW
   if (CRT_utf8)
Hisham Muhammad's avatar
Hisham Muhammad committed
459
      LEDMeterMode_digits = LEDMeterMode_digitsUtf8;
460
461
   else
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
462
463
      LEDMeterMode_digits = LEDMeterMode_digitsAscii;

464
   char buffer[METER_BUFFER_LEN];
465
   Meter_setValues(this, buffer, METER_BUFFER_LEN - 1);
466
467
468
   
   RichString_begin(out);
   Meter_displayBuffer(this, buffer, &out);
469

470
471
   int yText =
#ifdef HAVE_LIBNCURSESW
Hisham Muhammad's avatar
Hisham Muhammad committed
472
      CRT_utf8 ? y+1 :
473
#endif
Hisham Muhammad's avatar
Hisham Muhammad committed
474
      y+2;
Hisham Muhammad's avatar
Hisham Muhammad committed
475
   attrset(CRT_colors[LED_COLOR]);
476
   mvaddstr(yText, x, this->caption);
Hisham Muhammad's avatar
Hisham Muhammad committed
477
   int xx = x + strlen(this->caption);
478
479
480
   int len = RichString_sizeVal(out);
   for (int i = 0; i < len; i++) {
      char c = RichString_getCharVal(out, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
481
      if (c >= '0' && c <= '9') {
482
483
         LEDMeterMode_drawDigit(xx, y, c-48);
         xx += 4;
Hisham Muhammad's avatar
Hisham Muhammad committed
484
      } else {
485
         mvaddch(yText, xx, c);
Hisham Muhammad's avatar
Hisham Muhammad committed
486
487
488
489
         xx += 1;
      }
   }
   attrset(CRT_colors[RESET_COLOR]);
490
   RichString_end(out);
Hisham Muhammad's avatar
Hisham Muhammad committed
491
492
}

493
494
495
496
497
498
499
500
501
502
503
504
505
506
static MeterMode BarMeterMode = {
   .uiName = "Bar",
   .h = 1,
   .draw = BarMeterMode_draw,
};

static MeterMode TextMeterMode = {
   .uiName = "Text",
   .h = 1,
   .draw = TextMeterMode_draw,
};

static MeterMode GraphMeterMode = {
   .uiName = "Graph",
507
   .h = GRAPH_HEIGHT,
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
   .draw = GraphMeterMode_draw,
};

static MeterMode LEDMeterMode = {
   .uiName = "LED",
   .h = 3,
   .draw = LEDMeterMode_draw,
};

MeterMode* Meter_modes[] = {
   NULL,
   &BarMeterMode,
   &TextMeterMode,
   &GraphMeterMode,
   &LEDMeterMode,
   NULL
};
Hisham Muhammad's avatar
Hisham Muhammad committed
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

/* Blank meter */

static void BlankMeter_setValues(Meter* this, char* buffer, int size) {
   (void) this; (void) buffer; (void) size;
}

static void BlankMeter_display(Object* cast, RichString* out) {
   (void) cast;
   RichString_prune(out);
}

int BlankMeter_attributes[] = {
   DEFAULT_COLOR
};

MeterClass BlankMeter_class = {
   .super = {
      .extends = Class(Meter),
      .delete = Meter_delete,
      .display = BlankMeter_display,
   },
   .setValues = BlankMeter_setValues,
   .defaultMode = TEXT_METERMODE,
549
   .maxItems = 0,
Hisham Muhammad's avatar
Hisham Muhammad committed
550
551
552
553
554
555
   .total = 100.0,
   .attributes = BlankMeter_attributes,
   .name = "Blank",
   .uiName = "Blank",
   .caption = ""
};