diff options
author | ache <ache@FreeBSD.org> | 1994-10-11 23:30:51 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1994-10-11 23:30:51 +0000 |
commit | c500015c14b43efa85ee7c9c9d2d690e35c5ec55 (patch) | |
tree | f384505ed94013858d95c38e03679a828809b732 /gnu | |
parent | ffabe2a5adaa26dfaf87b217a6866cd4408ba80f (diff) | |
parent | ef40875ab11f11f67df3bc407b3f76774856f199 (diff) | |
download | FreeBSD-src-c500015c14b43efa85ee7c9c9d2d690e35c5ec55.zip FreeBSD-src-c500015c14b43efa85ee7c9c9d2d690e35c5ec55.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r3515,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/lib/libdialog/COPYING | 339 | ||||
-rw-r--r-- | gnu/lib/libdialog/Makefile | 17 | ||||
-rw-r--r-- | gnu/lib/libdialog/README | 7 | ||||
-rw-r--r-- | gnu/lib/libdialog/checklist.c | 357 | ||||
-rw-r--r-- | gnu/lib/libdialog/colors.h | 219 | ||||
-rw-r--r-- | gnu/lib/libdialog/dialog.h | 35 | ||||
-rw-r--r-- | gnu/lib/libdialog/dialog.priv.h | 218 | ||||
-rw-r--r-- | gnu/lib/libdialog/inputbox.c | 281 | ||||
-rw-r--r-- | gnu/lib/libdialog/kernel.c | 330 | ||||
-rw-r--r-- | gnu/lib/libdialog/menubox.c | 311 | ||||
-rw-r--r-- | gnu/lib/libdialog/msgbox.c | 82 | ||||
-rw-r--r-- | gnu/lib/libdialog/radiolist.c | 368 | ||||
-rw-r--r-- | gnu/lib/libdialog/rc.c | 375 | ||||
-rw-r--r-- | gnu/lib/libdialog/rc.h | 222 | ||||
-rw-r--r-- | gnu/lib/libdialog/textbox.c | 710 | ||||
-rw-r--r-- | gnu/lib/libdialog/yesno.c | 114 |
16 files changed, 3985 insertions, 0 deletions
diff --git a/gnu/lib/libdialog/COPYING b/gnu/lib/libdialog/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/gnu/lib/libdialog/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gnu/lib/libdialog/Makefile b/gnu/lib/libdialog/Makefile new file mode 100644 index 0000000..06f73bf --- /dev/null +++ b/gnu/lib/libdialog/Makefile @@ -0,0 +1,17 @@ +# Makefile for libdialog +# $Id: Makefile,v 1.2 1994/10/09 00:46:16 pst Exp $ + +LIB= dialog +SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \ + radiolist.c textbox.c yesno.c + +CFLAGS+= -Wall -Wstrict-prototypes -DHAVE_NCURSES -DLOCALE + +SHARED_LDADD+= -lncurses -lmytinfo + +beforeinstall: + -cd ${.CURDIR}; cmp -s dialog.h ${DESTDIR}/usr/include/dialog.h || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 dialog.h \ + ${DESTDIR}/usr/include + +.include <bsd.lib.mk> diff --git a/gnu/lib/libdialog/README b/gnu/lib/libdialog/README new file mode 100644 index 0000000..ce66cf2 --- /dev/null +++ b/gnu/lib/libdialog/README @@ -0,0 +1,7 @@ +This library splitted out from 'dialog' program for use inside +C-programs. For interface function list see dialog.h. +For usage examples see 'dialog' program sources itself into +/usr/src/gnu/usr.bin/dialog. +You can additionly use any ncurses functions after init_dialog(). + + Ache. diff --git a/gnu/lib/libdialog/checklist.c b/gnu/lib/libdialog/checklist.c new file mode 100644 index 0000000..78a6b95 --- /dev/null +++ b/gnu/lib/libdialog/checklist.c @@ -0,0 +1,357 @@ +/* + * checklist.c -- implements the checklist box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected); + + +static int list_width, check_x, item_x; + + +/* + * Display a dialog box with a list of options that can be turned on or off + */ +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 i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, + scroll = 0, max_choice, *status; + WINDOW *dialog, *list; + + /* Allocate space for storing item on/off status */ + if ((status = malloc(sizeof(int)*item_no)) == NULL) { + endwin(); + fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n"); + exit(-1); + } + /* Initializes status */ + for (i = 0; i < item_no; i++) + status[i] = !strcasecmp(items[i*3 + 2], "on"); + + max_choice = MIN(list_height, item_no); + + /* 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); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset(dialog, border_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, ' '); + + 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); + print_autowrap(dialog, prompt, width, 1, 3); + + list_width = width-6; + getyx(dialog, cur_y, cur_x); + box_y = cur_y + 1; + box_x = (width - list_width)/2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1); + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height+2, list_width+2, menubox_border_attr, menubox_attr); + + check_x = 0; + item_x = 0; + /* Find length of longest item in order to center checklist */ + for (i = 0; i < item_no; i++) { + check_x = MAX(check_x, strlen(items[i*3]) + strlen(items[i*3 + 1]) + 6); + item_x = MAX(item_x, strlen(items[i*3])); + } + check_x = (list_width - check_x) / 2; + item_x = check_x + item_x + 6; + + /* Print the list */ + for (i = 0; i < max_choice; i++) + print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice); + wnoutrefresh(list); + + if (list_height < item_no) { + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddstr(dialog, "(+)"); + } + + 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) { + key = wgetch(dialog); + /* Check if key pressed matches first character of any item tag in list */ + for (i = 0; i < max_choice; i++) + if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || + key == KEY_UP || key == KEY_DOWN || key == ' ' || + key == '+' || key == '-' ) { + if (key >= '1' && key <= MIN('9', '0'+max_choice)) + i = key - '1'; + else if (key == KEY_UP || key == '-') { + if (!choice) { + if (scroll) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll--; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint list to scroll down */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); + +#else + + /* Scroll list down */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (list_height > 1) { + /* De-highlight current first item before scrolling down */ + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE); +#endif + wnoutrefresh(list); + + /* print the up/down arrows */ + wmove(dialog, box_y, box_x + check_x + 5); + wattrset(dialog, scroll ? uarrow_attr : menubox_attr); + waddch(dialog, scroll ? ACS_UARROW : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 6); + waddch(dialog, scroll ? '(' : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 7); + waddch(dialog, scroll ? '-' : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 8); + waddch(dialog, scroll ? ')' : ACS_HLINE); + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddch(dialog, '('); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 7); + waddch(dialog, '+'); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 8); + waddch(dialog, ')'); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll+choice < item_no-1) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll++; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint list to scroll up */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); + +#else + + /* Scroll list up */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, FALSE); + scrollok(list, TRUE); + scroll(list); + scrollok(list, FALSE); + } + scroll++; + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, TRUE); +#endif + wnoutrefresh(list); + + /* print the up/down arrows */ + wattrset(dialog, uarrow_attr); + wmove(dialog, box_y, box_x + check_x + 5); + waddch(dialog, ACS_UARROW); + wmove(dialog, box_y, box_x + check_x + 6); + waddstr(dialog, "(-)"); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + wattrset(dialog, scroll+choice < item_no-1 ? darrow_attr : menubox_border_attr); + waddch(dialog, scroll+choice < item_no-1 ? ACS_DARROW : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddch(dialog, scroll+choice < item_no-1 ? '(' : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 7); + waddch(dialog, scroll+choice < item_no-1 ? '+' : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 8); + waddch(dialog, scroll+choice < item_no-1 ? ')' : ACS_HLINE); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice + 1; + } + else if (key == ' ') { /* Toggle item status */ + status[scroll+choice] = !status[scroll+choice]; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + wmove(list, choice, check_x); + wattrset(list, check_selected_attr); + wprintw(list, "[%c]", status[scroll+choice] ? 'X' : ' '); + wnoutrefresh(list); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + continue; /* wait for another key press */ + } + + if (i != choice) { + /* De-highlight current item */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, FALSE); + + /* Highlight new item */ + choice = i; + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE); + wnoutrefresh(list); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + switch (key) { + case 'O': + case 'o': + delwin(dialog); + *result = '\0'; + for (i = 0; i < item_no; i++) + if (status[i]) { + strcat(result, items[i*3]); + strcat(result, "\n"); + } + free(status); + return 0; + case 'C': + case 'c': + delwin(dialog); + free(status); + return 1; + case TAB: + case KEY_BTAB: + case KEY_LEFT: + case KEY_RIGHT: + if (!button) { + button = 1; /* Indicates "Cancel" button is selected */ + print_button(dialog, " OK ", y, x, FALSE); + print_button(dialog, "Cancel", y, x+14, TRUE); + } + else { + button = 0; /* Indicates "OK" button is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + } + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + if (!button) { + *result = '\0'; + for (i = 0; i < item_no; i++) + if (status[i]) { + strcat(result, items[i*3]); + strcat(result, "\n"); + } + } + free(status); + return button; + case ESC: + break; + } + } + + delwin(dialog); + free(status); + return -1; /* ESC pressed */ +} +/* End of dialog_checklist() */ + + +/* + * Print list item + */ +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset(win, menubox_attr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + wmove(win, choice, check_x); + wattrset(win, selected ? check_selected_attr : check_attr); + wprintw(win, "[%c]", status ? 'X' : ' '); + wattrset(win, menubox_attr); + waddch(win, ' '); + wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); + waddch(win, tag[0]); + wattrset(win, selected ? tag_selected_attr : tag_attr); + waddstr(win, tag + 1); + wmove(win, choice, item_x); + wattrset(win, selected ? item_selected_attr : item_attr); + waddstr(win, item); +} +/* End of print_item() */ diff --git a/gnu/lib/libdialog/colors.h b/gnu/lib/libdialog/colors.h new file mode 100644 index 0000000..7cea0a0 --- /dev/null +++ b/gnu/lib/libdialog/colors.h @@ -0,0 +1,219 @@ +/* + * colors.h -- color attribute definitions + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * Default color definitions + * + * *_FG = foreground + * *_BG = background + * *_HL = highlight? + */ +#define SCREEN_FG COLOR_CYAN +#define SCREEN_BG COLOR_BLUE +#define SCREEN_HL TRUE + +#define SHADOW_FG COLOR_BLACK +#define SHADOW_BG COLOR_BLACK +#define SHADOW_HL TRUE + +#define DIALOG_FG COLOR_BLACK +#define DIALOG_BG COLOR_WHITE +#define DIALOG_HL FALSE + +#define TITLE_FG COLOR_YELLOW +#define TITLE_BG COLOR_WHITE +#define TITLE_HL TRUE + +#define BORDER_FG COLOR_WHITE +#define BORDER_BG COLOR_WHITE +#define BORDER_HL TRUE + +#define BUTTON_ACTIVE_FG COLOR_WHITE +#define BUTTON_ACTIVE_BG COLOR_BLUE +#define BUTTON_ACTIVE_HL TRUE + +#define BUTTON_INACTIVE_FG COLOR_BLACK +#define BUTTON_INACTIVE_BG COLOR_WHITE +#define BUTTON_INACTIVE_HL FALSE + +#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE +#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE +#define BUTTON_KEY_ACTIVE_HL TRUE + +#define BUTTON_KEY_INACTIVE_FG COLOR_RED +#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE +#define BUTTON_KEY_INACTIVE_HL FALSE + +#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW +#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE +#define BUTTON_LABEL_ACTIVE_HL TRUE + +#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK +#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE +#define BUTTON_LABEL_INACTIVE_HL TRUE + +#define INPUTBOX_FG COLOR_BLACK +#define INPUTBOX_BG COLOR_WHITE +#define INPUTBOX_HL FALSE + +#define INPUTBOX_BORDER_FG COLOR_BLACK +#define INPUTBOX_BORDER_BG COLOR_WHITE +#define INPUTBOX_BORDER_HL FALSE + +#define SEARCHBOX_FG COLOR_BLACK +#define SEARCHBOX_BG COLOR_WHITE +#define SEARCHBOX_HL FALSE + +#define SEARCHBOX_TITLE_FG COLOR_YELLOW +#define SEARCHBOX_TITLE_BG COLOR_WHITE +#define SEARCHBOX_TITLE_HL TRUE + +#define SEARCHBOX_BORDER_FG COLOR_WHITE +#define SEARCHBOX_BORDER_BG COLOR_WHITE +#define SEARCHBOX_BORDER_HL TRUE + +#define POSITION_INDICATOR_FG COLOR_YELLOW +#define POSITION_INDICATOR_BG COLOR_WHITE +#define POSITION_INDICATOR_HL TRUE + +#define MENUBOX_FG COLOR_BLACK +#define MENUBOX_BG COLOR_WHITE +#define MENUBOX_HL FALSE + +#define MENUBOX_BORDER_FG COLOR_WHITE +#define MENUBOX_BORDER_BG COLOR_WHITE +#define MENUBOX_BORDER_HL TRUE + +#define ITEM_FG COLOR_BLACK +#define ITEM_BG COLOR_WHITE +#define ITEM_HL FALSE + +#define ITEM_SELECTED_FG COLOR_WHITE +#define ITEM_SELECTED_BG COLOR_BLUE +#define ITEM_SELECTED_HL TRUE + +#define TAG_FG COLOR_YELLOW +#define TAG_BG COLOR_WHITE +#define TAG_HL TRUE + +#define TAG_SELECTED_FG COLOR_YELLOW +#define TAG_SELECTED_BG COLOR_BLUE +#define TAG_SELECTED_HL TRUE + +#define TAG_KEY_FG COLOR_RED +#define TAG_KEY_BG COLOR_WHITE +#define TAG_KEY_HL TRUE + +#define TAG_KEY_SELECTED_FG COLOR_RED +#define TAG_KEY_SELECTED_BG COLOR_BLUE +#define TAG_KEY_SELECTED_HL TRUE + +#define CHECK_FG COLOR_BLACK +#define CHECK_BG COLOR_WHITE +#define CHECK_HL FALSE + +#define CHECK_SELECTED_FG COLOR_WHITE +#define CHECK_SELECTED_BG COLOR_BLUE +#define CHECK_SELECTED_HL TRUE + +#define UARROW_FG COLOR_GREEN +#define UARROW_BG COLOR_WHITE +#define UARROW_HL TRUE + +#define DARROW_FG COLOR_GREEN +#define DARROW_BG COLOR_WHITE +#define DARROW_HL TRUE + +/* End of default color definitions */ + +#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y))) +#define COLOR_NAME_LEN 10 +#define COLOR_COUNT 8 + + +/* + * Global variables + */ + +typedef struct { + unsigned char name[COLOR_NAME_LEN]; + int value; +} color_names_st; + + +#ifdef __DIALOG_MAIN__ + +/* + * For matching color names with color values + */ +color_names_st color_names[] = { + {"BLACK", COLOR_BLACK}, + {"RED", COLOR_RED}, + {"GREEN", COLOR_GREEN}, + {"YELLOW", COLOR_YELLOW}, + {"BLUE", COLOR_BLUE}, + {"MAGENTA", COLOR_MAGENTA}, + {"CYAN", COLOR_CYAN}, + {"WHITE", COLOR_WHITE}, +}; /* color names */ + + +/* + * Table of color values + */ +int color_table[][3] = { + {SCREEN_FG, SCREEN_BG, SCREEN_HL }, + {SHADOW_FG, SHADOW_BG, SHADOW_HL }, + {DIALOG_FG, DIALOG_BG, DIALOG_HL }, + {TITLE_FG, TITLE_BG, TITLE_HL }, + {BORDER_FG, BORDER_BG, BORDER_HL }, + {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL }, + {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL }, + {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL }, + {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL }, + {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL }, + {BUTTON_LABEL_INACTIVE_FG,BUTTON_LABEL_INACTIVE_BG,BUTTON_LABEL_INACTIVE_HL}, + {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL }, + {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL }, + {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL }, + {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL }, + {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL }, + {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL }, + {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL }, + {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL }, + {ITEM_FG, ITEM_BG, ITEM_HL }, + {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL }, + {TAG_FG, TAG_BG, TAG_HL }, + {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL }, + {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL }, + {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL }, + {CHECK_FG, CHECK_BG, CHECK_HL }, + {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL }, + {UARROW_FG, UARROW_BG, UARROW_HL }, + {DARROW_FG, DARROW_BG, DARROW_HL }, +}; /* color_table */ + +#else + +extern color_names_st color_names[]; +extern int color_table[][3]; + +#endif /* __DIALOG_MAIN__ */ diff --git a/gnu/lib/libdialog/dialog.h b/gnu/lib/libdialog/dialog.h new file mode 100644 index 0000000..ffc03ac --- /dev/null +++ b/gnu/lib/libdialog/dialog.h @@ -0,0 +1,35 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define VERSION "0.4" +#define MAX_LEN 2048 + +void dialog_create_rc(unsigned char *filename); +int dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int width); +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_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(char *title, 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); +void dialog_clear(void); +void dialog_update(void); +void init_dialog(void); +void end_dialog(void); diff --git a/gnu/lib/libdialog/dialog.priv.h b/gnu/lib/libdialog/dialog.priv.h new file mode 100644 index 0000000..90a2432 --- /dev/null +++ b/gnu/lib/libdialog/dialog.priv.h @@ -0,0 +1,218 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_NCURSES +#include <ncurses.h> + +#else + +#ifdef ultrix +#include <cursesX.h> +#else +#include <curses.h> +#endif + +#endif + +#if defined(LOCALE) +#include <locale.h> +#endif + +/* + * Change these if you want + */ +#define USE_SHADOW TRUE +#define USE_COLORS TRUE + +#define ESC 27 +#define TAB 9 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef HAVE_NCURSES +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif +#endif /* HAVE_NCURSES */ + + +/* + * Attribute names + */ +#define screen_attr attributes[0] +#define shadow_attr attributes[1] +#define dialog_attr attributes[2] +#define title_attr attributes[3] +#define border_attr attributes[4] +#define button_active_attr attributes[5] +#define button_inactive_attr attributes[6] +#define button_key_active_attr attributes[7] +#define button_key_inactive_attr attributes[8] +#define button_label_active_attr attributes[9] +#define button_label_inactive_attr attributes[10] +#define inputbox_attr attributes[11] +#define inputbox_border_attr attributes[12] +#define searchbox_attr attributes[13] +#define searchbox_title_attr attributes[14] +#define searchbox_border_attr attributes[15] +#define position_indicator_attr attributes[16] +#define menubox_attr attributes[17] +#define menubox_border_attr attributes[18] +#define item_attr attributes[19] +#define item_selected_attr attributes[20] +#define tag_attr attributes[21] +#define tag_selected_attr attributes[22] +#define tag_key_attr attributes[23] +#define tag_key_selected_attr attributes[24] +#define check_attr attributes[25] +#define check_selected_attr attributes[26] +#define uarrow_attr attributes[27] +#define darrow_attr attributes[28] + +/* number of attributes */ +#define ATTRIBUTE_COUNT 29 + + +/* + * Global variables + */ +#ifdef __DIALOG_MAIN__ + +#ifdef HAVE_NCURSES + +/* use colors by default? */ +bool use_colors = USE_COLORS; + +/* shadow dialog boxes by default? + Note that 'use_shadow' implies 'use_colors' */ +bool use_shadow = USE_SHADOW; + +#endif + + +/* + * Attribute values, default is for mono display + */ +chtype attributes[] = { + A_NORMAL, /* screen_attr */ + A_NORMAL, /* shadow_attr */ + A_REVERSE, /* dialog_attr */ + A_REVERSE, /* title_attr */ + A_REVERSE, /* border_attr */ + A_BOLD, /* button_active_attr */ + A_DIM, /* button_inactive_attr */ + A_UNDERLINE, /* button_key_active_attr */ + A_UNDERLINE, /* button_key_inactive_attr */ + A_NORMAL, /* button_label_active_attr */ + A_NORMAL, /* button_label_inactive_attr */ + A_REVERSE, /* inputbox_attr */ + A_REVERSE, /* inputbox_border_attr */ + A_REVERSE, /* searchbox_attr */ + A_REVERSE, /* searchbox_title_attr */ + A_REVERSE, /* searchbox_border_attr */ + A_REVERSE, /* position_indicator_attr */ + A_REVERSE, /* menubox_attr */ + A_REVERSE, /* menubox_border_attr */ + A_REVERSE, /* item_attr */ + A_NORMAL, /* item_selected_attr */ + A_REVERSE, /* tag_attr */ + A_REVERSE, /* tag_selected_attr */ + A_NORMAL, /* tag_key_attr */ + A_BOLD, /* tag_key_selected_attr */ + A_REVERSE, /* check_attr */ + A_REVERSE, /* check_selected_attr */ + A_REVERSE, /* uarrow_attr */ + A_REVERSE /* darrow_attr */ +}; + +#else + +#ifdef HAVE_NCURSES +extern bool use_colors; +extern bool use_shadow; +#endif + +extern chtype attributes[]; + +#endif /* __DIALOG_MAIN__ */ + + + +#ifdef HAVE_NCURSES + +/* + * Function prototypes + */ +#ifdef __DIALOG_MAIN__ + +extern int parse_rc(void); + +#endif /* __DIALOG_MAIN__ */ + +#endif + + +#ifdef HAVE_NCURSES +void color_setup(void); +#endif +void attr_clear(WINDOW *win, int height, int width, chtype attr); +void print_autowrap(WINDOW *win, unsigned char *prompt, int width, int y, int x); +void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected); +void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border); +#ifdef HAVE_NCURSES +void draw_shadow(WINDOW *win, int y, int x, int height, int width); +#endif + diff --git a/gnu/lib/libdialog/inputbox.c b/gnu/lib/libdialog/inputbox.c new file mode 100644 index 0000000..a30e39a --- /dev/null +++ b/gnu/lib/libdialog/inputbox.c @@ -0,0 +1,281 @@ +/* + * inputbox.c -- implements the input box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result) +{ + int i, x, y, box_y, box_x, box_width, + input_x = 0, scroll = 0, key = 0, button = -1; + unsigned char instr[MAX_LEN+1]; + WINDOW *dialog; + + /* center dialog box on screen */ + x = (COLS - width)/2; + y = (LINES - height)/2; + + memset(instr, 0, sizeof(instr)); + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset(dialog, border_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, ' '); + + 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); + print_autowrap(dialog, prompt, width, 1, 3); + + /* Draw the input field box */ + box_width = width-6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width)/2; + draw_box(dialog, y+1, box_x-1, 3, box_width+2, border_attr, dialog_attr); + + x = width/2-11; + y = height-2; + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + + wmove(dialog, box_y, box_x); + wrefresh(dialog); + while (key != ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_BTAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_HOME: + input_x = scroll = 0; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, instr[i] ? instr[i] : ' '); + wmove(dialog, box_y, box_x); + wrefresh(dialog); + continue; + case KEY_END: + for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--) + instr[i] = '\0'; + i++; + input_x = i % box_width; + scroll = i - input_x; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + continue; + case KEY_LEFT: + if (input_x || scroll) { + wattrset(dialog, inputbox_attr); + if (!input_x) { + int oldscroll = scroll; + scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, instr[scroll+input_x+i] ? instr[scroll+input_x+i] : ' '); + input_x = oldscroll - 1 - scroll; + } + else + input_x--; + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + case KEY_RIGHT: + if (scroll+input_x < MAX_LEN) { + wattrset(dialog, inputbox_attr); + if (!instr[scroll+input_x]) + instr[scroll+input_x] = ' '; + if (input_x == box_width-1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' '); + wmove(dialog, box_y, box_x + box_width - 1); + } + else { + wmove(dialog, box_y, input_x + box_x); + waddch(dialog, instr[scroll+input_x]); + input_x++; + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + case KEY_BACKSPACE: + case KEY_DC: + if (input_x || scroll) { + i = strlen(instr); + memmove(instr+scroll+input_x-1, instr+scroll+input_x, i-scroll+input_x+1); + wattrset(dialog, inputbox_attr); + if (!input_x) { + int oldscroll = scroll; + scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, instr[scroll+input_x+i] ? instr[scroll+input_x+i] : ' '); + input_x = oldscroll - 1 - scroll; + } + else + input_x--; + wmove(dialog, box_y, input_x + box_x); + for (i = input_x; i < box_width; i++) + waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + default: + if (key < 0x100 && isprint(key)) { + for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--) + instr[i] = '\0'; + i++; + if (i < MAX_LEN) { + memmove(instr+scroll+input_x+1, instr+scroll+input_x, i-scroll+input_x); + wattrset(dialog, inputbox_attr); + instr[scroll+input_x] = key; + if (input_x == box_width-1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width-1; i++) + waddch(dialog, instr[scroll+i]); + } + else { + wmove(dialog, box_y, input_x + box_x); + for (i = input_x; i < box_width; i++) + waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' '); + wmove(dialog, box_y, ++input_x + box_x); + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + + switch (key) { + case 'O': + case 'o': + delwin(dialog); + strcpy(result, instr); + return 0; + case 'C': + case 'c': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + case KEY_BTAB: + switch (button) { + case -1: + button = 1; /* Indicates "Cancel" button is selected */ + print_button(dialog, " OK ", y, x, FALSE); + print_button(dialog, "Cancel", y, x+14, TRUE); + wrefresh(dialog); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + wrefresh(dialog); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + wrefresh(dialog); + break; + case 0: + button = 1; /* Indicates "Cancel" button is selected */ + print_button(dialog, " OK ", y, x, FALSE); + print_button(dialog, "Cancel", y, x+14, TRUE); + wrefresh(dialog); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--) + instr[i] = '\0'; + if (button < 1) + strcpy(result, instr); + return (button == -1 ? 0 : button); + case ESC: + break; + } + } + + delwin(dialog); + return -1; /* ESC pressed */ +} +/* End of dialog_inputbox() */ diff --git a/gnu/lib/libdialog/kernel.c b/gnu/lib/libdialog/kernel.c new file mode 100644 index 0000000..4a45dd3 --- /dev/null +++ b/gnu/lib/libdialog/kernel.c @@ -0,0 +1,330 @@ +/* + * dialog - Display simple dialog boxes from shell scripts + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * HISTORY: + * + * 17/12/93 - Version 0.1 released. + * + * 19/12/93 - menu will now scroll if there are more items than can fit + * on the screen. + * - added 'checklist', a dialog box with a list of options that + * can be turned on or off. A list of options that are on is + * returned on exit. + * + * 20/12/93 - Version 0.15 released. + * + * 29/12/93 - Incorporated patch from Patrick J. Volkerding + * (volkerdi@mhd1.moorhead.msus.edu) that made these changes: + * - increased MAX_LEN to 2048 + * - added 'infobox', equivalent to a message box without pausing + * - added option '--clear' that will clear the screen + * - Explicit line breaking when printing prompt text can be + * invoked by real newline '\n' besides the string "\n" + * - an optional parameter '--title <string>' can be used to + * specify a title string for the dialog box + * + * 03/01/94 - added 'textbox', a dialog box for displaying text from a file. + * - Version 0.2 released. + * + * 04/01/94 - some fixes and improvements for 'textbox': + * - fixed a bug that will cause a segmentation violation when a + * line is longer than MAX_LEN characters. Lines will now be + * truncated if they are longer than MAX_LEN characters. + * - removed wrefresh() from print_line(). This will increase + * efficiency of print_page() which calls print_line(). + * - display current position in the form of percentage into file. + * - Version 0.21 released. + * + * 05/01/94 - some changes for faster screen update. + * + * 07/01/94 - much more flexible color settings. Can use all 16 colors + * (8 normal, 8 highlight) of the Linux console. + * + * 08/01/94 - added run-time configuration using configuration file. + * + * 09/01/94 - some minor bug fixes and cleanups for menubox, checklist and + * textbox. + * + * 11/01/94 - added a man page. + * + * 13/01/94 - some changes for easier porting to other Unix systems (tested + * on Ultrix, SunOS and HPUX) + * - Version 0.3 released. + * + * 08/06/94 - Patches by Stuart Herbert - S.Herbert@shef.ac.uk + * Fixed attr_clear and the textbox stuff to work with ncurses 1.8.5 + * Fixed the wordwrap routine - it'll actually wrap properly now + * Added a more 3D look to everything - having your own rc file could + * prove 'interesting' to say the least :-) + * Added radiolist option + * - Version 0.4 released. + */ + +#define __DIALOG_MAIN__ + +#include "dialog.priv.h" +#include <dialog.h> +#ifdef HAVE_NCURSES +#include "colors.h" +#endif + +/* + * Do some initialization for dialog + */ +void init_dialog(void) +{ +#if defined(LOCALE) + (void) setlocale(LC_ALL, ""); +#endif + +#ifdef HAVE_NCURSES + if (parse_rc() == -1) /* Read the configuration file */ + exit(-1); +#endif + + initscr(); /* Init curses */ + keypad(stdscr, TRUE); + cbreak(); + noecho(); + +#ifdef HAVE_NCURSES + if (use_colors || use_shadow) /* Set up colors */ + color_setup(); +#endif + + /* Set screen to screen attribute */ + attr_clear(stdscr, LINES, COLS, screen_attr); + wnoutrefresh(stdscr); +} +/* End of init_dialog() */ + + +#ifdef HAVE_NCURSES +/* + * Setup for color display + */ +void color_setup(void) +{ + int i; + + if (has_colors()) { /* Terminal supports color? */ + start_color(); + + /* Initialize color pairs */ + for (i = 0; i < ATTRIBUTE_COUNT; i++) + init_pair(i+1, color_table[i][0], color_table[i][1]); + + /* Setup color attributes */ + for (i = 0; i < ATTRIBUTE_COUNT; i++) + attributes[i] = C_ATTR(color_table[i][2], i+1); + } +} +/* End of color_setup() */ +#endif + + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW *win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); /* Set window to attribute 'attr' */ + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } +} +/* End of attr_clear() */ + + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Note that the + * string may contain "\n" to represent a newline character or the real + * newline '\n', but in that case, auto wrap around will be disabled. + */ +void print_autowrap(WINDOW *win, unsigned char *prompt, int width, int y, int x) +{ + int first = 1, cur_x, cur_y; + unsigned char tempstr[MAX_LEN+1], *word, *tempptr, *tempptr1; + + strcpy(tempstr, prompt); + if ((strstr(tempstr, "\\n") != NULL) || + (strchr(tempstr, '\n') != NULL)) { /* Prompt contains "\n" or '\n' */ + word = tempstr; + cur_y = y; + wmove(win, cur_y, x); + while (1) { + tempptr = strstr(word, "\\n"); + tempptr1 = strchr(word, '\n'); + if (tempptr == NULL && tempptr1 == NULL) + break; + else if (tempptr == NULL) { /* No more "\n" */ + tempptr = tempptr1; + tempptr[0] = '\0'; + } + else if (tempptr1 == NULL) { /* No more '\n' */ + tempptr[0] = '\0'; + tempptr++; + } + else { /* Prompt contains both "\n" and '\n' */ + if (strlen(tempptr)-2 < strlen(tempptr1)-1) { + tempptr = tempptr1; + tempptr[0] = '\0'; + } + else { + tempptr[0] = '\0'; + tempptr++; + } + } + + waddstr(win, word); + word = tempptr + 1; + wmove(win, ++cur_y, x); + } + waddstr(win, word); + } + else if (strlen(tempstr) <= width-x*2) { /* If prompt is short */ + wmove(win, y, (width - strlen(tempstr)) / 2); + waddstr(win, tempstr); + } + else { + cur_x = x; + cur_y = y; + /* Print prompt word by word, wrap around if necessary */ + while ((word = strtok(first ? tempstr : NULL, " ")) != NULL) { + if (first) /* First iteration */ + first = 0; + if (cur_x+strlen(word) >= width) { /* wrap around to next line */ + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + cur_x++; + } + } +} +/* End of print_autowrap() */ + + +/* + * Print a button + */ +void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? button_active_attr : button_inactive_attr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? button_key_active_attr : button_key_inactive_attr); + waddch(win, label[0]); + wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr); + waddstr(win, label+1); + wattrset(win, selected ? button_active_attr : button_inactive_attr); + waddstr(win, ">"); + wmove(win, y, x+temp+1); +} +/* End of print_button() */ + + +/* + * Draw a rectangular box with line drawing characters + */ +void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height-1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width-1) + waddch(win, box | ACS_URCORNER); + else if (i == height-1 && j == width-1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height-1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width-1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} +/* End of draw_box() */ + + +#ifdef HAVE_NCURSES +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW *win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, shadow_attr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} +/* End of draw_shadow() */ +#endif + +void dialog_clear(void) +{ + attr_clear(stdscr, LINES, COLS, screen_attr); +} + +void dialog_update(void) +{ + refresh(); +} + +void end_dialog(void) +{ + endwin(); +} diff --git a/gnu/lib/libdialog/menubox.c b/gnu/lib/libdialog/menubox.c new file mode 100644 index 0000000..da818aa --- /dev/null +++ b/gnu/lib/libdialog/menubox.c @@ -0,0 +1,311 @@ +/* + * menubox.c -- implements the menu box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.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 i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, + scroll = 0, max_choice; + WINDOW *dialog, *menu; + + max_choice = MIN(menu_height, item_no); + + /* 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); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset(dialog, border_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, ' '); + + 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); + print_autowrap(dialog, prompt, width, 1, 3); + + menu_width = width-6; + getyx(dialog, cur_y, cur_x); + box_y = cur_y + 1; + box_x = (width - menu_width)/2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height+2, menu_width+2, menubox_border_attr, menubox_attr); + + tag_x = 0; + item_x = 0; + /* Find length of longest item in order to center menu */ + for (i = 0; i < item_no; i++) { + tag_x = MAX(tag_x, strlen(items[i*2]) + strlen(items[i*2 + 1]) + 2); + item_x = MAX(item_x, strlen(items[i*2])); + } + tag_x = (menu_width - tag_x) / 2; + item_x = tag_x + item_x + 2; + + /* Print the menu */ + for (i = 0; i < max_choice; i++) + print_item(menu, items[i*2], items[i*2 + 1], i, i == choice); + wnoutrefresh(menu); + + if (menu_height < item_no) { + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2); + waddstr(dialog,"(+)"); + } + + 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) { + key = wgetch(dialog); + /* Check if key pressed matches first character of any item tag in menu */ + for (i = 0; i < max_choice; i++) + if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*2][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || + key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') { + if (key >= '1' && key <= MIN('9', '0'+max_choice)) + i = key - '1'; + else if (key == KEY_UP || key == '-') { + if (!choice) { + if (scroll) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll--; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint menu to scroll down */ + for (i = 0; i < max_choice; i++) + print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice); + +#else + + /* Scroll menu down */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (menu_height > 1) { + /* De-highlight current first item before scrolling down */ + print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, FALSE); + scrollok(menu, TRUE); + wscrl(menu, -1); + scrollok(menu, FALSE); + } + scroll--; + print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, TRUE); +#endif + wnoutrefresh(menu); + + /* print the up/down arrows */ + wmove(dialog, box_y, box_x + tag_x + 1); + wattrset(dialog, scroll ? uarrow_attr : menubox_attr); + waddch(dialog, scroll ? ACS_UARROW : ACS_HLINE); + wmove(dialog, box_y, box_x + tag_x + 2); + waddch(dialog, scroll ? '(' : ACS_HLINE); + wmove(dialog, box_y, box_x + tag_x + 3); + waddch(dialog, scroll ? '-' : ACS_HLINE); + wmove(dialog, box_y, box_x + tag_x + 4); + waddch(dialog, scroll ? ')' : ACS_HLINE); + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2); + waddstr(dialog,"(+)"); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (key == KEY_DOWN || key == '+') + if (choice == max_choice - 1) { + if (scroll+choice < item_no-1) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll++; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint menu to scroll up */ + for (i = 0; i < max_choice; i++) + print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice); + +#else + + /* Scroll menu up */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (menu_height > 1) { + /* De-highlight current last item before scrolling up */ + print_item(menu, items[(scroll+max_choice-1)*2], items[(scroll+max_choice-1)*2 + 1], max_choice-1, FALSE); + scrollok(menu, TRUE); + scroll(menu); + scrollok(menu, FALSE); + } + scroll++; + print_item(menu, items[(scroll+max_choice-1)*2], items[(scroll+max_choice-1)*2 + 1], max_choice-1, TRUE); +#endif + wnoutrefresh(menu); + + /* print the up/down arrows */ + wattrset(dialog, uarrow_attr); + wmove(dialog, box_y, box_x + tag_x + 1); + waddch(dialog, ACS_UARROW); + wmove(dialog, box_y, box_x + tag_x + 2); + waddstr(dialog,"(-)"); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1); + wattrset(dialog, scroll+choice < item_no-1 ? darrow_attr : menubox_border_attr); + waddch(dialog, scroll+choice < item_no-1 ? ACS_DARROW : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2); + waddch(dialog, scroll+choice < item_no-1 ? '(' : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 3); + waddch(dialog, scroll+choice < item_no-1 ? '+' : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 4); + waddch(dialog, scroll+choice < item_no-1 ? ')' : ACS_HLINE); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice + 1; + + if (i != choice) { + /* De-highlight current item */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + print_item(menu, items[(scroll+choice)*2], items[(scroll+choice)*2 + 1], choice, FALSE); + + /* Highlight new item */ + choice = i; + print_item(menu, items[(scroll+choice)*2], items[(scroll+choice)*2 + 1], choice, TRUE); + wnoutrefresh(menu); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + switch (key) { + case 'O': + case 'o': + delwin(dialog); + strcpy(result, items[(scroll+choice)*2]); + return 0; + case 'C': + case 'c': + delwin(dialog); + return 1; + 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); + print_button(dialog, "Cancel", y, x+14, TRUE); + } + else { + button = 0; /* Indicates "OK" button is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + } + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + if (!button) + strcpy(result, items[(scroll+choice)*2]); + return button; + case ESC: + break; + } + } + + delwin(dialog); + return -1; /* ESC pressed */ +} +/* End of dialog_menu() */ + + +/* + * Print menu item + */ +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset(win, menubox_attr); + wmove(win, choice, 0); + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + wmove(win, choice, tag_x); + wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); + waddch(win, tag[0]); + wattrset(win, selected ? tag_selected_attr : tag_attr); + waddstr(win, tag + 1); + wmove(win, choice, item_x); + wattrset(win, selected ? item_selected_attr : item_attr); + waddstr(win, item); +} +/* End of print_item() */ diff --git a/gnu/lib/libdialog/msgbox.c b/gnu/lib/libdialog/msgbox.c new file mode 100644 index 0000000..c28a7c8 --- /dev/null +++ b/gnu/lib/libdialog/msgbox.c @@ -0,0 +1,82 @@ +/* + * msgbox.c -- implements the message box and info box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause) +{ + int i, x, y, key = 0; + WINDOW *dialog; + + /* 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); + 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); + print_autowrap(dialog, prompt, width-2, 1, 2); + + if (pause) { + wattrset(dialog, border_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, ' '); + print_button(dialog, " OK ", height-2, width/2-4, TRUE); + wrefresh(dialog); + while (key != ESC && key != '\n' && key != ' ') + key = wgetch(dialog); + } + else { + key = '\n'; + wrefresh(dialog); + } + + delwin(dialog); + return (key == ESC ? -1 : 0); +} +/* End of dialog_msgbox() */ diff --git a/gnu/lib/libdialog/radiolist.c b/gnu/lib/libdialog/radiolist.c new file mode 100644 index 0000000..fd69bb8 --- /dev/null +++ b/gnu/lib/libdialog/radiolist.c @@ -0,0 +1,368 @@ +/* + * radiolist.c -- implements the radiolist box + * + * AUTHOR: Stuart Herbert - S.Herbert@sheffield.ac.uk + * (from checklist.c by Savio Lam (lam836@cs.cuhk.hk)) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected); + + +static int list_width, check_x, item_x; + + +/* + * Display a dialog box with a list of options that can be turned on or off + */ +int dialog_radiolist(char *title, char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result) +{ + int i, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, + scroll = 0, max_choice, *status, was_on = 0; + WINDOW *dialog, *list; + + /* Allocate space for storing item on/off status */ + if ((status = malloc(sizeof(int)*item_no)) == NULL) { + endwin(); + fprintf(stderr, "\nCan't allocate memory in dialog_radiolist().\n"); + exit(-1); + } + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = !strcasecmp(items[i*3 + 2], "on"); + if (status[i]) + if (was_on) { + endwin(); + fprintf(stderr, "\nOnly one status can be ON in dialog_radiolist().\n"); + exit(-1); + } else + was_on = 1; + } + max_choice = MIN(list_height, item_no); + + /* 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); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset(dialog, border_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, ' '); + + 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); + print_autowrap(dialog, prompt, width, 1, 3); + + list_width = width-6; + getyx(dialog, cur_y, cur_x); + box_y = cur_y + 1; + box_x = (width - list_width)/2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1); + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height+2, list_width+2, menubox_border_attr, menubox_attr); + + check_x = 0; + item_x = 0; + /* Find length of longest item in order to center radiolist */ + for (i = 0; i < item_no; i++) { + check_x = MAX(check_x, strlen(items[i*3]) + strlen(items[i*3 + 1]) + 6); + item_x = MAX(item_x, strlen(items[i*3])); + } + check_x = (list_width - check_x) / 2; + item_x = check_x + item_x + 6; + + /* Print the list */ + for (i = 0; i < max_choice; i++) + print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice); + wnoutrefresh(list); + + if (list_height < item_no) { + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddstr(dialog, "(+)"); + } + + 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) { + key = wgetch(dialog); + /* Check if key pressed matches first character of any item tag in list */ + for (i = 0; i < max_choice; i++) + if (toupper(key) == toupper(items[(scroll+i)*3][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || + key == KEY_UP || key == KEY_DOWN || key == ' ' || + key == '+' || key == '-' ) { + if (key >= '1' && key <= MIN('9', '0'+max_choice)) + i = key - '1'; + else if (key == KEY_UP || key == '-') { + if (!choice) { + if (scroll) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll--; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint list to scroll down */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); + +#else + + /* Scroll list down */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (list_height > 1) { + /* De-highlight current first item before scrolling down */ + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE); +#endif + wnoutrefresh(list); + + /* print the up/down arrows */ + wmove(dialog, box_y, box_x + check_x + 5); + wattrset(dialog, scroll ? uarrow_attr : menubox_attr); + waddch(dialog, scroll ? ACS_UARROW : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 6); + waddch(dialog, scroll ? '(' : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 7); + waddch(dialog, scroll ? '-' : ACS_HLINE); + wmove(dialog, box_y, box_x + check_x + 8); + waddch(dialog, scroll ? ')' : ACS_HLINE); + wattrset(dialog, darrow_attr); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + waddch(dialog, ACS_DARROW); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddch(dialog, '('); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 7); + waddch(dialog, '+'); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 8); + waddch(dialog, ')'); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll+choice < item_no-1) { +#ifdef BROKEN_WSCRL + /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation + violation when scrolling windows of height = 4, so scrolling is not + used for now */ + scroll++; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + /* Reprint list to scroll up */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); + +#else + + /* Scroll list up */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, FALSE); + scrollok(list, TRUE); + scroll(list); + scrollok(list, FALSE); + } + scroll++; + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, TRUE); +#endif + wnoutrefresh(list); + + /* print the up/down arrows */ + wattrset(dialog, uarrow_attr); + wmove(dialog, box_y, box_x + check_x + 5); + waddch(dialog, ACS_UARROW); + wmove(dialog, box_y, box_x + check_x + 6); + waddstr(dialog, "(-)"); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 5); + wattrset(dialog, scroll+choice < item_no-1 ? darrow_attr : menubox_border_attr); + waddch(dialog, scroll+choice < item_no-1 ? ACS_DARROW : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 6); + waddch(dialog, scroll+choice < item_no-1 ? '(' : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 7); + waddch(dialog, scroll+choice < item_no-1 ? '+' : ACS_HLINE); + wmove(dialog, box_y + list_height + 1, box_x + check_x + 8); + waddch(dialog, scroll+choice < item_no-1 ? ')' : ACS_HLINE); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice + 1; + } + else if (key == ' ') { /* Toggle item status */ + if (!status[scroll+choice]) + { + for (i=0; i<item_no; i++) + status[i]=0; + status[scroll+choice]=1; + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); + wnoutrefresh(list); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + if (i != choice) { + /* De-highlight current item */ + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 +1], status[scroll+choice], choice, FALSE); + /* Highlight new item */ + choice = i; + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE); + wnoutrefresh(list); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + switch (key) { + case 'O': + case 'o': + delwin(dialog); + *result = '\0'; + for (i = 0; i < item_no; i++) + if (status[i]) { + strcpy(result, items[i*3]); + break; + } + free(status); + return 0; + case 'C': + case 'c': + delwin(dialog); + free(status); + return 1; + 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); + print_button(dialog, "Cancel", y, x+14, TRUE); + } + else { + button = 0; /* Indicates "OK" button is selected */ + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + } + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + if (!button) { + *result = '\0'; + for (i = 0; i < item_no; i++) + if (status[i]) { + strcpy(result, items[i*3]); + break; + } + } + free(status); + return button; + case ESC: + break; + } + } + + delwin(dialog); + free(status); + return -1; /* ESC pressed */ +} +/* End of dialog_radiolist() */ + + +/* + * Print list item + */ +static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset(win, menubox_attr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + wmove(win, choice, check_x); + wattrset(win, selected ? check_selected_attr : check_attr); + wprintw(win, "(%c)", status ? '*' : ' '); + wattrset(win, menubox_attr); + waddch(win, ' '); + wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); + waddch(win, tag[0]); + wattrset(win, selected ? tag_selected_attr : tag_attr); + waddstr(win, tag + 1); + wmove(win, choice, item_x); + wattrset(win, selected ? item_selected_attr : item_attr); + waddstr(win, item); +} +/* End of print_item() */ diff --git a/gnu/lib/libdialog/rc.c b/gnu/lib/libdialog/rc.c new file mode 100644 index 0000000..7d244da --- /dev/null +++ b/gnu/lib/libdialog/rc.c @@ -0,0 +1,375 @@ +/* + * rc.c -- routines for processing the configuration file + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.priv.h" +#include <dialog.h> +#include "colors.h" +#include "rc.h" + + +static unsigned char *attr_to_str(int fg, int bg, int hl); +static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl); +static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value); + + +/* + * Create the configuration file + */ +void dialog_create_rc(unsigned char *filename) +{ + int i; + FILE *rc_file; + + if ((rc_file = fopen(filename, "wt")) == NULL) { + fprintf(stderr, "\nError opening file for writing in create_rc().\n"); + exit(-1); + } + + fprintf(rc_file, "#\ +\n# Run-time configuration file for dialog\ +\n#\ +\n# Automatically generated by \"dialog --create-rc <file>\"\ +\n#\ +\n#\ +\n# Types of values:\ +\n#\ +\n# Number - <number>\ +\n# String - \"string\"\ +\n# Boolean - <ON|OFF>\ +\n# Attribute - (foreground,background,highlight?)\ +\n#\n\n"); + + /* Print an entry for each configuration variable */ + for (i = 0; i < VAR_COUNT; i++) { + fprintf(rc_file, "\n# %s\n", vars[i].comment); /* print comment */ + switch (vars[i].type) { + case VAL_INT: + fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var)); + break; + case VAL_STR: + fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (unsigned char *) vars[i].var); + break; + case VAL_BOOL: + fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF"); + break; + case VAL_ATTR: + fprintf(rc_file, "%s = %s\n", vars[i].name, attr_to_str(((int *) vars[i].var)[0], ((int *) vars[i].var)[1], ((int *) vars[i].var)[2])); + break; + } + } + + fclose(rc_file); +} +/* End of create_rc() */ + + +/* + * Parse the configuration file and set up variables + */ +int parse_rc(void) +{ + int i, l = 1, parse, fg, bg, hl; + unsigned char str[MAX_LEN+1], *var, *value, *tempptr; + FILE *rc_file; + + /* + * + * At start, 'dialog' determines the settings to use as follows: + * + * a) if environment variable DIALOGRC is set, it's value determines the + * name of the configuration file. + * + * b) if the file in (a) can't be found, use the file $HOME/.dialogrc + * as the configuration file. + * + * c) if the file in (b) can't be found, use compiled in defaults. + * + */ + + if ((tempptr = getenv("DIALOGRC")) != NULL) + rc_file = fopen(tempptr, "rt"); + + if (tempptr == NULL || rc_file == NULL) { /* step (a) failed? */ + /* try step (b) */ + if ((tempptr = getenv("HOME")) == NULL) + return 0; /* step (b) failed, use default values */ + + if (tempptr[0] == '\0' || lastch(tempptr) == '/') + sprintf(str, "%s%s", tempptr, DIALOGRC); + else + sprintf(str, "%s/%s", tempptr, DIALOGRC); + + if ((rc_file = fopen(str, "rt")) == NULL) + return 0; /* step (b) failed, use default values */ + } + + /* Scan each line and set variables */ + while (fgets(str, MAX_LEN, rc_file) != NULL) { + if (lastch(str) != '\n') { /* ignore rest of file if line too long */ + fprintf(stderr, "\nParse error: line %d of configuration file too long.\n", l); + fclose(rc_file); + return -1; /* parse aborted */ + } + else { + lastch(str) = '\0'; + parse = parse_line(str, &var, &value); /* parse current line */ + + switch (parse) { + case LINE_BLANK: /* ignore blank lines and comments */ + case LINE_COMMENT: + break; + case LINE_OK: + /* search table for matching config variable name */ + for (i = 0; i < VAR_COUNT && strcmp(vars[i].name, var); i++); + + if (i == VAR_COUNT) { /* no match */ + fprintf(stderr, "\nParse error: unknown variable at line %d of configuration file.\n", l); + return -1; /* parse aborted */ + } + else { /* variable found in table, set run time variables */ + switch (vars[i].type) { + case VAL_INT: + *((int *) vars[i].var) = atoi(value); + break; + case VAL_STR: + if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) { + fprintf(stderr, "\nParse error: string value expected at line %d of configuration file.\n", l); + return -1; /* parse aborted */ + } + else { + /* remove the (") quotes */ + value++; + lastch(value) = '\0'; + strcpy((unsigned char *) vars[i].var, value); + } + break; + case VAL_BOOL: + if (!strcasecmp(value, "ON")) + *((bool *) vars[i].var) = TRUE; + else if (!strcasecmp(value, "OFF")) + *((bool *) vars[i].var) = FALSE; + else { + fprintf(stderr, "\nParse error: boolean value expected at line %d of configuration file.\n", l); + return -1; /* parse aborted */ + } + break; + case VAL_ATTR: + if (str_to_attr(value, &fg, &bg, &hl) == -1) { + fprintf(stderr, "\nParse error: attribute value expected at line %d of configuration file.\n", l); + return -1; /* parse aborted */ + } + ((int *) vars[i].var)[0] = fg; + ((int *) vars[i].var)[1] = bg; + ((int *) vars[i].var)[2] = hl; + break; + } + } + break; + case LINE_ERROR: + fprintf(stderr, "\nParse error: syntax error at line %d of configuration file.\n", l); + return -1; /* parse aborted */ + } + } + + l++; /* next line */ + } + + fclose(rc_file); + return 0; /* parse successful */ +} +/* End of parse_rc() */ + + +/* + * Convert an attribute to a string representation like this: + * + * "(foreground,background,highlight)" + */ +static unsigned char *attr_to_str(int fg, int bg, int hl) +{ + int i; + static unsigned char str[MAX_LEN+1]; + + strcpy(str, "("); + /* foreground */ + for (i = 0; fg != color_names[i].value; i++); + strcat(str, color_names[i].name); + strcat(str, ","); + + /* background */ + for (i = 0; bg != color_names[i].value; i++); + strcat(str, color_names[i].name); + + /* highlight */ + strcat(str, hl ? ",ON)" : ",OFF)"); + + return str; +} +/* End of attr_to_str() */ + + +/* + * Extract the foreground, background and highlight values from an attribute + * represented as a string in this form: + * + * "(foreground,background,highlight)" + */ +static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl) +{ + int i = 0, j, get_fg = 1; + unsigned char tempstr[MAX_LEN+1], *part; + + if (str[0] != '(' || lastch(str) != ')') + return -1; /* invalid representation */ + + /* remove the parenthesis */ + strcpy(tempstr, str + 1); + lastch(tempstr) = '\0'; + + + /* get foreground and background */ + + while (1) { + /* skip white space before fg/bg string */ + while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++; + if (tempstr[i] == '\0') + return -1; /* invalid representation */ + part = tempstr + i; /* set 'part' to start of fg/bg string */ + + /* find end of fg/bg string */ + while(!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++; + + if (tempstr[i] == '\0') + return -1; /* invalid representation */ + else if (whitespace(tempstr[i])) { /* not yet ',' */ + tempstr[i++] = '\0'; + + /* skip white space before ',' */ + while(whitespace(tempstr[i]) && tempstr[i] != '\0') i++; + + if (tempstr[i] != ',') + return -1; /* invalid representation */ + } + + tempstr[i++] = '\0'; /* skip the ',' */ + for (j = 0; j < COLOR_COUNT && strcasecmp(part, color_names[j].name); j++); + if (j == COLOR_COUNT) /* invalid color name */ + return -1; + if (get_fg) { + *fg = color_names[j].value; + get_fg = 0; /* next we have to get the background */ + } + else { + *bg = color_names[j].value; + break; + } + } /* got foreground and background */ + + + /* get highlight */ + + /* skip white space before highlight string */ + while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++; + if (tempstr[i] == '\0') + return -1; /* invalid representation */ + part = tempstr + i; /* set 'part' to start of highlight string */ + + /* trim trailing white space from highlight string */ + i = strlen(part) - 1; + while(whitespace(part[i])) i--; + part[i+1] = '\0'; + + if (!strcasecmp(part, "ON")) + *hl = TRUE; + else if (!strcasecmp(part, "OFF")) + *hl = FALSE; + else + return -1; /* invalid highlight value */ + + return 0; +} +/* End of str_to_attr() */ + + +/* + * Parse a line in the configuration file + * + * Each line is of the form: "variable = value". On exit, 'var' will contain + * the variable name, and 'value' will contain the value string. + * + * Return values: + * + * LINE_BLANK - line is blank + * LINE_COMMENT - line is comment + * LINE_OK - line is ok + * LINE_ERROR - syntax error in line + */ +static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value) +{ + int i = 0; + + /* ignore white space at beginning of line */ + while(whitespace(line[i]) && line[i] != '\0') i++; + + if (line[i] == '\0') /* line is blank */ + return LINE_BLANK; + else if (line[i] == '#') /* line is comment */ + return LINE_COMMENT; + else if (line[i] == '=') /* variables names can't strart with a '=' */ + return LINE_ERROR; + + /* set 'var' to variable name */ + *var = line + i++; /* skip to next character */ + + /* find end of variable name */ + while(!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++; + + if (line[i] == '\0') /* syntax error */ + return LINE_ERROR; + else if (line[i] == '=') + line[i++] = '\0'; + else { + line[i++] = '\0'; + + /* skip white space before '=' */ + while(whitespace(line[i]) && line[i] != '\0') i++; + + if (line[i] != '=') /* syntax error */ + return LINE_ERROR; + else + i++; /* skip the '=' */ + } + + /* skip white space after '=' */ + while(whitespace(line[i]) && line[i] != '\0') i++; + + if (line[i] == '\0') + return LINE_ERROR; + else + *value = line + i; /* set 'value' to value string */ + + /* trim trailing white space from 'value' */ + i = strlen(*value) - 1; + while(whitespace((*value)[i])) i--; + (*value)[i+1] = '\0'; + + return LINE_OK; /* no syntax error in line */ +} +/* End of parse_line() */ diff --git a/gnu/lib/libdialog/rc.h b/gnu/lib/libdialog/rc.h new file mode 100644 index 0000000..fc19d03 --- /dev/null +++ b/gnu/lib/libdialog/rc.h @@ -0,0 +1,222 @@ +/* + * rc.h -- declarations for configuration file processing + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#define DIALOGRC ".dialogrc" +#define VAR_LEN 30 +#define COMMENT_LEN 70 + +/* Types of values */ +#define VAL_INT 0 +#define VAL_STR 1 +#define VAL_BOOL 2 +#define VAL_ATTR 3 + +/* Type of line in configuration file */ +#define LINE_BLANK 2 +#define LINE_COMMENT 1 +#define LINE_OK 0 +#define LINE_ERROR -1 + +/* number of configuration variables */ +#define VAR_COUNT (sizeof(vars) / sizeof(vars_st)) + +/* check if character is white space */ +#define whitespace(c) (c == ' ' || c == '\t') + +/* check if character is string quoting characters */ +#define isquote(c) (c == '"' || c == '\'') + +/* get last character of string */ +#define lastch(str) str[strlen(str)-1] + +/* + * Configuration variables + */ +typedef struct { + unsigned char name[VAR_LEN]; /* name of configuration variable as in DIALOGRC */ + void *var; /* address of actually variable to change */ + int type; /* type of value */ + unsigned char comment[COMMENT_LEN]; /* comment to put in "rc" file */ +} vars_st; + +vars_st vars[] = { + { "use_shadow", + &use_shadow, + VAL_BOOL, + "Shadow dialog boxes? This also turns on color." }, + + { "use_colors", + &use_colors, + VAL_BOOL, + "Turn color support ON or OFF" }, + + { "screen_color", + color_table[0], + VAL_ATTR, + "Screen color" }, + + { "shadow_color", + color_table[1], + VAL_ATTR, + "Shadow color" }, + + { "dialog_color", + color_table[2], + VAL_ATTR, + "Dialog box color" }, + + { "title_color", + color_table[3], + VAL_ATTR, + "Dialog box title color" }, + + { "border_color", + color_table[4], + VAL_ATTR, + "Dialog box border color" }, + + { "button_active_color", + color_table[5], + VAL_ATTR, + "Active button color" }, + + { "button_inactive_color", + color_table[6], + VAL_ATTR, + "Inactive button color" }, + + { "button_key_active_color", + color_table[7], + VAL_ATTR, + "Active button key color" }, + + { "button_key_inactive_color", + color_table[8], + VAL_ATTR, + "Inactive button key color" }, + + { "button_label_active_color", + color_table[9], + VAL_ATTR, + "Active button label color" }, + + { "button_label_inactive_color", + color_table[10], + VAL_ATTR, + "Inactive button label color" }, + + { "inputbox_color", + color_table[11], + VAL_ATTR, + "Input box color" }, + + { "inputbox_border_color", + color_table[12], + VAL_ATTR, + "Input box border color" }, + + { "searchbox_color", + color_table[13], + VAL_ATTR, + "Search box color" }, + + { "searchbox_title_color", + color_table[14], + VAL_ATTR, + "Search box title color" }, + + { "searchbox_border_color", + color_table[15], + VAL_ATTR, + "Search box border color" }, + + { "position_indicator_color", + color_table[16], + VAL_ATTR, + "File position indicator color" }, + + { "menubox_color", + color_table[17], + VAL_ATTR, + "Menu box color" }, + + { "menubox_border_color", + color_table[18], + VAL_ATTR, + "Menu box border color" }, + + { "item_color", + color_table[19], + VAL_ATTR, + "Item color" }, + + { "item_selected_color", + color_table[20], + VAL_ATTR, + "Selected item color" }, + + { "tag_color", + color_table[21], + VAL_ATTR, + "Tag color" }, + + { "tag_selected_color", + color_table[22], + VAL_ATTR, + "Selected tag color" }, + + { "tag_key_color", + color_table[23], + VAL_ATTR, + "Tag key color" }, + + { "tag_key_selected_color", + color_table[24], + VAL_ATTR, + "Selected tag key color" }, + + { "check_color", + color_table[25], + VAL_ATTR, + "Check box color" }, + + { "check_selected_color", + color_table[26], + VAL_ATTR, + "Selected check box color" }, + + { "uarrow_color", + color_table[27], + VAL_ATTR, + "Up arrow color" }, + + { "darrow_color", + color_table[28], + VAL_ATTR, + "Down arrow color" } +}; /* vars */ + + + +/* + * Routines to process configuration file + */ +int parse_rc(void); diff --git a/gnu/lib/libdialog/textbox.c b/gnu/lib/libdialog/textbox.c new file mode 100644 index 0000000..e99cc86 --- /dev/null +++ b/gnu/lib/libdialog/textbox.c @@ -0,0 +1,710 @@ +/* + * textbox.c -- implements the text box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +static void back_lines(int n); +static void print_page(WINDOW *win, int height, int width); +static void print_line(WINDOW *win, int row, int width); +static unsigned char *get_line(void); +static int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width); +static void print_position(WINDOW *win, int height, int width); + + +static int hscroll = 0, fd, file_size, bytes_read, begin_reached = 1, + end_reached = 0, page_length; +static unsigned char *buf, *page; + + +/* + * Display text from a file in a dialog box. + */ +int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width) +{ + int i, x, y, cur_x, cur_y, fpos, key = 0, dir, temp, temp1; +#ifdef HAVE_NCURSES + int passed_end; +#endif + unsigned char search_term[MAX_LEN+1], *tempptr, *found; + WINDOW *dialog, *text; + + search_term[0] = '\0'; /* no search term entered yet */ + + /* Open input file for reading */ + if ((fd = open(file, O_RDONLY)) == -1) { + endwin(); + fprintf(stderr, "\nCan't open input file in dialog_textbox().\n"); + exit(-1); + } + /* Get file size. Actually, 'file_size' is the real file size - 1, + since it's only the last byte offset from the beginning */ + if ((file_size = lseek(fd, 0, SEEK_END)) == -1) { + endwin(); + fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); + exit(-1); + } + /* Restore file pointer to beginning of file after getting file size */ + if (lseek(fd, 0, SEEK_SET) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + /* Allocate space for read buffer */ + if ((buf = malloc(BUF_SIZE+1)) == NULL) { + endwin(); + fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n"); + exit(-1); + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in dialog_textbox().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; /* mark end of valid data */ + page = buf; /* page is pointer to start of page to be displayed */ + + /* 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); + keypad(dialog, TRUE); + + /* Create window for text region, used for scrolling text */ +/* text = newwin(height-4, width-2, y+1, x+1); */ + text = subwin(dialog, height-4, width-2, y+1, x+1); + keypad(text, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + + wattrset(dialog, border_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, ' '); + + if (title != NULL) { + wattrset(dialog, title_attr); + wmove(dialog, 0, (width - strlen(title))/2 - 1); + waddch(dialog, ' '); + waddstr(dialog, title); + waddch(dialog, ' '); + } + print_button(dialog, " EXIT ", height-2, width/2-4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(text, height-4, width-2, dialog_attr); + print_page(text, height-4, width-2); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + + while ((key != ESC) && (key != '\n')) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + delwin(dialog); + free(buf); + close(fd); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + /* First page not in buffer? */ + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + if (fpos > bytes_read) { /* Yes, we have to read it in */ + if (lseek(fd, 0, SEEK_SET) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in dialog_textbox().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + } + page = buf; + print_page(text, height-4, width-2); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'G': /* Last page */ +#ifdef HAVE_NCURSES + case KEY_END: +#endif + end_reached = 1; + /* Last page not in buffer? */ + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + if (fpos < file_size) { /* Yes, we have to read it in */ + if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in dialog_textbox().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + } + page = buf + bytes_read; + back_lines(height-4); + print_page(text, height-4, width-2); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines(page_length+1); +#ifdef HAVE_NCURSES + /* We don't call print_page() here but use scrolling to ensure + faster screen update. However, 'end_reached' and 'page_length' + should still be updated, and 'page' should point to start of + next page. This is done by calling get_line() in the following + 'for' loop. */ + scrollok(text, TRUE); + wscrl(text, -1); /* Scroll text region down one line */ + scrollok(text, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < height-4; i++) { + if (!i) { + print_line(text, 0, width-2); /* print first line of page */ + wnoutrefresh(text); + } + else + get_line(); /* Called to update 'end_reached' and 'page' */ + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } +#else + print_page(text, height-4, width-2); +#endif + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (!begin_reached) { + back_lines(page_length + height-4); + print_page(text, height-4, width-2); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok(text, TRUE); + scroll(text); /* Scroll text region up one line */ + scrollok(text, FALSE); + print_line(text, height-5, width-2); +#ifndef HAVE_NCURSES + wmove(text, height-5, 0); + waddch(text, ' '); + wmove(text, height-5, width-3); + waddch(text, ' '); +#endif + wnoutrefresh(text); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case ' ': /* Next page */ + case KEY_NPAGE: + if (!end_reached) { + begin_reached = 0; + print_page(text, height-4, width-2); + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll > 0) { + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + print_page(text, height-4, width-2); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll < MAX_LEN) { + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + print_page(text, height-4, width-2); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case '/': /* Forward search */ + case 'n': /* Repeat forward search */ + case '?': /* Backward search */ + case 'N': /* Repeat backward search */ + /* set search direction */ + dir = (key == '/' || key == 'n') ? 1 : 0; + if (dir ? !end_reached : !begin_reached) { + if (key == 'n' || key == 'N') { + if (search_term[0] == '\0') { /* No search term yet */ + fprintf(stderr, "\a"); /* beep */ + break; + } + } + else /* Get search term from user */ + if (get_search_term(text, search_term, height-4, width-2) == -1) { + /* ESC pressed in get_search_term(). Reprint page to clear box */ + wattrset(text, dialog_attr); + back_lines(page_length); + print_page(text, height-4, width-2); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + break; + } + /* Save variables for restoring in case search term can't be found */ + tempptr = page; + temp = begin_reached; + temp1 = end_reached; + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + fpos -= bytes_read; + /* update 'page' to point to next (previous) line before + forward (backward) searching */ + back_lines(dir ? page_length-1 : page_length+1); + found = NULL; + if (dir) /* Forward search */ + while((found = strstr(get_line(), search_term)) == NULL) { + if (end_reached) + break; + } + else /* Backward search */ + while((found = strstr(get_line(), search_term)) == NULL) { + if (begin_reached) + break; + back_lines(2); + } + if (found == NULL) { /* not found */ + fprintf(stderr, "\a"); /* beep */ + /* Restore program state to that before searching */ + if (lseek(fd, fpos, SEEK_SET) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit(-1); + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in dialog_textbox().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + page = tempptr; + begin_reached = temp; + end_reached = temp1; + /* move 'page' to point to start of current page in order to + re-print current page. Note that 'page' always points to + start of next page, so this is necessary */ + back_lines(page_length); + } + else /* Search term found */ + back_lines(1); + /* Reprint page */ + wattrset(text, dialog_attr); + print_page(text, height-4, width-2); + if (found != NULL) + print_position(dialog, height, width); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + else /* no need to find */ + fprintf(stderr, "\a"); /* beep */ + break; + case ESC: + break; + } + } + + delwin(dialog); + free(buf); + close(fd); + return -1; /* ESC pressed */ +} +/* End of dialog_textbox() */ + + +/* + * Go back 'n' lines in text file. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i, fpos; + + begin_reached = 0; + /* We have to distinguish between end_reached and !end_reached since at end + of file, the line is not ended by a '\n'. The code inside 'if' basically + does a '--page' to move one character backward so as to skip '\n' of the + previous line */ + if (!end_reached) { + /* Either beginning of buffer or beginning of file reached? */ + if (page == buf) { + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + if (fpos > bytes_read) { /* Not beginning of file yet */ + /* We've reached beginning of buffer, but not beginning of file yet, + so read previous part of file into buffer. Note that we only + move backward for BUF_SIZE/2 bytes, but not BUF_SIZE bytes to + avoid re-reading again in print_page() later */ + /* Really possible to move backward BUF_SIZE/2 bytes? */ + if (fpos < BUF_SIZE/2 + bytes_read) { + /* No, move less then */ + if (lseek(fd, 0, SEEK_SET) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + page = buf + fpos - bytes_read; + } + else { /* Move backward BUF_SIZE/2 bytes */ + if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + page = buf + BUF_SIZE/2; + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in back_lines().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + } + else { /* Beginning of file reached */ + begin_reached = 1; + return; + } + } + if (*(--page) != '\n') { /* '--page' here */ + /* Something's wrong... */ + endwin(); + fprintf(stderr, "\nInternal error in back_lines().\n"); + exit(-1); + } + } + + /* Go back 'n' lines */ + for (i = 0; i < n; i++) + do { + if (page == buf) { + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + if (fpos > bytes_read) { + /* Really possible to move backward BUF_SIZE/2 bytes? */ + if (fpos < BUF_SIZE/2 + bytes_read) { + /* No, move less then */ + if (lseek(fd, 0, SEEK_SET) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + page = buf + fpos - bytes_read; + } + else { /* Move backward BUF_SIZE/2 bytes */ + if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in back_lines().\n"); + exit(-1); + } + page = buf + BUF_SIZE/2; + } + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in back_lines().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + } + else { /* Beginning of file reached */ + begin_reached = 1; + return; + } + } + } while (*(--page) != '\n'); + page++; +} +/* End of back_lines() */ + + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void print_page(WINDOW *win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} +/* End of print_page() */ + + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void print_line(WINDOW *win, int row, int width) +{ + int i, y, x; + unsigned char *line; + + line = get_line(); + line += MIN(strlen(line),hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win,' '); +#ifdef HAVE_NCURSES + waddnstr(win, line, MIN(strlen(line),width-2)); +#else + line[MIN(strlen(line),width-2)] = '\0'; + waddstr(win, line); +#endif + + getyx(win, y, x); + /* Clear 'residue' of previous line */ + for (i = 0; i < width-x; i++) + waddch(win, ' '); +} +/* End of print_line() */ + + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static unsigned char *get_line(void) +{ + int i = 0, fpos; + static unsigned char line[MAX_LEN+1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { /* Either end of file or end of buffer reached */ + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in get_line().\n"); + exit(-1); + } + if (fpos < file_size) { /* Not end of file yet */ + /* We've reached end of buffer, but not end of file yet, so read next + part of file into buffer */ + if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) { + endwin(); + fprintf(stderr, "\nError reading file in get_line().\n"); + exit(-1); + } + buf[bytes_read] = '\0'; + page = buf; + } + else { + if (!end_reached) + end_reached = 1; + break; + } + } + else + if (i < MAX_LEN) + line[i++] = *(page++); + else { + if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */ + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} +/* End of get_line() */ + + +/* + * Display a dialog box and get the search term from user + */ +static int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width) +{ + int i, x, y, input_x = 0, scroll = 0, key = 0, + box_height = 3, box_width = 30; + + x = (width - box_width)/2; + y = (height - box_height)/2; +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(win, y, x, box_height, box_width); +#endif + draw_box(win, y, x, box_height, box_width, dialog_attr, searchbox_border_attr); + wattrset(win, searchbox_title_attr); + wmove(win, y, x+box_width/2-4); + waddstr(win, " Search "); + + box_width -= 2; + wmove(win, y+1, x+1); + wrefresh(win); + search_term[0] = '\0'; + wattrset(win, searchbox_attr); + while (key != ESC) { + key = wgetch(win); + switch (key) { + case '\n': + if (search_term[0] != '\0') + return 0; + break; + case KEY_BACKSPACE: + if (input_x || scroll) { + if (!input_x) { + scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1); + wmove(win, y+1, x+1); + for (i = 0; i < box_width; i++) + waddch(win, search_term[scroll+input_x+i] ? + search_term[scroll+input_x+i] : ' '); + input_x = strlen(search_term) - scroll; + } + else + input_x--; + search_term[scroll+input_x] = '\0'; + wmove(win, y+1, input_x + x+1); + waddch(win, ' '); + wmove(win, y+1, input_x + x+1); + wrefresh(win); + } + break; + case ESC: + break; + default: + if (isprint(key)) + if (scroll+input_x < MAX_LEN) { + search_term[scroll+input_x] = key; + search_term[scroll+input_x+1] = '\0'; + if (input_x == box_width-1) { + scroll++; + wmove(win, y+1, x+1); + for (i = 0; i < box_width-1; i++) + waddch(win, search_term[scroll+i]); + } + else { + wmove(win, y+1, input_x++ + x+1); + waddch(win, key); + } + wrefresh(win); + } + } + } + + return -1; /* ESC pressed */ +} +/* End of get_search_term() */ + + +/* + * Print current position + */ +static void print_position(WINDOW *win, int height, int width) +{ + int fpos, percent; + + if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) { + endwin(); + fprintf(stderr, "\nError moving file pointer in print_position().\n"); + exit(-1); + } + wattrset(win, position_indicator_attr); + percent = !file_size ? 100 : ((fpos-bytes_read+page-buf)*100)/file_size; + wmove(win, height-3, width-9); + wprintw(win, "(%3d%%)", percent); +} +/* End of print_position() */ diff --git a/gnu/lib/libdialog/yesno.c b/gnu/lib/libdialog/yesno.c new file mode 100644 index 0000000..9a34fb5 --- /dev/null +++ b/gnu/lib/libdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "dialog.priv.h" +#include <dialog.h> + + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(unsigned char *title, unsigned char * prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + + /* 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); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset(dialog, border_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, ' '); + + 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); + print_autowrap(dialog, prompt, width, 1, 3); + + x = width/2-10; + y = height-2; + print_button(dialog, " No ", y, x+13, FALSE); + print_button(dialog, " Yes ", y, x, TRUE); + wrefresh(dialog); + + while (key != ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + case KEY_BTAB: + case TAB: + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + if (!button) { + button = 1; /* Indicates "No" button is selected */ + print_button(dialog, " Yes ", y, x, FALSE); + print_button(dialog, " No ", y, x+13, TRUE); + } + else { + button = 0; /* Indicates "Yes" button is selected */ + print_button(dialog, " No ", y, x+13, FALSE); + print_button(dialog, " Yes ", y, x, TRUE); + } + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case ESC: + break; + } + } + + delwin(dialog); + return -1; /* ESC pressed */ +} +/* End of dialog_yesno() */ |