Panel.c 13 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
/*
2
htop - Panel.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
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

8
#include "Panel.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
9

Hisham Muhammad's avatar
Hisham Muhammad committed
10
11
#include "CRT.h"
#include "RichString.h"
12
#include "ListItem.h"
David Hunt's avatar
David Hunt committed
13
#include "StringUtils.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
14
15
16

#include <math.h>
#include <stdbool.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
17
18
19
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
20
#include <assert.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
21

Hisham Muhammad's avatar
Hisham Muhammad committed
22
23
24
//#link curses

/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
25
26
#include "Object.h"
#include "Vector.h"
27
#include "FunctionBar.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
28

29
typedef struct Panel_ Panel;
Hisham Muhammad's avatar
Hisham Muhammad committed
30
31

typedef enum HandlerResult_ {
32
33
34
   HANDLED     = 0x01,
   IGNORED     = 0x02,
   BREAK_LOOP  = 0x04,
35
36
   REDRAW      = 0x08,
   RESCAN      = 0x10,
37
   SYNTH_KEY   = 0x20,
Hisham Muhammad's avatar
Hisham Muhammad committed
38
39
} HandlerResult;

40
41
42
43
#define EVENT_SET_SELECTED -1

#define EVENT_HEADER_CLICK(x_) (-10000 + x_)
#define EVENT_HEADER_CLICK_GET_X(ev_) (ev_ + 10000)
Hisham Muhammad's avatar
Hisham Muhammad committed
44
45
46
47
48
#define EVENT_IS_HEADER_CLICK(ev_) (ev_ >= -10000 && ev_ < -9000)

#define EVENT_SCREEN_TAB_CLICK(x_) (-20000 + x_)
#define EVENT_SCREEN_TAB_GET_X(ev_) (ev_ + 20000)
#define EVENT_IS_SCREEN_TAB_CLICK(ev_) (ev_ >= -20000 && ev_ < -10000)
49

50
typedef HandlerResult(*Panel_EventHandler)(Panel*, int);
Hisham Muhammad's avatar
Hisham Muhammad committed
51

52
53
54
55
56
57
58
59
60
typedef struct PanelClass_ {
   const ObjectClass super;
   const Panel_EventHandler eventHandler;
} PanelClass;

#define As_Panel(this_)                ((PanelClass*)((this_)->super.klass))
#define Panel_eventHandlerFn(this_)    As_Panel(this_)->eventHandler
#define Panel_eventHandler(this_, ev_) As_Panel(this_)->eventHandler((Panel*)(this_), ev_)

61
struct Panel_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
62
63
   Object super;
   int x, y, w, h;
64
   int cursorX, cursorY;
Hisham Muhammad's avatar
Hisham Muhammad committed
65
   WINDOW* window;
66
   Vector* items;
Hisham Muhammad's avatar
Hisham Muhammad committed
67
68
   int selected;
   int oldSelected;
69
   int selectedLen;
Hisham Muhammad's avatar
Hisham Muhammad committed
70
   void* eventHandlerState;
Hisham Muhammad's avatar
Hisham Muhammad committed
71
72
   int scrollV;
   short scrollH;
Hisham Muhammad's avatar
Hisham Muhammad committed
73
   bool needsRedraw;
74
   bool cursorOn;
75
76
   FunctionBar* currentBar;
   FunctionBar* defaultBar;
Hisham Muhammad's avatar
Hisham Muhammad committed
77
   RichString header;
78
   int selectionColor;
Hisham Muhammad's avatar
Hisham Muhammad committed
79
80
};

81
82
#define Panel_setDefaultBar(this_) do{ (this_)->currentBar = (this_)->defaultBar; }while(0)

Hisham Muhammad's avatar
Hisham Muhammad committed
83
84
85
86
87
88
89
90
91
}*/

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif

92
#define KEY_CTRL(l) ((l)-'A'+1)
Hisham Muhammad's avatar
Hisham Muhammad committed
93

94
95
96
97
98
void Panel_setCursorToSelection(Panel* this) {
   this->cursorY = this->y + this->selected - this->scrollV + 1;
   this->cursorX = this->x + this->selectedLen - this->scrollH;
}

99
100
101
102
103
PanelClass Panel_class = {
   .super = {
      .extends = Class(Object),
      .delete = Panel_delete
   },
104
   .eventHandler = Panel_selectByTyping,
105
106
};

107
Panel* Panel_new(int x, int y, int w, int h, bool owner, ObjectClass* type, FunctionBar* fuBar) {
108
   Panel* this;
Hisham's avatar
Hisham committed
109
   this = xMalloc(sizeof(Panel));
110
   Object_setClass(this, Class(Panel));
111
   Panel_init(this, x, y, w, h, type, owner, fuBar);
Hisham Muhammad's avatar
Hisham Muhammad committed
112
113
114
   return this;
}

115
116
117
void Panel_delete(Object* cast) {
   Panel* this = (Panel*)cast;
   Panel_done(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
118
119
120
   free(this);
}

121
void Panel_init(Panel* this, int x, int y, int w, int h, ObjectClass* type, bool owner, FunctionBar* fuBar) {
Hisham Muhammad's avatar
Hisham Muhammad committed
122
123
124
125
   this->x = x;
   this->y = y;
   this->w = w;
   this->h = h;
126
127
   this->cursorX = 0;
   this->cursorY = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
128
   this->eventHandlerState = NULL;
129
   this->items = Vector_new(type, owner, DEFAULT_SIZE);
Hisham Muhammad's avatar
Hisham Muhammad committed
130
131
132
133
134
   this->scrollV = 0;
   this->scrollH = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
135
   RichString_beginAllocated(this->header);
136
137
   this->defaultBar = fuBar;
   this->currentBar = fuBar;
138
   this->selectionColor = CRT_colors[PANEL_SELECTION_FOCUS];
Hisham Muhammad's avatar
Hisham Muhammad committed
139
140
}

141
void Panel_done(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
142
   assert (this != NULL);
Hisham Muhammad's avatar
Hisham Muhammad committed
143
   free(this->eventHandlerState);
144
   Vector_delete(this->items);
145
   FunctionBar_delete(this->defaultBar);
146
   RichString_end(this->header);
Hisham Muhammad's avatar
Hisham Muhammad committed
147
148
}

149
150
151
152
void Panel_setSelectionColor(Panel* this, int color) {
   this->selectionColor = color;
}

153
RichString* Panel_getHeader(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
154
155
156
   assert (this != NULL);

   this->needsRedraw = true;
157
   return &(this->header);
Hisham Muhammad's avatar
Hisham Muhammad committed
158
159
}

Hisham Muhammad's avatar
Hisham Muhammad committed
160
inline void Panel_setHeader(Panel* this, const char* header) {
161
162
   RichString_write(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
   this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
163
164
}

165
void Panel_move(Panel* this, int x, int y) {
Hisham Muhammad's avatar
Hisham Muhammad committed
166
167
168
169
170
171
172
   assert (this != NULL);

   this->x = x;
   this->y = y;
   this->needsRedraw = true;
}

173
void Panel_resize(Panel* this, int w, int h) {
Hisham Muhammad's avatar
Hisham Muhammad committed
174
175
   assert (this != NULL);

176
   if (RichString_sizeVal(this->header) > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
177
178
179
180
181
182
      h--;
   this->w = w;
   this->h = h;
   this->needsRedraw = true;
}

183
void Panel_prune(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
184
185
   assert (this != NULL);

186
   Vector_prune(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
187
188
189
190
191
192
   this->scrollV = 0;
   this->selected = 0;
   this->oldSelected = 0;
   this->needsRedraw = true;
}

193
void Panel_add(Panel* this, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
194
195
   assert (this != NULL);

196
   Vector_add(this->items, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
197
198
199
   this->needsRedraw = true;
}

200
void Panel_insert(Panel* this, int i, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
201
202
   assert (this != NULL);

203
   Vector_insert(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
204
205
206
   this->needsRedraw = true;
}

207
void Panel_set(Panel* this, int i, Object* o) {
Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
   assert (this != NULL);

210
   Vector_set(this->items, i, o);
Hisham Muhammad's avatar
Hisham Muhammad committed
211
212
}

213
Object* Panel_get(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
214
215
   assert (this != NULL);

216
   return Vector_get(this->items, i);
Hisham Muhammad's avatar
Hisham Muhammad committed
217
218
}

219
Object* Panel_remove(Panel* this, int i) {
Hisham Muhammad's avatar
Hisham Muhammad committed
220
221
222
   assert (this != NULL);

   this->needsRedraw = true;
223
224
   Object* removed = Vector_remove(this->items, i);
   if (this->selected > 0 && this->selected >= Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
225
226
227
228
      this->selected--;
   return removed;
}

229
Object* Panel_getSelected(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
230
   assert (this != NULL);
231
232
233
234
   if (Vector_size(this->items) > 0)
      return Vector_get(this->items, this->selected);
   else
      return NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
235
236
}

237
void Panel_moveSelectedUp(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
238
239
   assert (this != NULL);

240
   Vector_moveUp(this->items, this->selected);
Hisham Muhammad's avatar
Hisham Muhammad committed
241
242
243
244
   if (this->selected > 0)
      this->selected--;
}

245
void Panel_moveSelectedDown(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
246
247
   assert (this != NULL);

248
249
   Vector_moveDown(this->items, this->selected);
   if (this->selected + 1 < Vector_size(this->items))
Hisham Muhammad's avatar
Hisham Muhammad committed
250
251
252
      this->selected++;
}

253
int Panel_getSelectedIndex(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
254
255
256
257
258
   assert (this != NULL);

   return this->selected;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
259
int Panel_size(Panel* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
260
261
   assert (this != NULL);

262
   return Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
263
264
}

265
void Panel_setSelected(Panel* this, int selected) {
Hisham Muhammad's avatar
Hisham Muhammad committed
266
267
   assert (this != NULL);

268
269
   int size = Vector_size(this->items);
   if (selected >= size) {
Hisham Muhammad's avatar
Hisham Muhammad committed
270
      selected = size - 1;
271
   }
272
273
   if (selected < 0)
      selected = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
274
   this->selected = selected;
275
   if (Panel_eventHandlerFn(this)) {
276
      Panel_eventHandler(this, EVENT_SET_SELECTED);
277
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
278
279
}

280
void Panel_draw(Panel* this, bool focus) {
Hisham Muhammad's avatar
Hisham Muhammad committed
281
282
   assert (this != NULL);

Hisham Muhammad's avatar
Hisham Muhammad committed
283
   int size = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
284
   int scrollH = this->scrollH;
Hisham Muhammad's avatar
Hisham Muhammad committed
285
286
287
   int y = this->y;
   int x = this->x;
   int h = this->h;
Hisham Muhammad's avatar
Hisham Muhammad committed
288

289
290
   int headerLen = RichString_sizeVal(this->header);
   if (headerLen > 0) {
Hisham Muhammad's avatar
Hisham Muhammad committed
291
292
293
294
295
      int attr = focus
               ? CRT_colors[PANEL_HEADER_FOCUS]
               : CRT_colors[PANEL_HEADER_UNFOCUS];
      attrset(attr);
      mvhline(y, x, ' ', this->w);
296
      if (scrollH < headerLen) {
297
         RichString_printoffnVal(this->header, y, x, scrollH,
298
            MIN(headerLen - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
299
300
301
302
      }
      attrset(CRT_colors[RESET_COLOR]);
      y++;
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323

   // ensure scroll area is on screen
   if (this->scrollV < 0) {
      this->scrollV = 0;
      this->needsRedraw = true;
   } else if (this->scrollV >= size) {
      this->scrollV = MAX(size - 1, 0);
      this->needsRedraw = true;
   }
   // ensure selection is on screen
   if (this->selected < this->scrollV) {
      this->scrollV = this->selected;
      this->needsRedraw = true;
   } else if (this->selected >= this->scrollV + h) {
      this->scrollV = this->selected - h + 1;
      this->needsRedraw = true;
   }

   int first = this->scrollV;
   int upTo = MIN(first + h, size);

324
325
326
   int selectionColor = focus
                 ? this->selectionColor
                 : CRT_colors[PANEL_SELECTION_UNFOCUS];
Hisham Muhammad's avatar
Hisham Muhammad committed
327
328

   if (this->needsRedraw) {
Hisham Muhammad's avatar
Hisham Muhammad committed
329
330
      int line = 0;
      for(int i = first; line < h && i < upTo; i++) {
331
         Object* itemObj = Vector_get(this->items, i);
332
         assert(itemObj); if(!itemObj) continue;
333
         RichString_begin(item);
334
         Object_display(itemObj, &item);
335
336
         int itemLen = RichString_sizeVal(item);
         int amt = MIN(itemLen - scrollH, this->w);
Hisham Muhammad's avatar
Hisham Muhammad committed
337
338
         bool selected = (i == this->selected);
         if (selected) {
339
340
            attrset(selectionColor);
            RichString_setAttr(&item, selectionColor);
341
            this->selectedLen = itemLen;
Hisham Muhammad's avatar
Hisham Muhammad committed
342
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
343
         mvhline(y + line, x, ' ', this->w);
Hisham Muhammad's avatar
Hisham Muhammad committed
344
         if (amt > 0)
Hisham Muhammad's avatar
Hisham Muhammad committed
345
            RichString_printoffnVal(item, y + line, x, scrollH, amt);
Hisham Muhammad's avatar
Hisham Muhammad committed
346
347
         if (selected)
            attrset(CRT_colors[RESET_COLOR]);
348
         RichString_end(item);
Hisham Muhammad's avatar
Hisham Muhammad committed
349
350
351
352
353
         line++;
      }
      while (line < h) {
         mvhline(y + line, x, ' ', this->w);
         line++;
Hisham Muhammad's avatar
Hisham Muhammad committed
354
355
356
357
      }
      this->needsRedraw = false;

   } else {
358
      Object* oldObj = Vector_get(this->items, this->oldSelected);
359
      assert(oldObj);
360
      RichString_begin(old);
361
      Object_display(oldObj, &old);
362
      int oldLen = RichString_sizeVal(old);
363
      Object* newObj = Vector_get(this->items, this->selected);
364
      RichString_begin(new);
365
      Object_display(newObj, &new);
366
      int newLen = RichString_sizeVal(new);
367
      this->selectedLen = newLen;
Hisham Muhammad's avatar
Hisham Muhammad committed
368
      mvhline(y+ this->oldSelected - first, x+0, ' ', this->w);
369
      if (scrollH < oldLen)
Hisham Muhammad's avatar
Hisham Muhammad committed
370
         RichString_printoffnVal(old, y+this->oldSelected - first, x,
Hisham Muhammad's avatar
Hisham Muhammad committed
371
            scrollH, MIN(oldLen - scrollH, this->w));
372
      attrset(selectionColor);
Hisham Muhammad's avatar
Hisham Muhammad committed
373
      mvhline(y+this->selected - first, x+0, ' ', this->w);
374
      RichString_setAttr(&new, selectionColor);
375
      if (scrollH < newLen)
Hisham Muhammad's avatar
Hisham Muhammad committed
376
         RichString_printoffnVal(new, y+this->selected - first, x,
Hisham Muhammad's avatar
Hisham Muhammad committed
377
            scrollH, MIN(newLen - scrollH, this->w));
Hisham Muhammad's avatar
Hisham Muhammad committed
378
      attrset(CRT_colors[RESET_COLOR]);
379
380
      RichString_end(new);
      RichString_end(old);
Hisham Muhammad's avatar
Hisham Muhammad committed
381
382
383
384
   }
   this->oldSelected = this->selected;
}

Hisham Muhammad's avatar
Hisham Muhammad committed
385
bool Panel_onKey(Panel* this, int key) {
Hisham Muhammad's avatar
Hisham Muhammad committed
386
   assert (this != NULL);
Hisham Muhammad's avatar
Hisham Muhammad committed
387
388
   
   int size = Vector_size(this->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
389
390
   switch (key) {
   case KEY_DOWN:
391
   case KEY_CTRL('N'):
Hisham Muhammad's avatar
Hisham Muhammad committed
392
393
      this->selected++;
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
394
   case KEY_UP:
395
   case KEY_CTRL('P'):
Hisham Muhammad's avatar
Hisham Muhammad committed
396
397
      this->selected--;
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
398
399
   #ifdef KEY_C_DOWN
   case KEY_C_DOWN:
Hisham Muhammad's avatar
Hisham Muhammad committed
400
401
      this->selected++;
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
402
403
404
   #endif
   #ifdef KEY_C_UP
   case KEY_C_UP:
Hisham Muhammad's avatar
Hisham Muhammad committed
405
406
      this->selected--;
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
407
   #endif
Hisham Muhammad's avatar
Hisham Muhammad committed
408
   case KEY_LEFT:
409
   case KEY_CTRL('B'):
Hisham Muhammad's avatar
Hisham Muhammad committed
410
      if (this->scrollH > 0) {
411
         this->scrollH -= MAX(CRT_scrollHAmount, 0);
Hisham Muhammad's avatar
Hisham Muhammad committed
412
413
         this->needsRedraw = true;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
414
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
415
   case KEY_RIGHT:
416
   case KEY_CTRL('F'):
Hisham Muhammad's avatar
Hisham Muhammad committed
417
      this->scrollH += CRT_scrollHAmount;
Hisham Muhammad's avatar
Hisham Muhammad committed
418
      this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
419
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
420
   case KEY_PPAGE:
Hisham Muhammad's avatar
Hisham Muhammad committed
421
      this->selected -= (this->h - 1);
422
      this->scrollV = MAX(0, this->scrollV - this->h + 1);
Hisham Muhammad's avatar
Hisham Muhammad committed
423
      this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
424
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
425
   case KEY_NPAGE:
Hisham Muhammad's avatar
Hisham Muhammad committed
426
      this->selected += (this->h - 1);
427
428
      this->scrollV = MAX(0, MIN(Vector_size(this->items) - this->h,
                                 this->scrollV + this->h - 1));
Hisham Muhammad's avatar
Hisham Muhammad committed
429
      this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
430
      break;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
   case KEY_WHEELUP:
      this->selected -= CRT_scrollWheelVAmount;
      this->scrollV -= CRT_scrollWheelVAmount;
      this->needsRedraw = true;
      break;
   case KEY_WHEELDOWN:
   {
      this->selected += CRT_scrollWheelVAmount;
      this->scrollV += CRT_scrollWheelVAmount;
      if (this->scrollV > Vector_size(this->items) - this->h) {
         this->scrollV = Vector_size(this->items) - this->h;
      }
      this->needsRedraw = true;
      break;
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
446
447
   case KEY_HOME:
      this->selected = 0;
Hisham Muhammad's avatar
Hisham Muhammad committed
448
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
449
   case KEY_END:
Hisham Muhammad's avatar
Hisham Muhammad committed
450
451
      this->selected = size - 1;
      break;
452
453
454
   case KEY_CTRL('A'):
   case '^':
      this->scrollH = 0;
455
      this->needsRedraw = true;
456
457
458
459
      break;
   case KEY_CTRL('E'):
   case '$':
      this->scrollH = MAX(this->selectedLen - this->w, 0);
460
      this->needsRedraw = true;
461
      break;
Hisham Muhammad's avatar
Hisham Muhammad committed
462
463
464
465
466
   default:
      return false;
   }

   // ensure selection within bounds
Hisham's avatar
Hisham committed
467
   if (this->selected < 0 || size == 0) {
Hisham Muhammad's avatar
Hisham Muhammad committed
468
469
470
471
472
      this->selected = 0;
      this->needsRedraw = true;
   } else if (this->selected >= size) {   
      this->selected = size - 1;
      this->needsRedraw = true;
Hisham Muhammad's avatar
Hisham Muhammad committed
473
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
474
   return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
475
}
476
477
478
479


HandlerResult Panel_selectByTyping(Panel* this, int ch) {
   int size = Panel_size(this);
Hisham Muhammad's avatar
Hisham Muhammad committed
480
   if (!this->eventHandlerState)
Hisham's avatar
Hisham committed
481
      this->eventHandlerState = xCalloc(100, sizeof(char));
Hisham Muhammad's avatar
Hisham Muhammad committed
482
   char* buffer = this->eventHandlerState;
483

484
   if (ch > 0 && ch < 255 && isalnum(ch)) {
Hisham Muhammad's avatar
Hisham Muhammad committed
485
      int len = strlen(buffer);
486
      if (len < 99) {
Hisham Muhammad's avatar
Hisham Muhammad committed
487
488
         buffer[len] = ch;
         buffer[len+1] = '\0';
489
490
      }
      for (int try = 0; try < 2; try++) {
Hisham Muhammad's avatar
Hisham Muhammad committed
491
         len = strlen(buffer);
492
493
494
         for (int i = 0; i < size; i++) {
            char* cur = ((ListItem*) Panel_get(this, i))->value;
            while (*cur == ' ') cur++;
Hisham Muhammad's avatar
Hisham Muhammad committed
495
            if (strncasecmp(cur, buffer, len) == 0) {
496
497
498
499
               Panel_setSelected(this, i);
               return HANDLED;
            }
         }
Hisham Muhammad's avatar
Hisham Muhammad committed
500
501
502
503
         // if current word did not match,
         // retry considering the character the start of a new word.
         buffer[0] = ch;
         buffer[1] = '\0';
504
505
506
      }
      return HANDLED;
   } else if (ch != ERR) {
Hisham Muhammad's avatar
Hisham Muhammad committed
507
      buffer[0] = '\0';
508
509
510
511
512
513
   }
   if (ch == 13) {
      return BREAK_LOOP;
   }
   return IGNORED;
}
514
515
516
517
518
519
520
521
522
523
524
525

int Panel_getCh(Panel* this) {
   if (this->cursorOn) {
      move(this->cursorY, this->cursorX);
      curs_set(1);
   } else {
      curs_set(0);
   }
   set_escdelay(25);
   return getch();
}