16458Sache/* 26458Sache * Program: objects.c 36458Sache * Author: Marc van Kempen 46458Sache * Desc: Implementation of UI-objects: 56458Sache * - String input fields 68858Srgrimes * - List selection 76458Sache * - Buttons 86458Sache * 96458Sache * Copyright (c) 1995, Marc van Kempen 106458Sache * 116458Sache * All rights reserved. 126458Sache * 136458Sache * This software may be used, modified, copied, distributed, and 146458Sache * sold, in both source and binary form provided that the above 156458Sache * copyright and these terms are retained, verbatim, as the first 166458Sache * lines of this file. Under no circumstances is the author 176458Sache * responsible for the proper functioning of this software, nor does 186458Sache * the author assume any responsibility for damages incurred with 196458Sache * its use. 208858Srgrimes * 216458Sache */ 226458Sache 236458Sache#include <stdlib.h> 246458Sache#include <sys/param.h> 256458Sache#include <ncurses.h> 266458Sache#include <dialog.h> 276458Sache#include "dialog.priv.h" 286458Sache#include "ui_objects.h" 296458Sache 306458Sache#define ESC 27 316458Sache 326458Sache/*********************************************************************** 336458Sache * 346458Sache * Obj routines 356458Sache * 366458Sache ***********************************************************************/ 376458Sache 386458Sachevoid 396458SacheAddObj(ComposeObj **Obj, int objtype, void *obj) 406458Sache/* 416458Sache * Desc: Add the object <obj> to the list of objects <Obj> 426458Sache */ 436458Sache{ 446458Sache if (*Obj == NULL) { 456458Sache /* Create the root object */ 466458Sache *Obj = (ComposeObj *) malloc( sizeof(ComposeObj) ); 476458Sache if (!Obj) { 486458Sache printf("AddObj: Error malloc'ing ComposeObj\n"); 496458Sache exit(-1); 506458Sache } 516458Sache (*Obj)->objtype = objtype; 526458Sache (*Obj)->obj = obj; 536458Sache (*Obj)->next = NULL; 546458Sache (*Obj)->prev = NULL; 556458Sache } else { 566458Sache ComposeObj *o = *Obj; 576458Sache 586458Sache /* create the next object */ 596458Sache while (o->next) o = (ComposeObj *) o->next; 606458Sache o->next = (struct ComposeObj *) malloc( sizeof(ComposeObj) ); 616458Sache if (!o->next) { 626458Sache printf("AddObj: Error malloc'ing o->next\n"); 636458Sache exit(-1); 646458Sache } 656458Sache o->next->objtype = objtype; 666458Sache o->next->obj = obj; 676458Sache o->next->next = NULL; 686458Sache o->next->prev = o; 696458Sache } 706458Sache 716458Sache return; 726458Sache} /* AddObj() */ 736458Sache 746458Sachevoid 756458SacheFreeObj(ComposeObj *Obj) 766458Sache/* 776458Sache * Desc: free the memory occupied by *Obj 786458Sache */ 796458Sache{ 806458Sache ComposeObj *o = Obj; 818858Srgrimes 826458Sache o = Obj; 836458Sache while (o) { 846458Sache o = Obj->next; 856458Sache free(Obj); 866458Sache Obj = o; 876458Sache } 888858Srgrimes 896458Sache return; 906458Sache} /* FreeObj() */ 916458Sache 926458Sache 936458Sacheint 946458SacheReadObj(ComposeObj *Obj) 956458Sache/* 968858Srgrimes * Desc: navigate through the different objects calling their 976458Sache * respective navigation routines as necessary 986458Sache * Pre: Obj != NULL 996458Sache */ 1006458Sache{ 1016458Sache ComposeObj *o; 1026458Sache ComposeObj *last; /* the last object in the list */ 1036458Sache int ret; /* the return value from the selection routine */ 1046458Sache 1056458Sache /* find the last object in the list */ 1066458Sache last = Obj; 1076458Sache while (last->next) last = last->next; 1086458Sache 1096458Sache ret = 0; 1106458Sache o = Obj; 1116458Sache while ((ret != SEL_BUTTON) && (ret != SEL_ESC)) { 1126458Sache switch(o->objtype) { 1136458Sache case STRINGOBJ: 1146458Sache ret = SelectStringObj((StringObj *) o->obj); 1156458Sache break; 1166458Sache case LISTOBJ: 1176458Sache ret = SelectListObj((ListObj *) o->obj); 1186458Sache break; 1196458Sache case BUTTONOBJ: 1206458Sache ret = SelectButtonObj((ButtonObj *) o->obj); 1216458Sache break; 1226458Sache } 1236458Sache switch(ret) { 12417984Sjkh case KEY_DOWN: 1256458Sache case SEL_CR: 1266458Sache case SEL_TAB: /* move to the next object in the list */ 1276458Sache if (o->next != NULL) { 1286458Sache o = o->next; /* next object */ 1296458Sache } else { 1306458Sache o = Obj; /* beginning of the list */ 1316458Sache } 1326458Sache break; 13317984Sjkh 13417984Sjkh case KEY_UP: 1356458Sache case SEL_BACKTAB: /* move to the previous object in the list */ 1366458Sache if (o->prev != NULL) { 1376458Sache o = o->prev; /* previous object */ 1386458Sache } else { 1396458Sache o = last; /* end of the list */ 1406458Sache } 1416458Sache break; 14217984Sjkh 1436458Sache case KEY_F(1): /* display help_file */ 1446458Sache case '?': 1456458Sache display_helpfile(); 1466458Sache break; 1476458Sache } 1486458Sache } 1496458Sache 1506458Sache return(ret); 1518858Srgrimes 1526458Sache} /* ReadObj() */ 1536458Sache 1546458Sache 1556458Sacheint 1566458SachePollObj(ComposeObj **Obj) 1576458Sache{ 1586458Sache ComposeObj *last; /* the last object in the list */ 1596458Sache ComposeObj *first; /* the first object in the list */ 1606458Sache int ret; /* the return value from the selection routine */ 1616458Sache 1626458Sache /* find the last object in the list */ 1636458Sache last = *Obj; 1646458Sache while (last->next) last = last->next; 1656458Sache 1666458Sache /* find the first object in the list */ 1676458Sache first = *Obj; 1686458Sache while (first->prev) first = first->prev; 1696458Sache 1706458Sache ret = 0; 1716458Sache switch((*Obj)->objtype) { 1726458Sache case STRINGOBJ: 1736458Sache ret = SelectStringObj((StringObj *) (*Obj)->obj); 1746458Sache break; 1756458Sache case LISTOBJ: 1766458Sache ret = SelectListObj((ListObj *) (*Obj)->obj); 1776458Sache break; 1786458Sache case BUTTONOBJ: 1796458Sache ret = SelectButtonObj((ButtonObj *) (*Obj)->obj); 1806458Sache break; 1816458Sache } 1826458Sache switch(ret) { 18317984Sjkh case KEY_DOWN: 1846458Sache case SEL_CR: 1856458Sache case SEL_TAB: /* move to the next object in the list */ 1866458Sache if ((*Obj)->next != NULL) { 1876458Sache *Obj = (*Obj)->next; /* next object */ 1886458Sache } else { 1896458Sache *Obj = first; /* beginning of the list */ 1906458Sache } 1916458Sache break; 19217984Sjkh 19317984Sjkh case KEY_UP: 1946458Sache case SEL_BACKTAB: /* move to the previous object in the list */ 1956458Sache if ((*Obj)->prev != NULL) { 1966458Sache *Obj = (*Obj)->prev; /* previous object */ 1976458Sache } else { 1986458Sache *Obj = last; /* end of the list */ 1996458Sache } 2006458Sache break; 2016458Sache } 2026458Sache 2036458Sache return(ret); 2046458Sache 2056458Sache} /* PollObj() */ 2066458Sache 2076458Sache 2086458Sachevoid 2096458SacheDelObj(ComposeObj *Obj) 2106458Sache/* 2116458Sache * Desc: Free all objects 2126458Sache */ 2136458Sache{ 2146458Sache ComposeObj *o; 2156458Sache 2166458Sache o = Obj; 2176458Sache while (Obj != NULL) { 2186458Sache switch(Obj->objtype) { 2196458Sache case STRINGOBJ: 2206458Sache DelStringObj((StringObj *) Obj->obj); 2216458Sache break; 2226458Sache case LISTOBJ: 2236458Sache DelListObj((ListObj *) Obj->obj); 2246458Sache break; 2256458Sache case BUTTONOBJ: 2266458Sache DelButtonObj((ButtonObj *) Obj->obj); 2276458Sache break; 2286458Sache } 2296458Sache Obj = Obj->next; 2306458Sache } 2316458Sache 2326458Sache FreeObj(o); 2336458Sache} /* DelObj() */ 2348858Srgrimes 2356458Sache/*********************************************************************** 2366458Sache * 2376458Sache * StringObj routines 2386458Sache * 2396458Sache ***********************************************************************/ 2406458Sache 24120442Sjkhstatic void 24220442Sjkhoutstr(WINDOW *win, char *str, int attrs) 24320442Sjkh{ 24420442Sjkh if (attrs & DITEM_NO_ECHO) { 24520442Sjkh char *cpy; 24620442Sjkh int n = strlen(str); 24720442Sjkh 24820442Sjkh cpy = alloca(n + 1); 24920442Sjkh memset(cpy, '*', n); 25020442Sjkh cpy[n] = '\0'; 25120442Sjkh waddstr(win, cpy); 25220442Sjkh } 25320442Sjkh else 25420442Sjkh waddstr(win, str); 25520442Sjkh} 25620442Sjkh 2576458Sachevoid 2586458SacheRefreshStringObj(StringObj *so) 2596458Sache/* 2606458Sache * Desc: redraw the object 2616458Sache */ 2626458Sache{ 2636458Sache char tmp[512]; 2646458Sache 2656458Sache wmove(so->win, so->y, so->x+1); 2666458Sache wattrset(so->win, dialog_attr); 2676458Sache waddstr(so->win, so->title); 2686458Sache 2696458Sache draw_box(so->win, so->y+1, so->x, 3, so->w, dialog_attr, border_attr); 2706458Sache wattrset(so->win, item_attr); 2716458Sache wmove(so->win, so->y+2, so->x+1); 2726458Sache if (strlen(so->s) > so->w-2) { 2736458Sache strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1); 27420442Sjkh outstr(so->win, tmp, so->attr_mask); 2756458Sache } else { 27620442Sjkh outstr(so->win, so->s, so->attr_mask); 2776458Sache } 2786458Sache 2796458Sache return; 2806458Sache} /* RefreshStringObj() */ 2816458Sache 2826458SacheStringObj * 2836458SacheNewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len) 2846458Sache/* 2856458Sache * Desc: Initialize a new stringobj and return a pointer to it. 2866458Sache * Draw the object on the screen at the specified coordinates 2876458Sache */ 2886458Sache{ 2896458Sache StringObj *so; 2908858Srgrimes 2916458Sache /* Initialize a new object */ 2926458Sache so = (StringObj *) malloc( sizeof(StringObj) ); 2936458Sache if (!so) { 2946458Sache printf("NewStringObj: Error malloc'ing StringObj\n"); 2956458Sache exit(-1); 2966458Sache } 2976458Sache so->title = (char *) malloc( strlen(title) + 1); 2986458Sache if (!so->title) { 2996458Sache printf("NewStringObj: Error malloc'ing so->title\n"); 3006458Sache exit(-1); 3016458Sache } 3026458Sache strcpy(so->title, title); 3036458Sache so->s = s; 3046458Sache strcpy(so->s, s); 3056458Sache so->x = x; 3066458Sache so->y = y; 3076458Sache so->w = w; 3086458Sache so->len = len; 3096458Sache so->win = win; 31020442Sjkh so->attr_mask = DialogInputAttrs; /* Grossly use a global to avoid changing API */ 3116458Sache 3126458Sache /* Draw it on the screen */ 3136458Sache RefreshStringObj(so); 3146458Sache 3156458Sache return(so); 3166458Sache} /* NewStringObj() */ 3176458Sache 3186458Sacheint 3196458SacheSelectStringObj(StringObj *so) 3206458Sache/* 3216458Sache * Desc: get input using the info in <so> 3226458Sache */ 3236458Sache{ 3246458Sache int key; 3256458Sache char tmp[so->len+1]; 3266458Sache 3276458Sache strcpy(tmp, so->s); 3288858Srgrimes key = line_edit(so->win, so->y+2, so->x+1, 32920442Sjkh so->len, so->w-2, inputbox_attr, TRUE, tmp, so->attr_mask); 3308804Sjkh if ((key == '\n') || (key == '\r') || (key == '\t') || key == (KEY_BTAB) ) { 3316458Sache strcpy(so->s, tmp); 3326458Sache } 3336458Sache RefreshStringObj(so); 3346458Sache if (key == ESC) { 3356458Sache return(SEL_ESC); 3366458Sache } 3376458Sache if (key == '\t') { 3386458Sache return(SEL_TAB); 3396458Sache } 3406458Sache if ( (key == KEY_BTAB) || (key == KEY_F(2)) ) { 3416458Sache return(SEL_BACKTAB); 3426458Sache } 3436458Sache if ((key == '\n') || (key == '\r')) { 3446458Sache return(SEL_CR); 3456458Sache } 3466458Sache return(key); 3476458Sache} /* SelectStringObj() */ 3486458Sache 3496458Sache 3506458Sachevoid 3516458SacheDelStringObj(StringObj *so) 3526458Sache/* 3536458Sache * Desc: Free the space occupied by <so> 3546458Sache */ 3556458Sache{ 3566458Sache free(so->title); 3576458Sache free(so); 3586458Sache 3596458Sache return; 3606458Sache} 3618858Srgrimes 3626458Sache/*********************************************************************** 3636458Sache * 3646458Sache * ListObj routines 3656458Sache * 3666458Sache ***********************************************************************/ 3676458Sache 3686458Sachevoid 3696458SacheDrawNames(ListObj *lo) 3706458Sache/* 3716458Sache * Desc: Just refresh the names, not the surrounding box and title 3726458Sache */ 3736458Sache{ 3746458Sache int i, j, h, x, y; 3756458Sache char tmp[MAXPATHLEN]; 3766458Sache 3776458Sache x = lo->x + 1; 3786458Sache y = lo->y + 2; 3796458Sache h = lo->h - 2; 3806458Sache for (i=lo->scroll; i<lo->n && i<lo->scroll+h; i++) { 3816458Sache wmove(lo->win, y+i-lo->scroll, x); 3827959Sache if (lo->seld[i]) { 3837959Sache wattrset(lo->win, A_BOLD); 3847959Sache } else { 3857959Sache wattrset(lo->win, item_attr); 3867959Sache } 3876458Sache if (strlen(lo->name[i]) > lo->w-2) { 3886458Sache strncpy(tmp, lo->name[i], lo->w-2); 3896458Sache tmp[lo->w - 2] = 0; 3906458Sache waddstr(lo->win, tmp); 3916458Sache } else { 3926458Sache waddstr(lo->win, lo->name[i]); 3936458Sache for (j=strlen(lo->name[i]); j<lo->w-2; j++) waddstr(lo->win, " "); 3946458Sache } 3956458Sache } 3967959Sache wattrset(lo->win, item_attr); 3976458Sache while (i<lo->scroll+h) { 3986458Sache wmove(lo->win, y+i-lo->scroll, x); 3996458Sache for (j=0; j<lo->w-2; j++) waddstr(lo->win, " "); 4006458Sache i++; 4016458Sache } 4026458Sache 4038858Srgrimes return; 4046458Sache} /* DrawNames() */ 4056458Sache 4066458Sachevoid 4076458SacheRefreshListObj(ListObj *lo) 4086458Sache/* 4096458Sache * Desc: redraw the list object 4106458Sache */ 4116458Sache{ 4126458Sache char perc[7]; 4136458Sache 4146458Sache /* setup the box */ 4156458Sache wmove(lo->win, lo->y, lo->x+1); 4166458Sache wattrset(lo->win, dialog_attr); 4176458Sache waddstr(lo->win, lo->title); 4186458Sache draw_box(lo->win, lo->y+1, lo->x, lo->h, lo->w, dialog_attr, border_attr); 4196458Sache 4206458Sache /* draw the names */ 4216458Sache DrawNames(lo); 4226458Sache 4236458Sache /* Draw % indication */ 4246458Sache sprintf(perc, "(%3d%%)", MIN(100, (int) (100 * (lo->sel+lo->h-2) / MAX(1, lo->n)))); 4256458Sache wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); 4266458Sache wattrset(lo->win, dialog_attr); 4278858Srgrimes waddstr(lo->win, perc); 4288858Srgrimes 4298858Srgrimes 4306458Sache return; 4316458Sache} /* RefreshListObj() */ 4328858Srgrimes 4336458SacheListObj * 4346458SacheNewListObj(WINDOW *win, char *title, char **list, char *listelt, int y, int x, 4356458Sache int h, int w, int n) 4366458Sache/* 4376458Sache * Desc: create a listobj, draw it on the screen and return a pointer to it. 4386458Sache */ 4396458Sache{ 4406458Sache ListObj *lo; 4417959Sache int i; 4426458Sache 4436458Sache /* Initialize a new object */ 4446458Sache lo = (ListObj *) malloc( sizeof(ListObj) ); 4456458Sache if (!lo) { 4467959Sache fprintf(stderr, "NewListObj: Error malloc'ing ListObj\n"); 4476458Sache exit(-1); 4486458Sache } 4496458Sache lo->title = (char *) malloc( strlen(title) + 1); 4506458Sache if (!lo->title) { 4517959Sache fprintf(stderr, "NewListObj: Error malloc'ing lo->title\n"); 4526458Sache exit(-1); 4536458Sache } 4546458Sache strcpy(lo->title, title); 4556458Sache lo->name = list; 4567959Sache if (n>0) { 4577959Sache lo->seld = (int *) malloc( n * sizeof(int) ); 4587959Sache if (!lo->seld) { 4597959Sache fprintf(stderr, "NewListObj: Error malloc'ing lo->seld\n"); 4607959Sache exit(-1); 4617959Sache } 4627959Sache for (i=0; i<n; i++) { 4637959Sache lo->seld[i] = FALSE; 4647959Sache } 4657959Sache } else { 4667959Sache lo->seld = NULL; 4677959Sache } 4686458Sache lo->y = y; 4696458Sache lo->x = x; 4706458Sache lo->w = w; 4716458Sache lo->h = h; 4726458Sache lo->n = n; 4736458Sache lo->scroll = 0; 4746458Sache lo->sel = 0; 4756458Sache lo->elt = listelt; 4766458Sache lo->win = win; 4776458Sache 4786458Sache /* Draw the object on the screen */ 4796458Sache RefreshListObj(lo); 4806458Sache 4816458Sache return(lo); 4826458Sache} /* NewListObj() */ 4836458Sache 4846458Sachevoid 4856458SacheUpdateListObj(ListObj *lo, char **list, int n) 4866458Sache/* 4876458Sache * Desc: Update the list in the listobject with the provided list 4887959Sache * Pre: lo->name "has been freed" 4897959Sache * "(A i: 0<=i<lo->n: "lo->name[i] has been freed")" 4906458Sache */ 4916458Sache{ 4926458Sache int i; 4936458Sache 4947959Sache if (lo->seld) { 4957959Sache free(lo->seld); 4966458Sache } 4976458Sache 4986458Sache /* Rewrite the list in the object */ 4996458Sache lo->name = list; 5007959Sache if (n>0) { 5017959Sache lo->seld = (int *) malloc( n * sizeof(int) ); 5027959Sache if (!lo->seld) { 5037959Sache fprintf(stderr, "UpdateListObj: Error malloc'ing lo->seld\n"); 5047959Sache exit(-1); 5057959Sache } 5067959Sache for (i=0; i<n; i++) { 5077959Sache lo->seld[i] = FALSE; 5087959Sache } 5097959Sache } else { 5107959Sache lo->seld = NULL; 5118858Srgrimes } 5126458Sache lo->n = n; 5136458Sache lo->scroll = 0; 5146458Sache lo->sel = 0; 5156458Sache 5166458Sache /* Draw the object on the screen */ 5176458Sache RefreshListObj(lo); 5186458Sache 5196458Sache return; 5206458Sache} /* UpdateListObj() */ 5216458Sache 5226458Sacheint 5236458SacheSelectListObj(ListObj *lo) 5246458Sache/* 5256458Sache * Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit 5266458Sache * Pre: lo->n >= 1 5276458Sache */ 5286458Sache{ 5297959Sache int key, sel_x, sel_y, quit; 5306458Sache char tmp[MAXPATHLEN]; 5316458Sache char perc[4]; 5326458Sache 5336458Sache sel_x = lo->x+1; 5346458Sache sel_y = lo->y + 2 + lo->sel - lo->scroll; 5356458Sache 5366458Sache if (lo->n == 0) return(SEL_TAB); 5376458Sache 5386458Sache keypad(lo->win, TRUE); 5396458Sache 5406458Sache /* Draw current selection in inverse video */ 5416458Sache wmove(lo->win, sel_y, sel_x); 5426458Sache wattrset(lo->win, item_selected_attr); 5436458Sache waddstr(lo->win, lo->name[lo->sel]); 5446458Sache 5456458Sache key = wgetch(lo->win); 5467959Sache quit = FALSE; 5478858Srgrimes while ((key != '\t') && (key != '\n') && (key != '\r') 5487959Sache && (key != ESC) && (key != KEY_F(1)) && (key != '?') && !quit) { 5496458Sache /* first draw current item in normal video */ 5506458Sache wmove(lo->win, sel_y, sel_x); 5517959Sache if (lo->seld[lo->sel]) { 5527959Sache wattrset(lo->win, A_BOLD); 5537959Sache } else { 5547959Sache wattrset(lo->win, item_attr); 5557959Sache } 5566458Sache if (strlen(lo->name[lo->sel]) > lo->w - 2) { 5576458Sache strncpy(tmp, lo->name[lo->sel], lo->w - 2); 5586458Sache tmp[lo->w - 2] = 0; 5596458Sache waddstr(lo->win, tmp); 5606458Sache } else { 5616458Sache waddstr(lo->win, lo->name[lo->sel]); 5626458Sache } 5636458Sache 5646458Sache switch (key) { 5656458Sache case KEY_DOWN: 5666458Sache case ctrl('n'): 5676458Sache if (sel_y < lo->y + lo->h-1) { 5686458Sache if (lo->sel < lo->n-1) { 5696458Sache sel_y++; 5706458Sache lo->sel++; 5716458Sache } 5726458Sache } else { 5736458Sache if (lo->sel < lo->n-1) { 5746458Sache lo->sel++; 5756458Sache lo->scroll++; 5766458Sache DrawNames(lo); 5776458Sache wrefresh(lo->win); 5786458Sache } 5796458Sache } 5806458Sache break; 5816458Sache case KEY_UP: 5826458Sache case ctrl('p'): 5836458Sache if (sel_y > lo->y+2) { 5846458Sache if (lo->sel > 0) { 5856458Sache sel_y--; 5866458Sache lo->sel--; 5876458Sache } 5886458Sache } else { 5896458Sache if (lo->sel > 0) { 5906458Sache lo->sel--; 5916458Sache lo->scroll--; 5926458Sache DrawNames(lo); 5936458Sache wrefresh(lo->win); 5946458Sache } 5956458Sache } 5966458Sache break; 5976458Sache case KEY_HOME: 5986458Sache case ctrl('a'): 5996458Sache lo->sel = 0; 6006458Sache lo->scroll = 0; 6016458Sache sel_y = lo->y + 2; 6026458Sache DrawNames(lo); 6036458Sache wrefresh(lo->win); 6046458Sache break; 6056458Sache case KEY_END: 6066458Sache case ctrl('e'): 6076458Sache if (lo->n < lo->h - 3) { 6086458Sache lo->sel = lo->n-1; 6096458Sache lo->scroll = 0; 6106458Sache sel_y = lo->y + 2 + lo->sel - lo->scroll; 6116458Sache } else { 6126458Sache /* more than one page of list */ 6136458Sache lo->sel = lo->n-1; 6146458Sache lo->scroll = lo->n-1 - (lo->h-3); 6156458Sache sel_y = lo->y + 2 + lo->sel - lo->scroll; 6166458Sache DrawNames(lo); 6176458Sache wrefresh(lo->win); 6186458Sache } 6196458Sache break; 6206458Sache case KEY_NPAGE: 6216458Sache case ctrl('f'): 6226458Sache lo->sel += lo->h - 2; 6236458Sache if (lo->sel >= lo->n) lo->sel = lo->n - 1; 6246458Sache lo->scroll += lo->h - 2; 6256458Sache if (lo->scroll >= lo->n - 1) lo->scroll = lo->n - 1; 6266458Sache if (lo->scroll < 0) lo->scroll = 0; 6276458Sache sel_y = lo->y + 2 + lo->sel - lo->scroll; 6286458Sache DrawNames(lo); 6296458Sache wrefresh(lo->win); 6306458Sache break; 6316458Sache case KEY_PPAGE: 6326458Sache case ctrl('b'): 6336458Sache lo->sel -= lo->h - 2; 6346458Sache if (lo->sel < 0) lo->sel = 0; 6356458Sache lo->scroll -= lo->h - 2; 6366458Sache if (lo->scroll < 0) lo->scroll = 0; 6376458Sache sel_y = lo->y + 2 + lo->sel - lo->scroll; 6386458Sache DrawNames(lo); 6396458Sache wrefresh(lo->win); 6406458Sache break; 6417959Sache default: 6427959Sache quit = TRUE; 6437959Sache break; 6446458Sache } 6456458Sache /* Draw % indication */ 6468858Srgrimes sprintf(perc, "(%3d%%)", MIN(100, (int) 6476458Sache (100 * (lo->sel+lo->h - 2) / MAX(1, lo->n)))); 6486458Sache wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); 6496458Sache wattrset(lo->win, dialog_attr); 6508858Srgrimes waddstr(lo->win, perc); 6516458Sache 6526458Sache /* draw current item in inverse */ 6536458Sache wmove(lo->win, sel_y, sel_x); 6546458Sache wattrset(lo->win, item_selected_attr); 6556458Sache if (strlen(lo->name[lo->sel]) > lo->w - 2) { 6566458Sache /* when printing in inverse video show the last characters in the */ 6576458Sache /* name that will fit in the window */ 6588858Srgrimes strncpy(tmp, 6598858Srgrimes lo->name[lo->sel] + strlen(lo->name[lo->sel]) - (lo->w - 2), 6606458Sache lo->w - 2); 6616458Sache tmp[lo->w - 2] = 0; 6626458Sache waddstr(lo->win, tmp); 6636458Sache } else { 6646458Sache waddstr(lo->win, lo->name[lo->sel]); 6656458Sache } 6667959Sache if (!quit) key = wgetch(lo->win); 6676458Sache } 6688858Srgrimes 6696458Sache if (key == ESC) { 6706458Sache return(SEL_ESC); 6716458Sache } 6726458Sache if (key == '\t') { 6736458Sache return(SEL_TAB); 6746458Sache } 6756458Sache if ((key == KEY_BTAB) || (key == ctrl('b'))) { 6766458Sache return(SEL_BACKTAB); 6776458Sache } 6786458Sache if ((key == '\n') || (key == '\r')) { 6796458Sache strcpy(lo->elt, lo->name[lo->sel]); 6806458Sache return(SEL_CR); 6816458Sache } 6826458Sache return(key); 6836458Sache} /* SelectListObj() */ 6846458Sache 6856458Sachevoid 6866458SacheDelListObj(ListObj *lo) 6876458Sache/* 6886458Sache * Desc: Free the space occupied by the listobject 6896458Sache */ 6906458Sache{ 6916458Sache free(lo->title); 6927959Sache if (lo->seld != NULL) free(lo->seld); 6936458Sache free(lo); 6946458Sache 6957959Sache return; 6966458Sache} /* DelListObj() */ 6976458Sache 6987959Sachevoid 6997959SacheMarkCurrentListObj(ListObj *lo) 7008858Srgrimes/* 7018858Srgrimes * Desc: mark the current item for the selection list 7027959Sache */ 7037959Sache{ 7047959Sache lo->seld[lo->sel] = !(lo->seld[lo->sel]); 7057959Sache DrawNames(lo); 7066458Sache 7077959Sache return; 7087959Sache} /* MarkCurrentListObj() */ 7097959Sache 7107959Sachevoid 7117959SacheMarkAllListObj(ListObj *lo) 7127959Sache/* 7137959Sache * Desc: mark all items 7147959Sache */ 7157959Sache{ 7167959Sache int i; 7177959Sache 7187959Sache for (i=0; i<lo->n; i++) { 7197959Sache lo->seld[i] = TRUE; 7207959Sache } 7217959Sache DrawNames(lo); 7227959Sache 7237959Sache return; 7247959Sache} /* MarkAllListObj() */ 7257959Sache 7267959Sachevoid 7277959SacheUnMarkAllListObj(ListObj *lo) 7287959Sache/* 7297959Sache * Desc: unmark all items 7307959Sache */ 7317959Sache{ 7327959Sache int i; 7338858Srgrimes 7347959Sache for (i=0; i<lo->n; i++) { 7357959Sache lo->seld[i] = FALSE; 7367959Sache } 7377959Sache DrawNames(lo); 7387959Sache 7397959Sache return; 7407959Sache} /* UnMarkAllListObj() */ 7417959Sache 7427959Sache 7436458Sache/*********************************************************************** 7446458Sache * 7456458Sache * ButtonObj routines 7466458Sache * 7476458Sache ***********************************************************************/ 7486458Sache 7496458Sache 7506458Sachevoid 7516458SacheRefreshButtonObj(ButtonObj *bo) 7526458Sache/* 7536458Sache * Desc: redraw the button 7546458Sache */ 7556458Sache{ 7566458Sache draw_box(bo->win, bo->y, bo->x, 3, bo->w, dialog_attr, border_attr); 7576458Sache print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); 7586458Sache 7596458Sache return; 7606458Sache} /* RefreshButtonObj() */ 7616458Sache 7626458SacheButtonObj * 7636458SacheNewButtonObj(WINDOW *win, char *title, int *pushed, int y, int x) 7646458Sache/* 7656458Sache * Desc: Create a new button object 7666458Sache */ 7676458Sache{ 7686458Sache ButtonObj *bo; 7696458Sache 7706458Sache bo = (ButtonObj *) malloc( sizeof(ButtonObj) ); 7718858Srgrimes 7726458Sache bo->win = win; 7736458Sache bo->title = (char *) malloc( strlen(title) + 1); 7746458Sache strcpy(bo->title, title); 7756458Sache bo->x = x; 7766458Sache bo->y = y; 7776458Sache bo->w = strlen(title) + 6; 7786458Sache bo->h = 3; 7796458Sache bo->pushed = pushed; 7806458Sache 7816458Sache RefreshButtonObj(bo); 7826458Sache 7836458Sache return(bo); 7846458Sache} /* NewButtonObj() */ 7856458Sache 7866458Sacheint 7876458SacheSelectButtonObj(ButtonObj *bo) 7886458Sache/* 7896458Sache * Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC 7906458Sache */ 7916458Sache{ 7926458Sache int key; 7936458Sache 7946458Sache print_button(bo->win, bo->title, bo->y+1, bo->x+2, TRUE); 7956458Sache wmove(bo->win, bo->y+1, bo->x+(bo->w/2)-1); 7966458Sache key = wgetch(bo->win); 7978858Srgrimes print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); 7986458Sache switch(key) { 7996458Sache case '\t': 8006458Sache return(SEL_TAB); 8016458Sache break; 8026458Sache case KEY_BTAB: 8036458Sache case ctrl('b'): 8046458Sache return(SEL_BACKTAB); 8056458Sache case '\n': 80622879Sache case '\r': 8076458Sache *(bo->pushed) = TRUE; 8086458Sache return(SEL_BUTTON); 8096458Sache break; 8106458Sache case ESC: 8116458Sache return(SEL_ESC); 8126458Sache break; 8136458Sache default: 8146458Sache return(key); 8156458Sache break; 8166458Sache } 8176458Sache} /* SelectButtonObj() */ 8186458Sache 8196458Sachevoid 8206458SacheDelButtonObj(ButtonObj *bo) 8216458Sache/* 8226458Sache * Desc: Free the space occupied by <bo> 8236458Sache */ 8246458Sache{ 8256458Sache free(bo->title); 8266458Sache free(bo); 8276458Sache 8286458Sache return; 8296458Sache} /* DelButtonObj() */ 830