file selector, helpline, helpfile and more, with my fixes

Submitted by: wmbfmk@urc.tue.nl
This commit is contained in:
Andrey A. Chernov 1995-02-15 19:44:08 +00:00
parent 7f8573b091
commit 895aadbcfb
22 changed files with 2313 additions and 22 deletions

View file

@ -0,0 +1,9 @@
- Added two variables to call to dialog_menu() to save the position
in the menu when choosing a menu-option.
- Added dialog_fselect(), implements a fileselector dialog
- Added ui-interface objects: Stringobject, Listobject and Buttonobject.
The fileselector dialog was built using these objects.
- changed dialog_menu to use PGUP and PGDN
- Added dialog_mesgbox, which display text given in a char buffer.
-

View file

@ -1,13 +1,15 @@
# Makefile for libdialog
# $Id: Makefile,v 1.5 1994/10/28 03:08:14 ache Exp $
# $Id: Makefile,v 1.6 1994/10/28 05:36:38 jkh Exp $
LIB= dialog
SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \
lineedit.c radiolist.c textbox.c yesno.c prgbox.c raw_popen.c
lineedit.c radiolist.c textbox.c yesno.c prgbox.c raw_popen.c \
fselect.c ui_objects.c dir.c notify.c help.c
CFLAGS+= -I${.CURDIR} -Wall -Wstrict-prototypes -DLOCALE
LDADD+= -lncurses -lmytinfo
DPADD+= ${LIBNCURSES} ${LIBMYTINFO}
beforeinstall:
-cd ${.CURDIR}; cmp -s dialog.h ${DESTDIR}/usr/include/dialog.h || \

36
gnu/lib/libdialog/TODO Normal file
View file

@ -0,0 +1,36 @@
- cut off names in the listbox that are to long
done 27Jan95
The current behaviour may not be desirable. When browsing through
long names these, when highlighted, will be shown with the first
characters cut off, when not highlighted the last characters will
be cut off.
- look at behaviour of TAB key when browsing through directories.
done 28Jan95
- make sure the full name of the directory is written to the
"Directory:"-box
done 28Jan95
- mark current selections in listbox when initializing the listobject
Idontknow
- test and use Notify() when checking for error conditions
ok
- test overall
- adapt color of buttons when changing focus to the button.
done 28Jan95
- add shade to dialog_fselect()-window
done 29Jan95
- add (nn%) indication to lists.
done 30Jan95
- add use_helpfile()
done 13Feb95
- add use_helpline()
NOTE: apparently there is a bug (or a strange interaction between pkg_manage
and dialog_textbox) in dialog_textbox. When I use this routine to display
the helpfile in display_helpfile() the program gets mysterious segmentation
faults and bus errors.
I now use dialog_mesgbox, after I have read the file into a buffer.

View file

@ -147,6 +147,8 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in
waddstr(dialog, "(+)");
}
display_helpline(dialog, height-1, width);
x = width/2-11;
y = height-2;
print_button(dialog, "Cancel", y, x+14, FALSE);
@ -349,6 +351,10 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in
return button;
case ESC:
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
}

View file

@ -36,6 +36,14 @@
#define VERSION "0.4"
#define MAX_LEN 2048
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
/*
* Attribute names
*/
@ -88,7 +96,7 @@ int dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int wi
int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell);
int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause);
int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width);
int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result);
int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result, int *ch, int *sc);
int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result);
int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result);
int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result);
@ -97,3 +105,10 @@ void dialog_clear(void);
void dialog_update(void);
void init_dialog(void);
void end_dialog(void);
/* Additions to libdialog */
char *dialog_fselect(char *dir, char *fmask);
void dialog_notify(char *msg);
int dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width);
void use_helpfile(char *helpfile);
void use_helpline(char *helpline);

View file

@ -39,8 +39,17 @@
#define ESC 27
#define TAB 9
#define BUF_SIZE (10*1024)
#ifndef MIN
#define MIN(x,y) (x < y ? x : y)
#endif
#ifndef MAX
#define MAX(x,y) (x > y ? x : y)
#endif
#ifndef ctrl
#define ctrl(a) ((a) - 'a' + 1)
#endif
#ifndef HAVE_NCURSES
#ifndef ACS_ULCORNER
@ -159,3 +168,5 @@ void print_autowrap(WINDOW *win, unsigned char *prompt, int height, int width, i
void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected);
FILE *raw_popen(const char *program, char * const *argv, const char *type);
int raw_pclose(FILE *iop);
void display_helpfile(void);
void display_helpline(WINDOW *w, int y, int width);

549
gnu/lib/libdialog/dir.c Normal file
View file

@ -0,0 +1,549 @@
/****************************************************************************
*
* Program: dir.c
* Author: Marc van Kempen
* desc: Directory routines, sorting and reading
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#if !defined sgi
#include <sys/dir.h>
#endif
#if defined __sun__
#include <sys/dirent.h>
#endif
#if defined sgi
#include <dirent.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fnmatch.h>
#include <sys/param.h>
#include "dir.h"
/****************************************************************************
*
* local prototypes
*
****************************************************************************/
void toggle_dotfiles(void);
int show_dotfiles(void);
int dir_alphasort(const void *d1, const void *d2);
int dir_sizesort(const void *d1, const void *d2);
int dir_datesort(const void *d1, const void *d2);
int dir_extsort(const void *d1, const void *d2);
/****************************************************************************
*
* global variables
*
****************************************************************************/
/* This is user-selectable, I've set them fixed for now however */
void *_sort_func = dir_alphasort;
static int _showdotfiles = TRUE;
/****************************************************************************
*
* Functions
*
****************************************************************************/
int
dir_select_nd(
#if defined __linux__
const struct dirent *d
#else
struct dirent *d
#endif
)
/*
* desc: allways include a directory entry <d>, except
* for the current directory and other dot-files
* keep '..' however.
* pre: <d> points to a dirent
* post: returns TRUE if d->d_name != "." else FALSE
*/
{
if (strcmp(d->d_name, ".")==0 ||
(d->d_name[0] == '.' && strlen(d->d_name) > 1 && d->d_name[1] != '.')) {
return(FALSE);
} else {
return(TRUE);
}
}/* dir_select_nd() */
int
dir_select(
#ifdef __linux__
const struct dirent *d
#else
struct dirent *d
#endif
)
/*
* desc: allways include a directory entry <d>, except
* for the current directory
* pre: <d> points to a dirent
* post: returns TRUE if d->d_name != "." else FALSE
*/
{
if (strcmp(d->d_name, ".")==0) { /* don't include the current directory */
return(FALSE);
} else {
return(TRUE);
}
} /* dir_select() */
int
dir_select_root_nd(
#ifdef __linux__
const struct dirent *d
#else
struct dirent *d
#endif
)
/*
* desc: allways include a directory entry <d>, except
* for the current directory and the parent directory.
* Also skip any other dot-files.
* pre: <d> points to a dirent
* post: returns TRUE if d->d_name[0] != "." else FALSE
*/
{
if (d->d_name[0] == '.') { /* don't include the current directory */
return(FALSE); /* nor the parent directory */
} else {
return(TRUE);
}
} /* dir_select_root_nd() */
int
dir_select_root(
#ifdef __linux__
const struct dirent *d
#else
struct dirent *d
#endif
)
/*
* desc: allways include a directory entry <d>, except
* for the current directory and the parent directory
* pre: <d> points to a dirent
* post: returns TRUE if d->d_name[0] != "." else FALSE
*/
{
if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
return(FALSE);
} else {
return(TRUE);
}
}/* dir_select_root() */
#ifdef NO_ALPHA_SORT
int
alphasort(const void *d1, const void *d2)
/*
* desc: a replacement for what should be in the library
*/
{
return(strcmp(((struct dirent *) d1)->d_name,
((struct dirent *) d2)->d_name));
} /* alphasort() */
#endif
int
dir_alphasort(const void *d1, const void *d2)
/*
* desc: compare d1 and d2, but put directories always first
* put '..' always on top
*
*/
{
DirList *f1 = ((DirList *) d1),
*f2 = ((DirList *) d2);
struct stat *s1 = &(f1->filestatus);
struct stat *s2 = &(f2->filestatus);
/* check for '..' */
if (strcmp(((DirList *) d1)->filename, "..") == 0) {
return(-1);
}
if (strcmp(((DirList *) d2)->filename, "..") == 0) {
return(1);
}
/* put directories first */
if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
return(strcmp(f1->filename, f2->filename));
};
if (s1->st_mode & S_IFDIR) {
return(-1);
}
if (s2->st_mode & S_IFDIR) {
return(1);
}
return(strcmp(f1->filename, f2->filename));
} /* dir_alphasort() */
int
dir_sizesort(const void *d1, const void *d2)
/*
* desc: compare d1 and d2, but put directories always first
*
*/
{
DirList *f1 = ((DirList *) d1),
*f2 = ((DirList *) d2);
struct stat *s1 = &(f1->filestatus);
struct stat *s2 = &(f2->filestatus);
/* check for '..' */
if (strcmp(((DirList *) d1)->filename, "..") == 0) {
return(-1);
}
if (strcmp(((DirList *) d2)->filename, "..") == 0) {
return(1);
}
/* put directories first */
if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
return(s1->st_size < s2->st_size ?
-1
:
s1->st_size >= s2->st_size);
};
if (s1->st_mode & S_IFDIR) {
return(-1);
}
if (s2->st_mode & S_IFDIR) {
return(1);
}
return(s1->st_size < s2->st_size ?
-1
:
s1->st_size >= s2->st_size);
} /* dir_sizesort() */
int
dir_datesort(const void *d1, const void *d2)
/*
* desc: compare d1 and d2 on date, but put directories always first
*/
{
DirList *f1 = ((DirList *) d1),
*f2 = ((DirList *) d2);
struct stat *s1 = &(f1->filestatus);
struct stat *s2 = &(f2->filestatus);
/* check for '..' */
if (strcmp(((DirList *) d1)->filename, "..") == 0) {
return(-1);
}
if (strcmp(((DirList *) d2)->filename, "..") == 0) {
return(1);
}
/* put directories first */
if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
return(s1->st_mtime < s2->st_mtime ?
-1
:
s1->st_mtime >= s2->st_mtime);
};
if (s1->st_mode & S_IFDIR) {
return(-1);
}
if (s2->st_mode & S_IFDIR) {
return(1);
}
return(s1->st_mtime < s2->st_mtime ?
-1
:
s1->st_mtime >= s2->st_mtime);
} /* dir_datesort() */
int
null_strcmp(char *s1, char *s2)
/*
* desc: compare strings allowing NULL pointers
*/
{
if ((s1 == NULL) && (s2 == NULL)) {
return(0);
}
if (s1 == NULL) {
return(-1);
}
if (s2 == NULL) {
return(1);
}
return(strcmp(s1, s2));
} /* null_strcmp() */
int
dir_extsort(const void *d1, const void *d2)
/*
* desc: compare d1 and d2 on extension, but put directories always first
* extension = "the characters after the last dot in the filename"
* pre: d1 and d2 are pointers to DirList type records
* post: see code
*/
{
DirList *f1 = ((DirList *) d1),
*f2 = ((DirList *) d2);
struct stat *s1 = &(f1->filestatus);
struct stat *s2 = &(f2->filestatus);
char *ext1, *ext2;
int extf, ret;
/* check for '..' */
if (strcmp(((DirList *) d1)->filename, "..") == 0) {
return(-1);
}
if (strcmp(((DirList *) d2)->filename, "..") == 0) {
return(1);
}
/* find the first extension */
ext1 = f1->filename + strlen(f1->filename);
extf = FALSE;
while (!extf && (ext1 > f1->filename)) {
extf = (*--ext1 == '.');
}
if (!extf) {
ext1 = NULL;
} else {
ext1++;
}
/* ext1 == NULL if there's no "extension" else ext1 points */
/* to the first character of the extension string */
/* find the second extension */
ext2 = f2->filename + strlen(f2->filename);
extf = FALSE;
while (!extf && (ext2 > f2->filename)) {
extf = (*--ext2 == '.');
}
if (!extf) {
ext2 = NULL;
} else {
ext2++;
}
/* idem as for ext1 */
if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
ret = null_strcmp(ext1, ext2);
if (ret == 0) {
return(strcmp(f1->filename, f2->filename));
} else {
return(ret);
}
};
if (s1->st_mode & S_IFDIR) {
return(-1);
}
if (s2->st_mode & S_IFDIR) {
return(1);
}
ret = null_strcmp(ext1, ext2);
if (ret == 0) {
return(strcmp(f1->filename, f2->filename));
} else {
return(ret);
}
} /* dir_extsort() */
void
get_dir(char *dirname, char *fmask, DirList **dir, int *n)
/*
* desc: get the files in the current directory
* pre: <dir> == NULL
* post: <dir> contains <n> dir-entries
*/
{
char cwd[MAXPATHLEN];
char buf[256];
struct dirent **dire;
struct stat status;
int i, j, nb;
long d;
getcwd(cwd, MAXPATHLEN);
if (strcmp(cwd, "/") == 0) { /* we are in the root directory */
if (show_dotfiles()) {
*n = scandir(dirname, &dire, dir_select_root, alphasort);
} else {
*n = scandir(dirname, &dire, dir_select_root_nd, alphasort);
}
} else {
if (show_dotfiles()) {
*n = scandir(dirname, &dire, dir_select, alphasort);
} else {
*n = scandir(dirname, &dire, dir_select_nd, alphasort);
}
}
/* There is the possibility that we have entered a directory */
/* which we are not allowed to read, scandir thus returning */
/* -1 for *n. */
/* Actually I should also check for lack of memory, but I'll */
/* let my application happily crash if this is the case */
/* Solution: */
/* manually insert the parent directory as the only */
/* directory entry, and return. */
if (*n == -1) {
*n = 1;
*dir = (DirList *) malloc(sizeof(DirList));
strcpy((*dir)[0].filename, "..");
lstat("..", &status);
(*dir)[0].filestatus = status;
(*dir)[0].link = FALSE;
return;
}
*dir = (DirList *) malloc( *n * sizeof(DirList) );
d = 0;
i = 0;
j = 0;
while (j<*n) {
lstat(dire[j]->d_name, &status);
/* check if this file is to be included */
/* always include directories, the rest is subject to fmask */
if (S_ISDIR(status.st_mode)
|| fnmatch(fmask, dire[j]->d_name, FNM_NOESCAPE) != FNM_NOMATCH) {
strcpy((*dir)[i].filename, dire[j]->d_name);
(*dir)[i].filestatus = status;
if ((S_IFMT & status.st_mode) == S_IFLNK) { /* handle links */
(*dir)[i].link = TRUE;
stat(dire[j]->d_name, &status);
nb = readlink(dire[j]->d_name, buf, 256);
if (nb == -1) {
printf("get_dir(): Error reading link: %s\n", dire[j]->d_name);
exit(-1);
} else {
(*dir)[i].linkname = malloc(sizeof(char) * nb + 1);
strncpy((*dir)[i].linkname, buf, nb);
(*dir)[i].linkname[nb] = 0;
}
(*dir)[i].filestatus = status;
} else {
(*dir)[i].link = FALSE;
(*dir)[i].linkname = NULL;
}
i++;
} else {
/* skip this entry */
}
j++;
}
*n = i;
/* sort the directory with the directory names on top */
qsort((*dir), *n, sizeof(DirList), _sort_func);
/* Free the allocated memory */
for (i=0; i<*n; i++) {
free(dire[i]);
}
free(dire);
return;
}/* get_dir() */
void
FreeDir(DirList *d, int n)
/*
* desc: free the dirlist d
* pre: d != NULL
* post: memory allocated to d has been released
*/
{
int i;
if (d) {
for (i=0; i<n; i++) {
if (d[i].linkname) {
free(d[i].linkname);
}
}
free(d);
} else {
printf("dir.c:FreeDir(): d == NULL\n");
exit(-1);
}
return;
} /* FreeDir() */
void
toggle_dotfiles(void)
/*
* desc: toggle visibility of dot-files
*/
{
_showdotfiles = !_showdotfiles;
return;
} /* toggle_dotfiles() */
int
show_dotfiles(void)
/*
* desc: return the value of _showdotfiles
*/
{
return(_showdotfiles);
} /* show_dotfiles() */
void
set_dotfiles(int b)
/*
* desc: set the value of _showdotfiles
*/
{
_showdotfiles = b;
return;
} /* set_dotfiles() */

36
gnu/lib/libdialog/dir.h Normal file
View file

@ -0,0 +1,36 @@
/*
* include file for dir.c
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dirent.h>
typedef struct DirList { /* structure to hold the directory entries */
char filename[MAXNAMLEN]; /* together with the stat-info per file */
struct stat filestatus; /* filename, or the name to which it points */
int link; /* is it a link ? */
char *linkname; /* the name of the file the link points to */
} DirList;
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
void get_dir(char *dirname, char *fmask, DirList **dir, int *n);

242
gnu/lib/libdialog/fselect.c Normal file
View file

@ -0,0 +1,242 @@
/*
* program: fselect.c
* author: Marc van Kempen (wmbfmk@urc.tue.nl)
* Desc: File selection routine
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <dialog.h>
#include "ui_objects.h"
#include "dir.h"
#include "dialog.priv.h"
void
get_directories(DirList *d, int n, char ***names, int *nd)
/*
* Desc: return the directorienames in <dir> as an array in
* <names>, the # of entries in <nd>, memory allocated
* to *names should be freed when done with it.
*/
{
int i;
/* count the directories, which are in front */
*nd = 0;
while ((*nd < n) && (S_ISDIR(d[*nd].filestatus.st_mode))) (*nd)++;
*names = (char **) malloc( *nd * sizeof(char *) );
for (i=0; i<*nd; i++) {
(*names)[i] = (char *) malloc( strlen(d[i].filename) + 1);
strcpy((*names)[i], d[i].filename);
}
return;
} /* get_directories() */
void
get_filenames(DirList *d, int n, char ***names, int *nf)
/*
* Desc: return the filenames in <dir> as an arry in
* <names>, the # of entries in <nf>, memory allocated
* to *names should be freed when done.
*/
{
int nd, i;
/* the # of regular files is the total # of files - # of directories */
/* count the # of directories */
nd = 0;
while ((nd < n) && (S_ISDIR(d[nd].filestatus.st_mode))) nd++;
*names = (char **) malloc( (n-nd) * sizeof(char *) );
*nf = n - nd;
for (i=0; i<*nf; i++) {
(*names)[i] = (char *) malloc( strlen(d[i+nd].filename) + 1);
strcpy((*names)[i], d[i+nd].filename);
}
return;
} /* get_filenames() */
void
FreeNames(char **names, int n)
/*
* Desc: free the space occupied by names
*/
{
int i;
/* free the space occupied by names */
for (i=0; i<n; i++) {
free(names[i]);
}
free(names);
return;
} /* FreeNames() */
char *
dialog_fselect(char *dir, char *fmask)
/*
* Desc: choose a file from the directory <dir>, which
* initially display files with the mask <filemask>
* pre: <dir> is the initial directory
* only files corresponding to the mask <fmask> are displayed
* post: returns NULL if no file was selected
* else returns pointer to filename, space is allocated, should
* be freed after use.
*/
{
DirList *d = NULL;
char msg[512];
char **names, *ret_name;
WINDOW *fs_win;
int n, nd, nf, ret;
StringObj *fm_obj, *dir_obj, *sel_obj;
char o_fm[255], o_dir[MAXPATHLEN], o_sel[MAXPATHLEN];
char old_fmask[255], old_dir[MAXPATHLEN];
ListObj *dirs_obj, *files_obj;
struct ComposeObj *obj = NULL, *o;
int quit, cancel;
ButtonObj *okbut_obj, *canbut_obj;
int ok_button, cancel_button;
if (chdir(dir)) {
sprintf(msg, "Could not move into specified directory: %s", dir);
dialog_notify(msg);
return(NULL);
}
getcwd(o_dir, MAXPATHLEN);
/* setup the fileselect-window and initialize its components */
fs_win = newwin(LINES-2, COLS-20, 1, 10);
if (fs_win == NULL) {
endwin();
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n",
LINES-2, COLS-20, 2, 10);
exit(1);
}
draw_box(fs_win, 0, 0, LINES-2, COLS-20, dialog_attr, border_attr);
wattrset(fs_win, dialog_attr);
mvwaddstr(fs_win, 0, (COLS-20)/2 - 7, " File Select ");
draw_shadow(stdscr, 1, 10, LINES-2, COLS-20);
/* Filemask entry */
strcpy(o_fm, fmask);
fm_obj = NewStringObj(fs_win, "Filemask:", o_fm, 1, 2, 19, 255);
AddObj(&obj, STRINGOBJ, (void *) fm_obj);
/* Directory entry */
dir_obj = NewStringObj(fs_win, "Directory:", o_dir, 1, 22, COLS-44, 255);
AddObj(&obj, STRINGOBJ, (void *) dir_obj);
/* Directory list */
get_dir(".", fmask, &d, &n); /* read the entire directory */
get_directories(d, n, &names, &nd); /* extract the dir-entries */
dirs_obj = NewListObj(fs_win, "Directories:", names, o_dir, 5, 2,
LINES-16, (COLS-20)/2-2, nd);
AddObj(&obj, LISTOBJ, (void *) dirs_obj);
/* Filenames list */
get_filenames(d, n, &names, &nf); /* extract the filenames */
files_obj = NewListObj(fs_win, "Files:", names, o_sel, 5, (COLS-20)/2+1,
LINES-16, (COLS-20)/2-3, nf);
AddObj(&obj, LISTOBJ, (void *) files_obj);
/* Selection entry */
o_sel[0] = '\0';
sel_obj = NewStringObj(fs_win, "Selection:", o_sel, LINES-10, 2, COLS-24, 255);
AddObj(&obj, STRINGOBJ, (void *) sel_obj);
/* Ok button */
ok_button = FALSE;
okbut_obj = NewButtonObj(fs_win, "Ok", &ok_button, LINES-6, 20);
AddObj(&obj, BUTTONOBJ, (void *) okbut_obj);
/* Cancel button */
cancel_button = FALSE;
canbut_obj = NewButtonObj(fs_win, "Cancel", &cancel_button, LINES-6, 30);
AddObj(&obj, BUTTONOBJ, (void *) canbut_obj);
/* Make sure all objects on the window are drawn */
wrefresh(fs_win);
keypad(fs_win, TRUE);
/* Start the reading */
o = obj;
strcpy(old_fmask, o_fm);
strcpy(old_dir, o_dir);
quit = FALSE;
cancel = FALSE;
while (!quit) {
ret = PollObj(&o);
switch(ret) {
case SEL_CR:
if (strcmp(old_fmask, o_fm) || strcmp(old_dir, o_dir)) {
/* reread directory and update the listobjects */
if (strcmp(old_dir, o_dir)) { /* dir entry was changed */
if (chdir(o_dir)) {
dialog_notify("Could not change into directory");
} else {
getcwd(o_dir, MAXPATHLEN);
strcpy(old_dir, o_dir);
RefreshStringObj(dir_obj);
}
} else { /* fmask entry was changed */
strcpy(old_fmask, o_fm);
}
get_dir(".", o_fm, &d, &n);
get_directories(d, n, &names, &nd);
UpdateListObj(dirs_obj, names, nd);
get_filenames(d, n, &names, &nf);
UpdateListObj(files_obj, names, nf);
if (((o->prev)->obj == (void *) dirs_obj)) {
o=o->prev;
}
}
break;
case SEL_BUTTON:
/* check which button was pressed */
if (ok_button) {
quit = TRUE;
}
if (cancel_button) {
quit = TRUE;
cancel = TRUE;
}
break;
case SEL_ESC:
quit = TRUE;
cancel = TRUE;
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
}
DelObj(obj);
if (cancel || (strlen(o_sel) == 0)) {
return(NULL);
} else {
ret_name = (char *) malloc( strlen(o_sel) + 1 );
strcpy(ret_name, o_sel);
return(ret_name);
}
} /* dialog_fselect() */

155
gnu/lib/libdialog/help.c Normal file
View file

@ -0,0 +1,155 @@
/***************************************************************
*
* Program: help.c
* Author: Marc van Kempen
* Desc: get help
*
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
***************************************************************/
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <dialog.h>
static char _helpfilebuf[MAXPATHLEN];
static char _helplinebuf[77]; /* limit the helpline to 76 characters */
static char *_helpfile = NULL;
static char *_helpline = NULL;
/******************************************************************
*
* helpfile routines
*
******************************************************************/
void
use_helpfile(char *hfile)
/*
* desc: set the helpfile to be opened on pressing F1 to <helpfile>
*/
{
if (hfile != NULL) {
_helpfile = _helpfilebuf;
strcpy(_helpfile, hfile);
} else {
_helpfile = NULL;
}
return;
} /* use_helpfile() */
void
display_helpfile(void)
/*
* desc: display the current helpfile in a window
*/
{
WINDOW *w;
FILE *f;
struct stat sb;
char msg[80], *buf;
static int in_help = FALSE;
if (in_help) return; /* dont call help when you're in help */
if (_helpfile != NULL) {
w = dupwin(curscr);
if ((f = fopen(_helpfile, "r")) == NULL) {
sprintf(msg, "Can't open helpfile : %s\n", _helpfile);
dialog_notify(msg);
return;
}
if (fstat(fileno(f), &sb)) {
sprintf(msg, "Can't stat helpfile : %s\n", _helpfile);
dialog_notify(msg);
return;
}
if ((buf = (char *) malloc( sb.st_size )) == NULL) {
sprintf(msg, "Could not malloc space for helpfile : %s\n", _helpfile);
dialog_notify(msg);
return;
}
if (fread(buf, 1, sb.st_size, f) != sb.st_size) {
sprintf(msg, "Could not read entire help file : %s", _helpfile);
dialog_notify(msg);
return;
}
buf[sb.st_size] = 0;
in_help = TRUE;
dialog_mesgbox("Online help", buf, LINES-4, COLS-4);
in_help = FALSE;
wrefresh(w);
delwin(w);
free(buf);
} else {
/* do nothing */
}
return;
} /* display_helpfile() */
/******************************************************************
*
* helpline routines
*
******************************************************************/
void
use_helpline(char *hline)
/*
* desc: set the helpline to printed in dialogs
*/
{
if (hline) {
_helpline = _helplinebuf;
if (strlen(hline) > 76) {
/* only display the first 76 characters in the helpline */
strncpy(_helpline, hline, 76);
_helpline[76] = 0;
} else {
strcpy(_helpline, hline);
}
} else {
_helpline = NULL;
}
return;
} /* use_helpline() */
void
display_helpline(WINDOW *w, int y, int width)
/*
* desc: display the helpline at the given coordinates <y, x> in the window <w>
*/
{
if (_helpline != NULL) {
if (strlen(_helpline) > width - 6) {
_helpline[width - 6] = 0;
}
wmove(w, y, (int) (width - strlen(_helpline)- 4) / 2);
wattrset(w, title_attr);
waddstr(w, "[ ");
waddstr(w, _helpline);
waddstr(w, " ]");
} else {
/* do nothing */
}
return;
}

View file

@ -92,6 +92,8 @@ int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int
box_x = (width - box_width)/2;
draw_box(dialog, y+1, box_x-1, 3, box_width+2, border_attr, dialog_attr);
display_helpline(dialog, height-1, width);
x = width/2-11;
y = height-2;
print_button(dialog, "Cancel", y, x+14, FALSE);
@ -175,6 +177,10 @@ int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int
return (button == -1 ? 0 : button);
case ESC:
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
}

View file

@ -375,6 +375,7 @@ void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chty
void draw_shadow(WINDOW *win, int y, int x, int height, int width)
{
int i,sx,sy;
WINDOW *newscr=win;
if (has_colors()) { /* Whether terminal supports color? */
getbegyx(win,sy,sx);

View file

@ -45,8 +45,10 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
memset(instr, 0, sizeof(instr));
strcpy(instr, result);
i = strlen(instr);
input_x = i % box_width;
scroll = i - input_x;
/* input_x = i % box_width;*/
input_x = (i > box_width) ? box_width - 1 : i;
/* scroll = i - input_x;*/
scroll = (i > box_width) ? i - box_width + 1: 0;
}
wmove(dialog, box_y, box_x);
wattrset(dialog, attr);
@ -65,6 +67,12 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
wrefresh(dialog);
key = wgetch(dialog);
switch (key) {
case ctrl('q'):
goto ret;
break;
case KEY_F(1):
display_helpfile();
break;
case TAB:
case KEY_BTAB:
case KEY_UP:

View file

@ -21,23 +21,27 @@
#include <dialog.h>
#include "dialog.priv.h"
#include <ncurses.h>
static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected);
static int menu_width, tag_x, item_x;
/*
* Display a menu for choosing among a number of options
*/
int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result)
int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result, int *ch, int *sc)
{
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
l, k, scroll = 0, max_choice;
l, k, scroll = 0, max_choice, redraw_menu = FALSE;
WINDOW *dialog, *menu;
if (ch) /* restore menu item info */
choice = *ch;
if (sc)
scroll = *sc;
max_choice = MIN(menu_height, item_no);
tag_x = 0;
@ -137,10 +141,13 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid
waddstr(dialog,"(+)");
}
display_helpline(dialog, height-1, width);
x = width/2-11;
y = height-2;
print_button(dialog, "Cancel", y, x+14, FALSE);
print_button(dialog, " OK ", y, x, TRUE);
wrefresh(dialog);
while (key != ESC) {
@ -273,20 +280,54 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid
continue; /* wait for another key press */
}
/* save info about menu item position */
if (ch)
*ch = choice;
if (sc)
*sc = scroll;
switch (key) {
case 'O':
case 'o':
case KEY_PPAGE:
if (scroll > height-4) { /* can we go up? */
scroll -= (height-4);
} else {
scroll = 0;
}
redraw_menu = TRUE;
break;
case KEY_NPAGE:
if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */
scroll = item_no - menu_height;
if (scroll < 0) scroll = 0;
} else {
scroll += menu_height;
}
redraw_menu = TRUE;
break;
case KEY_HOME:
scroll = 0;
choice = 0;
redraw_menu = TRUE;
break;
case KEY_END:
scroll = item_no - menu_height;
if (scroll < 0) scroll = 0;
choice = max_choice - 1;
redraw_menu = TRUE;
break;
case 'O':
case 'o':
delwin(dialog);
strcpy(result, items[(scroll+choice)*2]);
return 0;
case 'C':
case 'c':
case 'C':
case 'c':
delwin(dialog);
return 1;
case KEY_BTAB:
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
case KEY_BTAB:
case TAB:
case KEY_LEFT:
case KEY_RIGHT:
if (!button) {
button = 1; /* Indicates "Cancel" button is selected */
print_button(dialog, " OK ", y, x, FALSE);
@ -299,15 +340,28 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid
}
wrefresh(dialog);
break;
case ' ':
case '\r':
case '\n':
case ' ':
case '\r':
case '\n':
delwin(dialog);
if (!button)
strcpy(result, items[(scroll+choice)*2]);
return button;
case ESC:
case ESC:
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
if (redraw_menu) {
for (i = 0; i < max_choice; i++) {
print_item(menu, items[(scroll+i)*2],
items[(scroll+i)*2 + 1], i, i == choice);
}
wnoutrefresh(menu);
wrefresh(dialog);
redraw_menu = FALSE;
}
}

View file

@ -23,6 +23,12 @@
#include "dialog.priv.h"
/* local prototypes */
static int getnlines(unsigned char *buf);
static void print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll);
static void print_perc(WINDOW *win, int y, int x, float p);
/*
* Display a message box. Program will pause and display an "OK" button
* if the parameter 'pause' is non-zero.
@ -86,6 +92,7 @@ int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int w
wmove(dialog, height-2, 1);
for (i = 0; i < width-2; i++)
waddch(dialog, ' ');
display_helpline(dialog, height-1, width);
print_button(dialog, " OK ", height-2, width/2-4, TRUE);
wrefresh(dialog);
while (key != ESC && key != '\n' && key != ' ' && key != '\r')
@ -102,3 +109,231 @@ int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int w
return (key == ESC ? -1 : 0);
}
/* End of dialog_msgbox() */
int
dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width)
/*
* Desc: basically the same as dialog_msgbox, but ... can use PGUP, PGDN and
* arrowkeys to move around the text and pause is always enabled
*/
{
int i, j, x, y, key=0;
int theight, startline, hscroll, max_lines;
WINDOW *dialog;
if (height < 0)
height = strheight(prompt)+2+2*(!!pause);
if (width < 0) {
i = strwidth(prompt);
j = strwidth(title);
width = MAX(i,j)+4;
}
if (width > COLS)
width = COLS;
if (height > LINES)
height = LINES;
/* center dialog box on screen */
x = (COLS - width)/2;
y = (LINES - height)/2;
#ifdef HAVE_NCURSES
if (use_shadow)
draw_shadow(stdscr, y, x, height, width);
#endif
dialog = newwin(height, width, y, x);
if (dialog == NULL) {
endwin();
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
exit(1);
}
keypad(dialog, TRUE);
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
if (title != NULL) {
wattrset(dialog, title_attr);
wmove(dialog, 0, (width - strlen(title))/2 - 1);
waddch(dialog, ' ');
waddstr(dialog, title);
waddch(dialog, ' ');
}
wattrset(dialog, dialog_attr);
wmove(dialog, height-3, 0);
waddch(dialog, ACS_LTEE);
for (i = 0; i < width-2; i++)
waddch(dialog, ACS_HLINE);
wattrset(dialog, dialog_attr);
waddch(dialog, ACS_RTEE);
wmove(dialog, height-2, 1);
for (i = 0; i < width-2; i++)
waddch(dialog, ' ');
display_helpline(dialog, height-1, width);
print_button(dialog, " EXIT ", height-2, width/2-4, TRUE);
wattrset(dialog, dialog_attr);
theight = height - 4;
startline = 0;
hscroll = 0;
max_lines = getnlines(prompt);
print_page(dialog, theight, width, prompt, startline, hscroll);
print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines);
wmove(dialog, height-2, width/2-2);
wrefresh(dialog);
while ((key != ESC) && (key != '\n') && (key != '\r')) {
key = wgetch(dialog);
switch(key) {
case KEY_HOME:
startline=0;
hscroll=0;
break;
case KEY_END:
startline = max_lines - theight;
if (startline < 0) startline = 0;
break;
case KEY_UP:
if (startline > 0) startline--;
break;
case KEY_DOWN:
if (startline < max_lines - theight) startline++;
break;
case KEY_RIGHT:
hscroll++;
break;
case KEY_LEFT:
if (hscroll > 0) hscroll--;
break;
case KEY_PPAGE:
if (startline - height > 0) {
startline -= theight;
} else {
startline = 0;
}
break;
case KEY_NPAGE:
if (startline + theight < max_lines - theight) {
startline += theight;
} else {
startline = max_lines - theight;
if (startline < 0) startline = 0;
}
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
print_page(dialog, theight, width, prompt, startline, hscroll);
print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines);
wmove(dialog, height-2, width/2-2);
wrefresh(dialog);
}
delwin(dialog);
return (key == ESC ? -1 : 0);
} /* dialog_mesgbox() */
static void
print_perc(WINDOW *win, int y, int x, float p)
/*
* Desc: print p as a percentage at the coordinates (y,x)
*/
{
char ps[10];
if (p>1.0) p=1.0;
sprintf(ps, "(%3d%%)", (int) (p*100));
wmove(win, y, x);
waddstr(win, ps);
return;
} /* print_perc() */
static int
getnlines(unsigned char *buf)
/*
* Desc: count the # of lines in <buf>
*/
{
int i = 0;
while (*buf) {
if (*buf == '\n' || *buf == '\r') {
i++;
}
buf++;
}
return(i);
} /* getlines() */
unsigned char *
getline(unsigned char *buf, int n)
/*
* Desc: return a pointer to the n'th line in <buf> or NULL if its
* not there
*/
{
int i;
if (n<0) {
return(NULL);
}
i=0;
while (*buf && i<n) {
if (*buf == '\n' || *buf == '\r') {
i++;
}
buf++;
}
if (i<n) {
return(NULL);
} else {
return(buf);
}
} /* getline() */
static void
print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll)
/*
* Desc: Print a page of text in the current window, starting at line <startline>
* with a <horizontal> scroll of hscroll from buffer <buf>
*/
{
int i, j;
unsigned char *b;
b = getline(buf, startline);
for (i=0; i<height; i++) {
/* clear line */
wmove(win, 1+i, 1);
for (j=0; j<width-2; j++) waddnstr(win, " ", 1);
wmove(win, 1+i, 1);
j = 0;
/* scroll to the right */
while (*b && (*b != '\n') && (*b != '\r') && (j<hscroll)) {
b++;
j++;
}
/* print new line */
j = 0;
while (*b && (*b != '\n') && (*b != '\r') && (j<width-2)) {
waddnstr(win, b, 1);
if (*b != '\t') { /* check for tabs */
j++;
} else {
j = ((int) (j+1)/8 + 1) * 8 - 1;
}
b++;
}
while (*b && (*b != '\n') && (*b != '\r')) b++;
if (*b) b++; /* skip over '\n', if it exists */
}
} /* print_page() */

View file

@ -0,0 +1,64 @@
/*
* File: notify.c
* Author: Marc van Kempen
* Desc: display a notify box with a message
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
*/
#include <dialog.h>
#include <stdio.h>
void
dialog_notify(char *msg)
/*
* Desc: display an error message
*/
{
int li, co, mco;
char *p;
WINDOW *w;
/* determine # of lines in msg and max colwidth */
li = 0;
co = 0;
mco = 0;
p = msg;
while (*p) {
if (*p == '\n') {
li++;
if (co > mco) mco = co;
co = 0;
}
p++;
co++;
}
if (co < mco) co = mco;
li += 5;
if (li > LINES) li = LINES;
co += 4;
if (co < 20) co = 20;
if (co > COLS) co = COLS;
w = dupwin(curscr);
dialog_msgbox("Message", msg, li, co, TRUE);
wrefresh(w);
delwin(w);
return;
} /* dialog_notify() */

View file

@ -129,6 +129,7 @@ int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, i
wmove(dialog, height-2, 1);
for (i = 0; i < width-2; i++)
waddch(dialog, ' ');
display_helpline(dialog, height-1, width);
print_button(dialog, " OK ", height-2, width/2-4, TRUE);
wrefresh(dialog);
while (key != ESC && key != '\n' && key != ' ' && key != '\r')

View file

@ -155,6 +155,8 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in
waddstr(dialog, "(+)");
}
display_helpline(dialog, height-1, width);
x = width/2-11;
y = height-2;
print_button(dialog, "Cancel", y, x+14, FALSE);
@ -360,6 +362,10 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in
return button;
case ESC:
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
}

View file

@ -59,7 +59,7 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
/* Open input file for reading */
if ((fd = open(file, O_RDONLY)) == -1) {
endwin();
fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
fprintf(stderr, "\nCan't open input file <%s>in dialog_textbox().\n", file);
exit(-1);
}
/* Get file size. Actually, 'file_size' is the real file size - 1,
@ -139,6 +139,8 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
waddstr(dialog, title);
waddch(dialog, ' ');
}
display_helpline(dialog, height-1, width);
print_button(dialog, " EXIT ", height-2, width/2-4, TRUE);
wnoutrefresh(dialog);
getyx(dialog, cur_y, cur_x); /* Save cursor position */
@ -411,6 +413,9 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
break;
case ESC:
break;
case KEY_F(1):
display_helpfile();
break;
}
}

View file

@ -0,0 +1,735 @@
/*
* Program: objects.c
* Author: Marc van Kempen
* Desc: Implementation of UI-objects:
* - String input fields
* - List selection
* - Buttons
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
*/
#include <stdlib.h>
#include <sys/param.h>
#include <ncurses.h>
#include <dialog.h>
#include "dialog.priv.h"
#include "ui_objects.h"
#define ESC 27
/***********************************************************************
*
* Obj routines
*
***********************************************************************/
void
AddObj(ComposeObj **Obj, int objtype, void *obj)
/*
* Desc: Add the object <obj> to the list of objects <Obj>
*/
{
if (*Obj == NULL) {
/* Create the root object */
*Obj = (ComposeObj *) malloc( sizeof(ComposeObj) );
if (!Obj) {
printf("AddObj: Error malloc'ing ComposeObj\n");
exit(-1);
}
(*Obj)->objtype = objtype;
(*Obj)->obj = obj;
(*Obj)->next = NULL;
(*Obj)->prev = NULL;
} else {
ComposeObj *o = *Obj;
/* create the next object */
while (o->next) o = (ComposeObj *) o->next;
o->next = (struct ComposeObj *) malloc( sizeof(ComposeObj) );
if (!o->next) {
printf("AddObj: Error malloc'ing o->next\n");
exit(-1);
}
o->next->objtype = objtype;
o->next->obj = obj;
o->next->next = NULL;
o->next->prev = o;
}
return;
} /* AddObj() */
void
FreeObj(ComposeObj *Obj)
/*
* Desc: free the memory occupied by *Obj
*/
{
ComposeObj *o = Obj;
o = Obj;
while (o) {
o = Obj->next;
free(Obj);
Obj = o;
}
return;
} /* FreeObj() */
int
ReadObj(ComposeObj *Obj)
/*
* Desc: navigate through the different objects calling their
* respective navigation routines as necessary
* Pre: Obj != NULL
*/
{
ComposeObj *o;
ComposeObj *last; /* the last object in the list */
int ret; /* the return value from the selection routine */
/* find the last object in the list */
last = Obj;
while (last->next) last = last->next;
ret = 0;
o = Obj;
while ((ret != SEL_BUTTON) && (ret != SEL_ESC)) {
switch(o->objtype) {
case STRINGOBJ:
ret = SelectStringObj((StringObj *) o->obj);
break;
case LISTOBJ:
ret = SelectListObj((ListObj *) o->obj);
break;
case BUTTONOBJ:
ret = SelectButtonObj((ButtonObj *) o->obj);
break;
}
switch(ret) {
case SEL_CR:
case SEL_TAB: /* move to the next object in the list */
if (o->next != NULL) {
o = o->next; /* next object */
} else {
o = Obj; /* beginning of the list */
}
break;
case SEL_BACKTAB: /* move to the previous object in the list */
if (o->prev != NULL) {
o = o->prev; /* previous object */
} else {
o = last; /* end of the list */
}
break;
case KEY_F(1): /* display help_file */
case '?':
display_helpfile();
break;
}
}
return(ret);
} /* ReadObj() */
int
PollObj(ComposeObj **Obj)
{
ComposeObj *last; /* the last object in the list */
ComposeObj *first; /* the first object in the list */
int ret; /* the return value from the selection routine */
/* find the last object in the list */
last = *Obj;
while (last->next) last = last->next;
/* find the first object in the list */
first = *Obj;
while (first->prev) first = first->prev;
ret = 0;
switch((*Obj)->objtype) {
case STRINGOBJ:
ret = SelectStringObj((StringObj *) (*Obj)->obj);
break;
case LISTOBJ:
ret = SelectListObj((ListObj *) (*Obj)->obj);
break;
case BUTTONOBJ:
ret = SelectButtonObj((ButtonObj *) (*Obj)->obj);
break;
}
switch(ret) {
case SEL_CR:
case SEL_TAB: /* move to the next object in the list */
if ((*Obj)->next != NULL) {
*Obj = (*Obj)->next; /* next object */
} else {
*Obj = first; /* beginning of the list */
}
break;
case SEL_BACKTAB: /* move to the previous object in the list */
if ((*Obj)->prev != NULL) {
*Obj = (*Obj)->prev; /* previous object */
} else {
*Obj = last; /* end of the list */
}
break;
}
return(ret);
} /* PollObj() */
void
DelObj(ComposeObj *Obj)
/*
* Desc: Free all objects
*/
{
ComposeObj *o;
o = Obj;
while (Obj != NULL) {
switch(Obj->objtype) {
case STRINGOBJ:
DelStringObj((StringObj *) Obj->obj);
break;
case LISTOBJ:
DelListObj((ListObj *) Obj->obj);
break;
case BUTTONOBJ:
DelButtonObj((ButtonObj *) Obj->obj);
break;
}
Obj = Obj->next;
}
FreeObj(o);
} /* DelObj() */
/***********************************************************************
*
* StringObj routines
*
***********************************************************************/
void
RefreshStringObj(StringObj *so)
/*
* Desc: redraw the object
*/
{
char tmp[512];
wmove(so->win, so->y, so->x+1);
wattrset(so->win, dialog_attr);
waddstr(so->win, so->title);
draw_box(so->win, so->y+1, so->x, 3, so->w, dialog_attr, border_attr);
wattrset(so->win, item_attr);
wmove(so->win, so->y+2, so->x+1);
if (strlen(so->s) > so->w-2) {
strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1);
waddstr(so->win, tmp);
} else {
waddstr(so->win, so->s);
}
return;
} /* RefreshStringObj() */
StringObj *
NewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len)
/*
* Desc: Initialize a new stringobj and return a pointer to it.
* Draw the object on the screen at the specified coordinates
*/
{
StringObj *so;
/* Initialize a new object */
so = (StringObj *) malloc( sizeof(StringObj) );
if (!so) {
printf("NewStringObj: Error malloc'ing StringObj\n");
exit(-1);
}
so->title = (char *) malloc( strlen(title) + 1);
if (!so->title) {
printf("NewStringObj: Error malloc'ing so->title\n");
exit(-1);
}
strcpy(so->title, title);
so->s = s;
strcpy(so->s, s);
so->x = x;
so->y = y;
so->w = w;
so->len = len;
so->win = win;
/* Draw it on the screen */
RefreshStringObj(so);
return(so);
} /* NewStringObj() */
int
SelectStringObj(StringObj *so)
/*
* Desc: get input using the info in <so>
*/
{
int key;
char tmp[so->len+1];
strcpy(tmp, so->s);
key = line_edit(so->win, so->y+2, so->x+1,
so->len, so->w-2, inputbox_attr, TRUE, tmp);
if ((key == '\n') || (key == '\r')) {
strcpy(so->s, tmp);
}
RefreshStringObj(so);
if (key == ESC) {
return(SEL_ESC);
}
if (key == '\t') {
return(SEL_TAB);
}
if ( (key == KEY_BTAB) || (key == KEY_F(2)) ) {
return(SEL_BACKTAB);
}
if ((key == '\n') || (key == '\r')) {
strcpy(so->s, tmp);
return(SEL_CR);
}
return(key);
} /* SelectStringObj() */
void
DelStringObj(StringObj *so)
/*
* Desc: Free the space occupied by <so>
*/
{
free(so->title);
free(so);
return;
}
/***********************************************************************
*
* ListObj routines
*
***********************************************************************/
void
DrawNames(ListObj *lo)
/*
* Desc: Just refresh the names, not the surrounding box and title
*/
{
int i, j, h, x, y;
char tmp[MAXPATHLEN];
x = lo->x + 1;
y = lo->y + 2;
h = lo->h - 2;
wattrset(lo->win, item_attr);
for (i=lo->scroll; i<lo->n && i<lo->scroll+h; i++) {
wmove(lo->win, y+i-lo->scroll, x);
if (strlen(lo->name[i]) > lo->w-2) {
strncpy(tmp, lo->name[i], lo->w-2);
tmp[lo->w - 2] = 0;
waddstr(lo->win, tmp);
} else {
waddstr(lo->win, lo->name[i]);
for (j=strlen(lo->name[i]); j<lo->w-2; j++) waddstr(lo->win, " ");
}
}
while (i<lo->scroll+h) {
wmove(lo->win, y+i-lo->scroll, x);
for (j=0; j<lo->w-2; j++) waddstr(lo->win, " ");
i++;
}
return;
} /* DrawNames() */
void
RefreshListObj(ListObj *lo)
/*
* Desc: redraw the list object
*/
{
char perc[7];
/* setup the box */
wmove(lo->win, lo->y, lo->x+1);
wattrset(lo->win, dialog_attr);
waddstr(lo->win, lo->title);
draw_box(lo->win, lo->y+1, lo->x, lo->h, lo->w, dialog_attr, border_attr);
/* draw the names */
DrawNames(lo);
/* Draw % indication */
sprintf(perc, "(%3d%%)", MIN(100, (int) (100 * (lo->sel+lo->h-2) / MAX(1, lo->n))));
wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8);
wattrset(lo->win, dialog_attr);
waddstr(lo->win, perc);
return;
} /* RefreshListObj() */
ListObj *
NewListObj(WINDOW *win, char *title, char **list, char *listelt, int y, int x,
int h, int w, int n)
/*
* Desc: create a listobj, draw it on the screen and return a pointer to it.
*/
{
ListObj *lo;
/* Initialize a new object */
lo = (ListObj *) malloc( sizeof(ListObj) );
if (!lo) {
printf("NewListObj: Error malloc'ing ListObj\n");
exit(-1);
}
lo->title = (char *) malloc( strlen(title) + 1);
if (!lo->title) {
printf("NewListObj: Error malloc'ing lo->title\n");
exit(-1);
}
strcpy(lo->title, title);
lo->name = list;
lo->y = y;
lo->x = x;
lo->w = w;
lo->h = h;
lo->n = n;
lo->scroll = 0;
lo->sel = 0;
lo->elt = listelt;
lo->win = win;
/* Draw the object on the screen */
RefreshListObj(lo);
return(lo);
} /* NewListObj() */
void
UpdateListObj(ListObj *lo, char **list, int n)
/*
* Desc: Update the list in the listobject with the provided list
* Pre: lo->name "has been allocated"
* (A i: 0<=i<lo->n: "lo->name[i] has been allocated")
*/
{
int i;
/* Free the current names */
if (lo->name != NULL) {
for (i=0; i<lo->n; i++) {
free(lo->name[i]);
}
free(lo->name);
}
/* Rewrite the list in the object */
lo->name = list;
lo->n = n;
lo->scroll = 0;
lo->sel = 0;
/* Draw the object on the screen */
RefreshListObj(lo);
return;
} /* UpdateListObj() */
int
SelectListObj(ListObj *lo)
/*
* Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit
* Pre: lo->n >= 1
*/
{
int key, sel_x, sel_y;
char tmp[MAXPATHLEN];
char perc[4];
sel_x = lo->x+1;
sel_y = lo->y + 2 + lo->sel - lo->scroll;
if (lo->n == 0) return(SEL_TAB);
keypad(lo->win, TRUE);
/* Draw current selection in inverse video */
wmove(lo->win, sel_y, sel_x);
wattrset(lo->win, item_selected_attr);
waddstr(lo->win, lo->name[lo->sel]);
key = wgetch(lo->win);
while ((key != '\t') && (key != '\n') && (key != '\r')
&& (key != ESC) && (key != KEY_F(1)) && (key != '?')) {
/* first draw current item in normal video */
wmove(lo->win, sel_y, sel_x);
wattrset(lo->win, item_attr);
if (strlen(lo->name[lo->sel]) > lo->w - 2) {
strncpy(tmp, lo->name[lo->sel], lo->w - 2);
tmp[lo->w - 2] = 0;
waddstr(lo->win, tmp);
} else {
waddstr(lo->win, lo->name[lo->sel]);
}
switch (key) {
case KEY_DOWN:
case ctrl('n'):
if (sel_y < lo->y + lo->h-1) {
if (lo->sel < lo->n-1) {
sel_y++;
lo->sel++;
}
} else {
if (lo->sel < lo->n-1) {
lo->sel++;
lo->scroll++;
DrawNames(lo);
wrefresh(lo->win);
}
}
break;
case KEY_UP:
case ctrl('p'):
if (sel_y > lo->y+2) {
if (lo->sel > 0) {
sel_y--;
lo->sel--;
}
} else {
if (lo->sel > 0) {
lo->sel--;
lo->scroll--;
DrawNames(lo);
wrefresh(lo->win);
}
}
break;
case KEY_HOME:
case ctrl('a'):
lo->sel = 0;
lo->scroll = 0;
sel_y = lo->y + 2;
DrawNames(lo);
wrefresh(lo->win);
break;
case KEY_END:
case ctrl('e'):
if (lo->n < lo->h - 3) {
lo->sel = lo->n-1;
lo->scroll = 0;
sel_y = lo->y + 2 + lo->sel - lo->scroll;
} else {
/* more than one page of list */
lo->sel = lo->n-1;
lo->scroll = lo->n-1 - (lo->h-3);
sel_y = lo->y + 2 + lo->sel - lo->scroll;
DrawNames(lo);
wrefresh(lo->win);
}
break;
case KEY_NPAGE:
case ctrl('f'):
lo->sel += lo->h - 2;
if (lo->sel >= lo->n) lo->sel = lo->n - 1;
lo->scroll += lo->h - 2;
if (lo->scroll >= lo->n - 1) lo->scroll = lo->n - 1;
if (lo->scroll < 0) lo->scroll = 0;
sel_y = lo->y + 2 + lo->sel - lo->scroll;
DrawNames(lo);
wrefresh(lo->win);
break;
case KEY_PPAGE:
case ctrl('b'):
lo->sel -= lo->h - 2;
if (lo->sel < 0) lo->sel = 0;
lo->scroll -= lo->h - 2;
if (lo->scroll < 0) lo->scroll = 0;
sel_y = lo->y + 2 + lo->sel - lo->scroll;
DrawNames(lo);
wrefresh(lo->win);
break;
}
/* Draw % indication */
sprintf(perc, "(%3d%%)", MIN(100, (int)
(100 * (lo->sel+lo->h - 2) / MAX(1, lo->n))));
wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8);
wattrset(lo->win, dialog_attr);
waddstr(lo->win, perc);
/* draw current item in inverse */
wmove(lo->win, sel_y, sel_x);
wattrset(lo->win, item_selected_attr);
if (strlen(lo->name[lo->sel]) > lo->w - 2) {
/* when printing in inverse video show the last characters in the */
/* name that will fit in the window */
strncpy(tmp,
lo->name[lo->sel] + strlen(lo->name[lo->sel]) - (lo->w - 2),
lo->w - 2);
tmp[lo->w - 2] = 0;
waddstr(lo->win, tmp);
} else {
waddstr(lo->win, lo->name[lo->sel]);
}
key = wgetch(lo->win);
}
if (key == ESC) {
return(SEL_ESC);
}
if (key == '\t') {
return(SEL_TAB);
}
if ((key == KEY_BTAB) || (key == ctrl('b'))) {
return(SEL_BACKTAB);
}
if ((key == '\n') || (key == '\r')) {
strcpy(lo->elt, lo->name[lo->sel]);
return(SEL_CR);
}
return(key);
} /* SelectListObj() */
void
DelListObj(ListObj *lo)
/*
* Desc: Free the space occupied by the listobject
*/
{
int i;
free(lo->title);
if (lo->name != NULL) {
for (i=0; i<lo->n; i++) {
free(lo->name[i]);
}
free(lo->name);
}
free(lo);
} /* DelListObj() */
/***********************************************************************
*
* ButtonObj routines
*
***********************************************************************/
void
RefreshButtonObj(ButtonObj *bo)
/*
* Desc: redraw the button
*/
{
draw_box(bo->win, bo->y, bo->x, 3, bo->w, dialog_attr, border_attr);
print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE);
return;
} /* RefreshButtonObj() */
ButtonObj *
NewButtonObj(WINDOW *win, char *title, int *pushed, int y, int x)
/*
* Desc: Create a new button object
*/
{
ButtonObj *bo;
bo = (ButtonObj *) malloc( sizeof(ButtonObj) );
bo->win = win;
bo->title = (char *) malloc( strlen(title) + 1);
strcpy(bo->title, title);
bo->x = x;
bo->y = y;
bo->w = strlen(title) + 6;
bo->h = 3;
bo->pushed = pushed;
RefreshButtonObj(bo);
return(bo);
} /* NewButtonObj() */
int
SelectButtonObj(ButtonObj *bo)
/*
* Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC
*/
{
int key;
print_button(bo->win, bo->title, bo->y+1, bo->x+2, TRUE);
wmove(bo->win, bo->y+1, bo->x+(bo->w/2)-1);
key = wgetch(bo->win);
print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE);
switch(key) {
case '\t':
return(SEL_TAB);
break;
case KEY_BTAB:
case ctrl('b'):
return(SEL_BACKTAB);
case '\n':
*(bo->pushed) = TRUE;
return(SEL_BUTTON);
break;
case ESC:
return(SEL_ESC);
break;
default:
return(key);
break;
}
} /* SelectButtonObj() */
void
DelButtonObj(ButtonObj *bo)
/*
* Desc: Free the space occupied by <bo>
*/
{
free(bo->title);
free(bo);
return;
} /* DelButtonObj() */

View file

@ -0,0 +1,109 @@
/*
* Author: Marc van Kempen
* Desc: include file for UI-objects
*
* Copyright (c) 1995, Marc van Kempen
*
* All rights reserved.
*
* This software may be used, modified, copied, distributed, and
* sold, in both source and binary form provided that the above
* copyright and these terms are retained, verbatim, as the first
* lines of this file. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with
* its use.
*
*/
#include "dialog.h"
#include <ncurses.h>
/***********************************************************************
*
* Defines
*
***********************************************************************/
#define ctrl(a) ((a) - 'a' + 1)
/* the Object types */
#define STRINGOBJ 1
#define LISTOBJ 2
#define BUTTONOBJ 3
/* the return signals from the selection routines */
/* 1000 and higher should avoid conflicts with keys pressed */
#define SEL_CR 1001 /* return was pressed */
#define SEL_ESC 1002 /* ESC pressed */
#define SEL_TAB 1003 /* TAB pressed */
#define SEL_BACKTAB 1004 /* SHIFT-TAB pressed */
#define SEL_BUTTON 1005 /* a button was pressed */
/***********************************************************************
*
* Typedefs
*
***********************************************************************/
typedef struct {
WINDOW *win; /* the window it's contained in */
char *title; /* the prompt for the input field */
char *s; /* initial value of the input field */
int x, y, w, len; /* the (y, x) position of the upperleft */
/* corner and the width <w> of the display */
/* and length <len> of the field */
} StringObj;
typedef struct {
WINDOW *win; /* the windows it's contained in */
char *title; /* the title of the list */
char **name; /* the names of the list */
char *elt; /* the current element in the list list[sel] */
int x, y, w, h, n; /* dimensions of list and # of elements (n) */
int scroll, sel; /* current position in the list */
} ListObj;
typedef struct {
WINDOW *win; /* the window it's contained in */
char *title; /* title for the button */
int x, y, w, h; /* its dimensions */
int *pushed; /* boolean that determines wether button was pushed */
} ButtonObj;
typedef struct ComposeObj {
int objtype;
void *obj;
struct ComposeObj *next, *prev;
} ComposeObj;
/**********************************************************************
*
* Prototypes
*
**********************************************************************/
void RefreshStringObj(StringObj *so);
StringObj *NewStringObj(WINDOW *win, char *title, char *s,
int y, int x, int w, int len);
int SelectStringObj(StringObj *so);
void DelStringObj(StringObj *so);
void RefreshListObj(ListObj *lo);
ListObj *NewListObj(WINDOW *win, char *title, char **list,
char *listelt, int y, int x, int h, int w, int n);
void UpdateListObj(ListObj *lo, char **list, int n);
int SelectListObj(ListObj *lo);
void DelListObj(ListObj *obj);
void RefreshButtonObj(ButtonObj *bo);
ButtonObj *NewButtonObj(WINDOW *win, char *title, int *pushed,
int y, int x);
int SelectButtonObj(ButtonObj *bo);
void DelButtonObj(ButtonObj *bo);
void AddObj(ComposeObj **Obj, int objtype, void *obj);
void FreeObj(ComposeObj *Obj);
int ReadObj(ComposeObj *Obj);
int PollObj(ComposeObj **Obj);
void DelObj(ComposeObj *Obj);

View file

@ -83,6 +83,8 @@ int dialog_yesno(unsigned char *title, unsigned char * prompt, int height, int w
wmove(dialog, 1, 2);
print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
display_helpline(dialog, height-1, width);
x = width/2-10;
y = height-2;
print_button(dialog, " No ", y, x+13, FALSE);
@ -125,6 +127,10 @@ int dialog_yesno(unsigned char *title, unsigned char * prompt, int height, int w
return button;
case ESC:
break;
case KEY_F(1):
case '?':
display_helpfile();
break;
}
}