diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-01-12 14:55:02 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-01-12 14:55:02 +0000 |
commit | 3d4e8889889e5e36302454225999f7e146d3219c (patch) | |
tree | fa315b999f531039df54ab7af8e99f7e8daad77c /gnu/lib/libodialog | |
parent | b905920a72950a63c9782b4911d252bfac08db6e (diff) | |
download | FreeBSD-src-3d4e8889889e5e36302454225999f7e146d3219c.zip FreeBSD-src-3d4e8889889e5e36302454225999f7e146d3219c.tar.gz |
Update dialog to version 20100428. This changes the license under which
dialog is distributed from GPLv2 to LGPLv2 and introduces a number of new
features and a new and better libdialog API. The existing libdialog will
be kept temporarily as libodialog for compatibility purposes until sade,
sysinstall and tzsetup have been either updated or replaced.
__FreeBSD_version is now 900030.
Discussed on: -current
Approved by: core
Obtained from: http://invisible-island.net/dialog
Diffstat (limited to 'gnu/lib/libodialog')
55 files changed, 11676 insertions, 0 deletions
diff --git a/gnu/lib/libodialog/CHANGES b/gnu/lib/libodialog/CHANGES new file mode 100644 index 0000000..1467a0e --- /dev/null +++ b/gnu/lib/libodialog/CHANGES @@ -0,0 +1,9 @@ +- Added two variables to call to dialog_menu() to save the position + in the menu when choosing a menu-option. + +- Added dialog_fselect(), implements a fileselector dialog +- Added ui-interface objects: Stringobject, Listobject and Buttonobject. + The fileselector dialog was built using these objects. +- changed dialog_menu to use PGUP and PGDN +- Added dialog_mesgbox, which display text given in a char buffer. +- diff --git a/gnu/lib/libodialog/COPYING b/gnu/lib/libodialog/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/gnu/lib/libodialog/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/libodialog/Makefile b/gnu/lib/libodialog/Makefile new file mode 100644 index 0000000..b03bb4a --- /dev/null +++ b/gnu/lib/libodialog/Makefile @@ -0,0 +1,24 @@ +# Makefile for libdialog +# $FreeBSD$ + +.include <bsd.own.mk> + +LIB= odialog +#MAN= NOMAN + +SHLIB_MAJOR= 7 +SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \ + lineedit.c radiolist.c textbox.c yesno.c prgbox.c raw_popen.c \ + fselect.c ui_objects.c dir.c notify.c help.c gauge.c tree.c + +CFLAGS+= -I${.CURDIR} -Wall -Wstrict-prototypes -DLOCALE + +DPADD= ${LIBNCURSES} +LDADD= -lncurses + +.if ${MK_HTML} != "no" +FILES= ${EXAMPLES:C;^;${.CURDIR}/TESTS/;} +FILESDIR= ${SHAREDIR}/examples/libdialog +.endif + +.include <bsd.lib.mk> diff --git a/gnu/lib/libodialog/README b/gnu/lib/libodialog/README new file mode 100644 index 0000000..e5e6d56 --- /dev/null +++ b/gnu/lib/libodialog/README @@ -0,0 +1,8 @@ +This library was split out from the `dialog' program for use +in C programs. For a list of interface functions, see dialog.h. +For usage examples, see the `dialog' program sources in +/usr/src/gnu/usr.bin/dialog. + +You can additionally use any ncurses functions after init_dialog(). + + Ache. diff --git a/gnu/lib/libodialog/TESTS/Makefile b/gnu/lib/libodialog/TESTS/Makefile new file mode 100644 index 0000000..65e3d71 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/Makefile @@ -0,0 +1,20 @@ +# Really quick and evil Makefile for building all the tests. I wish that +# bmake was friendlier to the concept of multiple progs/libs in the same +# directory. +# +# $FreeBSD$ + +PROGS= msg yesno prgbox gauge dselect fselect text menu1 menu2 menu3 \ + input1 input2 check1 check2 check3 radio1 radio2 radio3 \ + ftree1 ftree2 tree + +WARNS?= 2 +CFLAGS+= -Wall -Wstrict-prototypes +LDFLAGS+= -ldialog + +all: ${PROGS} + +clean: + rm -f ${PROGS} + +.include <bsd.prog.mk> diff --git a/gnu/lib/libodialog/TESTS/check1.c b/gnu/lib/libodialog/TESTS/check1.c new file mode 100644 index 0000000..a2bec62 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/check1.c @@ -0,0 +1,83 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int +getBool(dialogMenuItem *self) +{ + if (self->data && *((int *)self->data)) + return TRUE; + return FALSE; +} + +static int +setBool(dialogMenuItem *self) +{ + if (self->data) { + *((int *)self->data) = !*((int *)self->data); + return DITEM_SUCCESS; + } + return DITEM_FAILURE; +} + +static int german_book, italian_book, slang_book; + +static int +clearBooks(dialogMenuItem *self) +{ + german_book = italian_book = slang_book = FALSE; + return DITEM_SUCCESS | DITEM_REDRAW; +} + +/* menu2 - A more advanced way of using checked and fire hooks to manipulate the backing-variables directly */ +/* prompt title checked fire sel data */ +static dialogMenuItem menu2[] = { + { "German", "Buy book on learning German", getBool, setBool, NULL, &german_book}, + { "Italian", "Buy book on learning Italian", getBool, setBool, NULL, &italian_book }, + { "Slang", "Buy book on commonly used insults", getBool, setBool, NULL, &slang_book }, + { "Clear", "Clear book list", NULL, clearBooks, NULL, NULL, ' ', ' ', ' ' }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_checklist("this is a dialog_checklist() in action, test #1", + "this checklist menu shows off some of the straight-forward features\n" + "of the new menu system's check & fire dispatch hooks", -1, -1, 4, -4, menu2, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_checklist was %d (%d %d %d)\n", retval, german_book, italian_book, slang_book); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/check2.c b/gnu/lib/libodialog/TESTS/check2.c new file mode 100644 index 0000000..3608261 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/check2.c @@ -0,0 +1,105 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int +getBool(dialogMenuItem *self) +{ + if (self->data && *((int *)self->data)) + return TRUE; + return FALSE; +} + +static int +setBool(dialogMenuItem *self) +{ + if (self->data) { + *((int *)self->data) = !*((int *)self->data); + return DITEM_SUCCESS; + } + return DITEM_FAILURE; +} + +static int german_book, italian_book, slang_book; + +static int +clearBooks(dialogMenuItem *self) +{ + german_book = italian_book = slang_book = FALSE; + return DITEM_SUCCESS | DITEM_REDRAW; +} + +static int +buyBooks(dialogMenuItem *self) +{ + char foo[256]; + + if (german_book || italian_book || slang_book) { + strcpy(foo, "Ok, you're buying books on"); + if (german_book) + strcat(foo, " german"); + if (italian_book) + strcat(foo, " italian"); + if (slang_book) + strcat(foo, " slang"); + } + else + strcpy(foo, "You're not buying any books?"); + dialog_mesgbox("This is a direct callback for the `Buy' button", foo, -1, -1); + return DITEM_SUCCESS; +} + +/* menu3 - Look mom! We can finally use our own OK and Cancel buttons! */ +/* prompt title checked fire sel data */ +static dialogMenuItem menu3[] = { + { "Buy!", NULL, NULL, buyBooks }, /* New "OK" button */ + { "No Way!", NULL, NULL, NULL }, /* New "Cancel" button */ + { "German", "Buy books on learning German", getBool, setBool, NULL, &german_book }, + { "Italian", "Buy books on learning Italian", getBool, setBool, NULL, &italian_book }, + { "Slang", "Buy books on commonly used insults", getBool, setBool, NULL, &slang_book }, + { "Clear", "Clear book list", NULL, clearBooks, NULL, NULL, ' ', ' ', ' ' }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_checklist("this is dialog_checklist() in action, test #2", + "Same as before, but now we relabel the buttons and override the OK action.", + -1, -1, 4, -4, menu3 + 2, (char *)TRUE); + dialog_clear(); + fprintf(stderr, "returned value for dialog_checklist was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/check3.c b/gnu/lib/libodialog/TESTS/check3.c new file mode 100644 index 0000000..f117bd6 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/check3.c @@ -0,0 +1,92 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int +getBool(dialogMenuItem *self) +{ + if (self->data && *((int *)self->data)) + return TRUE; + return FALSE; +} + +static int +setBool(dialogMenuItem *self) +{ + if (self->data) { + *((int *)self->data) = !*((int *)self->data); + return DITEM_SUCCESS; + } + return DITEM_FAILURE; +} + +static int german_book, italian_book, slang_book; +static int spending; + +static int +check(dialogMenuItem *self) +{ + return ((int)(intptr_t)self->data == spending); +} + +static int +spend(dialogMenuItem *self) +{ + spending = (int)(intptr_t)self->data; + return DITEM_SUCCESS | DITEM_REDRAW; +} + +/* menu4 - Show off a simulated compound menu (group at top is checklist, group at bottom radio) */ +/* prompt title checked fire sel, data lbra mark rbra */ +static dialogMenuItem menu4[] = { + { "German", "Buy books on learning German", getBool, setBool, NULL, &german_book }, + { "Italian","Buy books on learning Italian", getBool, setBool, NULL, &italian_book }, + { "Slang", "Buy books on commonly used insults", getBool, setBool, NULL, &slang_book }, + { "-----", "----------------------------------", NULL, NULL, NULL, NULL, ' ', ' ', ' ' }, + { "1000", "Spend $1,000", check, spend, NULL, (void *)1000, '(', '*', ')' }, + { "500", "Spend $500", check, spend, NULL, (void *)500, '(', '*', ')' }, + { "100", "Spend $100", check, spend, NULL, (void *)100, '(', '*', ')' }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + + retval = dialog_checklist("this is dialog_checklist() in action, test #3", + "Now we show off some of the button 'styles' one can create.", + -1, -1, 7, -7, menu4, NULL); + dialog_clear(); + fprintf(stderr, "spent $%d on %s%s%s books\n", spending, german_book ? " german" : "", + italian_book ? " italian" : "", slang_book ? " slang" : ""); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/dselect.c b/gnu/lib/libodialog/TESTS/dselect.c new file mode 100644 index 0000000..1110379 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/dselect.c @@ -0,0 +1,41 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_dselect(".", "*"); + dialog_clear(); + fprintf(stderr, "returned value for dialog_dselect was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/fselect.c b/gnu/lib/libodialog/TESTS/fselect.c new file mode 100644 index 0000000..6cefaf3 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/fselect.c @@ -0,0 +1,44 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + char *retval; + + init_dialog(); + + retval = dialog_fselect(".", "*.[ch]"); + dialog_clear(); + if (retval) + fprintf(stderr, "returned value for dialog_fselect was %s\n", retval); + else + fprintf(stderr, "returned value for dialog_fselect was NULL\n"); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/ftree1.c b/gnu/lib/libodialog/TESTS/ftree1.c new file mode 100644 index 0000000..f21e0e5 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/ftree1.c @@ -0,0 +1,45 @@ +/* + * ftree1.c + * + * small test-driver for new dialog functionality + * + * Copyright (c) 1998, Anatoly A. Orehovsky + * + * file ./ftree1.test with xterm widget tree from + * direct editres(1) dump needed !!! + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <dialog.h> + +int +main(int argc, char **argv) +{ + int retval; + unsigned char *tresult; + + init_dialog(); + retval = dialog_ftree("ftree1.test", '\t', + "ftree dialog box example", + "xterm widget tree from direct editres(1) dump", + -1, -1, 15, + &tresult); + + dialog_update(); + + dialog_clear(); + + end_dialog(); + + if (!retval) + { + puts(tresult); + free(tresult); + } + + exit(retval); +} diff --git a/gnu/lib/libodialog/TESTS/ftree1.test b/gnu/lib/libodialog/TESTS/ftree1.test new file mode 100644 index 0000000..4a8f0fa --- /dev/null +++ b/gnu/lib/libodialog/TESTS/ftree1.test @@ -0,0 +1,73 @@ +XTerm login + VendorShellExt shellext + VT100 vt100 + SimpleMenu fontMenu + SmeBSB menuLabel + SmeBSB fontdefault + SmeBSB font1 + SmeBSB font2 + SmeBSB font3 + SmeBSB font4 + SmeBSB font5 + SmeBSB font6 + SmeBSB fontescape + SmeBSB fontsel + SimpleMenu mainMenu + SmeBSB menuLabel + SmeBSB securekbd + SmeBSB allowsends + SmeBSB redraw + SmeLine line1 + SmeBSB 8-bit control + SmeBSB sun function-keys + SmeLine line2 + SmeBSB suspend + SmeBSB continue + SmeBSB interrupt + SmeBSB hangup + SmeBSB terminate + SmeBSB kill + SmeLine line3 + SmeBSB quit + SimpleMenu vtMenu + SmeBSB menuLabel + SmeBSB scrollbar + SmeBSB jumpscroll + SmeBSB reversevideo + SmeBSB autowrap + SmeBSB reversewrap + SmeBSB autolinefeed + SmeBSB appcursor + SmeBSB appkeypad + SmeBSB scrollkey + SmeBSB scrollttyoutput + SmeBSB allow132 + SmeBSB cursesemul + SmeBSB visualbell + SmeBSB marginbell + SmeBSB altscreen + SmeLine line1 + SmeBSB softreset + SmeBSB hardreset + SmeBSB clearsavedlines + SmeLine line2 + SmeBSB tekshow + SmeBSB tekmode + SmeBSB vthide + TopLevelShell tektronix + VendorShellExt shellext + Tek4014 tek4014 + SimpleMenu tekMenu + SmeBSB menuLabel + SmeBSB tektextlarge + SmeBSB tektext2 + SmeBSB tektext3 + SmeBSB tektextsmall + SmeLine line1 + SmeBSB tekpage + SmeBSB tekreset + SmeBSB tekcopy + SmeLine line2 + SmeBSB vtshow + SmeBSB vtmode + SmeBSB tekhide diff --git a/gnu/lib/libodialog/TESTS/ftree2.c b/gnu/lib/libodialog/TESTS/ftree2.c new file mode 100644 index 0000000..aa4663a --- /dev/null +++ b/gnu/lib/libodialog/TESTS/ftree2.c @@ -0,0 +1,47 @@ +/* + * ftree2.c + * + * small test-driver for new dialog functionality + * + * Copyright (c) 1998, Anatoly A. Orehovsky + * + * file ./ftree2.test with xterm widget tree from + * preprocess editres(1) dump needed !!! + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <dialog.h> + +int +main(int argc, char **argv) +{ + int retval; + unsigned char *tresult; + + init_dialog(); + use_helpfile("ftree2.test"); + use_helpline("Press Arrows, Tab, Enter or F1"); + retval = dialog_ftree("ftree2.test", '\t', + "ftree dialog box example", + "xterm widget tree from preprocess editres(1) dump", + -1, -1, 15, + &tresult); + + dialog_update(); + + dialog_clear(); + + end_dialog(); + + if (!retval) + { + puts(tresult); + free(tresult); + } + + exit(retval); +} diff --git a/gnu/lib/libodialog/TESTS/ftree2.test b/gnu/lib/libodialog/TESTS/ftree2.test new file mode 100644 index 0000000..0850862 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/ftree2.test @@ -0,0 +1,73 @@ +XTerm login +XTerm login VendorShellExt shellext +XTerm login VT100 vt100 +XTerm login SimpleMenu fontMenu +XTerm login SimpleMenu fontMenu SmeBSB menuLabel +XTerm login SimpleMenu fontMenu SmeBSB fontdefault +XTerm login SimpleMenu fontMenu SmeBSB font1 +XTerm login SimpleMenu fontMenu SmeBSB font2 +XTerm login SimpleMenu fontMenu SmeBSB font3 +XTerm login SimpleMenu fontMenu SmeBSB font4 +XTerm login SimpleMenu fontMenu SmeBSB font5 +XTerm login SimpleMenu fontMenu SmeBSB font6 +XTerm login SimpleMenu fontMenu SmeBSB fontescape +XTerm login SimpleMenu fontMenu SmeBSB fontsel +XTerm login SimpleMenu mainMenu +XTerm login SimpleMenu mainMenu SmeBSB menuLabel +XTerm login SimpleMenu mainMenu SmeBSB securekbd +XTerm login SimpleMenu mainMenu SmeBSB allowsends +XTerm login SimpleMenu mainMenu SmeBSB redraw +XTerm login SimpleMenu mainMenu SmeLine line1 +XTerm login SimpleMenu mainMenu SmeBSB 8-bit control +XTerm login SimpleMenu mainMenu SmeBSB sun function-keys +XTerm login SimpleMenu mainMenu SmeLine line2 +XTerm login SimpleMenu mainMenu SmeBSB suspend +XTerm login SimpleMenu mainMenu SmeBSB continue +XTerm login SimpleMenu mainMenu SmeBSB interrupt +XTerm login SimpleMenu mainMenu SmeBSB hangup +XTerm login SimpleMenu mainMenu SmeBSB terminate +XTerm login SimpleMenu mainMenu SmeBSB kill +XTerm login SimpleMenu mainMenu SmeLine line3 +XTerm login SimpleMenu mainMenu SmeBSB quit +XTerm login SimpleMenu vtMenu +XTerm login SimpleMenu vtMenu SmeBSB menuLabel +XTerm login SimpleMenu vtMenu SmeBSB scrollbar +XTerm login SimpleMenu vtMenu SmeBSB jumpscroll +XTerm login SimpleMenu vtMenu SmeBSB reversevideo +XTerm login SimpleMenu vtMenu SmeBSB autowrap +XTerm login SimpleMenu vtMenu SmeBSB reversewrap +XTerm login SimpleMenu vtMenu SmeBSB autolinefeed +XTerm login SimpleMenu vtMenu SmeBSB appcursor +XTerm login SimpleMenu vtMenu SmeBSB appkeypad +XTerm login SimpleMenu vtMenu SmeBSB scrollkey +XTerm login SimpleMenu vtMenu SmeBSB scrollttyoutput +XTerm login SimpleMenu vtMenu SmeBSB allow132 +XTerm login SimpleMenu vtMenu SmeBSB cursesemul +XTerm login SimpleMenu vtMenu SmeBSB visualbell +XTerm login SimpleMenu vtMenu SmeBSB marginbell +XTerm login SimpleMenu vtMenu SmeBSB altscreen +XTerm login SimpleMenu vtMenu SmeLine line1 +XTerm login SimpleMenu vtMenu SmeBSB softreset +XTerm login SimpleMenu vtMenu SmeBSB hardreset +XTerm login SimpleMenu vtMenu SmeBSB clearsavedlines +XTerm login SimpleMenu vtMenu SmeLine line2 +XTerm login SimpleMenu vtMenu SmeBSB tekshow +XTerm login SimpleMenu vtMenu SmeBSB tekmode +XTerm login SimpleMenu vtMenu SmeBSB vthide +XTerm login TopLevelShell tektronix +XTerm login TopLevelShell tektronix VendorShellExt shellext +XTerm login TopLevelShell tektronix Tek4014 tek4014 +XTerm login SimpleMenu tekMenu +XTerm login SimpleMenu tekMenu SmeBSB menuLabel +XTerm login SimpleMenu tekMenu SmeBSB tektextlarge +XTerm login SimpleMenu tekMenu SmeBSB tektext2 +XTerm login SimpleMenu tekMenu SmeBSB tektext3 +XTerm login SimpleMenu tekMenu SmeBSB tektextsmall +XTerm login SimpleMenu tekMenu SmeLine line1 +XTerm login SimpleMenu tekMenu SmeBSB tekpage +XTerm login SimpleMenu tekMenu SmeBSB tekreset +XTerm login SimpleMenu tekMenu SmeBSB tekcopy +XTerm login SimpleMenu tekMenu SmeLine line2 +XTerm login SimpleMenu tekMenu SmeBSB vtshow +XTerm login SimpleMenu tekMenu SmeBSB vtmode +XTerm login SimpleMenu tekMenu SmeBSB tekhide diff --git a/gnu/lib/libodialog/TESTS/gauge.c b/gnu/lib/libodialog/TESTS/gauge.c new file mode 100644 index 0000000..bf0cfc9 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/gauge.c @@ -0,0 +1,41 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int i; + + init_dialog(); + + for (i = 0; i <= 100; i++) { + dialog_gauge("Gas tank", "When this gets 100% full, you'd better yank out the nozzle!", 10, 1, 7, 70, i); + usleep(30000); + } + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/input1.c b/gnu/lib/libodialog/TESTS/input1.c new file mode 100644 index 0000000..3751071 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/input1.c @@ -0,0 +1,45 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + unsigned char result[128]; + + init_dialog(); + + strcpy(result, "not this!"); + retval = dialog_inputbox("this is dialog_inputbox() in action, test #1", + "Enter something really profound below, please.", + -1, -1, result); + dialog_clear(); + fprintf(stderr, "returned value for dialog_inputbox was %d (%s)\n", retval, result); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/input2.c b/gnu/lib/libodialog/TESTS/input2.c new file mode 100644 index 0000000..827c052 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/input2.c @@ -0,0 +1,47 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + unsigned char result[128]; + + init_dialog(); + + result[0]='\0'; + DialogInputAttrs |= DITEM_NO_ECHO; + retval = dialog_inputbox("this is dialog_inputbox() in action, test #2 (no echo)", + "Enter something really secret below, please.", + -1, -1, result); + DialogInputAttrs &= DITEM_NO_ECHO; + dialog_clear(); + fprintf(stderr, "returned value for dialog_inputbox was %d (%s)\n", retval, result); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/menu1.c b/gnu/lib/libodialog/TESTS/menu1.c new file mode 100644 index 0000000..640157a --- /dev/null +++ b/gnu/lib/libodialog/TESTS/menu1.c @@ -0,0 +1,96 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Start of hook functions */ +static enum { nowhere, berlin, rome, ny } where; + +static int +_menu1_berlin_action(dialogMenuItem *self) +{ + if (where == berlin) { + dialog_mesgbox("excuse me?", "But you're already *in* Berlin!", -1, -1); + } + else { + where = berlin; + dialog_mesgbox("whoosh!", "Welcome to Berlin! Have a beer!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +static int +_menu1_rome_action(dialogMenuItem *self) +{ + if (where == rome) { + dialog_mesgbox("The wine must be getting to you..", "You're already in Rome!", -1, -1); + } + else { + where = rome; + dialog_mesgbox("whoosh!", "Welcome to Rome! Have a coffee!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +static int +_menu1_ny_action(dialogMenuItem *self) +{ + if (where == ny) { + dialog_mesgbox("Say what?", "You're already there!", -1, -1); + } + else { + where = ny; + dialog_mesgbox("whoosh!", "Welcome to New York! Now go someplace else!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +/* menu1 - show off the "fire" action hook */ +/* prompt title checked fire */ +static dialogMenuItem menu1[] = { + { "Berlin", "Go visit Germany's new capitol", NULL, _menu1_berlin_action }, + { "Rome", "Go visit the Roman ruins", NULL, _menu1_rome_action }, + { "New York", "Go visit the streets of New York", NULL, _menu1_ny_action }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_menu("this is dialog_menu() in action, test #1", + "this simple menu shows off some of the straight-forward features\n" + "of the new menu system's action dispatch hooks. Select Cancel to leave", + -1, -1, 3, -3, menu1, NULL, NULL, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_menu was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/menu2.c b/gnu/lib/libodialog/TESTS/menu2.c new file mode 100644 index 0000000..1545cd8 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/menu2.c @@ -0,0 +1,96 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Start of hook functions */ +static enum { nowhere, berlin, rome, ny } where; + +static int +_menu1_berlin_action(dialogMenuItem *self) +{ + if (where == berlin) + dialog_mesgbox("excuse me?", "But you're already *in* Berlin!", -1, -1); + else { + where = berlin; + dialog_mesgbox("whoosh!", "Welcome to Berlin! Have a beer!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +static int +_menu1_rome_action(dialogMenuItem *self) +{ + if (where == rome) + dialog_mesgbox("The wine must be getting to you..", "You're already in Rome!", -1, -1); + else { + where = rome; + dialog_mesgbox("whoosh!", "Welcome to Rome! Have a coffee!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +static int +_menu1_ny_action(dialogMenuItem *self) +{ + if (where == ny) + dialog_mesgbox("Say what?", "You're already there!", -1, -1); + else { + where = ny; + dialog_mesgbox("whoosh!", "Welcome to New York! Now go someplace else!", -1, -1); + } + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +/* menu1 - show off the "fire" action hook */ +/* prompt title checked fire */ +static dialogMenuItem menu1[] = { + { "Berlin", "Go visit Germany's new capitol", NULL, _menu1_berlin_action }, + { "Rome", "Go visit the Roman ruins", NULL, _menu1_rome_action }, + { "New York", "Go visit the streets of New York", NULL, _menu1_ny_action }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + use_helpfile("menu2.c"); + use_helpline("Type F1 to view the source for this demo"); + retval = dialog_menu("this is dialog_menu() in action, test #2", + "this simple menu shows off some of the straight-forward features\n" + "of the new menu system's action dispatch hooks as well as a helpline\n" + "and a helpfile. Select Cancel to leave", + -1, -1, 3, -3, menu1, NULL, NULL, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_menu was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/menu3.c b/gnu/lib/libodialog/TESTS/menu3.c new file mode 100644 index 0000000..3a7a137 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/menu3.c @@ -0,0 +1,107 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int +stop(dialogMenuItem *self) +{ + dialog_mesgbox("!", "I'm no idiot!", -1, -1); + return DITEM_SUCCESS; +} + +static int +maybe(dialogMenuItem *self) +{ + dialog_mesgbox("!", "I said don't rush me! I'm THINKING!", -1, -1); + return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE; +} + +/* Dummy menu just to show of the ability */ +static char *insurance[] = { + "1,000,000", "Mondo insurance policy", "Off", + "5,000,000", "Mega insurance policy", "Off", + "10,000,000", "Friend! Most Favored customer!", "On" +}; + +static void +preinsure(dialogMenuItem *self, int is_selected) +{ + if (is_selected) { + static WINDOW *w; + + /* This has to be here first if you want to see selection traverse properly in the invoking menu */ + refresh(); + + w = dupwin(newscr); + DialogX = 1; + DialogY = 13; + dialog_radiolist("How much insurance would you like to take out?", + "If you're really going to do this, we recommend some insurance\n" + "first! What kind of life insurance policy would you like?", + -1, -1, 3, 3, insurance, NULL); + touchwin(w); + wrefresh(w); + delwin(w); + } +} + +/* + * Show a simple menu that puts up a sub menu when a certain item is traversed to + */ + +/* prompt title checked fire sel */ +static dialogMenuItem doit[] = { + { "Rah!" }, + { "No way!" }, + { "Stop", "No, I'm not going to do that!", NULL, stop, NULL }, + { "Maybe", "I'm still thinking about it, don't rush me!", NULL, maybe, NULL, }, + { "Go", "Yes! Yes! I want to do it!", NULL, NULL, preinsure }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + + DialogX = 5; + DialogY = 1; + retval = dialog_menu("Do you have the GUTS?", + "C'mon, macho man! Do you have what it takes to do something REALLY\n" + "dangerous and stupid? WHAT ARE YOU WAITING FOR?!", + -1, -1, 3, -3, doit + 2, (char *)TRUE, NULL, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_menu was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/msg.c b/gnu/lib/libodialog/TESTS/msg.c new file mode 100644 index 0000000..c6f590f --- /dev/null +++ b/gnu/lib/libodialog/TESTS/msg.c @@ -0,0 +1,42 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_msgbox("This is dialog_msgbox() in action with pause on", "Hi there. Please press return now.", + -1, -1, 1); + dialog_clear(); + fprintf(stderr, "returned value for dialog_msgbox was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/prgbox.c b/gnu/lib/libodialog/TESTS/prgbox.c new file mode 100644 index 0000000..2da4611 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/prgbox.c @@ -0,0 +1,41 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_prgbox("This is dialog_prgbox() in action with cal(1)", "cal", 14, 50, TRUE, TRUE); + dialog_clear(); + fprintf(stderr, "returned value for dialog_prgbox was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/radio1.c b/gnu/lib/libodialog/TESTS/radio1.c new file mode 100644 index 0000000..c4eeffd --- /dev/null +++ b/gnu/lib/libodialog/TESTS/radio1.c @@ -0,0 +1,71 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int spending; + +static int +check(dialogMenuItem *self) +{ + return ((int)(intptr_t)self->data == spending); +} + +static int +spend(dialogMenuItem *self) +{ + spending = (int)(intptr_t)self->data; + return DITEM_SUCCESS | DITEM_REDRAW; +} + +/* menu5 - Show a simple radiolist menu that inherits the radio appearance by default */ +/* prompt title checked fire sel data */ +static dialogMenuItem menu5[] = { + { "1000", "Spend $1,000", check, spend, NULL, (void *)1000 }, + { "500", "Spend $500", check, spend, NULL, (void *)500 }, + { "100", "Spend $100", check, spend, NULL, (void *)100 }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + + retval = dialog_radiolist("this is dialog_radiolist() in action, test #1", + "this radio menu shows off some of the straight-forward features\n" + "of the new menu system's check & fire dispatch hooks", -1, -1, 3, -3, menu5, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_radiolist was %d (money set to %d)\n", retval, spending); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/radio2.c b/gnu/lib/libodialog/TESTS/radio2.c new file mode 100644 index 0000000..15e353c --- /dev/null +++ b/gnu/lib/libodialog/TESTS/radio2.c @@ -0,0 +1,89 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static char bachelor[10], bachelette[10]; + +static int +getBachelor(dialogMenuItem *self) +{ + return !strcmp(bachelor, self->prompt); +} + +static int +setBachelor(dialogMenuItem *self) +{ + strcpy(bachelor, self->prompt); + return DITEM_SUCCESS | DITEM_REDRAW; +} + +static int +getBachelette(dialogMenuItem *self) +{ + return !strcmp(bachelette, self->prompt); +} + +static int +setBachelette(dialogMenuItem *self) +{ + strcpy(bachelette, self->prompt); + return DITEM_SUCCESS | DITEM_REDRAW; +} + +/* menu6- More complex radiolist menu that creates two groups in a single menu */ +/* prompt title checked fire */ +static dialogMenuItem menu6[] = { + { "Tom", "Tom's a dynamic shoe salesman from Tulsa, OK!", getBachelor, setBachelor }, + { "Dick", "Dick's a retired engine inspector from McDonnell-Douglas!", getBachelor, setBachelor }, + { "Harry", "Harry's a professional female impersonator from Las Vegas!", getBachelor, setBachelor }, + { "-----", "----------------------------------", NULL, NULL, NULL, NULL, ' ', ' ', ' ' }, + { "Jane", "Jane's a twice-divorced housewife from Moose, Oregon!", getBachelette, setBachelette }, + { "Sally", "Sally's a shy Human Resources Manager for IBM!", getBachelette, setBachelette }, + { "Mary", "Mary's an energetic serial killer on the lam!", getBachelette, setBachelette }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_radiolist("this is dialog_radiolist() in action, test #2", + "Welcome to \"The Love Blender!\" - America's favorite game show\n" + "where YOU, the contestant, get to choose which of these two\n" + "fine specimens of humanity will go home together, whether they\n" + "like it or not!", -1, -1, 7, -7, menu6, NULL); + dialog_clear(); + fprintf(stderr, "I'm sure that %s and %s will be very happy together!\n", bachelor, bachelette); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/radio3.c b/gnu/lib/libodialog/TESTS/radio3.c new file mode 100644 index 0000000..2175358 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/radio3.c @@ -0,0 +1,98 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Hook functions */ + +static int spending; + +static int +check(dialogMenuItem *self) +{ + return ((int)(intptr_t)self->data == spending); +} + +static int +spend(dialogMenuItem *self) +{ + spending = (int)(intptr_t)self->data; + return DITEM_SUCCESS | DITEM_REDRAW; +} + +static void +ask(dialogMenuItem *self, int is_selected) +{ + if (is_selected) { + char *str; + + if (!strcmp(self->prompt, "1000")) + str = "You'd better ask both your parents first! "; + else if (!strcmp(self->prompt, "500")) + str = "You'd better at least ask your Dad! "; + else + str = "Yes, being frugal is probably a good idea!"; + DialogX = 15; + DialogY = 17; + dialog_msgbox("Free Advice", str, -1, -1, 0); + } +} + +/* + * menu5 - Show a simple radiolist menu that inherits the radio appearance by default and appears at + * a different location, leaving room for a msg box below it. This shows off the DialogX/DialogY extensions. + */ + +/* prompt title checked fire sel data */ +static dialogMenuItem menu5[] = { + { "1000", "Spend $1,000", check, spend, ask, (void *)1000 }, + { "500", "Spend $500", check, spend, ask, (void *)500 }, + { "100", "Spend $100", check, spend, ask, (void *)100 }, +}; + +/* End of hook functions */ + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + + DialogX = 5; + DialogY = 1; + retval = dialog_radiolist("this is dialog_radiolist() in action, test #3", + "This radio menu shows off the ability to put dialog menus and other\n" + "controls at different locations, as well as the `selected' hook which\n" + "lets you follow the traversal of the selection bar as well as what's\n" + "selected.", + -1, -1, 3, -3, menu5, NULL); + dialog_clear(); + fprintf(stderr, "returned value for dialog_radiolist was %d (money set to %d)\n", retval, spending); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/text.c b/gnu/lib/libodialog/TESTS/text.c new file mode 100644 index 0000000..e071937 --- /dev/null +++ b/gnu/lib/libodialog/TESTS/text.c @@ -0,0 +1,41 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int retval; + + init_dialog(); + + retval = dialog_textbox("This is dialog_textbox() in action with /etc/passwd", "/etc/passwd", 10, 60); + dialog_clear(); + fprintf(stderr, "returned value for dialog_textbox was %d\n", retval); + + end_dialog(); + return 0; +} diff --git a/gnu/lib/libodialog/TESTS/tree.c b/gnu/lib/libodialog/TESTS/tree.c new file mode 100644 index 0000000..c69b52e --- /dev/null +++ b/gnu/lib/libodialog/TESTS/tree.c @@ -0,0 +1,111 @@ +/* + * tree.c + * + * small test-driver for new dialog functionality + * + * Copyright (c) 1998, Anatoly A. Orehovsky + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <dialog.h> + +unsigned char *names[] = { + "/", + "/dev", + "/dev/fd", + "/tmp", + "/usr", + "/var", + "/home", + "/stand", + "/stand/etc", + "/stand/en_US.ISO8859-1", + "/stand/info", + "/stand/info/bin", + "/stand/info/des", + "/stand/info/games", + "/stand/info/manpages", + "/stand/info/proflibs", + "/stand/info/dict", + "/stand/info/info", + "/stand/info/src", + "/etc", + "/etc/gnats", + "/etc/kerberosIV", + "/etc/mtree", + "/etc/namedb", + "/etc/ppp", + "/etc/uucp", + "/etc/sliphome", + "/proc", + "/lkm", + "/mnt", + "/root", + "/sbin", + "/bin", + 0 +}; + +unsigned char *names1[] = { + "a", + "a:b", + "a:b:c", + "a:d" +}; + +int +main(int argc, char **argv) +{ + int retval; + unsigned char *tresult; + char comstr[BUFSIZ]; + + init_dialog(); + do { + use_helpline("Press OK for listing directory"); + retval = dialog_tree(names, + sizeof(names)/sizeof(unsigned char *) - 1, + '/', + "tree dialog box example", + "Typical find -x / -type d output", + -1, -1, 15, + &tresult); + + if (retval) + break; + + use_helpline(NULL); + (void)snprintf(comstr, sizeof(comstr), + "ls -CF %s", tresult); + + retval = dialog_prgbox( + comstr, + comstr, 20, 60, TRUE, TRUE); + + dialog_clear(); + + retval = dialog_tree(names1, + sizeof(names1)/sizeof(unsigned char *), + ':', + "tree dialog box example", + "Other tree", + -1, -1, 5, + &tresult); + if (!retval) + { + dialog_clear(); + } + } while (!retval); + + dialog_update(); + + dialog_clear(); + + end_dialog(); + + exit(retval); +} diff --git a/gnu/lib/libodialog/TESTS/yesno.c b/gnu/lib/libodialog/TESTS/yesno.c new file mode 100644 index 0000000..647b51c --- /dev/null +++ b/gnu/lib/libodialog/TESTS/yesno.c @@ -0,0 +1,45 @@ +/* + * small test-driver for new dialog functionality + * + * Copyright (c) 1995, Jordan Hubbard + * + * All rights reserved. + * + * This source code may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of the software nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <dialog.h> + +/* Kick it off, James! */ +int +main(int argc, char **argv) +{ + int rval1, rval2; + + init_dialog(); + + rval1 = dialog_yesno("This is dialog_yesno() in action", + "Have you stopped deliberately putting bugs into your code?", -1, -1); + dialog_clear(); + rval2 = dialog_noyes("This is dialog_noyes() in action", + "Have you stopped beating your wife?", -1, -1); + dialog_clear(); + end_dialog(); + fprintf(stderr, "returned value for dialog_yesno was %d\n", rval1); + fprintf(stderr, "returned value for dialog_noyes was %d\n", rval2); + return 0; +} diff --git a/gnu/lib/libodialog/TODO b/gnu/lib/libodialog/TODO new file mode 100644 index 0000000..132a4a4 --- /dev/null +++ b/gnu/lib/libodialog/TODO @@ -0,0 +1,36 @@ +- cut off names in the listbox that are to long +done 27Jan95 + The current behaviour may not be desirable. When browsing through + long names these, when highlighted, will be shown with the first + characters cut off, when not highlighted the last characters will + be cut off. + +- look at behaviour of TAB key when browsing through directories. +done 28Jan95 + +- make sure the full name of the directory is written to the + "Directory:"-box +done 28Jan95 + +- mark current selections in listbox when initializing the listobject +Idontknow +- test and use Notify() when checking for error conditions +ok +- test overall +- adapt color of buttons when changing focus to the button. +done 28Jan95 +- add shade to dialog_fselect()-window +done 29Jan95 +- add (nn%) indication to lists. +done 30Jan95 +- add use_helpfile() +done 13Feb95 +- add use_helpline() + +NOTE: apparently there is a bug (or a strange interaction between pkg_manage +and dialog_textbox) in dialog_textbox. When I use this routine to display +the helpfile in display_helpfile() the program gets mysterious segmentation +faults and bus errors. +I now use dialog_mesgbox, after I have read the file into a buffer. + + diff --git a/gnu/lib/libodialog/checklist.c b/gnu/lib/libodialog/checklist.c new file mode 100644 index 0000000..e349ca6 --- /dev/null +++ b/gnu/lib/libodialog/checklist.c @@ -0,0 +1,661 @@ +/* + * checklist.c -- implements the checklist box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * + * 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.h" + + +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x); + +#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL) + +/* + * 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 cnt, void *it, unsigned char *result) +{ + int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button, + choice, l, k, scroll, max_choice, item_no = 0, *status; + int redraw_menu = FALSE, cursor_reset = FALSE; + int rval = 0, onlist = 1, ok_space, cancel_space; + char okButton, cancelButton; + WINDOW *dialog, *list; + unsigned char **items = NULL; + dialogMenuItem *ditems; + int list_width, check_x, item_x; + + /* Allocate space for storing item on/off status */ + if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) { + endwin(); + fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n"); + exit(-1); + } + +draw: + choice = scroll = button = 0; + /* Previous calling syntax, e.g. just a list of strings? */ + if (cnt >= 0) { + items = it; + ditems = NULL; + item_no = cnt; + /* Initializes status */ + for (i = 0; i < item_no; i++) + status[i] = !strcasecmp(items[i*3 + 2], "on"); + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(cnt); + ditems = it; + if (!items) + items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *)); + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE; + items[i*3] = ditems[i].prompt; + items[i*3 + 1] = ditems[i].title; + items[i*3 + 2] = status[i] ? "on" : "off"; + } + } + max_choice = MIN(list_height, item_no); + + check_x = 0; + item_x = 0; + /* Find length of longest item in order to center checklist */ + for (i = 0; i < item_no; i++) { + l = strlen(items[i*3]); + for (j = 0; j < item_no; j++) { + k = strlen(items[j*3 + 1]); + check_x = MAX(check_x, l + k + 6); + } + item_x = MAX(item_x, l); + } + if (height < 0) + height = strheight(prompt)+list_height+4+2; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j); + width = MAX(width,check_x+4)+4; + } + width = MAX(width,24); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = (COLS - width)/2; + y = (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width, y, x); + return -1; + } + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE); + + 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); + if (list == NULL) { + delwin(dialog); + endwin(); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width, + y + box_y + 1, x + box_x + 1); + return -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 = (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, DREF(ditems, i), list_width, item_x, check_x); + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + + display_helpline(dialog, height - 1, width); + + x = width / 2 - 11; + y = height - 2; + /* Is this a fancy new style argument string where we get to override + * the buttons, or an old style one where they're fixed? + */ + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } + wnoutrefresh(dialog); + wmove(list, choice, check_x+1); + wrefresh(list); + + /* + * XXX Black magic voodoo that allows printing to the checklist + * window. For some reason, if this "refresh" code is not in + * place, printing to the window from the selected callback + * prints "behind" the checklist window. There is probably a + * better way to do this. + */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr); + + for (i = 0; i < max_choice; i++) + print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + /* XXX Black magic XXX */ + + while (key != ESC) { + key = wgetch(dialog); + + /* Shortcut to OK? */ + if (toupper(key) == okButton) { + if (ditems) { + if (result && ditems[OK_BUTTON].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + } + else if (result) { + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcat(result, items[i*3]); + strcat(result, "\n"); + } + } + } + rval = 0; + key = ESC; /* Lemme out! */ + break; + } + + /* Shortcut to cancel? */ + if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + wmove(dialog, cur_y, cur_x); + } + delwin(save); + } + rval = 1; + key = ESC; /* I gotta go! */ + break; + } + + /* Check if key pressed matches first character of any item tag in list */ + for (i = 0; i < max_choice; i++) + if (key != ' ' && key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || + KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\n' || + key == '\r') && onlist)) { + + /* if moving from buttons to the list, reset and redraw buttons */ + if (!onlist) { + onlist = 1; + button = 0; + + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + } + + if (key >= '1' && key <= MIN('9', '0'+max_choice)) + i = key - '1'; + + else if (KEY_IS_UP(key)) { + if (!choice) { + if (scroll) { + /* 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, DREF(ditems, scroll), list_width, item_x, check_x); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, + TRUE, DREF(ditems, scroll), list_width, item_x, check_x); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (KEY_IS_DOWN(key)) { + if (choice == max_choice - 1) { + if (scroll + choice < item_no - 1) { + /* 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, DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x); + 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, + DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + else + i = choice + 1; + } + else if ((key == ' ' || key == '\n' || key == '\r') && onlist) { /* Toggle item status */ + char lbra = 0, rbra = 0, mark = 0; + + getyx(list, old_y, old_x); /* Save cursor position */ + + if (ditems) { + if (ditems[scroll + choice].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[scroll + choice].fire(&ditems[scroll + choice]); /* Call "fire" action */ + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + if (st & DITEM_REDRAW) { + wclear(list); + for (i = 0; i < item_no; i++) + status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE; + 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, DREF(ditems, scroll + i), list_width, item_x, check_x); + } + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, + cur_x, cur_y); + wrefresh(dialog); + } + if (st & DITEM_LEAVE_MENU) { + /* Allow a fire action to take us out of the menu */ + key = ESC; + rval = 0; + break; + } + else if (st & DITEM_RECREATE) { + delwin(list); + delwin(dialog); + dialog_clear(); + goto draw; + } + } + status[scroll + choice] = ditems[scroll + choice].checked ? + ditems[scroll + choice].checked(&ditems[scroll + choice]) : FALSE; + lbra = ditems[scroll + choice].lbra; + rbra = ditems[scroll + choice].rbra; + mark = ditems[scroll + choice].mark; + } + else + status[scroll + choice] = !status[scroll + choice]; + wmove(list, choice, check_x); + wattrset(list, check_selected_attr); + if (!lbra) + lbra = '['; + if (!rbra) + rbra = ']'; + if (!mark) + mark = 'X'; + wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra); + wmove(list, old_y, old_x); /* Restore cursor to previous position */ + wrefresh(list); + 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, DREF(ditems, scroll + choice), list_width, item_x, check_x); + + /* Highlight new item */ + choice = i; + print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1], status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice), list_width, item_x, check_x); + wmove(list, choice, check_x+1); /* Restore cursor to previous position */ + wrefresh(list); + } + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_PPAGE: /* can we go up? */ + if (scroll > height - 4) + scroll -= (height-4); + else + scroll = 0; + redraw_menu = TRUE; + if (!onlist) { + onlist = 1; + button = 0; + } + break; + + case KEY_NPAGE: /* can we go down a full page? */ + if (scroll + list_height >= item_no-1 - list_height) { + scroll = item_no - list_height; + if (scroll < 0) + scroll = 0; + } + else + scroll += list_height; + redraw_menu = TRUE; + if (!onlist) { + onlist = 1; + button = 0; + } + break; + + case KEY_HOME: /* go to the top */ + scroll = 0; + choice = 0; + redraw_menu = TRUE; + cursor_reset = TRUE; + onlist = 1; + break; + + case KEY_END: /* Go to the bottom */ + scroll = item_no - list_height; + if (scroll < 0) + scroll = 0; + choice = max_choice - 1; + redraw_menu = TRUE; + cursor_reset = TRUE; + onlist = 1; + break; + + case TAB: + case KEY_BTAB: + /* move to next component */ + if (onlist) { /* on list, next is ok button */ + onlist = 0; + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + ok_space = 1; + cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6; + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + ok_space = 3; + cancel_space = 15; + } + if (button) + wmove(dialog, y, x + cancel_space); + else + wmove(dialog, y, x + ok_space); + wrefresh(dialog); + break; + } + else if (button) { /* on cancel button, next is list */ + button = 0; + onlist = 1; + redraw_menu = TRUE; + break; + } + /* on ok button, next is cancel button, same as left/right case */ + + case KEY_LEFT: + case KEY_RIGHT: + onlist = 0; + button = !button; + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + ok_space = 1; + cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6; + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + ok_space = 3; + cancel_space = 15; + } + if (button) + wmove(dialog, y, x + cancel_space); + else + wmove(dialog, y, x + ok_space); + wrefresh(dialog); + break; + + case ' ': + case '\n': + case '\r': + if (!onlist) { + if (ditems) { + if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) { + int st; + WINDOW *save = dupwin(newscr); + + st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + if (st == DITEM_FAILURE) + continue; + } + } + else if (result) { + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcat(result, items[i*3]); + strcat(result, "\n"); + } + } + } + rval = button; + key = ESC; /* Bail out! */ + break; + } + + /* Let me outta here! */ + case ESC: + rval = -1; + break; + + /* Help! */ + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + + if (redraw_menu) { + getyx(list, old_y, old_x); + wclear(list); + + /* + * Re-draw a box around the list items. It is required + * if amount of list items is smaller than height of listbox. + * Otherwise un-redrawn field will be filled with default + * screen attributes instead of dialog attributes. + */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr); + + 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, DREF(ditems, scroll + i), list_width, item_x, check_x); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + + /* redraw buttons to fix highlighting */ + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + wnoutrefresh(dialog); + if (cursor_reset) { + wmove(list, choice, check_x+1); + cursor_reset = FALSE; + } + else { + wmove(list, old_y, old_x); + } + wrefresh(list); + redraw_menu = FALSE; + } + } + delwin(list); + delwin(dialog); + return rval; +} + + +/* + * Print list item + */ +static void +print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x) +{ + 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%c%c", me && me->lbra ? me->lbra : '[', + status ? me && me->mark ? me->mark : 'X' : ' ', + me && me->rbra ? me->rbra : ']'); + 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); + /* If have a selection handler for this, call it */ + if (me && me->selected) { + wrefresh(win); + me->selected(me, selected); + } +} +/* End of print_item() */ diff --git a/gnu/lib/libodialog/colors.h b/gnu/lib/libodialog/colors.h new file mode 100644 index 0000000..7cea0a0 --- /dev/null +++ b/gnu/lib/libodialog/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/libodialog/dialog.3 b/gnu/lib/libodialog/dialog.3 new file mode 100644 index 0000000..2e4b8fb --- /dev/null +++ b/gnu/lib/libodialog/dialog.3 @@ -0,0 +1,842 @@ +.\" +.\" Copyright (c) 1995, Jordan Hubbard +.\" +.\" All rights reserved. +.\" +.\" This manual page may be used, modified, copied, distributed, and +.\" sold, in both source and binary form provided that the above +.\" copyright and these terms are retained, verbatim, as the first +.\" lines of this file. Under no circumstances is the author +.\" responsible for the proper functioning of the software described herein +.\" nor does the author assume any responsibility for damages incurred with +.\" its use. +.\" +.\" $FreeBSD$ +.\" +.Dd January 1, 2000 +.Dt DIALOG 3 +.Os +.Sh NAME +.Nm draw_shadow , +.Nm draw_box , +.Nm line_edit , +.Nm strheight , +.Nm strwidth , +.Nm dialog_create_rc , +.Nm dialog_yesno , +.Nm dialog_noyes , +.Nm dialog_prgbox , +.Nm dialog_msgbox , +.Nm dialog_textbox , +.Nm dialog_menu , +.Nm dialog_checklist , +.Nm dialog_radiolist , +.Nm dialog_inputbox , +.Nm dialog_clear_norefresh , +.Nm dialog_clear , +.Nm dialog_update , +.Nm dialog_fselect , +.Nm dialog_notify , +.Nm dialog_mesgbox , +.Nm dialog_gauge , +.Nm init_dialog , +.Nm end_dialog , +.Nm use_helpfile , +.Nm use_helpline , +.Nm get_helpline , +.Nm restore_helpline , +.Nm dialog_ftree , +.Nm dialog_tree +.Nd provide a simple ncurses-based GUI interface +.Sh SYNOPSIS +.In dialog.h +.Ft "void" +.Fn draw_shadow "WINDOW *win" "int y" "int x" "int height" "int width" +.Ft "void" +.Fn draw_box "WINDOW *win" "int y" "int x" "int height" "int width" "chtype box" "chtype border" +.Ft "int" +.Fo line_edit +.Fa "WINDOW *dialog" +.Fa "int box_y" +.Fa "int box_x" +.Fa "int flen" +.Fa "int box_width" +.Fa "chtype attr" +.Fa "int first" +.Fa "unsigned char *result" +.Fa "int attr_mask" +.Fc +.Ft "int" +.Fn strheight "const char *p" +.Ft "int" +.Fn strwidth "const char *p" +.Ft "void" +.Fn dialog_create_rc "unsigned char *filename" +.Ft "int" +.Fn dialog_yesno "unsigned char *title" "unsigned char *prompt" "int height" "int width" +.Ft "int" +.Fn dialog_noyes "unsigned char *title" "unsigned char *prompt" "int height" "int width" +.Ft "int" +.Fn dialog_prgbox "unsigned char *title" "const unsigned char *line" "int height" "int width" "int pause" "int use_shell" +.Ft "int" +.Fn dialog_textbox "unsigned char *title" "unsigned char *file" "int height" "int width" +.Ft "int" +.Fo dialog_menu +.Fa "unsigned char *title" +.Fa "unsigned char *prompt" +.Fa "int height" +.Fa "int width" +.Fa "int menu_height" +.Fa "int cnt" +.Fa "void *it" +.Fa "unsigned char *result" +.Fa "int *ch" +.Fa "int *sc" +.Fc +.Ft "int" +.Fn dialog_checklist "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int list_height" "int cnt" "void *it" "unsigned char *result" +.Ft "int" +.Fn dialog_radiolist "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int list_height" "int cnt" "void *it" "unsigned char *result" +.Ft "int" +.Fn dialog_inputbox "unsigned char *title" "unsigned char *prompt" "int height" "int width" "unsigned char *result" +.Ft "char *" +.Fn dialog_fselect "char *dir" "char *fmask" +.Ft "int" +.Fn dialog_dselect "char *dir" "char *fmask" +.Ft "void" +.Fn dialog_notify "char *msg" +.Ft "int" +.Fn dialog_mesgbox "unsigned char *title" "unsigned char *prompt" "int height" "int width" +.Ft "void" +.Fn dialog_gauge "char *title" "char *prompt" "int y" "int x" "int height" "int width" "int perc" +.Ft "void" +.Fn use_helpfile "char *hfile" +.Ft "void" +.Fn use_helpline "char *hline" +.Ft "char *" +.Fn get_helpline "void" +.Ft "void" +.Fn dialog_clear_norefresh "void" +.Ft "void" +.Fn dialog_clear "void" +.Ft "void" +.Fn dialog_update "void" +.Ft "void" +.Fn init_dialog "void" +.Ft "void" +.Fn end_dialog "void" +.Ft "int" +.Fn dialog_ftree "unsigned char *filename" "unsigned char FS" "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int menu_height" "unsigned char **result" +.Ft "int" +.Fo dialog_tree +.Fa "unsigned char **names" +.Fa "int size" +.Fa "unsigned char FS" +.Fa "unsigned char *title" +.Fa "unsigned char *prompt" +.Fa "int height" +.Fa "int width" +.Fa "int menu_height" +.Fa "unsigned char **result" +.Fc +.Sh DESCRIPTION +The dialog library attempts to provide a fairly simplistic set of +fixed-presentation menus, input boxes, gauges, file requestors and +other general purpose GUI (a bit of a stretch, since it uses +ncurses) objects. +Since the library also had its roots in a +shell-script writer's utility (see the +.Xr dialog 1 +command), the +early API was somewhat primitively based on strings being passed in or +out and parsed. +This API was later extended to take either the +original arguments or arrays of +.Va dialogMenuItem +structures, +giving the user much more control over the internal behavior of each +control. +The +.Va dialogMenuItem +structure internals are public: +.Bd -literal -offset indent +typedef struct _dmenu_item { + char *prompt; + char *title; + int (*checked)(struct _dmenu_item *self); + int (*fire)(struct _dmenu_item *self); + int (*selected)(struct _dmenu_item *self, int is_selected); + void *data; + char lbra, mark, rbra; + long aux; +} dialogMenuItem; +.Ed +.Pp +The +.Dv prompt +and +.Dv title +strings are pretty much self-explanatory, +and the +.Va checked +and +.Va fire +function pointers provide optional +display and action hooks (the +.Dv data +variable being available for +the convenience of those hooks) when more tightly coupled feedback between +a menu object and user code is required. +The +.Va selected +hook also +allows you to verify whether or not a given item is selected (the cursor is +over it) for implementing pretty much any possible context-sensitive +behavior. +A number of clever tricks for simulating various kinds of item +types can also be done by adjusting the values of +.Va lbra +(default: '['), +.Va mark +(default: '*' for radio menus, 'X' for check menus) +and +.Va rbra +(default: ']') and declaring a reasonable +.Va checked +hook, +which should return TRUE for the +.Dq marked +state and FALSE for +.Dq unmarked . +The +.Va aux +field is not used internally, and is available for miscellaneous usage. +If an item has a +.Va fire +hook associated with it, it will also be called +whenever the item is "toggled" in some way and should return one of the +following codes: +.Bd -literal -offset 4n +#define DITEM_SUCCESS 0 /* Successful completion */ +#define DITEM_FAILURE 1 /* Failed to "fire" */ +.Ed +.Pp +The following flags are in the upper 16 bits of return status: +.Bd -literal -offset 4n +#define DITEM_LEAVE_MENU (1 << 16) +#define DITEM_REDRAW (1 << 17) +#define DITEM_RECREATE (1 << 18) +#define DITEM_RESTORE (1 << 19) +#define DITEM_CONTINUE (1 << 20) +.Ed +.Pp +Two special globals also exist for putting a dialog at any arbitrary +X,Y location (the early designers rather short-sightedly made no provisions +for this). +If set to zero, the default centering behavior will be in +effect. +.Pp +Below is a short description of the various functions: +.Pp +The +.Fn draw_shadow +function draws a shadow in curses window +.Va win +using the dimensions of +.Va x , y , width +and +.Va height . +.Pp +The +.Fn draw_box +function draws a bordered box using the dimensions of +.Va x , y , width +and +.Va height . +The attributes from +.Va box +and +.Va border +are used, if specified, while painting the box and border regions of the +object. +.Pp +The +.Fn line_edit +function invokes a simple line editor with an edit box of dimensions +.Va box_x , box_y +and +.Va box_width . +The field length is constrained by +.Va flen , +starting at the +.Va first +character specified and +optionally displayed with character attributes +.Va attr . +The string being edited is stored in +.Va result . +Returns 0 on success, 1 on Cancel, and -1 on failure or ESC. +.Pp +The +.Fn strheight +function returns the height of string in +.Va p , +counting newlines. +.Pp +The +.Fn strwidth +function returns the width of string in +.Va p , +counting newlines. +.Pp +The +.Fn dialog_create_rc +function dumps dialog library settings into +.Pa filename +for later retrieval as defaults. +Returns 0 on success, -1 on failure. +.Pp +The +.Fn dialog_yesno +function displays a text box using +.Va title +and +.Va prompt +strings of dimensions +.Va height +and +.Va width . +Also paint a pair of +.Em Yes +and +.Em \&No +buttons at the bottom. +The default selection is +.Em Yes . +If the +.Em Yes +button is chosen, return FALSE. +If +.Em \&No , +return TRUE. +.Pp +The +.Fn dialog_noyes +function is the same as +.Fn dialog_yesno , +except the default selection is +.Em \&No . +.Pp +The +.Fn dialog_prgbox +function displays a text box of dimensions +.Va height +and +.Va width +containing the output of command +.Va line . +If +.Va use_shell +is TRUE, +.Va line +is passed as an argument to +.Xr sh 1 , +otherwise it is simply passed to +.Xr exec 3 . +If +.Va pause +is TRUE, a final confirmation requestor will be put up when execution +terminates. +Returns 0 on success, -1 on failure. +.Pp +The +.Fn dialog_textbox +function displays a text box containing the contents of +.Va file +with dimensions of +.Va height +and +.Va width . +.Pp +The +.Fn dialog_menu +function displays a menu of dimensions +.Va height +and +.Va width +with an optional internal menu height of +.Va menu_height . +The +.Va cnt +and +.Va it +arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. +To use the +older and traditional interface, +.Va cnt +should be a positive +integer representing the number of string pointer pairs to find in +.Va it +(which should be of type +.Ft char "**" ) , +the strings are +expected to be in prompt and title order for each item and the +.Va result +parameter is expected to point to an array where the +prompt string of the item selected will be copied. +To use the newer +interface, +.Va cnt +should be a +.Va negative +integer representing the number of +.Va dialogMenuItem +structures pointed to by +.Va it +(which should be of type +.Vt dialogMenuItem "*" ) , +one structure per item. +In the new interface, the +.Va result +variable is used as a simple boolean (not a pointer) and should be NULL if +.Va it +only points to menu items and the default OK and Cancel buttons are desired. +If +.Va result +is non-NULL, then +.Va it +is actually expected to point 2 locations +.Va past +the start of the menu item list. +.Va it +is then expected to +point to an item representing the Cancel button, from which the +.Va prompt +and +.Va fire +actions are used to override the default behavior, and +.Va it +to the same for the OK button. +.Pp +Using either API behavior, the +.Va ch +and +.Va sc +values may be passed in to preserve current +item selection and scroll position values across calls. +.Pp +The +.Fn dialog_checklist +function displays a menu of dimensions +.Va height +and +.Va width +with an +optional internal menu height of +.Va list_height . +The +.Va cnt +and +.Va it +arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. +To use the +older and traditional interface, +.Va cnt +should be a positive +integer representing the number of string pointer tuples to find in +.Va it +(which should be of type +.Ft "char **" ) , +the strings are +expected to be in prompt, title and state ("on" or "off") order for +each item and the +.Va result +parameter is expected to point to an +array where the prompt string of the item(s) selected will be +copied. +To use the newer interface, +.Va cnt +should be a +.Em negative +integer representing the number of +.Ft dialogMenuItem +structures pointed to by +.Va it +(which should be of type +.Ft "dialogMenuItem *" ) , +one structure per item. +In the new interface, +the +.Va result +variable is used as a simple boolean (not a pointer) +and should be NULL if +.Va it +only points to menu items and the default OK and Cancel +buttons are desired. +If +.Va result +is non-NULL, then +.Va it +is actually expected to +point 2 locations +.Va past +the start of the menu item list. +.Va it +is then expected to point to an item representing the Cancel +button, from which the +.Va prompt +and +.Va fire +actions are used to override the default behavior, and +.Va it +to the same for the OK button. +.Pp +In the standard API model, the menu supports the selection of multiple items, +each of which is marked with an `X' character to denote selection. +When +the OK button is selected, the prompt values for all items selected are +concatenated into the +.Va result +string. +.Pp +In the new API model, it is not actually necessary to preserve +"checklist" semantics at all since practically everything about how +each item is displayed or marked as "selected" is fully configurable. +You could have a single checklist menu that actually contained a group +of items with "radio" behavior, "checklist" behavior and standard menu +item behavior. +The only reason to call +.Fn dialog_checklist +over +.Fn dialog_radiolist +in the new API model is to inherit the base +behavior, you are no longer constrained by it. +.Pp +Returns 0 on success, 1 on Cancel, and -1 on failure or ESC. +.Pp +The +.Fn dialog_radiolist +function displays a menu of dimensions +.Va height +and +.Va width +with an +optional internal menu height of +.Va list_height . +The +.Va cnt +and +.Va it +arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. +To use the +older and traditional interface, +.Va cnt +should be a positive +integer representing the number of string pointer tuples to find in +.Va it +(which should be of type +.Ft "char **" ) , +the strings are +expected to be in prompt, title and state ("on" or "off") order for +each item and the +.Va result +parameter is expected to point to an +array where the prompt string of the item(s) selected will be +copied. +To use the newer interface, +.Va cnt +should be a +.Dv negative +integer representing the number of +.Ft dialogMenuItem +structures pointed to by +.Va it +(which should be of type +.Ft "dialogMenuItem *" , +one structure per item. +In the new interface, +the +.Va result +variable is used as a simple boolean (not a pointer) +and should be NULL if +.Va it +only points to menu items and the default OK and Cancel +buttons are desired. +If +.Va result +is non-NULL, then +.Va it +is actually expected to point 2 locations +.Va past +the start of the menu item list. +.Va it +is then expected to point to an item representing the Cancel +button, from which the +.Va prompt +and +.Va fire +actions are used to override the default behavior, and +.Va it +does the same for the traditional OK button. +.Pp +In the standard API model, the menu supports the selection of only one +of multiple items, the currently active item marked with an `*' +character to denote selection. +When the OK button is selected, the +prompt value for this item is copied into the +.Va result +string. +.Pp +In the new API model, it is not actually necessary to preserve +"radio button" semantics at all since practically everything about how +each item is displayed or marked as "selected" is fully configurable. +You could have a single radio menu that actually contained a group +of items with "checklist" behavior, "radio" behavior and standard menu +item behavior. +The only reason to call +.Fn dialog_radiolist +over +.Fn dialog_checklistlist +in the new API model is to inherit the base +behavior. +.Pp +Returns 0 on success, 1 on Cancel and -1 on failure or ESC. +.Pp +The +.Fn dialog_inputbox +function displays a single-line text input field in a box displaying +.Va title +and +.Va prompt +of dimensions +.Va height +and +.Va width . +The field entered is stored in +.Va result . +.Pp +Returns 0 on success, -1 on failure or ESC. +.Pp +The +.Fn dialog_fselect +function brings up a file selector dialog starting at +.Va dir +and showing only those file names +matching +.Va fmask . +.Pp +Returns filename selected or NULL. +.Pp +The +.Fn dialog_dselect +function brings up a directory selector dialog starting at +.Va dir +and showing only those directory names +matching +.Va fmask . +.Pp +Returns directory name selected or NULL. +.Pp +The +.Fn dialog_notify +function brings up a generic "hey, you!" notifier dialog containing +.Va msg . +.Pp +The +.Fn dialog_mesgbox +function displays a notifier dialog, but with more control over +.Va title , +.Va prompt , +.Va width +and +.Va height . +This object will also wait for user confirmation, unlike +.Fn dialog_notify . +.Pp +Returns 0 on success, -1 on failure. +.Pp +The +.Fn dialog_gauge +function displays a horizontal bar-graph style gauge. +A value of +.Em 100 +for +.Em perc +constitutes a full gauge, a value of +.Em 0 +an empty one. +.Pp +The +.Fn use_helpfile +function for any menu supporting context sensitive help, invokes the text box +object on this file whenever the +.Em F1 +key is pressed. +.Pp +The +.Fn use_helpline +function displays this line of helpful text below any menu being displayed. +.Pp +The +.Fn get_helpline +function gets the current value of the helpful text line. +.Pp +The +.Fn dialog_clear_norefresh +function clears the screen back to the dialog background color, but do not +refresh the contents just yet. +.Pp +The +.Fn dialog_clear +function clears the screen back to the dialog background color immediately. +.Pp +The +.Fn dialog_update +function does any pending screen refreshes now. +.Pp +The +.Fn init_dialog +function initializes the dialog library (call this routine before any other +dialog API calls). +.Pp +The +.Fn end_dialog +function shuts down the dialog library (call this if you need to get back to +sanity). +.Pp +The +.Fn dialog_ftree +function shows a tree described by the data from the file +.Pa filename . +The data in the file should look like +.Xr find 1 +output. +For the +.Xr find 1 +output, the field separator +.Va FS +will be +.Dq \&/ . +If +.Va height +and +.Va width +are positive numbers, they set the absolute +size of the whole +.Fn dialog_ftree +box. +If +.Va height +and +.Va width +are negative numbers, the size of the +.Fn dialog_ftree +box will be calculated automatically. +.Va menu_height +sets the height of the tree subwindow inside the +.Fn dialog_ftree +box and must be set. +.Va title +is shown centered on the upper border of the +.Fn dialog_ftree +box. +.Va prompt +is shown inside the +.Fn dialog_ftree +box above the tree subwindow and can contain +.Ql \e\&n +to split lines. +One can navigate in +the tree by pressing UP/DOWN or +.Sm off +.So \&+ Sc \&/ So \&- Sc , +.Sm on +PG_UP/PG_DOWN or +.Sm off +.So b Sc \&/SPACE +.Sm on +and +HOME/END or +.Sm off +.So g Sc \&/ So G Sc . +.Sm on +A leaf of the +tree is selected by pressing TAB or LEFT/RIGHT the OK +button and pressing ENTER. +filename may contain data like +.Xr find 1 +output, as well as like the output of +.Xr find 1 +with +.Fl d +option. +Some of the transient paths to the leaves of the tree may +be absent. +Such data is corrected when fed from filename. +.Pp +The function returns 0 and a pointer to the selected leaf (to the path to +the leaf from the root of the tree) into result, if the OK button was +selected. +The memory allocated for the building of the tree is freed on +exiting +.Fn dialog_ftree . +The memory for the result line should be freed +later manually, if necessary. +If the Cancel button was selected, the +function returns 1. +In case of exiting +.Fn dialog_ftree +on ESC, the function returns -1. +.Pp +The +.Fn dialog_tree +function returns the same results as +.Fn dialog_ftree . +If 0 is returned, result will contain a pointer from the array +.Va names . +.\" \fBdialog_tree\fR displays the tree very much like \fBdialog_ftree\fR does, +.\" with some exceptions. The source data for the building of the tree is an +.\" array \fBnames\fR of paths to the leaves (should be similar to \fBfind(1)\fR +.\" output) of the size \fBsize\fR. However, there is no correction of data like +.\" in \fBdialog_ftree\fR. Thus, to display a correct tree, the array must +.\" already contain correct data. Besides, in each session every unique use of +.\" \fBdialog_tree\fR is kept in memory, and later, when calling +.\" \fBdialog_tree\fR with the same \fBnames\fR, \fBsize\fR, \fBFS\fR, +.\" \fBheight\fR, \fBwidth\fR and \fBmenu_height\fR the position of the cursor +.\" in the tree subwindow is restored. +.Sh SEE ALSO +.Xr dialog 1 , +.Xr ncurses 3 +.Sh HISTORY +These functions appeared in +.Fx 2.0 +as the +.Xr dialog 1 +command and were soon split into a separate library +and command by +.An Andrey Chernov . +.An Marc van Kempen +implemented most of the extra controls and objects, +.An Jordan Hubbard +added the dialogMenuItem renovations and this man page and +.An Anatoly A. Orehovsky +implemented +.Fn dialog_ftree +and +.Fn dialog_tree . +.Sh AUTHORS +.An -nosplit +The primary author would appear to be +.An Savio Lam Aq lam836@cs.cuhk.hk +with contributions over the years by +.An Stuart Herbert Aq S.Herbert@sheffield.ac.uk , +.An Marc van Kempen Aq wmbfmk@urc.tue.nl , +.An Andrey Chernov Aq ache@FreeBSD.org , +.An Jordan Hubbard Aq jkh@FreeBSD.org +and +.An Anatoly A. Orehovsky Aq tolik@mpeks.tomsk.su . +.Sh BUGS +Sure! diff --git a/gnu/lib/libodialog/dialog.h b/gnu/lib/libodialog/dialog.h new file mode 100644 index 0000000..369b139 --- /dev/null +++ b/gnu/lib/libodialog/dialog.h @@ -0,0 +1,211 @@ +#ifndef _DIALOG_H_INCLUDE +#define _DIALOG_H_INCLUDE + +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * + * 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. + * + * $FreeBSD$ + * + */ + +#define HAVE_NCURSES + +#ifdef HAVE_NCURSES +#include <ncurses.h> + +#else + +#ifdef ultrix +#include <cursesX.h> +#else +#include <curses.h> +#endif + +#endif + +/* special return codes for `fire' actions */ +#define DITEM_STATUS(flag) ((flag) & 0x0000FFFF) +#define DITEM_SUCCESS 0 +#define DITEM_FAILURE 1 + +/* Flags - returned in upper 16 bits of return status */ +#define DITEM_LEAVE_MENU (1 << 16) +#define DITEM_REDRAW (1 << 17) +#define DITEM_RECREATE (1 << 18) +#define DITEM_RESTORE (1 << 19) +#define DITEM_CONTINUE (1 << 20) + +/* Attributes as used by entry fields right now */ +#define DITEM_NO_ECHO 0x0001 + + +/* negative offsets for buttons in item lists, if specified */ +#define OK_BUTTON -2 +#define CANCEL_BUTTON -1 + +/* for use in describing more exotic behaviors */ +typedef struct _dmenu_item { + char *prompt; + char *title; + int (*checked)(struct _dmenu_item *self); + int (*fire)(struct _dmenu_item *self); + void (*selected)(struct _dmenu_item *self, int is_selected); + void *data; + char lbra, mark, rbra; + long aux; +} dialogMenuItem; + +#define VERSION "0.4" +#define MAX_LEN 4096 + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +extern int DialogX, DialogY, DialogInputAttrs; + +/* + * 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 + +extern chtype attributes[]; + +#ifdef HAVE_NCURSES +extern bool use_shadow; +void draw_shadow(WINDOW *win, int y, int x, int height, int width); +#endif +void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border); +int line_edit(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result, int attr_mask); +int strheight(const char *p); +int strwidth(const char *p); + +void dialog_create_rc(unsigned char *filename); +int dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int width); +int dialog_noyes(unsigned char *title, unsigned char *prompt, int height, int width); +int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell); +int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause); +int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width); +int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, + int item_no, void *itptr, unsigned char *result, int *ch, int *sc); +int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int item_no, void *itptr, unsigned char *result); +int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int item_no, void *itptr, unsigned char *result); +int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result); +void dialog_clear_norefresh(void); +void dialog_clear(void); +void dialog_update(void); +void init_dialog(void); +void end_dialog(void); + +/* Additions to libdialog */ +char *dialog_fselect(char *dir, char *fmask); +int dialog_dselect(char *dir, char *fmask); +void dialog_notify(char *msg); +int dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width); +void use_helpfile(char *helpfile); +void use_helpline(char *helpline); +char *get_helpline(void); +void restore_helpline(char *helpline); +void dialog_gauge(char *title, char *prompt, int y, int x, int height, int width, int perc); + +/* + * Display a tree menu from file + * + * filename - file with like find(1) output + * FS - fields separator + * title - title of dialog box + * prompt - prompt text into dialog box + * height - height of dialog box + * width - width of dialog box + * menu_height - height of menu box + * result - pointer to char array + * + * return values: + * -1 - ESC pressed + * 0 - Ok, result set (must be freed later) + * 1 - Cancel + */ +int dialog_ftree(unsigned char *filename, unsigned char FS, + unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + unsigned char **result); + +/* + * Display a tree menu from array + * + * names - array with like find(1) output + * size - size of array + * FS - fields separator + * title - title of dialog box + * prompt - prompt text into dialog box + * height - height of dialog box + * width - width of dialog box + * menu_height - height of menu box + * result - pointer to char array + * + * return values: + * -1 - ESC pressed + * 0 - Ok, result set + * 1 - Cancel + */ + +int dialog_tree(unsigned char **names, int size, unsigned char FS, + unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + unsigned char **result); + +#endif /* _DIALOG_H_INCLUDE */ diff --git a/gnu/lib/libodialog/dialog.priv.h b/gnu/lib/libodialog/dialog.priv.h new file mode 100644 index 0000000..06c01a5 --- /dev/null +++ b/gnu/lib/libodialog/dialog.priv.h @@ -0,0 +1,183 @@ +/* + * 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> +#include <termios.h> + +#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) + +#ifndef MIN +#define MIN(x,y) (x < y ? x : y) +#endif +#ifndef MAX +#define MAX(x,y) (x > y ? x : y) +#endif + +#ifndef ctrl +#define ctrl(a) ((a) - 'a' + 1) +#endif + +#ifndef HAVE_NCURSES +#ifndef ACS_ULCORNER +#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 */ + +/* Travel key conventions */ +#define KEY_IS_UP(key) ((key) == KEY_UP || (key) == '-' || key == '\020' /* ^P */) +#define KEY_IS_DOWN(key) ((key) == KEY_DOWN || (key) == '+' || key == '\016' /* ^N */) + +/* + * 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; +#endif + +#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 height, int width, int maxwidth, + int y, int x, int center, int rawmode); +void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected); +FILE *raw_popen(const char *program, char * const *argv, const char *type); +int raw_pclose(FILE *iop); +void display_helpfile(void); +void display_helpline(WINDOW *w, int y, int width); +void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no, int box_x, + int box_y, int tag_x, int cur_x, int cur_y); + diff --git a/gnu/lib/libodialog/dir.c b/gnu/lib/libodialog/dir.c new file mode 100644 index 0000000..5348c2f --- /dev/null +++ b/gnu/lib/libodialog/dir.c @@ -0,0 +1,549 @@ +/**************************************************************************** + * + * Program: dir.c + * Author: Marc van Kempen + * desc: Directory routines, sorting and reading + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + ****************************************************************************/ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <unistd.h> /* XXX for _POSIX_VERSION ifdefs */ + +#if !defined sgi && !defined _POSIX_VERSION +#include <sys/dir.h> +#endif +#if defined __sun__ +#include <sys/dirent.h> +#endif +#if defined sgi || defined _POSIX_VERSION +#include <dirent.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fnmatch.h> +#include <sys/param.h> +#include "dir.h" + +/**************************************************************************** + * + * local prototypes + * + ****************************************************************************/ + +void toggle_dotfiles(void); +int show_dotfiles(void); +int dir_alphasort(const void *d1, const void *d2); +int dir_sizesort(const void *d1, const void *d2); +int dir_datesort(const void *d1, const void *d2); +int dir_extsort(const void *d1, const void *d2); + +/**************************************************************************** + * + * global variables + * + ****************************************************************************/ + + +/* This is user-selectable, I've set them fixed for now however */ + +void *_sort_func = dir_alphasort; +static int _showdotfiles = TRUE; + +/**************************************************************************** + * + * Functions + * + ****************************************************************************/ + +int +dir_select_nd( +#if defined __linux__ + const struct dirent *d +#else + struct dirent *d +#endif +) +/* + * desc: allways include a directory entry <d>, except + * for the current directory and other dot-files + * keep '..' however. + * pre: <d> points to a dirent + * post: returns TRUE if d->d_name != "." else FALSE + */ +{ + if (strcmp(d->d_name, ".")==0 || + (d->d_name[0] == '.' && strlen(d->d_name) > 1 && d->d_name[1] != '.')) { + return(FALSE); + } else { + return(TRUE); + } +}/* dir_select_nd() */ + + +int +dir_select( +#ifdef __linux__ + const struct dirent *d +#else + struct dirent *d +#endif +) +/* + * desc: allways include a directory entry <d>, except + * for the current directory + * pre: <d> points to a dirent + * post: returns TRUE if d->d_name != "." else FALSE + */ +{ + if (strcmp(d->d_name, ".")==0) { /* don't include the current directory */ + return(FALSE); + } else { + return(TRUE); + } +} /* dir_select() */ + +int +dir_select_root_nd( +#ifdef __linux__ + const struct dirent *d +#else + struct dirent *d +#endif +) +/* + * desc: allways include a directory entry <d>, except + * for the current directory and the parent directory. + * Also skip any other dot-files. + * pre: <d> points to a dirent + * post: returns TRUE if d->d_name[0] != "." else FALSE + */ +{ + if (d->d_name[0] == '.') { /* don't include the current directory */ + return(FALSE); /* nor the parent directory */ + } else { + return(TRUE); + } +} /* dir_select_root_nd() */ + + +int +dir_select_root( +#ifdef __linux__ + const struct dirent *d +#else + struct dirent *d +#endif +) +/* + * desc: allways include a directory entry <d>, except + * for the current directory and the parent directory + * pre: <d> points to a dirent + * post: returns TRUE if d->d_name[0] != "." else FALSE + */ +{ + if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) { + return(FALSE); + } else { + return(TRUE); + } +}/* dir_select_root() */ + + +#ifdef NO_ALPHA_SORT +int +alphasort(const void *d1, const void *d2) +/* + * desc: a replacement for what should be in the library + */ +{ + return(strcmp(((struct dirent *) d1)->d_name, + ((struct dirent *) d2)->d_name)); +} /* alphasort() */ +#endif + +int +dir_alphasort(const void *d1, const void *d2) +/* + * desc: compare d1 and d2, but put directories always first + * put '..' always on top + * + */ +{ + DirList *f1 = ((DirList *) d1), + *f2 = ((DirList *) d2); + struct stat *s1 = &(f1->filestatus); + struct stat *s2 = &(f2->filestatus); + + /* check for '..' */ + if (strcmp(((DirList *) d1)->filename, "..") == 0) { + return(-1); + } + if (strcmp(((DirList *) d2)->filename, "..") == 0) { + return(1); + } + + /* put directories first */ + if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) { + return(strcmp(f1->filename, f2->filename)); + }; + if (s1->st_mode & S_IFDIR) { + return(-1); + } + if (s2->st_mode & S_IFDIR) { + return(1); + } + return(strcmp(f1->filename, f2->filename)); + +} /* dir_alphasort() */ + + +int +dir_sizesort(const void *d1, const void *d2) +/* + * desc: compare d1 and d2, but put directories always first + * + */ +{ + DirList *f1 = ((DirList *) d1), + *f2 = ((DirList *) d2); + struct stat *s1 = &(f1->filestatus); + struct stat *s2 = &(f2->filestatus); + + /* check for '..' */ + if (strcmp(((DirList *) d1)->filename, "..") == 0) { + return(-1); + } + if (strcmp(((DirList *) d2)->filename, "..") == 0) { + return(1); + } + + /* put directories first */ + if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) { + return(s1->st_size < s2->st_size ? + -1 + : + s1->st_size >= s2->st_size); + }; + if (s1->st_mode & S_IFDIR) { + return(-1); + } + if (s2->st_mode & S_IFDIR) { + return(1); + } + return(s1->st_size < s2->st_size ? + -1 + : + s1->st_size >= s2->st_size); + +} /* dir_sizesort() */ + +int +dir_datesort(const void *d1, const void *d2) +/* + * desc: compare d1 and d2 on date, but put directories always first + */ +{ + DirList *f1 = ((DirList *) d1), + *f2 = ((DirList *) d2); + struct stat *s1 = &(f1->filestatus); + struct stat *s2 = &(f2->filestatus); + + + /* check for '..' */ + if (strcmp(((DirList *) d1)->filename, "..") == 0) { + return(-1); + } + if (strcmp(((DirList *) d2)->filename, "..") == 0) { + return(1); + } + + /* put directories first */ + if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) { + return(s1->st_mtime < s2->st_mtime ? + -1 + : + s1->st_mtime >= s2->st_mtime); + }; + if (s1->st_mode & S_IFDIR) { + return(-1); + } + if (s2->st_mode & S_IFDIR) { + return(1); + } + return(s1->st_mtime < s2->st_mtime ? + -1 + : + s1->st_mtime >= s2->st_mtime); + +} /* dir_datesort() */ + + +int +null_strcmp(char *s1, char *s2) +/* + * desc: compare strings allowing NULL pointers + */ +{ + if ((s1 == NULL) && (s2 == NULL)) { + return(0); + } + if (s1 == NULL) { + return(-1); + } + if (s2 == NULL) { + return(1); + } + return(strcmp(s1, s2)); +} /* null_strcmp() */ + + +int +dir_extsort(const void *d1, const void *d2) +/* + * desc: compare d1 and d2 on extension, but put directories always first + * extension = "the characters after the last dot in the filename" + * pre: d1 and d2 are pointers to DirList type records + * post: see code + */ +{ + DirList *f1 = ((DirList *) d1), + *f2 = ((DirList *) d2); + struct stat *s1 = &(f1->filestatus); + struct stat *s2 = &(f2->filestatus); + char *ext1, *ext2; + int extf, ret; + + + /* check for '..' */ + if (strcmp(((DirList *) d1)->filename, "..") == 0) { + return(-1); + } + if (strcmp(((DirList *) d2)->filename, "..") == 0) { + return(1); + } + + + /* find the first extension */ + + ext1 = f1->filename + strlen(f1->filename); + extf = FALSE; + while (!extf && (ext1 > f1->filename)) { + extf = (*--ext1 == '.'); + } + if (!extf) { + ext1 = NULL; + } else { + ext1++; + } + /* ext1 == NULL if there's no "extension" else ext1 points */ + /* to the first character of the extension string */ + + /* find the second extension */ + + ext2 = f2->filename + strlen(f2->filename); + extf = FALSE; + while (!extf && (ext2 > f2->filename)) { + extf = (*--ext2 == '.'); + } + if (!extf) { + ext2 = NULL; + } else { + ext2++; + } + /* idem as for ext1 */ + + if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) { + ret = null_strcmp(ext1, ext2); + if (ret == 0) { + return(strcmp(f1->filename, f2->filename)); + } else { + return(ret); + } + }; + if (s1->st_mode & S_IFDIR) { + return(-1); + } + if (s2->st_mode & S_IFDIR) { + return(1); + } + ret = null_strcmp(ext1, ext2); + if (ret == 0) { + return(strcmp(f1->filename, f2->filename)); + } else { + return(ret); + } + +} /* dir_extsort() */ + + +void +get_dir(char *dirname, char *fmask, DirList **dir, int *n) +/* + * desc: get the files in the current directory + * pre: <dir> == NULL + * post: <dir> contains <n> dir-entries + */ +{ + char cwd[MAXPATHLEN]; + char buf[256]; + struct dirent **dire; + struct stat status; + int i, j, nb; + long d; + + + getcwd(cwd, MAXPATHLEN); + if (strcmp(cwd, "/") == 0) { /* we are in the root directory */ + if (show_dotfiles()) { + *n = scandir(dirname, &dire, dir_select_root, alphasort); + } else { + *n = scandir(dirname, &dire, dir_select_root_nd, alphasort); + } + } else { + if (show_dotfiles()) { + *n = scandir(dirname, &dire, dir_select, alphasort); + } else { + *n = scandir(dirname, &dire, dir_select_nd, alphasort); + } + } + + /* There is the possibility that we have entered a directory */ + /* which we are not allowed to read, scandir thus returning */ + /* -1 for *n. */ + /* Actually I should also check for lack of memory, but I'll */ + /* let my application happily crash if this is the case */ + /* Solution: */ + /* manually insert the parent directory as the only */ + /* directory entry, and return. */ + + if (*n == -1) { + *n = 1; + *dir = (DirList *) malloc(sizeof(DirList)); + strcpy((*dir)[0].filename, ".."); + lstat("..", &status); + (*dir)[0].filestatus = status; + (*dir)[0].link = FALSE; + return; + } + + *dir = (DirList *) malloc( *n * sizeof(DirList) ); + d = 0; + i = 0; + j = 0; + while (j<*n) { + lstat(dire[j]->d_name, &status); + /* check if this file is to be included */ + /* always include directories, the rest is subject to fmask */ + if (S_ISDIR(status.st_mode) + || fnmatch(fmask, dire[j]->d_name, FNM_NOESCAPE) != FNM_NOMATCH) { + strcpy((*dir)[i].filename, dire[j]->d_name); + (*dir)[i].filestatus = status; + if ((S_IFMT & status.st_mode) == S_IFLNK) { /* handle links */ + (*dir)[i].link = TRUE; + stat(dire[j]->d_name, &status); + nb = readlink(dire[j]->d_name, buf, sizeof(buf) - 1); + if (nb == -1) { + printf("get_dir(): Error reading link: %s\n", dire[j]->d_name); + exit(-1); + } else { + (*dir)[i].linkname = malloc(sizeof(char) * nb + 1); + strncpy((*dir)[i].linkname, buf, nb); + (*dir)[i].linkname[nb] = 0; + } + (*dir)[i].filestatus = status; + } else { + (*dir)[i].link = FALSE; + (*dir)[i].linkname = NULL; + } + i++; + } else { + /* skip this entry */ + } + j++; + } + *n = i; + + /* sort the directory with the directory names on top */ + qsort((*dir), *n, sizeof(DirList), _sort_func); + + /* Free the allocated memory */ + for (i=0; i<*n; i++) { + free(dire[i]); + } + free(dire); + + return; +}/* get_dir() */ + + +void +FreeDir(DirList *d, int n) +/* + * desc: free the dirlist d + * pre: d != NULL + * post: memory allocated to d has been released + */ +{ + int i; + + if (d) { + for (i=0; i<n; i++) { + if (d[i].linkname) { + free(d[i].linkname); + } + } + free(d); + } else { + printf("dir.c:FreeDir(): d == NULL\n"); + exit(-1); + } + + return; +} /* FreeDir() */ + +void +toggle_dotfiles(void) +/* + * desc: toggle visibility of dot-files + */ +{ + _showdotfiles = !_showdotfiles; + + return; +} /* toggle_dotfiles() */ + +int +show_dotfiles(void) +/* + * desc: return the value of _showdotfiles + */ +{ + return(_showdotfiles); +} /* show_dotfiles() */ + +void +set_dotfiles(int b) +/* + * desc: set the value of _showdotfiles + */ +{ + _showdotfiles = b; + + return; +} /* set_dotfiles() */ diff --git a/gnu/lib/libodialog/dir.h b/gnu/lib/libodialog/dir.h new file mode 100644 index 0000000..eadc0c5 --- /dev/null +++ b/gnu/lib/libodialog/dir.h @@ -0,0 +1,38 @@ +/* + * include file for dir.c + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/dirent.h> + +typedef struct DirList { /* structure to hold the directory entries */ + char filename[MAXNAMLEN]; /* together with the stat-info per file */ + struct stat filestatus; /* filename, or the name to which it points */ + int link; /* is it a link ? */ + char *linkname; /* the name of the file the link points to */ +} DirList; + +#ifndef TRUE +#define TRUE (1) +#endif +#ifndef FALSE +#define FALSE (0) +#endif + +void get_dir(char *dirname, char *fmask, DirList **dir, int *n); +void get_filenames(DirList *d, int n, char ***names, int *nf); +void FreeDir(DirList *d, int n); diff --git a/gnu/lib/libodialog/fselect.c b/gnu/lib/libodialog/fselect.c new file mode 100644 index 0000000..6669edc --- /dev/null +++ b/gnu/lib/libodialog/fselect.c @@ -0,0 +1,402 @@ +/* + * program: fselect.c + * author: Marc van Kempen (wmbfmk@urc.tue.nl) + * Desc: File selection routine + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> +#include <dialog.h> +#include "ui_objects.h" +#include "dir.h" +#include "dialog.priv.h" + +/* + * Local prototypes + */ + +char *dialog_dfselect(char *dir, char *fmask, int is_fselect); + +/* + * Functions + */ + +void +get_directories(DirList *d, int n, char ***names, int *nd) +/* + * Desc: return the directorienames in <dir> as an array in + * <names>, the # of entries in <nd>, memory allocated + * to *names should be freed when done with it. + */ +{ + int i; + + /* count the directories, which are in front */ + *nd = 0; + while ((*nd < n) && (S_ISDIR(d[*nd].filestatus.st_mode))) (*nd)++; + *names = (char **) malloc( *nd * sizeof(char *) ); + for (i=0; i<*nd; i++) { + (*names)[i] = (char *) malloc( strlen(d[i].filename) + 1); + strcpy((*names)[i], d[i].filename); + } + + return; +} /* get_directories() */ + +void +get_filenames(DirList *d, int n, char ***names, int *nf) +/* + * Desc: return the filenames in <dir> as an arry in + * <names>, the # of entries in <nf>, memory allocated + * to *names should be freed when done. + */ +{ + int nd, i; + + /* the # of regular files is the total # of files - # of directories */ + /* count the # of directories */ + nd = 0; + while ((nd < n) && (S_ISDIR(d[nd].filestatus.st_mode))) nd++; + + *names = (char **) malloc( (n-nd) * sizeof(char *) ); + *nf = n - nd; + for (i=0; i<*nf; i++) { + (*names)[i] = (char *) malloc( strlen(d[i+nd].filename) + 1); + strcpy((*names)[i], d[i+nd].filename); + } + + return; +} /* get_filenames() */ + +void +FreeNames(char **names, int n) +/* + * Desc: free the space occupied by names + */ +{ + int i; + + /* free the space occupied by names */ + for (i=0; i<n; i++) { + free(names[i]); + } + free(names); + + return; +} /* FreeNames() */ + +int +dialog_dselect_old(void) +/* + * Desc: starting from the current directory, + * choose a new current directory + */ +{ + DirList *d = NULL; + char **names, old_dir[MAXPATHLEN]; + WINDOW *ds_win; + ButtonObj *okbut, *cancelbut; + ListObj *dirs_obj; + StringObj *dir_obj; + char o_dir[MAXPATHLEN]; + struct ComposeObj *obj = NULL; + int n, nd, okbutton, cancelbutton, + quit, cancel, ret; + + ds_win = newwin(LINES-8, COLS-30, 4, 15); + if (ds_win == NULL) { + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", + LINES-8, COLS-30, 4, 15); + exit(1); + } + draw_box(ds_win, 0, 0, LINES-8, COLS-30, dialog_attr, border_attr); + wattrset(ds_win, dialog_attr); + mvwaddstr(ds_win, 0, (COLS-30)/2 - 9, " Directory Select "); + draw_shadow(stdscr, 4, 15, LINES-8, COLS-30); + display_helpline(ds_win, LINES-9, COLS-30); + + /* the Directory string input field */ + getcwd(o_dir, MAXPATHLEN); + dir_obj = NewStringObj(ds_win, "Directory:", o_dir, 1, 2, COLS-34, MAXPATHLEN-1); + AddObj(&obj, STRINGOBJ, (void *) dir_obj); + + /* the list of directories */ + get_dir(".", "*", &d, &n); + get_directories(d, n, &names, &nd); + dirs_obj = NewListObj(ds_win, "Directories:", names, o_dir, 5, 2, + LINES-15, COLS-48, nd); + AddObj(&obj, LISTOBJ, (void *) dirs_obj); + + /* the Ok-button */ + okbutton = FALSE; + okbut = NewButtonObj(ds_win, "Continue", &okbutton, 7, COLS-45); + AddObj(&obj, BUTTONOBJ, (void *) okbut); + + /* the Cancel-button */ + cancelbutton = FALSE; + cancelbut = NewButtonObj(ds_win, "Return", &cancelbutton, 11, COLS-44); + AddObj(&obj, BUTTONOBJ, (void *) cancelbut); + + quit = FALSE; + cancel = FALSE; + strcpy(old_dir, o_dir); + while (!quit) { + ret = PollObj(&obj); + switch(ret) { + case SEL_BUTTON: + if (okbutton) { + quit = TRUE; + } + if (cancelbutton) { + quit = TRUE; + cancel = TRUE; + } + break; + case SEL_CR: + if (strcmp(old_dir, o_dir)) { + /* the directory was changed, cd into it */ + if (chdir(o_dir)) { + dialog_notify("Could not change into directory"); + strcpy(o_dir, old_dir); + } else { + getcwd(o_dir, MAXPATHLEN); + strcpy(old_dir, o_dir); + } + RefreshStringObj(dir_obj); + } + get_dir(".", "*", &d, &n); + FreeNames(names, nd); + get_directories(d, n, &names, &nd); + UpdateListObj(dirs_obj, names, nd); + if (((obj->prev)->obj == (void *) dirs_obj)) { + obj=obj->prev; + } + break; + case SEL_ESC: + quit = TRUE; + cancel = TRUE; + break; + case KEY_F(1): + display_helpfile(); + break; + } + } + + FreeNames(names, nd); + DelObj(obj); + delwin(ds_win); + + return(cancel); + +} /* dialog_dselect() */ + +int +dialog_dselect(char *dir, char *fmask) +/* + * Desc: Choose a directory + */ +{ + if (dialog_dfselect(dir, fmask, FALSE)) { + return(FALSE); /* esc or cancel was pressed */ + } else { + return(TRUE); /* directory was selected */ + } +} /* dialog_dselect() */ + +char * +dialog_fselect(char *dir, char *fmask) +/* + * Desc: Choose a file from a directory + */ +{ + return(dialog_dfselect(dir, fmask, TRUE)); +} /* dialog_fselect() */ + +char * +dialog_dfselect(char *dir, char *fmask, int is_fselect) +/* + * Desc: choose a file from the directory <dir>, which + * initially display files with the mask <filemask> + * pre: <dir> is the initial directory + * only files corresponding to the mask <fmask> are displayed + * post: returns NULL if no file was selected + * else returns pointer to filename, space is allocated, should + * be freed after use. + */ +{ + DirList *d = NULL; + char msg[512]; + char **fnames, **dnames, *ret_name; + WINDOW *fs_win; + int n, nd, nf, ret; + StringObj *fm_obj, *dir_obj, *sel_obj; + char o_fm[255], o_dir[MAXPATHLEN], o_sel[MAXPATHLEN]; + char old_fmask[255], old_dir[MAXPATHLEN]; + ListObj *dirs_obj, *files_obj; + struct ComposeObj *obj = NULL, *o; + int quit, cancel; + ButtonObj *okbut_obj, *canbut_obj; + int ok_button, cancel_button; + + if (chdir(dir)) { + sprintf(msg, "Could not move into specified directory: %s", dir); + dialog_notify(msg); + return(NULL); + } + getcwd(o_dir, MAXPATHLEN); + + /* setup the fileselect-window and initialize its components */ + fs_win = newwin(LINES-2, COLS-20, 1, 10); + if (fs_win == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", + LINES-2, COLS-20, 2, 10); + exit(1); + } + draw_box(fs_win, 0, 0, LINES-2, COLS-20, dialog_attr, border_attr); + wattrset(fs_win, dialog_attr); + if (is_fselect) { + mvwaddstr(fs_win, 0, (COLS-20)/2 - 7, " File Select "); + } else { + mvwaddstr(fs_win, 0, (COLS-20)/2 - 9, " Directory Select "); + } + draw_shadow(stdscr, 1, 10, LINES-2, COLS-20); + display_helpline(fs_win, LINES-3, COLS-20); + + /* Filemask entry */ + strcpy(o_fm, fmask); + fm_obj = NewStringObj(fs_win, "Filemask:", o_fm, 1, 2, 19, 255); + AddObj(&obj, STRINGOBJ, (void *) fm_obj); + + /* Directory entry */ + dir_obj = NewStringObj(fs_win, "Directory:", o_dir, 1, 22, COLS-44, 255); + AddObj(&obj, STRINGOBJ, (void *) dir_obj); + + /* Directory list */ + get_dir(".", fmask, &d, &n); /* read the entire directory */ + get_directories(d, n, &dnames, &nd); /* extract the dir-entries */ + if (is_fselect) { + dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2, + LINES-16, (COLS-20)/2-2, nd); + } else { + dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2, + LINES-12, (COLS-20)/2-2, nd); + } + AddObj(&obj, LISTOBJ, (void *) dirs_obj); + + /* Filenames list */ + get_filenames(d, n, &fnames, &nf); /* extract the filenames */ + if (is_fselect) { + files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1, + LINES-16, (COLS-20)/2-3, nf); + } else { + files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1, + LINES-12, (COLS-20)/2-3, nf); + } + AddObj(&obj, LISTOBJ, (void *) files_obj); + + if (is_fselect) { + /* Selection entry */ + o_sel[0] = '\0'; + sel_obj = NewStringObj(fs_win, "Selection:", o_sel, LINES-10, 2, COLS-24, 255); + AddObj(&obj, STRINGOBJ, (void *) sel_obj); + } + + /* Ok button */ + ok_button = FALSE; + okbut_obj = NewButtonObj(fs_win, "Ok", &ok_button, LINES-6, 20); + AddObj(&obj, BUTTONOBJ, (void *) okbut_obj); + + /* Cancel button */ + cancel_button = FALSE; + canbut_obj = NewButtonObj(fs_win, "Cancel", &cancel_button, LINES-6, 30); + AddObj(&obj, BUTTONOBJ, (void *) canbut_obj); + + /* Make sure all objects on the window are drawn */ + wrefresh(fs_win); + keypad(fs_win, TRUE); + + /* Start the reading */ + o = obj; + strcpy(old_fmask, o_fm); + strcpy(old_dir, o_dir); + quit = FALSE; + cancel = FALSE; + while (!quit) { + ret = PollObj(&o); + switch(ret) { + case SEL_CR: + if (strcmp(old_fmask, o_fm) || strcmp(old_dir, o_dir)) { + /* reread directory and update the listobjects */ + if (strcmp(old_dir, o_dir)) { /* dir entry was changed */ + if (chdir(o_dir)) { + dialog_notify("Could not change into directory"); + strcpy(o_dir, old_dir); + } else { + getcwd(o_dir, MAXPATHLEN); + strcpy(old_dir, o_dir); + } + RefreshStringObj(dir_obj); + } else { /* fmask entry was changed */ + strcpy(old_fmask, o_fm); + } + get_dir(".", o_fm, &d, &n); + FreeNames(dnames, nd); + get_directories(d, n, &dnames, &nd); + UpdateListObj(dirs_obj, dnames, nd); + FreeNames(fnames, nf); + get_filenames(d, n, &fnames, &nf); + UpdateListObj(files_obj, fnames, nf); + if (((o->prev)->obj == (void *) dirs_obj)) { + o=o->prev; + } + } + break; + case SEL_BUTTON: + /* check which button was pressed */ + if (ok_button) { + quit = TRUE; + } + if (cancel_button) { + quit = TRUE; + cancel = TRUE; + } + break; + case SEL_ESC: + quit = TRUE; + cancel = TRUE; + break; + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + } + DelObj(obj); + FreeNames(dnames, nd); + FreeNames(fnames, nf); + delwin(fs_win); + + if (cancel || (strlen(o_sel) == 0)) { + return(NULL); + } else { + ret_name = (char *) malloc( strlen(o_sel) + 1 ); + strcpy(ret_name, o_sel); + return(ret_name); + } +} /* dialog_fselect() */ + diff --git a/gnu/lib/libodialog/gauge.c b/gnu/lib/libodialog/gauge.c new file mode 100644 index 0000000..d8138f6 --- /dev/null +++ b/gnu/lib/libodialog/gauge.c @@ -0,0 +1,79 @@ +/* + * gauge.c + * + * progress indicator for libdialog + * + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdlib.h> +#include <string.h> + +#include "dialog.h" + +void +dialog_gauge(char *title, char *prompt, int y, int x, + int height, int width, int perc) +/* + * Desc: display a progress bar, progress indicated by <perc> + */ +{ + WINDOW *gw; + int glen, i; + char percs[5]; + + gw = newwin(height, width, y, x); + if (!gw) { + fprintf(stderr, "dialog_gauge: Error creating window (%d, %d, %d, %d)", + height, width, y, x); + exit(-1); + } + + draw_box(gw, 0, 0, height, width, dialog_attr, border_attr); + draw_shadow(stdscr, y, x, height, width); + + wattrset(gw, title_attr); + if (title) { + wmove(gw, 0, (width - strlen(title))/2 - 1); + waddstr(gw, "[ "); + waddstr(gw, title); + waddstr(gw, " ]"); + } + wattrset(gw, dialog_attr); + if (prompt) { + wmove(gw, 1, (width - strlen(prompt))/2 - 1); + waddstr(gw, prompt); + } + + draw_box(gw, 2, 2, 3, width-4, dialog_attr, border_attr); + glen = (int) ((float) perc/100 * (width-6)); + + wattrset(gw, dialog_attr); + sprintf(percs, "%3d%%", perc); + wmove(gw, 5, width/2 - 2); + waddstr(gw, percs); + + wattrset(gw, A_BOLD); + wmove(gw, 3, 3); + for (i=0; i<glen; i++) waddch(gw, ' '); + + wrefresh(gw); + delwin(gw); + + return; +} /* dialog_gauge() */ + diff --git a/gnu/lib/libodialog/help.c b/gnu/lib/libodialog/help.c new file mode 100644 index 0000000..de49c6a --- /dev/null +++ b/gnu/lib/libodialog/help.c @@ -0,0 +1,194 @@ +/*************************************************************** + * + * Program: help.c + * Author: Marc van Kempen + * Desc: get help + * + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + ***************************************************************/ + +#include <stdlib.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <dialog.h> + +static char _helpfilebuf[MAXPATHLEN]; +static char _helplinebuf[77]; /* limit the helpline to 76 characters */ +static char *_helpfile = NULL; +static char *_helpline = NULL; + +/****************************************************************** + * + * helpfile routines + * + ******************************************************************/ + +void +use_helpfile(char *hfile) +/* + * desc: set the helpfile to be opened on pressing F1 to <helpfile> + */ +{ + if (hfile != NULL) { + _helpfile = _helpfilebuf; + strcpy(_helpfile, hfile); + } else { + _helpfile = NULL; + } + + return; +} /* use_helpfile() */ + +void +display_helpfile(void) +/* + * desc: display the current helpfile in a window + */ +{ + WINDOW *w; + FILE *f; + struct stat sb; + char msg[80], *buf; + static int in_help = FALSE; + char *savehline = NULL; + + if (in_help) return; /* dont call help when you're in help */ + + if (_helpfile != NULL) { + if ((w = dupwin(newscr)) == NULL) { + dialog_notify("No memory to dup previous screen\n"); + return; + } + if ((f = fopen(_helpfile, "r")) == NULL) { + sprintf(msg, "Can't open helpfile : %s\n", _helpfile); + dialog_notify(msg); + return; + } + if (fstat(fileno(f), &sb)) { + sprintf(msg, "Can't stat helpfile : %s\n", _helpfile); + dialog_notify(msg); + return; + } + if ((buf = (char *) malloc( sb.st_size )) == NULL) { + sprintf(msg, "Could not malloc space for helpfile : %s\n", _helpfile); + dialog_notify(msg); + return; + } + if (fread(buf, 1, sb.st_size, f) != sb.st_size) { + sprintf(msg, "Could not read entire help file : %s", _helpfile); + dialog_notify(msg); + free(buf); + return; + } + buf[sb.st_size] = 0; + in_help = TRUE; + savehline = get_helpline(); + use_helpline("Use arrowkeys, PgUp, PgDn, Home and End to move through text"); + dialog_mesgbox("Online help", buf, LINES-4, COLS-4); + restore_helpline(savehline); + in_help = FALSE; + touchwin(w); + wrefresh(w); + delwin(w); + free(buf); + } else { + /* do nothing */ + } + + return; +} /* display_helpfile() */ + + +/****************************************************************** + * + * helpline routines + * + ******************************************************************/ + +void +use_helpline(char *hline) +/* + * desc: set the helpline to printed in dialogs + */ +{ + if (hline) { + _helpline = _helplinebuf; + if (strlen(hline) > 76) { + /* only display the first 76 characters in the helpline */ + strncpy(_helpline, hline, 76); + _helpline[76] = 0; + } else { + strcpy(_helpline, hline); + } + } else { + _helpline = NULL; + } + + return; +} /* use_helpline() */ + +void +display_helpline(WINDOW *w, int y, int width) +/* + * desc: display the helpline at the given coordinates <y, x> in the window <w> + */ +{ + if (_helpline != NULL) { + if (strlen(_helpline) > width - 6) { + _helpline[width - 6] = 0; + } + wmove(w, y, (int) (width - strlen(_helpline)- 4) / 2); + wattrset(w, title_attr); + waddstr(w, "[ "); + waddstr(w, _helpline); + waddstr(w, " ]"); + } else { + /* do nothing */ + } + + return; +} + +char * +get_helpline(void) +/* + * desc: allocate new space, copy the helpline to it and return a pointer to it + */ +{ + char *hlp; + + if (_helpline) { + hlp = (char *) malloc( strlen(_helpline) + 1 ); + strcpy(hlp, _helpline); + } else { + hlp = NULL; + } + + return(hlp); +} /* get_helpline() */ + +void +restore_helpline(char *helpline) +/* + * Desc: set the helpline to <helpline> and free the space allocated to it + */ +{ + use_helpline(helpline); + free(helpline); + + return; +} /* restore_helpline() */ diff --git a/gnu/lib/libodialog/inputbox.c b/gnu/lib/libodialog/inputbox.c new file mode 100644 index 0000000..1f61ed5 --- /dev/null +++ b/gnu/lib/libodialog/inputbox.c @@ -0,0 +1,190 @@ +/* + * 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.h> +#include "dialog.priv.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, j, x, y, box_y, box_x, box_width, first, + key = 0, button = -1; + unsigned char instr[MAX_LEN+1]; + WINDOW *dialog; + + if (height < 0) + height = strheight(prompt)+2+4; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j) + 4; + } + width = MAX(width,24); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width)/2; + y = DialogY ? DialogY : (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); + + /* 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); + + display_helpline(dialog, height-1, width); + + x = width/2-11; + y = height-2; + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + + first = 1; + strcpy(instr, result); + wattrset(dialog, dialog_attr); + + while (key != ESC) { + + if (button == -1) { /* Input box selected */ + key = line_edit(dialog, box_y, box_x, -1, box_width, inputbox_attr, first, instr, DialogInputAttrs); + first = 0; + } + else + key = wgetch(dialog); + + 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); + 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); + break; + } + break; + case ' ': + case '\n': + case '\r': + delwin(dialog); + if (button < 1) + strcpy(result, instr); + return (button == -1 ? 0 : button); + case ESC: + break; + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + } + + delwin(dialog); + return -1; /* ESC pressed */ +} +/* End of dialog_inputbox() */ diff --git a/gnu/lib/libodialog/kernel.c b/gnu/lib/libodialog/kernel.c new file mode 100644 index 0000000..9ed5eac --- /dev/null +++ b/gnu/lib/libodialog/kernel.c @@ -0,0 +1,536 @@ +/* + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define __DIALOG_MAIN__ + +#include <dialog.h> +#include <err.h> +#include "dialog.priv.h" +#ifdef HAVE_NCURSES +#include "colors.h" +#endif + +/* These are two "secret" globals that can be fiddled to make a dialog + * come up someplace other than a "centered" calculation for X,Y + */ +int DialogX, DialogY; + +/* This "secret" global allows you to change the behavior of an input field */ +int DialogInputAttrs; + +/* + * Do some initialization for dialog + */ +void init_dialog(void) +{ + + if (issetugid()) { + errx(1, "libdialog is unsafe to use in setugid applications"); + } + +#if defined(LOCALE) + (void) setlocale(LC_ALL, ""); +#endif + +#ifdef HAVE_NCURSES + if (parse_rc() == -1) /* Read the configuration file */ + exit(-1); +#endif + + if (initscr() == NULL) { /* Init curses */ + fprintf(stderr, "\nCurses initialization error.\n"); + exit(-1); + } + keypad(stdscr, TRUE); + cbreak(); + noecho(); + +#ifdef HAVE_NCURSES + if (use_colors || use_shadow) /* Set up colors */ + color_setup(); +#endif + + /* Set screen to screen attribute */ + dialog_clear_norefresh(); + DialogX = DialogY = 0; +} +/* 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 height, int width, int maxwidth, int y, int x, int center, int rawmode) +{ + int cur_x, cur_y, i; + unsigned char tempstr[MAX_LEN+1], *word, *tempptr, *tempptr1; + chtype ostuff[132], attrs = 0, init_bottom = 0; + + wsetscrreg(win, y, height); + getyx(win, cur_y, cur_x); + + strncpy(tempstr, prompt, MAX_LEN); + tempstr[MAX_LEN] = '\0'; + if ((!rawmode && strstr(tempstr, "\\n") != NULL) || + (strchr(tempstr, '\n') != NULL)) { /* Prompt contains "\n" or '\n' */ + word = tempstr; + while (1) { + tempptr = rawmode ? NULL : 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; + if (++cur_y > height) { + cur_y--; + if (!init_bottom) { + for (i = 0; i < x; i++) + ostuff[i] = mvwinch(win, cur_y, i); + for (i = width; i < maxwidth; i++) + ostuff[i] = mvwinch(win, cur_y, i); + attrs = getattrs(win); + init_bottom = 1; + } + scrollok(win, TRUE); + scroll(win); + scrollok(win, FALSE); + wmove(win, cur_y, 0); + for (i = 0; i < x; i++) { + wattrset(win, ostuff[i]&A_ATTRIBUTES); + waddch(win, ostuff[i]); + } + wattrset(win, attrs); + for ( ; i < width; i++) + waddch(win, ' '); + for ( ; i < maxwidth; i++) { + wattrset(win, ostuff[i]&A_ATTRIBUTES); + waddch(win, ostuff[i]); + } + wattrset(win, attrs); + wrefresh(win); + } + wmove(win, cur_y, cur_x = x); + } + waddstr(win, word); + } + else if (center && strlen(tempstr) <= width-x*2) { /* If prompt is short */ + wmove(win, cur_y, (width - strlen(tempstr)) / 2); + waddstr(win, tempstr); + } + else if (!center && strlen(tempstr) <= width-cur_x) { /* If prompt is short */ + waddstr(win, tempstr); + } + else { + char *p = tempstr; + + /* Print prompt word by word, wrap around if necessary */ + while ((word = strsep(&p, "\t\n ")) != NULL) { + int loop; + unsigned char sc; + + if (*word == '\0') + continue; + do { + loop = 0; + if (cur_x+strlen(word) >= width+1) { /* wrap around to next line */ + if (x+strlen(word) >= width+1) { + sc = word[width-cur_x-1]; + word[width-cur_x-1] = '\0'; + wmove(win, cur_y, cur_x); + waddstr(win, word); + word[width-cur_x-1] = sc; + word += width-cur_x-1; + getyx(win, cur_y, cur_x); + loop = 1; + } + cur_y++; + cur_x = x; + if (cur_y > height) { + cur_y--; + if (!init_bottom) { + for (i = 0; i < x; i++) + ostuff[i] = mvwinch(win, cur_y, i); + for (i = width; i < maxwidth; i++) + ostuff[i] = mvwinch(win, cur_y, i); + attrs = getattrs(win); + init_bottom = 1; + } + scrollok(win, TRUE); + scroll(win); + scrollok(win, FALSE); + wmove(win, cur_y, 0); + for (i = 0; i < x; i++) { + wattrset(win, ostuff[i]&A_ATTRIBUTES); + waddch(win, ostuff[i]); + } + wattrset(win, attrs); + for ( ; i < width; i++) + waddch(win, ' '); + for ( ; i < maxwidth; i++) { + wattrset(win, ostuff[i]&A_ATTRIBUTES); + waddch(win, ostuff[i]); + } + wattrset(win, attrs); + wrefresh(win); + } + } + } + while(loop); + 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, selected ? "[" : " "); + temp = strspn(label, " "); + label += temp; + 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_active_attr : button_inactive_attr); + waddstr(win, label+1); + waddstr(win, selected ? "]" : " "); + 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,sx,sy; + chtype attrs; + + if (has_colors()) { /* Whether terminal supports color? */ + getbegyx(win,sy,sx); + attrs = getattrs(win); + if (y+height < getmaxy(win)) { + /* small touch */ + wattrset(win, A_INVIS); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + if (i+x+2 < getmaxx(win)) + waddch(win, ' '); + /* end touch */ + wattrset(win, shadow_attr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + if (i+x+2 < getmaxx(win)) + waddch(win, mvwinch(newscr, sy+y+height, sx+x+2+i) & A_CHARTEXT); + } + if (x+width < getmaxx(win)) { + for (i = y + 1; i < y + height + 1; i++) { + if (i < getmaxy(win)) { + /* small touch */ + wattrset(win, A_INVIS); + wmove(win, i, x + width); + waddch(win, ' '); + if (x+width+1 < getmaxx(win)) + waddch(win, ' '); + /* end touch */ + wattrset(win, shadow_attr); + wmove(win, i, x + width); + waddch(win, mvwinch(newscr, sy+i, sx+x+width) & A_CHARTEXT); + if (x+width+1 < getmaxx(win)) + waddch(win, mvwinch(newscr, sy+i, sx+x+width+1) & A_CHARTEXT); + } + } + } + wattrset(win, attrs); + wnoutrefresh(win); + } +} +/* End of draw_shadow() */ +#endif + +void dialog_clear_norefresh(void) +{ + attr_clear(stdscr, LINES, COLS, screen_attr); + touchwin(stdscr); + wnoutrefresh(stdscr); +} + +void dialog_clear(void) +{ + dialog_clear_norefresh(); + doupdate(); +} + +void dialog_update(void) +{ + refresh(); +} + +void end_dialog(void) +{ + endwin(); +} + +int strwidth(const char *p) +{ + int i = 0, len, incr; + const char *start, *s, *s1, *s2; + + for (start = s = p; ; start = (s += incr)) { + s1 = strchr(s, '\n'); + s2 = strstr(s, "\\n"); + if (s2 == NULL) + s = s1; + else if (s1 == NULL) + s = s2; + else + s = MIN(s1, s2); + if (s == NULL) + break; + incr = 1 + (s == s2); + len = s - start; + if (len > i) + i = len; + } + len = strlen(start); + if (len > i) + i = len; + return i; +} + +int strheight(const char *p) +{ + int i = 1, incr; + const char *s, *s1, *s2; + + for (s = p; ; s += incr) { + s1 = strchr(s, '\n'); + s2 = strstr(s, "\\n"); + if (s2 == NULL) + s = s1; + else if (s1 == NULL) + s = s2; + else + s = MIN(s1, s2); + if (s == NULL) + break; + incr = 1 + (s == s2); + i++; + } + return i; +} + +void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no, + int box_x, int box_y, int tag_x, int cur_x, int cur_y) +{ + 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); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1); + wattrset(dialog, scroll+menu_height < item_no ? darrow_attr : menubox_border_attr); + waddch(dialog, scroll+menu_height < item_no ? ACS_DARROW : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2); + waddch(dialog, scroll+menu_height < item_no ? '(' : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 3); + waddch(dialog, scroll+menu_height < item_no ? '+' : ACS_HLINE); + wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 4); + waddch(dialog, scroll+menu_height < item_no ? ')' : ACS_HLINE); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ +} + diff --git a/gnu/lib/libodialog/lineedit.c b/gnu/lib/libodialog/lineedit.c new file mode 100644 index 0000000..7bfe0e0 --- /dev/null +++ b/gnu/lib/libodialog/lineedit.c @@ -0,0 +1,213 @@ +/* + * Changes Copyright (C) 1995 by Andrey A. Chernov, Moscow + * + * Original Copyright: + * + * 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.h> +#include "dialog.priv.h" + +static void redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask); + +/* + * Line editor + */ +int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, chtype attr, int first, unsigned char *result, int attr_mask) +{ + int i, key; + chtype old_attr; + static int input_x, scroll; + static unsigned char instr[MAX_LEN+1]; + unsigned char erase_char = erasechar(); + unsigned char kill_char = killchar(); +#ifdef notyet + unsignec char werase_char = cur_term->Ottyb.c_cc[VWERASE]; +#endif + + old_attr = getattrs(dialog); + keypad(dialog, TRUE); + + if (first) { + memset(instr, 0, sizeof(instr)); + strcpy(instr, result); + i = strlen(instr); +/* input_x = i % box_width;*/ + input_x = (i > box_width) ? box_width - 1 : i; +/* scroll = i - input_x;*/ + scroll = (i > box_width) ? i - box_width + 1: 0; + } + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + + for (;;) { + wattrset(dialog, attr); + wrefresh(dialog); + key = wgetch(dialog); + switch (key) { + case ctrl('q'): + goto ret; + break; + case KEY_F(1): + display_helpfile(); + break; + case TAB: + case KEY_BTAB: + case KEY_UP: + case KEY_DOWN: + case ESC: + case '\r': + case '\n': + for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--) + instr[i] = '\0'; + if (key == '\r') + key = '\n'; + goto ret; + case '\025': + case '\030': + kill_it: + input_x = scroll = 0; + /* fall through */ + case '\013': + case KEY_EOL: + memset(instr + scroll + input_x, '\0', sizeof(instr) - scroll - input_x); + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + continue; + case '\001': + case KEY_HOME: + input_x = scroll = 0; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + continue; + case '\005': + 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; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + continue; + case '\002': + case KEY_LEFT: + if (input_x || scroll) { + if (!input_x) { + int oldscroll = scroll; + scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1); + input_x = oldscroll - 1 - scroll; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + } else { + input_x--; + wmove(dialog, box_y, input_x + box_x); + } + } else + beep(); + continue; + case '\006': + case KEY_RIGHT: + if ( scroll+input_x < MAX_LEN + && (flen < 0 || scroll+input_x < flen) + ) { + if (!instr[scroll+input_x]) + instr[scroll+input_x] = ' '; + if (input_x == box_width-1) { + scroll++; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + } + else { + wmove(dialog, box_y, input_x + box_x); + waddch(dialog, instr[scroll+input_x]); + input_x++; + } + } else + beep(); /* Alarm user about overflow */ + continue; + case '\b': + case '\177': + case KEY_BACKSPACE: + erase_it: + if (input_x || scroll) { + i = strlen(instr); + memmove(instr+scroll+input_x-1, instr+scroll+input_x, i-(scroll+input_x)+1); + if (!input_x) { + int oldscroll = scroll; + scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1); + input_x = oldscroll - 1 - scroll; + } else + input_x--; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + } else + beep(); + continue; + case '\004': + case KEY_DC: + for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--) + instr[i] = '\0'; + i++; + if (i == 0) { + beep(); + continue; + } + memmove(instr+scroll+input_x, instr+scroll+input_x+1, i-(scroll+input_x)); + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + continue; + default: + if (CCEQ(key, erase_char)) + goto erase_it; + if (CCEQ(key, kill_char)) + goto kill_it; + 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 && (flen < 0 || scroll+input_x < flen)) { + if (flen < 0 || i < flen) + memmove(instr+scroll+input_x+1, instr+scroll+input_x, i-(scroll+input_x)); + instr[scroll+input_x] = key; + if (input_x == box_width-1 && (flen < 0 || i < flen)) + scroll++; + else + input_x++; + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask); + } else + beep(); /* Alarm user about overflow */ + continue; + } + } + } +ret: + redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, TRUE, attr_mask); + wrefresh(dialog); + strcpy(result, instr); + return key; +} + +static void +redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask) +{ + int i, fix_len; + + wattrset(dialog, fexit ? old_attr : attr); + wmove(dialog, box_y, box_x); + fix_len = flen >= 0 ? MIN(flen-scroll,box_width) : box_width; + for (i = 0; i < fix_len; i++) + waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' '); + wattrset(dialog, old_attr); + for ( ; i < box_width; i++) + waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' '); + wmove(dialog, box_y, input_x + box_x); +} diff --git a/gnu/lib/libodialog/menubox.c b/gnu/lib/libodialog/menubox.c new file mode 100644 index 0000000..a01acd5 --- /dev/null +++ b/gnu/lib/libodialog/menubox.c @@ -0,0 +1,469 @@ +/* + * menubox.c -- implements the menu box + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * + * 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.h" +#include <err.h> +#include <ncurses.h> + +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected, dialogMenuItem *me, int menu_width, int tag_x, int item_x); + +#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL) + +/* + * 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 cnt, void *it, unsigned char *result, int *ch, int *sc) +{ + int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button, choice, + l, k, scroll, max_choice, item_no, redraw_menu = FALSE; + char okButton, cancelButton; + int rval = 0, ok_space, cancel_space; + WINDOW *dialog, *menu; + unsigned char **items = NULL; + dialogMenuItem *ditems; + int menu_width, tag_x, item_x; + +draw: + choice = ch ? *ch : 0; + scroll = sc ? *sc : 0; + button = 0; + + /* If item_no is a positive integer, use old item specification format */ + if (cnt >= 0) { + items = it; + ditems = NULL; + item_no = cnt; + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(cnt); + ditems = it; + if (!items) + items = (unsigned char **)alloca((item_no * 2) * sizeof(unsigned char *)); + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + items[i*2] = ditems[i].prompt; + items[i*2 + 1] = ditems[i].title; + } + } + max_choice = MIN(menu_height, item_no); + + tag_x = 0; + item_x = 0; + /* Find length of longest item in order to center menu */ + for (i = 0; i < item_no; i++) { + l = strlen(items[i * 2]); + for (j = 0; j < item_no; j++) { + k = strlen(items[j * 2 + 1]); + tag_x = MAX(tag_x, l + k + 2); + } + item_x = MAX(item_x, l); + } + if (height < 0) + height = strheight(prompt) + menu_height + 4 + 2; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i, j); + width = MAX(width, tag_x + 4) + 4; + } + width = MAX(width, 24); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width) / 2; + y = DialogY ? DialogY : (LINES - height) / 2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x); + return -1; + } + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE); + + 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); + if (menu == NULL) { + delwin(dialog); + endwin(); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + return -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 = menu_width > tag_x + 1 ? (menu_width - tag_x) / 2 : 1; + item_x = menu_width > item_x + 4 ? tag_x + item_x + 2 : menu_width - 3; + + /* Print the menu */ + for (i = 0; i < max_choice; i++) + print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i, i == choice, DREF(ditems, scroll + i), menu_width, tag_x, item_x); + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); + + display_helpline(dialog, height - 1, width); + + x = width / 2 - 11; + y = height - 2; + + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } + + wrefresh(dialog); + while (key != ESC) { + key = wgetch(dialog); + + /* Shortcut to OK? */ + if (toupper(key) == okButton) { + if (ditems) { + if (result && ditems[OK_BUTTON].fire) { + int status; + WINDOW *save; + + save = dupwin(newscr); + status = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]); + if (status & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + } + else if (result) + strcpy(result, items[(scroll + choice) * 2]); + rval = 0; + key = ESC; /* Punt! */ + break; + } + + /* Shortcut to cancel? */ + if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + int status; + WINDOW *save; + + save = dupwin(newscr); + status = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]); + if (status & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + rval = 1; + key = ESC; /* Run away! */ + break; + } + + /* Check if key pressed matches first character of any item tag in menu */ + for (i = 0; i < max_choice; i++) + if (key < 0x100 && key != ' ' && toupper(key) == toupper(items[(scroll + i) * 2][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || KEY_IS_UP(key) || KEY_IS_DOWN(key)) { + if (key >= '1' && key <= MIN('9', '0'+max_choice)) + i = key - '1'; + else if (KEY_IS_UP(key)) { + if (!choice) { + if (scroll) { + /* 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, DREF(ditems, scroll), menu_width, tag_x, item_x); + scrollok(menu, TRUE); + wscrl(menu, -1); + scrollok(menu, FALSE); + } + scroll--; + print_item(menu, items[scroll * 2], items[scroll * 2 + 1], 0, TRUE, DREF(ditems, scroll), menu_width, tag_x, item_x); + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (KEY_IS_DOWN(key)) { + if (choice == max_choice - 1) { + if (scroll + choice < item_no - 1) { + /* 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, DREF(ditems, scroll + max_choice - 1), menu_width, tag_x, item_x); + 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, DREF(ditems, scroll + max_choice - 1), menu_width, tag_x, item_x); + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); + 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, DREF(ditems, scroll + choice), menu_width, tag_x, item_x); + + /* Highlight new item */ + choice = i; + print_item(menu, items[(scroll + choice) * 2], items[(scroll + choice) * 2 + 1], choice, TRUE, DREF(ditems, scroll + choice), menu_width, tag_x, item_x); + wnoutrefresh(menu); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_PPAGE: + if (scroll > height - 4) { /* can we go up? */ + scroll -= (height - 4); + } else { + scroll = 0; + } + redraw_menu = TRUE; + break; + + case KEY_NPAGE: + if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */ + scroll = item_no - menu_height; + if (scroll < 0) + scroll = 0; + } else { + scroll += menu_height; + } + redraw_menu = TRUE; + break; + + case KEY_HOME: + scroll = 0; + choice = 0; + redraw_menu = TRUE; + break; + + case KEY_END: + scroll = item_no - menu_height; + if (scroll < 0) + scroll = 0; + choice = max_choice - 1; + redraw_menu = TRUE; + break; + + case KEY_BTAB: + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = !button; + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + ok_space = 1; + cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6; + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + ok_space = 3; + cancel_space = 15; + } + if (button) + wmove(dialog, y, x+cancel_space); + else + wmove(dialog, y, x+ok_space); + wrefresh(dialog); + break; + + case ' ': + case '\r': + case '\n': + if (!button) { + /* A fire routine can do just about anything to the screen, so be prepared + to accept some hints as to what to do in the aftermath. */ + if (ditems) { + if (ditems[scroll + choice].fire) { + int status; + WINDOW *save; + + save = dupwin(newscr); + status = ditems[scroll + choice].fire(&ditems[scroll + choice]); + if (status & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + if (status & DITEM_CONTINUE) + continue; + else if (status & DITEM_LEAVE_MENU) { + /* Allow a fire action to take us out of the menu */ + key = ESC; + break; + } + else if (status & DITEM_RECREATE) { + delwin(menu); + delwin(dialog); + dialog_clear(); + goto draw; + } + } + } + else if (result) + strcpy(result, items[(scroll+choice)*2]); + } + rval = button; + key = ESC; + break; + + case ESC: + rval = -1; + break; + + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + + /* save info about menu item position */ + if (ch) + *ch = choice; + if (sc) + *sc = scroll; + + if (redraw_menu) { + for (i = 0; i < max_choice; i++) { + print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i, i == choice, DREF(ditems, scroll + i), menu_width, tag_x, item_x); + } + wnoutrefresh(menu); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + redraw_menu = FALSE; + } + } + delwin(menu); + delwin(dialog); + return rval; +} + + +/* + * Print menu item + */ +static void +print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected, dialogMenuItem *me, int menu_width, int tag_x, int item_x) +{ + int i; + + if (tag == NULL) + errx(1, "bad parameter to print_item()\n"); + + /* 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); + waddnstr(win, tag + 1, item_x - tag_x - 3); + wmove(win, choice, item_x); + wattrset(win, selected ? item_selected_attr : item_attr); + waddnstr(win, item, menu_width - item_x - 1); + /* If have a selection handler for this, call it */ + if (me && me->selected) { + wrefresh(win); + me->selected(me, selected); + } +} +/* End of print_item() */ diff --git a/gnu/lib/libodialog/msgbox.c b/gnu/lib/libodialog/msgbox.c new file mode 100644 index 0000000..41d78c8 --- /dev/null +++ b/gnu/lib/libodialog/msgbox.c @@ -0,0 +1,346 @@ +/* + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.h" + + +/* local prototypes */ +static int getnlines(unsigned char *buf); +static void print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll); +static void print_perc(WINDOW *win, int y, int x, float p); + + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause) +{ + int i, j, x, y, key = 0; + WINDOW *dialog; + + if (height < 0) + height = strheight(prompt)+2+2*(!!pause); + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j)+4; + } + if (pause) + width = MAX(width,10); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width)/2; + y = DialogY ? DialogY : (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + + if (title != NULL) { + wattrset(dialog, title_attr); + wmove(dialog, 0, (width - strlen(title))/2 - 1); + waddch(dialog, ' '); + waddstr(dialog, title); + waddch(dialog, ' '); + } + wattrset(dialog, dialog_attr); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); + + 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, ' '); + display_helpline(dialog, height-1, width); + print_button(dialog, " OK ", height-2, width/2-6, TRUE); + wrefresh(dialog); + while (key != ESC && key != '\n' && key != ' ' && key != '\r') + key = wgetch(dialog); + if (key == '\r') + key = '\n'; + } + else { + key = '\n'; + wrefresh(dialog); + } + + delwin(dialog); + return (key == ESC ? -1 : 0); +} +/* End of dialog_msgbox() */ + +int +dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width) +/* + * Desc: basically the same as dialog_msgbox, but ... can use PGUP, PGDN and + * arrowkeys to move around the text and pause is always enabled + */ +{ + int i, j, x, y, key=0; + int theight, startline, hscroll, max_lines; + WINDOW *dialog; + + if (height < 0) + height = strheight(prompt)+2+2; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j)+4; + } + width = MAX(width,10); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = (COLS - width)/2; + y = (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + + if (title != NULL) { + wattrset(dialog, title_attr); + wmove(dialog, 0, (width - strlen(title))/2 - 1); + waddch(dialog, ' '); + waddstr(dialog, title); + waddch(dialog, ' '); + } + + wattrset(dialog, 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, ' '); + display_helpline(dialog, height-1, width); + print_button(dialog, " OK ", height-2, width/2-6, TRUE); + wattrset(dialog, dialog_attr); + + theight = height - 4; + startline = 0; + hscroll = 0; + max_lines = getnlines(prompt); + print_page(dialog, theight, width, prompt, startline, hscroll); + print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines); + wmove(dialog, height-2, width/2-3); + wrefresh(dialog); + while ((key != ESC) && (key != '\n') && (key != '\r') && (key != ' ')) { + key = wgetch(dialog); + switch(key) { + case KEY_HOME: + startline=0; + hscroll=0; + break; + case KEY_END: + startline = max_lines - theight; + if (startline < 0) startline = 0; + break; + case '\020': /* ^P */ + case KEY_UP: + if (startline > 0) startline--; + break; + case '\016': /* ^N */ + case KEY_DOWN: + if (startline < max_lines - theight) startline++; + break; + case KEY_RIGHT: + hscroll+=5; + break; + case KEY_LEFT: + if (hscroll > 0) hscroll-=5; + if (hscroll < 0) hscroll =0; + break; + case KEY_PPAGE: + if (startline - height > 0) { + startline -= theight; + } else { + startline = 0; + } + break; + case KEY_NPAGE: + if (startline + theight < max_lines - theight) { + startline += theight; + } else { + startline = max_lines - theight; + if (startline < 0) startline = 0; + } + break; + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + print_page(dialog, theight, width, prompt, startline, hscroll); + print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines); + wmove(dialog, height-2, width/2-3); + wrefresh(dialog); + } + + delwin(dialog); + return (key == ESC ? -1 : 0); + +} /* dialog_mesgbox() */ + +static void +print_perc(WINDOW *win, int y, int x, float p) +/* + * Desc: print p as a percentage at the coordinates (y,x) + */ +{ + char ps[10]; + + if (p>1.0) p=1.0; + sprintf(ps, "(%3d%%)", (int) (p*100)); + wmove(win, y, x); + waddstr(win, ps); + + return; +} /* print_perc() */ + +static int +getnlines(unsigned char *buf) +/* + * Desc: count the # of lines in <buf> + */ +{ + int i = 0; + + if (*buf) + i++; + while (*buf) { + if (*buf == '\n' || *buf == '\r') + i++; + buf++; + } + return(i); +} /* getlines() */ + + +unsigned char * +getline(unsigned char *buf, int n) +/* + * Desc: return a pointer to the n'th line in <buf> or NULL if its + * not there + */ +{ + int i; + + if (n<0) { + return(NULL); + } + + i=0; + while (*buf && i<n) { + if (*buf == '\n' || *buf == '\r') { + i++; + } + buf++; + } + if (i<n) { + return(NULL); + } else { + return(buf); + } +} /* getline() */ + +static void +print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll) +/* + * Desc: Print a page of text in the current window, starting at line <startline> + * with a <horizontal> scroll of hscroll from buffer <buf> + */ +{ + int i, j; + unsigned char *b; + + b = getline(buf, startline); + for (i=0; i<height; i++) { + /* clear line */ + wmove(win, 1+i, 1); + for (j=0; j<width-2; j++) waddnstr(win, " ", 1); + wmove(win, 1+i, 1); + j = 0; + /* scroll to the right */ + while (*b && (*b != '\n') && (*b != '\r') && (j<hscroll)) { + b++; + j++; + } + /* print new line */ + j = 0; + while (*b && (*b != '\n') && (*b != '\r') && (j<width-2)) { + waddnstr(win, b, 1); + if (*b != '\t') { /* check for tabs */ + j++; + } else { + j = ((int) (j+1)/8 + 1) * 8 - 1; + } + b++; + } + while (*b && (*b != '\n') && (*b != '\r')) b++; + if (*b) b++; /* skip over '\n', if it exists */ + } +} /* print_page() */ + + + + diff --git a/gnu/lib/libodialog/notify.c b/gnu/lib/libodialog/notify.c new file mode 100644 index 0000000..7fc22eb --- /dev/null +++ b/gnu/lib/libodialog/notify.c @@ -0,0 +1,53 @@ +/* + * File: notify.c + * Author: Marc van Kempen + * Desc: display a notify box with a message + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include <stdio.h> +#include <stdlib.h> + +void +dialog_notify(char *msg) +/* + * Desc: display an error message + */ +{ + char *tmphlp; + WINDOW *w; + + w = dupwin(newscr); + if (w == NULL) { + endwin(); + fprintf(stderr, "\ndupwin(newscr) failed, malloc memory corrupted\n"); + exit(1); + } + tmphlp = get_helpline(); + use_helpline("Press enter or space"); + dialog_mesgbox("Message", msg, -1, -1); + restore_helpline(tmphlp); + touchwin(w); + wrefresh(w); + delwin(w); + + return; + +} /* dialog_notify() */ + diff --git a/gnu/lib/libodialog/prgbox.c b/gnu/lib/libodialog/prgbox.c new file mode 100644 index 0000000..bcafacf --- /dev/null +++ b/gnu/lib/libodialog/prgbox.c @@ -0,0 +1,152 @@ +/* + * prgbox.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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> + +#include <dialog.h> +#include <errno.h> +#include <sys/wait.h> +#include "dialog.priv.h" + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell) +{ + int i, x, y, key = 0; + WINDOW *dialog; + FILE *f; + const unsigned char *name; + unsigned char *s, buf[MAX_LEN]; + int status; + + if (height < 0 || width < 0) { + endwin(); + fprintf(stderr, "\nAutosizing is impossible in dialog_prgbox().\n"); + exit(-1); + } + width = MAX(width,10); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width)/2; + y = DialogY ? DialogY : (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + + if (title != NULL) { + wattrset(dialog, title_attr); + wmove(dialog, 0, (width - strlen(title))/2 - 1); + waddch(dialog, ' '); + waddstr(dialog, title); + waddch(dialog, ' '); + } + wattrset(dialog, dialog_attr); + wmove(dialog, 1, 2); + + if (!use_shell) { + char cmdline[MAX_LEN]; + char *av[51], **ap = av, *val, *p; + + strcpy(cmdline, line); + p = cmdline; + while ((val = strsep(&p," \t")) != NULL) { + if (*val != '\0') + *ap++ = val; + } + *ap = NULL; + f = raw_popen(name = av[0], av, "r"); + } else + f = raw_popen(name = line, NULL, "r"); + + status = -1; + if (f == NULL) { + err: + sprintf(buf, "%s: %s\n", name, strerror(errno)); + prr: + print_autowrap(dialog, buf, height-(pause?3:1), width-2, width, 1, 2, FALSE, TRUE); + wrefresh(dialog); + } else { + while (fgets(buf, sizeof(buf), f) != NULL) { + i = strlen(buf); + if (buf[i-1] == '\n') + buf[i-1] = '\0'; + s = buf; + while ((s = strchr(s, '\t')) != NULL) + *s++ = ' '; + print_autowrap(dialog, buf, height-(pause?3:1), width-2, width, 1, 2, FALSE, TRUE); + print_autowrap(dialog, "\n", height-(pause?3:1), width-2, width, 1, 2, FALSE, FALSE); + wrefresh(dialog); + } + if ((status = raw_pclose(f)) == -1) + goto err; + if (WIFEXITED(status) && WEXITSTATUS(status) == 127) { + sprintf(buf, "%s: program not found\n", name); + goto prr; + } + } + + 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, ' '); + display_helpline(dialog, height-1, width); + print_button(dialog, " OK ", height-2, width/2-6, TRUE); + wrefresh(dialog); + while (key != ESC && key != '\n' && key != ' ' && key != '\r') + key = wgetch(dialog); + if (key == '\r') + key = '\n'; + } + else { + key = '\n'; + wrefresh(dialog); + } + + delwin(dialog); + return (status); +} +/* End of dialog_msgbox() */ diff --git a/gnu/lib/libodialog/radiolist.c b/gnu/lib/libodialog/radiolist.c new file mode 100644 index 0000000..4b865a6 --- /dev/null +++ b/gnu/lib/libodialog/radiolist.c @@ -0,0 +1,628 @@ +/* + * radiolist.c -- implements the radiolist box + * + * AUTHOR: Stuart Herbert - S.Herbert@sheffield.ac.uk + * (from checklist.c by Savio Lam (lam836@cs.cuhk.hk)) + * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * + * 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.h" + + +static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, dialogMenuItem *me); + +#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL) + +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(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int cnt, void *it, unsigned char *result) +{ + int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button, + choice, l, k, scroll, max_choice, *status, item_no = 0, was_on = 0; + int redraw_menu = FALSE, cursor_reset = FALSE; + int rval = 0, onlist = 1, ok_space, cancel_space; + char okButton, cancelButton; + WINDOW *dialog, *list; + unsigned char **items = NULL; + dialogMenuItem *ditems; + + /* Allocate space for storing item on/off status */ + if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) { + endwin(); + fprintf(stderr, "\nCan't allocate memory in dialog_radiolist().\n"); + exit(-1); + } + +draw: + button = choice = scroll = 0; + /* Previous calling syntax, e.g. just a list of strings? */ + if (cnt >= 0) { + items = it; + ditems = NULL; + item_no = cnt; + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = !strcasecmp(items[i*3 + 2], "on"); + if (status[i]) { + if (was_on) + status[i] = FALSE; + else + was_on = 1; + } + } + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(cnt); + ditems = it; + if (!items) + items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *)); + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE; + if (status[i]) { + if (was_on) + status[i] = FALSE; + else + was_on = 1; + } + items[i*3] = ditems[i].prompt; + items[i*3 + 1] = ditems[i].title; + items[i*3 + 2] = status[i] ? "on" : "off"; + } + } + max_choice = MIN(list_height, item_no); + + check_x = 0; + item_x = 0; + /* Find length of longest item in order to center radiolist */ + for (i = 0; i < item_no; i++) { + l = strlen(items[i * 3]); + for (j = 0; j < item_no; j++) { + k = strlen(items[j * 3 + 1]); + check_x = MAX(check_x, l + k + 6); + } + item_x = MAX(item_x, l); + } + if (height < 0) + height = strheight(prompt) + list_height + 4 + 2; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i, j); + width = MAX(width, check_x + 4) + 4; + } + width = MAX(width, 24); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width) / 2; + y = DialogY ? DialogY : (LINES - height) / 2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x); + return -1; + } + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE); + + 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); + if (list == NULL) { + delwin(dialog); + endwin(); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width, + y + box_y + 1,x + box_x + 1); + return -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 = (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, DREF(ditems, i)); + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + + display_helpline(dialog, height-1, width); + + x = width/ 2 - 11; + y = height - 2; + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } + wnoutrefresh(dialog); + wmove(list, choice, check_x+1); + wrefresh(list); + + while (key != ESC) { + key = wgetch(dialog); + + /* See if its the short-cut to "OK" */ + if (toupper(key) == okButton) { + if (ditems) { + if (result && ditems[OK_BUTTON].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + } + else if (result) { + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcat(result, items[i*3]); + break; + } + } + } + rval = 0; + key = ESC; + break; + } + + /* Shortcut to cancel */ + if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + rval = 1; + key = ESC; + break; + } + + /* Check if key pressed matches first character of any item tag in list */ + for (i = 0; i < max_choice; i++) + if (key != ' ' && toupper(key) == toupper(items[(scroll + i) * 3][0])) + break; + + if (i < max_choice || (key >= '1' && key <= MIN('9', '0' + max_choice)) || + KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\r' || key == '\n') && onlist == 1)) { + + /* if moving from buttons to the list, reset and redraw buttons */ + if (!onlist) { + onlist = 1; + button = 0; + + if (ditems && result ) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + } + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + + if (key >= '1' && key <= MIN('9', '0' + max_choice)) + i = key - '1'; + else if (KEY_IS_UP(key)) { + if (!choice) { + if (scroll) { + /* 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, DREF(ditems, scroll)); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, + TRUE, DREF(ditems, scroll)); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + else + i = choice - 1; + } + else if (KEY_IS_DOWN(key)) { + if (choice == max_choice - 1) { + if (scroll + choice < item_no - 1) { + /* 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, DREF(ditems, scroll + max_choice - 1)); + 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, DREF(ditems, scroll + max_choice - 1)); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wmove(list, choice, check_x+1); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + else + i = choice + 1; + } + else if ((key == ' ' || key == '\r' || key == '\n') && onlist) { /* Toggle item status */ + getyx(list, old_y, old_x); /* Save cursor position */ + if (status[scroll + choice]) + continue; + else if (ditems) { + if (ditems[scroll + choice].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[scroll + choice].fire(&ditems[scroll + choice]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + if (st & DITEM_REDRAW) { + wclear(list); + for (i = 0; i < item_no; i++) + status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE; + + 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, + DREF(ditems, scroll + i)); + } +/* wmove(list, old_y, old_x);*/ /* Restore cursor to previous position */ +/* wrefresh(list); */ + } + if (st & DITEM_LEAVE_MENU) { + /* Allow a fire action to take us out of the menu */ + key = ESC; + break; + } + else if (st & DITEM_RECREATE) { + delwin(list); + delwin(dialog); + dialog_clear(); + goto draw; + } + } + for (i = 0; i < item_no; i++) + status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE; + } + else { + for (i = 0; i < item_no; i++) + status[i] = 0; + status[scroll + choice] = TRUE; + } + 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, DREF(ditems, scroll + i)); + wmove(list, choice, check_x+1); /* Restore cursor position */ + wrefresh(list); + continue; /* wait for another key press */ + } + + if (i != choice) { + /* De-highlight current item */ + print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 +1], + status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice)); + /* Highlight new item */ + choice = i; + print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1], + status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice)); + wmove(list, choice, check_x+1); /* Restore cursor position */ + wrefresh(list); + } + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_PPAGE: + if (scroll > height-4) /* can we go up? */ + scroll -= (height-4); + else + scroll = 0; + redraw_menu = TRUE; + if (!onlist) { + onlist = 1; + button = 0; + } + break; + + case KEY_NPAGE: + if (scroll + list_height >= item_no-1 - list_height) { /* can we go down a full page? */ + scroll = item_no - list_height; + if (scroll < 0) + scroll = 0; + } + else + scroll += list_height; + redraw_menu = TRUE; + if (!onlist) { + onlist = 1; + button = 0; + } + break; + + case KEY_HOME: + scroll = 0; + choice = 0; + redraw_menu = TRUE; + cursor_reset = TRUE; + onlist = 1; + break; + + case KEY_END: + scroll = item_no - list_height; + if (scroll < 0) + scroll = 0; + choice = max_choice - 1; + redraw_menu = TRUE; + cursor_reset = TRUE; + onlist = 1; + break; + + case TAB: + case KEY_BTAB: + /* move to next component */ + if (onlist) { /* on list, next is ok button */ + onlist = 0; + if (ditems && result) + ok_space = 1; + else + ok_space = 3; + wmove(dialog, y, x + ok_space); + wrefresh(dialog); + break; + } + else if (button) { /* on cancel button, next is list */ + button = 0; + onlist = 1; + redraw_menu = TRUE; + break; + } + /* on ok button, next is cancel button, same as left/right case */ + + case KEY_LEFT: + case KEY_RIGHT: + onlist = 0; + button = !button; + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + ok_space = 1; + cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6; + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + ok_space = 3; + cancel_space = 15; + } + if (button) + wmove(dialog, y, x + cancel_space); + else + wmove(dialog, y, x + ok_space); + wrefresh(dialog); + break; + + case ' ': + case '\r': + case '\n': + if (!onlist) { + if (ditems) { + if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) { + int st; + WINDOW *save; + + save = dupwin(newscr); + st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]); + if (st & DITEM_RESTORE) { + touchwin(save); + wrefresh(save); + } + delwin(save); + } + } + else if (result) { + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcpy(result, items[i*3]); + break; + } + } + } + rval = button; + key = ESC; + break; + } + + case ESC: + rval = -1; + break; + + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + + if (redraw_menu) { + getyx(list, old_y, old_x); + wclear(list); + 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, DREF(ditems, scroll + i)); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + + /* redraw buttons to fix highlighting */ + if (ditems && result) { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + wnoutrefresh(dialog); + if (cursor_reset) { + wmove(list, choice, check_x+1); + cursor_reset = FALSE; + } + else { + wmove(list, old_y, old_x); + } + wrefresh(list); + redraw_menu = FALSE; + } + } + + delwin(list); + delwin(dialog); + return rval; /* ESC pressed */ +} + +/* + * Print list item + */ +static void +print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, dialogMenuItem *me) +{ + 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%c%c", me && me->lbra ? me->lbra : '(', + status ? me && me->mark ? me->mark : '*' : ' ', + me && me->rbra ? me->rbra : ')'); + 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); + /* If have a selection handler for this, call it */ + if (me && me->selected) { + wrefresh(win); + me->selected(me, selected); + } +} +/* End of print_item() */ diff --git a/gnu/lib/libodialog/raw_popen.c b/gnu/lib/libodialog/raw_popen.c new file mode 100644 index 0000000..163c09a --- /dev/null +++ b/gnu/lib/libodialog/raw_popen.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/wait.h> + +#include <signal.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <paths.h> + +static struct pid { + struct pid *next; + FILE *fp; + pid_t pid; +} *pidlist; + +FILE * +raw_popen(const char *program, char * const *argv, const char *type) +{ + struct pid *cur; + FILE *iop; + int pdes[2], pid; + + if ((*type != 'r' && *type != 'w') || type[1]) + return (NULL); + + if ((cur = malloc(sizeof(struct pid))) == NULL) + return (NULL); + + if (pipe(pdes) < 0) { + (void)free(cur); + return (NULL); + } + + switch (pid = vfork()) { + case -1: /* Error. */ + (void)close(pdes[0]); + (void)close(pdes[1]); + (void)free(cur); + return (NULL); + /* NOTREACHED */ + case 0: /* Child. */ + if (*type == 'r') { + if (pdes[1] != STDOUT_FILENO) { + (void)dup2(pdes[1], STDOUT_FILENO); + (void)close(pdes[1]); + } + (void) close(pdes[0]); + } else { + if (pdes[0] != STDIN_FILENO) { + (void)dup2(pdes[0], STDIN_FILENO); + (void)close(pdes[0]); + } + (void)close(pdes[1]); + } + if (argv == NULL) + execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL); + else + execvp(program, argv); + _exit(127); + /* NOTREACHED */ + } + + /* Parent; assume fdopen can't fail. */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + (void)close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + (void)close(pdes[0]); + } + + /* Link into list of file descriptors. */ + cur->fp = iop; + cur->pid = pid; + cur->next = pidlist; + pidlist = cur; + + return (iop); +} + +/* + * pclose -- + * Pclose returns -1 if stream is not associated with a `popened' command, + * if already `pclosed', or waitpid returns an error. + */ +int +raw_pclose(FILE *iop) +{ + register struct pid *cur, *last; + int omask, pstat; + pid_t pid; + + (void)fclose(iop); + + /* Find the appropriate file pointer. */ + for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) + if (cur->fp == iop) + break; + if (cur == NULL) + return (-1); + + /* Get the status of the process. */ + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); + do { + pid = waitpid(cur->pid, (int *) &pstat, 0); + } while (pid == -1 && errno == EINTR); + (void)sigsetmask(omask); + + /* Remove the entry from the linked list. */ + if (last == NULL) + pidlist = cur->next; + else + last->next = cur->next; + free(cur); + + return (pid == -1 ? -1 : pstat); +} diff --git a/gnu/lib/libodialog/rc.c b/gnu/lib/libodialog/rc.c new file mode 100644 index 0000000..36631a6 --- /dev/null +++ b/gnu/lib/libodialog/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.h> +#include "dialog.priv.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/libodialog/rc.h b/gnu/lib/libodialog/rc.h new file mode 100644 index 0000000..fc19d03 --- /dev/null +++ b/gnu/lib/libodialog/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/libodialog/textbox.c b/gnu/lib/libodialog/textbox.c new file mode 100644 index 0000000..19a13bb --- /dev/null +++ b/gnu/lib/libodialog/textbox.c @@ -0,0 +1,699 @@ +/* + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.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; + + if (height < 0 || width < 0) { + fprintf(stderr, "\nAutosizing is impossible in dialog_textbox().\n"); + return(-1); + } + + search_term[0] = '\0'; /* no search term entered yet */ + + /* Open input file for reading */ + if ((fd = open(file, O_RDONLY)) == -1) { + fprintf(stderr, "\nCan't open input file <%s>in dialog_textbox().\n", file); + return(-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) { + fprintf(stderr, "\nError getting file size in dialog_textbox().\n"); + return(-1); + } + /* Restore file pointer to beginning of file after getting file size */ + if (lseek(fd, 0, SEEK_SET) == -1) { + fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n"); + return(-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) { + fprintf(stderr, "\nError reading file in dialog_textbox().\n"); + return(-1); + } + buf[bytes_read] = '\0'; /* mark end of valid data */ + page = buf; /* page is pointer to start of page to be displayed */ + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width)/2; + y = DialogY ? DialogY : (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + /* 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); + if (text == NULL) { + endwin(); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", height-4,width-2,y+1,x+1); + exit(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, ' '); + } + display_helpline(dialog, height-1, width); + + print_button(dialog, " OK ", height-2, width/2-6, 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 != '\r') && (key != ' ')) { + 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 '\020': /* ^P */ + 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 '\016': /* ^N */ + 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 'F': /* Next page */ + case 'f': + 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; + case KEY_F(1): + display_helpfile(); + break; + } + } + + delwin(dialog); + free(buf); + close(fd); + return (key == ESC ? -1 : 0); +} +/* 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 x, y, key = 0, first, + 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 "); + wattrset(win, dialog_attr); + + search_term[0] = '\0'; + + first = 1; + while (key != ESC) { + key = line_edit(win, y+1, x+1, -1, box_width-2, searchbox_attr, first, search_term, 0); + first = 0; + switch (key) { + case '\n': + if (search_term[0] != '\0') + return 0; + break; + case ESC: + break; + } + } + + 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/libodialog/tree.c b/gnu/lib/libodialog/tree.c new file mode 100644 index 0000000..ceacf05 --- /dev/null +++ b/gnu/lib/libodialog/tree.c @@ -0,0 +1,1133 @@ +/* + * tree.c -- implements the 'tree' interface element for libdialog + * + * Author: Anatoly A. Orehovsky (tolik@mpeks.tomsk.su) + * + * Copyright (c) 1997, Anatoly A. Orehovsky + * 09/28/98 - patched by Anatoly A. Orehovsky (smart_tree()) + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdlib.h> +#include <strings.h> +#include <stdio.h> +#include <dialog.h> +#include "dialog.priv.h" +#include <ncurses.h> + +/* static utils for make tree */ +struct leaf { + unsigned char *name; /* name of leaf */ + unsigned char *branches; /* branches that going by leaf */ + unsigned char slip; /* slip of leaf*/ + int shift; /* shift relative root of tree */ +}; + +static int mk_slip(struct leaf array[], int arr_size, + int number, int shift); + +/* make tree from file + * + * filename - name of file with like find(1) output + * p_names - pointer to array of strings + * p_size - pointer to size of array + * FS - fields separator + * p_array - pointer to array of leafs + * + * return values: + * 0 - ok and names by p_names, size by p_size, array by p_array set + * -1 - memory allocation error (errno set) + */ + +static int mk_ftree(char *filename, + unsigned char ***p_names, int *p_size, unsigned char FS, + struct leaf **p_array); + +/* make tree from array + * + * names - array of strings + * size - size of array + * FS - fields separator + * p_array - pointer to array of leafs + * + * return values: + * 0 - ok and array by p_array set + * -1 - memory allocation error (errno set) + */ + +static int mk_tree(unsigned char **names, int size, unsigned char FS, + struct leaf **p_array); + +/* free memory from tree (leafs) + * + * return values: + * nothing + */ + +static void free_leafs(struct leaf *array, int size); + +/* free memory from source data for tree (names) + * + * return values: + * if 0 <= choice <= size - pointer to name from names, + * and memory for name not released (must be freed later) + * else - NULL (recomended choice -1 for it) + */ + +static unsigned char *free_names(unsigned char **names, + int size, int choice); + +/* end of static utils for make tree */ + +/* static utils for ftree */ + +/* control struct for queue */ +struct queue { + int size; /* size of queue */ + struct m_queue *first; /* begin of queue */ + struct m_queue *last; /* end of queue */ +}; + +/* queue member */ +struct m_queue { + void *pointer; /* queue member */ + struct m_queue *next; /* next queue member */ +}; + +/* init struct queue by zeros */ +static void init_queue(struct queue *queue); + +/* add pointer to queue */ +/* return - pointer or NULL if error */ +static void *p2_queue(struct queue *queue, void *pointer); + +/* get first from queue */ +/* return - pointer or NULL if queue is empty */ +static void *first_queue(struct queue *queue); + +/* make zero terminated array from queue */ +/* return - pointer to array or NULL if error */ +static void **q2arr(struct queue *queue, int depth); + +/* smart_tree (for like find(1) with -d flag output compliance) */ +/* return - not NULL or NULL if malloc error */ +static unsigned char *smart_tree(struct queue *queue, unsigned char FS, + unsigned char *current, + unsigned char *prev); + +/* end of static utils for ftree */ + +/* static utils for saved_tree */ + +/* saved values for unique tree */ +struct saved_tree { + unsigned char **names; /* names + */ + int size; /* size + */ + unsigned char FS; /* FS + */ + int height; /* height + */ + int width; /* width + */ + int menu_height; /* menu_height - unique for treebox ? */ + int ch; /* saved ch - choice */ + int sc; /* saved sc - scroll */ +}; + +/* search saved tree within queue */ +/* return - struct saved_tree * or NULL if not found */ +static struct saved_tree *search_saved_tree(struct queue *queue, + unsigned char **names, + int size, + unsigned char FS, + int height, + int width, + int menu_height); + +/* end of static utils for saved_tree */ + +static void print_item(WINDOW *win, struct leaf item, int choice, int selected); + +static void print_position(WINDOW *win, int x, int y, + int cur_pos, int size); + +static int menu_width, item_x; + +static int dialog_treemenu(unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + int item_no, struct leaf items[], + int *result, + int *ch, int *sc); + +/* + * Display a menu for choosing among a number of options + */ +static +int dialog_treemenu(unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + int item_no, struct leaf items[], + int *result, + int *ch, int *sc) +{ + int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, + l, scroll = 0, max_choice, redraw_menu = FALSE; + WINDOW *dialog, *menu; + + if (ch) /* restore menu item info */ + choice = *ch; + if (sc) + scroll = *sc; + + max_choice = MIN(menu_height, item_no); + + item_x = 0; + /* Find length of longest item in order to center menu */ + for (i = 0; i < item_no; i++) { + l = strlen(items[i].name) + strlen(items[i].branches) * 4 + 4; + item_x = MAX(item_x, l); + } + + if (height < 0) + height = strheight(prompt)+menu_height+4+2; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j); + width = MAX(width,item_x+4)+4; + } + width = MAX(width,24); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = (COLS - width)/2; + y = (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); + + 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); + if (menu == NULL) { + endwin(); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height,menu_width,y+box_y+1,x+box_x+1); + exit(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); + + item_x = 1; + + /* Print the menu */ + for (i = 0; i < max_choice; i++) + print_item(menu, items[(scroll+i)], i, i == choice); + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); + print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); + + display_helpline(dialog, height-1, width); + + x = width/2-11; + y = height-2; + print_button(dialog, "Cancel", y, x+14, FALSE); + print_button(dialog, " OK ", y, x, TRUE); + + wrefresh(dialog); + + while (key != ESC) { + key = wgetch(dialog); + /* Check if key pressed matches first character of any item tag in menu */ + + if (key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') { + 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)], 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], 0, FALSE); + scrollok(menu, TRUE); + wscrl(menu, -1); + scrollok(menu, FALSE); + } + scroll--; + print_item(menu, items[scroll], 0, TRUE); +#endif + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); + print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous 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)], 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)], max_choice-1, FALSE); + scrollok(menu, TRUE); + scroll(menu); + scrollok(menu, FALSE); + } + scroll++; + print_item(menu, items[(scroll+max_choice-1)], max_choice-1, TRUE); +#endif + wnoutrefresh(menu); + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); + print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous 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)], choice, FALSE); + + /* Highlight new item */ + choice = i; + print_item(menu, items[(scroll+choice)], choice, TRUE); + wnoutrefresh(menu); + print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + } + continue; /* wait for another key press */ + } + + /* save info about menu item position */ + if (ch) + *ch = choice; + if (sc) + *sc = scroll; + + switch (key) { + case KEY_PPAGE: + case 'B' : + case 'b' : + if (scroll > menu_height) { /* can we go up? */ + scroll -= (menu_height); + } else { + scroll = 0; + } + redraw_menu = TRUE; + break; + case KEY_NPAGE: + case 'F' : + case 'f' : + if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */ + scroll = item_no - menu_height; + if (scroll < 0) scroll = 0; + } else { + scroll += menu_height; + } + redraw_menu = TRUE; + break; + case KEY_HOME: + case 'g' : + scroll = 0; + choice = 0; + redraw_menu = TRUE; + break; + case KEY_END: + case 'G' : + scroll = item_no - menu_height; + if (scroll < 0) scroll = 0; + choice = max_choice - 1; + redraw_menu = TRUE; + break; + case 'O': + case 'o': + delwin(dialog); + *result = scroll+choice; + 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 '\r': + case '\n': + delwin(dialog); + if (!button) + *result = scroll+choice; + return button; + case ESC: + break; + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + if (redraw_menu) { + for (i = 0; i < max_choice; i++) { + print_item(menu, items[(scroll+i)], + i, i == choice); + } + wnoutrefresh(menu); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); + print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); + redraw_menu = FALSE; + } + } + + delwin(dialog); + return -1; /* ESC pressed */ +} +/* End of dialog_treemenu() */ + + +/* + * Print menu item + */ +static void print_item(WINDOW *win, struct leaf item, int choice, int selected) +{ + int i, j = menu_width - 2; + char *branches = item.branches; + + /* 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, item_x); + + while(*branches && j) + { + switch (*branches++) { + case ' ' : waddch(win, ' '); + break; + case '|' : waddch(win, ACS_VLINE); + } + + j--; + i = 3; + while(i-- && j) + { + waddch(win, ' '); + j--; + } + } + + if (j) + { + switch (item.slip) { + case '+' : waddch(win, ACS_LTEE); + break; + case '`' : waddch(win, ACS_LLCORNER); + } + j--; + } + + i = 3; + while(i-- && j) + { + waddch(win, ACS_HLINE); + j--; + } + + wattrset(win, selected ? item_selected_attr : item_attr); + if (j) + waddnstr(win, item.name, j); +} +/* End of print_item() */ + +/* + * Print current position + */ +static void print_position(WINDOW *win, int x, int y, + int cur_pos, int size) +{ + int percent; + + wattrset(win, position_indicator_attr); + percent = cur_pos == size - 1 ? 100 : (cur_pos * 100)/(size - 1); + wmove(win, y + 1, x - 6); + wprintw(win, "(%3d%%)", percent); +} +/* End of print_position() */ + +/* + * Display a tree menu from file + * + * filename - file with like find(1) output + * FS - fields separator + * title - title of dialog box + * prompt - prompt text into dialog box + * height - height of dialog box + * width - width of dialog box + * menu_height - height of menu box + * result - pointer to char array + * + * return values: + * -1 - ESC pressed + * 0 - Ok, result set (must be freed later) + * 1 - Cancel + */ + +int dialog_ftree(unsigned char *filename, unsigned char FS, + unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + unsigned char **result) +{ + int retcode, choice, size; + struct leaf *items; + unsigned char **names; + + if (mk_ftree(filename, &names, &size, FS, &items)) + { + perror("dialog_ftree"); + end_dialog(); + exit(-1); + } + + if (!size) + { + fprintf(stderr, "\ndialog_ftree: file %s is empty\n", filename); + end_dialog(); + exit(-1); + } + + retcode = dialog_treemenu(title, prompt, height, width, menu_height, + size, items, &choice, NULL, NULL); + + free_leafs(items, size); + + if (!retcode) + *result = free_names(names, size, choice); + else + (void)free_names(names, size, -1); + + return retcode; +} +/* End of dialog_ftree() */ + +/* + * Display a tree menu from array + * + * names - array with like find(1) output + * size - size of array + * FS - fields separator + * title - title of dialog box + * prompt - prompt text into dialog box + * height - height of dialog box + * width - width of dialog box + * menu_height - height of menu box + * result - pointer to char array + * + * return values: + * -1 - ESC pressed + * 0 - Ok, result set + * 1 - Cancel + */ + +int dialog_tree(unsigned char **names, int size, unsigned char FS, + unsigned char *title, unsigned char *prompt, + int height, int width, int menu_height, + unsigned char **result) +{ + int retcode, choice; + struct leaf *items; + struct saved_tree *st; + static struct queue *q_saved_tree = NULL; + + if (!size) + { + fprintf(stderr, "\ndialog_tree: source array is empty\n"); + end_dialog(); + exit(-1); + } + + if (mk_tree(names, size, FS, &items)) + { + perror("dialog_tree"); + end_dialog(); + exit(-1); + } + +/* is tree saved ? */ + if (!(st = search_saved_tree(q_saved_tree, names, + size, FS, + height, width, menu_height))) { + if (!q_saved_tree) { + if (!(q_saved_tree = + calloc(sizeof (struct queue), 1))) { + perror("dialog_tree"); + end_dialog(); + exit(-1); + } + } + + if (!(st = calloc(sizeof (struct saved_tree), 1))) { + perror("dialog_tree"); + end_dialog(); + exit(-1); + } + + st->names = names; + st->size = size; + st->FS = FS; + st->height = height; + st->width = width; + st->menu_height = menu_height; + + if (!p2_queue(q_saved_tree, st)) { + perror("dialog_tree"); + end_dialog(); + exit(-1); + } + } + + retcode = dialog_treemenu(title, prompt, height, width, menu_height, + size, items, &choice, + &(st->ch), &(st->sc)); + + free_leafs(items, size); + + if (!retcode) + *result = names[choice]; + + return retcode; +} +/* End of dialog_tree() */ + +/* utils for ftree */ + +/* init struct queue by zeros */ +static void +init_queue(struct queue *queue) +{ + bzero((void *)queue, sizeof(struct queue)); +} + +/* add pointer to queue */ +/* return - pointer or NULL if error */ +static void * +p2_queue(struct queue *queue, void *pointer) +{ + if (!queue) + return NULL; + + if (!queue->first) + { + if (!(queue->first = queue->last = + calloc(1, sizeof(struct m_queue)))) + return NULL; + + } + else + { + if (!(queue->last->next = + calloc(1, sizeof(struct m_queue)))) + return NULL; + + queue->last = queue->last->next; + } + + queue->size++; + return queue->last->pointer = pointer; +} + +/* get first from queue */ +/* return - pointer or NULL if queue is empty */ +static void * +first_queue(struct queue *queue) +{ + void *retval; + struct m_queue *new_first; + + if (!queue || + !queue->first || + !queue->size) + return NULL; + + retval = queue->first->pointer; + new_first = queue->first->next; + free(queue->first); + queue->first = new_first; + queue->size--; + + return retval; + +} + +/* make zero terminated array from queue */ +/* return - pointer to array or NULL if error */ +static void ** +q2arr(struct queue *queue, int depth) +{ + void **mono, **end; + + if (!queue || + !queue->first || + !queue->size) + return NULL; + + /* memory allocation for array */ + if (!(mono = end = malloc(depth * sizeof(void *) + 1))) + return NULL; + + while(depth--) + { + if (!(*end++ = first_queue(queue))) + break; + } + + *end = NULL; + + return mono; + +} + +/* + * smart_tree (for like find(1) with -d flag output compliance) + * + * return values: + * NULL - malloc error + * not NULL - ok + * + */ +static +unsigned char * +smart_tree(struct queue *queue, + unsigned char FS, + unsigned char *current, + unsigned char *prev) { + unsigned char *pcurrent = current, *pprev = prev, *toqueue; + register char break_flag = 0; + + while(*pcurrent && *pprev) { + if (*pcurrent == *pprev) { + pcurrent++; + pprev++; + } + else { + break_flag = 1; + break; + } + } + + if (!*pprev || break_flag) { + if (*pcurrent == FS) { + pcurrent++; + + if ((!*prev) && (*pcurrent)) { + unsigned char tchar = *pcurrent; + + *pcurrent = '\0'; + if (!(toqueue = strdup(current))) { + *pcurrent = tchar; + return NULL; + } + if (!p2_queue(queue, toqueue)) { + *pcurrent = tchar; + return NULL; + } + *pcurrent = tchar; + } + } + + while(*pcurrent) { + if (*pcurrent == FS) { + *pcurrent = '\0'; + if (!(toqueue = strdup(current))) { + *pcurrent = FS; + return NULL; + } + if (!p2_queue(queue, toqueue)) { + *pcurrent = FS; + return NULL; + } + *pcurrent = FS; + } + pcurrent++; + } + if (!p2_queue(queue, current)) + return NULL; + } + return current; +} + +/* end of utils for ftree */ + +/* utils for make tree */ + +/* if error - return -1 */ +static +int +mk_slip(struct leaf array[], int arr_size, int number, int shift) +{ + int t_number; + int t_shift; + + if (number > arr_size - 1) + return number - 1; + + t_shift = shift; + + if (!(array[number].branches = calloc(1, t_shift + 1))) + return -1; + + (void)memset(array[number].branches, ' ', t_shift); + + t_number = number; + + while (array[number].shift < array[t_number + 1].shift) + { + t_number = mk_slip(array, arr_size, t_number + 1, t_shift + 1); + if (t_number < 0) + return -1; + if (t_number == arr_size - 1) + break; + } + + if (array[number].shift == array[t_number + 1].shift) + array[number].slip = '+'; + + if ((array[number].shift > array[t_number + 1].shift) || + t_number == arr_size - 1) + array[number].slip = '`'; + + return t_number; + +} /* mk_slip() */ + +/* make tree from file + * + * filename - name of file with like find(1) output + * p_names - pointer to array of strings + * p_size - pointer to size of array + * FS - fields separator + * p_array - pointer to array of leafs + * + * return values: + * 0 - ok and names by p_names, size by p_size, array by p_array set + * -1 - memory allocation error (errno set) + */ + +static +int +mk_ftree(char *filename, + unsigned char ***p_names, int *p_size, unsigned char FS, + struct leaf **p_array) +{ + int NR; /* number of input records */ + struct queue queue; + unsigned char *string, *sstring = ""; + unsigned char **names; + + FILE *input_file; + + if (!(input_file = fopen(filename, "r"))) + return -1; + + init_queue(&queue); + + if (!(string = malloc(BUFSIZ))) + return -1; + + /* read input file into queue */ + while(fgets(string, BUFSIZ, input_file)) + { + if (strchr(string, '\n')) + *strchr(string, '\n') = '\0'; + + if (!(string = realloc(string, strlen(string) + 1))) + return -1; + + if (!smart_tree(&queue, FS, string, sstring)) + return -1; + sstring = string; + + if (!(string = malloc(BUFSIZ))) + return -1; + } /* read input file into queue */ + + if (fclose(input_file) == EOF) + return -1; + + if (!(NR = queue.size)) + { + *p_size = 0; + return 0; + } + + /* make array from queue */ + if (!(names = (unsigned char **)q2arr(&queue, NR))) + return -1; + + *p_names = names; + *p_size = NR; + + /* make tree from array */ + return mk_tree(names, NR, FS, p_array); + +} /* mk_ftree */ + +/* make tree from array + * + * names - array of strings + * size - size of array + * FS - fields separator + * p_array - pointer to array of leafs + * + * return values: + * 0 - ok and array by p_array set + * -1 - memory allocation error (errno set) + */ + +static +int +mk_tree(unsigned char **names, int size, unsigned char FS, + struct leaf **p_array) +{ + int i; + struct leaf *array; + + /* make array of leafs */ + if (!(array = calloc(size, sizeof(struct leaf)))) + return -1; + + /* init leafs */ + for (i = 0; i < size; i++) + { + unsigned char *in_string, *name; + int shift = 0; + + in_string = name = names[i]; + while(*in_string) + { + if (*in_string == FS) { + if (!i && !*(in_string + 1)) + name = in_string; + else + { + shift++; + name = in_string + 1; + } + } + in_string++; + } + array[i].name = name; + array[i].shift = shift; + array[i].slip = '\0'; + array[i].branches = NULL; + } /* init leafs */ + + /* make slips */ + for (i = 0;i < size; i++) + { + i = mk_slip(array, size, i, 0); + if (i < 0) + return -1; + } /* make slips */ + + /* make branches */ + for (i = 1;i < size; i++) + { + unsigned char *src = array[i - 1].branches; + unsigned char *dst = array[i].branches; + + while(*src && *dst) + *dst++ = *src++; + + if (*dst) + switch (array[i - 1].slip) { + case '+' : *dst = '|'; + break; + case '`' : *dst = ' '; + } + } /* make branches */ + + *p_array = array; + return 0; + +} /* mk_tree() */ + +/* free memory from tree (leafs) + * + * return values: + * nothing + */ + +static +void +free_leafs(struct leaf *array, int size) +{ + struct leaf *p_array = array; + + while (size--) + free(array++->branches); + + free(p_array); +} /* free_leafs() */ + +/* free memory from source data for tree (names) + * + * return values: + * if 0 <= choice <= size - pointer to name from names, + * and memory for name not released (must be freed later) + * else - NULL (recomended choice -1 for it) + */ + +static +unsigned char * +free_names(unsigned char **names, int size, int choice) +{ + unsigned char *retval = NULL; + unsigned char **p_names = names; + + while (size--) + { + if (!choice--) + retval = *names++; + else + free(*names++); + } + free(p_names); + return retval; +} /* free_names() */ + +/* end of utils for make tree */ + +/* static utils for saved_tree */ + +/* search saved tree within queue */ +/* return - struct *saved_tree or NULL if not found */ +static +struct saved_tree * +search_saved_tree(struct queue *queue, unsigned char **names, int size, + unsigned char FS, + int height, int width, + int menu_height) +{ + struct m_queue *member; + struct saved_tree *retval; + + if (!queue || !names || !FS || + !height || !width || !menu_height) + return NULL; + + if (!(member = queue->first)) + return NULL; + + while (member->next) { + retval = member->pointer; + if ((names == retval->names) && + (size == retval->size) && + (FS == retval->FS) && + (height == retval->height) && + (width == retval->width) && + (menu_height == retval->menu_height)) + return retval; + member = member->next; + } + retval = member->pointer; + if ((names == retval->names) && + (size == retval->size) && + (FS == retval->FS) && + (height == retval->height) && + (width == retval->width) && + (menu_height == retval->menu_height)) + return retval; + return NULL; +} + +/* end of static utils for saved_tree */ diff --git a/gnu/lib/libodialog/ui_objects.c b/gnu/lib/libodialog/ui_objects.c new file mode 100644 index 0000000..dde1513 --- /dev/null +++ b/gnu/lib/libodialog/ui_objects.c @@ -0,0 +1,829 @@ +/* + * Program: objects.c + * Author: Marc van Kempen + * Desc: Implementation of UI-objects: + * - String input fields + * - List selection + * - Buttons + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include <stdlib.h> +#include <sys/param.h> +#include <ncurses.h> +#include <dialog.h> +#include "dialog.priv.h" +#include "ui_objects.h" + +#define ESC 27 + +/*********************************************************************** + * + * Obj routines + * + ***********************************************************************/ + +void +AddObj(ComposeObj **Obj, int objtype, void *obj) +/* + * Desc: Add the object <obj> to the list of objects <Obj> + */ +{ + if (*Obj == NULL) { + /* Create the root object */ + *Obj = (ComposeObj *) malloc( sizeof(ComposeObj) ); + if (!Obj) { + printf("AddObj: Error malloc'ing ComposeObj\n"); + exit(-1); + } + (*Obj)->objtype = objtype; + (*Obj)->obj = obj; + (*Obj)->next = NULL; + (*Obj)->prev = NULL; + } else { + ComposeObj *o = *Obj; + + /* create the next object */ + while (o->next) o = (ComposeObj *) o->next; + o->next = (struct ComposeObj *) malloc( sizeof(ComposeObj) ); + if (!o->next) { + printf("AddObj: Error malloc'ing o->next\n"); + exit(-1); + } + o->next->objtype = objtype; + o->next->obj = obj; + o->next->next = NULL; + o->next->prev = o; + } + + return; +} /* AddObj() */ + +void +FreeObj(ComposeObj *Obj) +/* + * Desc: free the memory occupied by *Obj + */ +{ + ComposeObj *o = Obj; + + o = Obj; + while (o) { + o = Obj->next; + free(Obj); + Obj = o; + } + + return; +} /* FreeObj() */ + + +int +ReadObj(ComposeObj *Obj) +/* + * Desc: navigate through the different objects calling their + * respective navigation routines as necessary + * Pre: Obj != NULL + */ +{ + ComposeObj *o; + ComposeObj *last; /* the last object in the list */ + int ret; /* the return value from the selection routine */ + + /* find the last object in the list */ + last = Obj; + while (last->next) last = last->next; + + ret = 0; + o = Obj; + while ((ret != SEL_BUTTON) && (ret != SEL_ESC)) { + switch(o->objtype) { + case STRINGOBJ: + ret = SelectStringObj((StringObj *) o->obj); + break; + case LISTOBJ: + ret = SelectListObj((ListObj *) o->obj); + break; + case BUTTONOBJ: + ret = SelectButtonObj((ButtonObj *) o->obj); + break; + } + switch(ret) { + case KEY_DOWN: + case SEL_CR: + case SEL_TAB: /* move to the next object in the list */ + if (o->next != NULL) { + o = o->next; /* next object */ + } else { + o = Obj; /* beginning of the list */ + } + break; + + case KEY_UP: + case SEL_BACKTAB: /* move to the previous object in the list */ + if (o->prev != NULL) { + o = o->prev; /* previous object */ + } else { + o = last; /* end of the list */ + } + break; + + case KEY_F(1): /* display help_file */ + case '?': + display_helpfile(); + break; + } + } + + return(ret); + +} /* ReadObj() */ + + +int +PollObj(ComposeObj **Obj) +{ + ComposeObj *last; /* the last object in the list */ + ComposeObj *first; /* the first object in the list */ + int ret; /* the return value from the selection routine */ + + /* find the last object in the list */ + last = *Obj; + while (last->next) last = last->next; + + /* find the first object in the list */ + first = *Obj; + while (first->prev) first = first->prev; + + ret = 0; + switch((*Obj)->objtype) { + case STRINGOBJ: + ret = SelectStringObj((StringObj *) (*Obj)->obj); + break; + case LISTOBJ: + ret = SelectListObj((ListObj *) (*Obj)->obj); + break; + case BUTTONOBJ: + ret = SelectButtonObj((ButtonObj *) (*Obj)->obj); + break; + } + switch(ret) { + case KEY_DOWN: + case SEL_CR: + case SEL_TAB: /* move to the next object in the list */ + if ((*Obj)->next != NULL) { + *Obj = (*Obj)->next; /* next object */ + } else { + *Obj = first; /* beginning of the list */ + } + break; + + case KEY_UP: + case SEL_BACKTAB: /* move to the previous object in the list */ + if ((*Obj)->prev != NULL) { + *Obj = (*Obj)->prev; /* previous object */ + } else { + *Obj = last; /* end of the list */ + } + break; + } + + return(ret); + +} /* PollObj() */ + + +void +DelObj(ComposeObj *Obj) +/* + * Desc: Free all objects + */ +{ + ComposeObj *o; + + o = Obj; + while (Obj != NULL) { + switch(Obj->objtype) { + case STRINGOBJ: + DelStringObj((StringObj *) Obj->obj); + break; + case LISTOBJ: + DelListObj((ListObj *) Obj->obj); + break; + case BUTTONOBJ: + DelButtonObj((ButtonObj *) Obj->obj); + break; + } + Obj = Obj->next; + } + + FreeObj(o); +} /* DelObj() */ + +/*********************************************************************** + * + * StringObj routines + * + ***********************************************************************/ + +static void +outstr(WINDOW *win, char *str, int attrs) +{ + if (attrs & DITEM_NO_ECHO) { + char *cpy; + int n = strlen(str); + + cpy = alloca(n + 1); + memset(cpy, '*', n); + cpy[n] = '\0'; + waddstr(win, cpy); + } + else + waddstr(win, str); +} + +void +RefreshStringObj(StringObj *so) +/* + * Desc: redraw the object + */ +{ + char tmp[512]; + + wmove(so->win, so->y, so->x+1); + wattrset(so->win, dialog_attr); + waddstr(so->win, so->title); + + draw_box(so->win, so->y+1, so->x, 3, so->w, dialog_attr, border_attr); + wattrset(so->win, item_attr); + wmove(so->win, so->y+2, so->x+1); + if (strlen(so->s) > so->w-2) { + strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1); + outstr(so->win, tmp, so->attr_mask); + } else { + outstr(so->win, so->s, so->attr_mask); + } + + return; +} /* RefreshStringObj() */ + +StringObj * +NewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len) +/* + * Desc: Initialize a new stringobj and return a pointer to it. + * Draw the object on the screen at the specified coordinates + */ +{ + StringObj *so; + + /* Initialize a new object */ + so = (StringObj *) malloc( sizeof(StringObj) ); + if (!so) { + printf("NewStringObj: Error malloc'ing StringObj\n"); + exit(-1); + } + so->title = (char *) malloc( strlen(title) + 1); + if (!so->title) { + printf("NewStringObj: Error malloc'ing so->title\n"); + exit(-1); + } + strcpy(so->title, title); + so->s = s; + strcpy(so->s, s); + so->x = x; + so->y = y; + so->w = w; + so->len = len; + so->win = win; + so->attr_mask = DialogInputAttrs; /* Grossly use a global to avoid changing API */ + + /* Draw it on the screen */ + RefreshStringObj(so); + + return(so); +} /* NewStringObj() */ + +int +SelectStringObj(StringObj *so) +/* + * Desc: get input using the info in <so> + */ +{ + int key; + char tmp[so->len+1]; + + strcpy(tmp, so->s); + key = line_edit(so->win, so->y+2, so->x+1, + so->len, so->w-2, inputbox_attr, TRUE, tmp, so->attr_mask); + if ((key == '\n') || (key == '\r') || (key == '\t') || key == (KEY_BTAB) ) { + strcpy(so->s, tmp); + } + RefreshStringObj(so); + if (key == ESC) { + return(SEL_ESC); + } + if (key == '\t') { + return(SEL_TAB); + } + if ( (key == KEY_BTAB) || (key == KEY_F(2)) ) { + return(SEL_BACKTAB); + } + if ((key == '\n') || (key == '\r')) { + return(SEL_CR); + } + return(key); +} /* SelectStringObj() */ + + +void +DelStringObj(StringObj *so) +/* + * Desc: Free the space occupied by <so> + */ +{ + free(so->title); + free(so); + + return; +} + +/*********************************************************************** + * + * ListObj routines + * + ***********************************************************************/ + +void +DrawNames(ListObj *lo) +/* + * Desc: Just refresh the names, not the surrounding box and title + */ +{ + int i, j, h, x, y; + char tmp[MAXPATHLEN]; + + x = lo->x + 1; + y = lo->y + 2; + h = lo->h - 2; + for (i=lo->scroll; i<lo->n && i<lo->scroll+h; i++) { + wmove(lo->win, y+i-lo->scroll, x); + if (lo->seld[i]) { + wattrset(lo->win, A_BOLD); + } else { + wattrset(lo->win, item_attr); + } + if (strlen(lo->name[i]) > lo->w-2) { + strncpy(tmp, lo->name[i], lo->w-2); + tmp[lo->w - 2] = 0; + waddstr(lo->win, tmp); + } else { + waddstr(lo->win, lo->name[i]); + for (j=strlen(lo->name[i]); j<lo->w-2; j++) waddstr(lo->win, " "); + } + } + wattrset(lo->win, item_attr); + while (i<lo->scroll+h) { + wmove(lo->win, y+i-lo->scroll, x); + for (j=0; j<lo->w-2; j++) waddstr(lo->win, " "); + i++; + } + + return; +} /* DrawNames() */ + +void +RefreshListObj(ListObj *lo) +/* + * Desc: redraw the list object + */ +{ + char perc[7]; + + /* setup the box */ + wmove(lo->win, lo->y, lo->x+1); + wattrset(lo->win, dialog_attr); + waddstr(lo->win, lo->title); + draw_box(lo->win, lo->y+1, lo->x, lo->h, lo->w, dialog_attr, border_attr); + + /* draw the names */ + DrawNames(lo); + + /* Draw % indication */ + sprintf(perc, "(%3d%%)", MIN(100, (int) (100 * (lo->sel+lo->h-2) / MAX(1, lo->n)))); + wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); + wattrset(lo->win, dialog_attr); + waddstr(lo->win, perc); + + + return; +} /* RefreshListObj() */ + +ListObj * +NewListObj(WINDOW *win, char *title, char **list, char *listelt, int y, int x, + int h, int w, int n) +/* + * Desc: create a listobj, draw it on the screen and return a pointer to it. + */ +{ + ListObj *lo; + int i; + + /* Initialize a new object */ + lo = (ListObj *) malloc( sizeof(ListObj) ); + if (!lo) { + fprintf(stderr, "NewListObj: Error malloc'ing ListObj\n"); + exit(-1); + } + lo->title = (char *) malloc( strlen(title) + 1); + if (!lo->title) { + fprintf(stderr, "NewListObj: Error malloc'ing lo->title\n"); + exit(-1); + } + strcpy(lo->title, title); + lo->name = list; + if (n>0) { + lo->seld = (int *) malloc( n * sizeof(int) ); + if (!lo->seld) { + fprintf(stderr, "NewListObj: Error malloc'ing lo->seld\n"); + exit(-1); + } + for (i=0; i<n; i++) { + lo->seld[i] = FALSE; + } + } else { + lo->seld = NULL; + } + lo->y = y; + lo->x = x; + lo->w = w; + lo->h = h; + lo->n = n; + lo->scroll = 0; + lo->sel = 0; + lo->elt = listelt; + lo->win = win; + + /* Draw the object on the screen */ + RefreshListObj(lo); + + return(lo); +} /* NewListObj() */ + +void +UpdateListObj(ListObj *lo, char **list, int n) +/* + * Desc: Update the list in the listobject with the provided list + * Pre: lo->name "has been freed" + * "(A i: 0<=i<lo->n: "lo->name[i] has been freed")" + */ +{ + int i; + + if (lo->seld) { + free(lo->seld); + } + + /* Rewrite the list in the object */ + lo->name = list; + if (n>0) { + lo->seld = (int *) malloc( n * sizeof(int) ); + if (!lo->seld) { + fprintf(stderr, "UpdateListObj: Error malloc'ing lo->seld\n"); + exit(-1); + } + for (i=0; i<n; i++) { + lo->seld[i] = FALSE; + } + } else { + lo->seld = NULL; + } + lo->n = n; + lo->scroll = 0; + lo->sel = 0; + + /* Draw the object on the screen */ + RefreshListObj(lo); + + return; +} /* UpdateListObj() */ + +int +SelectListObj(ListObj *lo) +/* + * Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit + * Pre: lo->n >= 1 + */ +{ + int key, sel_x, sel_y, quit; + char tmp[MAXPATHLEN]; + char perc[4]; + + sel_x = lo->x+1; + sel_y = lo->y + 2 + lo->sel - lo->scroll; + + if (lo->n == 0) return(SEL_TAB); + + keypad(lo->win, TRUE); + + /* Draw current selection in inverse video */ + wmove(lo->win, sel_y, sel_x); + wattrset(lo->win, item_selected_attr); + waddstr(lo->win, lo->name[lo->sel]); + + key = wgetch(lo->win); + quit = FALSE; + while ((key != '\t') && (key != '\n') && (key != '\r') + && (key != ESC) && (key != KEY_F(1)) && (key != '?') && !quit) { + /* first draw current item in normal video */ + wmove(lo->win, sel_y, sel_x); + if (lo->seld[lo->sel]) { + wattrset(lo->win, A_BOLD); + } else { + wattrset(lo->win, item_attr); + } + if (strlen(lo->name[lo->sel]) > lo->w - 2) { + strncpy(tmp, lo->name[lo->sel], lo->w - 2); + tmp[lo->w - 2] = 0; + waddstr(lo->win, tmp); + } else { + waddstr(lo->win, lo->name[lo->sel]); + } + + switch (key) { + case KEY_DOWN: + case ctrl('n'): + if (sel_y < lo->y + lo->h-1) { + if (lo->sel < lo->n-1) { + sel_y++; + lo->sel++; + } + } else { + if (lo->sel < lo->n-1) { + lo->sel++; + lo->scroll++; + DrawNames(lo); + wrefresh(lo->win); + } + } + break; + case KEY_UP: + case ctrl('p'): + if (sel_y > lo->y+2) { + if (lo->sel > 0) { + sel_y--; + lo->sel--; + } + } else { + if (lo->sel > 0) { + lo->sel--; + lo->scroll--; + DrawNames(lo); + wrefresh(lo->win); + } + } + break; + case KEY_HOME: + case ctrl('a'): + lo->sel = 0; + lo->scroll = 0; + sel_y = lo->y + 2; + DrawNames(lo); + wrefresh(lo->win); + break; + case KEY_END: + case ctrl('e'): + if (lo->n < lo->h - 3) { + lo->sel = lo->n-1; + lo->scroll = 0; + sel_y = lo->y + 2 + lo->sel - lo->scroll; + } else { + /* more than one page of list */ + lo->sel = lo->n-1; + lo->scroll = lo->n-1 - (lo->h-3); + sel_y = lo->y + 2 + lo->sel - lo->scroll; + DrawNames(lo); + wrefresh(lo->win); + } + break; + case KEY_NPAGE: + case ctrl('f'): + lo->sel += lo->h - 2; + if (lo->sel >= lo->n) lo->sel = lo->n - 1; + lo->scroll += lo->h - 2; + if (lo->scroll >= lo->n - 1) lo->scroll = lo->n - 1; + if (lo->scroll < 0) lo->scroll = 0; + sel_y = lo->y + 2 + lo->sel - lo->scroll; + DrawNames(lo); + wrefresh(lo->win); + break; + case KEY_PPAGE: + case ctrl('b'): + lo->sel -= lo->h - 2; + if (lo->sel < 0) lo->sel = 0; + lo->scroll -= lo->h - 2; + if (lo->scroll < 0) lo->scroll = 0; + sel_y = lo->y + 2 + lo->sel - lo->scroll; + DrawNames(lo); + wrefresh(lo->win); + break; + default: + quit = TRUE; + break; + } + /* Draw % indication */ + sprintf(perc, "(%3d%%)", MIN(100, (int) + (100 * (lo->sel+lo->h - 2) / MAX(1, lo->n)))); + wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8); + wattrset(lo->win, dialog_attr); + waddstr(lo->win, perc); + + /* draw current item in inverse */ + wmove(lo->win, sel_y, sel_x); + wattrset(lo->win, item_selected_attr); + if (strlen(lo->name[lo->sel]) > lo->w - 2) { + /* when printing in inverse video show the last characters in the */ + /* name that will fit in the window */ + strncpy(tmp, + lo->name[lo->sel] + strlen(lo->name[lo->sel]) - (lo->w - 2), + lo->w - 2); + tmp[lo->w - 2] = 0; + waddstr(lo->win, tmp); + } else { + waddstr(lo->win, lo->name[lo->sel]); + } + if (!quit) key = wgetch(lo->win); + } + + if (key == ESC) { + return(SEL_ESC); + } + if (key == '\t') { + return(SEL_TAB); + } + if ((key == KEY_BTAB) || (key == ctrl('b'))) { + return(SEL_BACKTAB); + } + if ((key == '\n') || (key == '\r')) { + strcpy(lo->elt, lo->name[lo->sel]); + return(SEL_CR); + } + return(key); +} /* SelectListObj() */ + +void +DelListObj(ListObj *lo) +/* + * Desc: Free the space occupied by the listobject + */ +{ + free(lo->title); + if (lo->seld != NULL) free(lo->seld); + free(lo); + + return; +} /* DelListObj() */ + +void +MarkCurrentListObj(ListObj *lo) +/* + * Desc: mark the current item for the selection list + */ +{ + lo->seld[lo->sel] = !(lo->seld[lo->sel]); + DrawNames(lo); + + return; +} /* MarkCurrentListObj() */ + +void +MarkAllListObj(ListObj *lo) +/* + * Desc: mark all items + */ +{ + int i; + + for (i=0; i<lo->n; i++) { + lo->seld[i] = TRUE; + } + DrawNames(lo); + + return; +} /* MarkAllListObj() */ + +void +UnMarkAllListObj(ListObj *lo) +/* + * Desc: unmark all items + */ +{ + int i; + + for (i=0; i<lo->n; i++) { + lo->seld[i] = FALSE; + } + DrawNames(lo); + + return; +} /* UnMarkAllListObj() */ + + +/*********************************************************************** + * + * ButtonObj routines + * + ***********************************************************************/ + + +void +RefreshButtonObj(ButtonObj *bo) +/* + * Desc: redraw the button + */ +{ + draw_box(bo->win, bo->y, bo->x, 3, bo->w, dialog_attr, border_attr); + print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); + + return; +} /* RefreshButtonObj() */ + +ButtonObj * +NewButtonObj(WINDOW *win, char *title, int *pushed, int y, int x) +/* + * Desc: Create a new button object + */ +{ + ButtonObj *bo; + + bo = (ButtonObj *) malloc( sizeof(ButtonObj) ); + + bo->win = win; + bo->title = (char *) malloc( strlen(title) + 1); + strcpy(bo->title, title); + bo->x = x; + bo->y = y; + bo->w = strlen(title) + 6; + bo->h = 3; + bo->pushed = pushed; + + RefreshButtonObj(bo); + + return(bo); +} /* NewButtonObj() */ + +int +SelectButtonObj(ButtonObj *bo) +/* + * Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC + */ +{ + int key; + + print_button(bo->win, bo->title, bo->y+1, bo->x+2, TRUE); + wmove(bo->win, bo->y+1, bo->x+(bo->w/2)-1); + key = wgetch(bo->win); + print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE); + switch(key) { + case '\t': + return(SEL_TAB); + break; + case KEY_BTAB: + case ctrl('b'): + return(SEL_BACKTAB); + case '\n': + case '\r': + *(bo->pushed) = TRUE; + return(SEL_BUTTON); + break; + case ESC: + return(SEL_ESC); + break; + default: + return(key); + break; + } +} /* SelectButtonObj() */ + +void +DelButtonObj(ButtonObj *bo) +/* + * Desc: Free the space occupied by <bo> + */ +{ + free(bo->title); + free(bo); + + return; +} /* DelButtonObj() */ diff --git a/gnu/lib/libodialog/ui_objects.h b/gnu/lib/libodialog/ui_objects.h new file mode 100644 index 0000000..b30feb8 --- /dev/null +++ b/gnu/lib/libodialog/ui_objects.h @@ -0,0 +1,114 @@ +/* + * Author: Marc van Kempen + * Desc: include file for UI-objects + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + */ + +#include "dialog.h" +#include <ncurses.h> + +/*********************************************************************** + * + * Defines + * + ***********************************************************************/ + +#define ctrl(a) ((a) - 'a' + 1) + +/* the Object types */ +#define STRINGOBJ 1 +#define LISTOBJ 2 +#define BUTTONOBJ 3 + +/* the return signals from the selection routines */ +/* 1000 and higher should avoid conflicts with keys pressed */ +#define SEL_CR 1001 /* return was pressed */ +#define SEL_ESC 1002 /* ESC pressed */ +#define SEL_TAB 1003 /* TAB pressed */ +#define SEL_BACKTAB 1004 /* SHIFT-TAB pressed */ +#define SEL_BUTTON 1005 /* a button was pressed */ + +/*********************************************************************** + * + * Typedefs + * + ***********************************************************************/ + +typedef struct { + WINDOW *win; /* the window it's contained in */ + char *title; /* the prompt for the input field */ + char *s; /* initial value of the input field */ + int x, y, w, len; /* the (y, x) position of the upperleft */ + /* corner and the width <w> of the display */ + /* and length <len> of the field */ + int attr_mask; /* special attributes */ +} StringObj; + +typedef struct { + WINDOW *win; /* the windows it's contained in */ + char *title; /* the title of the list */ + char **name; /* the names of the list */ + int *seld; /* the currently selected names */ + char *elt; /* the current element in the list list[sel] */ + int x, y, w, h, n; /* dimensions of list and # of elements (n) */ + int scroll, sel; /* current position in the list */ +} ListObj; + +typedef struct { + WINDOW *win; /* the window it's contained in */ + char *title; /* title for the button */ + int x, y, w, h; /* its dimensions */ + int *pushed; /* boolean that determines wether button was pushed */ +} ButtonObj; + +typedef struct ComposeObj { + int objtype; + void *obj; + struct ComposeObj *next, *prev; +} ComposeObj; + +/********************************************************************** + * + * Prototypes + * + **********************************************************************/ + +void RefreshStringObj(StringObj *so); +StringObj *NewStringObj(WINDOW *win, char *title, char *s, + int y, int x, int w, int len); +int SelectStringObj(StringObj *so); +void DelStringObj(StringObj *so); + +void RefreshListObj(ListObj *lo); +ListObj *NewListObj(WINDOW *win, char *title, char **list, + char *listelt, int y, int x, int h, int w, int n); +void UpdateListObj(ListObj *lo, char **list, int n); +int SelectListObj(ListObj *lo); +void DelListObj(ListObj *obj); +void MarkCurrentListObj(ListObj *lo); +void MarkAllListObj(ListObj *lo); +void UnMarkAllListObj(ListObj *lo); + +void RefreshButtonObj(ButtonObj *bo); +ButtonObj *NewButtonObj(WINDOW *win, char *title, int *pushed, + int y, int x); +int SelectButtonObj(ButtonObj *bo); +void DelButtonObj(ButtonObj *bo); +void AddObj(ComposeObj **Obj, int objtype, void *obj); +void FreeObj(ComposeObj *Obj); +int ReadObj(ComposeObj *Obj); +int PollObj(ComposeObj **Obj); +void DelObj(ComposeObj *Obj); + diff --git a/gnu/lib/libodialog/yesno.c b/gnu/lib/libodialog/yesno.c new file mode 100644 index 0000000..24eb41a --- /dev/null +++ b/gnu/lib/libodialog/yesno.c @@ -0,0 +1,169 @@ +/* + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <dialog.h> +#include "dialog.priv.h" + +/* Actual work function */ +static int dialog_yesno_proc(unsigned char *title, unsigned char *prompt, + int height, int width, int yesdefault); + +/* + * Display a dialog box with two buttons - Yes and No + */ +int +dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int width) +{ + return dialog_yesno_proc(title, prompt, height, width, TRUE); +} + +/* + * Display a dialog box with two buttons - No and Yes + */ +int +dialog_noyes(unsigned char *title, unsigned char *prompt, int height, int width) +{ + return dialog_yesno_proc(title, prompt, height, width, FALSE); +} + +static int +dialog_yesno_proc(unsigned char *title, unsigned char *prompt, int height, int width, int yesdefault) +{ + int i, j, x, y, key, button; + WINDOW *dialog; + char *tmphlp; + + /* disable helpline */ + tmphlp = get_helpline(); + use_helpline(NULL); + + if (height < 0) + height = strheight(prompt)+4; + if (width < 0) { + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j)+4; + } + width = MAX(width,23); + + if (width > COLS) + width = COLS; + if (height > LINES) + height = LINES; + /* center dialog box on screen */ + x = DialogX ? DialogX : (COLS - width)/2; + y = DialogY ? DialogY : (LINES - height)/2; + +#ifdef HAVE_NCURSES + if (use_shadow) + draw_shadow(stdscr, y, x, height, width); +#endif + dialog = newwin(height, width, y, x); + if (dialog == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); + exit(1); + } + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); + 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); + wmove(dialog, 1, 2); + print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); + + display_helpline(dialog, height-1, width); + + x = width/2-10; + y = height-2; + + /* preset button 0 or 1 for YES or NO as the default */ + key = 0; + button = !yesdefault; + while (key != ESC) { + print_button(dialog, " No ", y, x+13, button); + print_button(dialog, " Yes " , y, x, !button); + if (button) + wmove(dialog, y, x+16); + else + wmove(dialog, y, x+2); + wrefresh(dialog); + + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + restore_helpline(tmphlp); + return 0; + case 'N': + case 'n': + delwin(dialog); + restore_helpline(tmphlp); + return 1; + case KEY_BTAB: + case TAB: + case KEY_UP: + case KEY_DOWN: + case KEY_LEFT: + case KEY_RIGHT: + button = !button; + /* redrawn at the loop's entry */ + break; + case ' ': + case '\r': + case '\n': + delwin(dialog); + restore_helpline(tmphlp); + return button; + case ESC: + break; + case KEY_F(1): + case '?': + display_helpfile(); + break; + } + } + + delwin(dialog); + restore_helpline(tmphlp); + return -1; /* ESC pressed */ +} +/* End of dialog_yesno() */ |