ui_objects.c revision 225736
18097Sjkh/* 28097Sjkh * Program: objects.c 38097Sjkh * Author: Marc van Kempen 48097Sjkh * Desc: Implementation of UI-objects: 58097Sjkh * - String input fields 68097Sjkh * - List selection 727798Sjkh * - Buttons 88097Sjkh * 98097Sjkh * Copyright (c) 1995, Marc van Kempen 108097Sjkh * 118097Sjkh * All rights reserved. 128097Sjkh * 138097Sjkh * This software may be used, modified, copied, distributed, and 148097Sjkh * sold, in both source and binary form provided that the above 158097Sjkh * copyright and these terms are retained, verbatim, as the first 168881Srgrimes * lines of this file. Under no circumstances is the author 178881Srgrimes * responsible for the proper functioning of this software, nor does 188097Sjkh * the author assume any responsibility for damages incurred with 198097Sjkh * its use. 208097Sjkh * 218097Sjkh */ 228097Sjkh 238097Sjkh#include <stdlib.h> 248097Sjkh#include <sys/param.h> 258097Sjkh#include <ncurses.h> 268097Sjkh#include <dialog.h> 278097Sjkh#include "dialog.priv.h" 288097Sjkh#include "ui_objects.h" 298097Sjkh 308097Sjkh#define ESC 27 318097Sjkh 328097Sjkh/*********************************************************************** 338097Sjkh * 348097Sjkh * Obj routines 358097Sjkh * 368097Sjkh ***********************************************************************/ 378097Sjkh 388097Sjkhvoid 398097SjkhAddObj(ComposeObj **Obj, int objtype, void *obj) 4021243Sjkh/* 4121243Sjkh * Desc: Add the object <obj> to the list of objects <Obj> 4225052Sjkh */ 438097Sjkh{ 448097Sjkh if (*Obj == NULL) { 458097Sjkh /* Create the root object */ 468097Sjkh *Obj = (ComposeObj *) malloc( sizeof(ComposeObj) ); 478097Sjkh if (!Obj) { 4821243Sjkh printf("AddObj: Error malloc'ing ComposeObj\n"); 4921243Sjkh exit(-1); 5021243Sjkh } 518281Sjkh (*Obj)->objtype = objtype; 528405Sjkh (*Obj)->obj = obj; 5312661Speter (*Obj)->next = NULL; 548097Sjkh (*Obj)->prev = NULL; 558208Sjkh } else { 568208Sjkh ComposeObj *o = *Obj; 5719385Sjkh 5819385Sjkh /* create the next object */ 5921276Sjkh while (o->next) o = (ComposeObj *) o->next; 6019385Sjkh o->next = (struct ComposeObj *) malloc( sizeof(ComposeObj) ); 6125052Sjkh if (!o->next) { 6219385Sjkh printf("AddObj: Error malloc'ing o->next\n"); 638208Sjkh exit(-1); 6412661Speter } 6512661Speter o->next->objtype = objtype; 668549Sjkh o->next->obj = obj; 6717007Sjkh o->next->next = NULL; 688208Sjkh o->next->prev = o; 6921806Sjkh } 7021806Sjkh 7121806Sjkh return; 728705Sjkh} /* AddObj() */ 738705Sjkh 748705Sjkhvoid 758705SjkhFreeObj(ComposeObj *Obj) 768705Sjkh/* 778705Sjkh * Desc: free the memory occupied by *Obj 788705Sjkh */ 798705Sjkh{ 8012661Speter ComposeObj *o = Obj; 818208Sjkh 8212661Speter o = Obj; 8315788Sjkh while (o) { 8415788Sjkh o = Obj->next; 8515788Sjkh free(Obj); 8615788Sjkh Obj = o; 8715788Sjkh } 8815788Sjkh 898549Sjkh return; 9012661Speter} /* FreeObj() */ 9112661Speter 9212661Speter 9312661Speterint 9412661SpeterReadObj(ComposeObj *Obj) 9512661Speter/* 9612661Speter * Desc: navigate through the different objects calling their 9712661Speter * respective navigation routines as necessary 9826456Sjkh * Pre: Obj != NULL 9925473Spst */ 10025473Spst{ 10125473Spst ComposeObj *o; 10225473Spst ComposeObj *last; /* the last object in the list */ 10325473Spst int ret; /* the return value from the selection routine */ 10425473Spst 10525473Spst /* find the last object in the list */ 10612661Speter last = Obj; 10714763Sjkh while (last->next) last = last->next; 10812661Speter 10916410Sjkh ret = 0; 11012661Speter o = Obj; 11112661Speter while ((ret != SEL_BUTTON) && (ret != SEL_ESC)) { 11216462Sjkh switch(o->objtype) { 11312661Speter case STRINGOBJ: 11412661Speter ret = SelectStringObj((StringObj *) o->obj); 11516410Sjkh break; 11621897Sjkh case LISTOBJ: 11712661Speter ret = SelectListObj((ListObj *) o->obj); 11812661Speter break; 11912661Speter case BUTTONOBJ: 12012661Speter ret = SelectButtonObj((ButtonObj *) o->obj); 12112661Speter break; 12224038Sjkh } 12317034Sjkh switch(ret) { 12412661Speter case KEY_DOWN: 12512661Speter case SEL_CR: 12612661Speter case SEL_TAB: /* move to the next object in the list */ 12712661Speter if (o->next != NULL) { 12821855Sjkh o = o->next; /* next object */ 12912661Speter } else { 13012661Speter o = Obj; /* beginning of the list */ 13126514Sjkh } 13212661Speter break; 13316410Sjkh 13412661Speter case KEY_UP: 13526010Sjkh case SEL_BACKTAB: /* move to the previous object in the list */ 13612661Speter if (o->prev != NULL) { 13726795Sjkh o = o->prev; /* previous object */ 13826717Sjkh } else { 13926456Sjkh o = last; /* end of the list */ 14016828Sjkh } 14126456Sjkh break; 14216366Sjkh 14321897Sjkh case KEY_F(1): /* display help_file */ 14416366Sjkh case '?': 14512661Speter display_helpfile(); 14612661Speter break; 14712661Speter } 14819385Sjkh } 14925476Sjkh 15019385Sjkh return(ret); 15116366Sjkh 15212661Speter} /* ReadObj() */ 15312661Speter 15412661Speter 15512661Speterint 15612661SpeterPollObj(ComposeObj **Obj) 15712661Speter{ 15821978Sjkh ComposeObj *last; /* the last object in the list */ 1599202Srgrimes ComposeObj *first; /* the first object in the list */ 16012661Speter int ret; /* the return value from the selection routine */ 1619202Srgrimes 16212661Speter /* find the last object in the list */ 16312661Speter last = *Obj; 1648549Sjkh while (last->next) last = last->next; 16516208Sjkh 16616294Sjkh /* find the first object in the list */ 16716366Sjkh first = *Obj; 16816208Sjkh while (first->prev) first = first->prev; 16920247Sjkh 17020569Sjkh ret = 0; 17116366Sjkh switch((*Obj)->objtype) { 1728208Sjkh case STRINGOBJ: 1738097Sjkh ret = SelectStringObj((StringObj *) (*Obj)->obj); 1748549Sjkh break; 1758549Sjkh case LISTOBJ: 1768097Sjkh ret = SelectListObj((ListObj *) (*Obj)->obj); 17715242Sjkh break; 17815242Sjkh case BUTTONOBJ: 17915242Sjkh ret = SelectButtonObj((ButtonObj *) (*Obj)->obj); 18015242Sjkh break; 18115242Sjkh } 1828097Sjkh switch(ret) { 1838097Sjkh case KEY_DOWN: 18415242Sjkh case SEL_CR: 1858174Sjkh case SEL_TAB: /* move to the next object in the list */ 1868174Sjkh if ((*Obj)->next != NULL) { 1878174Sjkh *Obj = (*Obj)->next; /* next object */ 1888174Sjkh } else { 18915091Sjkh *Obj = first; /* beginning of the list */ 1908097Sjkh } 1918097Sjkh break; 19225251Sjkh 1938097Sjkh case KEY_UP: 1948097Sjkh case SEL_BACKTAB: /* move to the previous object in the list */ 19520331Sjkh if ((*Obj)->prev != NULL) { 19620331Sjkh *Obj = (*Obj)->prev; /* previous object */ 1978097Sjkh } else { 1988097Sjkh *Obj = last; /* end of the list */ 19922099Sjkh } 20022099Sjkh break; 20122099Sjkh } 20222099Sjkh 20321243Sjkh return(ret); 20421243Sjkh 20521243Sjkh} /* PollObj() */ 20621243Sjkh 20721243Sjkh 20821243Sjkhvoid 20921243SjkhDelObj(ComposeObj *Obj) 21021243Sjkh/* 21121243Sjkh * Desc: Free all objects 21221243Sjkh */ 21321243Sjkh{ 21421243Sjkh ComposeObj *o; 21521243Sjkh 21612661Speter o = Obj; 2178792Sjkh while (Obj != NULL) { 21812661Speter switch(Obj->objtype) { 21912661Speter case STRINGOBJ: 2208792Sjkh DelStringObj((StringObj *) Obj->obj); 2218792Sjkh break; 22220355Sjkh case LISTOBJ: 22320355Sjkh DelListObj((ListObj *) Obj->obj); 2248792Sjkh break; 2258792Sjkh case BUTTONOBJ: 2268208Sjkh DelButtonObj((ButtonObj *) Obj->obj); 2278363Sjkh break; 2288208Sjkh } 2298208Sjkh Obj = Obj->next; 2308756Sjkh } 2318208Sjkh 2328208Sjkh FreeObj(o); 2338208Sjkh} /* DelObj() */ 2348642Sjkh 2358837Sjkh/*********************************************************************** 2368837Sjkh * 2378363Sjkh * StringObj routines 2388208Sjkh * 2398097Sjkh ***********************************************************************/ 24017189Sjkh 24117189Sjkhstatic void 24217189Sjkhoutstr(WINDOW *win, char *str, int attrs) 24317189Sjkh{ 24417189Sjkh if (attrs & DITEM_NO_ECHO) { 2458208Sjkh char *cpy; 2468208Sjkh int n = strlen(str); 2478208Sjkh 2488556Sjkh cpy = alloca(n + 1); 2498636Sjkh memset(cpy, '*', n); 2508208Sjkh cpy[n] = '\0'; 2518549Sjkh waddstr(win, cpy); 2529202Srgrimes } 25320315Sjkh else 2549202Srgrimes waddstr(win, str); 2558556Sjkh} 2569202Srgrimes 2578208Sjkhvoid 2588208SjkhRefreshStringObj(StringObj *so) 2598307Sjkh/* 2608307Sjkh * Desc: redraw the object 2618307Sjkh */ 2628307Sjkh{ 2638307Sjkh char tmp[512]; 2648549Sjkh 2658549Sjkh wmove(so->win, so->y, so->x+1); 2668307Sjkh wattrset(so->win, dialog_attr); 2678208Sjkh waddstr(so->win, so->title); 2688336Sjkh 2698336Sjkh draw_box(so->win, so->y+1, so->x, 3, so->w, dialog_attr, border_attr); 2708336Sjkh wattrset(so->win, item_attr); 2718307Sjkh wmove(so->win, so->y+2, so->x+1); 2728307Sjkh if (strlen(so->s) > so->w-2) { 2738307Sjkh strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1); 2748336Sjkh outstr(so->win, tmp, so->attr_mask); 2758307Sjkh } else { 2768307Sjkh outstr(so->win, so->s, so->attr_mask); 27712661Speter } 27812661Speter 27912661Speter return; 28012661Speter} /* RefreshStringObj() */ 28112661Speter 28212661SpeterStringObj * 28312661SpeterNewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len) 28412661Speter/* 28512661Speter * Desc: Initialize a new stringobj and return a pointer to it. 28612661Speter * Draw the object on the screen at the specified coordinates 28712661Speter */ 28812661Speter{ 28912661Speter StringObj *so; 29012661Speter 29112661Speter /* Initialize a new object */ 29212661Speter so = (StringObj *) malloc( sizeof(StringObj) ); 29312661Speter if (!so) { 29412661Speter printf("NewStringObj: Error malloc'ing StringObj\n"); 29512661Speter exit(-1); 29612661Speter } 29712661Speter so->title = (char *) malloc( strlen(title) + 1); 29812661Speter if (!so->title) { 29912661Speter printf("NewStringObj: Error malloc'ing so->title\n"); 30012661Speter exit(-1); 30112661Speter } 30212661Speter strcpy(so->title, title); 30312661Speter so->s = s; 30412661Speter strcpy(so->s, s); 30512661Speter so->x = x; 30612661Speter so->y = y; 30714670Sjkh so->w = w; 30812661Speter so->len = len; 30912661Speter so->win = win; 31012661Speter so->attr_mask = DialogInputAttrs; /* Grossly use a global to avoid changing API */ 31112661Speter 3128549Sjkh /* Draw it on the screen */ 3138307Sjkh RefreshStringObj(so); 31412661Speter 3158810Sjkh return(so); 31612661Speter} /* NewStringObj() */ 3178549Sjkh 3188810Sjkhint 3198810SjkhSelectStringObj(StringObj *so) 3208810Sjkh/* 3218810Sjkh * Desc: get input using the info in <so> 3228810Sjkh */ 3238810Sjkh{ 3248810Sjkh int key; 3258810Sjkh char tmp[so->len+1]; 3268208Sjkh 32725052Sjkh strcpy(tmp, so->s); 3288576Sjkh key = line_edit(so->win, so->y+2, so->x+1, 32915439Sjkh so->len, so->w-2, inputbox_attr, TRUE, tmp, so->attr_mask); 3308881Srgrimes if ((key == '\n') || (key == '\r') || (key == '\t') || key == (KEY_BTAB) ) { 3318735Sjkh strcpy(so->s, tmp); 3328576Sjkh } 3338576Sjkh RefreshStringObj(so); 3348576Sjkh if (key == ESC) { 3358576Sjkh return(SEL_ESC); 3368636Sjkh } 3378576Sjkh if (key == '\t') { 3389202Srgrimes return(SEL_TAB); 3398576Sjkh } 3408576Sjkh if ( (key == KEY_BTAB) || (key == KEY_F(2)) ) { 3418576Sjkh return(SEL_BACKTAB); 3428576Sjkh } 3439202Srgrimes if ((key == '\n') || (key == '\r')) { 34417375Sjkh return(SEL_CR); 3458576Sjkh } 34615242Sjkh return(key); 3478660Sjkh} /* SelectStringObj() */ 3488715Sjkh 3498576Sjkh 35010882Spetervoid 35116412SjkhDelStringObj(StringObj *so) 3528576Sjkh/* 3538576Sjkh * Desc: Free the space occupied by <so> 3548576Sjkh */ 35512661Speter{ 3568576Sjkh free(so->title); 3578677Sjkh free(so); 3588576Sjkh 3598576Sjkh return; 3608677Sjkh} 3618677Sjkh 3628810Sjkh/*********************************************************************** 3638722Sjkh * 36419488Sjkh * ListObj routines 3658810Sjkh * 3668810Sjkh ***********************************************************************/ 3678810Sjkh 36819488Sjkhvoid 3698810SjkhDrawNames(ListObj *lo) 37010882Speter/* 3718576Sjkh * Desc: Just refresh the names, not the surrounding box and title 37212661Speter */ 3739202Srgrimes{ 3748576Sjkh int i, j, h, x, y; 3758576Sjkh char tmp[MAXPATHLEN]; 3768576Sjkh 3778576Sjkh x = lo->x + 1; 3788576Sjkh y = lo->y + 2; 37919577Sjkh h = lo->h - 2; 3808576Sjkh for (i=lo->scroll; i<lo->n && i<lo->scroll+h; i++) { 3818576Sjkh wmove(lo->win, y+i-lo->scroll, x); 38212661Speter if (lo->seld[i]) { 38320231Sjkh wattrset(lo->win, A_BOLD); 38421010Sjkh } else { 38521978Sjkh wattrset(lo->win, item_attr); 3868576Sjkh } 38721243Sjkh if (strlen(lo->name[i]) > lo->w-2) { 38821243Sjkh strncpy(tmp, lo->name[i], lo->w-2); 38921243Sjkh tmp[lo->w - 2] = 0; 3908576Sjkh waddstr(lo->win, tmp); 3918208Sjkh } else { 3928107Sjkh waddstr(lo->win, lo->name[i]); 39312661Speter for (j=strlen(lo->name[i]); j<lo->w-2; j++) waddstr(lo->win, " "); 39415091Sjkh } 39512661Speter } 3968792Sjkh wattrset(lo->win, item_attr); 39712661Speter while (i<lo->scroll+h) { 39812661Speter wmove(lo->win, y+i-lo->scroll, x); 39920315Sjkh for (j=0; j<lo->w-2; j++) waddstr(lo->win, " "); 4008792Sjkh i++; 4018792Sjkh } 4028792Sjkh 40320315Sjkh return; 4048792Sjkh} /* DrawNames() */ 4058792Sjkh 4068347Sjkhvoid 4078347SjkhRefreshListObj(ListObj *lo) 4088347Sjkh/* 4098347Sjkh * Desc: redraw the list object 4108549Sjkh */ 4118549Sjkh{ 4128347Sjkh char perc[7]; 4138705Sjkh 41412661Speter /* setup the box */ 41525251Sjkh wmove(lo->win, lo->y, lo->x+1); 41622756Sjkh wattrset(lo->win, dialog_attr); 41725251Sjkh waddstr(lo->win, lo->title); 41826456Sjkh draw_box(lo->win, lo->y+1, lo->x, lo->h, lo->w, dialog_attr, border_attr); 41923588Sjkh 4208722Sjkh /* draw the names */ 42115091Sjkh DrawNames(lo); 42219397Sjkh 42315091Sjkh /* Draw % indication */ 42415091Sjkh sprintf(perc, "(%3d%%)", MIN(100, (int) (100 * (lo->sel+lo->h-2) / MAX(1, lo->n)))); 42521701Sjkh wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); 42626764Sjkh wattrset(lo->win, dialog_attr); 42719385Sjkh waddstr(lo->win, perc); 42816828Sjkh 42916828Sjkh 43025251Sjkh return; 43119577Sjkh} /* RefreshListObj() */ 43216828Sjkh 43319577SjkhListObj * 4348705SjkhNewListObj(WINDOW *win, char *title, char **list, char *listelt, int y, int x, 4359202Srgrimes int h, int w, int n) 4369202Srgrimes/* 4379202Srgrimes * Desc: create a listobj, draw it on the screen and return a pointer to it. 4388351Sjkh */ 43915242Sjkh{ 44015242Sjkh ListObj *lo; 4418556Sjkh int i; 4428556Sjkh 44321730Sjkh /* Initialize a new object */ 4448636Sjkh lo = (ListObj *) malloc( sizeof(ListObj) ); 4458641Sjkh if (!lo) { 4468641Sjkh fprintf(stderr, "NewListObj: Error malloc'ing ListObj\n"); 44720315Sjkh exit(-1); 44820315Sjkh } 44920315Sjkh lo->title = (char *) malloc( strlen(title) + 1); 4508722Sjkh if (!lo->title) { 4519202Srgrimes fprintf(stderr, "NewListObj: Error malloc'ing lo->title\n"); 45220315Sjkh exit(-1); 4539202Srgrimes } 4548097Sjkh strcpy(lo->title, title); 4558351Sjkh lo->name = list; 45615091Sjkh if (n>0) { 45715091Sjkh lo->seld = (int *) malloc( n * sizeof(int) ); 45815242Sjkh if (!lo->seld) { 4598097Sjkh fprintf(stderr, "NewListObj: Error malloc'ing lo->seld\n"); 46015788Sjkh exit(-1); 46115788Sjkh } 46215788Sjkh for (i=0; i<n; i++) { 4638278Sjkh lo->seld[i] = FALSE; 46415383Sjkh } 46525473Spst } else { 46626456Sjkh lo->seld = NULL; 46715091Sjkh } 46815091Sjkh lo->y = y; 46915091Sjkh lo->x = x; 47015091Sjkh lo->w = w; 47115091Sjkh lo->h = h; 47215091Sjkh lo->n = n; 47315091Sjkh lo->scroll = 0; 47415091Sjkh lo->sel = 0; 47515091Sjkh lo->elt = listelt; 47615091Sjkh lo->win = win; 47715091Sjkh 4788278Sjkh /* Draw the object on the screen */ 4798107Sjkh RefreshListObj(lo); 48015091Sjkh 48115091Sjkh return(lo); 48215091Sjkh} /* NewListObj() */ 48315091Sjkh 48415416Sjkhvoid 48515091SjkhUpdateListObj(ListObj *lo, char **list, int n) 48619573Sjoerg/* 48719488Sjkh * Desc: Update the list in the listobject with the provided list 48816327Sjkh * Pre: lo->name "has been freed" 48915091Sjkh * "(A i: 0<=i<lo->n: "lo->name[i] has been freed")" 49015091Sjkh */ 49116887Sjkh{ 49216887Sjkh int i; 49315091Sjkh 49426610Sjkh if (lo->seld) { 49515091Sjkh free(lo->seld); 49615091Sjkh } 4978097Sjkh 49812661Speter /* Rewrite the list in the object */ 49915091Sjkh lo->name = list; 50015091Sjkh if (n>0) { 50112661Speter lo->seld = (int *) malloc( n * sizeof(int) ); 5028792Sjkh if (!lo->seld) { 50320315Sjkh fprintf(stderr, "UpdateListObj: Error malloc'ing lo->seld\n"); 5048792Sjkh exit(-1); 50520315Sjkh } 5068792Sjkh for (i=0; i<n; i++) { 5078792Sjkh lo->seld[i] = FALSE; 5088792Sjkh } 5098792Sjkh } else { 5108792Sjkh lo->seld = NULL; 51120315Sjkh } 5128792Sjkh lo->n = n; 5138792Sjkh lo->scroll = 0; 5148792Sjkh lo->sel = 0; 51520315Sjkh 5168792Sjkh /* Draw the object on the screen */ 51720315Sjkh RefreshListObj(lo); 5188792Sjkh 5198792Sjkh return; 5208351Sjkh} /* UpdateListObj() */ 5218351Sjkh 5228351Sjkhint 52312661SpeterSelectListObj(ListObj *lo) 52420315Sjkh/* 52512661Speter * Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit 52612661Speter * Pre: lo->n >= 1 52712661Speter */ 52812661Speter{ 52912661Speter int key, sel_x, sel_y, quit; 53014670Sjkh char tmp[MAXPATHLEN]; 53112661Speter char perc[4]; 5328351Sjkh 53317368Sjkh sel_x = lo->x+1; 53415091Sjkh sel_y = lo->y + 2 + lo->sel - lo->scroll; 53515788Sjkh 53615091Sjkh if (lo->n == 0) return(SEL_TAB); 53715091Sjkh 53821010Sjkh keypad(lo->win, TRUE); 53915242Sjkh 54015242Sjkh /* Draw current selection in inverse video */ 54115091Sjkh wmove(lo->win, sel_y, sel_x); 54215091Sjkh wattrset(lo->win, item_selected_attr); 54315091Sjkh waddstr(lo->win, lo->name[lo->sel]); 54415091Sjkh 54522756Sjkh key = wgetch(lo->win); 54612661Speter quit = FALSE; 5478351Sjkh while ((key != '\t') && (key != '\n') && (key != '\r') 54819573Sjoerg && (key != ESC) && (key != KEY_F(1)) && (key != '?') && !quit) { 54919573Sjoerg /* first draw current item in normal video */ 5508351Sjkh wmove(lo->win, sel_y, sel_x); 5518549Sjkh if (lo->seld[lo->sel]) { 55215091Sjkh wattrset(lo->win, A_BOLD); 55315091Sjkh } else { 5548549Sjkh wattrset(lo->win, item_attr); 55512661Speter } 55612661Speter if (strlen(lo->name[lo->sel]) > lo->w - 2) { 55712661Speter strncpy(tmp, lo->name[lo->sel], lo->w - 2); 5588351Sjkh tmp[lo->w - 2] = 0; 55927798Sjkh waddstr(lo->win, tmp); 5608405Sjkh } else { 5618405Sjkh waddstr(lo->win, lo->name[lo->sel]); 5628405Sjkh } 5638405Sjkh 5648405Sjkh switch (key) { 5658405Sjkh case KEY_DOWN: 5668405Sjkh case ctrl('n'): 5678601Sjkh if (sel_y < lo->y + lo->h-1) { 5688601Sjkh if (lo->sel < lo->n-1) { 5698629Sjkh sel_y++; 5708629Sjkh lo->sel++; 5718629Sjkh } 5728351Sjkh } else { 5738351Sjkh if (lo->sel < lo->n-1) { 57412661Speter lo->sel++; 57524038Sjkh lo->scroll++; 57621855Sjkh DrawNames(lo); 57715091Sjkh wrefresh(lo->win); 57815091Sjkh } 57915091Sjkh } 58015091Sjkh break; 58115091Sjkh case KEY_UP: 58215091Sjkh case ctrl('p'): 58315091Sjkh if (sel_y > lo->y+2) { 58415091Sjkh if (lo->sel > 0) { 58515091Sjkh sel_y--; 58618619Sjkh lo->sel--; 58715091Sjkh } 58815091Sjkh } else { 58920484Sjkh if (lo->sel > 0) { 5908837Sjkh lo->sel--; 5918799Sphk lo->scroll--; 5928556Sjkh DrawNames(lo); 5938576Sjkh wrefresh(lo->win); 5948107Sjkh } 5958097Sjkh } 5968097Sjkh break; 59714670Sjkh case KEY_HOME: 59817034Sjkh case ctrl('a'): 59916462Sjkh lo->sel = 0; 6008097Sjkh lo->scroll = 0; 60112661Speter sel_y = lo->y + 2; 6028097Sjkh DrawNames(lo); 6038097Sjkh wrefresh(lo->win); 60412661Speter break; 60512661Speter case KEY_END: 6068097Sjkh case ctrl('e'): 6078208Sjkh if (lo->n < lo->h - 3) { 6088363Sjkh lo->sel = lo->n-1; 60915242Sjkh lo->scroll = 0; 61015242Sjkh sel_y = lo->y + 2 + lo->sel - lo->scroll; 61115242Sjkh } else { 61215242Sjkh /* more than one page of list */ 61315242Sjkh lo->sel = lo->n-1; 61415242Sjkh lo->scroll = lo->n-1 - (lo->h-3); 61517005Sjkh sel_y = lo->y + 2 + lo->sel - lo->scroll; 6168556Sjkh DrawNames(lo); 61721243Sjkh wrefresh(lo->win); 61821243Sjkh } 61921243Sjkh break; 62021243Sjkh case KEY_NPAGE: 62121243Sjkh case ctrl('f'): 62215242Sjkh lo->sel += lo->h - 2; 62315242Sjkh if (lo->sel >= lo->n) lo->sel = lo->n - 1; 62420247Sjkh lo->scroll += lo->h - 2; 6258097Sjkh if (lo->scroll >= lo->n - 1) lo->scroll = lo->n - 1; 6268107Sjkh if (lo->scroll < 0) lo->scroll = 0; 6278837Sjkh sel_y = lo->y + 2 + lo->sel - lo->scroll; 6288097Sjkh DrawNames(lo); 6298262Sjkh wrefresh(lo->win); 6308097Sjkh break; 6318347Sjkh case KEY_PPAGE: 6328097Sjkh case ctrl('b'): 6338097Sjkh lo->sel -= lo->h - 2; 6348208Sjkh if (lo->sel < 0) lo->sel = 0; 6358313Sjkh lo->scroll -= lo->h - 2; 6368705Sjkh if (lo->scroll < 0) lo->scroll = 0; 6378208Sjkh sel_y = lo->y + 2 + lo->sel - lo->scroll; 6388262Sjkh DrawNames(lo); 63912661Speter wrefresh(lo->win); 64012661Speter break; 6418097Sjkh default: 6428792Sjkh quit = TRUE; 6438792Sjkh break; 6448792Sjkh } 6458792Sjkh /* Draw % indication */ 6468837Sjkh sprintf(perc, "(%3d%%)", MIN(100, (int) 6478837Sjkh (100 * (lo->sel+lo->h - 2) / MAX(1, lo->n)))); 64820315Sjkh wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); 6498837Sjkh wattrset(lo->win, dialog_attr); 6508837Sjkh waddstr(lo->win, perc); 65112661Speter 65215091Sjkh /* draw current item in inverse */ 65312661Speter wmove(lo->win, sel_y, sel_x); 65412661Speter wattrset(lo->win, item_selected_attr); 65526613Sjkh if (strlen(lo->name[lo->sel]) > lo->w - 2) { 65612661Speter /* when printing in inverse video show the last characters in the */ 65714738Sjkh /* name that will fit in the window */ 65815788Sjkh strncpy(tmp, 65912661Speter lo->name[lo->sel] + strlen(lo->name[lo->sel]) - (lo->w - 2), 66023904Sjkh lo->w - 2); 66123904Sjkh tmp[lo->w - 2] = 0; 66223904Sjkh waddstr(lo->win, tmp); 6638351Sjkh } else { 6648351Sjkh waddstr(lo->win, lo->name[lo->sel]); 66515788Sjkh } 66612661Speter if (!quit) key = wgetch(lo->win); 6678351Sjkh } 66812661Speter 6698351Sjkh if (key == ESC) { 6708351Sjkh return(SEL_ESC); 6718351Sjkh } 67212661Speter if (key == '\t') { 6738351Sjkh return(SEL_TAB); 67412661Speter } 6758351Sjkh if ((key == KEY_BTAB) || (key == ctrl('b'))) { 6768107Sjkh return(SEL_BACKTAB); 6778792Sjkh } 67812661Speter if ((key == '\n') || (key == '\r')) { 6798792Sjkh strcpy(lo->elt, lo->name[lo->sel]); 68020315Sjkh return(SEL_CR); 6818792Sjkh } 6828792Sjkh return(key); 6838556Sjkh} /* SelectListObj() */ 6848768Sjkh 68515091Sjkhvoid 68622842SjkhDelListObj(ListObj *lo) 6878556Sjkh/* 6888351Sjkh * Desc: Free the space occupied by the listobject 6898351Sjkh */ 6908208Sjkh{ 6918792Sjkh free(lo->title); 6928837Sjkh if (lo->seld != NULL) free(lo->seld); 6938792Sjkh free(lo); 69420315Sjkh 6958792Sjkh return; 69620231Sjkh} /* DelListObj() */ 69720231Sjkh 69820231Sjkhvoid 69920231SjkhMarkCurrentListObj(ListObj *lo) 70012661Speter/* 7018208Sjkh * Desc: mark the current item for the selection list 7028208Sjkh */ 70312661Speter{ 70412661Speter lo->seld[lo->sel] = !(lo->seld[lo->sel]); 70512661Speter DrawNames(lo); 70626610Sjkh 7078208Sjkh return; 70824038Sjkh} /* MarkCurrentListObj() */ 70924038Sjkh 71024038Sjkhvoid 7118281SjkhMarkAllListObj(ListObj *lo) 7128549Sjkh/* 7138281Sjkh * Desc: mark all items 7148097Sjkh */ 7158097Sjkh{ 716 int i; 717 718 for (i=0; i<lo->n; i++) { 719 lo->seld[i] = TRUE; 720 } 721 DrawNames(lo); 722 723 return; 724} /* MarkAllListObj() */ 725 726void 727UnMarkAllListObj(ListObj *lo) 728/* 729 * Desc: unmark all items 730 */ 731{ 732 int i; 733 734 for (i=0; i<lo->n; i++) { 735 lo->seld[i] = FALSE; 736 } 737 DrawNames(lo); 738 739 return; 740} /* UnMarkAllListObj() */ 741 742 743/*********************************************************************** 744 * 745 * ButtonObj routines 746 * 747 ***********************************************************************/ 748 749 750void 751RefreshButtonObj(ButtonObj *bo) 752/* 753 * Desc: redraw the button 754 */ 755{ 756 draw_box(bo->win, bo->y, bo->x, 3, bo->w, dialog_attr, border_attr); 757 print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); 758 759 return; 760} /* RefreshButtonObj() */ 761 762ButtonObj * 763NewButtonObj(WINDOW *win, char *title, int *pushed, int y, int x) 764/* 765 * Desc: Create a new button object 766 */ 767{ 768 ButtonObj *bo; 769 770 bo = (ButtonObj *) malloc( sizeof(ButtonObj) ); 771 772 bo->win = win; 773 bo->title = (char *) malloc( strlen(title) + 1); 774 strcpy(bo->title, title); 775 bo->x = x; 776 bo->y = y; 777 bo->w = strlen(title) + 6; 778 bo->h = 3; 779 bo->pushed = pushed; 780 781 RefreshButtonObj(bo); 782 783 return(bo); 784} /* NewButtonObj() */ 785 786int 787SelectButtonObj(ButtonObj *bo) 788/* 789 * Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC 790 */ 791{ 792 int key; 793 794 print_button(bo->win, bo->title, bo->y+1, bo->x+2, TRUE); 795 wmove(bo->win, bo->y+1, bo->x+(bo->w/2)-1); 796 key = wgetch(bo->win); 797 print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); 798 switch(key) { 799 case '\t': 800 return(SEL_TAB); 801 break; 802 case KEY_BTAB: 803 case ctrl('b'): 804 return(SEL_BACKTAB); 805 case '\n': 806 case '\r': 807 *(bo->pushed) = TRUE; 808 return(SEL_BUTTON); 809 break; 810 case ESC: 811 return(SEL_ESC); 812 break; 813 default: 814 return(key); 815 break; 816 } 817} /* SelectButtonObj() */ 818 819void 820DelButtonObj(ButtonObj *bo) 821/* 822 * Desc: Free the space occupied by <bo> 823 */ 824{ 825 free(bo->title); 826 free(bo); 827 828 return; 829} /* DelButtonObj() */ 830